Verilog addition unexpectedly results in x - verilog

The output of this executable is x until you remove d from the c assignment. The output is x x x x. When d is removed from the assignment, the output is as expected "2 3 4 5".
module test();
logic [1:0] a, b, d;
logic [2:0] c;
assign c = a+b+d;
initial begin
d = 0;
a = 1;
b = 1;
$display(c);
a = 2;
b = 1;
$display(c);
a = 2;
b = 2;
$display(c);
a = 2;
b = 3;
d = 3;
$display(c);
end
endmodule

Both outputs are valid, you have a race condition.
A continuous assign statement is a concurrent process that waits for signals on the RHS to change, then evaluates the expression and makes the assignment.
The initial block is another concurrent process. As you procedurally make assignments to each signal, the scheduler is free to jump to to the other process and execute it, ... or it can continue executing statements until hitting a blocking delay, or it terminates.
If fact, many tools in-line continuous assignments as an optimization, only executing them when the lhs gets referenced. That could be what's happening here when you remove d from the rhs.

Your problem is in understanding verilog simulation. It is an event-driven flow.
In your case assignment to 'c' happens when any input to the assign statement change.
But the change will be detected only when execution of the non-timed chunk in your initial block is done. And this chunk ended with the last statement.
So, as a result, all your $display(c) will show the value of 'c' as it existed before the initial block starts execution. In order to see updates, you need let the code wait till the changes have a chance to propagate. A simple example would be the following:
initial begin
d = 0;
a = 1;
b = 1;
#1 $display(c);
a = 2;
b = 1;
#1 $display(c);
a = 2;
b = 2;
#1 $display(c);
a = 2;
b = 3;
d = 3;
#1 $display(c);
end
Adding #1 before every $display will let the changes to propagate and display expected results.
There is a gray area in interpretation of the code like yours. Note that the initial block has a, b, and d as the output. In the sequential code with no timing control constructs it just re-assigns the values of those outputs. For simulation semantics only the lastly assigned values matter and should trigger an event. However, it looks like some simulators might interpret it differently and trigger events whenever the value changes. This is up to the simulator implementation in this case. For example, as i noticed, VCS does trigger events for every change, but only in some cases. NC does not trigger those events.
I guess you can interpret the simulation behavior as undefined for this kinds of the code. To make it deterministic, use correct timing controls, as in the example above.

Related

Why is my counter out value producing StX?

I made a simple counter that goes to 32 and a testbench for it. I'm not sure why the value for the output (co) is still coming out as StX. I've been trying to debug this for many hours now and I'm not sure of the issue.
co is X (unknown) because it is a continuous assignment to an expression dependent on current, which is X. current is X because you declared it as a reg, and reg types default to X at time 0, and then you never assign it to a known value.
Your testbench always drives rst as 0. This means line 8 is never executed. Line 10 will be executed at every rising clk edge, but current will remain at X. X+1 returns X.
You need to reset your design properly. At time 0, you should assert the reset by setting rst=1. After a delay, you should release the reset setting rst=0.
initial begin
clk = 0;
rst = 1; // Assert reset
#20;
rst = 0; // Release reset
#10;
en = 1;
init = 1;
end
The reset of you counter is active high. You never set it to 1. You need to set it to 1 for at least one clock cycle.

Verilog - Changing a reg in sensitivity list in Always block

reg A,B,C;
always #(*)begin
//some other computations
C=B;
//some other computations
A=C;
end
always #(posedge clk)begin
B<=A;
end
Hi there,
In the code above, at the posedge of clk reg A changes the value of reg B and that starts the process of first always block since B is in the sensitivity list. My question is what will be happening at the line "C=B" since reg C is also in the sensitivity list? Will that start the process of the first loop again and causes an infinite loop?
I check that on simulation and it works fine. But I don't know want would happen on hardware.
My guess is it will not cause a problem. Since Verilog only creates a LUT to mimic the algorithm inside of the always block, that will not cause a problem on hardware. However, I am not sure so I would like to ask.
Thank you,
Remember that procedural code executes one statement at a time. Your code is effectively interpreted the same as
initial begin
#(B or C) // wait for a change on B or C
C = B;
A = C;
#(B or C) // wait for a change on B or C
C = B;
A = C;
#(B or C) // wait for a change on B or C
C = B;
A = C;
...
end
The assignment to C happens, but any change to C has already happened before you get to the next #. Synthesis interprets C as an intermediate value.

Wait for A Bit Change in Same Timestep in SV

Here is the code
module m;
bit x;
initial
begin
fork
begin
wait(x == 1);
wait(x == 0);
end
begin
#(x == 1);
#(x == 0);
end
#10 $display("Timeout");
join_any
disable fork;
end
initial
begin
#5;
x = 1;
// Some other Logical Stuff
x = 0;;
end
endmodule
Now in this code, Timeout will happen, because x = 1 & x = 0 is done in the single time step.
One solution is to provide delay between x = 1 & x = 0, then both waits will work fine.
Is there any other method, which can work without providing hard-coded delays?
Note :- With events or semaphores like stuff, this problem can be solved. But I am looking for the answer in terms of coding style or methods, which can work without usage of events.
There are several ways, which you can use here like event, semaphore, flag, etc.
I have added an event in your code. Please find a modified code in below link.
http://www.edaplayground.com/x/Ws3
There are other ways also like,
1. Assign value "1" to x, during its declaration
E.g., bit x=1;
2. Use blocking and nonblocking assignment together in your 2nd initial block.
E.g.,
initial
begin
#5;
x = 1;
// Some other Logical Stuff
x <= 0; // Add non-blocking assignment
end
end
=> The second option is not a good coding practice, but it'll solve your issue as both the assignment statments will work on different regions.

What are the uses of force - release statements?

From a hardware point of view, what do force and release statements model? What are the uses of these statements?
The force/release statements are generally used to aid in simulations.
One scenario is to avoid X-propagation in gate simulations. The RTL code sometimes contains registers without asynchronous resets. Although the RTL simulations will run cleanly, gate simulations often do not. Either the X's never get resolved, or they take so many cycles to resolve so as to make simulations take an impractical amount of time to run. By forcing and releasing a random known value into the register during reset, the simulation is allowed to proceed cleanly and complete in a timely manner.
Another scenario involves large counters. For example, to see a 32-bit counter roll over, it requires 4 billion cycles. Typically, you want it to roll over several times in one simulation. Again, this could take an impractically long time to simulate. The force/release can be used to deposit a random value into the counter close to the roll-over value.
Another scenario involves boosting code coverage results. It can be difficult to achieve 100% coverage on all metrics, especially when using IP which can not be modified. The force can be used to toggle an unused signal.
The force/release should be used sparingly and only when you are convinced it is valid to do so.
Based on IEEE Std 1364-2005, the force procedural continuous assignment statement shall override all procedural assignments to a variable or net. The release procedural statement shall end a procedural continuous assignment to a variable or net. The value of the variable shall remain the same until the variable is assigned a new value through a procedural assignment or a procedural continuous assignment.
For example:
module test;
reg a, b, c, d;
wire e;
and and1 (e, a, b, c);
initial begin
$monitor("%d d=%b,e=%b", $stime, d, e);
assign d = a & b & c;
a = 1;
b = 0;
c = 1;
#10;
force d = (a | b | c);
force e = (a | b | c);
#10;
release d;
release e;
#10 $finish;
end
endmodule
In the example above and gate and1 is patched to work as or gate. If you simulate it, you'd get following results:
Results:
00 d=0,e=0
10 d=1,e=1
20 d=0,e=0
Without force statement, for t = 10, e should be equal to 0 (since 1 & 0 & 1 = 0). Using force statement overrides result of and1 and force e = 1. But as soon as release is applied to e, the value is change to 0 (the functionality of and gate is restored).
In the example above you can also see that force/release can be applied both to regs (d) and wires (e). This statements are used in testbenches, when you want to force determined value in reg or wire.

Verilog Blocking Assignment

I am somewhat new to Verilog. I know that in a Clock Process we should use non blocking assignments, and in a Non Clock processes, we use blocking assignments.
I have came across this code, when I was reading someone else's code.
reg iowrb_int,iowrb_met;
reg iordb_int,iordb_met;
always#(*)
begin
iowrb_int <= iowrb_met;
iordb_int <= iordb_met;
iowrb_met <= iowr_bar;
iordb_met <= iord_bar;
end
I am really not sure about the above code ! I don't think it is doing any registering, correct? Would it mean anything to have a non-blocking in a always#(*) statement ?
Is there any difference in using blocking vs non-blocking in a always#(*) statement ?
The main difference is:
a blocking assignment is executed before the next assignment i.e. it blocks the execution of the next statement.
non-blocking assignments execute in parallel i.e. they don't block the execution of the statement following them.
Suppose a = 2 and b = 3 then non-blocking assignments:
a <= 4;
b <= a;
results in a = 4 and b = 2 - value of a before assignment
But
a = 4;
b = a;
Will result in a=4 and b=4 - value of a after the blocking assignment completes.
A variable getting synthesized to a register (latch or flip-flop) vs. combinatorial logic depends on the sensitivity list of the always block. It does not depend on use of blocking or non-blocking assignment.
For example:
always #(*) begin
if (enable)
q = d;
end
This will result in a D-latch since assignment to q is not specified for when enable==0 so it needs to remember is last assignment.
While
always #(*) begin
if (enable)
q = d;
else
q = f;
end
This will result in a mux (combinatorial logic) since assignment to q is specified for both cases of enable and so q need not remember anything.
The blocking vs non-blocking is so that your gate level (synthesis) matches your RTL simulation. Using a different one to alter the behaviour of the simulation as far as I know will not effect synthesis and therefore the behaviour of gate-level.
<= non-blocking effectively take a temporary copy of the copy right-hand side, and make the = blocking assignment at the end of the timestep.
a <= b;
b <= a;
is equivalent to:
a_temp = b;
b_temp = a;
//
a = a_temp;
b = b_temp;
The example uses combinatorial logic, that is it contains no state, so all inputs must be defined by all outputs.
always#* begin
iowrb_int <= iowrb_met;
iordb_int <= iordb_met;
iowrb_met <= iowr_bar;
iordb_met <= iord_bar;
end
When the right hand side updates the block should be retriggered. Since iowrb_met is on both sides I am not sure what this implies interms of electrical connectivity.
while <= implies copying to a temp location, combinatorial logic does not have this capability, it is always and continuously driven by the assignment.
I think in simulation you effectively have this:
always#* begin
iowrb_int_temp = iowrb_met;
iordb_int_temp = iordb_met;
iowrb_met = iowr_bar;
iordb_met = iord_bar;
iowrb_int = iowrb_int_temp;
iordb_int = iordb_int_temp;
end
In hardware you would have:
always#* begin
iowrb_int = iowrb_met; //= iowr_bar;
iordb_int = iordb_met; //= iord_bar;
iowrb_met = iowr_bar;
iordb_met = iord_bar;
end
Where iowrb_int is effectively the same as iowrb_met
Flip-flops are implied using always #(posedge clk
Combinatorial logic is implied using always #* but latches can be implied when the output is not fully defined from inputs.
By only changing to code to blocking assignments it may synthesize to latches and/or create logical equivalency check mismatches depending on the tools handle.
This is how it looks through the scheduler:
With blocking:
The *_int signals are assigned
The *_met signals are assigned
Move on to the next time step.
*_int keeps the non-updated values of *_met
With non-blocking:
The *_int signals are assigned
The *_met signals are assigned
A change to *_met is detected causes a loop back the the Active region of the scheduler
Re-assign the *_int signals
Re-assign the *_int signals
Move on to the next time step.
*_int has the same values as *_met
Waste CPU time to reprocessing. This is not important on a small project, but can add noticeable overhead used throughout a large project.
The correct, logical equivalent, and CPU friendly way would be to revers the assignment order (assign *_met before *_int):
always#(*)
begin
iowrb_met = iowr_bar;
iordb_met = iord_bar;
iowrb_int = iowrb_met;
iordb_int = iordb_met;
end
The *_int signals are assigned
The *_met signals are assigned
Move on to the next time step.
*_int has the same values as *_met
OR use *_bar as the assigning value (i.e. if a==b and b==c, then a==b and a==c):
always#(*)
begin
iowrb_int = iowr_bar;
iordb_int = iord_bar;
iowrb_met = iowr_bar;
iordb_met = iord_bar;
end
The *_int and *_met signals are assigned
Move on to the next time step.
*_int has the same values as *_met
As others have said, changing to blocking assignments here will actually not work. Using blocking assignments in combinational always blocks (which is the recommendation) require you to put assignments in the right order.
Using non-blocking assignments in combinational always blocks may seem attractive, because you can then have assignments in any order, like in VHDL. Besides performance, one good reason to avoid this is that it doesn't work with always_comb. This code does not work:
always_comb begin
tmp <= in;
out <= tmp;
end
The reason is that tmp will not be part of the sensitivity list. It will work as expected if you use always #(*), always #(tmp, in) or replace with blocking assignments.

Resources