SURF  1.0
FifoMux.vhd
Go to the documentation of this file.
1 -------------------------------------------------------------------------------
2 -- File : FifoMux.vhd
3 -- Company : SLAC National Accelerator Laboratory
4 -- Created : 2013-07-24
5 -- Last update: 2015-01-14
6 -------------------------------------------------------------------------------
7 -- Description: Resizing FIFO module
8 -------------------------------------------------------------------------------
9 -- This file is part of 'SLAC Firmware Standard Library'.
10 -- It is subject to the license terms in the LICENSE.txt file found in the
11 -- top-level directory of this distribution and at:
12 -- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html.
13 -- No part of 'SLAC Firmware Standard Library', including this file,
14 -- may be copied, modified, propagated, or distributed except according to
15 -- the terms contained in the LICENSE.txt file.
16 -------------------------------------------------------------------------------
17 
18 library ieee;
19 use ieee.std_logic_1164.all;
20 use ieee.numeric_std.all;
21 
22 use work.StdRtlPkg.all;
23 
24 --! @see entity
25  --! @ingroup base_fifo
26 entity FifoMux is
27  generic (
28  TPD_G : time := 1 ns;
29  CASCADE_SIZE_G : integer range 1 to (2**24) := 1; -- number of FIFOs to cascade (if set to 1, then no FIFO cascading)
30  LAST_STAGE_ASYNC_G : boolean := true; -- if set to true, the last stage will be the ASYNC FIFO
31  RST_POLARITY_G : sl := '1'; -- '1' for active high rst, '0' for active low
32  RST_ASYNC_G : boolean := false;
33  GEN_SYNC_FIFO_G : boolean := false;
34  BRAM_EN_G : boolean := true;
35  FWFT_EN_G : boolean := true;
36  USE_DSP48_G : string := "no";
37  ALTERA_SYN_G : boolean := false;
38  ALTERA_RAM_G : string := "M9K";
39  USE_BUILT_IN_G : boolean := false; -- If set to true, this module is only Xilinx compatible only!!!
40  XIL_DEVICE_G : string := "7SERIES"; -- Xilinx only generic parameter
41  SYNC_STAGES_G : integer range 3 to (2**24) := 3;
42  PIPE_STAGES_G : natural range 0 to 16 := 0;
43  WR_DATA_WIDTH_G : integer range 1 to (2**24) := 64;
44  RD_DATA_WIDTH_G : integer range 1 to (2**24) := 16;
45  LITTLE_ENDIAN_G : boolean := false;
46  ADDR_WIDTH_G : integer range 4 to 48 := 10;
47  INIT_G : slv := "0";
48  FULL_THRES_G : integer range 1 to (2**24) := 1;
49  EMPTY_THRES_G : integer range 1 to (2**24) := 1);
50  port (
51  -- Resets
52  rst : in sl := '0'; -- Reset
53  --Write Ports (wr_clk domain)
54  wr_clk : in sl;
55  wr_en : in sl := '0';
56  din : in slv(WR_DATA_WIDTH_G-1 downto 0);
57  wr_data_count : out slv(ADDR_WIDTH_G-1 downto 0);
58  wr_ack : out sl;
59  overflow : out sl;
60  prog_full : out sl;
61  almost_full : out sl;
62  full : out sl;
63  not_full : out sl;
64  --Read Ports (rd_clk domain)
65  rd_clk : in sl; --unused if GEN_SYNC_FIFO_G = true
66  rd_en : in sl := '0';
67  dout : out slv(RD_DATA_WIDTH_G-1 downto 0);
68  rd_data_count : out slv(ADDR_WIDTH_G-1 downto 0);
69  valid : out sl;
70  underflow : out sl;
71  prog_empty : out sl;
73  empty : out sl);
74 end FifoMux;
75 
76 architecture rtl of FifoMux is
77 
78  constant FIFO_DATA_WIDTH_C : integer := ite(WR_DATA_WIDTH_G > RD_DATA_WIDTH_G, WR_DATA_WIDTH_G, RD_DATA_WIDTH_G);
79 
80  ----------------
81  -- Write Signals
82  ----------------
83  constant WR_LOGIC_EN_C : boolean := (WR_DATA_WIDTH_G < RD_DATA_WIDTH_G);
84  constant WR_SIZE_C : integer := ite(WR_LOGIC_EN_C, RD_DATA_WIDTH_G / WR_DATA_WIDTH_G, 1);
85 
86  type WrDataArray is array (0 to WR_SIZE_C-1) of slv(WR_DATA_WIDTH_G-1 downto 0);
87  type WrRegType is record
88  count : unsigned(bitSize(WR_SIZE_C)-1 downto 0);
89  wrData : WrDataArray;
90  wrEn : sl;
91  end record WrRegType;
92 
93  constant WR_REG_INIT_C : WrRegType := (
94  count => (others => '0'),
95  wrData => (others => (others => '0')),
96  wrEn => '0');
97 
98  signal wrR, wrRin : WrRegType := WR_REG_INIT_C;
99  signal fifo_din : slv(FIFO_DATA_WIDTH_C-1 downto 0);
100  signal fifo_wr_en : sl;
101  signal wrRst : sl;
102 
103  ---------------
104  -- Read Signals
105  ---------------
106  constant RD_LOGIC_EN_C : boolean := (RD_DATA_WIDTH_G < WR_DATA_WIDTH_G);
107  constant RD_SIZE_C : integer := ite(RD_LOGIC_EN_C, WR_DATA_WIDTH_G / RD_DATA_WIDTH_G, 1);
108 
109  type RdRegType is record
110  count : unsigned(bitSize(RD_SIZE_C)-1 downto 0);
111  end record RdRegType;
112 
113  constant RD_REG_INIT_C : RdRegType := (
114  count => (others => '0'));
115 
116  type RdDataArray is array (0 to RD_SIZE_C-1) of slv(RD_DATA_WIDTH_G-1 downto 0);
117 
118  signal rdR, rdRin : RdRegType := RD_REG_INIT_C;
119  signal fifo_dout : slv(FIFO_DATA_WIDTH_C-1 downto 0);
120  signal fifo_rd_data : slv(RD_DATA_WIDTH_G-1 downto 0);
121  signal fifo_valid : sl;
122  signal fifo_rd_en : sl;
123  signal fifo_empty : sl;
124  signal rdRst : sl;
125 
126 begin
127 
130  report "FifoMux: Data widths must be even number multiples of each other"
131  severity failure;
132 
133  assert ((FWFT_EN_G = false and RD_DATA_WIDTH_G >= WR_DATA_WIDTH_G) or FWFT_EN_G)
134  report "FifoMux: non-FWFT mode can only be used if the read width is >= the write data width"
135  severity failure;
136 
137  --------------
138  -- Write Logic
139  --------------
140  wrComb : process (din, wrR, wr_en) is
141  variable v : WrRegType;
142  variable index : integer;
143  variable high : integer;
144  variable low : integer;
145  begin
146  v := wrR;
147 
148  v.wrEn := '0';
149 
150  if (wr_en = '1') then
151  v.wrData(to_integer(wrR.count)) := din;
152  v.count := wrR.count + 1;
153  if (wrR.count = WR_SIZE_C-1) then
154  v.count := (others => '0');
155  v.wrEn := '1';
156  end if;
157  end if;
158 
159  wrRin <= v;
160 
161  if (RD_DATA_WIDTH_G > WR_DATA_WIDTH_G) then
162  for i in 0 to WR_SIZE_C-1 loop
163  index := ite(LITTLE_ENDIAN_G, i, WR_SIZE_C-1-i);
164  high := index * WR_DATA_WIDTH_G + WR_DATA_WIDTH_G - 1;
165  low := index * WR_DATA_WIDTH_G;
166  fifo_din(high downto low) <= wrR.wrData(i);
167  end loop;
168  fifo_wr_en <= wrR.wrEn;
169  else
170  fifo_din <= din;
171  fifo_wr_en <= wr_en;
172  end if;
173 
174  end process wrComb;
175 
176  wrSeq : process (rst, wr_clk) is
177  begin
178  if (RST_ASYNC_G and rst = RST_POLARITY_G) then
179  wrR <= WR_REG_INIT_C after TPD_G;
180  elsif (rising_edge(wr_clk)) then
181  if (RST_ASYNC_G = false and rst = RST_POLARITY_G) then
182  wrR <= WR_REG_INIT_C after TPD_G;
183  else
184  wrR <= wrRin after TPD_G;
185  end if;
186  end if;
187  end process wrSeq;
188 
189  -------------
190  -- Read logic
191  -------------
192  -- Module reset should be driven by wr_clk
193  -- Must synchronize it over to the rd_clk
194  RstSync_RdRst : entity work.RstSync
195  generic map (
196  TPD_G => TPD_G,
199  port map (
200  clk => rd_clk,
201  asyncRst => rst,
202  syncRst => rdRst);
203 
204  rdComb : process (fifo_dout, fifo_empty, fifo_valid, rdR, rd_en) is
205  variable v : RdRegType;
206  variable rdData : RdDataArray;
207  variable index : integer;
208  variable high : integer;
209  variable low : integer;
210  begin
211  v := rdR;
212 
213  --check for normal read
214  if (rd_en = '1' and fifo_valid = '1') then
215  v.count := rdR.count + 1;
216  if (rdR.count = RD_SIZE_C-1) then
217  v.count := (others => '0');
218  end if;
219  end if;
220 
221  -- Separate fifo_dout into an array of RD_DATA_WIDTH_G sized vectors
222  for i in 0 to RD_SIZE_C-1 loop
223  index := ite(LITTLE_ENDIAN_G, i, RD_SIZE_C-1-i);
224  high := index * RD_DATA_WIDTH_G + RD_DATA_WIDTH_G - 1;
225  low := index * RD_DATA_WIDTH_G;
226  rdData(i) := fifo_dout(high downto low);
227  end loop;
228 
229  rdRin <= v;
230 
231  if (RD_DATA_WIDTH_G < WR_DATA_WIDTH_G) then
232  fifo_rd_en <= toSl(rdR.count = (RD_SIZE_C-1));
233  dout <= rdData(to_integer(rdR.count));
234  valid <= fifo_valid;
235  empty <= fifo_empty;
236  else
237  fifo_rd_en <= rd_en;
238  dout <= fifo_dout;
239  valid <= fifo_valid;
240  empty <= fifo_empty;
241  end if;
242 
243  end process rdComb;
244 
245  -- If fifo is asynchronous, must use async reset on rd side.
246  rdSeq : process (rdRst, rd_clk) is
247  begin
248  if (GEN_SYNC_FIFO_G = false and rdRst = RST_POLARITY_G) then
249  rdR <= RD_REG_INIT_C after TPD_G;
250  elsif (rising_edge(rd_clk)) then
251  if (GEN_SYNC_FIFO_G and RST_ASYNC_G = false and rdRst = RST_POLARITY_G) then
252  rdR <= RD_REG_INIT_C after TPD_G;
253  else
254  rdR <= rdRin after TPD_G;
255  end if;
256  end if;
257  end process rdSeq;
258 
259  --------
260  -- Fifo
261  --------
262  FifoCascade_Inst : entity work.FifoCascade
263  generic map (
264  TPD_G => TPD_G,
270  BRAM_EN_G => BRAM_EN_G,
271  FWFT_EN_G => FWFT_EN_G,
279  DATA_WIDTH_G => FIFO_DATA_WIDTH_C,
281  INIT_G => INIT_G,
284  port map (
285  rst => rst,
286  wr_clk => wr_clk,
287  wr_en => fifo_wr_en,
288  din => fifo_din,
290  wr_ack => wr_ack,
291  overflow => overflow,
292  prog_full => prog_full,
294  full => full,
295  not_full => not_full,
296  rd_clk => rd_clk,
297  rd_en => fifo_rd_en,
298  dout => fifo_dout,
300  valid => fifo_valid,
301  underflow => underflow,
304  empty => fifo_empty);
305 
306 end architecture rtl;
out almost_fullsl
Definition: FifoCascade.vhd:59
RD_DATA_WIDTH_Ginteger range 1 to ( 2** 24):= 16
Definition: FifoMux.vhd:44
ALTERA_RAM_Gstring := "M9K"
Definition: FifoCascade.vhd:38
out validsl
Definition: FifoCascade.vhd:68
out doutslv( DATA_WIDTH_G- 1 downto 0)
Definition: FifoCascade.vhd:66
out doutslv( RD_DATA_WIDTH_G- 1 downto 0)
Definition: FifoMux.vhd:67
XIL_DEVICE_Gstring := "7SERIES"
Definition: FifoCascade.vhd:40
out syncRstsl
Definition: RstSync.vhd:36
out overflowsl
Definition: FifoMux.vhd:59
IN_POLARITY_Gsl := '1'
Definition: RstSync.vhd:28
RST_ASYNC_Gboolean := false
Definition: FifoCascade.vhd:32
out almost_emptysl
Definition: FifoCascade.vhd:71
in wr_clksl
Definition: FifoMux.vhd:54
in dinslv( WR_DATA_WIDTH_G- 1 downto 0)
Definition: FifoMux.vhd:56
INIT_Gslv := "0"
Definition: FifoCascade.vhd:45
std_logic sl
Definition: StdRtlPkg.vhd:28
BRAM_EN_Gboolean := true
Definition: FifoCascade.vhd:34
in wr_ensl := '0'
Definition: FifoMux.vhd:55
in dinslv( DATA_WIDTH_G- 1 downto 0)
Definition: FifoCascade.vhd:54
SYNC_STAGES_Ginteger range 3 to ( 2** 24):= 3
Definition: FifoMux.vhd:41
out validsl
Definition: FifoMux.vhd:69
GEN_SYNC_FIFO_Gboolean := false
Definition: FifoMux.vhd:33
in rd_clksl
Definition: FifoCascade.vhd:64
out prog_fullsl
Definition: FifoCascade.vhd:58
PIPE_STAGES_Gnatural range 0 to 16:= 0
Definition: FifoCascade.vhd:42
USE_BUILT_IN_Gboolean := false
Definition: FifoMux.vhd:39
CASCADE_SIZE_Ginteger range 1 to ( 2** 24):= 1
Definition: FifoMux.vhd:29
out almost_emptysl
Definition: FifoMux.vhd:72
EMPTY_THRES_Ginteger range 1 to ( 2** 24):= 1
Definition: FifoCascade.vhd:47
out not_fullsl
Definition: FifoMux.vhd:63
out wr_data_countslv( ADDR_WIDTH_G- 1 downto 0)
Definition: FifoMux.vhd:57
in asyncRstsl
Definition: RstSync.vhd:35
out prog_fullsl
Definition: FifoMux.vhd:60
ALTERA_SYN_Gboolean := false
Definition: FifoCascade.vhd:37
out underflowsl
Definition: FifoMux.vhd:70
RST_POLARITY_Gsl := '1'
Definition: FifoMux.vhd:31
WR_DATA_WIDTH_Ginteger range 1 to ( 2** 24):= 64
Definition: FifoMux.vhd:43
RST_ASYNC_Gboolean := false
Definition: FifoMux.vhd:32
in clksl
Definition: RstSync.vhd:34
PIPE_STAGES_Gnatural range 0 to 16:= 0
Definition: FifoMux.vhd:42
OUT_POLARITY_Gsl := '1'
Definition: RstSync.vhd:29
in rd_ensl := '0'
Definition: FifoCascade.vhd:65
out wr_acksl
Definition: FifoCascade.vhd:56
LAST_STAGE_ASYNC_Gboolean := true
Definition: FifoMux.vhd:30
in rstsl := '0'
Definition: FifoCascade.vhd:50
TPD_Gtime := 1 ns
Definition: FifoMux.vhd:28
ALTERA_RAM_Gstring := "M9K"
Definition: FifoMux.vhd:38
in wr_clksl
Definition: FifoCascade.vhd:52
out overflowsl
Definition: FifoCascade.vhd:57
FULL_THRES_Ginteger range 1 to ( 2** 24):= 1
Definition: FifoCascade.vhd:46
ALTERA_SYN_Gboolean := false
Definition: FifoMux.vhd:37
SYNC_STAGES_Ginteger range 3 to ( 2** 24):= 3
Definition: FifoCascade.vhd:41
XIL_DEVICE_Gstring := "7SERIES"
Definition: FifoMux.vhd:40
FWFT_EN_Gboolean := true
Definition: FifoMux.vhd:35
out emptysl
Definition: FifoMux.vhd:73
out wr_acksl
Definition: FifoMux.vhd:58
in rd_clksl
Definition: FifoMux.vhd:65
in rstsl := '0'
Definition: FifoMux.vhd:52
TPD_Gtime := 1 ns
Definition: RstSync.vhd:27
ADDR_WIDTH_Ginteger range 4 to 48:= 10
Definition: FifoMux.vhd:46
in wr_ensl := '0'
Definition: FifoCascade.vhd:53
out fullsl
Definition: FifoCascade.vhd:60
GEN_SYNC_FIFO_Gboolean := false
Definition: FifoCascade.vhd:33
out prog_emptysl
Definition: FifoMux.vhd:71
TPD_Gtime := 1 ns
Definition: FifoCascade.vhd:28
INIT_Gslv := "0"
Definition: FifoMux.vhd:47
USE_DSP48_Gstring := "no"
Definition: FifoCascade.vhd:36
LAST_STAGE_ASYNC_Gboolean := true
Definition: FifoCascade.vhd:30
ADDR_WIDTH_Ginteger range 4 to 48:= 4
Definition: FifoCascade.vhd:44
_library_ ieeeieee
Definition: FifoCascade.vhd:18
FULL_THRES_Ginteger range 1 to ( 2** 24):= 1
Definition: FifoMux.vhd:48
LITTLE_ENDIAN_Gboolean := false
Definition: FifoMux.vhd:45
USE_DSP48_Gstring := "no"
Definition: FifoMux.vhd:36
USE_BUILT_IN_Gboolean := false
Definition: FifoCascade.vhd:39
FWFT_EN_Gboolean := false
Definition: FifoCascade.vhd:35
BRAM_EN_Gboolean := true
Definition: FifoMux.vhd:34
out not_fullsl
Definition: FifoCascade.vhd:61
in rd_ensl := '0'
Definition: FifoMux.vhd:66
DATA_WIDTH_Ginteger range 1 to ( 2** 24):= 16
Definition: FifoCascade.vhd:43
out rd_data_countslv( ADDR_WIDTH_G- 1 downto 0)
Definition: FifoMux.vhd:68
out emptysl
Definition: FifoCascade.vhd:72
out fullsl
Definition: FifoMux.vhd:62
out underflowsl
Definition: FifoCascade.vhd:69
out almost_fullsl
Definition: FifoMux.vhd:61
CASCADE_SIZE_Ginteger range 1 to ( 2** 24):= 1
Definition: FifoCascade.vhd:29
out prog_emptysl
Definition: FifoCascade.vhd:70
out wr_data_countslv( ADDR_WIDTH_G- 1 downto 0)
Definition: FifoCascade.vhd:55
EMPTY_THRES_Ginteger range 1 to ( 2** 24):= 1
Definition: FifoMux.vhd:49
RST_POLARITY_Gsl := '1'
Definition: FifoCascade.vhd:31
std_logic_vector slv
Definition: StdRtlPkg.vhd:29
out rd_data_countslv( ADDR_WIDTH_G- 1 downto 0)
Definition: FifoCascade.vhd:67