Problema al mapear VHDL en la placa de desarrollo

Tengo un problema muy frustrante y realmente agradecería alguna ayuda.

Estoy tratando de probar un bloque de RAM usando los interruptores y los LED en la placa de desarrollo Nexys A7-100T FPGA. Mi código se sintetiza bien pero falla en la implementación debido a los errores que se muestran en la imagen a continuación.

También he mostrado mi archivo de restricciones y el archivo de código de nivel superior.

Soy nuevo en las placas FPGA y no estoy seguro de lo que estoy haciendo mal. He probado este código en testbench y funciona perfecto. Me gustaría mapearlo en el FPGA para aprender cómo hacerlo.

EDITAR

Tengo los relojes comentados en el archivo de restricciones, ya que causaron aún más errores.

¡Gracias!

ingrese la descripción de la imagen aquí

archivo de restricciones



#create_clock -period 10.000 -name clk -waveform {0.000 5.000} [get_ports clk]
#set_property -dict { PACKAGE_PIN E3    IOSTANDARD LVCMOS33 } [get_ports { clk }];

set_property -dict { PACKAGE_PIN P17   IOSTANDARD LVCMOS33 } [get_ports { Set_Button }]; #IO_L12P_T1_MRCC_14 Sch=btnl
set_property -dict { PACKAGE_PIN M17   IOSTANDARD LVCMOS33 } [get_ports { Enable_Button }]; #IO_L10N_T1_D15_14 Sch=btnr

set_property -dict { PACKAGE_PIN J15   IOSTANDARD LVCMOS33 } [get_ports { RAM_Address[0] }]; #IO_L24N_T3_RS0_15 Sch=sw[0]
set_property -dict { PACKAGE_PIN L16   IOSTANDARD LVCMOS33 } [get_ports { RAM_Address[1] }]; #IO_L3N_T0_DQS_EMCCLK_14 Sch=sw[1]
set_property -dict { PACKAGE_PIN M13   IOSTANDARD LVCMOS33 } [get_ports { RAM_Address[2] }]; #IO_L6N_T0_D08_VREF_14 Sch=sw[2]
set_property -dict { PACKAGE_PIN R15   IOSTANDARD LVCMOS33 } [get_ports { RAM_Address[3] }]; #IO_L13N_T2_MRCC_14 Sch=sw[3]

set_property -dict { PACKAGE_PIN H17   IOSTANDARD LVCMOS33 } [get_ports { Data_out[0] }]; #IO_L18P_T2_A24_15 Sch=led[0]
set_property -dict { PACKAGE_PIN K15   IOSTANDARD LVCMOS33 } [get_ports { Data_out[1] }]; #IO_L24P_T3_RS1_15 Sch=led[1]
set_property -dict { PACKAGE_PIN J13   IOSTANDARD LVCMOS33 } [get_ports { Data_out[2] }]; #IO_L17N_T2_A25_15 Sch=led[2]
set_property -dict { PACKAGE_PIN N14   IOSTANDARD LVCMOS33 } [get_ports { Data_out[3] }]; #IO_L8P_T1_D11_14 Sch=led[3]

archivo de nivel superior



library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use work.Architecture_size.ALL;

entity RAM_Block is
 Port ( RAM_Address : in std_logic_vector (Data_width-1 downto 0); 
        Data_in  : in std_logic_vector (Data_width-1 downto 0);
        Set_Button : in std_logic;
        Enable_Button : in std_logic;
        Data_out : out std_logic_vector (Data_width-1 downto 0));
end RAM_Block;

architecture Behavioral of RAM_Block is

component Enabler_Block is
 Port ( A : in std_logic_vector(Data_width-1 downto 0);
        Enable : in std_logic;
        Q : out std_logic_vector(Data_width-1 downto 0));
end component;

type memory is array (0 to 3) of std_logic_vector (Data_width-1 downto 0);
signal RAM : memory := ("0000" , "0000" , "0000" , "0000");
signal RAM_output : std_logic_vector (Data_width-1 downto 0);
signal RAM_Address_int : integer;


begin



Enabler_Block_instance : Enabler_Block port map (A => RAM_output , Enable => Enable_Button , Q => Data_out);

RAM_Address_int <= conv_integer(unsigned(RAM_Address)); 

   Process (Set_Button , Enable_Button)

    begin

     if(rising_edge(Set_Button) and Set_Button = '1') then
        RAM(RAM_Address_int) <= Data_in;

     end if;

     if(rising_edge(Enable_Button) and Enable_Button = '1') then
        RAM_output <= RAM(RAM_Address_int);

     end if;

    end Process;

end Behavioral;

Aquí hay dos cosas: una, debe tener cuidado con el estilo de codificación. especialmente con los relojes. Debe codificar de una manera específica para que la herramienta lo identifique como FF o RAM. Hay plantillas de idioma en Vivado sobre cómo codificar una RAM. En segundo lugar, todos los relojes deben estar conectados a un PIN con capacidad de reloj para un enrutamiento eficiente.
Definitivamente es que los relojes que usó en el diseño no están conectados a un pin con capacidad de reloj de un FPGA. Enable_Button se considera como un reloj y está conectado a M17, que no es un pin CC
¿Pudiste arreglar esto?
@MituRaj Sí, proporcioné una respuesta para explicar cómo se resolvió el problema, ¡gracias por su ayuda!

Respuestas (4)

El problema son las declaraciones:

if(rising_edge(Set_Button) and Set_Button = '1')
.
.
if(rising_edge(Enable_Button) and Enable_Button = '1')

Cuando sintetiza este código, el sintetizador reconoce estas dos señales como los relojes en su diseño. Estos también son puertos de entrada en su módulo. Si estas señales fueran realmente entradas de reloj en su diseño (que no creo que tuviera la intención de hacerlo), debería asignarlas a pines con capacidad de reloj en el FPGA. De lo contrario, el sintetizador no podrá usar el enrutamiento de reloj dedicado desde los respectivos IO a través de BUFG, a los flip-flops sincronizados por ellos. Por lo tanto, los mensajes de error.

Bueno, de todos modos, no creo que tuviera la intención de usarlos como relojes, así que esto es lo que podría estar buscando en su lugar:

if rising_edge(clk) then

   if Enable_button = '1' then 
      ..
   end if

   if Set_button = '1' then
      ...
   end if   

end if

Su diseño tal como está no está cronometrado en absoluto.

Esto será difícil de sintetizar ya que los registros en los bloques lógicos tienen un reloj y una entrada de habilitación, y se supone que el FF cambia en un flanco ascendente del reloj mientras la habilitación está configurada.

En cambio, lo que está haciendo es tomar datos en el flanco ascendente de una señal de habilitación, que debe sintetizarse derivando la señal de "habilitación" a la entrada de reloj del FF. Dado que el enrutamiento del reloj es independiente (debido a que los relojes tienen requisitos estrictos de temporización y fanout alto), generalmente no existe un buen mecanismo para eso.

El mensaje de error que recibe se queja de que está enrutando un pin de entrada que no es compatible con el reloj a una red de reloj, lo que conduce a un enrutamiento muy complicado porque el único lugar para conectarlos es en el otro lado del chip.

La restricción que sugiere aclararía que no está solicitando que esta señal se inyecte en una red de distribución de reloj, lo que relajaría el problema de enrutamiento aquí, pero limitaría el despliegue de la señal.

Es probable que la restricción también genere el enrutamiento que espera, con el reloj atado alto y la habilitación enrutada al FF, pero sin restricción de tiempo en la habilitación, porque las restricciones se rastrean contra un reloj interno, que usted no tiene.

El problema debería desaparecer si realmente haces que este diseño esté cronometrado.

Gracias por tu respuesta. Ok, veo lo que a Vivado no le gusta ahora, sin embargo, todo mi diseño se basa en esto. Nunca tuve este problema durante la simulación, pero ahora, cuando uso la placa FPGA, veo que mis diseños no van a funcionar. ¿Me recomendaría que cambie mi diseño para que todos los componentes estén cronometrados y luego, en mis procesos, decida si establecer o habilitar o no en función de las entradas en el flanco ascendente del reloj? ¿Al menos esto se sintetizará en el tablero?
@ David777 El estilo es malo y simplemente no funcionará para la mayoría de VHDL, pero para algo tan simple como lo que tiene aquí, la detección de bordes LUT funcionará, aunque soy escéptico de que haya escrito una RAM. Si todo lo que quiere en este momento es hacer que algunos LED parpadeen, simplemente deshabilite el enrutamiento de reloj dedicado como se menciona en el mensaje de error y tome en serio las lecciones de Simon y Mitu Raj para la próxima vez.
@DonFusili Entiendo lo que quieres decir, es un mal ejemplo. Sin embargo, esto será para un bloque de RAM real, solo usé la placa FPGA con botones como conjunto y habilité las entradas para acelerar las pruebas de diferentes combinaciones de datos.

El mensaje le dice que uno de los pines se está utilizando como reloj, pero en realidad no es un buen pin para usar como reloj. Primero me desharía del extra "and Set_Button = '1')" y "and Enable_Button='1')". Solo necesita la parte "rising_edge".

También debe dividir el proceso en dos procesos y hacer que cada uno sea sensible a su reloj respectivo.

Si aún recibe el error, ¿puede elegir pines diferentes para "Set_Button" y "Enable_Button"?

Gracias por su consejo. Dividí los procesos y cambié su lista de sensibilidad y todavía no me gustó. También probé algunos pines diferentes sin éxito. Vea mi comentario La respuesta de Simon Richter arriba
@David777. Intente eliminar la restricción del pin Xilinx para Set_Button y Enable_Button. Vea si funcionará con Xilinx recogiendo el alfiler.

Solo proporciona una actualización a esta pregunta. Según el consejo de todos, modifiqué mi VHDL para sincronizar el diseño y el problema está resuelto. Esto permitió que el sintetizador usara pines con capacidad de reloj para el reloj y los otros pines para establecer y habilitar la entrada.

Sin embargo, me ha causado más problemas a lo largo de mi diseño completo, ya que tengo este mismo problema en otro código VHDL. Gracias por la ayuda de todos. He aceptado una respuesta, sin embargo, la respuesta de todos fue muy útil y muy apreciada.



library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use work.Architecture_size.ALL;

entity RAM_Block is
 Port ( Clock : in std_logic;
        RAM_Address : in std_logic_vector (Data_width-1 downto 0); 
        Data_in  : in std_logic_vector (Data_width-1 downto 0);
        Set : in std_logic;
        Enable : in std_logic;
        Data_out : out std_logic_vector (Data_width-1 downto 0);
        RAM_Address_LED : out std_logic_vector (Data_width-1 downto 0);
        Data_in_LED : out std_logic_vector (Data_width-1 downto 0));
end RAM_Block;

architecture Behavioral of RAM_Block is

component Enabler_Block is
 Port ( A : in std_logic_vector(Data_width-1 downto 0);
        Enable : in std_logic;
        Q : out std_logic_vector(Data_width-1 downto 0));
end component;

type ram_type is array (0 to 3) of std_logic_vector (Data_width-1 downto 0);
signal RAM : ram_type := (others => "0000");
signal RAM_output : std_logic_vector (Data_width-1 downto 0);
signal RAM_Address_int : integer;


begin

Data_in_LED <= Data_in; 

RAM_Address_LED <= RAM_Address;

Enabler_Block_instance : Enabler_Block port map (A => RAM_output , Enable => Enable , Q => Data_out);

RAM_Address_int <= conv_integer(unsigned(RAM_Address)); 

   Process (Clock)

    begin

     if(rising_edge(Clock)) then
     
       if(Set = '1') then
        RAM(RAM_Address_int) <= Data_in;
        
       end if;
       
     end if;
     
    end process;
    
    Process (Clock)

     begin

     if(rising_edge(Clock)) then
     
        if(Enable = '1') then
         RAM_output <= RAM(RAM_Address_int);
         
        end if;  
     end if;

    end Process;
   
end Behavioral;

```