¿Por qué este concepto en VHDL no funciona?

0

Quiero hacer un elemento de procesamiento simple para calcular la diferencia absoluta entre dos palabras de 8 bits. Sin embargo, este elemento se puede usar como parte de una matriz para acelerar el cálculo de AD, haciéndolo en paralelo con más datos. Entonces, para lograr eso, excepto por las dos entradas de datos de 8 bits y la salida de datos de 8 bits, debería tener otras dos salidas de datos de 8 bits (llamémoslas SHIFT_A y SHIFT_B) que mantendrán el valor del anterior entradas (como un registro de desplazamiento).

Intenté realizar una implementación en VHDL, pero no funciona porque no puedo averiguar cómo hacer que las dos salidas SHIFT tengan valores diferentes a las dos entradas de datos. He intentado muchas cosas sin éxito, por lo que proporciono mi código fuente:

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
--use ieee.std_logic_arith.ALL;
use IEEE.NUMERIC_STD.ALL;

entity pe_element is
  port(
    --Output signals
    AD_o : out std_logic_vector(7 downto 0);
    SHIFT_CB_o : out std_logic_vector(7 downto 0);
    SHIFT_RB_o : out std_logic_vector(7 downto 0);
    --Input signals
    cb_en_i : in std_logic;
    rb_en_i : in std_logic;
    diff_en_i: in std_logic;
    clk_i : in std_logic;
    rst_i : in std_logic;
    CB_i : in std_logic_vector(7 downto 0);
    RB_i : in std_logic_vector(7 downto 0) 
  );
end pe_element;

architecture pe_element of pe_element is

--Define FSM states
type statetype is (S0, S1, S2, S3);
signal state, nextstate: statetype;

--Signal definitions
signal adder_tmp: std_logic_vector(8 downto 0);

-- That particular hack is a pretty annoying one. Idiots. 
signal am: integer;
signal bm: integer;
signal CBreg: std_logic_vector(7 downto 0);
signal RBreg: std_logic_vector(7 downto 0);

begin

-- Current State Register

process(clk_i)
  begin
    if clk_i'event and clk_i = '1' then
      if rst_i = '1' then
        state <= S0;
      else 
        state <= nextstate;
      end if;
    end if;
end process;

-- Next State Logic

process(state, diff_en_i, cb_en_i, rb_en_i) begin
  case state is
    when S0 => if diff_en_i = '0' and cb_en_i = '1' then nextstate <= S1;
               else nextstate <= S0;
               end if;
    when S1 => if diff_en_i = '0' and rb_en_i = '1' then nextstate <= S2;
               else nextstate <= S1;
               end if;
    when S2 => if diff_en_i = '1' and rb_en_i = '0' and cb_en_i = '0' then nextstate <= S3;
               else nextstate <= S2;
               end if;
    when S3 => if diff_en_i = '1' then nextstate <= S3;
               else nextstate <= S1;
               end if;
    when others => nextstate <= S0;
  end case;
end process;

-- Output Logic
am <= to_integer(signed(CB_i));
bm <= to_integer(signed(RB_i));


CBreg <= CB_i when
        ((state = S1) and cb_en_i='1');

SHIFT_CB_o <= CBreg when
           ((state = S1) and cb_en_i = '1');

RBreg <= RB_i when
        ((state = S2) and rb_en_i='1');

SHIFT_RB_o <= RBreg when
           ((state = S2) and rb_en_i = '1');

adder_tmp <= std_logic_vector(to_signed(abs((am - bm)),9)) when
           ((state = S3) and rb_en_i = '0' and cb_en_i = '0' and diff_en_i = '1')
           else "000000000";

AD_o <= adder_tmp(7 downto 0) when
           ((state = S3) and rb_en_i = '0' and cb_en_i = '0' and diff_en_i = '1')
           else "00000000";

end pe_element; 

Como se puede ver en la siguiente imagen de simulación, la salida de SHIFT mantiene solo el nuevo valor cada vez, y no el anterior.

Estoy bastante seguro de que he codificado algo mal, pero no puedo encontrarlo. ¿Tienes alguna idea?

    
pregunta Arkoudinos

1 respuesta

2

Parece que está intentando crear pestillos en la última sección usando when en sus declaraciones de asignación. Esta no es una práctica de diseño recomendada. Entre otras cosas, esto permite que los datos "fluyan" tan pronto como se cumplan las condiciones, que es lo que el simulador le muestra.

Si desea crear registros de canalización (disparados por el borde, maestro-esclavo), debe realizar esas asignaciones dentro de un proceso cronometrado.

EDITAR: Realmente no estoy siguiendo toda la complejidad de tu código. Si tuviera que hacer lo que creo que estás tratando de hacer, lo codificaría más así:

entity pe_element is
  port(
    --Output signals
    AD_o        : out std_logic_vector (7 downto 0);
    SHIFT_CB_o  : out std_logic_vector (7 downto 0);
    SHIFT_RB_o  : out std_logic_vector (7 downto 0);
    --Input signals
    cb_en_i     : in  std_logic;
    rb_en_i     : in  std_logic;
    diff_en_i   : in  std_logic;
    clk_i       : in  std_logic;
    rst_i       : in  std_logic;
    CB_i        : in  std_logic_vector (7 downto 0);
    RB_i        : in  std_logic_vector (7 downto 0) 
  );
end pe_element;

architecture pe_element of pe_element is

  --Signal definitions
  signal adder_tmp      : std_logic_vector (8 downto 0);

  -- That particular hack is a pretty annoying one. Idiots. 
  signal am             : integer;
  signal bm             : integer;

begin

  process (clk_i)
  begin
    if rising_edge(clk_i) then

      -- update CB pipeline
      if cb_en_i = '1' then
        SHIFT_CB_o <= CB_i;
      end if;

      -- update RB pipeline
      if rb_en_i = '1' then
        SHIFT_RB_o <= RB_i;
      end if;

      -- update output
      if diff_en_i = '1' then
        AD_o <= adder_tmp (7 downto 0);
      end if;

    end if;
  end process;

  -- Output Logic
  am <= to_integer(signed(CB_i));
  bm <= to_integer(signed(RB_i));
  adder_tmp <= std_logic_vector(to_signed(abs((am - bm)),9));

end pe_element; 
    
respondido por el Dave Tweed

Lea otras preguntas en las etiquetas