advertencia XST sobre nodos desconectados en FSM

0

Dado el siguiente código

library ieee;
use ieee.numeric_std.all;
use ieee.std_logic_1164.all;

library unisim;
use unisim.vcomponents.all;

entity sw_ctrl_top is

  generic (
    switch_window_g        : positive := 50;
    trig_heralding_delay_g : positive := 40);

  port (
    sysclk_p : in  std_logic;
    sysclk_n : in  std_logic;
    trig     : in  std_logic;
    dl_inc   : in  std_logic;
    dl_dec   : in  std_logic;
    dl_sign  : in  std_logic;
    rst      : in  std_logic;
    d        : in  std_logic_vector(3 downto 0);
    q0       : out std_logic;
    q1       : out std_logic;
    dl_led   : out std_logic_vector(3 downto 0));

end entity sw_ctrl_top;

architecture struct of sw_ctrl_top is

  -------------------------------------------------------------------------------
  -- Internal signals
  -------------------------------------------------------------------------------
  signal rst_i            : std_logic := '0';
  signal dl_inc_i         : std_logic := '0';
  signal dl_dec_i         : std_logic := '0';
  signal dl_sign_i        : std_logic := '0';
  signal clk_s, clk_div_s : std_logic := '0';

  -----------------------------------------------------------------------------
  -- Components
  -----------------------------------------------------------------------------
  component debouncer is
    port (
      CLK         : in  std_logic;
      D           : in  std_logic;
      D_DEBOUNCED : out std_logic);
  end component debouncer;

  component clk_divider is
    generic (
      div_factor_g : positive);
    port (
      I : in  std_logic;
      O : out std_logic);
  end component clk_divider;

  component sw_ctrl is
    generic (
      switch_window_g        : positive;
      trig_heralding_delay_g : positive);
    port (
      clk     : in  std_logic;
      trig    : in  std_logic;
      dl_inc  : in  std_logic;
      dl_dec  : in  std_logic;
      dl_sign : in  std_logic;
      rst     : in  std_logic;
      d       : in  std_logic_vector(3 downto 0);
      q0      : out std_logic;
      q1      : out std_logic;
      dl_led  : out std_logic_vector(3 downto 0));
  end component sw_ctrl;

begin  -- architecture struct

  clk_buf : IBUFGDS_LVDS_25
    port map(
      O  => clk_s,
      I  => sysclk_p,
      IB => sysclk_n
      );
  clk_div : component clk_divider
    generic map (
      div_factor_g => 3)
    port map (
      I => clk_s,
      O => clk_div_s);
  inc_deb : component debouncer
    port map (
      CLK         => clk_div_s,
      D           => dl_inc,
      D_DEBOUNCED => dl_inc_i);
  dec_deb : component debouncer
    port map (
      CLK         => clk_div_s,
      D           => dl_dec,
      D_DEBOUNCED => dl_dec_i);
  sign_deb : component debouncer
    port map (
      CLK         => clk_div_s,
      D           => dl_sign,
      D_DEBOUNCED => dl_sign_i);
  rst_deb : component debouncer
    port map (
      CLK         => clk_div_s,
      D           => rst,
      D_DEBOUNCED => rst_i);
  sw_controller : component sw_ctrl
    generic map (
      switch_window_g        => switch_window_g,
      trig_heralding_delay_g => trig_heralding_delay_g)
    port map (
      clk     => clk_s,
      trig    => trig,
      dl_inc  => dl_inc_i,
      dl_dec  => dl_dec_i,
      dl_sign => dl_sign_i,
      rst     => rst_i,
      d       => d,
      q0      => q0,
      q1      => q1,
      dl_led  => dl_led);



end architecture struct;

y la parte relevante del componente sw_ctrl

sw_proc : process (clk) is
    type sw_state_t is (
      idle, wait_delay, save_detectors_state,
      keep_sw_state, reset);            -- state type
    variable state_v                 : sw_state_t                         := idle;  -- current state variable
    variable switch_window_counter_v : natural range 0 to switch_window_g := 0;
    variable delay_counter_v         : natural range 0 to 7               := 0;
  begin
    if rising_edge(clk) then
      if rst = '1' then
        state_v := reset;
      end if;
      case state_v is
        when idle =>
          if trig = '0' then
            state_v := idle;
          end if;
          if trig = '1' and trig_heralding_delay_g = 0 then
            state_v := save_detectors_state;
          end if;
          if trig = '1' and trig_heralding_delay_g /= 0 then
            state_v := wait_delay;
          end if;
        when wait_delay =>
          if delay_counter_v < trig_heralding_delay_g + delay_after_trigger_s then
            delay_counter_v := delay_counter_v + 1;
            state_v         := wait_delay;
          end if;
          if delay_counter_v = trig_heralding_delay_g + delay_after_trigger_s then
            state_v := save_detectors_state;
          end if;
        when save_detectors_state =>
          state_v := keep_sw_state;
          if xor_result_s = '1' then
            switch_signal_s <= '1';
          else
            switch_signal_s <= '0';
          end if;
        when keep_sw_state =>
          if switch_window_counter_v < switch_window_g then
            switch_window_counter_v := switch_window_counter_v + 1;
            state_v                 := keep_sw_state;
          end if;
          if switch_window_counter_v = switch_window_g then
            state_v := reset;
          end if;
        when reset =>
          if trig = '0' then
            state_v := idle;
          end if;
          if trig = '1' then
            state_v := reset;
          end if;
          switch_window_counter_v := 0;
          delay_counter_v         := 0;
          switch_signal_s         <= '0';
        when others => state_v := reset;
      end case;
    end if;
  end process sw_proc;

No veo por qué la variable state_v estaría desconectada. XST dice que tiene un valor constante de 0 , lo que supongo que significa que nunca deja el estado idle y que está "desconectado". No veo cómo idle podría ser un estado muerto e ISE realmente no ayuda con que sus mensajes sean muy vagos. Además, state_v tiene una asignación en todas las ramas en la lógica FSM y la señal rst se inicializa en '0' en el componente superior (lo cual pensé que podría ser la única razón por la que XST dice que state_v siempre es 0 ), así que aparentemente me falta algo muy obvio para ISE pero no para mí.

Para mayor claridad e integridad, delay_after_trigger_s es una señal natural definida en otro proceso que no activa ningún error o advertencia.

¿Dónde se esconde este "bloqueo"?

Editar # 1

Resultados esperados

Básicamente, este diseño es un XOR excesivamente complicado. La entrada d , que es un vector de 4 bits, se alimenta a un XOR4 y su salida se enruta tanto a q0 como a q1 . Entonces, si alguno, y solo uno, de las entradas d es alto, q0 y q1 también son altos, y viceversa.

Testbench y resultados de simulación

Simulando este diseño con el siguiente banco de pruebas (ignore la señal delayed_photons , ya que no está conectado al uut )

ENTITY tb IS
END tb;

ARCHITECTURE behavior OF tb IS 

    -- Component Declaration for the Unit Under Test (UUT)

    COMPONENT sw_ctrl_top
    PORT(
         SYSCLK_P : IN  std_logic;
         SYSCLK_N : IN  std_logic;
         TRIG : IN  std_logic;
         DL_INC : IN  std_logic;
         DL_DEC : IN  std_logic;
            DL_SIGN : IN std_logic;
         RST : IN  std_logic;
         D : IN  std_logic_vector(3 downto 0);
         Q0 : OUT  std_logic;
         Q1 : OUT  std_logic;
         DL_LED : OUT  std_logic_vector(3 downto 0)
        );
    END COMPONENT;


   --Inputs
   signal SYSCLK_P : std_logic := '0';
   signal SYSCLK_N : std_logic := '0';
   signal TRIG : std_logic := '0';
   signal DL_INC : std_logic := '0';
   signal DL_DEC : std_logic := '0';
   signal DL_SIGN : std_logic := '0';
   signal RST : std_logic := '0';
   signal D : std_logic_vector(3 downto 0) := (others => '0');

    --Outputs
   signal Q0 : std_logic;
   signal Q1 : std_logic;
   signal DL_LED : std_logic_vector(3 downto 0);

    -- Clocking settings
   constant clk_period : time := 5 ns;
    constant trig_period : time := 1 us;

    -- Other simulation signals
    signal delayed_photons : std_logic_vector(3 downto 0) := (others => '0');

BEGIN

    -- Instantiate the Unit Under Test (UUT)
   uut: sw_ctrl_top PORT MAP (
          SYSCLK_P => SYSCLK_P,
          SYSCLK_N => SYSCLK_N,
          TRIG => TRIG,
          DL_INC => DL_INC,
          DL_DEC => DL_DEC,
             DL_SIGN => DL_SIGN,
          RST => RST,
          D => D,
          Q0 => Q0,
          Q1 => Q1,
          DL_LED => DL_LED
        );

   -- Clock process definitions
   clk_process :process
   begin
        SYSCLK_N <= '0';
        SYSCLK_P <= '1';
        wait for clk_period/2;
        SYSCLK_N <= '1';
        SYSCLK_P <= '0';
        wait for clk_period/2;
   end process;

    -- Trigger process
    trig_process : process
    begin
        TRIG <= '0';
        wait for trig_period/2;
        TRIG <= '1';
        wait for trig_period/2;
    end process;


   -- Stimulus process
   stim_proc: process
   begin
        --DL_INC <= '1', '0' after 10 ms;
        wait for 700 ns;
        D <= X"1", X"0" after 60 ns;
        wait for 5 ns;
        delayed_photons <= X"1", X"0" after 60 ns;
        wait for 0.995 us;
        D <= X"3", X"0" after 60 ns;
        wait;
   end process;

END;

Da los resultados que espero, es decir, q0 es 1 durante el primer impulso de disparo y 0 durante el segundo, ya que las entradas d en esos ciclos son, respectivamente, "0001" y "0011" .

Lo que todavía no entiendo es: ¿no es la síntesis más importante que la simulación? Lo que me importa es un diseño que también funciona en el "mundo real" y si XST me dice que algunos nodos no están conectados, ¿no debería preocuparme más esto que los resultados de la simulación?

Editar # 2

Mi sistema es el siguiente:

  • Paquete de software: Xilinx ISE 14.7
  • Sintetizador: XST
  • Simulador: ISim
  • FPGA: Spartan-6

Editar # 3

Como la simulación fue buena, intenté implementar el diseño en el chip. Hay un problema mucho más grande durante el paso del mapeo, en el cual me advierte que todas las entradas d(i) han sido eliminadas. Esto no es realmente una sorpresa, dado que la única asignación a esas señales está dentro del FSM, que según el sintetizador no está progresando.

Durante el sintetizador, XST emite la advertencia (como ejemplo):

Xst:2677 - Node <sw_proc.state_v_0> of sequential type is unconnected in block <sw_ctrl>.

Durante el mapa, la advertencia es (nuevamente solo uno como ejemplo):

MapLib:701 - Signal d<0> connected to top level port d<0> has been removed.
    
pregunta mmassaro

2 respuestas

0

Después de escanear línea por línea, localicé el problema.

signal delay_counter_v : natural range 0 to 7 := 0;
...
when wait_delay =>
  if delay_counter_v < trig_heralding_delay_g + delay_after_trigger_s then
    delay_counter_v := delay_counter_v + 1;
    state_v         := wait_delay;

Allí el FSM se atascó porque su rango era menor que lo que necesitaba. Agregando el valor de trig_heralding_delay_g al rango de los sintetizadores y mapas sin problemas.

Esto realmente me desconcierta, ya que las simulaciones dieron resultados correctos ... Estoy feliz de haber resuelto el problema pero en realidad estoy más confundido.

    
respondido por el mmassaro
0

Simular.

Escriba un banco de pruebas, agréguelo a la pregunta y simule ... Use aserciones para ver qué hace cuando lo activa. ¿Puedes sacarlo de Idle en simulación? ¿Hace todo lo que esperas?

Mi conjetura ... en el proceso de responder a eso, encontrará algún error (probablemente en las conexiones de nivel superior) que lo mantiene inactivo.

Y ... el consejo para evitar elsif / else es monumentalmente despistado. Pero su uso de las variables está bien, SIEMPRE que está al tanto de la diferencia entre la semántica de asignación de la señal y la variable.

    
respondido por el Brian Drummond

Lea otras preguntas en las etiquetas