Reputation: 1097
I was wondering how a logic synthesizer interprets a conditional reset value. For example, the initial state of a FSM depends on an asynchronous reset signal and some other signal as shown below.
state_reg : process(clk, reset)
begin
if reset = '0' then
if cond = '1' then
state <= init_state_0;
else
state <= init_state_1;
end if;
elsif rising_edge(clk) then
state <= next_state;
end if;
end process;
I'm aware that certain register optimizations are performed by synthesizers when the reset value is some constant, however is this also the case in a example like the one above?
One reason for such a design could be the optimization of the state machine since no intermediate state is required to choose between the two initial states.
Upvotes: 1
Views: 513
Reputation: 1306
I write verilog.
I used to modify a piece of industry code which implements conditional reset value.
assign ctrl_rst_n = sw_rst_n | cond;
assign ctrl_set_n = sw_rst_n | ~cond;
always@(posedge clk or negedge ctrl_rst_n or negedge ctrl_set_n)begin
if(~ctrl_rst_n)begin
ctrl <= 1'b0;
end else if(~ctrl_set_n)begin
ctrl <= 1'b1;
end else begin
(... normal function logic ...)
end
end
I got the following netlist after synthesis:
ctrl_rst_n ---+
___v___
| clr |
|D Q|
|CK |
|__set__|
^
ctrl_set_n ---+
There're 2 user registers named sw_rst_n
and cond
in an external block which can be accessed by software.
The programming guide is as follows:
user sets or clears cond
register to configure the reset value of signal ctrl
;
then clears sw_rst_n
register followed by a set operation to issue a software reset (s/w reset will not reset user register block);
after s/w reset, the signal ctrl
will start from the desired reset value.
Upvotes: 1
Reputation: 902
I am not sure that we can think about optimization on this small code sample
So we can take advantage of these constraints to elaborate a somewhat proper ( imho ) reset state by de-asserting the internal reset after 3 clock periods, taking into account that the double sampling of COND will take 2 clock periods.
By this way we may benefit from (almost) one clock period stable reset state.
But for sure you may do this on FPGA where you can export a data signal ( here the internal reset compared to the external RESET_N) to a "clock" distribution "grid".
The code is given for information below and and you may find it under EDA Playground
library IEEE;
use IEEE.std_logic_1164.all;
entity state_machine is
port ( CLOCK : in std_logic;
RESET_N : in std_logic;
COND : in std_logic;
OUTPUT : out std_logic_vector(7 downto 0));
end entity;
architecture rtl of state_machine is
type state_type is ( S1, S2, S3, S4);
signal state, next_state : state_type;
signal reset_state : state_type;
constant RSYNC_LENGTH : natural := 3;
signal reset : std_logic;
signal reset_v : std_logic_vector(RSYNC_LENGTH-1 downto 0);
signal scond : std_logic;
signal scond_q1 : std_logic;
signal outbuf : std_logic_vector(7 downto 0);
begin
reset_sync: process(CLOCK,RESET_N)
begin
if RESET_N = '0' then
reset_v <= (others => '1');
elsif rising_edge(CLOCK) then
reset_v(0) <= '0';
reset_v(RSYNC_LENGTH-1 downto 1) <= reset_v(RSYNC_LENGTH-2 downto 0);
end if;
end process reset_sync;
reset <= reset_v(RSYNC_LENGTH-1);
sync: process(CLOCK,RESET_N)
begin
if RESET_N = '0' then
scond <= '0';
scond_q1 <= '0';
elsif rising_edge(CLOCK) then
scond_q1 <= COND;
scond <= scond_q1;
end if;
end process sync;
reset_state <= S2 when scond='1' else S1;
SM : process(CLOCK,reset)
begin
if reset = '1' then
state <= reset_state;
elsif ( rising_edge(CLOCK) ) then
state <= next_state;
end if;
end process SM;
statedecoder: process(state)
begin
case ( state ) is
when S1 => next_state <= S2;
outbuf <= x"01";
when S2 => next_state <= S3;
outbuf <= x"02";
when S3 => next_state <= S4;
outbuf <= x"03";
when S4 => next_state <= S1;
outbuf <= x"04";
when others =>
next_state <= S1;
outbuf <= x"00";
end case;
end process statedecoder;
OUTPUT <= outbuf when reset = '0' else x"00";
end architecture rtl;
Upvotes: 1