I am reading the IEEE Standard Verilog Hardware Description Language (specifically IEEE Std 1364-2001) which unambiguously defines and discusses simulatable Verilog. Unfortunately, the document does not touch upon the notion of synthesis.
I haven't been able to find a similar reference for synthesisable Verilog. All I find is vague rules, or unnecessarily restrictive ones.
Where can I learn the formal language of synthesisable Verilog?
IEEE 1364.1 is an adjunct to the 1364 Verilog standard titled Verilog Register Transfer Level Synthesis, which attempts to define a common synthesizable subset. However, as Jerry points out, different tools support different constructs, and to determine tool-specific behavior, you need to consult the tool documentation.
There isn't a formal (BNF-style) syntax definition for synthesizable Verilog. Whether code is synthesizable depends on usage as well as syntax. For example, the behavior described by an always construct with incomplete sensitivity, like always #(a) o = a || b, isn't synthesizable. (Most tools will synthesize that code as if the sensitivity list were complete, resulting in a possible simulation/synthesis mismatch.)
Circuit constructs like latches and multiply-driven nets can be synthesized from a Verilog description, but are disallowed or discouraged under most design rules. There are also synthesizable constructs that are unsupported or inadvisable given the choice of target library. For example, describing a RAM that's larger than the maximum supported by a chosen FPGA technology, or describing tri-state drivers when they aren't present in the target library.
The general constructs to stick to for synthesizable Verilog are:
Combinational logic modeled with continuous assignments (assign statements)
Combinational logic modeled with always blocks, which should use blocking assignments, and either have a complete sensitivity list or use always #*
Sequential logic (flip-flops) modeled with always blocks, which should use non-blocking assignments, and have either posedge clock alone (for sync reset or non-reset flops) or posedge clock and posedge or negedge reset (for async reset flops) in the sensitivity list.
The safest coding style for sequential logic is to code only reset logic in the sequential always block:
always #(posedge clk or posedge reset)
if (reset)
q <= reset_value;
else
q <= next_value;
However, if you're careful, you can code additional combinational logic in the sequential block. A common case where it may make sense to do this is a mux in front of a flop:
always #(posedge clk)
if (!sel)
q <= sel0_value;
else if (sel)
q <= sel1_value;
else
q <= 'bx;
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.
This is a basic question but it seems to lack of clear explanation to me.
In many of code examples,one style to write FSM output is
assign a = (current_state==DONE)?1:0;
I confuse this with definition of latches. Will this combinational logic infer latches as "a" holds its previous value if current_state != DONE? It seems no warnings from my compiler.
sometimes, i would have
always#(posedge clk)
begin
if(reset)
a<= 1'b0;
else
if(current_state == DONE)
a <=1'b1;
end
This is certainly a sequential logic(tho my output does not depend on my chains of past input) and a would keep its previous value until my control signal current_state == DONE.I would guess this logic will synthesize to a mux to the input of a flipflop.
so if in the 2nd case that I actually have a clocked FSM, i would have my mux with FSM states output as the select signal input.
Until now, can i say anything that is not combinational logic will not generate any latches?
However,when i have a structure like the following,
always#(posedge DCO or posedge reset or posedge enable)
begin
if(reset)
begin
end
else if(enable)
begin
end
else
begin
end
end
I get a warning in my FPGA that i have inferred a latch with control signal enable.
Why?
My enable changes based on another state machine for example,
assign enable = (pcurrent_state == START)?1:0;
Moreover, we have unintentional latches and intentional latches. but design rule basically says to avoid latches to avoid timing arches. Can someone give some examples of where intentional latches should be used in design rather than clock gating example?
Plus,
The output of all the storage elements (flip-flops) in the circuit at any given time, the binary data they contain, is called the state of the circuit. The state of a synchronous circuit only changes on clock pulses. At each cycle, the next state is determined by the current state and the value of the input signals when the clock pulse occurs.(from https://en.wikipedia.org/wiki/Sequential_logic)
This sounds like describing a mealy machine to me rather than a typical sequential logic. My simplest sequential logic does not need my output change determined by my current_state
Thank you for any help. I am doing this coding everyday and reading its definition but it seems that i am confusing myself without discuss with others.
To answer your question in parts:
The given assign statement will not infer a latch as a does not retain it's value. It will be 1 if current_state == DONE and otherwise be 0. So it's pure combinational logic.
The second block of code implements a flip-flop with synchronous reset and only loads itself with 1'b1 if current_state == DONE so there is retention in that code. This code shouldn't generate a latch due to the edge sensitivity on a single clock.
The last block would be difficult for any synthesis tool to handle due to the sensitivity on serveral signals, which is not common in hardware. Moreover, if say enable is asserted but not an edge when a positive edge of DC0 comes along, the code would have the body of the else if (enable) run, thus simulating some sort of latching behavior. Synthesis tools generally allow for a single clock and single reset to be specified in the sensitivity list of an always block to indicate a flip-flop with asynchronous reset. While Verilog certainly allows for more complicated sensitivity lists, their physical meaning gets complicated quickly, thus inferring latches. In most designs, you shouldnt ever need these complex sensitivity lists are you are then getting into asynchronous design for which most synthesis tools are not well suited on a behavioral level. FPGA tools especially are poor at asynchronous elements and even latches as the logic cells in the fpga to which the design must be mapped are designed specifically for synchronous designs using flip-flops; that's how fpgas are implemented.
Finally, in non-fpga designs, it is sometimes desirable to use latches if edge sensitivity isn't required, as latches are physically smaller and can allow a design to be smaller, faster and more power efficient in some cases. However, you need to have a firm grasp on what you are designing and understand potential trade offs and timing requirements when doing so. Here's an example of when a latch is a useful element: https://electronics.stackexchange.com/questions/255009/what-is-application-of-latch-in-vlsi-design
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