qantik
qantik

Reputation: 1097

VHDL Synthesis: Conditional Reset Value

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

Answers (2)

Light
Light

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:

  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.

Upvotes: 1

NGI
NGI

Reputation: 902

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;

Upvotes: 1

Related Questions