I'm a bit confused about what is considered an input when you use the wildcard #* in an always block sensitivity list. For instance, in the following example which signals are interpreted as inputs that cause the always block to be reevaluated? From what I understand clk and reset aren't included because they dont appear on the right hand side of any procedural statement in the always block. a and b are included because they both appear on the right hand side of procedural statements in the always block. But where I'm really confused about is en and mux. Because they are used as test conditions in the if and case statements are they considered inputs? Is the always block reevaluated each time en and mux change value? I'm pretty much a noob, and in the 3 Verilog books I have I haven't found a satisfactory explanation. I've always found the explanations here to be really helpful. Thanks
module example
(
input wire clk, reset, en, a, b,
input wire [1:0] mux,
output reg x,y, z
);
always #*
begin
x = a & b;
if (en)
y= a | b;
case(mux)
2'b00: z = 0;
2'b01: z = 1;
2'b10: z = 1;
2'b11: z = 0;
endcase
end
endmodule
Any signal that is read inside a block, and so may cause the result of a block to change if it's value changes, will be included by #*. Any change on a read signal used must cause the block to be re-evaluated, as it could cause the outputs of the block to change. As I'm sure you know, if you hadn't used #* you'd be listing those signals out by hand.
In the case of the code you've provided it's any signal that is:
Evaluated on the right hand side of an assignment (a and b)
Evaluated as part of a conditional (en and mux)
...but it's any signal that would be evaluated for any reason. (I can't think of any other reasons right now, but maybe someone else can)
clk and reset aren't on the sensitivity list because they aren't used. Simple as that. There's nothing special about them; they're signals like any other.
In your example, the following signals are included in the implicit sensitivity list:
a
b
en
mux
clk and reset are not part of the sensitivity list.
This is described completely in the IEEE Std for Verilog (1800-2009, for example). The IEEE spec is the best source of detailed information on Verilog. The documentation for your simulator may also describe how #* works.
The simplest answer depends on if you are writing RTL, or a testbench. If you are writing RTL then you should try to forget about the concept of Sensitivity lists, as they don't really exist. There is no logic that only updates when an item on the list is triggered. All sensitivity lists can do in RTL is cause your simulation and actual circuit to differ, they don't do anything good.
So, always use "always #*" or better yet "always_comb" and forget about the concept of sensitivity lists. If the item in the code is evaluated it will trigger the process. Simple as that. It an item is in an if/else, a case, assigned to a variable, or anything else, it will be "evaluated" and thus cause the process to be triggered.
But, just remember, in digital circuits, there is no sensitivity list.
Related
I understand that always block can be used to implement procedural and sequential logic.
Will the gate-level realization of the following two codes be the same? If yes, what is the correct way of describing this continuous-time logic?
a.
module func(input a, input b , output reg o);
always #(a,b)
o=a&b;
endmodule
b.
module func(input, a, input b, output o);
assign o = a & b;
endmodule
In (a), 'o' is a reg type and in (b) it is a wire. What does this difference mean?
What are the required 'always' block properties for the synthesis tool to implement a FF? I know the following will result in a FF:
always #(posedge clk or negedge rst)
[...]
But, I'm looking for a more in-depth understanding.
Your (a) and (b) codes are functionally equivalent. This means that they will simulate the same way and they will infer the same logic when synthesized.
They use 2 different styles of modeling: (a) uses a procedural assignment because it uses an always block, whereas (b) uses a continuous assignment because there is no always block and it uses the assign keyword.
In this simple case, there is no "correct" way; they are 2 different styles to achieve the same functionality. For such simple logic, it is preferable to use (b) because it uses less code and it is easier to understand. However, if your combinational logic were more complicated, the procedural approach might be easier to understand.
In (a), the o signal must be a reg type since it is assigned inside a procedural logic block. There is no such requirement for continuous assignments. In this case, defining a reg type does not result in a flip-flop. A reg only infers a flip-flop when the always block describes sequential logic
Synthesis tools look for specific types of patterns in Verilog code to infer sequential logic. The following will infer flip-flops with an asynchronous reset:
always #(posedge clk or negedge rst)
if (!rst) ...
else ...
The following will infer flip-flops with an synchronous reset:
always #(posedge clk)
if (!rst) ...
else ...
These are just a couple examples.
I understand that always block can be used to implement procedural and sequential logic.
Will the gate-level realization of the following two codes be the same? If yes, what is the correct way of describing this continuous-time logic?
a.
module func(input a, input b , output reg o);
always #(a,b)
o=a&b;
endmodule
b.
module func(input, a, input b, output o);
assign o = a & b;
endmodule
In (a), 'o' is a reg type and in (b) it is a wire. What does this difference mean?
What are the required 'always' block properties for the synthesis tool to implement a FF? I know the following will result in a FF:
always #(posedge clk or negedge rst)
[...]
But, I'm looking for a more in-depth understanding.
Your (a) and (b) codes are functionally equivalent. This means that they will simulate the same way and they will infer the same logic when synthesized.
They use 2 different styles of modeling: (a) uses a procedural assignment because it uses an always block, whereas (b) uses a continuous assignment because there is no always block and it uses the assign keyword.
In this simple case, there is no "correct" way; they are 2 different styles to achieve the same functionality. For such simple logic, it is preferable to use (b) because it uses less code and it is easier to understand. However, if your combinational logic were more complicated, the procedural approach might be easier to understand.
In (a), the o signal must be a reg type since it is assigned inside a procedural logic block. There is no such requirement for continuous assignments. In this case, defining a reg type does not result in a flip-flop. A reg only infers a flip-flop when the always block describes sequential logic
Synthesis tools look for specific types of patterns in Verilog code to infer sequential logic. The following will infer flip-flops with an asynchronous reset:
always #(posedge clk or negedge rst)
if (!rst) ...
else ...
The following will infer flip-flops with an synchronous reset:
always #(posedge clk)
if (!rst) ...
else ...
These are just a couple examples.
Let's say there's a code that runs like this
reg [4:0] data;
always # (posedge clk, posedge clr)
begin
if(clr)
data <= 0;
else
data <= data +1;
end
How would this look like in circuit level? My guess is roughly
but then that wouldn't help if Clk goes from 0 to 1 while Clr is 1......
Also, is it good practice to have multiple elements in the sensitivity list? From what I see, there's som overhead going on here..
Verilog excerpt will infer DFF (D Flip-Flop) with async reset. This happens due to the fact that reset signal is a part of sensitivity list.
NOTE1: as per LRM for Verilog, adding the reset to the sensitivity list is what makes the reset asynchronous.
NOTE2: each Verilog procedural block should model only one type of flip-flop. In other words, a designer should not mix resetable (sync or async) flip-flops with follower flip-flops (flops with no resets) in the same procedural block.
Your diagram is incorrect, 'clr' signal will be connected to extra input of the DFF called as CLEAR (it is basically an async reset). I suggest to start with some sort of Verilog tutorial, this is very basic thing and it is well explained in materials that are generally available. To grasp on concept of reset in HDL code I recommend the following material:
http://www.sunburst-design.com/papers/CummingsSNUG2003Boston_Resets.pdf
The schematic is not accurate. 4 D-FF will be implemented for each bit of data declared.
Adding reset (i.e. clr) to sensitivity list will make the ckt async (Verilog LRM).
The D-FF will have an additional clear pin, there will be NO bubble to this pin as your reset (i.e. clr) is active high.
I just want to use some if else statement in verilog.
So I have to use always block.
integer count,index;
reg a=0;
always#(a) begin
a=1;
for(count=0;count<7;count=count+1) begin
index=4*count;
if((significand[index]==1'b0)&&(significand[index+1]==1'b0)&&
(significand[index+2]==1'b0) &&(significand[index+3]==1'b0))
lzero=lzero+1;
end
end
This code does make some sense now. I was able to get the correct simulation result, but I failed to get the correct synthesis on the board. Please help
This is a very typical problem with people who know how to program in C or C++ but forget that Verilog and VHDL are not the same as those.
EVERY signal line of Verilog code inside the ALWAYS block are 'executed' at the same time. The same goes with the combinatorial logic outside of the ALWAYS block.
In your code, both the
assign a=1'b1;
assign a=1'b0;
Will happen at the same time, no matter what.
The only way to change that is to put the last line inside your always block,after the end statement of the for loop.
One page that will give you some help on understanding the difference between C and Verilog is the page:EE-Times: The C Programmers Guide to Verilog
Neither assign 1'b1; nor assign 1'b0; are valid assignments. If you want to constantly drive some net with 1'b1, then you have to write something like assign myvar = 1'b1;.
Also, if your intent was to actually assign to a, then always block doesn't make sense since a is the only thing in its sensitivity list meaning that that block must be executed whenever a changes its value. Since a will essentially never change its value, that block should never be executed.
It is hard to help you out unless you provide a minimal working example demonstrating your problem. The only thing that I can recommend is to use ternary operator in assign right hand side statement. That way you can model a behavioural logic without using always block. For example:
assign a = (b == 1'b1 ? c : 1'b0);
Hope it helps.
UPDATE:
Your second code example is neither complete nor legal as well. You cannot have two combinatorial assignments for the same net.
However, a sensitivity list in always block is now a star, which is Verilog 2001 notation to include all right hand side operands into a sensitivity list automatically. In your case, the block will get executed every time significand or lzero changes.
I have read "Nonblocking Assignments in Verilog Synthesis, Coding Styles that Kill!" by Clifford Cummings. He says that the following code (page 12, simplified) is a correct implementation of a flip-flop often used in textbooks, even if not exactly the kind that anyone should use. The document won a best paper award, so I assume the claim is true.
module ff (q, d, clk)
output q;
input d, clk;
reg q;
always #(posedge clk)
q = d;
endmodule
I would like to know why this would continue to work correctly if two or more of these flip-flops were connected in series. Say
module two_ffs (q, d, clk)
input d, clk;
output q;
wire tmp;
ff firstff (tmp, d, clk);
ff secondff (q, tmp, clk);
endmodule
The way I see it, it's possible that the value of tmp is updated before it is used by secondff, thus resulting in one flip-flop rather than two. Can someone please tell me what part of the standard says that cannot happen? Many thanks.
[not that I would ever contemplate writing code like that, I just want to understand the blocking/nonblocking behavior even in cases when poor coding style makes the meaning non-obvious]
Added later:
I now think the paper is unlikely to be correct. Section 5 "Scheduling Semantics" of the 1364-2201 Verilog standard explains what happens. In particular, section 5.6.6 "Port connections" on page 68 says that unidirectional ports are just like continuous assignments. In turn, a continuous assignment is just an always block sensitive to everything. So the bottom line is that that the two instantiations of an ff in my example below are equivalent to a module with multiple always clauses, which everyone would agree is broken.
Added after Clive Cummings answered the question:
I am grateful to CC for pointing out that that the statements above taken out of section 5 of the standard only refer to the timing of update events, and do not imply literal equivalence between e.g. some continuous assignments and always blocks. Nevertheless, I think they explain why some simulators (e.g. Icarus Verilog) will produce different simulation results with a blocking and a non-blocking assignment in the "flip-flop". [On a larger example, I got 2 apparent ffs with a blocking assignment, and the correct five with a non-blocking one.] Other simulators (e.g. Modelsim with default options or Cver) seem to produce the same result no matter which form of assignment is used.
All -
A few corrections and updates. Section 5.6.6 of the 2001 Verilog Standard does not say that "unidirectional ports are just like continuous assignments," it says "Ports connect processes through implicit continuous assignment statements." There is a difference that I will note below.
Second, "a continuous assignment is just an always block sensitive to everything," is not true. Continuous assignments Drive values onto nets that can be driven by other sources with pre-defined resolution functions as described in the Verilog Standard. Always blocks Change values of variables and last procedural change wins (no resolution).
Regarding my description of the 1-always block flip-flop, my description in the paper is not 100% accurate (but is usually accurate). The 2-instantiated flip-flop model in theory does have a race condition, though it is rarely seen. The race is rarely seen because when you make an always block assignment to a variable that is declared as an output, Verilog compilers automatically throw in an "implicit continuous assignment statement" (IEEE-1364-2001, Section 5.6.6, 1st paragraph) to convert the procedural variable into a net-Driving assignment (you never see this happen!) This conversion is typically sufficient to introduce the equivalent of a nonblocking assignment delay on the port, so the simulation works. I have experimented in the past with compiler optimization switches that effectively remove the module ports between the flip-flops and have observed the unwanted race conditions, so technically, my description of an okay 1-always, blocking-assignment flip-flop is not 100% correct; hence, you should still use the nonblocking assignments described in the paper.
The 2-always blocking-assignment example in the same module has a definite race condition. As written, it will probably work because most compilers execute the code top-down, but if you reverse the order of the always blocks, you will probably see a race.
Regards - Cliff Cummings -
Verilog & SystemVerilog Guru
Reading Version 1.3 of the paper, Section 9 Example 13. The text under it explains that it is OK if the module only contains a single always block. My current understanding is that it is not an issue between separate modules. Allowing your example to work. However if a module contained multiple always blocks then the order of execution is undefined and will lead to the race conditions talked about in section 2 of the paper.
The example below is almost the same as the 2 flop example in the question, except it is in 1 module and so has an undefined order of execution, this will likely not work.
module ff (q, d, clk)
output reg q;
input d, clk;
reg d_delay ;
always #(posedge clk)
d_delay = d;
always #(posedge clk)
q = d_delay;
endmodule