1

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.

qantik
  • 1,067
  • 1
  • 10
  • 20
  • 2
    The basic function of the reset is to bring the system to a known state. Adding an `if` thwarts that. Also upon a reset what will be the value of `cond`? For you scheme to work that has to be variable as well. All you did is move the problem upstream. The only way to avoid that, is if `cond` comes from an external signal. – Oldfart Oct 11 '19 at 11:39
  • The `cond` signal can be assumed to be external and is stable once `reset` goes low. – qantik Oct 11 '19 at 11:46
  • I am not sure why you would want two initial states. If it's the case that `cond` is a constant/generic and the initial state might be different depending on its value, then it makes sense. Else, if `cond` changes during runtime, then there should only be one initial state, and you switch to the other state during runtime. – hkassir72 Oct 11 '19 at 11:49
  • `cond` is constant until the next reset trigger. It's a question of optimization since we don't spend on clock cycle choosing the initial states in a prior state. – qantik Oct 11 '19 at 11:54
  • *"cond is constant until the next reset trigger."* Thus `cond` changes between the first and the second reset? If so, how do you select the one you want for the first reset? – Oldfart Oct 11 '19 at 12:19
  • It's probably cleaner to add a post-reset state which transitions immediately to init_state_0 or _1 depending on the value of cond. –  Oct 11 '19 at 18:22
  • I would write two variants (1st with constant reset value, 2nd with selectable value) and synthesize it. Then I could have a look at the resulting gate/flipflop logic. Optimization is always a question of the synthsizer AND the target device. So no generic answer can be given. – the busybee Oct 11 '19 at 19:55
  • I guess you'll have to put the non-clocked signals `cond`, `init_state_0` and `init_state_1` into the sensitivity list. Anyway, your logic is a flip-flop with both asynchronous reset and asynchronous set, which I recommend to generally avoid… – aschipfl Oct 26 '22 at 16:06

2 Answers2

1

I am not sure that we can think about optimization on this small code sample

  • Often company design rules will compel you to have an asynchronous reset assertion and synchronous de-assertion
  • 50% of the time you will not have a 'cond' signal synchronous of the clock so that you will have to double sample it anyway

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;
NGI
  • 852
  • 1
  • 12
  • 31
1

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:

  1. user sets or clears cond register to configure the reset value of signal ctrl;

  2. 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);

  3. after s/w reset, the signal ctrl will start from the desired reset value.

Light
  • 1,206
  • 1
  • 9
  • 16