Tengo que restringir una FPGA de Lattice Semiconductor y tengo algunas dudas acerca de la restricción multiciclo descrita aquí . Tengo el siguiente RTL:
Básicamente se trata de un contador accionado por un detector de flanco ascendente. Cada vez que una señal sube de 0 a 1 se genera un impulso y el contador aumenta. Este es también el código VHDL, para que quede claro:
type COM_PACKETS_COUNTER is array ( 7 downto 0) of std_logic_vector(31 downto 0);
signal capture_com_tx_packet_counter : COM_PACKETS_COUNTER;
signal capture_com_rx_packet_counter : COM_PACKETS_COUNTER;
signal capture_com_tx_data_reg : std_logic_vector(7 downto 0);
signal capture_com_rx_data_reg : std_logic_vector(7 downto 0);
signal capture_com_tx_start_byte_reg : std_logic_vector(7 downto 0);
signal capture_com_rx_start_byte_reg : std_logic_vector(7 downto 0);
signal capture_com_tx_start_byte_reg_delay : std_logic_vector(7 downto 0);
signal capture_com_rx_start_byte_reg_delay : std_logic_vector(7 downto 0);
signal capture_com_tx_start_byte_reg_edge : std_logic_vector(7 downto 0);
signal capture_com_rx_start_byte_reg_edge : std_logic_vector(7 downto 0);
..........................
COM_COUNTER_PROCESS :
for i in 0 to capture_com_tx_data_reg'length-1 generate
process(clk_i, rst_i)
begin
if rst_i = '1' then
capture_com_rx_start_byte_reg_delay(i) <= '0';
capture_com_rx_start_byte_reg_edge(i) <= '0';
capture_com_tx_start_byte_reg_delay(i) <= '0';
capture_com_tx_start_byte_reg_edge(i) <= '0';
elsif clk_i = '1' and clk_i'event then
capture_com_rx_start_byte_reg_delay(i) <= capture_com_rx_start_byte_reg(i);
capture_com_rx_start_byte_reg_edge(i) <= not ( capture_com_rx_start_byte_reg_delay(i) ) and capture_com_rx_start_byte_reg(i) and CAPTURE_COM_RX_SELECTED_FILTER(i);
capture_com_tx_start_byte_reg_delay(i) <= capture_com_tx_start_byte_reg(i);
capture_com_tx_start_byte_reg_edge(i) <= not ( capture_com_tx_start_byte_reg_delay(i) ) and capture_com_tx_start_byte_reg(i) and CAPTURE_COM_TX_SELECTED_FILTER(i);
end if;
end process;
process(clk_i,rst_i)
begin
if rst_i = '0' then
capture_com_tx_packet_counter(i) <= (others => '0');
elsif clk_i'event and clk_i = '1' then
if capture_com_tx_start_byte_reg_edge(i) = '1' then
capture_com_tx_packet_counter(i) <= capture_com_tx_packet_counter(i) + 1;
end if;
if capture_com_rx_start_byte_reg_edge(i) = '1' then
capture_com_rx_packet_counter(i) <= capture_com_rx_packet_counter(i) + 1;
end if;
end if;
end process;
end generate;
Tengo varios mostradores en mi diseño. Ahora quiero relajar el tiempo, así que me pregunto si puedo usar una "restricción de ciclo múltiple" entre el registro de origen ( capture_com_rx_start_byte_reg_edge ) y el registro de destino ( capture_com_rx_packet_counter ) porque no necesito que el contador se actualice después del aumento de capture_com_tx_start_byte_reg.
Mi única preocupación es que el impulso generado pueda durar más de un ciclo de reloj, eso podría ser un problema porque el contador podría aumentar más de 1 unidad.
Cuando utilice multiciclos, debe tener cuidado de que la ruta sea segura para multiciclos. En su caso, la falta de activación del reloj capture_com_rx_packet_counter
lo haría "inseguro". Debería ser posible obligar a la herramienta de síntesis a usar una primitiva de flip-flop con un reloj-en, que sería el primer paso para multiciclo.
Sin embargo, aunque el multiciclo es muy útil para relajar los tiempos, solo lo recomendaría si es tu última solución. ¿Es ese camino realmente problemático? ¿Falla los tiempos? ¿Todos los demás caminos son significativamente más rápidos?
También puede cortar los tiempos con código VHDL. Un ejemplo que hace la suma en 2 ciclos (la entrada debe ser estable 2 ciclos, la salida solo es válida en el segundo ciclo):
signal s_lo : unsigned(16 downto 0);
signal s_hi : unsigned(15 downto 0);
process(clk)
begin
if rising_edge(clk) then
s_lo <= '0' & a(15 downto 0) + b(15 downto 0);
s_hi <= a(31 downto 16) + b(31 downto 16) + s_lo(16);
end if;
end process;
s <= s_hi & s_lo(15 downto 0);
haster8558