VHDL ALU, registro de 8 bits

2

El siguiente código vhdl está destinado a hacer la operación como se muestra en el diagrama. Pero la forma de onda simulada no parece ser correcta, he pasado horas pero no puedo detectar el error. ¿Puede alguien ayudarme por favor?

libraryieee;useieee.std_logic_1164.all;entityLUisport(CLK:instd_logic;--SystemClockRES:instd_logic;--SynchronousresetOPCODE:instd_logic_vector(2downto0);--LogicUnitOpcodeA:instd_logic_vector(7downto0);--AinputbusB:instd_logic_vector(7downto0);--BinputbusQ:outstd_logic_vector(7downto0)--QoutputfromLogicUnit);endLU;architecturebehavioralofLUissignalQA,Aa,Bb:std_logic_vector(7downto0);beginAa<=A;Bb<=B;process(clk)beginifRES='1'thenQA<="00000000" ;
elsif rising_edge(clk) then
  case OPCODE is
        when "000" => 
            QA <= not(Aa);  
        when "001" => 
            QA <= not( Aa xor Bb);
        when "010" => 
            QA <= not(Aa or Bb); 
        when "011" => 
            QA <= not( Aa and Bb);
        when "100" => 
            QA <= Aa;              
        when "101" => 
            QA <= ( Aa xor Bb); 
        when "110" => 
            QA <= ( Aa or Bb);   
        when "111" => 
            QA <= ( Aa and Bb); 
        when others =>
            NULL;
    end case;
 Q<= QA ;
 end if ;
 end process ;
 end behavioral;

EsaeslaoladespuésdequeintentémoverQ<=QAasignaciónafueradelproceso

    
pregunta super95

1 respuesta

7

El problema que estás viendo se debe a la etapa innecesaria que genera tu señal QA , declarada aquí:

  

señal QA, Aa, Bb: std_logic_vector (7 downto 0);

Su OPCODE selecciona una asignación para QA en un ciclo de reloj que, a su vez, asigna la salida final Q en el siguiente ciclo de reloj.

Un enfoque más limpio sería eliminar todas las señales internas, que son totalmente innecesarias para su entidad LU .

Prueba esto en su lugar:

library ieee;
use ieee.std_logic_1164.all;

entity LU is
port(
    CLK       :in  std_logic;                      -- System Clock
    RES       :in  std_logic;                      -- Synchronous reset
    OPCODE    :in  std_logic_vector(2 downto 0);   -- Logic Unit Opcode
    A         :in  std_logic_vector(7 downto 0);   -- A input bus
    B         :in  std_logic_vector(7 downto 0);   -- B input bus
    Q         :out std_logic_vector(7 downto 0));  -- Q output from Logic Unit     
end LU;

architecture behavioral of LU is
begin
    process(clk)
    begin
        if rising_edge(clk) then
            if RES = '1' then
                Q <= (others => '0');
            else
              case OPCODE is
                    when "000" => 
                        Q <= not(A);  
                    when "001" => 
                        Q <= not(A xor B);
                    when "010" => 
                        Q <= not(A or B); 
                    when "011" => 
                        Q <= not(A and B);
                    when "100" => 
                        Q <= A;              
                    when "101" => 
                        Q <= (A xor B); 
                    when "110" => 
                        Q <= (A or B);   
                    when "111" => 
                        Q <= (A and B); 
                    when others =>
                        Q <= (others => '0');
                end case;
            end if;
         end if;
     end process;
 end behavioral;

Que produce el RTL correcto:

Conestasimulación:

TuVHDLproduceestaRTL:

Hay tres cosas que notar aquí:

  1. Tu señal QA adicional termina generando una etapa 2 nd de gates no deseadas
  2. La etapa 2 nd de las puertas no está habilitada correctamente. ¿Observa que su señal RES termina actuando como un reloj invertido habilitado en las puertas finales? Esto se debe al hecho de que a su salida final Q no se le asigna un valor durante su condición RES = 1 . Su código solo asigna realmente Q dentro de la cláusula elsif rising_edge(clk) then . Esto conduce a un mal diseño. Si a una señal se le asigna un valor en un caso (o si-entonces nivel), se le debe asignar un valor en todos ellos. De lo contrario, terminará con cierres o señales de CE inapropiadas.
  3. Debes usar reinicios síncronos (como lo hice en el código anterior). Aparte de eso, una buena convención para usar es
    • Nombre la señal CLR para operaciones asíncronas
    • Nombre la señal RST para operaciones sincrónicas

Observe que esta es la convención empleada por Xilinx, como puede confirmar comparando los dos diagramas RTL.

    
respondido por el Blair Fonville

Lea otras preguntas en las etiquetas