Understanding the Verilog Stratified Event Queue - verilog

I'm trying to understand how the Verilog scheduling algorithm works. The below example outputs 0, xxxx and not 1010. I'm not clear why. If I do put a delay before $display, it would output 1010.
module test;
reg [3:0] t_var;
initial begin
t_var <= 4'b1010;
$display("%0t, %b", $realtime, t_var);
end
endmodule
Same output, 0, xxxx, for the below example:
module test;
reg [3:0] t_var;
wire [3:0] y;
assign y = ~t_var;
initial begin
t_var = 4'b1010;
$display("%0t, %b, %b", $realtime, t_var, y);
end
endmodule
Based on the examples, it seems that nonblocking assignment and continuous assignment are both two-step processes where the RHS is evaluated at the current time step and the LHS is scheduled to happen at the next time step (if no delay is specified) or at a later time step (if a delay is specified).
Can someone please confirm and explain to me a step-by-step flow of the algorithm below (from Clifford Cummings) as it applies to the examples above?
Thanks!

You are correct in saying that the non-blocking assignment(NBA) and continuous assignment(CA) act like two-step processes, because they are. The problem is what you are calling "the next time-step" is not an advance in time; it is an iteration of the while() loop without advancing time. This is usually referred to as a delta-step.
When using an NBA, the LHS gets scheduled as an NBA update event, but right after that, the $display is the next active event to execute. It prints the value of y before the NBA update events have a chance to execute. As soon as you introduce a delay, the NBA has a chance to execute before advancing to the next event time.
When using a CA, you are creating a separate process that activates anytime the RHS changes it makes an assignment to the LHS in the same active region. The initial and CA are two independent processes, and the ordering between statements in the active region is non-deterministic. So whether you see the old uninitialized value of y of updated value of y is a race condition. And you will see differences between simulators depending on how they optimize this code.

Related

I have faced a problem with Verilog Multiplier Module

Picture given is a module I'd like to express.
MulCell
For some reason I had to bring up the Multiplicand or Multiplier from arrays of numbers using wire. ex)wire [3:0] abc = 4'b1111;
But very odd! When I assign specific value of wire abc to "Multiplier", it works well. However if I assign it to "Multiplicand", I see red lines just as in the picture. redline
Any idea what had gone wrong? Thanks
Code for MulCell
module MulCell(Multiplicand,Multiplier,Sin,Cin,Sout,Cout);
input Multiplicand,Multiplier,Sin,Cin;
output Sout,Cout;
reg Sout,Cout;
wire tmp;
assign tmp=Multiplicand&Multiplier;
always#(tmp) begin
{Cout,Sout} <= tmp+Sin+Cin;
end
endmodule
Code for testbench_MulCell
`timescale 1ns/1ns
module testbench_MulCell();
reg Multiplicand,Multiplier,Sin,Cin;
wire Sout,Cout;
MulCell MC(Multiplicand,Multiplier,Sin,Cin,Sout,Cout);
wire [3:0]abc;
assign abc=4'b1111;
initial begin
Multiplicand=abc[2];
Multiplier=1'b1;
Sin=1'b1;
Cin=1'b1;
#10 //expecting 11
Multiplicand=1'b0;
Multiplier=abc[1];
Sin=1'b1;
Cin=1'b1;
#10 $stop;//expecting 10
end
endmodule
I can be wrong, but it seems there's a race condition between assigning value to abc and running initial block. At the moment when initial block started running, the assign abc =.. isn't executed yet. That's why you get x/red_lines in waveform view.
Verilog is an event driven simulator. It means that every 'always...', 'assign' block has inputs and outputs. Inputs in always block is are represented by its sensitivity list. In your case that would be the tmp signal. The whole block will start evaluation if and only if a change of an input is detected.
Also in the module the initial is scheduled for execution once during the simulation and is always executed first, before any of the always blocks (except in special cases in system verilog). So, in your case first few statements of the initial block (before first #10) are executed before the assign statement. So, for the first 10 cycles value of abc will be `4bxxxx, which explains your red line. For the same reason the values. As a result, values of multiplicand and consequently of MC/tmp,Sout,Cout will also be 'x'.
At #10 you change the values of the variables, causing always block in MC to re-evaluate with new values. By that time abc is already set to 1111 and all 'x' disappear.
So, efficiently you simulated only the second set of values but hot the first.
The suggestion is: add a small delay in front of the initial block:
initial begin
#1
Multiplicand=abc[2];
Multiplier=1'b1;
Sin=1'b1;
This will delay execution of the statements and the value of 'abc' will be set by this time. You will have a short period (1) of the red line, but you will see results of the values you set.
Another possibility is to set value of abc in the initial block first, but you would need a reg variable to do so:
reg[3:0] abcSet;
assign abc = abcSet;
initial begin
abcSet = 4'b1111;
...
another thing, in your always block you use non-blocking assignment (<=). Do not! This is good for flops and latches but bad for simple combinatorial logic. Use the regular assignment there (=).
{Cout,Sout} = tmp+Sin+Cin;
Also, this always block will not be avaluated if you just change Sin or Cin and tmp stays the same. You should either add those into the sensitivity list:
always #(tmp, Sin, Cin)
or use always #* instead. Actually it is a good idea to always use this construct instead of regular V95 always blocks. This way you will avoid possible implicit latches in the design (as in your case in respect to missing parts of the sensitivity list).
Also, in general most of the modern designs are synchronous designs and use a clock signal for synchronization. In your case the multpliplier sell shoudl be synchronized as well, you would need to provide a toggling clock signal. In theis case your operation could look like the following:
always #(posedge clk)
{Cout,Sout} <= tmp+Sin+Cin;
It makes evaluation happen at positive edge of the clk signal, it it is the only member of the sensitivity list. All other signals should set before the clock change. And yes, it is a flop and <= is used there.

register inferred by blocking assignment and races

I am new to verilog and have a doubt concerning the race conditions in the following code which is taken from FPGA Prototyping by Veriloog Examples by Pong P. Chu. The code is:
always #(posedge clk)
a = b;
always #(posedge clk)
b = a;
This will infer races depending on which always block gets executed first. But always blocks should get executed in parallel. Correct me if I am wrong. I know there is blocking assignment but how does it affect the first statement of the block, which is the always statement?
The second code using the non-blocking assignment is:-
always #(posedge clk)
begin //b(entry) = b
a <= b; //a(exit) = b(entry)
end //a = a(exit)
always #(posedge clk)
begin //a(entry) = a
b <= a; //b(exit) = a(entry)
end //b = b(exit)
This will work fine according to the book but I couldn't understand why? Is it because the always blocks are executed in parallel in this case because of non-blocking assignment?
Because the Verilog "stratified event queue" has different regions, the type of assignment operator used makes a difference in how the code is executed. The details can be found in section 5 of the IEEE Verilog standard, but in terms of your question, it boils roughly down to this:
The blocking assignments (in your first example) are evaluated immediately, i.e. when the always block they're in is activated. Since both blocks are parallel, order of their activation is undefined.
The non-blocking assignments are not executed immediately but rather scheduled after all blocks of the same time step have finished executing.
So when encountering a rising clk edge, in your first example a simulator would
Pick at random one of the always blocks
Find that the assignment is a blocking one and execute it immediately, therefore changing the left-hand variable in that assignment.
Pick the other always block and do the same, at which point the value of the first variable was already changed.
In your second example, the simulator would
Pick at random one of the always blocks
Find that the assignment is a non-blocking one and therefore
evaluate the right-hand side of the = sign and schedule the value it found there as a non-blocking assign update event to the variable left of the =.
Pick the other always block and do the same. Note that both variables still have their values from before the rising clk edge.
Since all blocks are done executing, update all variables which were scheduled for non-blocking assign update events, effectively swapping their values.

Verilog always block with pushbutton activation, FSM

I'm writing some Verilog code to be programmed on an Altera Cyclone II FPGA board, and I have an always block which should be activated on the press of a key switch:
reg START;
...
...
always # (negedge key[3]) begin
if (START != 1) START = 1;
end
I'm writing a program for a finite state machine and this key press is supposed to indicate that the user would like to begin using the program and it should move from its initial state to the next state. Since the initialization of registers is not synthesizable, I can't assume that START begins at 0.
The problem is that once I program the board and turn it on, this always block has already run once before I press the key assigned to key[3]. I've done checks for the value of START at program execution and it is already at 1. I can't figure out why this would be happening, as the key is at its negative edge only upon key press. I've used always blocks with the same condition in previous situations and it worked fine, so I assume this has something to do with the initialization of START?
It should be noted that synthesizability of initial depends on a target you are coding for.
For example, if you code for simulator, initial works just nice. If your target is FPGA, the tool (quartus in your case) has full control over the schematics and over the initial state of every trigger inside it: actually, uploading the firmware to FPGA sets every trigger to a known state, and quartus is able to parse initials to derive each trigger's state.
In contrary, if your target is a bare silicon, every trigger is just a bunch of transistors and its state is totally indefinite upon power-on, so the only way to control it's power-on state is to apply some type of reset, like this:
always #(posedge clk, negedge rst_n)
if( !rst_n )
START <= 1'b0; // no start condition upon reset
else if( some_condition )
START <= 1'b1;
Another point on your code is that when parsing inputs from switches you should do first resynchronization to your design's clock, like this:
reg start_r, start_rr;
always #(posedge clk)
begin
start_r <= START;
start_rr <= start_r;
end
// now use start_rr instead of START
Resynchronization is a key element to avoid metastable states in your synchronous design.
The second point is that you should consider debouncing of any input from mechanic switches, unless your design is tolerant to multiple tripping of switches.
Returning to the original problem Ryan McClure asks for. It could be seen, that in the original code without initial START is undefined at startup, and can trip only to '1' state. Therefore, synthesizer just assumes START is constant, always having it '1'.
You should use an "initial" block to set the startup value of your signals. The value of START and key[3] has to be set.
initial begin
START = 1'b0;
key[3] = 1'b1;
end
You said
Since the initialization of registers is not synthesizable, I can't
assume that START begins at 0.
But this is not true! You can set a default value to any signal in your design with the method above. This value is included in the bitstream of your firmware and the signal startup with this very value.
cheers

always block #posedge clock

Let's take the example code below:
always #(posedge clock)
begin
if (reset == 1)
begin
something <= 0
end
end
Now let's say reset changes from 0 to 1 at the same time there's a posedge for the clock. Will something <= 0 at that point? Or will that happen the next time there's a posedge for the clock (assuming reset stays at 1)?
It depends on exactly how reset is driven.
If reset and something are both triggered off the same clock, then something will go to 0 one clock cycle after reset goes to 1. For example:
always #(posedge clock)
begin
if (somethingelse)
begin
reset <= 1;
end
end
If reset is synchronous and based on clock, The simulatore will defiantly see reset on the next clock and not the current. Physical design has clock-to-Q, therefor a rise in reset will not be observed in the same clock that caused it. You may see reset at the same time as clock in waveform. reset <= 1'b1; make the assignment happen near the end of the scheduler (after all code has executed).
To not have to worry about this when looking at a waveform, some logic designers like to put a delay on the assignment creating an artificial clock-to-Q delay (ex reset <= #1 1'b1; and something <=#1 0;). Synthesis tools will ignore the delay, but some will give warnings. That warning can be avoided by using a macro.
`ifdef SYNTHESIS
`define Q /* blank */
`else
`define Q #1
`endif
...
reset <= `Q 1'b1;
...
something <=`Q 1'b1;
...
If reset is asynchronous and being use with synchronous reset, setup time requirements need to be respected. In simulation if clock and reset rise at the same time, it is up to your verilog scheduler to decide if reset will be the new value or old value. Usually it will take the left-hand side value (old value), which means the reset will be missed on the current clock. Physical design uncertainly as well with a meta-stability risk.
The code you have written infers a flip-flop with synchronous reset. This means it is assumed that the "reset" signal is synchronised to the "clock" domain before being used in this way. If the "reset" signal is not synchronised then you should modify the code to infer a flip-flop with asynchronous reset as below:
always#(posedge clock or posedge reset)
begin
if (reset)
something <= 0
else
something <= something_else
end
Coming back to your question and assuming the code you have written is what you want, the outcome depends on how the reset is driven. If it is synchronous then the simulator will see it in the next clock edge. If it is asynchronous then the simulator can assume anything, it can vary from simulator to simulator. Please note that in simulator everything is a sequence of events and there is no such thing as happening at the same time.
In the physical world, what you have coded will result in a flip-flop with reset signal being one of the inputs to the combo driving the input of this flop. Now if the reset is synchronous, you are guaranteed that there will be no setup or hold violation at this flop. Whether the flop will 'see' the reset in this clock or the next depends on the various delays of the synthesised circuit (Usually this is the main reason that the reset is always held for few clock cycles to make sure all the flops in your design sees the reset). If reset is asynchronous then the flop will go into a metastable state. You will never want this in your design.
Hope this clarifies.
The short answer is that either of your two outcomes (immediately, or next cycle) could happen. This is a standard race condition, and simulators are free to handle this any way they want; some will give one answer, and others will give the other one.
For the long answer, look up any introductory text on how VHDL delta cycles work. Verilog doesn't specify 'delta cycles', but any Verilog simulator will work in exactly the same way, with some (irrelevant) changes in the overall scheduling algorithm. In this case, the scheduler finds that it has two events on the queue in a specific delta - reset rising, and clock rising. This is what "at the same time" means. It chooses one in an unspecified way (it might be earlier in the text source, or later, for example), works through all changes associated with that edge, and then goes back and works through all changes associated with the other edge.

About verilog flip flop delay

I want to buffer a single-bit signal "done" with two single-bit flip-flops. The done signal will rise for only one clock cycle in my design. So I wrote the following code.
//first level buffer done signal for one cycle to get ciphertext_reg ready
always #(posedge clk or posedge rst) begin
if(rst)
done_buf_1 = 1'b0;
else
done_buf_1 = done;
end
//second level buffer
always #(posedge clk or posedge rst) begin
if(rst)
done_buf_2 = 1'b0;
else
done_buf_2 = done_buf_1;
end
In functional simulation, I discover the done_buf_1 rises one cycle after done, but done_buf_2 rises at the same time as done_buf_1.
What is the explanation for this?
Thank you!
You've already got answers with the solution ("use non-blocking assignments"), but here's an attempt at why you need to do that.
Both of your always statements have the same event, so they could run in any order. What seems to be happening is that the first one is running first. When the line...
done_buf_1 = done;
... is hit, it will block until the assignment is complete (it's a "blocking" assignment). Therefore done_buf_1 takes the new value immediately. This differs from the non-blocking version...
done_buf_1 <= done;
... which says 'give done_buf_1 the value of done (which I'll evaluate now) at the end of the time slice'.
Now we move on, and done_buf_2 is assigned.
done_buf_2 = done_buf_1;
Now, if done_buf_1 was updated with a blocking assignment it already has the current value of done, and you'll see both signal rise at the same time. If it was a non-blocking assignment then done_buf_1 still has the previous value of done, as it won't be updated until the end of the time-slice, the result being a 2 cycle delay for done_buf_2.
There's also another problem though. Remember that I said that the always statements could be run in either order because the events were the same? Well if the second one was executed first the code would appear to work as intended (db2 = db1; db1 = done; No problem). So it's worth knowing that using blocking assignments like this gives erratic results especially between tools. That can lead to some subtle bugs.
You're using blocking assignments = to model synchronous logic. You need to use non-blocking assignments <=.
As others have said: don't use blocking assignments (=) for this.
The key point is that "this" is the job of communicating between different processes. The race conditions inherent in blocking assignments make this unpredictable. VHDL takes this so seriously that it separates these types of assignment such that you can't use the wrong one (as long as you keep away from shared variables).
Some interesting writings on the subject from Jan Decaluwe:
Verilog's major flaw
VHDL's crown jewel

Resources