SURF  1.0
FifoAsyncBuiltIn.vhd
Go to the documentation of this file.
1 -------------------------------------------------------------------------------
2 -- File : FifoAsyncBuiltIn.vhd
3 -- Company : SLAC National Accelerator Laboratory
4 -- Created : 2013-07-28
5 -- Last update: 2014-07-14
6 -------------------------------------------------------------------------------
7 -- Description: Wrapper for Xilinx's built-in ASYNC 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.std_logic_unsigned.all;
21 use ieee.std_logic_arith.all;
22 
23 use work.StdRtlPkg.all;
24 
25 library UNISIM;
26 use UNISIM.vcomponents.all;
27 
28 library UNIMACRO;
29 use UNIMACRO.vcomponents.all;
30 
31 --! @see entity
32  --! @ingroup base_fifo
34  generic (
35  TPD_G : time := 1 ns;
36  RST_POLARITY_G : sl := '1'; -- '1' for active high rst, '0' for active low
37  FWFT_EN_G : boolean := false;
38  USE_DSP48_G : string := "no";
39  XIL_DEVICE_G : string := "7SERIES"; -- Target Device: "VIRTEX5", "VIRTEX6", "7SERIES"
40  SYNC_STAGES_G : integer range 3 to (2**24) := 3;
41  PIPE_STAGES_G : natural range 0 to 16 := 0;
42  DATA_WIDTH_G : integer range 1 to 72 := 18;
43  ADDR_WIDTH_G : integer range 9 to 13 := 10;
44  FULL_THRES_G : integer range 1 to 8190 := 1;
45  EMPTY_THRES_G : integer range 1 to 8190 := 1);
46  port (
47  -- Asynchronous Reset
48  rst : in sl;
49  -- Write Ports (wr_clk domain)
50  wr_clk : in sl;
51  wr_en : in sl;
52  din : in slv(DATA_WIDTH_G-1 downto 0);
53  wr_data_count : out slv(ADDR_WIDTH_G-1 downto 0);
54  wr_ack : out sl;
55  overflow : out sl;
56  prog_full : out sl;
57  almost_full : out sl;
58  full : out sl;
59  not_full : out sl;
60  -- Read Ports (rd_clk domain)
61  rd_clk : in sl;
62  rd_en : in sl;
63  dout : out slv(DATA_WIDTH_G-1 downto 0);
64  rd_data_count : out slv(ADDR_WIDTH_G-1 downto 0);
65  valid : out sl;
66  underflow : out sl;
67  prog_empty : out sl;
69  empty : out sl);
70 end FifoAsyncBuiltIn;
71 
72 architecture mapping of FifoAsyncBuiltIn is
73 
74  function GetFifoType (d_width : in integer; a_width : in integer) return string is
75  begin
76  if ((d_width >= 37) and (d_width <= 72) and (a_width = 9)) then
77  return "36Kb";
78  elsif ((d_width >= 19) and (d_width <= 36) and (a_width = 10)) then
79  return "36Kb";
80  elsif ((d_width >= 19) and (d_width <= 36) and (a_width = 9)) then
81  return "18Kb";
82  elsif ((d_width >= 10) and (d_width <= 18) and (a_width = 11)) then
83  return "36Kb";
84  elsif ((d_width >= 10) and (d_width <= 18) and (a_width = 10)) then
85  return "18Kb";
86  elsif ((d_width >= 5) and (d_width <= 9) and (a_width = 12)) then
87  return "36Kb";
88  elsif ((d_width >= 5) and (d_width <= 9) and (a_width = 11)) then
89  return "18Kb";
90  elsif ((d_width >= 1) and (d_width <= 4) and (a_width = 13)) then
91  return "36Kb";
92  elsif ((d_width >= 1) and (d_width <= 4) and (a_width = 12)) then
93  return "18Kb";
94  else
95  return "???Kb"; -- Generate error in Xilinx marco
96  end if;
97  end;
98 
99  constant FIFO_LENGTH_C : integer := ((2**ADDR_WIDTH_G)- 1);
100  constant FIFO_SIZE_C : string := GetFifoType(DATA_WIDTH_G, ADDR_WIDTH_G);
101 
102  signal wrAddrPntr,
103  rdAddrPntr,
104  wrGrayPntr,
105  rdGrayPntr,
106  wcnt,
107  rcnt : slv(ADDR_WIDTH_G-1 downto 0) := (others => '0');
108 
109  signal buildInFull,
110  buildInEmpty,
111  progEmpty,
112  progFull,
113  fifoWrRst,
114  fifoRdRst,
115  rstEmpty,
116  rstFull,
117  wrEn,
118  sValid,
119  sRdEn,
120  dummyWRERR,
123  rstDet : sl := '0';
124 
125  signal dataOut : slv(DATA_WIDTH_G-1 downto 0);
126 
127  -- Attribute for XST
128  attribute use_dsp48 : string;
129  attribute use_dsp48 of wcnt : signal is USE_DSP48_G;
130  attribute use_dsp48 of rcnt : signal is USE_DSP48_G;
131 
132 begin
133 
134  -- Check ADDR_WIDTH_G and DATA_WIDTH_G when USE_BUILT_IN_G = true
135  assert (((DATA_WIDTH_G >= 37) and (DATA_WIDTH_G <= 72) and (ADDR_WIDTH_G = 9))
136  or ((DATA_WIDTH_G >= 19) and (DATA_WIDTH_G <= 36) and (ADDR_WIDTH_G = 10))
137  or ((DATA_WIDTH_G >= 19) and (DATA_WIDTH_G <= 36) and (ADDR_WIDTH_G = 9))
138  or ((DATA_WIDTH_G >= 10) and (DATA_WIDTH_G <= 18) and (ADDR_WIDTH_G = 11))
139  or ((DATA_WIDTH_G >= 10) and (DATA_WIDTH_G <= 18) and (ADDR_WIDTH_G = 10))
140  or ((DATA_WIDTH_G >= 5) and (DATA_WIDTH_G <= 9) and (ADDR_WIDTH_G = 12))
141  or ((DATA_WIDTH_G >= 5) and (DATA_WIDTH_G <= 9) and (ADDR_WIDTH_G = 11))
142  or ((DATA_WIDTH_G >= 1) and (DATA_WIDTH_G <= 4) and (ADDR_WIDTH_G = 13))
143  or ((DATA_WIDTH_G >= 1) and (DATA_WIDTH_G <= 4) and (ADDR_WIDTH_G = 12)))
144  report "Invalid DATA_WIDTH_G or ADDR_WIDTH_G for built-in FIFO configuration"
145  severity failure;
146  -----------------------------------------------------------------
147  -- DATA_WIDTH | FIFO_SIZE | FIFO Depth | RDCOUNT/WRCOUNT Width --
148  -- ===========|===========|============|=======================--
149  -- 37-72 | "36Kb" | 512 | 9-bit --
150  -- 19-36 | "36Kb" | 1024 | 10-bit --
151  -- 19-36 | "18Kb" | 512 | 9-bit --
152  -- 10-18 | "36Kb" | 2048 | 11-bit --
153  -- 10-18 | "18Kb" | 1024 | 10-bit --
154  -- 5-9 | "36Kb" | 4096 | 12-bit --
155  -- 5-9 | "18Kb" | 2048 | 11-bit --
156  -- 1-4 | "36Kb" | 8192 | 13-bit --
157  -- 1-4 | "18Kb" | 4096 | 12-bit --
158  -----------------------------------------------------------------
159  -- FULL_THRES_G upper range check
160  assert (FULL_THRES_G <= ((2**ADDR_WIDTH_G)-1))
161  report "FULL_THRES_G must be <= ((2**ADDR_WIDTH_G)-1)"
162  severity failure;
163  -- EMPTY_THRES_G upper range check
164  assert (EMPTY_THRES_G <= ((2**ADDR_WIDTH_G)-2))
165  report "EMPTY_THRES_G must be <= ((2**ADDR_WIDTH_G)-2)"
166  severity failure;
167  -- USE_DSP48_G check
168  assert ((USE_DSP48_G = "yes") or (USE_DSP48_G = "no") or (USE_DSP48_G = "auto") or (USE_DSP48_G = "automax"))
169  report "USE_DSP48_G must be either yes, no, auto, or automax"
170  severity failure;
171 
172  -------------------------------
173  -- Resets
174  -------------------------------
175  RstSync_FULL : entity work.RstSync
176  generic map (
177  TPD_G => TPD_G,
179  RELEASE_DELAY_G => 10)
180  port map (
181  clk => wr_clk,
182  asyncRst => rst,
183  syncRst => rstFull);
184 
185  SynchronizerEdge_FULL : entity work.SynchronizerEdge
186  generic map (
187  TPD_G => TPD_G)
188  port map (
189  clk => wr_clk,
190  dataIn => rstFull,
191  risingEdge => rstDet);
192 
193  RstSync_FIFO : entity work.RstSync
194  generic map (
195  TPD_G => TPD_G,
196  RELEASE_DELAY_G => 6)
197  port map (
198  clk => wr_clk,
199  asyncRst => rstDet,
200  syncRst => fifoWrRst);
201 
202  RstSync_RD : entity work.RstSync
203  generic map (
204  TPD_G => TPD_G,
206  RELEASE_DELAY_G => 6)
207  port map (
208  clk => rd_clk,
209  asyncRst => rst,
210  syncRst => fifoRdRst);
211 
212  RstSync_EMPTY : entity work.RstSync
213  generic map (
214  TPD_G => TPD_G,
216  RELEASE_DELAY_G => 10)
217  port map (
218  clk => rd_clk,
219  asyncRst => rst,
220  syncRst => rstEmpty);
221 
222  FIFO_DUALCLOCK_MACRO_inst : FIFO_DUALCLOCK_MACRO
223  generic map (
224  DEVICE => XIL_DEVICE_G, -- Target Device: "VIRTEX5", "VIRTEX6", "7SERIES"
225  ALMOST_FULL_OFFSET => x"000F", -- Sets almost full threshold
226  ALMOST_EMPTY_OFFSET => x"000F", -- Sets the almost empty threshold
227  DATA_WIDTH => DATA_WIDTH_G, -- Valid values are 1-72 (37-72 only valid when FIFO_SIZE="36Kb")
228  FIFO_SIZE => FIFO_SIZE_C, -- Target BRAM, "18Kb" or "36Kb"
229  FIRST_WORD_FALL_THROUGH => FWFT_EN_G) -- Sets the FIFO FWFT to TRUE or FALSE
230  port map (
231  RST => fifoWrRst, -- 1-bit input reset
232  WRCLK => wr_clk, -- 1-bit input write clock
233  WREN => wrEn, -- 1-bit input write enable
234  DI => din, -- Input data, width defined by DATA_WIDTH parameter
235  WRCOUNT => wrAddrPntr, -- Output write address pointer
236  WRERR => dummyWRERR, -- 1-bit output write error
237  ALMOSTFULL => dummyALMOSTFULL, -- 1-bit output almost full
238  FULL => buildInFull, -- 1-bit output full
239  RDCLK => rd_clk, -- 1-bit input read clock
240  RDEN => sRdEn, -- 1-bit input read enable
241  DO => dataOut, -- Output data, width defined by DATA_WIDTH parameter
242  RDCOUNT => rdAddrPntr, -- Output read address pointer
243  RDERR => underflow, -- 1-bit output read error
244  ALMOSTEMPTY => dummyALMOSTEMPTY, -- 1-bit output almost empty
245  EMPTY => buildInEmpty); -- 1-bit output empty
246 
247 
248  -------------------------------
249  -- wr_clk domain
250  -------------------------------
251  SynchronizerVector_0 : entity work.SynchronizerVector
252  generic map (
253  TPD_G => TPD_G,
254  RST_ASYNC_G => false,
257  port map (
258  rst => fifoWrRst,
259  clk => wr_clk,
260  dataIn => grayEncode(rdAddrPntr),
261  dataOut => rdGrayPntr);
262 
263  -- Calculate wr_data_count
264  wcnt <= wrAddrPntr - grayDecode(rdGrayPntr);
265 
266  -- Full signals
267  wrEn <= wr_en and not(rstFull) and not(buildInFull);
268  prog_full <= '1' when (wcnt > FULL_THRES_G) else rstFull;
269  almost_full <= '1' when (wcnt = (FIFO_LENGTH_C-2)) else (buildInFull or rstFull);
270  full <= buildInFull or rstFull;
271  not_full <= not(buildInFull or rstFull);
272  wr_data_count <= wcnt when(rstFull = '0') else (others => '1');
273 
274  process(wr_clk)
275  begin
276  if rising_edge(wr_clk) then
277  wr_ack <= '0' after TPD_G;
278  if wr_en = '1' then
279  wr_ack <= not(buildInFull) after TPD_G;
280  end if;
281  end if;
282  end process;
283 
284  process(wr_clk)
285  begin
286  if rising_edge(wr_clk) then
287  overflow <= '0' after TPD_G;
288  if (wr_en = '1') and (buildInFull = '1') then
289  overflow <= '1' after TPD_G; -- Error strobe
290  end if;
291  end if;
292  end process;
293 
294  -------------------------------
295  -- rd_clk domain
296  -------------------------------
297  SynchronizerVector_1 : entity work.SynchronizerVector
298  generic map (
299  TPD_G => TPD_G,
300  RST_ASYNC_G => false,
303  port map (
304  rst => fifoRdRst,
305  clk => rd_clk,
306  dataIn => grayEncode(wrAddrPntr),
307  dataOut => wrGrayPntr);
308 
309  -- Calculate rd_data_count
310  rcnt <= grayDecode(wrGrayPntr) - rdAddrPntr;
311 
312  -- Empty signals
313  prog_empty <= '1' when (rcnt < EMPTY_THRES_G) else rstEmpty;
314  almost_empty <= '1' when (rcnt = 1) else (buildInEmpty or rstEmpty);
316  rd_data_count <= rcnt when(rstEmpty = '0') else (others => '0');
317 
318  FIFO_Gen : if (FWFT_EN_G = false) generate
319 
320  dout <= dataOut;
321 
322  process(rd_clk)
323  begin
324  if rising_edge(rd_clk) then
325  valid <= '0' after TPD_G;
326  if rd_en = '1' then
327  valid <= not(buildInEmpty) after TPD_G;
328  end if;
329  end if;
330  end process;
331  end generate;
332 
333  FWFT_Gen : if (FWFT_EN_G = true) generate
334 
335  FifoOutputPipeline_Inst : entity work.FifoOutputPipeline
336  generic map (
337  TPD_G => TPD_G,
338  RST_POLARITY_G => '1',
339  RST_ASYNC_G => false,
342  port map (
343  -- Slave Port
344  sData => dataOut,
345  sValid => sValid,
346  sRdEn => sRdEn,
347  -- Master Port
348  mData => dout,
349  mValid => valid,
350  mRdEn => rd_en,
351  -- Clock and Reset
352  clk => rd_clk,
353  rst => fifoRdRst);
354 
355  sValid <= not(buildInEmpty);
356 
357  end generate;
358 
359 end architecture mapping;
out wr_data_countslv( ADDR_WIDTH_G- 1 downto 0)
USE_DSP48_Gstring := "no"
slv( ADDR_WIDTH_G- 1 downto 0) :=( others => '0') wrAddrPntr
out rd_data_countslv( ADDR_WIDTH_G- 1 downto 0)
out syncRstsl
Definition: RstSync.vhd:36
RST_ASYNC_Gboolean := false
IN_POLARITY_Gsl := '1'
Definition: RstSync.vhd:28
DATA_WIDTH_Ginteger range 1 to 72:= 18
out doutslv( DATA_WIDTH_G- 1 downto 0)
ADDR_WIDTH_Ginteger range 9 to 13:= 10
std_logic sl
Definition: StdRtlPkg.vhd:28
FULL_THRES_Ginteger range 1 to 8190:= 1
RST_ASYNC_Gboolean := false
integer :=(( 2** ADDR_WIDTH_G)- 1) FIFO_LENGTH_C
in dataInslv( WIDTH_G- 1 downto 0)
in asyncRstsl
Definition: RstSync.vhd:35
string GetFifoTyped_width,a_width,
EMPTY_THRES_Ginteger range 1 to 8190:= 1
in clksl
Definition: RstSync.vhd:34
XIL_DEVICE_Gstring := "7SERIES"
string := GetFifoType( DATA_WIDTH_G, ADDR_WIDTH_G) FIFO_SIZE_C
FWFT_EN_Gboolean := false
slv( DATA_WIDTH_G- 1 downto 0) dataOut
RELEASE_DELAY_Ginteger range 3 to positive'high:= 3
Definition: RstSync.vhd:31
SYNC_STAGES_Ginteger range 3 to ( 2** 24):= 3
slv( ADDR_WIDTH_G- 1 downto 0) :=( others => '0') rdGrayPntr
TPD_Gtime := 1 ns
Definition: RstSync.vhd:27
in dinslv( DATA_WIDTH_G- 1 downto 0)
out dataOutslv( WIDTH_G- 1 downto 0)
in rstsl :=not RST_POLARITY_G
slv( ADDR_WIDTH_G- 1 downto 0) :=( others => '0') rcnt
PIPE_STAGES_Gnatural range 0 to 16:= 1
slv( ADDR_WIDTH_G- 1 downto 0) :=( others => '0') rdAddrPntr
DATA_WIDTH_Ginteger range 1 to ( 2** 24):= 16
in sDataslv( DATA_WIDTH_G- 1 downto 0)
in rstsl :=not RST_POLARITY_G
out mDataslv( DATA_WIDTH_G- 1 downto 0)
_library_ ieeeieee
Definition: FifoAsync.vhd:18
slv( ADDR_WIDTH_G- 1 downto 0) :=( others => '0') wcnt
PIPE_STAGES_Gnatural range 0 to 16:= 0
std_logic_vector slv
Definition: StdRtlPkg.vhd:29
slv( ADDR_WIDTH_G- 1 downto 0) :=( others => '0') wrGrayPntr