VHDL - Inferred Latch With Reset - FSM - vhdl

I have an issue with this process where if I include a reset statement, I get an inferred latch. However, if I do not include the reset statement, I do not get an inferred latch on duty_cycle_triangle.
SIGNAL duty_cycle_triangle : INTEGER := 0;
SIGNAL count_up : STD_LOGIC;
SIGNAL tick_zero : STD_LOGIC;
triangle_count: PROCESS(clk, reset signal, tick_zero)
BEGIN
IF (reset = '1') THEN
duty_cycle_triangle <= 0;
ELSIF (RISING_EDGE(clk)) THEN
IF (tick_zero = '1') THEN
IF (count_up = '1') THEN
duty_cycle_triangle <= duty_cycle_triangle + 2;
ELSE
duty_cycle_triangle <= duty_cycle_triangle - 2;
END IF;
END IF;
END IF;
END PROCESS;
I am trying to design an FSM that will output a triangle wave using a PWM and an FSM shown below:
FSM_comb: PROCESS(currentState, duty_cycle_triangle)
BEGIN
CASE currentState IS
WHEN triangle_up =>
PWM_enable <= '1';
count_up <= '1';
IF (duty_cycle_triangle > 99) THEN
nextState <= triangle_down;
ELSE
nextState <= triangle_up;
END IF;
WHEN triangle_down =>
PWM_enable <= '1';
count_up <= '0';
IF (duty_cycle_triangle < 1) THEN
nextState <= triangle_up;
ELSE
nextState <= triangle_down;
END IF;
END CASE;
END PROCESS;
FSM_seq: PROCESS(clk, reset)
BEGIN
IF (reset = '1') THEN
currentState <= triangle_up;
ELSIF (RISING_EDGE(clk)) THEN
currentState <= nextState;
END IF;
END PROCESS FSM_seq;
Basically, after every "tick" I want the duty cycle of the triangle wave to increase by 2. After the duty cycle reaches 100, I want the duty cycle to decrease by 2 until the duty cycle reaches 0. Once the duty cycle reaches 0, I want the duty cycle to start increasing from 0 again until it reaches 100 and it starts over.
Does anyone see any problems with my code or can anyone point me in the right direction to correcting any issues?

If you want to create a sequential process, only include a reset and a clock in your sensitivity list. I suspect that it's inferring the latch because you're including too many signals in this process:
triangle_count: PROCESS(clk, reset signal, tick_zero)
It should just be
triangle_count: PROCESS(reset, clk)
The tools don't see that as a sequential process and make it combinational and that's how you get your latch.

Without trying it out i'm wondering if when the reset statement is removed, the tool is recognising the process as a synchronous process and inferring registers. In this case you don't need to explicitly define duty_cycle_triangle for each outcome of the process as the value is stored in a register.
With the reset statement included it may be treating the process as combinatorial and therefore inferring latches to store the state of duty_cycle_triangle when it's not explicitly defined.
Either way I agree with Russell's suggestion of changing the process sensitivity list which should get rid of the latch.

Related

Switch on LED after receiving Ethernet packets

I'm a novice in VHDL programming and currently try to execute a program where the LED on the FPGA board should switch on after transmitting every 10 Ethernet packets which I generate from a Linux server. The code I've written is in the following which doesn't work properly. I'm trying to figure out the problem but still undone. Any help would be much appreciated.
---------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
---------------------------------------------
entity notification is
port (clk, reset, qdv: in std_logic;
LED: out std_logic
);
end notification;
architecture behavior of notification is
signal qdv_a: std_logic;
signal qdv_b: std_logic;
signal packet_count: std_logic_vector (3 downto 0);
begin
no_1: process(clk, reset)
begin
if (reset = '1') then
qdv_a <= '0';
elsif rising_edge (clk) then
qdv_a <= qdv;
end if;
end process no_1;
qdv_b <= qdv and (not qdv_a);
no_2: process(clk, reset)
begin
if (reset = '1') then
packet_count <= "0000";
elsif rising_edge (clk) then
if qdv_b = '1' then
if packet_count < "1010" then
packet_count <= packet_count + 1;
LED <= '0';
else
LED <= '1';
packet_count <= (others => '0');
end if;
end if;
end if;
end process no_2;
end behavior;
I am making assumptions based on your code:
1) You are trying to increment packet_count every time you see a rising edge on qdv,
2) The pulse width of qdv is longer than a period of the 25MHz clock (clk_25MHz) - 40ns and
3) You want an asynchronous reset. (Trying to decide which is better - a synchronous or asynchronous reset - is like trying to decide which is a better - a Mac or a PC.)
So,
If (1) and (2) are true, you need a synchronous edge detector:
signal qdv_d : std_logic;
signal qdv_r : std_logic;
...
process (clk_25MHz, reset)
begin
if reset = '1' then
qdv_d <= '0';
elsif rising_edge (clk_25MHz) then
qdv_d <= qdv;
end if;
end process;
qdv_r <= qdv and not qdv_d;
Please draw this out as a schematic so that you can see how it works.
Then, assuming (3), you need to sort out your main process. If you're coding sequential logic, you should stick to a template. Here is the template for sequential logic with an asynchronous reset, which all synthesis tools should understand:
process(clock, async_reset) -- nothing else should go in the sensitivity list
begin
-- never put anything here
if async_reset ='1' then -- or '0' for an active low reset
-- set/reset the flip-flops here
-- ie drive the signals to their initial values
elsif rising_edge(clock) then -- or falling_edge(clock)
-- put the synchronous stuff here
-- ie the stuff that happens on the rising or falling edge of the clock
end if;
-- never put anything here
end process;
Only clock and reset go in the sensitivity list, because the outputs of the sequential process (though they depend on all the inputs) only change when clock and/or reset change. On a real D-type flip-flop, reset takes priority over clock, so we test that first and do the resetting should reset be asserted. If there is a change on clock (when reset is not asserted) and that change is a rising edge, then do all the stuff that should happen on the rising edge of a clock (stuff that will get synthesised to combinational logic driving the D inputs of the flip-flops).
So, using that template, here is how I would write your main process:
process(clk_25MHz, reset)
begin
if reset = '1' then
packet_count <= "0000";
elsif rising_edge (clk_25MHz) then
if qdv_r = '1' then
if packet_count < "1010" then
packet_count <= packet_count + 1;
LED <= '0';
else
LED <= '1';
packet_count <= (others => '0');
end if;
end if;
end if;
end process;
Now we have a synchronous process which increments packet_count and drives the LED output. (What is q bringing to the party?)
Please
bear in mind that I haven't simulated any of this
don't just type it in without trying to understand how it works

Is the use of rising_edge on non-clock signal bad practice? Are there alternatives?

I am working on a VHDL design and I have it working, but the code is pretty ugly and the fact that it seems that I am trying to work around the language's design to accomplish my goal makes me feel like something is wrong. I'm pretty new to VHDL, but I have been working on smaller chunks of the project for nearly a month so I have the general idea. However, This part is a bit more complex.
I need a process that will create a one clock period long pulse (LOAD_PULSE) after the rising edge of a signal (END_ADC), but not until 4 clocks has passed from the latest rising edge of that signal (END_ADC) OR the falling edge of a second signal (LVAL).
To accomplish the wait period, I have built a timer module that counts microseconds and periods, here:
entity uS_generator is
generic(
Frequency : integer := 66 -- Frequency in MHz
);
Port (
CLK : in STD_LOGIC;
RESET : in STD_LOGIC;
T_CNT : out integer range Frequency downto 1 := 1;
uS_CNT : out integer range 65535 downto 0 := 0
);
end uS_generator;
architecture behavior of uS_generator is
signal T_CNT_INT : integer range Frequency downto 1 := 1; -- Counter for 1 uS
signal uS_CNT_INT : integer range 65535 downto 0 := 0;
begin
COUNT: process(CLK, RESET)
begin
if RESET = '1' then
T_CNT_INT <= 1;
uS_CNT_INT <= 0;
elsif rising_edge(CLK) then
if T_CNT_INT = (Frequency - 1) then -- Increment one clock early so last rising edge sees one uS elapsed.
uS_CNT_INT <= uS_CNT_INT + 1;
T_CNT_INT <= T_CNT_INT + 1;
if uS_CNT_INT = 65535 then
uS_CNT_INT <= 0;
end if;
elsif T_CNT_INT = Frequency then
T_CNT_INT <= 1;
else
T_CNT_INT <= T_CNT_INT + 1;
end if;
end if;
end process COUNT;
T_CNT <= T_CNT_INT;
uS_CNT <= uS_CNT_INT;
end behavior;
The processes I'm using for the pulse generation portion of the design are as follows:
loadPulseProc: process(PIXEL_CLK, END_ADC, RESET)
begin
if RESET = '1' then
PULSE_FLAG <= '0';
LOAD_PULSE <= '0';
elsif rising_edge(END_ADC) then
PULSE_FLAG <= '1';
end if;
if rising_edge(PIXEL_CLK) then
if PULSE_FLAG = '1' and END_ADC = '1' and LVAL <= '0' and ADC_TMR_T >= 4 and LVAL_TMR_T >= 4 then
LOAD_PULSE <= '1', '0' after PIXEL_CLK_T;
PULSE_FLAG <= '0';
end if;
end if;
end process loadPulseProc;
ADCTimerProc: process(END_ADC, RESET)
begin
if RESET = '1' then
ADC_TMR_RST <= '1', '0' after PIXEL_CLK_T/10;
end if;
if rising_edge(END_ADC) then
ADC_TMR_RST <= '1', '0' after PIXEL_CLK_T/10;
end if;
if falling_edge(END_ADC) then
ADC_TMR_RST <= '1', '0' after PIXEL_CLK_T/10;
end if;
end process ADCTimerProc;
LVALTimerProc: process(LVAL, RESET)
begin
if RESET = '1' then
LVAL_TMR_RST <= '1', '0' after PIXEL_CLK_T/10;
end if;
if rising_edge(LVAL) then
LVAL_TMR_RST <= '1', '0' after PIXEL_CLK_T/10;
end if;
if falling_edge(LVAL) then
LVAL_TMR_RST <= '1', '0' after PIXEL_CLK_T/10;
end if;
end process LVALTimerProc;
PIXEL_CLK_T is the period of the clock, 15.152 ns.
This design works, simulation shows that it does as I require, but only after significant hassle avoiding errors due to using multiple rising_edge of falling_edge calls by separating them into separate if statements that really should be together. As far as I've read using rising_edge and falling_edge seems to be reserved for clocks only, so is this just bad practice? How can avoid this behavior but still create the same output?
Thanks!
Yes, rising_edge()/falling_edge() should only be used for clock signal. While it works in simulation it can cause problems and unintended hardware in synthesis.
Synthesis tools infer a clock from the function's argument and place such signals/wires on special tracks in the FPGAs (assuming you are targeting an FPGA for your design). The tool will further infer special clock buffers and warn if your input clock pin is not a clock capable pin.
Introducing several clocks can lead to asynchronous designs and make it vulnerable for cross clock faults.
Detecting a rising or falling edge on a signal is done by an edge detection circuit like the following which compares the signal in the previous clock cycle to the current value.
Needed signals:
signal mySignal_d : std_logic := '0';
signal mySignal_re : std_logic;
Needed logic:
mySignal_d <= mySignal when rising_edge(Clock);
mySignal_re <= not mySignal_d and mySignal;
This first line translates to an 1-bit D-flipflop (You could also use a process). The second lines generates a one cycle strobe signal when mySignal changes from low to high. I'm using *_d to indicate a delayed signal of the original input and *_re for rising edge.
The generated signal is still synchronous to Clock.

How can I generate a "tick" inside a process in VHDL?

I am writing a specified UART component in VHDL.
send: process(send_start)
variable bit_index : integer range 0 to 2 := 0;
begin
if (falling_edge(send_start)) then
if (start = '0' and transceiver_start = '1') then
bit_index := 0;
end if;
transceiver_start <= '1';
if (bit_index = 0) then
temp_data <= data.RE;
bit_index := 1;
transceiver_start <= '0';
delay_counter <= 0;
elsif (bit_index = 1) then
temp_data <= data.IM;
bit_index := 2;
transceiver_start <= '0';
end if;
end if;
end process;
The falling edge of the transceiver_start signal triggers the sub-component to run. I wanted to trigger it twice, but I do not know how to generate a second falling edge.
I thought about using a concurrent process, which would basically reset the transceiver_start signal to it's hi-state after delay_counter reaches some limit. Therefore I could bring it down inside the send process again to generate a falling edge. However, this makes me have two driving processes for the delay_counter signal, and I read that having resolution functions is not a good practice for synthesis (this code needs to be synthesizable.)
Is there any way for me to generate that falling edge when bit_index = 1?
FPGA devices and related synthesis tools are optimized for synchronous logic,
thus VHDL where a clock triggers process execution. Using a specific signal to
trigger process execution, as in the question code, is thus not in line with
the indented FPGA and VHDL design methodology.
Instead, use an internal clock to trigger process execution, usually the rising
edge of the clock. Actual update inside the process can then be conditional on
detection of change to a control signal, which can be send_start.
process (clock) is
begin
if rising_edge(clock) then
send_start_prev <= send_start; -- Previous for edge detection
if ((send_start = '0') and (send_start_prev = '1')) then -- Falling edge of send_start
... -- More code
end if;
end if;
end process;
For rerunning of conditional process code, for example based on bit_index = 1, the process contents can be updated like:
send_start_prev <= send_start; -- Previous for edge detection
rerun_request <= '0'; -- Default no rerun
if ((send_start = '0') and (send_start_prev = '1')) or -- Falling edge of send_start
(rerun_request = '1') then -- Rerun request
if bit_index = 1 then
rerun_request <= '1';
end if;
... -- More code
end if;

Handling Interrupt in VHDL

We are using OR1200 for our project and we would like to assign an interrupt to the 8th button of FPGA Board. Here is the code to generate interrupt:
inrpt: process(CLK_I, RST_I)
begin
if RST_I = '1' then
butt_int_pul <= '0';
butt_int_tmp <= '0';
elsif rising_edge(CLK_I) then
if(DATA_I(8) = '1' and butt_int_tmp = '0') then
butt_int_pul <= '1';
else
butt_int_pul <= '0';
end if;
butt_int_tmp <= DATA_I(8);
end if;
end process inrpt;
process(CLK_I, RST_I)
begin
if RST_I = '1' then
butt_int <= '0';
elsif butt_int_pul = '1' then
butt_int <= '1';
elsif clear_int = '1' then
butt_int <= '0';
end if;
end process;
We only want this interrupt to be handled only once (holding the button should not call the interrupt again), that's why we included a flag to check this (butt_int_tmp).
The problem is that the interrupt call is not stable. It does not call each time we press the button. When we remove the flag, it works, but in this case, it is handled as many as we hold the button.
What are we doing wrong?
To start with, that second process is not properly written. It should have a structure equivalent to the first process (i.e., if(rising_edge(CLK_I)) surrounding all but the reset logic). You are currently describing a latch with multiple enable signals and wrong sensitivity list.
Moving on, there's no real reason you need that second process at all. You just need one register to act as interrupt (butt_int), and one to keep track of the previous state of the button (butt_prev). The interrupt is triggered for one cycle when DATA_I(8) is '1' while butt_prev is '0' (i.e., the button changed from not-pressed to pressed).
process(CLK_I, RST_I) begin
if(RST_I='1') then
butt_prev <= '0';
butt_int <= '0';
elsif(rising_edge(CLK_I)) then
if(DATA_I(8)='1' and butt_prev='0') then
butt_int <= '1';
else
butt_int <= '0';
end if;
butt_prev <= DATA_I(8);
end if;
end process;
Note that this will only work if your button is properly debounced, otherwise you are likely to get multiple interrupts triggered when you press (or even release) the button.
Its best not to think about interrupts. As you're targetting an FPGA, you're describing digital logic, not a software processor.
There a numerous way to build a circuit with the behaviour you want.
The simplest is probably a re-timed latch
signal latched_button : std_logic;
signal meta_chain : std_logic_vector(2 downto 0);
p_async_latch: process(rst_i,data(8))
begin
if rst_i = '1' then
latched_button <= '0';
elsif data(8) = '1' then
latched_button <= '1';
end if;
end process;
p_meta_chain: process(rst_i,clk_i)
begin
if rst_i = '1' then
meta_chain <= (others => '0');
elsif rising_edge(clk_i) then
meta_chain <= meta_chain(1 downto 0) & latched_button;
end if;
end process;
button_int <= '1' when meta_chain(2 downto 1) = "01" else '0';
This causes the button press to be latched asynchronously. The latched signal is then clocked along a shift register, and the interrupt is only valid for one cycle, which is the first clock cycle that the latch is seen on the clock domain.

Communication between processes in VHDL

I have problems on communicating between the processes. I used to use flag and clearFlag to tackle this, but it's kind of annoying and not looking good. What is the best practice to handle this? Here is a sample code on how I did it before:
Proc_A : process (clk, reset, clrFlag)
begin
if clrFlag = '1' then
flag <='0';
elsif reset = '0' then
A <= (others => '0');
elsif rising_edge (clk) then
A <= in;
flag <= '1';
end if;
end process;
Proc_B : process (clk, reset)
begin
if reset = '0' then
B <= (others => '0');
elsif rising_edge (clk) then
if flag = '1' then
B <= data;
clrFlag <= '1';
else
clrFlag <= '0';
end if;
end if;
end process;
This way works but I don't think it is nice method. I have to write a flag and clrFlag couple to do this task. All I want to do is when something happened (e.g. A <= in;), it triggers another proc, Proc_B for example, to run once or a number of times. What is the best practice to this problem? Thanks!
For simulation, you can make a process wait on a signal:
Proc_B : process
begin
wait until flag'event;
B <= data;
end process;
and just write the flag with its inverse every time you need something to happen.
In synthesisable logic, you either have to exchange flag signals, as you do, or use some other higher-level communication (like a FIFO, messagebox, or similar).
However, if all your proc_b logic takes place in a single cycle - so you can guarantee not to miss a flag, and to be able to keep up even if flag is asserted all the time (as it looks like you do) - you can do this (and combine the two processes):
Proc : process (clk, reset, clrFlag)
begin
flag <='0';
if reset = '0' then
A <= (others => '0');
B <= (others => '0');
elsif rising_edge (clk) then
if some_trigger_event = '1' then
A <= in;
flag <= '1';
end if;
-- recall that due to VHDL's scheduling rules, this "if" will take place
-- one clock cycle after the flag is written to, just as if it were in a
-- separate process
if flag = '1' then
B <= data;
end if;
end if;
end process;
Side note - your code is not ideal for synthesis... you really only want the reset part outside the clocked part:
Proc_A : process (clk, reset)
begin
if reset = '0' then
A <= (others => '0');
elsif rising_edge (clk) then
if clrFlag = '1' then
flag <='0';
else
A <= in;
flag <= '1';
end if;
end process;

Resources