Sunday, November 06, 2016

Why one should use asynchronous resets in a digital design (in FPGAs) - Part 2

I studied the reset matter a bit more.
This time the following questions are answered:

1. What happens if the reset signal is omitted from the sensitivity list in a process with an asynchronous reset?
2. What happens if the flip-flop (FF) is not reset in the asynchronous reset assignment?

The answer to question 1 is pretty simple, at least when using Altera Quartus II.
The example code looks like this:

  async_reset : process (Clk)
  begin
    if (Rst = '1') then
      FF_Q <= '0';
    elsif (rising_edge(Clk)) then
      FF_Q <= FF_D;
    end if;
  end process;

Compiling this will inform you that you've been a naughty boy forgetting the reset signal in the sensitivity list and proceeds to add the reset signal for you.
The generated logic is identical to the one where the reset signal is in the sensitivity list:



The result of question 2 is more interesting:
2. What happens if the flip-flop (FF) is not reset in the asynchronous reset assignment?

The example code looks like this:

  async_reset : process (Clk, Rst)
  begin
    if (Rst = '1') then
      -- Reset of FF_Q disabled purposefully
      -- FF_Q <= '0';
    elsif (rising_edge(Clk)) then
      FF_Q <= FF_D;
    end if;
  end process;

Synthesis produced the following result, without yielding any warning!
First of all the synthesiser is playing smart here:
The reset is actually active low here, it has moved a previous inverter into this logical block, that is why the implementation above looks a bit strange.

If reset is 1 the D input of the FF will maintain the current state.
If reset is 0 the D input of the FF will be controlled by the input.
The reset input of the FF is not connected at all.

This implementation reflects what was written, but probably not what was intended, and the compiler didn't even warn about it.

This is also important to understand if some flops are to be reset within a design and some not.
The typical pattern here is that you have some control logic manipulating a larger cloud of data logic.
The control needs to be reset while the data doesn't.

These flops cannot be generated within the same process!
You then need to have multiple synchronous processes:

The control process with the asynchronous reset statement:
 ctrl_async_reset : process (Clk, Rst)
  begin
    if (Rst = '1') then
      C_FF_Q <= '0';
    elsif (rising_edge(Clk)) then
      C_Q <= C_FF_D;
    end if;
  end process;

The data process lacking the asynchronous reset statement:
 data_no_async_reset : process (Clk)
  begin
    if (rising_edge(Clk)) then
      D_FF_Q <= D_FF_D;
    end if;
  end process;