Almacenamiento de valores en la variable fpga vhdl

1

Quiero desarrollar una aplicación que pueda obtener y almacenar dos valores de entrada y luego generar los dos valores almacenados. E.g .: La cadena de entrada es "John". La aplicación debería obtener "J" de user_w_write_8_data y almacenarla en my_buffer_1 , luego obtener "o" almacenarla en my_buffer_2 , luego generar "J", luego generar "o". Después de eso, la aplicación debería obtener "h" de user_w_write_8_data y almacenarla en my_buffer_1 , luego obtener "n" almacenarla en my_buffer_2 , luego generar "h", luego generar "n". Básicamente, la aplicación debe almacenar dos caracteres y luego generar estos dos, almacenar otros dos caracteres y luego generar estos dos caracteres, etc.

Como se sugirió, comencé desde la demostración de loopback de XillyBus ( xillydemo ) y luego debería encapsular su propia lógica en una entidad separada que reemplaza al FIFO fifo_8.

Primero creé la entidad my_buffer , que se utiliza para almacenar los datos que entran en el fifo y luego se imprimen.

EDIT 2: tuve que poner la instrucción if (counter=0) [my_buffer.vhd] porque cuando se ejecuta la simulación, el programa primero ejecuta esa instrucción if (counter=0) [my_buffer.vhd] y después de eso agrega las asignaciones de entrada para el siguiente flanco ascendente [my_buffer_tb.vhd]. Tenga en cuenta que el programa solo va una vez a if (counter=0) [my_buffer.vhd] (no hay counter <= 0 ).

Aquí el código:

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

entity my_buffer is
  port (
bus_clk             : in  std_logic;
reset_8             : in  std_logic;
-- Data from CPU via XillyBus
user_w_write_8_wren : in  std_logic;
user_w_write_8_full : out std_logic;
user_w_write_8_data : in  std_logic_vector(7 DOWNTO 0);
-- Data to CPU via XillyBus
user_r_read_8_rden  : in  std_logic;
user_r_read_8_empty : out std_logic;
user_r_read_8_data  : out std_logic_vector(7 DOWNTO 0));
end my_buffer;

architecture rtl of my_buffer is
signal tmp_1 : std_logic_vector(7 downto 0); --tmp for the first char
signal tmp_2 : std_logic_vector(7 downto 0); --tmp for the second char
signal counter : integer := 0; --counter used to control the if else statements

begin 

process (bus_clk)
   begin 
        if (bus_clk'event and bus_clk = '1') then 
              if (counter = 0) then --after this statement, the program adds input assigmnents for next rising edge here [my_buffer_tb.vhd] 
                 user_r_read_8_empty <= '0';
                 user_w_write_8_full <= '0';
                 counter <= 1;
              elsif (counter = 1) then --data valid on user_w_write_8_data
                 user_r_read_8_empty <= '0';
                 tmp_1 <= user_w_write_8_data; --store the first char
                 user_w_write_8_full <= '0';
                 counter <= 2;
              elsif (counter = 2) then --data valid on user_w_write_8_data
                 user_r_read_8_empty <= '1';
                 tmp_2 <= user_w_write_8_data; --store the second char
                 user_w_write_8_full <= '1';
                 counter <= 3;
              elsif (counter = 3) then
                 user_r_read_8_empty <= '1';
                 user_r_read_8_data <= tmp_1; --put the first char on xillybus_read_8
                 user_w_write_8_full <= '1';
                 counter <= 4;
              elsif (counter = 4) then
                 user_r_read_8_empty <= '0';
                 user_r_read_8_data <= tmp_2; --put the second char on xillybus_read_8
                 user_w_write_8_full <= '0';
                 counter <= 1;
              end if;

        end if;

 end process;
end rtl; 

LAS PREGUNTAS YA HAN SIDO RESPONDIDAS EN EL COMENTARIO (¡muchas gracias!):

1) La documentación de Xillybus explica que se usa user_w_write_8_full para informar que no se pueden aceptar más datos y que se debe establecer 1 solo cuando user_w_write_8_wren='1' . El problema en mi lógica es que cuando user_w_write_8_wren='1' tengo que almacenar datos en tmp_1 o tmp_2 . Entonces, cuando tengo que configurar user_w_write_8_full desde cuando user_w_write_8_wren='1' tengo que tomar datos?

2) La documentación de Xillybus explica que user_r_read_8_rden informa que los datos válidos están presentes en user_r_read_8_data . En mi lógica, parece que no tengo que tener cuidado cuando los datos están presentes en user_r_read_8_data . Bueno, cuando el programa está en elsif (counter = 2) then o elsif (counter = 3) then , tengo que poner los datos, almacenados en tmp_1 o tmp_2 , en el archivo del dispositivo xillybus_read_8. ¿Es la forma correcta de extraer datos de fifo (my_buffer) a un archivo de dispositivo xillybus_read_8?

3) La documentación de Xillybus explica que user_r_read_8_empty informa que no se pueden leer más datos. ¿Cuándo debo informarme cuando ya no se pueden leer más datos? ¿Mi lógica necesita esta información?

El siguiente código es xillydemo . He comentado las líneas de código que no uso. Como solo trabajo con los archivos de dispositivo xillybus_write_8 y xillybus_read_8 , comenté todas las señales relacionadas con 32 archivos de dispositivo y archivos de dispositivo mem. Además agregué el componente my_buffer.

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

entity xillydemo is
  port (
PCIE_PERST_B_LS : IN std_logic;
PCIE_REFCLK_N : IN std_logic;
PCIE_REFCLK_P : IN std_logic;
PCIE_RX_N : IN std_logic_vector(3 DOWNTO 0);
PCIE_RX_P : IN std_logic_vector(3 DOWNTO 0);
GPIO_LED : OUT std_logic_vector(3 DOWNTO 0);
PCIE_TX_N : OUT std_logic_vector(3 DOWNTO 0);
PCIE_TX_P : OUT std_logic_vector(3 DOWNTO 0));
end xillydemo;

architecture sample_arch of xillydemo is
  component xillybus
    port (
  PCIE_PERST_B_LS : IN std_logic;
  PCIE_REFCLK_N : IN std_logic;
  PCIE_REFCLK_P : IN std_logic;
  PCIE_RX_N : IN std_logic_vector(3 DOWNTO 0);
  PCIE_RX_P : IN std_logic_vector(3 DOWNTO 0);
  GPIO_LED : OUT std_logic_vector(3 DOWNTO 0);
  PCIE_TX_N : OUT std_logic_vector(3 DOWNTO 0);
  PCIE_TX_P : OUT std_logic_vector(3 DOWNTO 0);
  bus_clk : OUT std_logic;
  quiesce : OUT std_logic;
--      user_r_mem_8_rden : OUT std_logic;
--      user_r_mem_8_empty : IN std_logic;
--      user_r_mem_8_data : IN std_logic_vector(7 DOWNTO 0);
--      user_r_mem_8_eof : IN std_logic;
--      user_r_mem_8_open : OUT std_logic;
--      user_w_mem_8_wren : OUT std_logic;
--      user_w_mem_8_full : IN std_logic;
--      user_w_mem_8_data : OUT std_logic_vector(7 DOWNTO 0);
--      user_w_mem_8_open : OUT std_logic;
--      user_mem_8_addr : OUT std_logic_vector(4 DOWNTO 0);
--      user_mem_8_addr_update : OUT std_logic;
--      user_r_read_32_rden : OUT std_logic;
--      user_r_read_32_empty : IN std_logic;
--      user_r_read_32_data : IN std_logic_vector(31 DOWNTO 0);
--      user_r_read_32_eof : IN std_logic;
--      user_r_read_32_open : OUT std_logic;
  user_r_read_8_rden : OUT std_logic;
  user_r_read_8_empty : IN std_logic;
  user_r_read_8_data : IN std_logic_vector(7 DOWNTO 0);
  user_r_read_8_eof : IN std_logic;
  user_r_read_8_open : OUT std_logic;
--      user_w_write_32_wren : OUT std_logic;
--      user_w_write_32_full : IN std_logic;
--      user_w_write_32_data : OUT std_logic_vector(31 DOWNTO 0);
--      user_w_write_32_open : OUT std_logic;
  user_w_write_8_wren : OUT std_logic;
  user_w_write_8_full : IN std_logic;
  user_w_write_8_data : OUT std_logic_vector(7 DOWNTO 0);
  user_w_write_8_open : OUT std_logic);
  end component;

--  component fifo_8x2048
--    port (
--      clk: IN std_logic;
--      srst: IN std_logic;
--      din: IN std_logic_VECTOR(7 downto 0);
--      wr_en: IN std_logic;
--      rd_en: IN std_logic;
--      dout: OUT std_logic_VECTOR(7 downto 0);
--      full: OUT std_logic;
--      empty: OUT std_logic);
--  end component;

component my_buffer
port (
  bus_clk: IN std_logic;
  reset_8: IN std_logic;
  user_w_write_8_wren: IN std_logic;
  user_w_write_8_full: OUT std_logic;      
  user_w_write_8_data: IN std_logic_VECTOR(7 downto 0);
  user_r_read_8_rden: IN std_logic;
  user_r_read_8_empty: OUT std_logic;
  user_r_read_8_data: OUT std_logic_VECTOR(7 downto 0)
  );
end component;

--  component fifo_32x512
--    port (
--      clk: IN std_logic;
--      srst: IN std_logic;
--      din: IN std_logic_VECTOR(31 downto 0);
--      wr_en: IN std_logic;
--      rd_en: IN std_logic;
--      dout: OUT std_logic_VECTOR(31 downto 0);
--      full: OUT std_logic;
--      empty: OUT std_logic);
--  end component;

-- Synplicity black box declaration
  attribute syn_black_box : boolean;
--  attribute syn_black_box of fifo_32x512: component is true;
--  attribute syn_black_box of fifo_8x2048: component is true;

--  type demo_mem is array(0 TO 31) of std_logic_vector(7 DOWNTO 0);
--  signal demoarray : demo_mem;

  signal bus_clk :  std_logic;
  signal quiesce : std_logic;

  signal reset_8 : std_logic;
  signal reset_32 : std_logic;

  signal ram_addr : integer range 0 to 31;

--  signal user_r_mem_8_rden :  std_logic;
--  signal user_r_mem_8_empty :  std_logic;
--  signal user_r_mem_8_data :  std_logic_vector(7 DOWNTO 0);    
--  signal user_r_mem_8_eof :  std_logic;
--  signal user_r_mem_8_open :  std_logic;
--  signal user_w_mem_8_wren :  std_logic;
--  signal user_w_mem_8_full :  std_logic;
--  signal user_w_mem_8_data :  std_logic_vector(7 DOWNTO 0);
--  signal user_w_mem_8_open :  std_logic;
--  signal user_mem_8_addr :  std_logic_vector(4 DOWNTO 0);
--  signal user_mem_8_addr_update :  std_logic;
--  signal user_r_read_32_rden :  std_logic;
--  signal user_r_read_32_empty :  std_logic;
--  signal user_r_read_32_data :  std_logic_vector(31 DOWNTO 0);
--  signal user_r_read_32_eof :  std_logic;
--  signal user_r_read_32_open :  std_logic;
  signal user_r_read_8_rden :  std_logic;
  signal user_r_read_8_empty :  std_logic;
 signal user_r_read_8_data :  std_logic_vector(7 DOWNTO 0);
  signal user_r_read_8_eof :  std_logic;
  signal user_r_read_8_open :  std_logic;
--  signal user_w_write_32_wren :  std_logic;
--  signal user_w_write_32_full :  std_logic;
--  signal user_w_write_32_data :  std_logic_vector(31 DOWNTO 0);
--  signal user_w_write_32_open :  std_logic;
  signal user_w_write_8_wren :  std_logic;
  signal user_w_write_8_full :  std_logic;
  signal user_w_write_8_data :  std_logic_vector(7 DOWNTO 0);
  signal user_w_write_8_open :  std_logic;

begin
  xillybus_ins : xillybus
port map (
  -- Ports related to /dev/xillybus_mem_8
  -- FPGA to CPU signals:
--      user_r_mem_8_rden => user_r_mem_8_rden,
--      user_r_mem_8_empty => user_r_mem_8_empty,
--      user_r_mem_8_data => user_r_mem_8_data,
--      user_r_mem_8_eof => user_r_mem_8_eof,
--      user_r_mem_8_open => user_r_mem_8_open,
  -- CPU to FPGA signals:
--      user_w_mem_8_wren => user_w_mem_8_wren,
--      user_w_mem_8_full => user_w_mem_8_full,
--      user_w_mem_8_data => user_w_mem_8_data,
--      user_w_mem_8_open => user_w_mem_8_open,
  -- Address signals:
--      user_mem_8_addr => user_mem_8_addr,
--      user_mem_8_addr_update => user_mem_8_addr_update,

  -- Ports related to /dev/xillybus_read_32
  -- FPGA to CPU signals:
--      user_r_read_32_rden => user_r_read_32_rden,
--      user_r_read_32_empty => user_r_read_32_empty,
--      user_r_read_32_data => user_r_read_32_data,
--      user_r_read_32_eof => user_r_read_32_eof,
--      user_r_read_32_open => user_r_read_32_open,

  -- Ports related to /dev/xillybus_read_8
  -- FPGA to CPU signals:
  user_r_read_8_rden => user_r_read_8_rden,
  user_r_read_8_empty => user_r_read_8_empty,
  user_r_read_8_data => user_r_read_8_data,
  user_r_read_8_eof => user_r_read_8_eof,
  user_r_read_8_open => user_r_read_8_open,

  -- Ports related to /dev/xillybus_write_32
  -- CPU to FPGA signals:
--      user_w_write_32_wren => user_w_write_32_wren,
--      user_w_write_32_full => user_w_write_32_full,
--      user_w_write_32_data => user_w_write_32_data,
--      user_w_write_32_open => user_w_write_32_open,

  -- Ports related to /dev/xillybus_write_8
  -- CPU to FPGA signals:
  user_w_write_8_wren => user_w_write_8_wren,
  user_w_write_8_full => user_w_write_8_full,
  user_w_write_8_data => user_w_write_8_data,
  user_w_write_8_open => user_w_write_8_open,

  -- General signals
  PCIE_PERST_B_LS => PCIE_PERST_B_LS,
  PCIE_REFCLK_N => PCIE_REFCLK_N,
  PCIE_REFCLK_P => PCIE_REFCLK_P,
  PCIE_RX_N => PCIE_RX_N,
  PCIE_RX_P => PCIE_RX_P,
  GPIO_LED => GPIO_LED,
  PCIE_TX_N => PCIE_TX_N,
  PCIE_TX_P => PCIE_TX_P,
  bus_clk => bus_clk,
  quiesce => quiesce
  );

--  A simple inferred RAM

--  ram_addr <= conv_integer(user_mem_8_addr);

  process (bus_clk)
  begin
    if (bus_clk'event and bus_clk = '1') then
--      if (user_w_mem_8_wren = '1') then 
--        demoarray(ram_addr) <= user_w_mem_8_data;
--      end if;
--      if (user_r_mem_8_rden = '1') then
--        user_r_mem_8_data <= demoarray(ram_addr);
--      end if;
end if;
  end process;

--  user_r_mem_8_empty <= '0';
--  user_r_mem_8_eof <= '0';
--  user_w_mem_8_full <= '0';

--  32-bit loopback

--  fifo_32 : fifo_32x512
--    port map(
--      clk        => bus_clk,
--      srst       => reset_32,
--      din        => user_w_write_32_data,
--      wr_en      => user_w_write_32_wren,
--      rd_en      => user_r_read_32_rden,
--      dout       => user_r_read_32_data,
--      full       => user_w_write_32_full,
--      empty      => user_r_read_32_empty
--      );

--  reset_32 <= not (user_w_write_32_open or user_r_read_32_open);

--  user_r_read_32_eof <= '0';

--  8-bit loopback

--  fifo_8 : fifo_8x2048
--    port map(
--      clk        => bus_clk,
--      srst       => reset_8,
--      din        => user_w_write_8_data,
--      wr_en      => user_w_write_8_wren,
--      rd_en      => user_r_read_8_rden,
--      dout       => user_r_read_8_data,
--      full       => user_w_write_8_full,
--      empty      => user_r_read_8_empty
--      );

--    reset_8 <= not (user_w_write_8_open or user_r_read_8_open);
--    user_r_read_8_eof <= '0';


my_buffer_1: my_buffer
  port map (
bus_clk             => bus_clk,
reset_8             => reset_8,
user_w_write_8_wren => user_w_write_8_wren,
user_w_write_8_full => user_w_write_8_full,
user_w_write_8_data => user_w_write_8_data,
user_r_read_8_rden  => user_r_read_8_rden,
user_r_read_8_empty => user_r_read_8_empty,
user_r_read_8_data  => user_r_read_8_data);

-- these lines must be preserved in the XillyDemo
reset_8 <= not (user_w_write_8_open or user_r_read_8_open);
user_r_read_8_eof <= user_r_read_8_empty and not(user_w_write_8_open);

end sample_arch;

EDIT 2: Test bench. El problema es que durante la simulación todos los valores de entrada y salida son correctos, pero cuando genero el archivo de bits y ejecuto este programa en FPGA, los valores de salida son totalmente incorrectos . Tenga en cuenta que durante la simulación, el programa asigna los valores correctos a tmp_1 y tmp_2 . En este banco de pruebas el programa:

-ejecuta if (counter = 0) enunciados (básicamente no hace nada). De esta manera, durante el siguiente ciclo de reloj, el programa inicializa las señales como se describe en my_buffer_tb.vhd
-escribe 3 (00000011) en tmp_1
-escribe 4 (00000100) en tmp_2
-escribe 3 (00000011) en user_r_read_8_data
-escribe 4 (00000100) en user_r_read_8_data

-escribe 5 (00000101) en tmp_1
-escribe 6 (00000110) en tmp_2
-escribe 5 (00000101) en user_r_read_8_data
-escribe 6 (00000110) en user_r_read_8_data

Aquí el código:

library ieee;
use ieee.std_logic_1164.all;

entity my_buffer_tb is
end my_buffer_tb;

architecture sim of my_buffer_tb is
  signal bus_clk             : std_logic := '1';
  signal reset_8             : std_logic;
  signal user_w_write_8_wren : std_logic;
  signal user_w_write_8_full : std_logic;
  signal user_w_write_8_data : std_logic_vector(7 DOWNTO 0);
  signal user_r_read_8_rden  : std_logic;
  signal user_r_read_8_empty : std_logic;
  signal user_r_read_8_data  : std_logic_vector(7 DOWNTO 0);
begin
  -- component instantiation
  DUT: entity work.my_buffer
port map (
  bus_clk             => bus_clk,
  reset_8             => reset_8,
  user_w_write_8_wren => user_w_write_8_wren,
  user_w_write_8_full => user_w_write_8_full,
  user_w_write_8_data => user_w_write_8_data,
  user_r_read_8_rden  => user_r_read_8_rden,
  user_r_read_8_empty => user_r_read_8_empty,
  user_r_read_8_data  => user_r_read_8_data);

  -- clock generation
  bus_clk <= not bus_clk after 5 ns;

  -- waveform generation
  WaveGen_Proc: process
  begin
-- Input values sampled by the DUT with the first rising edge of bus_clk
reset_8 <= '1';                     -- apply reset
-- other input values don't care during reset
wait until rising_edge(bus_clk);

-- Input values sampled by DUT with second rising edge of bus_clk
--    reset_8 <= '0';
--    user_w_write_8_wren <= '0';
--    user_w_write_8_data <= (others => '-');
--    user_r_read_8_rden  <= '0';
--    wait until rising_edge(bus_clk);

--FIRST BUFFER

-- Add input assigmnents for next rising edge here
reset_8 <= '0';
user_w_write_8_wren <= '1';
user_r_read_8_empty <= '0';
user_w_write_8_full <= '0';
user_w_write_8_data <= "00000011"; --3
wait until rising_edge(bus_clk);

-- Add input assigmnents for next rising edge here
reset_8 <= '0';
user_w_write_8_wren <= '1';
user_r_read_8_empty <= '1';
user_w_write_8_full <= '1';
user_w_write_8_data <= "00000100"; --4
wait until rising_edge(bus_clk);

-- Add input assigmnents for next rising edge here
reset_8 <= '0';
user_w_write_8_wren <= '0';
user_r_read_8_empty <= '1';
user_w_write_8_full <= '1';
wait until rising_edge(bus_clk);

-- Add input assigmnents for next rising edge here
reset_8 <= '0';
user_w_write_8_wren <= '0';
user_r_read_8_empty <= '0';
user_w_write_8_full <= '0';
wait until rising_edge(bus_clk);


--SECOND BUFFER

-- Add input assigmnents for next rising edge here
reset_8 <= '0';
user_w_write_8_wren <= '1';
user_r_read_8_empty <= '0';
user_w_write_8_full <= '0';
user_w_write_8_data <= "00000101"; --5
wait until rising_edge(bus_clk);

-- Add input assigmnents for next rising edge here
reset_8 <= '0';
user_w_write_8_wren <= '1';
user_r_read_8_empty <= '1';
user_w_write_8_full <= '1';
user_w_write_8_data <= "00000110"; --6
wait until rising_edge(bus_clk);

-- Add input assigmnents for next rising edge here
reset_8 <= '0';
user_w_write_8_wren <= '0';
user_r_read_8_empty <= '1';
user_w_write_8_full <= '1';
wait until rising_edge(bus_clk);

-- Add input assigmnents for next rising edge here
reset_8 <= '0';
user_w_write_8_wren <= '0';
user_r_read_8_empty <= '0';
user_w_write_8_full <= '0';
wait until rising_edge(bus_clk);     


-- finished
wait;
  end process WaveGen_Proc;
end sim;

Nuevamente, durante la simulación, los valores de la señal están bien, pero cuando genero el archivo de bits y ejecuto este programa en FPGA, los valores de salida son totalmente erróneos. ¿Dónde estoy equivocado?

EDIT 3: aquí, la lógica después de las sugerencias edit 2 :

begin 

process (bus_clk)
begin 
   if (bus_clk'event and bus_clk = '1') then
      if (reset_8 = '1') then
         -- reset has highest priority, initalize all state registers
         user_r_read_8_empty <= '1';  -- no data available
         user_w_write_8_full <= '1';  -- not ready yet
         counter <= 0;                -- counter starts at 0

      elsif (counter = 0) then
         -- just signal that we are ready for accepting data in the following cycle  
         user_w_write_8_full <= '0';
         counter <= 1;

      elsif (counter = 1) then
         -- wait for first byte!
         if user_w_write_8_wren = '1' then
            tmp_1 <= user_w_write_8_data; -- store the first char
            -- user_w_write_8_full is kept low, thus, we are ready for accepting more data
            counter <= 2;
         end if;

      elsif (counter = 2) then
         if user_w_write_8_wren = '1' then
            tmp_2 <= user_w_write_8_data; -- store the eighth char
            user_w_write_8_full <= '1';   -- now our data buffers are full
            user_r_read_8_empty <= '0';  -- we are ready for reading in the next cycle
            counter <= 3;
         end if;          


      elsif (counter = 3) then
          if user_r_read_8_rden = '1' then 
             user_r_read_8_data <= tmp_1;
             counter <= 4;
          end if;      

      elsif (counter = 4) then
        if user_r_read_8_rden = '1' then 
            user_r_read_8_data <= tmp_2;
            user_w_write_8_full <= '0';
            user_r_read_8_empty <= '1';
            counter <= 0;
        end if;  
      end if;
   end if;
end process;
end rtl;
    
pregunta Message Passing

1 respuesta

1

Recomiendo reiniciar desde la demostración de loopback de XillyBus ( xillydemo ). Entonces debes encapsular tu propia lógica en una entidad separada, llamémosla my_buffer . Esta entidad reemplazará la instanciación del componente fifo_8 . Es decir, su componente tomará directamente la entrada del XillyBus y la salida también estará directamente relacionada con el XillyBus.

Como my_buffer reemplazará a FIFO, tiene que manejar todas las señales de control y datos relacionadas con FIFO. Por lo tanto, debe crear un nuevo archivo (por ejemplo, my_buffer.vhdl ) y comenzar con esta implementación; Por supuesto, debes agregar tu lógica personalizada:

library ieee;
use ieee.std_logic_1164.all;

entity my_buffer is
  port (
    bus_clk             : in  std_logic;
    reset_8             : in  std_logic;
    -- Data from CPU via XillyBus
    user_w_write_8_wren : in  std_logic;
    user_w_write_8_full : out std_logic;
    user_w_write_8_data : in  std_logic_vector(7 DOWNTO 0);
    -- Data to CPU via XillyBus
    user_r_read_8_rden  : in  std_logic;
    user_r_read_8_empty : out std_logic;
    user_r_read_8_data  : out std_logic_vector(7 DOWNTO 0));
end my_buffer;

architecture rtl of my_buffer is
begin  -- rtl

  -- add custom logic here

end rtl;

Esta entidad puede crear una instancia en la arquitectura de xillydemo con:

my_buffer_1: my_buffer
  port map (
    bus_clk             => bus_clk,
    reset_8             => reset_8,
    user_w_write_8_wren => user_w_write_8_wren,
    user_w_write_8_full => user_w_write_8_full,
    user_w_write_8_data => user_w_write_8_data,
    user_r_read_8_rden  => user_r_read_8_rden,
    user_r_read_8_empty => user_r_read_8_empty,
    user_r_read_8_data  => user_r_read_8_data);

-- these lines must be preserved in the XillyDemo
reset_8 <= not (user_w_write_8_open or user_r_read_8_open);
user_r_read_8_eof <= user_r_read_8_empty and not(user_w_write_8_open);

Antes, usted sintetiza xillydemo , debe verificar su implementación de my_buffer por simulación. Cree un nuevo archivo (por ejemplo, my_buffer_tb.vhdl ) y comience con la siguiente implementación de un banco de pruebas. Este banco de pruebas proporciona las entradas del XillyBus para cada ciclo de reloj. Luego puede verificar la respuesta de su entidad (instanciada como DUT ) y compararla con la documentación de XillyBus. Ya he agregado las asignaciones de entrada para los dos primeros ciclos de reloj. Simplemente continúa de la misma manera.

library ieee;
use ieee.std_logic_1164.all;

entity my_buffer_tb is
end my_buffer_tb;

architecture sim of my_buffer_tb is
  signal bus_clk             : std_logic := '1';
  signal reset_8             : std_logic;
  signal user_w_write_8_wren : std_logic;
  signal user_w_write_8_full : std_logic;
  signal user_w_write_8_data : std_logic_vector(7 DOWNTO 0);
  signal user_r_read_8_rden  : std_logic;
  signal user_r_read_8_empty : std_logic;
  signal user_r_read_8_data  : std_logic_vector(7 DOWNTO 0);
begin
  -- component instantiation
  DUT: entity work.my_buffer
    port map (
      bus_clk             => bus_clk,
      reset_8             => reset_8,
      user_w_write_8_wren => user_w_write_8_wren,
      user_w_write_8_full => user_w_write_8_full,
      user_w_write_8_data => user_w_write_8_data,
      user_r_read_8_rden  => user_r_read_8_rden,
      user_r_read_8_empty => user_r_read_8_empty,
      user_r_read_8_data  => user_r_read_8_data);

  -- clock generation
  bus_clk <= not bus_clk after 5 ns;

  -- waveform generation
  WaveGen_Proc: process
  begin
    -- Input values sampled by the DUT with the first rising edge of bus_clk
    reset_8 <= '1';                     -- apply reset
    -- other input values don't care during reset
    wait until rising_edge(bus_clk);

    -- Input values sampled by DUT with second rising edge of bus_clk
    reset_8 <= '0';
    user_w_write_8_wren <= '0';
    user_w_write_8_data <= (others => '-');
    user_r_read_8_rden  <= '0';
    wait until rising_edge(bus_clk);

    -- Add input assigmnents for next rising edge here

    -- finished
    wait;
  end process WaveGen_Proc;
end sim;

Después de modificar la pregunta:

1) Si implementa la señal full con un registro, inicialícelo a bajo. Cuando XillyBus escribe el primer valor, manténgalo bajo. Cuando XillyBus escribe el segundo, configúrelo en alto (en el flanco ascendente del reloj) porque su búfer no aceptará valores en los estados de contador subsiguientes. Cuando regrese al contador 0 también ajuste el registro completo a bajo. Puedes ignorar wren high de XillyBus cuando generas full = high desde tu búfer.

2) La señal rden es controlada por XillyBus, no por su búfer. No se activa el nivel alto hasta que las señales del búfer se vacían bajo (ver más abajo). Cuando rden es alto, su búfer debe presentar los datos en el siguiente ciclo de reloj.

3) La señal empty indica que los datos están disponibles desde su búfer, de modo que XillyBus puede leerlos (indicado por rden ).

Sugerencias sobre la "Edición 2" de la pregunta:

Al principio, el banco de pruebas es incorrecto porque asignó la salida empty en lugar de la entrada rden de su búfer en el banco de pruebas.

Luego, el banco de pruebas es demasiado simple para detectar los errores en su implementación de my_buffer . reset_8 se aplica solo para un ciclo, pero puede aplicarse para muchos ciclos. Además, su banco de pruebas no incluye suficientes ciclos de inactividad, donde tanto rden como wren son bajos. Puede y habrá un número arbitrario de ciclos de inactividad antes de la primera escritura (CPU- > FPGA) entre el primer y segundo byte, y también entre escritura y lectura y viceversa.

Por lo tanto, el banco de pruebas no reveló que se olvidó de verificar reset , rden y wren en la implementación de my_buffer . Para darle una pista, el proceso en my_buffer debería comenzar así:

process (bus_clk)
begin 
   if (bus_clk'event and bus_clk = '1') then
      if reset_8 = '1' then
         -- reset has highest priority, initalize all state registers
         user_r_read_8_empty <= '1';  -- no data available
         user_w_write_8_full <= '1';  -- not ready yet
         counter <= 0;                -- counter starts at 0

      elsif (counter = 0) then
         -- just signal that we are ready for accepting data in the following cycle  
         user_w_write_8_full <= '0';
         counter <= 1;

      elsif (counter = 1) then
         -- wait for first byte!
         if user_w_write_8_wren = '1' then
            tmp_1 <= user_w_write_8_data; -- store the first char
            -- user_w_write_8_full is kept low, thus, we are ready for accepting more data
            counter <= 2;
         end if;

      elsif (counter = 2) then
         -- wait for second byte!
         if user_w_write_8_wren = '1' then
            tmp_2 <= user_w_write_8_data; -- store the second char
            user_w_write_8_full <= '1';   -- now our data buffers are full
            user_r_read_8_empty <= '0';  -- we are ready for reading in the next cycle
            counter <= 3;
         end if;

      -- and so on

En el banco de pruebas, se requiere al menos un ciclo inactivo después del restablecimiento porque, full se inicializa a alto y baja un ciclo más tarde.

También tenga en cuenta que he eliminado los requisitos de registro innecesarios. Los registros conservan sus valores, si no se les asigna un nuevo valor en el ciclo del reloj actual.

    
respondido por el Martin Zabel

Lea otras preguntas en las etiquetas