During synthesis, should I care about the "found latch" warnings if I actually want the latches? - vhdl

say I have the following state machine:
....
if state_a then
output_a <= '0';
next_state <= state_b;
elsif state_b then
output_a < '0';
if cond then
output_b <= '1';
next_state <= state_a;
else
next_state <= state_b;
end if;
end if;
......
I don't want output_b to change except when being assigned again in state_b. However, when I try to synthesise this code, most synthesis tools will say something along this line:
warning: found 1-bit latch for signal "output_b". latches aren't
recommended for FPGA design because it might result in timing
problems.
Should I worry about this at all? If so, why and what are the alternatives?

Following Xilinx:
If latch inference is intended, you can safely ignore this message. However, some inefficient coding styles can lead to accidental latch inference. You should analyse your code to see if this result is intended.
Some techniques to avoid latch inference:
Make sure any "if / else if" statements have a concluding "else" clause,
Assign to all the same outputs in each case,
Include all possible cases in the case statement (but be aware that WHEN OTHERS clause always works, but can create extraneous logic).

if you have incomplete if/elsif or case statement in a clocked process, it's absolutely harmless.
if rising_edge(clk)
if a then
out <= b;
end if;
end if;
It means that you have flip-flop with some sort of feedback, or, like in this case, you have flip-flop with clock enable pin used, which is even better.
If you have incomplete if/elsif or case statement in not clocked process - it's a latch and it's in most cases:
something you don't really want;
something that point out on a poor design and can be avoided with redesign.
If you complete your little example, someone can help you redesign it. Now it is not enough information.

The problem you have stems from the FSM coding style you're (presumably) using. As other pointed it is not possible to guess what you want the code to do, since you did not provide enough code to figure that out, so I present one possible interpretation, assuming you really wanted to change output_a somehow and that one time (after reset) latching of output_b should happen at the same time FSM state transitions.
Using 2 processes per FSM style, we have code that is not giving latch warnings:
----
signal CLK, RESET, cond : std_logic;
type state_t is (a,b);
signal state, state_next : state_t;
signal ouput_a, output_b, output_b_next : std_logic;
----
FSM_clock: process(all)
begin
if rising_edge(CLK) then
if RESET then
state <= a;
output_b <= '0';
else
state <= state_next;
output_b <= output_b_next;
end if;
end if;
end process;
FSM_next: process(all)
begin
state_next <= state;
output_b_next <= output_b;
output_a <= '0';
case state is
when a =>
state_next <= b;
when b =>
output_a <= '1';
if cond then
output_b_next <= '1';
state_next <= a;
else
state_next <= b;
end if;
end case;
end process;

Related

Signal assignment method

I am new to VHDL and have had some difficulty in performing the assignment of two different values to the same signal inside a process. For example,
process(CLK)
if rising_edge(CLK) then
OUTPUT0 <= X(0);
OUTPUT1 <= X(1);
OUTPUT2 <= X(2);
LED0 <= VALUE;
OUTPUT0 <= Y(0);
OUTPUT1 <= Y(1);
OUTPUT2 <= Y(2);
LED1 <= VALUE;
end if;
end process;
Note that VALUE is an output dependent on the values assigned to OUTPUT0, OUTPUT1, OUTPUT2.
From what I understand in a process is that the last assignment to the same signal is always applied. What I am trying to do is apply two different sets of values to one set of inputs, map the output and it be done sequentially. I have tried separate processes tied to the same clock, a FSM to attempt to move sequentially and so on. At this point I have exhausted my knowledge of things to try.
My question is: What would be the best way to sequentially assign two values to one input and map its output in order?
EDIT:
As per Brian's suggestion on the state machine I had went ahead and implemented one again and found my error and fixed it. This gave the sequential assignment I was looking for.
I was reading 2 addresses from one instance of 32x1 distributed RAM which is the reason for a sequential assignment. Apologies for not providing the best example. Below is my final implementation:
RAM_READ_FSM : process(CLOCK) -- FSM to read the RAM addresses sequentially
begin
if rising_edge(CLOCK) then
case curr_state is
when S0 => if SW2 = '1' then
RAMADDR0 <= XYVEC(5); -- Y addresses
RAMADDR1 <= XYVEC(6);
RAMADDR2 <= XYVEC(7);
RAMADDR3 <= XYVEC(8);
RAMADDR4 <= XYVEC(9);
LED1 <= RAMOUT;
curr_state <= S1;
else
curr_state <= S0;
end if;
when S1 => if SW2 = '1' then
RAMADDR0 <= XYVEC(0); -- X addresses
RAMADDR1 <= XYVEC(1);
RAMADDR2 <= XYVEC(2);
RAMADDR3 <= XYVEC(3);
RAMADDR4 <= XYVEC(4);
LED2 <= RAMOUT;
curr_state <= S0;
else
curr_state <= S1;
end if;
end case;
end if;
end process;
The signals should be driven from the same process : multiple drivers would interfere with each other..
See Is process in VHDL reentrant? on signal assignment semantics.
now you can see there is need for some delay (even just 2 delta cycles, if the logic calculating VALUE is just a simple signal assignment) between the X and LED0 assignments.
You were on the right lines with a state machine but you didn't say anything about how it failed. Worth adding that to the Q to get a fuller answer.
Meanwhile there is a simple way to add delay :
like
LEDS : process is
begin
wait until rising_edge(CLK);
OUTPUT0 <= X(0);
OUTPUT1 <= X(1);
OUTPUT2 <= X(2);
wait until rising_edge(CLK);
LED0 <= VALUE;
wait until rising_edge(CLK);
OUTPUT0 <= Y(0);
-- etc
end process LEDS;

How would I do something like this without a synchronous error in vhdl?

How would I do something like this without a synchronous error in vhdl?
process (shift_button)
variable x : STD_LOGIC;
begin
x := '0';
if falling_edge(shift_button) then
x := '1';
end if;
shift_button_let_go <= x;
end process;
I would first read the Xilinx support article about the error you're encountering:
http://www.xilinx.com/support/answers/14047.html
It basically states there is a certain template that XST expects when making synchronous design elements (note that falling_edge() will use the VHDL 'event attribute). I'm guessing that XST doesn't like how you are defining your clear of shift_button_let_go on the rising edge of shift_button.
You mentioned you want shift_button_let_go to go high for one clock cycle after shift_button goes low. If this is the case then you would want to use your clock in the process' sensitivity list instead of shift_button.
process (clk)
begin
if rising_edge(clk) then
shift_button_d <= shift_button;
if (shift_button_d = '1' and shift_button = '0') then -- Falling edge detect
shift_button_let_go <= '1';
else
shift_button_let_go <= '0';
end if;
end process;
NOTE This logic can suffer from meta stability issues if shift_button is not synchronous to clk and is not held stable for several clk cycles.

Strange spikes in the signal ModelSim VHDL

I'm working on a final project for school and this is my first time working with VHDL in Quartus and ModelSIM. It's supposed to be a control for an elevator that services three floors. I have these strange spikes in a few signals, and I can't seem to find their source.
The one problem I have is a spike in a signal that feeds to an up/down counter that shows the current floor. When it stops at a floor, it ends up counting one additional time and going either one floor too high or one floor too low, while the next floor display seems to show the same floor just fine until another floor is called. The next floor display comes from an FSM, while the current floor display is from an up/down counter.
It's a bit complex to post everything here, so I'm just going to post the waveform for now in case someone's come across this signal spike thing and it ends up being a minor error/easy fix.!
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
entity FSM_Elevador is
port (Up_Down, Igual, Reset, Clock: in std_logic;
Andar_Dif: out std_logic
);
end FSM_Elevador;
architecture FSM_beh of FSM_Elevador is
type Elev_States is (Start, Wait_State, Pulse_State);
signal Current_State, Next_State: Elev_States;
signal RST, CLK, Sig_Andar_Dif, Cont_Mesmo_Andar: std_logic;
begin
RST <= Reset;
CLK <= Clock;
process(RST, CLK)
begin
if RST = '0' then
Current_State <= Start;
elsif CLK'event and CLK = '1' then
Current_State <= Next_State;
end if;
end process;
process(Current_State, Igual)
begin
case Current_State is
when Start =>
Next_State <= Wait_State;
when Wait_State =>
if Igual = '1' then
Next_State <= Wait_State;
Sig_Andar_Dif <= '0';
else
Next_State <= Pulse_State;
Sig_Andar_Dif <= '1';
end if;
when Pulse_State =>
if Igual = '1' then
Sig_Andar_Dif <= '0';
Next_State <= Wait_State;
else
Sig_Andar_Dif <= '0';
Next_State <= Pulse_State;
end if;
end case;
end process;
Andar_Dif <= Sig_Andar_Dif;
end FSM_beh;
fru1tbat: I use the Elev_pulse to make the counter go up or down once, and yes it enters the counter as a clock. It was suggested by the professor.
Edit: sorry that was the wrong code earlier. Andar_Dif is what sends out the signal that ends up going to the component that has Elev_Pulse
Get rid of the reassignment of Clock and Reset to CLK and RST and just use the signals from the port directly. That is creating a delta cycle delay which is the cause of these kind of spikes. It looks like you have resets with different delays in the design which can also complicate matters. If the removal of the indirection doesn't clear things up you need to scrutinize the ordering of when events are generated on signals and when they are processed.
The outputs from your state machine are unregistered which is also potentially involved. Consider reworking the FSM so that all outputs are registered. This is a better design practice in general as it ensures that you don't have unknown combinational delays affecting downstream logic.

VHDL synthesis of registers - separate process for each register vs. one merged process

Let's say I have two registers named reg_operand1 and reg_operand2. For both of them I have an appropriate write-enable signal. Somewhere I read I should have separate process for each register assignment, something like this:
process(CLK, RESET)
begin
if (RESET = '1') then
reg_operand1 <= (others => '0');
elsif (CLK'event and CLK = '1') then
if reg_operand1_we='1' then
reg_operand1 <= DI;
end if;
end if;
end process;
process(CLK, RESET)
begin
if (RESET = '1') then
reg_operand2 <= (others => '0');
elsif (CLK'event and CLK = '1') then
if reg_operand2_we='1' then
reg_operand2 <= DI;
end if;
end if;
end process;
But what happen if I merge the processes into this? Will the synthesized circuit be different? Also, what if I put "elsif" between the if-statements in merged process? Will the synthesizer insert a multiplexor into the circuit? Thanks!
process(CLK, RESET)
begin
if (RESET = '1') then
reg_operand1 <= (others => '0');
reg_operand2 <= (others => '0');
elsif (CLK'event and CLK = '1') then
if reg_operand1_we='1' then
reg_operand1 <= DI;
end if;
if reg_operand2_we='1' then
reg_operand2 <= DI;
end if;
end if;
end process;
The second one will produce exactly the same hardware as the first, and as already been said, contains less boilerplate.
If I understand your question about elsif correctly, you're proposing:
process(CLK, RESET)
begin
if (RESET = '1') then
reg_operand1 <= (others => '0');
reg_operand2 <= (others => '0');
elsif (CLK'event and CLK = '1') then
if reg_operand1_we='1' then
reg_operand1 <= DI;
elsif reg_operand2_we='1' then
reg_operand2 <= DI;
end if;
end if;
end process;
This generates different hardware, and also gives different behaviour.
In the example without the elsif, reg_operand2 is assigned DI when reg_operand2_we is high, irrespective of the state of reg_operand1_we.
When elsif is used, the assignment to of reg_operand2 only occurs when reg_operand2_we is high and reg_operand1_we is low
In general, if the two assignments do not depend on each other, use a seperate if construct.
The second one is shorter and simpler, and will generate the same hardware. (from a brief inspection : i.e. assuming there are no accidental typos in one or the other)
An elsif in the second version, combining the two register writes, will just prioritise the registers; i.e. if you attempt to write to both registers by asserting both we signals in the same cycle, only reg_operand1 will actually be written. It will have no other effect on the design.
So...
Unless you have specific corporate style guides that prohibit it, use the second style as a general rule.
There may be a FEW cases where you want to COMPLETELY separate some functionality to make it clear that it IS separate; in that case it's better not to be dogmatic about this style; but USUALLY fewer lines of code means less to go wrong, especially where (as here) it's easier to read and understand.
"I read somewhere" ... it would be worth knowing where you read this. There are a LOT of excruciatingly bad books, teaching materials and example projects out there, waiting to ruin potential VHDL programmers, and it's worth publicising which ones to avoid...

VHDL driving signal from different processes

I have a little problem with following VHDL code:
process (zbroji)
begin
if rising_edge(zbroji) then
oduzima <= '0';
ucitanPrvi <= '1';
broj1 <= ulaz_broj;
end if;
end process;
process (oduzmi)
begin
if rising_edge(oduzmi) then
oduzima <= '1';
ucitanPrvi <= '1';
broj1 <= ulaz_broj;
end if;
end process;
The problem is that signal ucitanPrvi always has value X. If I don't try to set it's value in two processes, then I don't have any problems ... So I know that I mustn't drive one signal from multiple processes, but I don't know how to write this differently ...
Does anyone have an idea how I could resolve this problem ?
Thanks !
EDIT: Thank you all guys for replying :) Now I understand why I can't drive one signal from multiple processes (at least in the way I wanted it to work).
If you want to synthesize your design for a real FPGA or ASIC, you are going to have to think of VHDL in terms of real hardware (wires, flip flops, gates, etc.). Also, if you want to perform a real rising edge detect in hardware, you will need a system clock that drives a flip flop. Given your original code sample, it doesn't seem that zbroji or oduzmi are system clocks, but just std_logic signals. I wrote this code example assuming basic functionality from your example, hopefully, you can take my code and comments and accomplish what you need.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity example is
port (Reset : in std_logic;
SysClk : in std_logic;
zbroji : in std_logic;
oduzmi : in std_logic;
ulaz_broj : in std_logic;
oduzima : out std_logic;
ucitanPrvi : out std_logic;
broj1 : out std_logic
);
end example;
architecture Behavioral of example is
-- Delayed version of input signals (1 clock cycle delay)
signal zbroji_d : std_logic;
signal oduzmi_d : std_logic;
signal zbrojiRE : std_logic;
signal oduzmiRE : std_logic;
begin
-- Generate 1 clock cycle delayed version of
-- signals we want to detect the rising edge
-- Assumes active high reset
-- Note: You should only use the rising_edge macro
-- on an actual global or regional clock signal. FPGA's and
-- ASICs place timing constraints on defined clock signals
-- that make it possible to use rising_edge, otherwise, we have
-- to generate our own rising edge signals by comparing delayed
-- versions of a signal with the current signal.
-- Also, with any respectable synthesizer / simulator using
-- rising_edge is almos exactly the same as (clk'event and clk='1')
-- except rising_edge only returns a '1' when the clock makes a
-- valid '0' to '1' transition. (see link below)
EdgeDetectProc : process (Reset, SysClk)
begin
if Reset = '1' then
zbroji_d <= '0';
oduzmi_d <= '0';
elsif rising_edge(SysClk) then
zbroji_d <= zbroji;
oduzmi_d <= oduzmi;
end if;
end process EdgeDetectProc;
-- Assert risinge edge signals for one clock cycle
zbrojiRE <= '1' when zbroji = '1' and zbroji_d = '0' else '0';
oduzmiRE <= '1' when oduzmi = '1' and oduzmi_d = '0' else '0';
-- Assumes that you want a single cycle pulse on ucitanPrvi on the
-- rising edege of zbroji or oduzmi;
ucitanPrvi <= zbrojiRE or oduzmiRE;
-- Based on your example, I can't tell what you want to do with the
-- broj1 signal, but this logic will drive broj1 with ulaz_broj on
-- either the zbroji or oduzmi rising edge, otherwise '0'.
broj1 <= ulaz_broj when zbrojiRE = '1' else
ulaz_broj when oduzmiRE = '1' else
'0';
-- Finally, it looks like you want to clear oduzima on the rising
-- edge of zbroji and assert oduzima on the rising edge of
-- oduzmi
LatchProc : process (Reset, SysClk)
begin
if Reset = '1' then
oduzima <= '0';
elsif rising_edge(SysClk) then
if zbrojiRE = '1' then
oduzima <= '0';
elsif oduzmiRE = '1' then
oduzima <= '1';
end if;
end if;
end process LatchProc;
end Behavioral;
The previous code assumes you have a system clock. In a simulator like ModelSim (free student edition), you can generate a 100 MHz clock with non-synthesizable testbench code like this...
ClockProc : process
begin
SysClk <= '0';
wait for 5 ns;
SysClk <= '1';
wait for 5 ns;
end process ClockProc;
In an actual FPGA/ASIC implementation, you will probably want to use an external oscillator that you run into your chip, drive the signal into a DCM (Digital clock manager), which will output a very clean clock signal to all of your VHDL logic, so you can have a glitch free design.
And finally, here is a great explanation on the differences between rising_edge and
(clk'event and clk='1')
http://vhdlguru.blogspot.com/2010/04/difference-between-risingedgeclk-and.html
Hope that helps.
If you drive a std_logic signal from more than one process (and remember that a continuous assignment outside of a process also creates an implied process!) then all but one of them must be driving Z onto the signal. To a first approximation, the resolution function (that decides what the final value should be) will produce Xs unless this happens.
I'm not sure how best to change your code - you need to decide when a particular process should not drive the signal and have it drive a Z at that point.
The full definition of how the multiple drivers are resolved is defined in the ieee.std_logic_1164 package and covers all possibilities, such as a 1 and an L driving etc. The IEEE get shirty about copyright, so I'm not going to post even an excerpt here, but you'll be able to find it in the source libraries of your simulator.
Driving signals from multiple processes is a bad idea unless you really know what you're doing. You can re-write this code in a single process like this.
process (zbroji, oduzmi)
begin
if rising_edge(zbroji) then
oduzima <= '0';
ucitanPrvi <= '1';
broj1 <= ulaz_broj;
end if;
if rising_edge(oduzmi) then
oduzima <= '1';
ucitanPrvi <= '1';
broj1 <= ulaz_broj;
end if;
end process;
Note that if you do this, and you get a rising edge on both zbroji & oduzmi then oduzima will get the value 1 as it happens last in the process. Before you'd have been trying to set it to 0 and 1 at the same time. That would simulate to X, and probably wouldn't synthesize. If it did synthesize you'd be connecting power and ground together in a CMOS design.
An alternative method is to have each process drive it's own version of the signal, and then resolve them externally with what ever function you like (or another process). In this case I used or:
process (zbroji)
begin
if rising_edge(zbroji) then
ucitanPrvi_1 <= '1';
end if;
end process;
process (oduzmi)
begin
if rising_edge(oduzmi) then
ucitanPrvi_2 <= '1';
end if;
end process;
ucitanPrvi <= ucitanPrvi_1 or ucitanPrvi_2;
Unless zbroji and oduzmi are seperate clocks this is my recommended implementation
This registers the zbroji and oduzmi and checks if the value in the register is the opposite of the original signal. This should only occur when zbroji/oduzmi go from 0 to 1 and the register has not yet updated the change in signal.
process (clk)
begin
if rising_edge(clk) then
if zbroji = '1' and zbroji_old = '0' then
oduzima <= '0';
ucitanPrvi <= '1';
broj1 <= ulaz_broj;
elif oduzmi = '1' and oduzmi_old = '0' then
oduzima <= '1';
ucitanPrvi <= '1';
broj1 <= ulaz_broj;
end if;
zbroji_old <= zbroji;
oduzmi_old <= oduzmi;
end if;
end process;
Also it appears that ucitanPrvi and broj1 are always the same thing. Either the signals are useless, this was orignally a typo or you are creating "update" pulses in which case you need the statement
ucitanPrvi <= '0'
broj1 <= (others=>'0') -- assumed reset?
following the if(rising_edge(clk) statement
When you're changing same signal value from multiple process, the simulator will be creating multiple signal drivers for this. The output of them will essentially will be unresolved. Think of it as the output of multiple gates connected together, what do you expect?
To overcome this, what you need to implement is, a resolution function, that drivers the output to signal.
http://www.csee.umbc.edu/portal/help/VHDL/misc.html#resf
If you have any doubts, let me know.

Resources