Verilog - Changing a reg in sensitivity list in Always block - verilog

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.

Related

When I compile my Verilog code I get this message. Anybody know what is the reason?

When I compile my code I get these error msg for following lines. can someone explain it.
This is verilog code for a processor
assign Imm = instruction[7:0];
assign OUT1addr = instruction[2:0];
assign OUT2addr = instruction[10:8];
assign INaddr = instruction[18:16];
assign address = instruction[23:16];
assign address = instruction[7:0];
The following message comes for ABOVE LINES
tgt-vvp sorry: procedural continuous assignments are not yet fully supp
orted. The RHS of this assignment will only be evaluated once, at the time the assignment statement is executed.
You did not do what I asked which is show me where that code is.
From the error message I very much suspect that code is inside an always block:
always #( ...)
...
assign Imm = instruction[7:0];
This is called "a procedural continuous assignment".
The alternative is:
always #( ...)
...
Imm = instruction[7:0];
This is a standard assignment.
There is a significant difference between the two. You would normally not use the first form (unless you really, really know what you are doing.)
Thus the solution is to remove all the 'assign' keywords if they are inside an always block.
Outside an always you need the assign:
always #( * )
begin
...
x = y ^ z;
end
assign write = valid & select;
The short answer is you should probably remove the assign keyword.
The assign keyword has two different meanings depending on context you do not show.
When used at the top level of a module, the assign keyword is a permanent process sensitive to RHS changes and assigns it to the LHS wire. The assign statement has equivalent functionality to the always block below
module mod;
...
assign Awire = B + C;
always #(B or C) begin
Areg = B + C;
end
endmodule
When used inside a procedural process, it is a temporary process that assigns the LHS variable every time the RHS changes. The two always blocks below have the same functionality
module top;
...
always #(sel)
begin
if (sel)
assign Areg = B;
else
assign Areg = C;
end
always #(sel or B or C) // #*
begin
if (sel)
Areg = B;
else
Areg = C;
end
endmodule
Unfortunately, almost all synthesis tools require you to write your code with a complete sensitivity list as in the latter always block. Thus this eliminates allowing the use of assign inside a procedural block.

how many flip-flips would this code produce when synthesized?

I'm trying to understand how many flip-flips would this code produce when synthesized?
I've got 2 test cases with non-blocking and blocking assignment code.
Test 1.
wire aclk;
wire [1:0] a;
reg [1:0] c;
reg [1:0] b;
always #(posedge aclk)
begin
b <= a + 1;
c = b;
end
Test 2.
wire aclk;
wire [1:0] a;
reg [1:0] c;
reg [1:0] b;
always #(posedge aclk)
begin
b = a + 1;
c <= b;
end
The Test 1 has 4 FFs and Test 2 has 2 FFs.
I can't understand how does it make a difference I just switching the code.
Thanks for letting me know at all.
They are functionally different. Non blocking assignment evaluate the right hand side and then continue to the next statement, storing into the left hand side isn't done until all other statements are evaluated first. Blocking statements evaluate the right hand side and store it into the left hand side immediately.
Test1 is doing this:
evaluate (a+1)
store b into c , BEFORE (a+1) is stored into b!!!
store (a+1) into b
Test2 is doing this:
evaluate (a+1)
store (a+1) into b
store b into c
Like toolic mentioned, you generally used non-blocking statements in sequential logic. Most people also recommend not mixing non-blocking and blocking statements in the same begin-end block.

Verilog: Is the following code going to make a race condition?

I'm trying to make a pipeline processor using Verilog HDL. I realized that there are maybe some race conditions somewhere in my code. So I'm going to write a sudo code and would like to ask you about if there is a race condition within and how to avoid it :
module A(input wire reset, input wire clock, output reg a_reg_o);
always #(posedge clock)
begin
if(reset == 1'h1)
begin
a_reg_o = 1'h0;
end
else
begin
a_reg_o = 1'h1;
end
end
endmodule
module B(input wire reset, input wire clock, input a_i);
reg b;
always #(posedge clock)
begin
if(reset == 1'h1)
begin
b = 1'h0;
end
else
begin
if(a_i == 1'h1)
begin
b = 1'h1;
end
else
begin
b = 1'h0;
end
end
end
endmodule
module Main(input wire reset, input wire clock);
wire a_o;
A a(reset, clock, a_o);
B b(reset, clock, a_o)
endmodule
So imagine I trigger reset signal. After the first positive edge of clock the register a_reg_o is going to be 0 and register b from module B also is going to be 0 (No race conditions yet). Now I release the reset button and let it to be negative. On the next positive edge of the clock the register a_reg_o is going to be 1, but what about register b from module B ? Is it going to be :
1. Zero, Because it didn't see the a_i changes yet.
2. It depends on the modules (A and B) total delay ( i.e. a race condition).
Thank you.
Yes there can be a race condition, because you won't know whether the net a_o is first driven by module A and then captured by module B or vice versa.
So you should use the Non Blocking Assignment for this, as that will ensure that no matter which module gets executed, the module B will always have the previous value of net a_o.
You can find more about this Non Blocking Assignments with following link. http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA.pdf
This is why there a non-blocking (NBA) assignments in Verilog. The coding rule is whenever there are multiple processes (in this case, multiple always blocks) accessing the same signal (a_o) synchronized to the same event (#posdege clock) where one process writes and another process reads, you need to use and NBA <= assignment to write to the signal.

What does always block #(*) means?

If I write the following code:
module POLY(CLK,RESET_n,IN_VALID,IN,OUT_VALID,OUT);
input CLK,RESET_n,IN_VALID;
input [ 3:0] IN;
output OUT_VALID;
output [12:0] OUT;
and then use it:
always #(*)
begin
.........
end
Does it mean that the input CLK,RESET_n,IN_VALID;input [ 3:0] IN; will trigger the always block or only the input that has used in the block will trigger the always block?
But it doesn't write posedge or negedge, so the two both edge will trigger the always block or not?
The (*) means "build the sensitivity list for me".
For example, if you had a statement a = b + c; then you'd want a to change every time either b or c changes. In other words, a is "sensitive" to b & c. So to set this up:
always #( b or c ) begin
a = b + c;
end
But imagine you had a large always block that was sensitive to loads of signals. Writing the sensitivity list would take ages. In fact, if you accidentally leave a signal out, the behaviour might change too! So (*) is a shorthand to solve these problems.
It considers that all the variable will be in sensitivity list. So, you don't need to worry about adding them in the sensitivity list.
It will behave like combinational logic.

"<signal> is not a constant" error in if-statement

I am trying to write a simple module to output a 14-bit number based on the value of four input signals. My attempt is shown below.
module select_size(
input a,
input b,
input c,
input d,
output [13:0] size
);
if (a) begin
assign size = 14'h2222;
end
else begin
if (b) begin
assign size = 14'h1111;
end
else begin
if (c) begin
assign size = 14'h0777;
end
else begin
assign size = 14'h0333;
end
end
end
endmodule
Upon compilation, I receive the following error:
ERROR:HDLCompiler:44 - Line 67: c is not a constant
I don't understand why that particular if-statement isn't working if the other two preceding it are. I have tried changing the condition to
if (c == 1) begin
but to no avail.
Does anybody know how to solve this error? Thank you!
Two problems:
1) You need to put if statements inside an always block.
If you use verilog-2001, you can use
always #*
if ....
end
end
Otherwise specify all the inputs in the sensitivity list:
always #(a or b or c or d)
if ....
end
end
2) Constant assignments are not allowed inside if statements.
Remove the assign keyword from any statements inside the if block:
if (a) begin
size = 14'h2222;
end
You will also have to declare size as a reg type.
However my preference would be to rewrite the entire module with conditional operator, I find it much preferrable to read. This following module achieves the same result:
module select_size(
input a,
input b,
input c,
input d,
output [13:0] size
);
assign size = a ? 14'h2222 :
b ? 14'h1111 :
c ? 14'h0777 :
14'h0333 ;
endmodule
As #Tim has already answered, using reg types inside always blocks or wire with assign.
#Tim has also described the nested ternary assignments, while in the example are written very well, they are generally seen as bad practice. They imply a very long combinatorial path and can be hard to maintain. The combinatorial path may be optimised by synthesis which should imply a mux with optimised selection logic.
Easier to maintain code will have a lower cost of ownership, and as long as it does not lead to a larger synthesised design it is normally preferred.
My implementation would be to use a casez, (? are don't cares). I find the precedence of each value easier to see/debug.
module select_size(
input a,
input b,
input c,
input d,
output logic [13:0] size //logic (SystemVerilog) or reg type
);
always #* begin
casez ({a,b,c})
3'b1?? : size = 14'h2222 ;
3'b01? : size = 14'h1111 ;
3'b001 : size = 14'h0777 ;
3'b000 : size = 14'h0333 ;
default: size = 'bx ;
endcase
end
endmodule

Resources