OpenCores
URL https://opencores.org/ocsvn/udp_ip_stack/udp_ip_stack/trunk

Subversion Repositories udp_ip_stack

[/] [udp_ip_stack/] [trunk/] [contrib/] [Headers sometimes have errors/] [rx_client_fifo.vhd] - Blame information for rev 37

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 35 pjf
--------------------------------------------------------------------------------
2
-- Title      : Receiver FIFO with AxiStream interfaces
3
-- Project    : Tri-Mode Ethernet MAC
4
--------------------------------------------------------------------------------
5
-- File       : rx_client_fifo.vhd
6
-- Author     : Xilinx Inc.
7
-- Project    : Virtex-6 Embedded Tri-Mode Ethernet MAC Wrapper
8
-- File       : rx_client_fifo.vhd
9
-- Version    : 2.1
10
-------------------------------------------------------------------------------
11
--
12
-- (c) Copyright 2004-2008 Xilinx, Inc. All rights reserved.
13
--
14
-- This file contains confidential and proprietary information
15
-- of Xilinx, Inc. and is protected under U.S. and
16
-- international copyright and other intellectual property
17
-- laws.
18
--
19
-- DISCLAIMER
20
-- This disclaimer is not a license and does not grant any
21
-- rights to the materials distributed herewith. Except as
22
-- otherwise provided in a valid license issued to you by
23
-- Xilinx, and to the maximum extent permitted by applicable
24
-- law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
25
-- WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
26
-- AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
27
-- BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
28
-- INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
29
-- (2) Xilinx shall not be liable (whether in contract or tort,
30
-- including negligence, or under any other theory of
31
-- liability) for any loss or damage of any kind or nature
32
-- related to, arising under or in connection with these
33
-- materials, including for any direct, or any indirect,
34
-- special, incidental, or consequential loss or damage
35
-- (including loss of data, profits, goodwill, or any type of
36
-- loss or damage suffered as a result of any action brought
37
-- by a third party) even if such damage or loss was
38
-- reasonably foreseeable or Xilinx had been advised of the
39
-- possibility of the same.
40
--
41
-- CRITICAL APPLICATIONS
42
-- Xilinx products are not designed or intended to be fail-
43
-- safe, or for use in any application requiring fail-safe
44
-- performance, such as life-support or safety devices or
45
-- systems, Class III medical devices, nuclear facilities,
46
-- applications related to the deployment of airbags, or any
47
-- other applications that could lead to death, personal
48
-- injury, or severe property or environmental damage
49
-- (individually and collectively, "Critical
50
-- Applications"). Customer assumes the sole risk and
51
-- liability of any use of Xilinx products in Critical
52
-- Applications, subject only to applicable laws and
53
-- regulations governing limitations on product liability.
54
--
55
-- THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
56
-- PART OF THIS FILE AT ALL TIMES.
57
--
58
-- Description: This is the receiver side FIFO for the design example
59
--              of the Tri-Mode Ethernet MAC core. AxiStream interfaces are used.
60
--
61
--              The FIFO is created from 2 Block RAMs of size 2048
62
--              words of 8-bits per word, giving a total frame memory capacity
63
--              of 4096 bytes.
64
--
65
--              Frame data received from the MAC receiver is written into the
66
--              FIFO on the rx_mac_aclk. An end-of-frame marker is written to
67
--              the BRAM parity bit on the last byte of data stored for a frame.
68
--              This acts as frame deliniation.
69
--
70
--              The rx_axis_mac_tvalid, rx_axis_mac_tlast, and rx_axis_mac_tuser signals
71
--              qualify the frame. A frame which ends with rx_axis_mac_tuser asserted
72
--              indicates a bad frame and will cause the FIFO write address
73
--              pointer to be reset to the base address of that frame. In this
74
--              way the bad frame will be overwritten with the next received
75
--              frame and is therefore dropped from the FIFO.
76
--
77
--              Frames will also be dropped from the FIFO if an overflow occurs.
78
--              If there is not enough memory capacity in the FIFO to store the
79
--              whole of an incoming frame, the write address pointer will be
80
--              reset and the overflow signal asserted.
81
--
82
--              When there is at least one complete frame in the FIFO,
83
--              the 8-bit AxiStream read interface's rx_axis_fifo_tvalid signal will
84
--              be enabled allowing data to be read from the FIFO.
85
--
86
--              The FIFO has been designed to operate with different clocks
87
--              on the write and read sides. The read clock (user side) should
88
--              always operate at an equal or faster frequency than the write
89
--              clock (MAC side).
90
--
91
--              The FIFO is designed to work with a minimum frame length of 8
92
--              bytes.
93
--
94
--              The FIFO memory size can be increased by expanding the rd_addr
95
--              and wr_addr signal widths, to address further BRAMs.
96
--
97
--              Requirements :
98
--              * Minimum frame size of 8 bytes
99
--              * Spacing between good/bad frame signaling (encoded by
100
--                rx_axis_mac_tvalid, rx_axis_mac_tlast, rx_axis_mac_tuser), is at least 64
101
--                clock cycles
102
--              * Write AxiStream clock is 125MHz downto 1.25MHz
103
--              * Read AxiStream clock equal to or faster than write clock,
104
--                and downto 20MHz
105
--
106
--------------------------------------------------------------------------------
107
 
108
library unisim;
109
use unisim.vcomponents.all;
110
 
111
library unimacro;
112
use unimacro.vcomponents.all;
113
 
114
library ieee;
115
use ieee.std_logic_1164.all;
116
use ieee.std_logic_unsigned.all;
117
use ieee.numeric_std.all;
118
 
119
 
120
--------------------------------------------------------------------------------
121
-- The entity declaration for the Receiver FIFO
122
--------------------------------------------------------------------------------
123
 
124
entity rx_client_fifo is
125
  port (
126
     -- User-side (read-side) AxiStream interface
127
     rx_fifo_aclk   : in  std_logic;
128
     rx_fifo_resetn : in  std_logic;
129
     rx_axis_fifo_tdata : out std_logic_vector(7 downto 0);
130
     rx_axis_fifo_tvalid : out std_logic;
131
     rx_axis_fifo_tlast : out std_logic;
132
     rx_axis_fifo_tready : in  std_logic;
133
 
134
     -- MAC-side (write-side) AxiStream interface
135
     rx_mac_aclk    : in  std_logic;
136
     rx_mac_resetn    : in  std_logic;
137
     rx_axis_mac_tdata : in  std_logic_vector(7 downto 0);
138
     rx_axis_mac_tvalid : in  std_logic;
139
     rx_axis_mac_tlast : in  std_logic;
140
     rx_axis_mac_tready : out std_logic;
141
     rx_axis_mac_tuser : in  std_logic;
142
 
143
     -- FIFO status and overflow indication,
144
     -- synchronous to write-side (rx_mac_aclk) interface
145
     fifo_status    : out std_logic_vector(3 downto 0);
146
     fifo_overflow  : out std_logic
147
     );
148
end rx_client_fifo;
149
 
150
 
151
architecture RTL of rx_client_fifo is
152
 
153
 
154
  ------------------------------------------------------------------------------
155
  -- Component declaration for the synchronisation flip-flop pair
156
  ------------------------------------------------------------------------------
157
  component sync_block
158
  port (
159
    clk                : in  std_logic;
160
    data_in            : in  std_logic;
161
    data_out           : out std_logic
162
    );
163
  end component;
164
 
165
 
166
  ------------------------------------------------------------------------------
167
  -- Define internal signals
168
  ------------------------------------------------------------------------------
169
 
170
  signal VCC                 : std_logic;
171
  signal GND_BUS             : std_logic_vector(8 downto 0);
172
  signal GND                 : std_logic_vector(0 downto 0);
173
 
174
  -- Encoded read state machine states
175
  type rd_state_typ is      (WAIT_s,
176
                             QUEUE1_s,
177
                             QUEUE2_s,
178
                             QUEUE3_s,
179
                             QUEUE_SOF_s,
180
                             SOF_s,
181
                             DATA_s,
182
                             EOF_s);
183
 
184
  signal rd_state            : rd_state_typ;
185
  signal rd_nxt_state        : rd_state_typ;
186
 
187
  -- Encoded write state machine states
188
  type wr_state_typ is      (IDLE_s,
189
                             FRAME_s,
190
                             GF_s,
191
                             BF_s,
192
                             OVFLOW_s);
193
 
194
  signal wr_state            : wr_state_typ;
195
  signal wr_nxt_state        : wr_state_typ;
196
 
197
  type data_pipe is array (0 to 1) of std_logic_vector(7 downto 0);
198
  type cntl_pipe_long is array(0 to 2) of std_logic;
199
  type cntl_pipe_short is array(0 to 1) of std_logic;
200
 
201
  signal wr_en               : std_logic;
202
  signal wr_en_u             : std_logic;
203
  signal wr_en_u_bram        : std_logic_vector(0 downto 0);
204
  signal wr_en_l             : std_logic;
205
  signal wr_en_l_bram        : std_logic_vector(0 downto 0);
206
  signal wr_addr             : unsigned(11 downto 0);
207
  signal wr_addr_inc         : std_logic;
208
  signal wr_start_addr_load  : std_logic;
209
  signal wr_addr_reload      : std_logic;
210
  signal wr_start_addr       : unsigned(11 downto 0);
211
  signal wr_eof_data_bram    : std_logic_vector(8 downto 0);
212
  signal wr_data_bram        : std_logic_vector(7 downto 0);
213
  signal wr_data_pipe        : data_pipe;
214
  signal wr_dv_pipe          : cntl_pipe_long;
215
  signal wr_gfbf_pipe        : cntl_pipe_short;
216
  signal wr_gf               : std_logic;
217
  signal wr_bf               : std_logic;
218
  signal wr_eof_bram_pipe    : cntl_pipe_short;
219
  signal wr_eof_bram         : std_logic;
220
  signal frame_in_fifo       : std_logic;
221
 
222
  signal rd_addr             : unsigned(11 downto 0);
223
  signal rd_addr_inc         : std_logic;
224
  signal rd_addr_reload      : std_logic;
225
  signal rd_eof_data_bram_u  : std_logic_vector(8 downto 0);
226
  signal rd_eof_data_bram_l  : std_logic_vector(8 downto 0);
227
  signal rd_data_bram_u      : std_logic_vector(7 downto 0);
228
  signal rd_data_bram_l      : std_logic_vector(7 downto 0);
229
  signal rd_data_pipe_u      : std_logic_vector(7 downto 0);
230
  signal rd_data_pipe_l      : std_logic_vector(7 downto 0);
231
  signal rd_data_pipe        : std_logic_vector(7 downto 0);
232
  signal rd_valid_pipe       : std_logic_vector(1 downto 0);
233
  signal rd_eof_bram_u       : std_logic_vector(0 downto 0);
234
  signal rd_eof_bram_l       : std_logic_vector(0 downto 0);
235
  signal rd_en               : std_logic;
236
  signal rd_bram_u           : std_logic;
237
  signal rd_bram_u_reg       : std_logic;
238
  signal rd_pull_frame       : std_logic;
239
  signal rd_eof              : std_logic;
240
 
241
  signal wr_store_frame_tog  : std_logic := '0';
242
  signal rd_store_frame_sync : std_logic;
243
  signal rd_store_frame_delay : std_logic := '0';
244
  signal rd_store_frame      : std_logic;
245
  signal rd_frames           : std_logic_vector(8 downto 0);
246
  signal wr_fifo_full        : std_logic;
247
 
248
  signal old_rd_addr         : std_logic_vector(1 downto 0);
249
  signal update_addr_tog     : std_logic;
250
  signal update_addr_tog_sync : std_logic;
251
  signal update_addr_tog_sync_reg : std_logic;
252
 
253
  signal wr_rd_addr          : unsigned(11 downto 0);
254
  signal wr_addr_diff_in     : unsigned(12 downto 0);
255
  signal wr_addr_diff        : unsigned(11 downto 0);
256
 
257
  signal wr_fifo_status      : unsigned(3 downto 0);
258
  signal rx_axis_fifo_tlast_int : std_logic;
259
 
260
  signal doa_l_unused        : std_logic_vector(8 downto 0);
261
  signal doa_u_unused        : std_logic_vector(8 downto 0);
262
 
263
  signal rx_fifo_reset       : std_logic;
264
  signal rx_mac_reset        : std_logic;
265
 
266
 
267
--------------------------------------------------------------------------------
268
-- Begin FIFO architecture
269
--------------------------------------------------------------------------------
270
 
271
begin
272
 
273
  VCC     <= '1';
274
  GND_BUS <= (others => '0');
275
  GND(0)  <= GND_BUS(0);
276
 
277
  -- invert reset sense as architecture is optimised for active high resets
278
  rx_fifo_reset <= not rx_fifo_resetn;
279
  rx_mac_reset  <= not rx_mac_resetn;
280
 
281
  ------------------------------------------------------------------------------
282
  -- Read state machines and control
283
  ------------------------------------------------------------------------------
284
 
285
  -- Read state machine.
286
  -- States are WAIT, QUEUE1, QUEUE2, QUEUE3, QUEUE_SOF, SOF, DATA, EOF.
287
  -- Clock state to next state.
288
  clock_rds_p : process(rx_fifo_aclk)
289
  begin
290
     if (rx_fifo_aclk'event and rx_fifo_aclk = '1') then
291
        if rx_fifo_reset = '1' then
292
           rd_state <= WAIT_s;
293
        else
294
           rd_state <= rd_nxt_state;
295
        end if;
296
     end if;
297
  end process clock_rds_p;
298
 
299
  rx_axis_fifo_tlast <= rx_axis_fifo_tlast_int;
300
 
301
  -- Decode next state, combinatorial.
302
  next_rds_p : process(rd_state, frame_in_fifo, rd_eof, rx_axis_fifo_tready,
303
                       rx_axis_fifo_tlast_int, rd_valid_pipe)
304
  begin
305
     case rd_state is
306
        when WAIT_s =>
307
           -- Wait until there is a full frame in the FIFO, then
308
           -- start to load the pipeline.
309
           if frame_in_fifo = '1' and rx_axis_fifo_tlast_int = '0' then
310
              rd_nxt_state <= QUEUE1_s;
311
           else
312
              rd_nxt_state <= WAIT_s;
313
           end if;
314
 
315
        -- Load the output pipeline, which takes three clock cycles.
316
        when QUEUE1_s =>
317
           rd_nxt_state <= QUEUE2_s;
318
 
319
        when QUEUE2_s =>
320
           rd_nxt_state <= QUEUE3_s;
321
 
322
        when QUEUE3_s =>
323
           rd_nxt_state <= QUEUE_SOF_s;
324
 
325
        when QUEUE_SOF_s =>
326
           -- The pipeline is full and the frame output starts now.
327
           rd_nxt_state <= DATA_s;
328
 
329
        when SOF_s =>
330
           -- A new frame begins immediately following end of last frame.
331
           if rx_axis_fifo_tready = '1' then
332
              rd_nxt_state <= DATA_s;
333
           else
334
              rd_nxt_state <= SOF_s;
335
           end if;
336
 
337
        when DATA_s =>
338
           -- Read data from the FIFO. When the EOF marker is detected from
339
           -- the BRAM output, move to the EOF state.
340
           if rx_axis_fifo_tready = '1' and rd_eof = '1' then
341
              rd_nxt_state <= EOF_s;
342
           else
343
              rd_nxt_state <= DATA_s;
344
           end if;
345
 
346
        when EOF_s =>
347
           -- Hold in this state until tready is asserted and the EOF
348
           -- marker (tlast) is accepted on interface.
349
           -- If there is another frame in the FIFO, then it will already be
350
           -- queued into the pipeline so so move straight to SOF state.
351
           if rx_axis_fifo_tready = '1' then
352
              if rd_valid_pipe(1) = '1' then
353
                rd_nxt_state <= SOF_s;
354
              else
355
                 rd_nxt_state <= WAIT_s;
356
              end if;
357
           else
358
              rd_nxt_state <= EOF_s;
359
           end if;
360
 
361
        when others =>
362
           rd_nxt_state <= WAIT_s;
363
        end case;
364
  end process next_rds_p;
365
 
366
  -- Detect if frame_in_fifo was high 3 reads ago.
367
  -- This is used to ensure we only treat data in the pipeline as valid if
368
  -- frame_in_fifo goes high at or before the EOF marker of the current frame.
369
  -- It may be that there is valid data (i.e a partial frame has been written)
370
  -- but until the end of that frame we do not know if it is a good frame.
371
  rd_valid_pipe_p : process(rx_fifo_aclk)
372
  begin
373
     if (rx_fifo_aclk'event and rx_fifo_aclk = '1') then
374
         if (rx_axis_fifo_tready = '1') then
375
            rd_valid_pipe <= rd_valid_pipe(0) & frame_in_fifo;
376
         end if;
377
     end if;
378
  end process rd_valid_pipe_p;
379
 
380
  -- Decode tlast signal from EOF marker.
381
  rd_ll_decode_p : process(rx_fifo_aclk)
382
  begin
383
     if (rx_fifo_aclk'event and rx_fifo_aclk = '1') then
384
        if rx_fifo_reset = '1' then
385
           rx_axis_fifo_tlast_int <= '0';
386
        elsif rx_axis_fifo_tready = '1' then
387
           -- Assert tlast signal when the EOF marker has been detected, and
388
           -- continue to drive it until it has been accepted on the interface.
389
           case rd_state is
390
              when EOF_s =>
391
                 rx_axis_fifo_tlast_int <= '1';
392
              when others =>
393
                 rx_axis_fifo_tlast_int <= '0';
394
           end case;
395
        end if;
396
     end if;
397
  end process rd_ll_decode_p;
398
 
399
  -- Decode the tvalid output based on state.
400
  rd_ll_src_p : process(rx_fifo_aclk)
401
  begin
402
     if (rx_fifo_aclk'event and rx_fifo_aclk = '1') then
403
        if rx_fifo_reset = '1' then
404
           rx_axis_fifo_tvalid <= '0';
405
        else
406
           case rd_state is
407
              when QUEUE_SOF_s =>
408
                 rx_axis_fifo_tvalid <= '1';
409
              when SOF_s =>
410
                 rx_axis_fifo_tvalid <= '1';
411
              when DATA_s =>
412
                 rx_axis_fifo_tvalid <= '1';
413
              when EOF_s =>
414
                 rx_axis_fifo_tvalid <= '1';
415
              when others =>
416
                 if rx_axis_fifo_tready = '1' then
417
                    rx_axis_fifo_tvalid <= '0';
418
                 end if;
419
            end case;
420
         end if;
421
     end if;
422
  end process rd_ll_src_p;
423
 
424
  -- Decode internal control signals.
425
  -- rd_en is used to enable the BRAM read and load the output pipeline.
426
  rd_en_p : process(rd_state, rx_axis_fifo_tready)
427
  begin
428
     case rd_state is
429
        when WAIT_s =>
430
           rd_en <= '0';
431
        when QUEUE1_s =>
432
           rd_en <= '1';
433
        when QUEUE2_s =>
434
           rd_en <= '1';
435
        when QUEUE3_s =>
436
           rd_en <= '1';
437
        when QUEUE_SOF_s =>
438
           rd_en <= '1';
439
        when others =>
440
           rd_en <= rx_axis_fifo_tready;
441
     end case;
442
  end process rd_en_p;
443
 
444
  -- When the BRAM is being read, enable the read address to be incremented.
445
  rd_addr_inc <= rd_en;
446
 
447
  -- When the current frame is done, and if there is no frame in the FIFO, then
448
  -- the FIFO must wait until a new frame is written in. This requires the read
449
  -- address to be moved back to where the new frame will be written. The
450
  -- pipeline is then reloaded using the QUEUE states.
451
  p_rd_addr_reload : process (rx_fifo_aclk)
452
  begin
453
    if rx_fifo_aclk'event and rx_fifo_aclk = '1' then
454
      if rx_fifo_reset = '1' then
455
        rd_addr_reload <= '0';
456
      else
457
        if rd_state = EOF_s and rd_nxt_state = WAIT_s then
458
          rd_addr_reload <= '1';
459
        else
460
          rd_addr_reload <= '0';
461
        end if;
462
      end if;
463
    end if;
464
  end process p_rd_addr_reload;
465
 
466
  -- Data is available if there is at least one frame stored in the FIFO.
467
  p_rd_avail : process (rx_fifo_aclk)
468
  begin
469
    if rx_fifo_aclk'event and rx_fifo_aclk = '1' then
470
      if rx_fifo_reset = '1' then
471
        frame_in_fifo <= '0';
472
      else
473
        if rd_frames /= (rd_frames'range => '0') then
474
          frame_in_fifo <= '1';
475
        else
476
          frame_in_fifo <= '0';
477
        end if;
478
      end if;
479
    end if;
480
  end process p_rd_avail;
481
 
482
  -- When a frame has been stored we need to synchronize that event to the
483
  -- read clock domain for frame count store.
484
  resync_wr_store_frame_tog : sync_block
485
  port map (
486
    clk       => rx_fifo_aclk,
487
    data_in   => wr_store_frame_tog,
488
    data_out  => rd_store_frame_sync
489
  );
490
 
491
  p_delay_rd_store : process (rx_fifo_aclk)
492
  begin
493
    if rx_fifo_aclk'event and rx_fifo_aclk = '1' then
494
      rd_store_frame_delay <= rd_store_frame_sync;
495
    end if;
496
  end process p_delay_rd_store;
497
 
498
  -- Edge detect of the resynchronized frame count. This creates a pulse
499
  -- when a new frame has been stored.
500
  p_sync_rd_store : process (rx_fifo_aclk)
501
  begin
502
    if rx_fifo_aclk'event and rx_fifo_aclk = '1' then
503
      if rx_fifo_reset = '1' then
504
        rd_store_frame       <= '0';
505
      else
506
        -- Edge detector
507
        if (rd_store_frame_delay xor rd_store_frame_sync) = '1' then
508
          rd_store_frame     <= '1';
509
        else
510
          rd_store_frame     <= '0';
511
        end if;
512
      end if;
513
    end if;
514
  end process p_sync_rd_store;
515
 
516
  -- This creates a pulse when a new frame has begun to be output.
517
  p_rd_pull_frame : process (rx_fifo_aclk)
518
  begin
519
    if rx_fifo_aclk'event and rx_fifo_aclk = '1' then
520
      if rx_fifo_reset = '1' then
521
        rd_pull_frame <= '0';
522
      else
523
        if rd_state = SOF_s and rd_nxt_state /= SOF_s then
524
          rd_pull_frame <= '1';
525
        elsif rd_state = QUEUE_SOF_s and rd_nxt_state /= QUEUE_SOF_s then
526
          rd_pull_frame <= '1';
527
        else
528
          rd_pull_frame <= '0';
529
        end if;
530
      end if;
531
    end if;
532
  end process p_rd_pull_frame;
533
 
534
  -- Up/down counter to monitor the number of frames stored within the FIFO.
535
  -- Note:
536
  --    * increments at the end of a frame write cycle
537
  --    * decrements at the beginning of a frame read cycle
538
  p_rd_frames : process (rx_fifo_aclk)
539
  begin
540
    if rx_fifo_aclk'event and rx_fifo_aclk = '1' then
541
      if rx_fifo_reset = '1' then
542
        rd_frames <= (others => '0');
543
      else
544
        -- A frame is written to the FIFO in this cycle, and no frame is being
545
        -- read out on the same cycle.
546
        if rd_store_frame = '1' and rd_pull_frame = '0' then
547
            rd_frames <= rd_frames + 1;
548
        -- A frame is being read out on this cycle and no frame is being
549
        -- written on the same cycle.
550
        elsif rd_store_frame = '0' and rd_pull_frame = '1' then
551
             rd_frames <= rd_frames - 1;
552
        end if;
553
      end if;
554
    end if;
555
  end process p_rd_frames;
556
 
557
 
558
  ------------------------------------------------------------------------------
559
  -- Write state machines and control
560
  ------------------------------------------------------------------------------
561
 
562
  -- Write state machine.
563
  -- States are IDLE, FRAME, GF, BF, OVFLOW.
564
  -- Clock state to next state.
565
  clock_wrs_p : process(rx_mac_aclk)
566
  begin
567
     if (rx_mac_aclk'event and rx_mac_aclk = '1') then
568
        if rx_mac_reset = '1' then
569
           wr_state <= IDLE_s;
570
        else
571
           wr_state <= wr_nxt_state;
572
        end if;
573
     end if;
574
  end process clock_wrs_p;
575
 
576
  -- Decode next state, combinatorial.
577
  next_wrs_p : process(wr_state, wr_dv_pipe(1), wr_gf, wr_bf, wr_fifo_full)
578
  begin
579
     case wr_state is
580
        when IDLE_s =>
581
           -- There is data in incoming pipeline when dv_pipe(1) goes high.
582
           if wr_dv_pipe(1) = '1' then
583
              wr_nxt_state <= FRAME_s;
584
           else
585
              wr_nxt_state <= IDLE_s;
586
           end if;
587
 
588
        when FRAME_s =>
589
           -- If FIFO is full then go to overflow state.
590
           -- If the good or bad flag is detected, then the end of the frame
591
           -- has been reached and the gf or bf state is visited before idle.
592
           -- Otherwise remain in frame state while data is written to FIFO.
593
           if wr_fifo_full = '1' then
594
              wr_nxt_state <= OVFLOW_s;
595
           elsif wr_gf = '1' then
596
              wr_nxt_state <= GF_s;
597
           elsif wr_bf = '1' then
598
              wr_nxt_state <= BF_s;
599
           else
600
              wr_nxt_state <= FRAME_s;
601
           end if;
602
 
603
        when GF_s =>
604
           -- Return to idle and wait for next frame.
605
           wr_nxt_state <= IDLE_s;
606
 
607
        when BF_s =>
608
           -- Return to idle and wait for next frame.
609
           wr_nxt_state <= IDLE_s;
610
 
611
        when OVFLOW_s =>
612
           -- Wait until the good or bad flag received.
613
           if wr_gf = '1' or wr_bf = '1' then
614
              wr_nxt_state <= IDLE_s;
615
           else
616
              wr_nxt_state <= OVFLOW_s;
617
           end if;
618
 
619
        when others =>
620
           wr_nxt_state <= IDLE_s;
621
     end case;
622
  end process next_wrs_p;
623
 
624
  -- Decode control signals, combinatorial.
625
  -- wr_en is used to enable the BRAM write and loading of the input pipeline.
626
  wr_en <= wr_dv_pipe(2) when wr_state = FRAME_s else '0';
627
 
628
  -- The upper and lower signals are used to distinguish between the upper and
629
  -- lower BRAMs.
630
  wr_en_l <= wr_en and not(wr_addr(11));
631
  wr_en_u <= wr_en and     wr_addr(11);
632
  wr_en_l_bram(0) <= wr_en_l;
633
  wr_en_u_bram(0) <= wr_en_u;
634
 
635
  -- Increment the write address when we are receiving valid frame data.
636
  wr_addr_inc <= wr_dv_pipe(2) when wr_state = FRAME_s else '0';
637
 
638
  -- If the FIFO overflows or a frame is to be dropped, we need to move the
639
  -- write address back to the start of the frame.  This allows the data to be
640
  -- overwritten.
641
  wr_addr_reload <= '1' when wr_state = BF_s or wr_state = OVFLOW_s else '0';
642
 
643
  -- The start address is saved when in the idle state.
644
  wr_start_addr_load <= '1' when wr_state = IDLE_s else '0';
645
 
646
  -- We need to know when a frame is stored, in order to increment the count of
647
  -- frames stored in the FIFO.
648
  p_wr_store_tog : process (rx_mac_aclk)
649
  begin
650
     if (rx_mac_aclk'event and rx_mac_aclk = '1') then
651
        if wr_state = GF_s then
652
           wr_store_frame_tog <= not wr_store_frame_tog;
653
        end if;
654
     end if;
655
  end process;
656
 
657
 
658
  ------------------------------------------------------------------------------
659
  -- Address counters
660
  ------------------------------------------------------------------------------
661
 
662
  -- Write address is incremented when data is being written into the FIFO.
663
  wr_addr_p : process(rx_mac_aclk)
664
  begin
665
     if (rx_mac_aclk'event and rx_mac_aclk = '1') then
666
        if rx_mac_reset = '1' then
667
           wr_addr <= (others => '0');
668
        else
669
           if wr_addr_reload = '1' then
670
              wr_addr <= wr_start_addr;
671
           elsif wr_addr_inc = '1' then
672
              wr_addr <= wr_addr + 1;
673
           end if;
674
        end if;
675
     end if;
676
  end process wr_addr_p;
677
 
678
  -- Store the start address.
679
  wr_staddr_p : process(rx_mac_aclk)
680
  begin
681
     if (rx_mac_aclk'event and rx_mac_aclk = '1') then
682
        if rx_mac_reset = '1' then
683
           wr_start_addr <= (others => '0');
684
        else
685
           if wr_start_addr_load = '1' then
686
              wr_start_addr <= wr_addr;
687
           end if;
688
        end if;
689
     end if;
690
  end process wr_staddr_p;
691
 
692
  -- Read address is incremented when data is being read from the FIFO.
693
  rd_addr_p : process(rx_fifo_aclk)
694
  begin
695
     if (rx_fifo_aclk'event and rx_fifo_aclk = '1') then
696
        if rx_fifo_reset = '1' then
697
           rd_addr <= (others => '0');
698
        else
699
           if rd_addr_reload = '1' then
700
              rd_addr <= rd_addr - 3;
701
           elsif rd_addr_inc = '1' then
702
              rd_addr <= rd_addr + 1;
703
           end if;
704
        end if;
705
     end if;
706
  end process rd_addr_p;
707
 
708
  -- Which BRAM is read from is dependant on the upper bit of the address
709
  -- space. This needs to be registered to give the correct timing.
710
  rd_bram_p : process(rx_fifo_aclk)
711
  begin
712
     if (rx_fifo_aclk'event and rx_fifo_aclk = '1') then
713
        if rx_fifo_reset = '1' then
714
           rd_bram_u <= '0';
715
           rd_bram_u_reg <= '0';
716
        elsif rd_addr_inc = '1' then
717
           rd_bram_u <= rd_addr(11);
718
           rd_bram_u_reg <= rd_bram_u;
719
        end if;
720
     end if;
721
  end process rd_bram_p;
722
 
723
 
724
  ------------------------------------------------------------------------------
725
  -- Data pipelines
726
  ------------------------------------------------------------------------------
727
 
728
  -- Register data inputs to BRAM.
729
  -- No resets to allow for SRL16 target.
730
  reg_din_p : process(rx_mac_aclk)
731
  begin
732
     if (rx_mac_aclk'event and rx_mac_aclk = '1') then
733
        wr_data_pipe(0) <= rx_axis_mac_tdata;
734
        wr_data_pipe(1) <= wr_data_pipe(0);
735
        wr_data_bram    <= wr_data_pipe(1);
736
     end if;
737
  end process reg_din_p;
738
 
739
  -- The valid input enables BRAM write and is a condition for other signals.
740
  reg_dv_p : process(rx_mac_aclk)
741
  begin
742
     if (rx_mac_aclk'event and rx_mac_aclk = '1') then
743
        wr_dv_pipe(0) <= rx_axis_mac_tvalid;
744
        wr_dv_pipe(1) <= wr_dv_pipe(0);
745
        wr_dv_pipe(2) <= wr_dv_pipe(1);
746
     end if;
747
  end process reg_dv_p;
748
 
749
  -- End of frame flag set when tlast and tvalid are asserted together.
750
  reg_eof_p : process(rx_mac_aclk)
751
  begin
752
     if (rx_mac_aclk'event and rx_mac_aclk = '1') then
753
        wr_eof_bram_pipe(0) <= rx_axis_mac_tlast;
754
        wr_eof_bram_pipe(1) <= wr_eof_bram_pipe(0);
755
        wr_eof_bram <= wr_eof_bram_pipe(1) and wr_dv_pipe(1);
756
     end if;
757
  end process reg_eof_p;
758
 
759
  -- Upon arrival of EOF flag, the frame is good if tuser signal
760
  -- is low, and bad if tuser signal is high.
761
  reg_gf_p : process(rx_mac_aclk)
762
  begin
763
     if (rx_mac_aclk'event and rx_mac_aclk = '1') then
764
        wr_gfbf_pipe(0) <= rx_axis_mac_tuser;
765
        wr_gfbf_pipe(1) <= wr_gfbf_pipe(0);
766
        wr_gf <= (not wr_gfbf_pipe(1)) and wr_eof_bram_pipe(1) and wr_dv_pipe(1);
767
        wr_bf <=      wr_gfbf_pipe(1)  and wr_eof_bram_pipe(1) and wr_dv_pipe(1);
768
     end if;
769
  end process reg_gf_p;
770
 
771
  -- The MAC's RX path cannot be helpd off, so the tready signal is always high.
772
  reg_ready_p : process(rx_mac_aclk)
773
  begin
774
     if (rx_mac_aclk'event and rx_mac_aclk = '1') then
775
        if (rx_mac_reset = '1') then
776
           rx_axis_mac_tready <= '0';
777
        else
778
           rx_axis_mac_tready <= '1';
779
        end if;
780
     end if;
781
  end process reg_ready_p;
782
 
783
  -- Register data outputs from BRAM.
784
  -- No resets to allow for SRL16 target.
785
  reg_dout_p : process(rx_fifo_aclk)
786
  begin
787
     if (rx_fifo_aclk'event and rx_fifo_aclk = '1') then
788
        if rd_en = '1' then
789
           rd_data_pipe_u <= rd_data_bram_u;
790
           rd_data_pipe_l <= rd_data_bram_l;
791
           if rd_bram_u_reg = '1' then
792
              rd_data_pipe <= rd_data_pipe_u;
793
           else
794
              rd_data_pipe <= rd_data_pipe_l;
795
           end if;
796
           rx_axis_fifo_tdata <= rd_data_pipe;
797
        end if;
798
     end if;
799
  end process reg_dout_p;
800
 
801
  reg_eofout_p : process(rx_fifo_aclk)
802
  begin
803
     if (rx_fifo_aclk'event and rx_fifo_aclk = '1') then
804
        if rd_en = '1' then
805
           if rd_bram_u = '1' then
806
              rd_eof <= rd_eof_bram_u(0);
807
           else
808
              rd_eof <= rd_eof_bram_l(0);
809
           end if;
810
        end if;
811
     end if;
812
  end process reg_eofout_p;
813
 
814
 
815
  ------------------------------------------------------------------------------
816
  -- Overflow functionality
817
  ------------------------------------------------------------------------------
818
 
819
  -- to minimise the number of read address updates the bottom 6 bits of the 
820
  -- read address are not passed across and the write domain will only sample 
821
  -- them when bits 5 and 4 of the read address transition from 01 to 10.  
822
  -- Since this is for full detection this just means that if the read stops
823
  -- the write will hit full up to 64 locations early
824
 
825
  -- need to use two bits and look for an increment transition as reload can cause
826
  -- a decrement on this boundary (decrement is only by 3 so above bit 2 should be safe)
827
  p_rd_addr_tog : process (rx_fifo_aclk)
828
  begin
829
     if rx_fifo_aclk'event and rx_fifo_aclk = '1' then
830
        if rx_fifo_reset = '1' then
831
           old_rd_addr <= (others => '0');
832
           update_addr_tog <= '0';
833
        else
834
           old_rd_addr <= std_logic_vector(rd_addr(5 downto 4));
835
           if rd_addr(5 downto 4) = "10" and old_rd_addr = "01" then
836
              update_addr_tog <= not update_addr_tog;
837
           end if;
838
        end if;
839
     end if;
840
  end process p_rd_addr_tog;
841
 
842
  sync_rd_addr_tog: sync_block
843
  port map (
844
     clk       => rx_mac_aclk,
845
     data_in   => update_addr_tog,
846
     data_out  => update_addr_tog_sync
847
  );
848
 
849
  -- Obtain the difference between write and read pointers.
850
  p_sample_addr : process (rx_mac_aclk)
851
  begin
852
     if rx_mac_aclk'event and rx_mac_aclk = '1' then
853
        if rx_mac_reset = '1' then
854
           update_addr_tog_sync_reg <= '0';
855
           wr_rd_addr               <= (others => '0');
856
        else
857
           update_addr_tog_sync_reg <= update_addr_tog_sync;
858
           if update_addr_tog_sync_reg /= update_addr_tog_sync then
859
              wr_rd_addr               <= rd_addr(11 downto 6) & "000000";
860
           end if;
861
        end if;
862
     end if;
863
  end process p_sample_addr;
864
 
865
  wr_addr_diff_in <= ('0' & wr_rd_addr) - ('0' & wr_addr);
866
 
867
  -- Obtain the difference between write and read pointers.
868
  p_addr_diff : process (rx_mac_aclk)
869
  begin
870
     if rx_mac_aclk'event and rx_mac_aclk = '1' then
871
        if rx_mac_reset = '1' then
872
           wr_addr_diff <= (others => '0');
873
        else
874
           wr_addr_diff <= wr_addr_diff_in(11 downto 0);
875
        end if;
876
     end if;
877
  end process p_addr_diff;
878
 
879
  -- Detect when the FIFO is full.
880
  -- The FIFO is considered to be full if the write address pointer is
881
  -- within 0 to 3 of the read address pointer.
882
  p_wr_full : process (rx_mac_aclk)
883
  begin
884
     if rx_mac_aclk'event and rx_mac_aclk = '1' then
885
       if rx_mac_reset = '1' then
886
         wr_fifo_full <= '0';
887
       else
888
         if wr_addr_diff(11 downto 4) = 0
889
            and wr_addr_diff(3 downto 2) /= "00" then
890
            wr_fifo_full <= '1';
891
         else
892
            wr_fifo_full <= '0';
893
         end if;
894
       end if;
895
     end if;
896
  end process p_wr_full;
897
 
898
  -- Decode the overflow indicator output.
899
  fifo_overflow <= '1' when wr_state = OVFLOW_s else '0';
900
 
901
 
902
  ------------------------------------------------------------------------------
903
  -- FIFO status signals
904
  ------------------------------------------------------------------------------
905
  -- The FIFO status is four bits which represents the occupancy of the FIFO
906
  -- in sixteenths. To generate this signal we therefore only need to compare
907
  -- the 4 most significant bits of the write address pointer with the 4 most
908
  -- significant bits of the read address pointer.
909
 
910
  p_wr_fifo_status : process (rx_mac_aclk)
911
  begin
912
     if rx_mac_aclk'event and rx_mac_aclk = '1' then
913
        if rx_mac_reset = '1' then
914
           wr_fifo_status <= "0000";
915
        else
916
           if wr_addr_diff = (wr_addr_diff'range => '0') then
917
              wr_fifo_status <= "0000";
918
           else
919
              wr_fifo_status(3) <= not wr_addr_diff(11);
920
              wr_fifo_status(2) <= not wr_addr_diff(10);
921
              wr_fifo_status(1) <= not wr_addr_diff(9);
922
              wr_fifo_status(0) <= not wr_addr_diff(8);
923
           end if;
924
        end if;
925
     end if;
926
  end process p_wr_fifo_status;
927
 
928
  fifo_status <= std_logic_vector(wr_fifo_status);
929
 
930
 
931
  ------------------------------------------------------------------------------
932
  -- Instantiate FIFO block memory
933
  ------------------------------------------------------------------------------
934
 
935
  wr_eof_data_bram(8) <= wr_eof_bram;
936
  wr_eof_data_bram(7 downto 0) <= wr_data_bram;
937
 
938
  -- Block RAM for lower address space (rx_addr(11) = '0')
939
  rd_eof_bram_l(0) <= rd_eof_data_bram_l(8);
940
  rd_data_bram_l   <= rd_eof_data_bram_l(7 downto 0);
941
  ramgen_l : BRAM_TDP_MACRO
942
    generic map (
943
      DEVICE        => "VIRTEX6",
944
      WRITE_WIDTH_A => 9,
945
      WRITE_WIDTH_B => 9,
946
      READ_WIDTH_A  => 9,
947
      READ_WIDTH_B  => 9)
948
    port map (
949
      DOA    => doa_l_unused,
950
      DOB    => rd_eof_data_bram_l,
951
      ADDRA  => std_logic_vector(wr_addr(10 downto 0)),
952
      ADDRB  => std_logic_vector(rd_addr(10 downto 0)),
953
      CLKA   => rx_mac_aclk,
954
      CLKB   => rx_fifo_aclk,
955
      DIA    => wr_eof_data_bram,
956
      DIB    => GND_BUS(8 downto 0),
957
      ENA    => VCC,
958
      ENB    => rd_en,
959
      REGCEA => VCC,
960
      REGCEB => VCC,
961
      RSTA   => rx_mac_reset,
962
      RSTB   => rx_fifo_reset,
963
      WEA    => wr_en_l_bram,
964
      WEB    => GND
965
  );
966
 
967
  -- Block RAM for lower address space (rx_addr(11) = '0')
968
  rd_eof_bram_u(0) <= rd_eof_data_bram_u(8);
969
  rd_data_bram_u   <= rd_eof_data_bram_u(7 downto 0);
970
  ramgen_u : BRAM_TDP_MACRO
971
    generic map (
972
      DEVICE        => "VIRTEX6",
973
      WRITE_WIDTH_A => 9,
974
      WRITE_WIDTH_B => 9,
975
      READ_WIDTH_A  => 9,
976
      READ_WIDTH_B  => 9)
977
    port map (
978
      DOA    => doa_u_unused,
979
      DOB    => rd_eof_data_bram_u,
980
      ADDRA  => std_logic_vector(wr_addr(10 downto 0)),
981
      ADDRB  => std_logic_vector(rd_addr(10 downto 0)),
982
      CLKA   => rx_mac_aclk,
983
      CLKB   => rx_fifo_aclk,
984
      DIA    => wr_eof_data_bram,
985
      DIB    => GND_BUS(8 downto 0),
986
      ENA    => VCC,
987
      ENB    => rd_en,
988
      REGCEA => VCC,
989
      REGCEB => VCC,
990
      RSTA   => rx_mac_reset,
991
      RSTB   => rx_fifo_reset,
992
      WEA    => wr_en_u_bram,
993
      WEB    => GND
994
  );
995
 
996
 
997
end RTL;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.