Is the use of records the solution to all latch problems in VHDL - vhdl

I was recently told that the solution to all (most) problems with unintended latches during VHDL synthesis is to put whatever the problematic signal is in a record.
This seems like it's a little bit too good to be true, but I'm not that experienced with VHDL so there could be something else that I'm not considering.
Should I put all my signals in records?

No, you should not put all your signals in records. This will quickly become very confusing and you will not gain anything by using the record.
One way that a record may help you avoid latches, is if you register an entire record in a clocked process, you are really registering all of the components of the record. This takes one line of code, instead of possibly tens of lines. In the case where you have many elements which all need to be treated the same, a record can save you "silly mistakes", and possibly save you from creating a latch.
As stated by others, a record doesn't have any specific synthesis interpretation. It is simply a group of signals that you are grouping together for coding-convenience.

I don't see how this would help - a record (or even just parts of a record) can become a latch just as easily as a signal. A latch is generated if a signal keeps its state through some combinatorial process (i.e., is not assigned a value on ALL paths through the process). The same holds for constituents of a record.
Records can be useful to group related signals for readability, but synthesis-wise a record is pretty much equivalent to a bunch of individual signals.
My personal suggestion to avoid latches: avoid combinatorial processes. Make all processes clocked, and do combinatorial logic at the architecture level.

A record is just another way of grouping other types, similar to using an array
for grouping of a std_logic to std_logic_vector, so there is nothing
magical about records that make them better for avoiding latches in a design.
If you get unintended latches in your design, what I guess you think of as
"latch problems", it is because you coding style specifies latches, and you
should change the coding style, as #zennehoy also suggests.
One approach can be to define some code templates for different constructions
that you use, and then stick to these known and working templates.
The template for a flip-flop (FF) with asynchronous reset can be:
process (clk_i, rst_i) is
begin
-- Clock
if rising_edge(clk_i) then
... Control structures with Qs assign by function for Ds
... Synchronous reset is just another branch
end if;
-- Reset (asynchronous) if required
if rst_i = '1' then
... Qs assign with constant reset value for so or all Qs
end if;
end process;
Use concurrent signal assigns when possible, and more complex expressions can
be done through use of concurrent function call, where a function is used
outside a process like:
z_o <= fun(a_i, b_i);
If a process is used to create combinatorial logic, then a common pitfall and
cause for latches in VHDL is to forget a signal in the sensitivity list.
However, VHDL-2008 has a solution for this, since you can use (all) as
sensitivity list, whereby all signal used in the process are implicitly
included in the sensitivity list. So if you use VHDL-2008, then your template
for combinatorial processes can be:
process (all) is
begin
z_o <= a_i and b_i;
end process;
These template should be all you need for typical synthesizable design, and
these will keep your design latch free.

Related

VHDL block and guarded input - what does this code do?

I have the following from a beginner's VHDL tutorial:
rising_edge: block(clk’event and clk = ‘1’)
begin
result <= guarded input or force after 10ns;
end block rising_edge
The explanatory text is
"Essentially I have a block called rising_edge, and it's a block with a guard condition which does the following, it checks that we have an event on the clock, and that the clock is equal to one, so we're effectively looking for the so called rising_edge. We're looking for the event where the clock goes from 0 to 1, and if it does, then we can conditionally assign the results, so you'll see that the result variable here says that it is a guarded input or force after 10 ns might seem a bit confusing, but consider it without the guarded keyword. All we're doing is we're assigning the result of the evaluation of input or force, and we're doing it in a guarded setup. So, in this case, the assignment of the signal result is only executed if the guard signal is actually true, and in our example it means that the assignment of the expression, which is input or force, will only happen on the rising_edge of the clock because that's on guard condition."
Now I've read this over and over and searched on the net but have come up blanks as to what this is actually doing. Can someone please gently explain its purpose?
A block is essentially a grouping of concurrent statements. In terms of practical usage, it is very similar to a process, only it has a limited scope wich allows component-style signal mapping(with port and port map). It can be used to improve readability(see this question) and really not much else. Blocks are resonably rarely used and frequently not synthesis supported(see here). To my (limited) knowledge, the use of blocks has no other advantage than readability.
Because your block statement contains a guard condition(clk'event and clk='1' is the guard condition here), it is a guarded block. Inside a guarded block, signals that are declared guarded (like in your example) will only be assigned if the guard condition evaluates to true
The entire statement that has been guarded(i.e. in your case input or force after 10ns) will only be executed when the guard condition evaluates to true, i.e. on the rising edge of clk. Thus, for all intents and purposes this block has the same behaviour as
process(clk)
begin
if clk'event and clk = '1' then
result <= input or force after 10ns;
end if;
end process;
I will say though, this is a terrible example. For one thing, as others have stated, the usage of block is very rare and they are generally only used in quite advanced designs. The usage of clk'event and clk = '1' has been discouraged since 1993(see here). It should also be mentioned again that the usage of rising_edge as a label is a terrible idea, as is the use of force for a signal name(in VHDL 2008, force is a reserved keyword that can be used to force a signal to a value).
Working from the idea that this is supposed to be a beginners tutorial, and with the lack of any explanation as to why such an unusual style has been used, a much more conventional implementation would be:
process : (clk)
begin
if (rising_edge(clk)) then
result <= input or force after 10 ns;
end if;
end process;
A couple of points to note:
This assumes that input and force are either signals, or inputs to the entity.
It is unusual to model signal assignment delays if your code is going to be implemented in a real hardware device.
The code in your question uses after 10ns;, which is not valid; you need a space between the value and the units (as in my code).
The code in your question uses rising_edge as an identifier, when this is actually already defined as a function, assuming you are including standard IEEE libraries newer than I believe VHDL93.
The code in your question uses force as a signal name, when this is also a reserved language keyword since VHDL2008.
My advice to you is to find a different tutorial. The quote you posted is not clearly written, and the code you posted appears to be sending you down a strange path. All I can think is that the tutorial is in fact very, very old.

VHDL: Mealy machine and button press detection

Hi I'm a bit confused about the implementation of Mealy state machine using VHDL. My current work is like this:
process(clk, rst)
begin
if rst = '1' then
state <= s1;
elsif (clk'event and clk = '1') then
state <= next_state;
end if;
end process;
and another process like this:
process(state, op)
begin
case state is
when s1 =>
...some implementation
end process;
And now the problem is: I need to detect the press of the button from the user, but I'm not sure where to put it. Should it be inside the first process or the second process? Besides, I also looked through the following guide: implement state machine in FPGA, is it okay to use just one process for the Mealy machine as shown on the webpage? If it is so then I think the work will be easier. Thanks!
You should put it in the second process. The first process is only used to change states and the next_state is also calculated in the second.
There are several ways to write FSMs and people tend to favour one or the other for various reasons. Pick the one that works for you.
You cannot design a Mealy state machine with only one process. Even Moore state machines, in most cases, cannot be modelled with only one process.
A state machine always has a state register which must be modelled with a synchronous process. That is, a process which sensitivity list contains only the clock (and set or reset signals if they are asynchronous).
Every output of a synchronous process will synthesize as the output of a register because its value changes only on an edge of the clock (plus states of asynchronous set or reset if any). So, you cannot describe the outputs of a Mealy state machine in the same synchronous process as the state register. If you were doing so, it would not be a Mealy machine any more because its outputs would not combinationally depend on the inputs.
For Moore machines, things are a bit more subtle but, except in very exceptional cases, you also need at least two processes. When I write "process", I include processes short-hands like concurrent signal assignments, concurrent procedure calls or component/entity instantiations.
To make it simple: VHDL modelling for synthesis is straightforward if you have a clear view of the hardware you want.
Draw a block diagram of your hardware with registers and combinatorial parts clearly identified.
Draw bubbles enclosing hardware elements, one bubble per process, respecting the rule that if a bubble contains a register, all its outputs must be register outputs.
The synchronous processes are those enclosing registers. Their code is exactly:
process(clk)
begin
if rising_edge(clk) then
<your code>
end if;
end process;
Put your code in <your code>, never put code elsewhere. If you have asynchronous set or reset the code must be something like:
process(clk, reset)
begin
if reset = '1' then
<initialize outputs>
elsif rising_edge(clk) then
<your code>
end if;
end process;
The other processes are combinatorial processes. List all their entering signals (INPUTS) and output signals (OUTPUTS). The code must be:
process(INPUTS)
begin
<your code>
end process;
with the constraint that each OUTPUT signal must be assigned a value in every execution of the process. The best way to guarantee this is to start the process with a default assignment of all OUTPUTS.
That's all. Draw and code what you see. Bonus: every arrow crossing the border of one of your process-bubbles is a signal that you will have to declare unless it is already a primary input or output of your design.
Exercise: draw the block diagram of a Mealy state machine and understand why it cannot be modelled with one single process. Understand also why it can always be modelled with two processes, even if it is not necessarily desirable. Finally, try to identify the rare cases where a Moore state machine can be modelled with one process only.

What is the practical difference between implementing FOR-LOOP and FOR-GENERATE? When is it better to use one over the other?

Let's suppose I have to test different bits on an std_logic_vector. would it be better to implement one single process, that for-loops for each bit or to instantiate 'n' processes using for-generate on which each process tests one bit?
FOR-LOOP
my_process: process(clk, reset) begin
if rising_edge (clk) then
if reset = '1' then
--init stuff
else
for_loop: for i in 0 to n loop
test_array_bit(i);
end loop;
end if;
end if;
end process;
FOR-GENERATE
for_generate: for i in 0 to n generate begin
my_process: process(clk, reset) begin
if rising_edge (clk) then
if reset = '1' then
--init stuff
else
test_array_bit(i);
end if;
end if;
end process;
end generate;
What would be the impact on FPGA and ASIC implementations for this cases? What is easy for the CAD tools to deal with?
EDIT:
Just adding a response I gave to one helping guy, to make my question more clear:
For instance, when I ran a piece of code using for-loops on ISE, the synthesis summary gave me a fair result, taking a long while to compute everything. when I re-coded my design, this time using for-generate, and several processes, I used a bit more area, but the tool was able to compute everything way way faster and my timing result was better as well. So, does it imply on a rule, that is always better to use for-generates with a cost of extra area and lower complexity or is it one of the cases I have to verify every single implementation possibility?
Assuming relatively simple logic in the reset and test functions (for example, no interactions between adjacent bits) I would have expected both to generate the same logic.
Understand that since the entire for loop is executed in a single clock cycle, synthesis will unroll it and generate a separate instance of test_array_bit for each input bit. Therefore it is quite possible for synthesis tools to generate identical logic for both versions - at least in this simple example.
And on that basis, I would (marginally) prefer the for ... loop version because it localises the program logic, whereas the "generate" version globalises it, placing it outside the process boilerplate. If you find the loop version slightly easier to read, then you will agree at some level.
However it doesn't pay to be dogmatic about style, and your experiment illustrates this : the loop synthesises to inferior hardware. Synthesis tools are complex and imperfect pieces of software, like highly optimising compilers, and share many of the same issues. Sometimes they miss an "obvious" optimisation, and sometimes they make a complex optimisation that (e.g. in software) runs slower because its increased size trashed the cache.
So it's preferable to write in the cleanest style where you can, but with some flexibility for working around tool limitations and occasionally real tool defects.
Different versions of the tools remove (and occasionally introduce) such defects. You may find that ISE's "use new parser" option (for pre-Spartan-6 parts) or Vivado or Synplicity get this right where ISE's older parser doesn't. (For example, passing signals out of procedures, older ISE versions had serious bugs).
It might be instructive to modify the example and see if synthesis can "get it right" (produce the same hardware) for the simplest case, and re-introduce complexity until you find which construct fails.
If you discover something concrete this way, it's worth reporting here (by answering your own question). Xilinx used to encourage reporting such defects via its Webcase system; eventually they were even fixed! They seem to have stopped that, however, in the last year or two.
The first snippet would be equivalent to the following:
my_process: process(clk, reset) begin
if rising_edge (clk) then
if reset = '1' then
--init stuff
else
test_array_bit(0);
test_array_bit(1);
............
test_array_bit(n);
end if;
end if;
end process;
While the second one will generate n+1 processes for each i, together with the reset logic and everything (which might be a problem as that logic will attempt to drive the same signals from different processes).
In general, the for loops are sequential statements, containing sequential statements (i.e. each iteration is sequenced to be executed after the previous one). The for-generate loops are concurrent statements, containing concurrent statements, and this is how you can use it to make several instances of a component, for example.

Do all Flip Flops in a design need to be resettable (ASIC)?

I'm trying to understand clock-reset in a chip. In a design what criteria are used to decide whether a flop should be assigned to a value (typically to zero) during reset?
always_ff #(posedge clk or negedge reset) begin : process_w_reset
if(~reset) begin
flop1 <= '0;
....
end else begin
if (condition) begin
flop1 <= something ;
....
end
end
end
always_ff #(posedge clk) begin : process_wo_reset
if (condition) begin
flop1 <= something ;
....
end
end
Is it a bad practice to not to reset a flop which is used later as a control signal in a comb logic? What if the design makes sure that the flop will have a valid value (0 or 1) assigned to it before its used in a comb logic block (i.e. in a if statement or in FSM comb logic) ?
I feel like it's better to always reset all the flops in the design. In that way there won't be any Xs after reset in the chip. However, it seems like for datapath logic, resetting flop might need not be a big deal as it'll be just pipe stages. However if a flop is in control path (i.e. FSM next state comb logic) then it should be reset to a default value. Is my understanding correct? I don't know much about DFT and not sure if it has any other implication.
Assuming that reset means asynchronous reset, as in the code examples.
The answer is partly opinion based, since a design can be made to work with reset of a minimum number of the Flip-Flops (FFs) and all of the FFs.
I suggest that a minimum number of FFs are reset, and typically that leads to reset of most FFs in the control path, and no reset of FFs in the data path. The advantages of this approach are outlined below.
Simulation is often conservative with respect to propagation of uninitialized values, both for Verilog and VHDL, so it is like simulation can check both 0 and 1 values at once when the value is uninitialized.
Bugs due to FFs that are not reset, are therefore likely to show earlier in verification with simulation, and the designer thereby gets valuable feedback about wrong design assumptions, which may lead to corrections in the design that fixes other bugs. Just resetting all the FFs is likely to hide such bugs.
It may seem like design and verification is just easier if all FFs are reset, both in control and data path, since it fixes all those "annoying" X propagation in the design. But it requires an increased number of tests in order to verify all value combinations when X propagation is suppressed through reset.
Implementation gives a smaller load on the reset signal, so it is easier to meet timing of the reset net throughout the chip.
DFT (Design For Test) in general, then adding reset to the FFs will not aid DFT in finding nets stuck at reset value. With a DFT scan chain approach where all the FFs are loaded through the scan chain, then the lack of reset on some FFs will not require more vectors.
Generally you need to think about where the 'X's will propagate in your simulation and which ones matter and which ones are don't care conditions. For example, if you have a block of logic which doesn't start operating until an enable bit is set, so long as the enable bit itself is set and enough upstream logic is reset so reset values will propagate through to the enabled logic in time, you are most likely OK with not reseting the logic in between. However, you do want to reset any logic that feeds back into itself, (for example state machines) otherwise the upstream resets will never be able to establish a known state in the feedback block.
I agree with Morten Zilmer that you should only reset flops that require resetting, although my background is more FPGA than ASIC.
It's worth pointing out there is a gotcha in Verilog / SystemVerilog - if you have a clocked process that drives registers that are reset and registers that aren't you will end up inferring a clock enable or an additional mux on the input of your flip-flop.
This is usually not what was intended.
There is a more detailed explanation in this answer. I also wrote a blog post outlining a mechanism for abstracting away synchronous/asynchronous and active high/low reset.
As a general rule of thumb, you should probably always reset control signals.
For data flops, resetting can cost you area, so it really depends on whether you care about area.
In recent years simulators started to support X propagation modes that allow you to catch some of the X issues in RTL (instead of gate level simulation). It is a good practice to run these to make sure you don't have a reset problem with uninitialized sram or flops.

Best VHDL design practice

Question about best VHDL design practice.
When designing state machines, should I use a signal within the Architecture or use an variable. I have until now used variables, since they are "kinda" private to the process, and IMHO makes good sense because they should not be accesses outside the process. But is this good design practice?
type state_type is (s0,s1);
signal state : state_type := s0;
A : process(clk)
begin
if rising_edge(clk) then
case state is
.....
end case;
end if;
end process;
--This process uses a variable
B : process(clk)
type state_type is (s0,s1);
variable state : state_type := s0;
begin
if rising_edge(clk) then
case state is
.....
end case;
end if;
end process;
I prefer to use signals. The reason is that it allows the design to be split between multiple processes. One process can worry about how the state machine moves from state to state, and other processes can contain logic that is dependent on the state.
Doing it this way means you can have multiple simple processes that do one thing each. Using variables, everything has to go into the one process and that can become unwieldy.
It's a stylistic choice though.
I always use variables unless I need to communicate some value to another process. Because that's what signals are for.
Another potential benefit (or alternatively, something to watch as a violation of your coding standards!) of "localising the state variable" is that you can call the type and the variable state_type and state in two state machines in the same entity without them clashing...
For synthesis, I almost exclusively use signals.
Why?
Signals seem to be more universally understood.
Code clarity. Signals are all updated once, at the same time. Mixing variables and signals can be (potentially) confusing because you must remember that variable assignment takes effect immediately, whereas subsequent signal assignment implies priority. The value of a signal will never change during the same execution of a process.
Lower risk of deep logic paths. Inexperienced designers may be tempted to use variables like a C program, which would result in logic that will not meet timing goals.
Why Not?
Large designs end up with very long lists of signals and can be difficult to find the signal types/sizes/etc. Typically this only occurs for wrappers of the largest blocks in a design, and/or a design top level.
For testbench, I use variables and signals, depending on the use.
If the signal in this case it's not needed as an input or output of your process is a better use to use variables because when you're building the architecture you will need to assign a signal to the output of the module, and if it won't be used, it's not necessary to create the signal and spend more memory for something you won't use to connect to another module of your architecture.

Resources