EmbDev.net

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


von Junior H. (Company: University) (junior_hpc)


Attached files:

Rate this post
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:
1
library IEEE;
2
USE IEEE.STD_LOGIC_1164.ALL;
3
USE IEEE.NUMERIC_STD.ALL;
4
5
entity STD_FIFO is
6
  Generic (
7
    constant DATA_WIDTH  : positive := 8;
8
    constant FIFO_DEPTH  : positive := 256
9
  );
10
  Port ( 
11
    CLK    : in  STD_LOGIC;
12
    RST    : in  STD_LOGIC;
13
    WriteEn  : in  STD_LOGIC;
14
    DataIn  : in  STD_LOGIC_VECTOR (DATA_WIDTH - 1 downto 0);
15
    ReadEn  : in  STD_LOGIC;
16
    DataOut  : out STD_LOGIC_VECTOR (DATA_WIDTH - 1 downto 0);
17
    Empty  : out STD_LOGIC;
18
    Full  : out STD_LOGIC
19
  );
20
end STD_FIFO;
21
22
architecture Behavioral of STD_FIFO is
23
24
begin
25
26
  -- Memory Pointer Process
27
  fifo_proc : process (CLK)
28
    type FIFO_Memory is array (0 to FIFO_DEPTH - 1) of STD_LOGIC_VECTOR (DATA_WIDTH - 1 downto 0);
29
    variable Memory : FIFO_Memory;
30
    
31
    variable Head : natural range 0 to FIFO_DEPTH - 1;
32
    variable Tail : natural range 0 to FIFO_DEPTH - 1;
33
    
34
    variable Looped : boolean;
35
  begin
36
    if rising_edge(CLK) then
37
      if RST = '1' then
38
        Head := 0;
39
        Tail := 0;
40
        
41
        Looped := false;
42
        
43
        Full  <= '0';
44
        Empty <= '1';
45
      else
46
        if (ReadEn = '1') then
47
          if ((Looped = true) or (Head /= Tail)) then
48
            -- Update data output
49
            DataOut <= Memory(Tail);
50
            
51
            -- Update Tail pointer as needed
52
            if (Tail = FIFO_DEPTH - 1) then
53
              Tail := 0;
54
              
55
              Looped := false;
56
            else
57
              Tail := Tail + 1;
58
            end if;
59
            
60
            
61
          end if;
62
        end if;
63
        
64
        if (WriteEn = '1') then
65
          if ((Looped = false) or (Head /= Tail)) then
66
            -- Write Data to Memory
67
            Memory(Head) := DataIn;
68
            
69
            -- Increment Head pointer as needed
70
            if (Head = FIFO_DEPTH - 1) then
71
              Head := 0;
72
              
73
              Looped := true;
74
            else
75
              Head := Head + 1;
76
            end if;
77
          end if;
78
        end if;
79
        
80
        -- Update Empty and Full flags
81
        if (Head = Tail) then
82
          if Looped then
83
            Full <= '1';
84
          else
85
            Empty <= '1';
86
          end if;
87
        else
88
          Empty  <= '0';
89
          Full  <= '0';
90
        end if;
91
      end if;
92
    end if;
93
  end process;
94
    
95
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):
1
LIBRARY IEEE;
2
USE IEEE.STD_LOGIC_1164.ALL;
3
4
ENTITY ac_fifo_wrap IS
5
  GENERIC(
6
          --== Data Width ==--
7
          data_width : NATURAL := 8
8
         );
9
  PORT(
10
       --==  General Interface ==--
11
       rst    : IN  STD_LOGIC;
12
       clk    : IN  STD_LOGIC;
13
14
       --== Input Interface ==--
15
       nwrite : IN  STD_LOGIC;
16
       full   : OUT STD_LOGIC;
17
       din    : IN  STD_LOGIC_VECTOR(data_width-1 DOWNTO 0);
18
19
       --== Output Interface ==--
20
       empty  : OUT STD_LOGIC;
21
       nread  : IN  STD_LOGIC;
22
       dout   : OUT STD_LOGIC_VECTOR(data_width-1 DOWNTO 0)
23
      );
24
END ac_fifo_wrap;
25
26
27
ARCHITECTURE rtl OF ac_fifo_wrap IS
28
29
---==========================---
30
--== Component Declarations ==--
31
---==========================---
32
33
34
component STD_FIFO
35
port (
36
  CLK: IN std_logic;
37
  RST: IN std_logic;
38
  WriteEn: IN std_logic;
39
  DataIn: IN std_logic_VECTOR(7 downto 0);
40
  ReadEn: IN std_logic;
41
  DataOut: OUT std_logic_VECTOR(7 downto 0);
42
  Empty: OUT std_logic;
43
  Full: OUT std_logic
44
);
45
end component;
46
47
---=======================---
48
--== Signal Declarations ==--
49
---=======================---
50
51
SIGNAL empty_int : STD_LOGIC;
52
SIGNAL empty_i   : STD_LOGIC;
53
SIGNAL full_i    : STD_LOGIC;
54
SIGNAL rd_en     : STD_LOGIC;
55
SIGNAL wr_en     : STD_LOGIC;
56
57
BEGIN
58
59
  ---====================---
60
  --== FIFO write logic ==--
61
  ---====================---
62
63
  wr_en <= NOT(full_i) AND NOT(nwrite);
64
65
  full <= full_i;
66
67
  ---================================---
68
  --== STD_FIFO (CoreGen Module) ==--
69
  ---================================---
70
71
      -- CPU to FPGA FIFO
72
      U0: STD_FIFO
73
      port map(
74
        RST       => rst,
75
        CLK       => clk,
76
        WriteEn    => wr_en,
77
        Full      => full_i,
78
        DataIn       => din,
79
        Empty     => empty_int,
80
        ReadEn     => rd_en,
81
        DataOut      => dout
82
      );
83
84
85
  ---===================---
86
  --== FIFO read logic ==--
87
  ---===================---
88
89
  rd_en <= NOT(empty_int) AND (empty_i OR NOT(nread));
90
91
  PROCESS(clk)
92
  BEGIN
93
    IF RISING_EDGE(clk) THEN
94
      IF (rst = '1') THEN
95
        empty_i <= '1';
96
      ELSE
97
        empty_i <= empty_int AND (empty_i OR NOT(nread));
98
      END IF;
99
    END IF;
100
  END PROCESS;
101
102
  empty <= empty_i;
103
104
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:
1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.std_logic_unsigned.all;
4
use ieee.numeric_std.all;
5
6
entity xillydemo is
7
  port (
8
PCIE_PERST_B_LS : IN std_logic;
9
PCIE_REFCLK_N : IN std_logic;
10
PCIE_REFCLK_P : IN std_logic;
11
PCIE_RX_N : IN std_logic_vector(3 DOWNTO 0);
12
PCIE_RX_P : IN std_logic_vector(3 DOWNTO 0);
13
GPIO_LED : OUT std_logic_vector(3 DOWNTO 0);
14
PCIE_TX_N : OUT std_logic_vector(3 DOWNTO 0);
15
PCIE_TX_P : OUT std_logic_vector(3 DOWNTO 0));
16
end xillydemo;
17
18
architecture sample_arch of xillydemo is
19
  component xillybus
20
    port (
21
  PCIE_PERST_B_LS : IN std_logic;
22
  PCIE_REFCLK_N : IN std_logic;
23
  PCIE_REFCLK_P : IN std_logic;
24
  PCIE_RX_N : IN std_logic_vector(3 DOWNTO 0);
25
  PCIE_RX_P : IN std_logic_vector(3 DOWNTO 0);
26
  GPIO_LED : OUT std_logic_vector(3 DOWNTO 0);
27
  PCIE_TX_N : OUT std_logic_vector(3 DOWNTO 0);
28
  PCIE_TX_P : OUT std_logic_vector(3 DOWNTO 0);
29
  bus_clk : OUT std_logic;
30
  quiesce : OUT std_logic;
31
32
  user_r_read_8_rden : OUT std_logic;
33
  user_r_read_8_empty : IN std_logic;
34
  user_r_read_8_data : IN std_logic_vector(7 DOWNTO 0);
35
  user_r_read_8_eof : IN std_logic;
36
  user_r_read_8_open : OUT std_logic;
37
  user_w_write_8_wren : OUT std_logic;
38
  user_w_write_8_full : IN std_logic;
39
  user_w_write_8_data : OUT std_logic_vector(7 DOWNTO 0);
40
  user_w_write_8_open : OUT std_logic);
41
  end component;
42
43
44
component ac_fifo_wrap
45
port (
46
  --==  General Interface ==--
47
  RST: IN std_logic;
48
  CLK: IN std_logic;
49
  
50
  --== Input Interface ==--
51
  nwrite: IN std_logic;
52
  full: OUT std_logic;
53
  din: IN std_logic_VECTOR(7 downto 0);
54
  
55
  --== Output Interface ==--
56
  empty: OUT std_logic;
57
  nread: IN std_logic;
58
  dout: OUT std_logic_VECTOR(7 downto 0) 
59
);
60
end component;
61
62
63
  signal bus_clk :  std_logic;
64
  signal quiesce : std_logic;
65
66
  signal reset_8 : std_logic;
67
68
  signal user_r_read_8_rden :  std_logic;
69
  signal user_r_read_8_empty :  std_logic;
70
  signal user_r_read_8_data :  std_logic_vector(7 DOWNTO 0);
71
  signal user_r_read_8_eof :  std_logic;
72
  signal user_r_read_8_open :  std_logic;
73
74
  signal user_w_write_8_wren :  std_logic;
75
  signal user_w_write_8_full :  std_logic;
76
  signal user_w_write_8_data :  std_logic_vector(7 DOWNTO 0);
77
  signal user_w_write_8_open :  std_logic;
78
  
79
  signal s_dout_din : std_logic_vector(7 DOWNTO 0);
80
  signal s_nread_full :  std_logic;
81
  signal s_empty_nwrite :  std_logic;
82
  
83
begin
84
  xillybus_ins : xillybus
85
port map (
86
  
87
88
  -- Ports related to /dev/xillybus_read_8
89
  -- FPGA to CPU signals:
90
  user_r_read_8_rden => user_r_read_8_rden,
91
  user_r_read_8_empty => user_r_read_8_empty,
92
  user_r_read_8_data => user_r_read_8_data,
93
  user_r_read_8_eof => user_r_read_8_eof,
94
  user_r_read_8_open => user_r_read_8_open,
95
96
  -- Ports related to /dev/xillybus_write_8
97
  -- CPU to FPGA signals:
98
  user_w_write_8_wren => user_w_write_8_wren,
99
  user_w_write_8_full => user_w_write_8_full,
100
  user_w_write_8_data => user_w_write_8_data,
101
  user_w_write_8_open => user_w_write_8_open,
102
103
  -- General signals
104
  PCIE_PERST_B_LS => PCIE_PERST_B_LS,
105
  PCIE_REFCLK_N => PCIE_REFCLK_N,
106
  PCIE_REFCLK_P => PCIE_REFCLK_P,
107
  PCIE_RX_N => PCIE_RX_N,
108
  PCIE_RX_P => PCIE_RX_P,
109
  GPIO_LED => GPIO_LED,
110
  PCIE_TX_N => PCIE_TX_N,
111
  PCIE_TX_P => PCIE_TX_P,
112
  bus_clk => bus_clk,
113
  quiesce => quiesce
114
  );
115
  
116
  
117
-- CPU to FPGA FIFO
118
ac_fifo_wrap_write: ac_fifo_wrap
119
port map(
120
  RST       => reset_8,
121
  CLK       => bus_clk,
122
  nwrite    => not user_w_write_8_wren,
123
  full      => user_w_write_8_full,
124
  din       => user_w_write_8_data,
125
  empty     => s_empty_nwrite, --
126
  nread     => s_nread_full, --
127
  dout      => s_dout_din--
128
);
129
  
130
-- FPGA to CPU FIFO  
131
ac_fifo_wrap_read: ac_fifo_wrap
132
  port map(
133
    RST       => reset_8,
134
    CLK       => bus_clk,
135
    nwrite    => s_empty_nwrite, --
136
    full      => s_nread_full, --
137
    din       => s_dout_din, --
138
    empty     => user_r_read_8_empty,
139
    nread     => not user_r_read_8_rden,
140
    dout      => user_r_read_8_data
141
  );
142
   
143
144
-- these lines must be preserved in the XillyDemo
145
reset_8 <= not (user_w_write_8_open or user_r_read_8_open);
146
user_r_read_8_eof <= user_r_read_8_empty and not(user_w_write_8_open);
147
148
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?
1
library ieee;
2
use ieee.std_logic_1164.all;
3
4
entity my_buffer_tb is
5
end my_buffer_tb;
6
7
architecture sim of ac_fifo_wrap_tb is
8
  signal clk        : std_logic := '1';
9
  signal rst        : std_logic;
10
  signal nwrite     : std_logic;
11
  signal full       : std_logic;
12
  signal din        : std_logic_vector(7 DOWNTO 0);
13
  signal nread      : std_logic;
14
  signal empty      : std_logic;
15
  signal dout       : std_logic_vector(7 DOWNTO 0);
16
begin
17
  -- component instantiation
18
  DUT: entity work.ac_fifo_wrap
19
    port map (
20
      clk       => bus_clk,
21
      rst       => reset_8,
22
      nwrite    => user_w_write_8_wren,
23
      full      => user_w_write_8_full,
24
      din       => user_w_write_8_data,
25
      nread     => user_r_read_8_rden,
26
      empty     => user_r_read_8_empty,
27
      dout      => user_r_read_8_data);
28
29
  -- clock generation
30
  clk <= not clk after 5 ns;
31
32
  -- waveform generation
33
  WaveGen_Proc: process
34
  begin
35
    rst  <= '1';                     -- apply reset
36
    -- other input values don't care during reset
37
    wait until rising_edge(clk);
38
39
    -- Endless idle cycles
40
    rst <= '0';
41
    nwrite <= '0';
42
    din <= (others => '-');
43
    nread  <= '0';
44
    wait;
45
  end process WaveGen_Proc;
46
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
Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.