VHDL: no se pudieron implementar registros para las asignaciones en este borde del reloj

1

Estoy recibiendo los siguientes errores:
Error (10822): error de HDL en pwm.vhd (15): no se pudieron implementar registros para las asignaciones en este borde del reloj
Error (10822): error de HDL en pwm.vhd (18): no se pudieron implementar registros para las asignaciones en este borde del reloj

Obviamente, el problema son los dos flancos ascendentes que cambian "salida". ¿Cómo podría solucionar este problema?
código:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_unsigned.all;
entity PWM is
port(
button1, button2 : in STD_LOGIC;
output : inout STD_LOGIC_VECTOR(7 downto 0) := "00000000"
);
end PWM;
architecture behavioral of PWM is 
begin
process(button1, button2)
begin
if rising_edge(button1) then
    output <= output + 1;
end if;
if rising_edge(button2) then
    output <= output - 1;
end if;
end process;
end behavioral;
    
pregunta gilianzz

2 respuestas

5

El circuito que describe es un registro con dos relojes de entrada, que realmente no existe. Hay registros DDR, pero eso no es lo que describiste.

Además, los relojes son muy especiales en un FPGA y deben usarse con especial cuidado. Un botón no es un reloj. Aunque es posible utilizar la señal normal como un reloj, no se recomienda.

Lo que necesita es un reloj real para conducir su circuito, ¡cada placa tiene uno! Luego, debe detectar los bordes ascendentes de su botón de acuerdo con el dominio de ese reloj:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
--use ieee.std_logic_unsigned.all; Do not use with numeric_std

entity PWM is
port(
    clk : in STD_LOGIC;
    button1, button2 : in STD_LOGIC;
    output : out STD_LOGIC_VECTOR(7 downto 0)
);
end entity PWM;

architecture behavioral of PWM is

    signal button1_r : std_logic_vector(2 downto 0);
    signal button2_r : std_logic_vector(2 downto 0);
    signal output_i  : unsigned(7 downto 0) := (others => '0');

begin

    process(clk)
    begin
        if rising_edge(clk) then
            -- Shift the value of button in button_r
            -- The LSB is unused and is there solely for metastability
            button1_r <= button1_r(button1_r'left-1 downto 0) & button1;
            button2_r <= button2_r(button2_r'left-1 downto 0) & button2;

            if button1_r(button1_r'left downto button1_r'left-1) = "01" then -- Button1 rising
                output_i <= output_i + 1;
            elsif button2_r(button2_r'left downto button2_r'left-1) = "01" then -- Button2 rising
                output_i <= output_i - 1;
            end if;
        end if;
    end process;

    output <= std_logic_vector(output_i);

end architecture behavioral;

Varias cosas a tener en cuenta:

  • La salida está controlada por un solo reloj
  • La salida es una salida, no una entrada. inout es un búfer tristate, que no necesitas. Usamos una señal interna para representar la salida y le asignamos la salida
  • Siempre que se use una señal asíncrona (como su botón) para un reloj en ese dominio de reloj, la metastabilidad es un problema. Le sugiero que lea en él, pero se resuelve utilizando dos registros en fila, la salida del primer registro (button1_r (0)) no debe usarse.

Finalmente, los botones físicos necesitan ser rebotados. A medida que lo presiona, la conexión eléctrica se enciende y se apaga varias veces mientras el interruptor físico alcanza su posición final. Por lo tanto, es probable que se detecten múltiples aristas ascendentes de los botones cuando lo presionas, incrementando el contador más de una vez.

    
respondido por el Jonathan Drolet
1

Quería hacer de esto un comentario, pero no puedo escribir VHDL de aspecto limpio allí.

Simplemente estoy disparando desde la cadera, pero la forma en que manejaste la salida es un poco poco ortodoxa y sospecho que podría ser tu problema, porque de lo contrario: tu VHDL es bastante simple y no veo nada malo con el resto de ello.

Esto es lo que escribiría personalmente:

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

entity PWM is
  port(
    button1, button2 : in STD_LOGIC;
    output : out STD_LOGIC_VECTOR(7 downto 0)  //Change this to just output
  );
end PWM;

architecture behavioral of PWM is 

  //Use a signal to act as a buffer that writes to your output
  signal s_output : STD_LOGIC_VECTOR(7 downto 0) := X"00";

begin

  process(button1, button2)
  begin
  if rising_edge(button1) then
    s_output <= s_output + 1;        //Instead of directly manipulating output, change the signal
  end if;
  if rising_edge(button2) then
    s_output <= s_output - 1;        //Instead of directly manipulating output, change the signal
  end if;
  end process;

  output <= s_output                //Assign the signal to output after the process

end behavioral;

Pongo comentarios donde hice cambios a tu código.

Básicamente, usas una señal que actúa como un búfer para tu salida. Utiliza la señal para manipular y cambiar, luego, cuando haya terminado con el proceso: asigne la señal a la salida.

    
respondido por el Nick Williams

Lea otras preguntas en las etiquetas