variable clock generation in verilog using task - verilog

I have used following code to generate clock (whichever value I pass through task it will create that frequency), but the code only works if I use CLKSEL_global = clksel_local (i.e. blocking assignment) but that creates delta delay.
How do I generate variable clock without introducing delta delay? Is their another way of using a task. I am using task so that I can pass real values
`timescale 1ns/1ps
module tb();
real CLKSEL_global;
reg CLK7;
new dut(clk,clk_out);
task task_CLOCK;
input real clksel_local;
begin
CLKSEL_global = clksel_local;
end
endtask
initial begin
CLK7 = 0;
forever begin
#(500.0/CLKSEL_global) CLK7 = 1;
#(500.0/CLKSEL_global) CLK7 = 0;
end
end
initial begin
task_CLOCK(340.0);
end
initial begin
#100 $finish ;
end
endmodule

This solution feels like a nasty hack but I think achieves the requirement. When changing the Clock frequency it will change on the next edge, but allows #(posedge clk) to be used for the edge you want to change it on. The change is actually 1ns after the positive edge.
Normally the you would set the frequency and allow it to take effect on the edge giving a full cycle of setup.
module tb();
real CLKSEL_global = 500;
reg clk;
task task_CLOCK;
input real clksel_local;
begin
CLKSEL_global <= clksel_local;
end
endtask
initial begin
#1ns;
clk = 1'b0;
forever begin
#((500.0ns/CLKSEL_global) -1ns) clk = ~clk;
end
end
initial begin
$dumpfile("dump.vcd"); $dumpvars;
task_CLOCK(1);
repeat(2)
#(posedge clk);
task_CLOCK(2);
repeat(2)
#(posedge clk);
$finish ;
end
endmodule
Working copy of above on EDA Playground.

Related

Not seeing a clock cycle delay in Vivado simulation during a register/flipflop assignment

I am trying to generate a pulse from a signal ext_sample_clk. My design currently has 2 clock signals, clk and ext_sample_clk, which I am generating through a testbench. The following is my simplified code. Besides this, I also have the clk and reset generation logic, which I have not shown for simplicity. I can share those if needed.
module tb;
reg clk;
reg rst;
reg ext_sample_clk;
reg ext_sample_clk_r1;
wire ext_sample_pulse_orig;
//clock gen logic
always
begin
clk = 1'b1;
#5; // 10 ns
clk = 1'b0;
#5;
end
// reset gen logic
initial
begin
rst = 1;
#(100);
rst = 0;
end
// ext_sample_clk logic
always
begin
ext_sample_clk = 1'b1;
#50;
ext_sample_clk = 1'b0;
#50;
end
// register the ext_sample_clk logic, should infer a flip flop
always #(posedge clk) begin
if (rst)
ext_sample_clk_r1 <= 0;
else
ext_sample_clk_r1 <= ext_sample_clk; // lhs doesn't appear to be delayed by 1 clock cycle wrt to rhs
end
assign ext_sample_pulse_orig = ext_sample_clk && !ext_sample_clk_r1;
endmodule
I am expecting to see ext_sample_clk_r1 delayed by one clock pulse compared to ext_sample_clk. But the following is what I observe when I run a simulation on Vivado.
Can anyone explain why I am not seeing a clock cycle delay in ext_sample_clk_r1 with reference to ext_sample_clk. Am I missing something ?
Since you want ext_sample_clk_r1 and ext_sample_clk to be synchronous to the same clock (clk), you need to drive them both off of posedge clk, using nonblocking assignments (<=):
initial begin
ext_sample_clk = 1'b1;
forever begin
repeat (10) #(posedge clk);
ext_sample_clk <= ~ext_sample_clk;
end
end
Here is a running example on edaplayground.
The most probably way of getting the results you see is by using a blocking assignment to ext_sample_clk instead of a non-blocking assignment. Your testbench needs to follow the same rules as if it were part of the design to avoid race conditions. Use a non-blocking assignment or have your testbench apply signals on the opposite edge.

Testbench clk not advancing

All my testbench is trying to do is verify whether or not the LED signal went high, but on Modelsim when I try and simulate it, the clock doesn't even start, but it initializes to zero. I can also step through my design so I don't appear to have an infinite loop or anything like that. Is there anything obviously wrong here, especially with regards to clock initialization and generation?
`timescale 1ns/100ps
module fir_filter_tb();
reg clk, reset_n;
reg led;
top top_level (
.clk(clk),
.reset_n(reset_n),
.led(led)
);
initial
begin
$display($time, " << Starting the Simulation >>");
clk = 1'b0; // at time 0
reset_n = 0; // reset is active
led = 0; // output is low
#10 reset_n = 1'b1; // at time 20 release reset
end
always #10 clk = ~clk;
always
begin
if (led == 1'b1) begin
$write($time, "Filter Successful");
end else begin
$write($time, "bleh you suck");
end
end
endmodule : fir_filter_tb
The problem is with the always block with led in it. Since there is no timing control, it prevents time from advancing (time remains stuck at 0). It creates an infinite zero-time loop.
One way to fix it is to use:
always #*
This will only trigger the block when led changes.

I2S Transmitter Verilog Implementation not working

I am trying to implement the I2S Transmitter in verilog. The datasheet for it is at: https://www.sparkfun.com/datasheets/BreakoutBoards/I2SBUS.pdf
I wrote the code, but my SD line is delayed 1 clock cycle when i test it.
Can someone check my implementation?
module Transmiter(
input signed [23:0] DLeft, input signed [23:0] DRight, input WS, input CLK,
output reg SD
);
wire PL;
reg Q1,Q2;
reg [23:0] shift_reg;
reg [23:0] Tdata;
assign PL = Q1^Q2;
always #(posedge CLK)
begin
Q1 <= WS;
Q2 <= Q1;
end
always #( Q1) begin
if (Q1)
begin
Tdata <= DRight;
end
else
begin
Tdata <= DLeft;
end
end
always #(negedge CLK)
begin
if(PL)
begin
shift_reg <= Tdata;
end
else begin
SD <= shift_reg[23];
shift_reg <= {shift_reg[22:0],1'b0};
end
end
endmodule
EDIT: here is a image of waveform image
TEST BENCH CODE:
module Transmitter_tb(
);
reg CLK, WS;
reg [23:0] dataL;
reg [23:0] dataR;
wire SDout;
Transmiter UT(dataL, dataR, WS, CLK, SDout);
initial begin
dataL = 24'hF0F0FF; #2;
dataR = 24'h0000F0; #2;
end
always begin
CLK=0; #20;
CLK=1; #20;
end;
always begin
WS=0; #1000;
WS=1; #1000;
end;
endmodule
Your negedge block contains an if-else construct and will only ever compute one or the other on a single clock edge. SD will therefore not change value when PL is high.
Furthermore you are using non-blocking assignments(<=) in your code. This roughly means that changes won't be evaluated until the end of the always block. So even if SD <= shift_reg[23] after shift_reg <= Tdata it will not take on the new value in shift_reg[23] but use the previous value. If you want SD to change immediately when shift_reg[23] changes you need to do this combinatorically.
This should work:
always #(negedge CLK)
begin
if(PL)
begin
shift_reg <= Tdata;
end
else
shift_reg <= {shift_reg[22:0],1'b0};
end
assign SD = shift_reg[23];
Working example: https://www.edaplayground.com/x/4bPv
On a side note I am still not convinced that DRight and DLeft are in fact constants, I can see that they are in your TB but it doesn't make sense that the data for your I2S is constant. Your current construct will probably generate a latch(instead of a MUX), and we generally don't want those in our design.
You should clean up your use of blocking versus non-blocking statements:
Always use non-blocking assigments, meaning "<=", in clocked statements.
Always use blocking assigments, meaning "=", in combinational (non-clocked) statements.
This is a industry-wide recommendation, not a personal opinion. You can find this recommendation many places, see for instance:
http://web.mit.edu/6.111/www/f2007/handouts/L06.pdf
The sensitivtity list being incomplete (as pointed out by #Hida) may also cause issues.
Try to correct these two things, and see if it starts working more as expected.
Also note that you are using Q1 (among other signals) to generate your PL signal. If the WS input is not synchronous to your local clock (as I assume it is not), you need to put one more flop (i.e. two in series) before starting to use the output, to avoid metastability-issues. But you won't see this in an RTL simulation.

clock implementation using forever in verilog

I am implementing a sequential circuit in verilog . I want a clock of time period 10 . For implementing that I have done something like
initial begin
forever begin
clk=0;
#5
clk=1;
#5
clk=0;
end
end
But when I run the code , it keeps on running without showing any output. Is there any error in above implementation?
One way of implementing it is as follows (assuming you are using this in a testbench):
parameter clock_period=10;
always
#(clock_period/2) clock=~clock;
initial begin
clock=0;
#1000 $finish; // You can put the delay as per your requirement.
end
Your code keeps on running since there is no $finish. So it's a free running oscillator.
Following are some of the methods for clock generation. More or less, they all are same.
Method 1 :
parameter int clk_tgl_period = 5;
parameter timeout = 500;
module clkgen1;
reg clk;
initial begin
clk <= '0;
forever #(clk_tgl_period) clk = ~clk;
end
initial begin
#(timeout) $finish
end
endmodule
Method - 2
parameter int clk_tgl_period = 5;
parameter timeout = 500;
module clkgen2;
reg clk;
initial begin
clk = 0;
#(timeout) $finish;
end
always #(clk_tgl_period) clk = ~clk;
endmodule
Method - 3
parameter int clk_tgl_period = 5;
parameter timeout = 500;
module clkgen3;
reg clk;
initial begin
clk = 0;
#(timeout) $finish;
end
always #(clk_tgl_period) clk++;
endmodule
For more information, you may want to have a look at Section-4 of CummingsSNUG2006Boston_SystemVerilog_Events Paper.

Frequency divisor in verilog

i need a frequency divider in verilog, and i made the code below. It works, but i want to know if is the best solution, thanks!
module frquency_divider_by2 ( clk ,clk3 );
output clk3 ;
reg clk2, clk3 ;
input clk ;
wire clk ;
initial clk2 = 0;
initial clk3 = 0;
always # (posedge (clk)) begin
clk2 <= ~clk2;
end
always # (posedge (clk2)) begin
clk3 <= ~clk3;
end
endmodule
the circuit generated by quartus:
Your block divides the frequency by 4 not 2. There is actually quite a good description of this on Wikipedia Digital Dividers. Your code can be tidied up a bit but only 1 D-Type is required, which is smaller than a JK Flip-flop so is optimal.
module frquency_divider_by2(
input rst_n,
input clk_rx,
output reg clk_tx
);
always # (posedge clk_rx) begin
if (~rst_n) begin
clk_tx <= 1'b0;
end
else begin
clk_tx <= ~clk_tx;
end
end
endmodule
When chaining these types of clock dividers together be aware that there is a clk to q latency which is compounded every time you go through one of these dividers. IF this is not managed correctly by synthesis the clocks can not be considered synchronous.
Example on EDAplayground, should open the waveform when run.

Resources