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;