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.