I'm using inertial delays in system verilog in the following code, mainly to filter glitch
logic y;
wire y_filter;
assign #10us y_filter = y;
my issue is that for the first 10us y_filter is at 'X'.
Is there a simple way to initiliaze the signal at 0?
Thanks,
Alessandro
You can use a force statement to force y_filter to 0 at time 0, and then release it at just after 10us. You will need to make sure that the release does not coincide with any scheduled change from the continuous assign statement to prevent another glitch.
Related
I am pretty new to Verilog
and I use it to verify some code from a simulation program.
Right now I am struggeling if a verilog code snippet because the simulation programm uses 2 clocks ( one system clock and a pll of this ) where two hardware componentes work together, thus synchronize each other:
module something (input data)
reg vid;
always #(posegde sys_clk)
vid <= data;
always #(posegde pll_clk)
if (vid)
// do something
When reading about non blocking assignments it says the evaluation of the left-hand side is postponed until other evaluations in the current time step are completed.
Intuitive I thought this means they are evaluated at the end of the time step, thus if data changes from 0 to 1 in sys_clk tick "A", this means at the end of "A" and the beginning of next sys_clk tick this value is in vid and so only after "A" the second always block ( of pll_clk) can read vid = 1
Is this how it works or did i miss something ?
Thank you :)
In this particular case it means that
if posedge sys_clk and pll_clk happen simultaneously then vid will not have a chance to update before it gets used in the pll_clk block. So, if vid was '0' before the clock edges (and is updated to '1' in the first block), it will still be '0' in the if statement of the second block. This sequence is guaranteed by use of the non-blocking assignment in the first block
if the posedges are not happening at the same time, then the value of vid will be updated at posedge sys_clk and picked up later at the following posedge of pll_clk.
In simulation non-blocking assignment guarantees that the assignment itself happens after all the blocks are evaluated in the current clock tick. It has nothing to do with the next clock cycle. However, the latter is often used in tutorials to illustrate a particular single-clock situation, creating confusion.
Also being simultaneous is a simulation abstraction, meaning that both edges happen in the same clock tick (or within a certain small time interval in hardware).
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.
I have a design I am working on in Verilog. In part of my design a counter is incremented by a clock - this occurs a half clock cycle before the output of the counter is latched into a parallel load shift register.
In some circumstances I want to HOLD the counter. To do this I have gated the clock:
assign sync_gated = i_sync || !r_en;
This is combinational logic, but I don't see any issue as there is a full clock cycle (we run at 2MHz) for the output of the counter to settle. A few ns of propagation delay will not cause a problem.
The code synthesises OK, but I get this warning:
y_ctr/sync_gated_inv(y_ctr/sync_gated_inv1:O)|
NONE()(y_ctr/r_axis_address_15)| 16 |
x_ctr/sync_gated_inv(x_ctr/sync_gated_inv1:O)|
NONE()(x_ctr/r_axis_address_15)| 16 |
---------------------------------------------+---------------------------------+-------+ (*) These 2 clock signal(s) are generated by combinatorial logic, and
XST is not able to identify which are the primary clock signals.
Please use the CLOCK_SIGNAL constraint to specify the clock signal(s)
generated by combinatorial logic
Is this bad design? if so, why? or do I just need to add some constraint here to reassure the compiler?
Thank you.
You can't 'just' gate the clock. You can get all kind of clocking artifacts.
Look here for how to gate a clock.
Everywhere it is mentioned this as a guideline, but after lot of thought i want to know what harm will it cause if we use Nonblocking statement inside Always Block for Combinatorial also. I won't be mixing the two together. But what i feel is when we use Nonblocking for Combinatorial statements in Always Block it represents the hardware more accurately. Does it not...?
For Example, if we take the following circuit:
In this diagram when the inputs a,b,c are supplied the outputs x1 and x will not be available instantly. There will be gate delays. first x1 will be available and then x will be available. If we use blocking statements both are available instantly. If we use nonblocking, it resembles the hardware more accurately.
For Example, if we take the following code based on the above diagram
module block_nonblock(output logic x,x1,y,y1,input logic a,b,c);
always#* begin : BLOCKING
x1 = a & b;
x = x1 & c;
end
always#* begin : NONBLOCKING
y1 <= a & b;
y <= y1 & c;
end
endmodule
This synthesizes as:
Both are synthesized as And gates, and give same simulation results but when we check for the changes in output in delta time, i feel the Non blocking matches the hardware more accurately as compared to the Blocking.
Also i went through : IEEE P1364.1 / D1.6 Draft Standard for VerilogĀ® Register Transfer Level Synthesis,
which specifies the use of non blocking for Sequential modeling but doesn't specify specifically using blocking for Combinational modeling using Always
Block. It says don't mix the two(Blocking and Nonblocking) in Combinational statements.
So, shouldn't we use nonblocking for combinational statements in always blocks which are dealing with pure combi logic (non sequential/ no clocks involved)
The harm is in simulation; in performance, and in race conditions.
Your NONBLOCKING code executes twice for every change in a or b. Non-blocking assignment updates are scheduled into a later queue of events, and this causes a much bigger rippling effect where blocks get repeatedly executed.
When you simulate RTL code, you are doing so in the absence of physical delays and synthesis tools understand how the logic is going to be implemented. But simulation tools cannot do this and also need to work with non-synthesizable code. They have to execute the code exactly as written. And they also have to deal with massive amounts of concurrency executing code on a processor with a single or limited number of threads. So simulation introduces race condition in software that would not exist in real hardware. Non-blocking assignments are there to prevent those race conditions when writing sequential logic. But they can have the opposite affect if you use them in combinational logic, especially when used in the combinational logic involved in the generation of clocks.
You ask "So, shouldn't we use nonblocking for combinational statemnts in Sequential?" The answer is No.
If you use non-blocking assignments for combinational logic in clocked always blocks, you will get more flip-flops than you expect. Basically, non-blocking assignments in clocked always blocks will behave like flip-flops when you simulate and infer flip-flops when you synthesise.
So,
1 - use blocking assignments for gates and
2 - use non-blocking assignments for flip-flops.
Your very own description of the behaviour of the circuit suggest actually the use of blocking operations.
You say: (emphasys mine)
In this diagram when the inputs a,b,c are supplied the outputs x1 and
x will not be available instantly. There will be gate delays. first x1
will be available and then x will be available. If we use blocking
statements both are available instantly. If we use nonblocking, it
resembles the hardware more accurately.
So you need x1 to be available before x. So your always block must use a blocking assignment, so...
always#* begin : BLOCKING
x1 = a & b;
x = x1 & c;
end
x1 first will have a known value, and then, and only then, x will have a value. If you use non blocking...
always#* begin : NON BLOCKING
x1 <= a & b;
x <= x1 & c;
end
You are telling the simulator that x1 and x will be evaluated at the same time.
Although for synthesis this may work, in simulation this won't, and you want to make sure your simulated circuit works as intended before going over the synthesis phase.
We should not use non-blocking assignments in Combinational block, because if we use non-blocking it will infer the transport delays in the design due to this our results will never come what we expected, but if we use blocking , this blocking will able to suppress the transport delays in the design and we can safely said that there is no glitches in the waveform. So it is recommended that we should use blocking statements in combinational designs.
I have found a satisfactory answer and need input for it. I feel we should use Nonblocking statements for both combinational and sequential statements.
For sequential it is pretty clear y we should use.
I will describe the reason for Combi Blocks.
For combinational segments we will use Nonblocking Statements because, when we use Blocking or NonBlocking statements, even though it gives us the same hardware or RTL in the end; it is the nonblocking statements which shows us the glitches in simulation. Theses glitches will be there in hardware as well (because of Gate Delays), so we can rectify them when we see them in Simulation so that they will cause less harm at a later stage of the design/development cycle.
In the circuit I originally mentioned in the question if we give the inputs together as (A = 1,B = 1,C = 0) and then change them together after say 10ns as (A=1,B=0,C=1) then we can see that there is a glitch. This glitch will be there in actual Hardware as well. But this is only shown in simulation by Nonblocking Statements Output (Y) and not by Blocking Statements Output (X). Once we see a glitch we van take additional measures to prevent this from happening, so that it doesnt happen in hardware.
Hence i feel it is safe to conclude that we must use Nonblocking statements for combi blocks.
I'm having problems with understanding such a simply looking thing: blocking and non-blocking assignments.
I created a small test bench just to simulate the behavior of this code:
module ATest(clk, out);
input wire clk;
output reg [7:0] out;
reg [7:0] A;
initial begin
A <= 8'b0;
end
always #(posedge clk) begin
A = A + 1;
out = A;
end
endmodule
After simulation, I got this wave:
I expected the same value under both A and out, as I assigned values to them sequentially. Why is out "don't care" during the first clock?
Then I tried to use non-blocking assignment. I changed a part of my code into:
always #(posedge clk) begin
A <= A + 1;
out <= A;
end
And I got this wave:
I didn't expect anything here, because non-blocking statements are kind of mystery to me. Why is both A and out set to "don't care"?
Also, I found different names on every page I got to, so please help me out:
Are blocking and non-blocking interchangeable with sequential and concurrent as terms? Which one is right: non-blocking statement or concurrent statement?
Without diving too deep into the simulation cycles used by Verilog Simulators, you can think of non-blocking vs blocking assignment simply as this:
Blocking assignment happens inline at the time the given assignment is executed, so that means if I have a line like A = A + 1, that means we take the present value of A, add 1 and assign A that new value. So, the assignment "blocks" execution until it is done.
Non-blocking assignment (NBA) happens at a time slightly later than while the line is executed. You can think of non-blocking assignments as lines telling the simulator to schedule this assignment for a little bit later (note, later is still with the same simulation time step, so all of this is still happening in simtime t). So, if you have something like A <= A + 1, this means take the value of A at the time of executing this line, add 1 and schedule A to be updated to that value in a little bit, but keep moving on with the lines following that one. So, if the next line after is out = (A == 1) ? 1 : 0, this line will execute using the old value of A, not the incremented one. Once the simulator finished with the active code, it can move on to perform all the non-blocking assignments. Now, A will get the incremented value and all other non-blocking assignments will take effect.
So, to your examples. In case one, we see the delayed effect of NBA. In the initial block, A is assigned to 0, which means A will take on the value of 0 a little bit later (still within sim time 0 remember); ie the assignment is scheduled to take place after all blocking assignments have run (Not strictly true but it works in this case). Also, you have the clock's posedge happen so the always block runs. Here, A takes on the value A + 1, but remember, the assignment of A to 0 hasnt happened, so A still has its initial value of 8'bx. so, A + 1 is also 8'bx. And since this is a blocking assignment, it happens right away. So, A doesnt change from don't care. Continuing on, out gets the current value of A, which is 8'bx. So, we get the don't cares on out. After these and other blocking assignments are done, now we finish up the NBAs, in this case, A to become 0. So, still within sim time 0, A becomes 0 and we are done. At the next posedge of the clock, A is 0, out is don't care and your always block runs as expected, incrementing A and assignment out to the same value.
If you change the always block to use NBA (which it should if it is suppose to be a register), things change slightly. The initial block still results in a NBA scheduled for A to become 0. But now, the always block does something different. Now, A <= A + 1 instead of assigning A to don't cares right away, it schedules A to become 8'bx (remember, the right-hand side expression for what value to assign is evaluated inline, so A + 1 still uses A as don't care just as before; whats changed is when A takes on this new value) and this is scheduled after A to become 0. So, both the NBAs of A are set up, but the one telling A to be 0 happens first and is wiped out by the later assignment of A to 8'bx. out is similarly scheduled to take on 8'bx but now, A never becomes 0. As such, both A and out get stuck at 8'bx.
You can look through the Verilog or SystemVerilog LRM's to get a better understanding of sim cycles and what really goes on, but I hope this helps you better understand the difference!
Your issue come from using a non-blocking assignment in your initial block. Use initial A = 8'b0; instead.
The casue for this is likely how the two assignments are processed. = assignments are done incrementally, with any new values being available to subsequent assignments. Changes made via <= assignments are only available once all assignments have been processed.
Because your first edge is at t = 0 (when intial blocks are processed), in the first example A is assigned 0, but that 0 isn't available to out until after it is processed. That's while the first cycle looks weird, but everything else is OK. In the second, A is assigned both 0 and A+1, so the simulator uses the always block instead of the initial, going with A+1, when A is still an unknown value. As such, the values for A and out are never known.
The terms are equivalent. "Blocking" is the same as "sequential" because "blocking" means that the assignment must be done before the simulator moves to the next line (in sequence). "Non-Blocking" means that all the lines may be done at once. As everything with Verilog, it helps to imagine the hardware intended, so you may think of it as "parallel" vs. "serial" sometimes.
Is there a positive clock edge at time 0 in your simulation?