eFEX firmware  1.7.3
ATLAS l1-calo - electron and tau feature extraction firmware for eFEX boards

Back to eFEX documentation
packet_ram_fifo.vhd
Go to the documentation of this file.
1 
10 
11 library IEEE;
12 use IEEE.STD_LOGIC_1164.ALL;
13 USE IEEE.NUMERIC_STD.ALL;
14 
16 entity packet_ram_fifo is
17  Generic (
19  DATA_WIDTH: positive := 64;
21  constant BUFWIDTH: positive := 10;
23  constant MAXWIDTH: positive := 5
24  );
25  Port (
27  clk : in STD_LOGIC;
29  rst_clk : in STD_LOGIC;
31  in_data : in STD_LOGIC_VECTOR(DATA_WIDTH-1 downto 0);
33  in_valid : in STD_LOGIC;
35  in_last : in STD_LOGIC;
37  out_pause : in STD_LOGIC;
39  out_data : out STD_LOGIC_VECTOR(DATA_WIDTH-1 downto 0);
41  out_valid : out STD_LOGIC;
43  out_last : out STD_LOGIC;
45  fifo_fill_level : out STD_LOGIC_VECTOR(15 downto 0);
47  packet_count : out STD_LOGIC_VECTOR(15 downto 0);
49  in_error : out STD_LOGIC;
51  out_error : out STD_LOGIC
52  );
53 end packet_ram_fifo;
54 
56 architecture Behavioral of packet_ram_fifo is
57 
58 type FIFO_Memory is array (0 to 2**BUFWIDTH - 1) of STD_LOGIC_VECTOR(DATA_WIDTH downto 0);
59 signal Memory : FIFO_Memory;
60 attribute ram_style : string;
61 attribute ram_style of Memory : signal is "block";
62 
63 signal fifo_fill_level_sig, write_ptr, read_ptr, new_read_ptr, read_addr, read_reg, npacket_sig : unsigned(BUFWIDTH-1 downto 0);
64 signal mem_out_reg, mem_out_data: STD_LOGIC_VECTOR(DATA_WIDTH downto 0);
65 signal in_data_reg: STD_LOGIC_VECTOR(DATA_WIDTH-1 downto 0);
66 signal rst_reg, in_valid_reg, in_last_reg, out_valid_sig, error_sig, input_error_sig, reset_ptr, running_sig, input_ok_sig: STD_LOGIC;
67 signal packet_change_sig: STD_LOGIC_VECTOR(1 downto 0);
68 
69 begin
70 
71  out_data <= mem_out_data(DATA_WIDTH-1 downto 0)
72 -- pragma translate_off
73  when out_valid_sig = '1' else (others => '0')
74 -- pragma translate_on
75  ;
76  out_last <= mem_out_data(DATA_WIDTH) or error_sig
77 -- pragma translate_off
78  when out_valid_sig = '1' else '0'
79 -- pragma translate_on
80  ;
81  in_error <= input_error_sig;
82  out_error <= error_sig;
83  out_valid <= out_valid_sig;
84  fifo_fill_level(BUFWIDTH-1 downto 0) <= STD_LOGIC_VECTOR(fifo_fill_level_sig);
85  fifo_fill_level(15 downto BUFWIDTH) <= (Others => '0');
86  packet_count(BUFWIDTH-1 downto 0) <= STD_LOGIC_VECTOR(npacket_sig);
87  packet_count(15 downto BUFWIDTH) <= (Others => '0');
88 
89  input_reg: process (clk)
90  begin
91  if rising_edge(clk) then
92  in_data_reg <= in_data
93 -- pragma translate_off
94  after 2 ns
95 -- pragma translate_on
96  ;
97  in_valid_reg <= in_valid
98 -- pragma translate_off
99  after 2 ns
100 -- pragma translate_on
101  ;
102  in_last_reg <= in_last
103 -- pragma translate_off
104  after 2 ns
105 -- pragma translate_on
106  ;
107  rst_reg <= rst_clk
108 -- pragma translate_off
109  after 2 ns
110 -- pragma translate_on
111  ;
112  end if;
113  end process input_reg;
114 
115  input_block: process (clk)
116  begin
117  if rising_edge(clk) then
118  if (in_valid_reg = '1') and (input_ok_sig = '1') then
119  -- Write Data to Memory
120  Memory(to_integer(write_ptr)) <= (in_last_reg or input_error_sig) & in_data_reg
121 -- pragma translate_off
122  after 2 ns
123 -- pragma translate_on
124  ;
125  end if;
126  end if;
127  end process input_block;
128 
129 -- Check for excessive input blocks, veto rest of packet if overrun
130  input_error_block: process (clk)
131  variable Watchdog : unsigned(MAXWIDTH downto 0);
132  variable input_error, input_ok : STD_LOGIC;
133  begin
134  if rising_edge(clk) then
135  if rst_reg = '1' then
136  Watchdog := (Others => '0');
137  input_ok := '1';
138  input_error := '0';
139  else
140 -- if watchdog has fired veto rest of packet until tlast
141  if (in_valid_reg = '1') and (in_last_reg = '1') then
142  input_ok := '1';
143  elsif (input_error_sig = '1') then
144  input_ok := '0';
145  end if;
146  input_error := '0';
147  if (in_valid = '1') then
148  if (in_last = '1') then
149  Watchdog := (Others => '0');
150  else
151  Watchdog := Watchdog + 1;
152  end if;
153  if (Watchdog(MAXWIDTH) = '1') and (input_ok = '1') then
154  input_error := '1';
155  end if;
156  end if;
157  end if;
158  input_error_sig <= input_error
159 -- pragma translate_off
160  after 2 ns
161 -- pragma translate_on
162  ;
163  input_ok_sig <= input_ok
164 -- pragma translate_off
165  after 2 ns
166 -- pragma translate_on
167  ;
168  end if;
169  end process input_error_block;
170 
171  output_block: process (clk)
172  begin
173  if rising_edge(clk) then
174  mem_out_reg <= Memory(to_integer(read_ptr))
175 -- pragma translate_off
176  after 2 ns
177 -- pragma translate_on
178  ;
179  end if;
180  end process output_block;
181 
182  output_reg: process (clk)
183  begin
184  if rising_edge(clk) then
185  mem_out_data <= mem_out_reg
186 -- pragma translate_off
187  after 2 ns
188 -- pragma translate_on
189  ;
190  end if;
191  end process output_reg;
192 
193  -- Output Control Process
194  fifo_proc : process (clk)
195  variable Watchdog : unsigned(MAXWIDTH downto 0);
196  variable error, packet_up, packet_down, Running : STD_LOGIC;
197  variable packet_change: STD_LOGIC_VECTOR(1 downto 0);
198  variable valid, reset_buf: std_logic_vector(2 downto 0);
199  begin
200  if rising_edge(clk) then
201  packet_down := '0';
202  packet_up := '0';
203  if rst_reg = '1' then
204  Watchdog := (Others => '0');
205  Running := '0';
206  reset_buf := (Others => '0');
207  error := '1'; -- trigger (packet_change_sig = "11")...
208  else
209 
210  if (in_valid_reg = '1') and (input_ok_sig = '1') then
211  if (in_last_reg = '1') or (input_error_sig = '1') then -- Last on incoming packet
212  packet_up := '1';
213  end if;
214  end if;
215 
216  if (Running = '1') then
217  -- Stop running if out_last was sent
218  if ((error = '1') or (mem_out_data(DATA_WIDTH) = '1')) and (out_valid_sig = '1') then
219  Running := '0';
220  packet_down := '1';
221  reset_buf := (Others => '1');
222  elsif (out_valid_sig = '1') then
223  Watchdog := Watchdog + 1;
224  end if;
225  elsif (npacket_sig /= 0) and (reset_buf(2) = '0') and (out_pause = '0') then
226  Running := '1';
227  Watchdog := (Others => '0');
228  else
229  reset_buf := reset_buf(1 downto 0) & '0';
230  end if;
231 
232  end if;
233 
234  If (Running = '1') then
235  valid := valid(1 downto 0) & not out_pause;
236  -- Die gracefully if the FIFO runs dry...
237  If (fifo_fill_level_sig = 0) or (Watchdog(MAXWIDTH) = '1') then
238  error := '1';
239  end if;
240  else
241  valid := (Others => '0');
242  end if;
243 
244  if (Running = '0') and (error = '1') then
245  packet_change := "11";
246  error := '0';
247  elsif (packet_up = packet_down) then
248  packet_change := "00";
249  else
250  packet_change := packet_up & packet_down;
251  end if;
252 
253  running_sig <= Running
254 -- pragma translate_off
255  after 2 ns
256 -- pragma translate_on
257  ;
258  error_sig <= error
259 -- pragma translate_off
260  after 2 ns
261 -- pragma translate_on
262  ;
263  reset_ptr <= reset_buf(0)
264 -- pragma translate_off
265  after 2 ns
266 -- pragma translate_on
267  ;
268  out_valid_sig <= valid(2)
269 -- pragma translate_off
270  after 2 ns
271 -- pragma translate_on
272  ;
273  packet_change_sig <= packet_change
274 -- pragma translate_off
275  after 2 ns
276 -- pragma translate_on
277  ;
278  end if;
279  end process fifo_proc;
280 
281  write_pointer_proc : process(clk)
282  variable Head, NextHead : unsigned(BUFWIDTH downto 0);
283  begin
284  if rising_edge(clk) then
285  if (packet_change_sig = "11") then
286  NextHead := (Others => '0');
287  else
288  Head := "0" & write_ptr;
289  if (in_valid_reg = '1') and (input_ok_sig = '1') then
290  NextHead := Head + 1;
291  else
292  NextHead := Head;
293  end if;
294  end if;
295  write_ptr <= NextHead(BUFWIDTH-1 downto 0)
296 -- pragma translate_off
297  after 2 ns
298 -- pragma translate_on
299  ;
300  end if;
301  end process write_pointer_proc;
302 
303  read_pointer_proc : process(clk)
304  variable Tail, NextTail, ThisAddr, NextAddr : unsigned(BUFWIDTH downto 0);
305  begin
306  if rising_edge(clk) then
307  if (packet_change_sig = "11") then
308  NextTail := (Others => '0');
309  else
310  if (reset_ptr = '1') then
311  Tail := "0" & new_read_ptr;
312  else
313  Tail := "0" & read_ptr;
314  end if;
315  if ((running_sig = '1') and (out_pause = '0')) then
316  NextTail := Tail + 1;
317  else
318  NextTail := Tail;
319  end if;
320  ThisAddr := "0" & read_addr;
321  NextAddr := ThisAddr + 1;
322  end if;
323  read_ptr <= NextTail(BUFWIDTH-1 downto 0)
324 -- pragma translate_off
325  after 2 ns
326 -- pragma translate_on
327  ;
328  read_reg <= read_ptr
329 -- pragma translate_off
330  after 2 ns
331 -- pragma translate_on
332  ;
333  read_addr <= read_reg
334 -- pragma translate_off
335  after 2 ns
336 -- pragma translate_on
337  ;
338  new_read_ptr <= NextAddr(BUFWIDTH-1 downto 0)
339 -- pragma translate_off
340  after 2 ns
341 -- pragma translate_on
342  ;
343  end if;
344  end process read_pointer_proc;
345 
346  packet_count_proc : process(clk)
347  variable npacket : unsigned(BUFWIDTH-1 downto 0);
348  constant zeros: unsigned(BUFWIDTH-1 downto 0) := (Others => '0');
349  begin
350  if rising_edge(clk) then
351  Case packet_change_sig is
352  When "11" =>
353  npacket := (Others => '0');
354  When "10" =>
355  npacket := npacket + 1;
356  When "01" =>
357  if (npacket /= zeros) then
358  npacket := npacket - 1;
359  end if;
360  When Others =>
361  null;
362  End Case;
363  npacket_sig <= npacket
364 -- pragma translate_off
365  after 2 ns
366 -- pragma translate_on
367  ;
368  end if;
369  end process packet_count_proc;
370 
371  fill_level_proc : process(clk)
372  variable FillLevel, Head, Tail : unsigned(BUFWIDTH downto 0);
373  begin
374  if rising_edge(clk) then
375  if rst_reg = '1' then
376  FillLevel := (Others => '0');
377  Tail := (Others => '0');
378  else
379  Head := "1" & write_ptr;
380  if (running_sig = '1') then
381  Tail := "0" & read_addr;
382  elsif (reset_ptr = '1') then
383  Tail := "0" & new_read_ptr;
384  end if;
385  FillLevel := Head - Tail;
386  end if;
387  fifo_fill_level_sig <= FillLevel(BUFWIDTH-1 downto 0)
388 -- pragma translate_off
389  after 2 ns
390 -- pragma translate_on
391  ;
392  end if;
393  end process fill_level_proc;
394 
395 end Behavioral;
Optimised RAM-based single clock packet FIFO.
Optimised RAM-based single clock packet FIFO.
out out_data STD_LOGIC_VECTOR( DATA_WIDTH- 1 downto 0)
AXI stream output.
in in_data STD_LOGIC_VECTOR( DATA_WIDTH- 1 downto 0)
AXI stream input.
MAXWIDTH positive := 5
Parameter for maximum packet size (2**MAXWIDTH - 1) on input or output before trigger reset mechanism...
out out_error STD_LOGIC
AXI stream output error (asserted on last)
in rst_clk STD_LOGIC
Synchronous reset.
out packet_count STD_LOGIC_VECTOR( 15 downto 0)
Number of packets stored in the FIFO.
in clk STD_LOGIC
Clock.
DATA_WIDTH positive := 64
Width of data for RAM.
in out_pause STD_LOGIC
AXI stream output pause request.
out out_valid STD_LOGIC
AXI stream output valid.
in in_last STD_LOGIC
AXI stream input last.
in in_valid STD_LOGIC
AXI stream input valid.
out fifo_fill_level STD_LOGIC_VECTOR( 15 downto 0)
Number of words stored in the FIFO.
BUFWIDTH positive := 10
Width of address bus for RAM, i.e. array (0 to 2**BUFWIDTH - 1)
out out_last STD_LOGIC
AXI stream output last.
out in_error STD_LOGIC
AXI stream input error.