SURF  1.0
FifoSync.vhd
Go to the documentation of this file.
1 -------------------------------------------------------------------------------
2 -- File : FifoSync.vhd
3 -- Company : SLAC National Accelerator Laboratory
4 -- Created : 2013-07-10
5 -- Last update: 2016-10-27
6 -------------------------------------------------------------------------------
7 -- Description: SYNC 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_arith.all;
21 use ieee.std_logic_unsigned.all;
22 
23 use work.StdRtlPkg.all;
24 
25 --! @see entity
26  --! @ingroup base_fifo
27 entity FifoSync is
28  generic (
29  TPD_G : time := 1 ns;
30  RST_POLARITY_G : sl := '1'; -- '1' for active high rst, '0' for active low
31  RST_ASYNC_G : boolean := false;
32  BRAM_EN_G : boolean := true;
33  BYP_RAM_G : boolean := false;
34  FWFT_EN_G : boolean := false;
35  USE_DSP48_G : string := "no";
36  ALTERA_SYN_G : boolean := false;
37  ALTERA_RAM_G : string := "M9K";
38  PIPE_STAGES_G : natural range 0 to 16 := 0;
39  DATA_WIDTH_G : integer range 1 to (2**24) := 16;
40  ADDR_WIDTH_G : integer range 4 to 48 := 4;
41  INIT_G : slv := "0";
42  FULL_THRES_G : integer range 1 to (2**24) := 1;
43  EMPTY_THRES_G : integer range 1 to (2**24) := 1);
44  port (
45  rst : in sl := not RST_POLARITY_G;
46  clk : in sl;
47  wr_en : in sl;
48  rd_en : in sl;
49  din : in slv(DATA_WIDTH_G-1 downto 0);
50  dout : out slv(DATA_WIDTH_G-1 downto 0);
51  data_count : out slv(ADDR_WIDTH_G-1 downto 0);
52  wr_ack : out sl;
53  valid : out sl;
54  overflow : out sl;
55  underflow : out sl;
56  prog_full : out sl;
57  prog_empty : out sl;
58  almost_full : out sl;
60  full : out sl;
61  not_full : out sl;
62  empty : out sl);
63 end FifoSync;
64 
65 architecture rtl of FifoSync is
66  constant INIT_C : slv(DATA_WIDTH_G-1 downto 0) := ite(INIT_G = "0", slvZero(DATA_WIDTH_G), INIT_G);
67  constant RAM_DEPTH_C : integer := 2**ADDR_WIDTH_G;
68 
69  type RamPortType is
70  record
71  clk : sl;
72  en : sl;
73  rst : sl;
74  we : sl;
75  addr : slv(ADDR_WIDTH_G-1 downto 0);
76  din : slv(DATA_WIDTH_G-1 downto 0);
77  dout : slv(DATA_WIDTH_G-1 downto 0);
78  end record;
79  signal portA, portB : RamPortType;
80 
81  type ReadStatusType is
82  record
83  prog_empty : sl;
84  almost_empty : sl;
85  empty : sl;
86  end record;
87  constant READ_STATUS_INIT_C : ReadStatusType := (
88  prog_empty => '1',
89  almost_empty => '1',
90  empty => '1');
91  signal fifoStatus, fwftStatus : ReadStatusType := READ_STATUS_INIT_C;
92 
93  signal raddr : slv (ADDR_WIDTH_G-1 downto 0);
94  signal waddr : slv (ADDR_WIDTH_G-1 downto 0);
95  signal cnt : slv (ADDR_WIDTH_G-1 downto 0);
96 
97  signal writeAck : sl;
98  signal readAck : sl;
99  signal overflowStatus : sl;
100  signal underflowStatus : sl;
101  signal fullStatus : sl;
102  signal readEnable : sl;
103  signal rstStatus : sl;
104 
105  signal sValid,
106  sRdEn : sl;
107 
108  -- Attribute for XST
109  attribute use_dsp48 : string;
110  attribute use_dsp48 of raddr : signal is USE_DSP48_G;
111  attribute use_dsp48 of waddr : signal is USE_DSP48_G;
112  attribute use_dsp48 of cnt : signal is USE_DSP48_G;
113 
114 begin
115 
116  -- FULL_THRES_G upper range check
117  assert (FULL_THRES_G <= ((2**ADDR_WIDTH_G)-1))
118  report "FULL_THRES_G must be <= ((2**ADDR_WIDTH_G)-1)"
119  severity failure;
120  -- EMPTY_THRES_G upper range check
121  assert (EMPTY_THRES_G <= ((2**ADDR_WIDTH_G)-2))
122  report "EMPTY_THRES_G must be <= ((2**ADDR_WIDTH_G)-2)"
123  severity failure;
124  -- USE_DSP48_G check
125  assert ((USE_DSP48_G = "yes") or (USE_DSP48_G = "no") or (USE_DSP48_G = "auto") or (USE_DSP48_G = "automax"))
126  report "USE_DSP48_G must be either yes, no, auto, or automax"
127  severity failure;
128  -- INIT_G length check
129  assert (INIT_G = "0" or INIT_G'length = DATA_WIDTH_G) report
130  "INIT_G must either be ""0"" or the same length as DATA_WIDTH_G" severity failure;
131 
132  rstStatus <= rst when(RST_POLARITY_G = '1') else not(rst);
133 
134  -- Write ports
135  full <= fullStatus;
136  not_full <= not(fullStatus);
137  wr_ack <= writeAck;
138  overflow <= overflowStatus;
139 
140  process (clk, rst) is
141  begin
142  -- Asynchronous reset
143  if (RST_ASYNC_G and rst = RST_POLARITY_G) then
144  data_count <= (others => '1') after TPD_G;
145  prog_full <= '1' after TPD_G;
146  almost_full <= '1' after TPD_G;
147  fullStatus <= '1' after TPD_G;
148  elsif rising_edge(clk) then
149  -- Synchronous reset
150  if (RST_ASYNC_G = false and rst = RST_POLARITY_G) then
151  data_count <= (others => '1') after TPD_G;
152  prog_full <= '1' after TPD_G;
153  almost_full <= '1' after TPD_G;
154  fullStatus <= '1' after TPD_G;
155  else
156  data_count <= cnt after TPD_G;
157  -- prog_full
158  if (cnt > FULL_THRES_G) then
159  prog_full <= '1' after TPD_G;
160  else
161  prog_full <= '0' after TPD_G;
162  end if;
163  -- almost_full
164  if (cnt = (RAM_DEPTH_C-1)) or (cnt = (RAM_DEPTH_C-2)) or (cnt = (RAM_DEPTH_C-3)) then
165  almost_full <= '1' after TPD_G;
166  else
167  almost_full <= '0' after TPD_G;
168  end if;
169  -- fullStatus
170  if (cnt = (RAM_DEPTH_C-1)) or (cnt = (RAM_DEPTH_C-2)) then
171  fullStatus <= '1' after TPD_G;
172  else
173  fullStatus <= '0' after TPD_G;
174  end if;
175  end if;
176  end if;
177  end process;
178 
179  -- Read ports
180  underflow <= underflowStatus;
181 
182  fifoStatus.prog_empty <= '1' when (cnt < EMPTY_THRES_G) else rstStatus;
183  fifoStatus.almost_empty <= '1' when (cnt = 1) else fifoStatus.empty;
184  fifoStatus.empty <= '1' when (cnt = 0) else rstStatus;
185 
186  FIFO_Gen : if (FWFT_EN_G = false) generate
187  readEnable <= rd_en;
188  valid <= readAck;
189  prog_empty <= fifoStatus.prog_empty;
190  almost_empty <= fifoStatus.almost_empty;
191  empty <= fifoStatus.empty;
192  dout <= portB.dout;
193  end generate;
194 
195  FWFT_Gen : if (FWFT_EN_G = true) generate
196 
197  FifoOutputPipeline_Inst : entity work.FifoOutputPipeline
198  generic map (
199  TPD_G => TPD_G,
204  port map (
205  -- Slave Port
206  sData => portB.dout,
207  sValid => sValid,
208  sRdEn => sRdEn,
209  -- Master Port
210  mData => dout,
211  mValid => valid,
212  mRdEn => rd_en,
213  -- Clock and Reset
214  clk => clk,
215  rst => rst);
216 
217  readEnable <= (sRdEn or fwftStatus.empty) and not(fifoStatus.empty);
218  sValid <= not(fwftStatus.empty);
219 
220  prog_empty <= fwftStatus.prog_empty;
221  almost_empty <= fwftStatus.almost_empty;
222  empty <= fwftStatus.empty;
223  process (clk, rst) is
224  begin
225  -- Asynchronous reset
226  if (RST_ASYNC_G and rst = RST_POLARITY_G) then
227  fwftStatus <= READ_STATUS_INIT_C after TPD_G;
228  elsif rising_edge(clk) then
229  -- Synchronous reset
230  if (RST_ASYNC_G = false and rst = RST_POLARITY_G) then
231  fwftStatus <= READ_STATUS_INIT_C after TPD_G;
232  else
233  fwftStatus.prog_empty <= fifoStatus.prog_empty after TPD_G;
234  fwftStatus.almost_empty <= fifoStatus.almost_empty after TPD_G;
235  fwftStatus.empty <= (sRdEn or fwftStatus.empty) and fifoStatus.empty after TPD_G;
236  end if;
237  end if;
238  end process;
239  end generate;
240 
241  process (clk, rst) is
242  begin
243  -- Asynchronous reset
244  if (RST_ASYNC_G and rst = RST_POLARITY_G) then
245  writeAck <= '0' after TPD_G;
246  readAck <= '0' after TPD_G;
247  waddr <= (others => '0') after TPD_G;
248  raddr <= (others => '0') after TPD_G;
249  cnt <= (others => '0') after TPD_G;
250  overflowStatus <= '0' after TPD_G;
251  underflowStatus <= '0' after TPD_G;
252  elsif rising_edge(clk) then
253  writeAck <= '0' after TPD_G;
254  readAck <= '0' after TPD_G;
255  overflowStatus <= '0' after TPD_G;
256  underflowStatus <= '0' after TPD_G;
257  -- Synchronous reset
258  if (RST_ASYNC_G = false and rst = RST_POLARITY_G) then
259  waddr <= (others => '0') after TPD_G;
260  raddr <= (others => '0') after TPD_G;
261  cnt <= (others => '0') after TPD_G;
262  else
263 
264  -- Check for write operation
265  if wr_en = '1' then
266  if fullStatus = '0' then
267  -- Increment the write address pointer
268  waddr <= waddr + 1 after TPD_G;
269  writeAck <= '1' after TPD_G;
270  else
271  overflowStatus <= '1' after TPD_G;
272  end if;
273  end if;
274 
275  -- Check for read operation
276  if readEnable = '1' then
277  if fifoStatus.empty = '0' then
278  -- Increment the read address pointer
279  raddr <= raddr + 1 after TPD_G;
280  readAck <= '1' after TPD_G;
281  else
282  underflowStatus <= '1' after TPD_G;
283  end if;
284  end if;
285 
286  -- Increment the FIFO counter
287  if (readEnable = '1') and (wr_en = '0') and (fifoStatus.empty = '0') then
288  cnt <= cnt - 1 after TPD_G;
289  elsif (readEnable = '0') and (wr_en = '1') and (fullStatus = '0') then
290  cnt <= cnt + 1 after TPD_G;
291  end if;
292 
293  end if;
294  end if;
295  end process;
296 
297  -- RAM Port A Mapping
298  portA.clk <= clk;
299  portA.en <= '1';
300  portA.we <= wr_en and not(fullStatus);
301  portA.addr <= waddr;
302  portA.din <= din;
303 
304  -- RAM Port B Mapping
305  portB.clk <= clk;
306  portB.en <= readEnable and not(fifoStatus.empty);
307  portB.rst <= rstStatus;
308  portB.we <= '0';
309  portB.addr <= raddr;
310  portB.din <= (others => '0');
311 
312  BYP_RAM : if (BYP_RAM_G = true) generate
313  portB.dout <= (others => '0');
314  end generate;
315 
316  GEN_RAM : if (BYP_RAM_G = false) generate
317  SimpleDualPortRam_Inst : entity work.SimpleDualPortRam
318  generic map(
319  TPD_G => TPD_G,
320  RST_POLARITY_G => '1', -- portB.rst already converted to active high
321  BRAM_EN_G => BRAM_EN_G,
326  INIT_G => INIT_C)
327  port map (
328  -- Port A
329  clka => portA.clk,
330  ena => portA.en,
331  wea => portA.we,
332  addra => portA.addr,
333  dina => portA.din,
334  -- Port B
335  clkb => portB.clk,
336  enb => portB.en,
337  rstb => '0', -- Rely on rd/wr ptrs
338  addrb => portB.addr,
339  doutb => portB.dout);
340  end generate;
341 
342 end rtl;
ADDR_WIDTH_Ginteger range 4 to 48:= 4
Definition: FifoSync.vhd:40
USE_DSP48_Gstring := "no"
Definition: FifoSync.vhd:35
in addrbslv( ADDR_WIDTH_G- 1 downto 0) :=( others => '0')
in wr_ensl
Definition: FifoSync.vhd:47
BRAM_EN_Gboolean := true
in rstbsl :=not ( RST_POLARITY_G)
RST_ASYNC_Gboolean := false
out prog_emptysl
Definition: FifoSync.vhd:57
ALTERA_RAM_Gstring := "M9K"
out doutbslv( DATA_WIDTH_G- 1 downto 0)
in rstsl :=not RST_POLARITY_G
Definition: FifoSync.vhd:45
DATA_WIDTH_Ginteger range 1 to ( 2** 24):= 16
std_logic sl
Definition: StdRtlPkg.vhd:28
BRAM_EN_Gboolean := true
Definition: FifoSync.vhd:32
out prog_fullsl
Definition: FifoSync.vhd:56
out overflowsl
Definition: FifoSync.vhd:54
out validsl
Definition: FifoSync.vhd:53
out data_countslv( ADDR_WIDTH_G- 1 downto 0)
Definition: FifoSync.vhd:51
PIPE_STAGES_Gnatural range 0 to 16:= 0
Definition: FifoSync.vhd:38
out almost_emptysl
Definition: FifoSync.vhd:59
TPD_Gtime := 1 ns
Definition: FifoSync.vhd:29
ALTERA_RAM_Gstring := "M9K"
Definition: FifoSync.vhd:37
DATA_WIDTH_Ginteger range 1 to ( 2** 24):= 16
Definition: FifoSync.vhd:39
in dinslv( DATA_WIDTH_G- 1 downto 0)
Definition: FifoSync.vhd:49
RST_POLARITY_Gsl := '1'
Definition: FifoSync.vhd:30
out emptysl
Definition: FifoSync.vhd:62
FULL_THRES_Ginteger range 1 to ( 2** 24):= 1
Definition: FifoSync.vhd:42
ADDR_WIDTH_Ginteger range 1 to ( 2** 24):= 4
in addraslv( ADDR_WIDTH_G- 1 downto 0) :=( others => '0')
out underflowsl
Definition: FifoSync.vhd:55
out doutslv( DATA_WIDTH_G- 1 downto 0)
Definition: FifoSync.vhd:50
in clksl
Definition: FifoSync.vhd:46
in rd_ensl
Definition: FifoSync.vhd:48
in rstsl :=not RST_POLARITY_G
ALTERA_SYN_Gboolean := false
Definition: FifoSync.vhd:36
PIPE_STAGES_Gnatural range 0 to 16:= 1
ALTERA_SYN_Gboolean := false
out almost_fullsl
Definition: FifoSync.vhd:58
RST_ASYNC_Gboolean := false
Definition: FifoSync.vhd:31
FWFT_EN_Gboolean := false
Definition: FifoSync.vhd:34
out wr_acksl
Definition: FifoSync.vhd:52
out not_fullsl
Definition: FifoSync.vhd:61
DATA_WIDTH_Ginteger range 1 to ( 2** 24):= 16
in sDataslv( DATA_WIDTH_G- 1 downto 0)
out mDataslv( DATA_WIDTH_G- 1 downto 0)
BYP_RAM_Gboolean := false
Definition: FifoSync.vhd:33
INIT_Gslv := "0"
Definition: FifoSync.vhd:41
EMPTY_THRES_Ginteger range 1 to ( 2** 24):= 1
Definition: FifoSync.vhd:43
out fullsl
Definition: FifoSync.vhd:60
std_logic_vector slv
Definition: StdRtlPkg.vhd:29
in dinaslv( DATA_WIDTH_G- 1 downto 0) :=( others => '0')