Tuesday, 1 January 2019

non-blocking assignment does not work as expected in Verilog


I have a very simple Verilog code and it does not seem to work as expected:


Here is my code:


always @ (posedge clk, negedge resetn) begin
if (resetn == 1'b0) begin
var <= 1'b0;
end else begin
if (valid == 1'b1) begin
var<= 1'b1;
end else begin

var <= 1'b0;
end
end
end

I expected that assuming resetn is H all along, when valid goes H the var becomes H in the next cycle. But in simulation, var becomes H in the same cycle. Why is that?


Here is a diagram as well:


next_state_d2 is my var


Simulation


EDIT: Testbench code:



initial begin
gclk = 1'b1;
resetn = 1'b1;
div_valid=1'b0;
#40 div_valid = 1'b1;
#40 div_valid = 1'b0;
end

always
#20 gclk = ~ gclk;


Answer



This is actually quite similar to a question I answered previously, but I will try to build up a canonical answer for this somewhat common issue.


In a zero-delay simulation like this, the test flip-flop has a setup time and a hold time of zero:


\$ T_{setup} = T_{hold} = 0 \$


What this means is that the instant the sensitive clock edge occurs, the output is updated, regardless of what happened immediately before or after that instant. This is not like real hardware which would usually have a non-zero \$ T_{setup} \$ and \$ T_{hold} \$.


I ran your testbench, and the results are pretty clear. The valid signal changes at the same time the clock signal does. You have delayed them by precisely the same amount. So at the very edge when the clock is high, the valid signal has also changed:


enter image description here


Both the input (div_valid), and the clock (gclk) go high at the same time: 220 ns. Therefore, the DFF latches this new data, and the output changes instantly since there is also 0 propagation delay. This simulation would look less confusing if we just chose a different delay value for the input to the design:


enter image description here


In this case, we update the input on the falling edge of the clock (620 ns). It is much more clear now that the next clock edge (640 ns) will be when the DFF updates its output.



Here is the testbench code so you can see exactly how it works in your own simulator. Please update the design name as it wasn't clear what yours was named.


module scratch_tb;

reg gclk;
reg resetn;
reg div_valid;
wire data;

// instantiate design under test
scratch scratch (gclk, resetn, div_valid, data);


// generate stimulus
initial begin
gclk = 1'b1;
resetn = 1'b0;
div_valid = 1'b0;

#80 resetn = 1'b1;

// test 1: input switches on rising clock edge

#160 div_valid = 1'b1;
#40 div_valid = 1'b0;

#160 div_valid = 1'b0;

// test 2: input switches on falling clock edge
#180 div_valid = 1'b1;
#40 div_valid = 1'b0;

#2000 $finish;

end

always begin
#20 gclk = ~ gclk;
end

endmodule

No comments:

Post a Comment

arduino - Can I use TI&#39;s cc2541 BLE as micro controller to perform operations/ processing instead of ATmega328P AU to save cost?

I am using arduino pro mini (which contains Atmega328p AU ) along with cc2541(HM-10) to process and transfer data over BLE to smartphone. I...