EmbDev.net

Forum: FPGA, VHDL & Verilog Connect 2 FIFOs and pass data [xillybus - VHDL]


Author: Junior Hpc (Company: University) (junior_hpc)
Posted on:
Attached files:

Rate this post
0 useful
not useful
Hello. My application is based on xillybus because I have to take data 
from a Linux machine, process it on FPGA and pass it back to linux 
machine. In particular, my application uses 2 FIFOs. One to receive data 
from PCI, and one to store data to send to PCI. In between there is the 
logic to process data.

The figure "schema" summarizes the data flow of my application. So, 
xillybus is used to pass data from and to PCI and the 2 FIFOs are used 
to take data from xillybus, process it and pass it back to xillybus.

In order to solve this problem I used the FIFO from this [link 1]. Here 
the code in STD_FIFO.vhd:
library IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;

entity STD_FIFO is
  Generic (
    constant DATA_WIDTH  : positive := 8;
    constant FIFO_DEPTH  : positive := 256
  );
  Port ( 
    CLK    : in  STD_LOGIC;
    RST    : in  STD_LOGIC;
    WriteEn  : in  STD_LOGIC;
    DataIn  : in  STD_LOGIC_VECTOR (DATA_WIDTH - 1 downto 0);
    ReadEn  : in  STD_LOGIC;
    DataOut  : out STD_LOGIC_VECTOR (DATA_WIDTH - 1 downto 0);
    Empty  : out STD_LOGIC;
    Full  : out STD_LOGIC
  );
end STD_FIFO;

architecture Behavioral of STD_FIFO is

begin

  -- Memory Pointer Process
  fifo_proc : process (CLK)
    type FIFO_Memory is array (0 to FIFO_DEPTH - 1) of STD_LOGIC_VECTOR (DATA_WIDTH - 1 downto 0);
    variable Memory : FIFO_Memory;
    
    variable Head : natural range 0 to FIFO_DEPTH - 1;
    variable Tail : natural range 0 to FIFO_DEPTH - 1;
    
    variable Looped : boolean;
  begin
    if rising_edge(CLK) then
      if RST = '1' then
        Head := 0;
        Tail := 0;
        
        Looped := false;
        
        Full  <= '0';
        Empty <= '1';
      else
        if (ReadEn = '1') then
          if ((Looped = true) or (Head /= Tail)) then
            -- Update data output
            DataOut <= Memory(Tail);
            
            -- Update Tail pointer as needed
            if (Tail = FIFO_DEPTH - 1) then
              Tail := 0;
              
              Looped := false;
            else
              Tail := Tail + 1;
            end if;
            
            
          end if;
        end if;
        
        if (WriteEn = '1') then
          if ((Looped = false) or (Head /= Tail)) then
            -- Write Data to Memory
            Memory(Head) := DataIn;
            
            -- Increment Head pointer as needed
            if (Head = FIFO_DEPTH - 1) then
              Head := 0;
              
              Looped := true;
            else
              Head := Head + 1;
            end if;
          end if;
        end if;
        
        -- Update Empty and Full flags
        if (Head = Tail) then
          if Looped then
            Full <= '1';
          else
            Empty <= '1';
          end if;
        else
          Empty  <= '0';
          Full  <= '0';
        end if;
      end if;
    end if;
  end process;
    
end Behavioral;

In this [link 2] I understood that it is not possible to connect the 
FIFOs as shown in Figure 1 because of possible problem of handshake 
mechanism. As workaround, the previous link provides the VHDL code to 
convert a standard dual port FIFO into an Autonomous Cascadable Dual 
Port FIFO. The Figure 2 shows how to convert a standard dual port FIFO 
into an Autonomous Cascadable Dual Port FIFO.

The VHDL code of the Autonomous Cascadable Dual Port FIFO is 
ac_fifo_wrap.vhd (in which I have already included the STD_FIFO):
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;

ENTITY ac_fifo_wrap IS
  GENERIC(
          --== Data Width ==--
          data_width : NATURAL := 8
         );
  PORT(
       --==  General Interface ==--
       rst    : IN  STD_LOGIC;
       clk    : IN  STD_LOGIC;

       --== Input Interface ==--
       nwrite : IN  STD_LOGIC;
       full   : OUT STD_LOGIC;
       din    : IN  STD_LOGIC_VECTOR(data_width-1 DOWNTO 0);

       --== Output Interface ==--
       empty  : OUT STD_LOGIC;
       nread  : IN  STD_LOGIC;
       dout   : OUT STD_LOGIC_VECTOR(data_width-1 DOWNTO 0)
      );
END ac_fifo_wrap;


ARCHITECTURE rtl OF ac_fifo_wrap IS

---==========================---
--== Component Declarations ==--
---==========================---


component STD_FIFO
port (
  CLK: IN std_logic;
  RST: IN std_logic;
  WriteEn: IN std_logic;
  DataIn: IN std_logic_VECTOR(7 downto 0);
  ReadEn: IN std_logic;
  DataOut: OUT std_logic_VECTOR(7 downto 0);
  Empty: OUT std_logic;
  Full: OUT std_logic
);
end component;

---=======================---
--== Signal Declarations ==--
---=======================---

SIGNAL empty_int : STD_LOGIC;
SIGNAL empty_i   : STD_LOGIC;
SIGNAL full_i    : STD_LOGIC;
SIGNAL rd_en     : STD_LOGIC;
SIGNAL wr_en     : STD_LOGIC;

BEGIN

  ---====================---
  --== FIFO write logic ==--
  ---====================---

  wr_en <= NOT(full_i) AND NOT(nwrite);

  full <= full_i;

  ---================================---
  --== STD_FIFO (CoreGen Module) ==--
  ---================================---

      -- CPU to FPGA FIFO
      U0: STD_FIFO
      port map(
        RST       => rst,
        CLK       => clk,
        WriteEn    => wr_en,
        Full      => full_i,
        DataIn       => din,
        Empty     => empty_int,
        ReadEn     => rd_en,
        DataOut      => dout
      );


  ---===================---
  --== FIFO read logic ==--
  ---===================---

  rd_en <= NOT(empty_int) AND (empty_i OR NOT(nread));

  PROCESS(clk)
  BEGIN
    IF RISING_EDGE(clk) THEN
      IF (rst = '1') THEN
        empty_i <= '1';
      ELSE
        empty_i <= empty_int AND (empty_i OR NOT(nread));
      END IF;
    END IF;
  END PROCESS;

  empty <= empty_i;

END rtl;



What I have done:

in ac_fifo_wrap I defined the component STD_FIFO. In this way I 
connected Autonomous Cascadable Dual Port FIFO (ac_fifo_wrap) with the 
dual port FIFO (STD_FIFO).

In xillydemo.vhd I defined 2 ac_fifo_wrap, ac_fifo_wrap_write and 
ac_fifo_wrap_read respectively. In this way I have 2 FIFOs connected and 
I should not have handshake problem. Here xillydemo.vhd:
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_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_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 ac_fifo_wrap
port (
  --==  General Interface ==--
  RST: IN std_logic;
  CLK: IN std_logic;
  
  --== Input Interface ==--
  nwrite: IN std_logic;
  full: OUT std_logic;
  din: IN std_logic_VECTOR(7 downto 0);
  
  --== Output Interface ==--
  empty: OUT std_logic;
  nread: IN std_logic;
  dout: OUT std_logic_VECTOR(7 downto 0) 
);
end component;


  signal bus_clk :  std_logic;
  signal quiesce : std_logic;

  signal reset_8 : 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_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;
  
  signal s_dout_din : std_logic_vector(7 DOWNTO 0);
  signal s_nread_full :  std_logic;
  signal s_empty_nwrite :  std_logic;
  
begin
  xillybus_ins : xillybus
port map (
  

  -- 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_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
  );
  
  
-- CPU to FPGA FIFO
ac_fifo_wrap_write: ac_fifo_wrap
port map(
  RST       => reset_8,
  CLK       => bus_clk,
  nwrite    => not user_w_write_8_wren,
  full      => user_w_write_8_full,
  din       => user_w_write_8_data,
  empty     => s_empty_nwrite, --
  nread     => s_nread_full, --
  dout      => s_dout_din--
);
  
-- FPGA to CPU FIFO  
ac_fifo_wrap_read: ac_fifo_wrap
  port map(
    RST       => reset_8,
    CLK       => bus_clk,
    nwrite    => s_empty_nwrite, --
    full      => s_nread_full, --
    din       => s_dout_din, --
    empty     => user_r_read_8_empty,
    nread     => not user_r_read_8_rden,
    dout      => 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;

Problem: Now I have to test my code and I wrote this test but it does 
not work. Vivado suite says to check in log file but in the log file 
there are no errors. I think I messed up with signals. Here the code. 
Any hint?
library ieee;
use ieee.std_logic_1164.all;

entity my_buffer_tb is
end my_buffer_tb;

architecture sim of ac_fifo_wrap_tb is
  signal clk        : std_logic := '1';
  signal rst        : std_logic;
  signal nwrite     : std_logic;
  signal full       : std_logic;
  signal din        : std_logic_vector(7 DOWNTO 0);
  signal nread      : std_logic;
  signal empty      : std_logic;
  signal dout       : std_logic_vector(7 DOWNTO 0);
begin
  -- component instantiation
  DUT: entity work.ac_fifo_wrap
    port map (
      clk       => bus_clk,
      rst       => reset_8,
      nwrite    => user_w_write_8_wren,
      full      => user_w_write_8_full,
      din       => user_w_write_8_data,
      nread     => user_r_read_8_rden,
      empty     => user_r_read_8_empty,
      dout      => user_r_read_8_data);

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

  -- waveform generation
  WaveGen_Proc: process
  begin
    rst  <= '1';                     -- apply reset
    -- other input values don't care during reset
    wait until rising_edge(clk);

    -- Endless idle cycles
    rst <= '0';
    nwrite <= '0';
    din <= (others => '-');
    nread  <= '0';
    wait;
  end process WaveGen_Proc;
end sim;



[link 1]: http://www.deathbylogic.com/2013/07/vhdl-standard-fifo/
[link 2]: http://www.spacewire.co.uk/auto_fifo.html

: Edited by User

Reply

Entering an e-mail address is optional. If you want to receive reply notifications by e-mail, please log in.

Rules — please read before posting

  • Post long source code as attachment, not in the text
  • Posting advertisements is forbidden.

Formatting options

  • [c]C code[/c]
  • [avrasm]AVR assembler code[/avrasm]
  • [vhdl]VHDL code[/vhdl]
  • [code]code in other languages, ASCII drawings[/code]
  • [math]formula (LaTeX syntax)[/math]




Bild automatisch verkleinern, falls nötig
Note: the original post is older than 6 months. Please don't ask any new questions in this thread, but start a new one.