Asynchronous Reset
proc_dtype:process(in_clk,in_reset)begin
if (in_reset = '1') then
out_q <= '0';
elsif (rising_edge(in_clk)) then
out_q <= in_d;
end if;
end process;
The VHDL above will generate a d-type shown in the RTL view below. It creates a reset that is independent on the clock or asynchronous.
The asynchronous reset is the simplest to implement and is probably the most common type of reset used in an FPGA design. The advantage of this kind of reset is it does not need to insert any extra logic in the data path and therefore will not inadvertently increase the logic layers between d-types in an RTL stage. This mean that asynchronous reset will not impact on the data arrival time to a register input. The other big advantage of an asynchronous reset is that the reset will take effect immediately i.e. it is not dependent on the clock.
Would a synchronous reset be any better?
Synchronous Reset
proc_dtype:process(in_clk)begin
if (rising_edge(in_clk)) then
if (in_reset = '1') then
out_q <= '0';
else
out_q <= in_d;
end if;
end if;
end process;
The VHDL above will generate a d-type shown in the RTL view below. It creates a reset that is dependent on the clock or synchronous.
This reset design is fully synchronous and is therefore predictable and we can use static timing analysis such as TimeQuest to test the timing of the circuit. This kind of reset can also be easier to use when you do circuit simulation. However there is a down side to synchronous resets. Your design will be more complex and you create the risk of adding additional gate delays to accommodate the reset signal. This will produce a negative impact on the d-types set-up slack time.
However it turns out that it is possible to use an asynchronous reset, but with a synchronous release.
A bit of both Asynchronous and Synchronous
proc_dtype:process(in_clk,reset)begin
if (reset = '1') then
out_q <= '0';
elsif (rising_edge(in_clk)) then
out_q <= in_d;
end if;
end process;
proc_reset:process(in_clk,in_reset)
begin
if (in_reset = '1') then
rst_reg <= '1';
reset <= '1';
elsif (rising_edge(in_clk)) then
rst_reg <= '0';
reset <= rst_reg;
end if;
end process;
The the VHDL above contains two processes. The top process is a d-type that we want to reset and the bottom process is a reset synchronization circuit. It produces the following RTL.
This design avoids the potential problems associated with synchronous reset and purely asynchronous reset. The reset is applied asynchronously and immediately. It also does not create the additional logic we have seen with the synchronous design. However the one big advantage is that when the reset is released, it is synchronous to the clock. This mean that all the registers will be reset in the same clock cycle. You can also use static timing analysis to prove your timings.
My Nios II reset
In my post Using a PLL to correct the SDRAM clock when using a Nios II on the DE0-Nano the Nios was connected directly to the reset pin and the pll used the reset pin via a NOT gate. Based on the above discussion this has now been replaced with a reset synchronization circuit shown below:
The VHDL for this reset circuit is as follows:
library ieee;use
ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity reset_synchronization is
port
(
in_clk : in std_logic;
in_reset_n : in std_logic;
out_reset : out std_logic;
out_reset_n : out std_logic
);
end entity;
architecture arch_reset_synchronization of reset_synchronization is
signal rst_reg: std_logic;
signal reset : std_logic;
begin
proc_reset:process(in_clk,in_reset_n)
begin
if (in_reset_n = '0') then
rst_reg <= '1';
reset <= '1';
elsif (rising_edge(in_clk)) then
rst_reg <= '0';
reset <= rst_reg;
end if;
end process;
out_reset <= reset;
out_reset_n <= not reset;
end architecture;
ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity reset_synchronization is
port
(
in_clk : in std_logic;
in_reset_n : in std_logic;
out_reset : out std_logic;
out_reset_n : out std_logic
);
end entity;
architecture arch_reset_synchronization of reset_synchronization is
signal rst_reg: std_logic;
signal reset : std_logic;
begin
proc_reset:process(in_clk,in_reset_n)
begin
if (in_reset_n = '0') then
rst_reg <= '1';
reset <= '1';
elsif (rising_edge(in_clk)) then
rst_reg <= '0';
reset <= rst_reg;
end if;
end process;
out_reset <= reset;
out_reset_n <= not reset;
end architecture;
And that it! We now has a DE0-nano design with a more robust reset!. Feel free to post comments to let me know what you think.
References
Altera - Recommended Design PracticesHow do I reset my FPGA?
Synchronizing Asynchronous Resets / Reset Design
No comments:
Post a Comment