OpenCores
URL https://opencores.org/ocsvn/1g_ethernet_dpi/1g_ethernet_dpi/trunk

Subversion Repositories 1g_ethernet_dpi

[/] [1g_ethernet_dpi/] [tags/] [v0.0/] [hw/] [src/] [rtl/] [tri_mode_emac/] [src/] [fifo/] [tri_mode_ethernet_mac_0_tx_client_fifo.v] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 kuzmi4
//------------------------------------------------------------------------------
2
// Title      : Transmitter FIFO with AxiStream interfaces
3
// Version    : 1.3
4
// Project    : Tri-Mode Ethernet MAC
5
//------------------------------------------------------------------------------
6
// File       : tri_mode_ethernet_mac_0_tx_client_fifo.v
7
// Author     : Xilinx Inc.
8
// -----------------------------------------------------------------------------
9
// (c) Copyright 2004-2013 Xilinx, Inc. All rights reserved.
10
//
11
// This file contains confidential and proprietary information
12
// of Xilinx, Inc. and is protected under U.S. and
13
// international copyright and other intellectual property
14
// laws.
15
//
16
// DISCLAIMER
17
// This disclaimer is not a license and does not grant any
18
// rights to the materials distributed herewith. Except as
19
// otherwise provided in a valid license issued to you by
20
// Xilinx, and to the maximum extent permitted by applicable
21
// law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
22
// WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
23
// AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
24
// BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
25
// INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
26
// (2) Xilinx shall not be liable (whether in contract or tort,
27
// including negligence, or under any other theory of
28
// liability) for any loss or damage of any kind or nature
29
// related to, arising under or in connection with these
30
// materials, including for any direct, or any indirect,
31
// special, incidental, or consequential loss or damage
32
// (including loss of data, profits, goodwill, or any type of
33
// loss or damage suffered as a result of any action brought
34
// by a third party) even if such damage or loss was
35
// reasonably foreseeable or Xilinx had been advised of the
36
// possibility of the same.
37
//
38
// CRITICAL APPLICATIONS
39
// Xilinx products are not designed or intended to be fail-
40
// safe, or for use in any application requiring fail-safe
41
// performance, such as life-support or safety devices or
42
// systems, Class III medical devices, nuclear facilities,
43
// applications related to the deployment of airbags, or any
44
// other applications that could lead to death, personal
45
// injury, or severe property or environmental damage
46
// (individually and collectively, "Critical
47
// Applications"). Customer assumes the sole risk and
48
// liability of any use of Xilinx products in Critical
49
// Applications, subject only to applicable laws and
50
// regulations governing limitations on product liability.
51
//
52
// THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
53
// PART OF THIS FILE AT ALL TIMES. 
54
// -----------------------------------------------------------------------------
55
// Description: This is a transmitter side FIFO for the design example
56
//              of the Tri-Mode Ethernet MAC core. AxiStream interfaces are used.
57
//
58
//              The FIFO is built around an Inferred Dual Port RAM, 
59
//              giving a total memory capacity of 4096 bytes.
60
//
61
//              Valid frame data received from the user interface is written
62
//              into the Block RAM on the tx_fifo_aclkk. The FIFO will store
63
//              frames up to 4kbytes in length. If larger frames are written
64
//              to the FIFO, the AxiStream interface will accept the rest of the
65
//              frame, but that frame will be dropped by the FIFO and the
66
//              overflow signal will be asserted.
67
//
68
//              The FIFO is designed to work with a minimum frame length of 14
69
//              bytes.
70
//
71
//              When there is at least one complete frame in the FIFO, the MAC
72
//              transmitter AxiStream interface will be driven to request frame
73
//              transmission by placing the first byte of the frame onto
74
//              tx_axis_mac_tdata and by asserting tx_axis_mac_tvalid. The MAC will later
75
//              respond by asserting tx_axis_mac_tready. At this point the remaining
76
//              frame data is read out of the FIFO subject to tx_axis_mac_tready.
77
//              Data is read out of the FIFO on the tx_mac_aclk.
78
//
79
//              If the generic FULL_DUPLEX_ONLY is set to false, the FIFO will
80
//              requeue and retransmit frames as requested by the MAC. Once a
81
//              frame has been transmitted by the FIFO it is stored until the
82
//              possible retransmit window for that frame has expired.
83
//
84
//              The FIFO has been designed to operate with different clocks
85
//              on the write and read sides. The minimum write clock
86
//              frequency is the read clock frequency divided by 2.
87
//
88
//              The FIFO memory size can be increased by expanding the rd_addr
89
//              and wr_addr signal widths, to address further BRAMs.
90
//
91
//------------------------------------------------------------------------------
92
 
93
`timescale 1ps / 1ps
94
 
95
//------------------------------------------------------------------------------
96
// The module declaration for the Transmitter FIFO
97
//------------------------------------------------------------------------------
98
 
99
(* DowngradeIPIdentifiedWarnings = "yes" *)
100
module tri_mode_ethernet_mac_0_tx_client_fifo #
101
  (
102
    parameter FULL_DUPLEX_ONLY = 0
103
  )
104
 
105
  (
106
    // User-side (write-side) AxiStream interface
107
    input            tx_fifo_aclk,
108
    input            tx_fifo_resetn,
109
    input      [7:0] tx_axis_fifo_tdata,
110
    input            tx_axis_fifo_tvalid,
111
    input            tx_axis_fifo_tlast,
112
    output           tx_axis_fifo_tready,
113
 
114
    // MAC-side (read-side) AxiStream interface
115
    input            tx_mac_aclk,
116
    input            tx_mac_resetn,
117
    output     [7:0] tx_axis_mac_tdata,
118
    output reg       tx_axis_mac_tvalid,
119
    output reg       tx_axis_mac_tlast,
120
    input            tx_axis_mac_tready,
121
    output reg       tx_axis_mac_tuser,
122
 
123
    // FIFO status and overflow indication,
124
    // synchronous to write-side (tx_user_aclk) interface
125
    output           fifo_overflow,
126
    output     [3:0] fifo_status,
127
 
128
    // FIFO collision and retransmission requests from MAC
129
    input            tx_collision,
130
    input            tx_retransmit
131
  );
132
 
133
 
134
  //----------------------------------------------------------------------------
135
  // Define internal signals
136
  //----------------------------------------------------------------------------
137
 
138
  // Binary encoded read state machine states.
139
  localparam  IDLE_s             = 4'b0000;
140
  localparam  QUEUE1_s           = 4'b0001;
141
  localparam  QUEUE2_s           = 4'b0010;
142
  localparam  QUEUE3_s           = 4'b0011;
143
  localparam  START_DATA1_s      = 4'b0100;
144
  localparam  DATA_PRELOAD1_s    = 4'b0101;
145
  localparam  DATA_PRELOAD2_s    = 4'b0110;
146
  localparam  WAIT_HANDSHAKE_s   = 4'b0111;
147
  localparam  FRAME_s            = 4'b1000;
148
  localparam  HANDSHAKE_s        = 4'b1001;
149
  localparam  FINISH_s           = 4'b1010;
150
  localparam  DROP_ERR_s         = 4'b1011;
151
  localparam  DROP_s             = 4'b1100;
152
  localparam  RETRANSMIT_ERR_s   = 4'b1101;
153
  localparam  RETRANSMIT_s       = 4'b1111;
154
 
155
 
156
  reg [3:0]   rd_state;
157
 
158
  reg [3:0]   rd_nxt_state;
159
 
160
  // Binary encoded write state machine states.
161
  localparam WAIT_s   = 2'b00;
162
  localparam DATA_s   = 2'b01;
163
  localparam EOF_s    = 2'b10;
164
  localparam OVFLOW_s = 2'b11;
165
 
166
 
167
  reg  [1:0]  wr_state;
168
 
169
  reg  [1:0]  wr_nxt_state;
170
 
171
  wire [8:0]  wr_eof_data_bram;
172
  reg  [7:0]  wr_data_bram;
173
  reg  [7:0]  wr_data_pipe[0:1];
174
  reg         wr_sof_pipe[0:1];
175
  reg         wr_eof_pipe[0:1];
176
  reg         wr_accept_pipe[0:1];
177
  reg         wr_accept_bram;
178
  wire        wr_sof_int;
179
  reg  [0:0]  wr_eof_bram;
180
  reg         wr_eof_reg;
181
  reg  [11:0] wr_addr;
182
  wire        wr_addr_inc;
183
  wire        wr_start_addr_load;
184
  wire        wr_addr_reload;
185
  reg  [11:0] wr_start_addr;
186
  reg         wr_fifo_full;
187
  wire        wr_en;
188
  reg         wr_ovflow_dst_rdy;
189
  wire        tx_axis_fifo_tready_int_n;
190
  reg  [3:0]  data_count;
191
 
192
  wire        frame_in_fifo;
193
  wire        frames_in_fifo;
194
  reg         frame_in_fifo_valid;
195
  (* INIT = "0" *)
196
  reg         frame_in_fifo_valid_tog = 1'b0;
197
  wire        frame_in_fifo_valid_sync;
198
  reg         frame_in_fifo_valid_delay;
199
  reg         rd_eof;
200
  reg         rd_eof_reg;
201
  reg         rd_eof_pipe;
202
  reg  [11:0] rd_addr;
203
  wire        rd_addr_inc;
204
  wire        rd_addr_reload;
205
  wire [8:0]  rd_eof_data_bram;
206
  wire [7:0]  rd_data_bram;
207
  reg  [7:0]  rd_data_pipe = 8'd0;
208
  reg  [7:0]  rd_data_delay = 8'd0;
209
  wire [0:0]  rd_eof_bram;
210
  wire        rd_en;
211
 
212
 
213
  (* INIT = "0" *)
214
  reg         rd_tran_frame_tog = 1'b0;
215
  wire        wr_tran_frame_sync;
216
 
217
  (* INIT = "0" *)
218
  reg         wr_tran_frame_delay = 1'b0;
219
 
220
  (* INIT = "0" *)
221
  reg         rd_retran_frame_tog = 1'b0;
222
  wire        wr_retran_frame_sync;
223
 
224
  (* INIT = "0" *)
225
  reg         wr_retran_frame_delay = 1'b0;
226
  wire        wr_store_frame;
227
  reg         wr_transmit_frame;
228
  reg         wr_transmit_frame_delay;
229
  reg         wr_retransmit_frame;
230
  reg  [8:0]  wr_frames;
231
  reg         wr_frame_in_fifo;
232
  reg         wr_frames_in_fifo;
233
 
234
  reg   [3:0] rd_16_count;
235
  wire        rd_txfer_en;
236
  reg  [11:0] rd_addr_txfer;
237
 
238
  (* INIT = "0" *)
239
  reg         rd_txfer_tog = 1'b0;
240
  wire        wr_txfer_tog_sync;
241
 
242
  (* INIT = "0" *)
243
  reg         wr_txfer_tog_delay = 1'b0;
244
  wire        wr_txfer_en;
245
 
246
  (* ASYNC_REG = "TRUE" *)
247
  reg  [11:0] wr_rd_addr;
248
 
249
  reg  [11:0] wr_addr_diff;
250
 
251
  reg  [3:0]  wr_fifo_status;
252
 
253
  reg         rd_drop_frame;
254
  reg         rd_retransmit;
255
 
256
  reg  [11:0] rd_start_addr;
257
  wire        rd_start_addr_load;
258
  wire        rd_start_addr_reload;
259
 
260
  reg  [11:0] rd_dec_addr;
261
 
262
  wire        rd_transmit_frame;
263
  wire        rd_retransmit_frame;
264
  reg         rd_col_window_expire;
265
  reg         rd_col_window_pipe[0:1];
266
 
267
  (* ASYNC_REG = "TRUE" *)
268
  reg         wr_col_window_pipe[0:1];
269
 
270
  wire        wr_eof_state;
271
  reg         wr_eof_state_reg;
272
  wire        wr_fifo_overflow;
273
  reg  [9:0]  rd_slot_timer;
274
  reg         wr_col_window_expire;
275
  wire        rd_idle_state;
276
 
277
  wire [7:0]  tx_axis_mac_tdata_int_frame;
278
  wire [7:0]  tx_axis_mac_tdata_int_handshake;
279
  reg  [7:0]  tx_axis_mac_tdata_int = 8'b0;
280
  wire        tx_axis_mac_tvalid_int_finish;
281
  wire        tx_axis_mac_tvalid_int_droperr;
282
  wire        tx_axis_mac_tvalid_int_retransmiterr;
283
  wire        tx_axis_mac_tlast_int_frame_handshake;
284
  wire        tx_axis_mac_tlast_int_finish;
285
  wire        tx_axis_mac_tlast_int_droperr;
286
  wire        tx_axis_mac_tlast_int_retransmiterr;
287
  wire        tx_axis_mac_tuser_int_droperr;
288
  wire        tx_axis_mac_tuser_int_retransmit;
289
 
290
  wire        tx_fifo_reset;
291
  wire        tx_mac_reset;
292
 
293
  // invert reset sense as architecture is optimised for active high resets
294
  assign tx_fifo_reset = !tx_fifo_resetn;
295
  assign tx_mac_reset  = !tx_mac_resetn;
296
 
297
  //----------------------------------------------------------------------------
298
  // Begin FIFO architecture
299
  //----------------------------------------------------------------------------
300
 
301
  //----------------------------------------------------------------------------
302
  // Write state machine and control
303
  //----------------------------------------------------------------------------
304
 
305
  // Write state machine.
306
  // States are WAIT, DATA, EOF, OVFLOW.
307
  // Clock state to next state.
308
  always @(posedge tx_fifo_aclk)
309
  begin
310
     if (tx_fifo_reset == 1'b1) begin
311
         wr_state <= WAIT_s;
312
     end
313
     else begin
314
         wr_state <= wr_nxt_state;
315
     end
316
  end
317
 
318
  // Decode next state, combinatorial.
319
  always @(wr_state, wr_sof_pipe[1], wr_eof_pipe[0], wr_eof_pipe[1],
320
           wr_eof_bram[0], wr_fifo_overflow, data_count)
321
  begin
322
  case (wr_state)
323
     WAIT_s : begin
324
        if (wr_sof_pipe[1] == 1'b1 && wr_eof_pipe[1] == 1'b0) begin
325
           wr_nxt_state <= DATA_s;
326
        end
327
        else begin
328
           wr_nxt_state <= WAIT_s;
329
        end
330
     end
331
 
332
     DATA_s : begin
333
        // Wait for the end of frame to be detected.
334
        if (wr_fifo_overflow == 1'b1 && wr_eof_pipe[0] == 1'b0
335
            && wr_eof_pipe[1] == 1'b0) begin
336
           wr_nxt_state <= OVFLOW_s;
337
        end
338
        else if (wr_eof_pipe[1] == 1'b1) begin
339
           if (data_count[3:2] != 2'b11) begin
340
              wr_nxt_state <= OVFLOW_s;
341
           end
342
           else begin
343
              wr_nxt_state <= EOF_s;
344
           end
345
        end
346
        else begin
347
           wr_nxt_state <= DATA_s;
348
        end
349
     end
350
 
351
     EOF_s : begin
352
        // If the start of frame is already in the pipe, a back-to-back frame
353
        // transmission has occured. Move straight back to frame state.
354
        if (wr_sof_pipe[1] == 1'b1 && wr_eof_pipe[1] == 1'b0) begin
355
           wr_nxt_state <= DATA_s;
356
        end
357
        else if (wr_eof_bram[0] == 1'b1) begin
358
           wr_nxt_state <= WAIT_s;
359
        end
360
        else begin
361
           wr_nxt_state <= EOF_s;
362
        end
363
     end
364
 
365
     OVFLOW_s : begin
366
        // Wait until the end of frame is reached before clearing the overflow.
367
        if (wr_eof_bram[0] == 1'b1) begin
368
           wr_nxt_state <= WAIT_s;
369
        end
370
        else begin
371
           wr_nxt_state <= OVFLOW_s;
372
        end
373
     end
374
 
375
     default : begin
376
        wr_nxt_state <= WAIT_s;
377
     end
378
 
379
  endcase
380
  end
381
 
382
  // small frame count - frames smaller than 10 bytes are problematic as the frame_in_fifo cannot
383
  // react quickly enough - empty detect could be used in the read domain but this doesn't fully cover all cases
384
  // the cleanest fix is to simply ignore frames smaller than 10 bytes
385
  // generate a counter which is cleaered on an sof and counts in data
386
  always @(posedge tx_fifo_aclk)
387
  begin
388
     if (tx_fifo_reset == 1'b1) begin
389
        data_count <= 0;
390
     end
391
     else begin
392
        if (wr_sof_pipe[1] == 1'b1) begin
393
            data_count <= 0;
394
        end
395
        else begin
396
           if (data_count[3:2] != 2'b11) begin
397
               data_count <= data_count + 1;
398
           end
399
        end
400
     end
401
  end
402
 
403
  // Decode output signals.
404
  // wr_en is used to enable the BRAM write and the address to increment.
405
  assign wr_en = (wr_state == OVFLOW_s) ? 1'b0 : wr_accept_bram;
406
 
407
  assign wr_addr_inc = wr_en;
408
 
409
  assign wr_addr_reload = (wr_state == OVFLOW_s) ? 1'b1 : 1'b0;
410
  assign wr_start_addr_load = (wr_state == EOF_s && wr_nxt_state == WAIT_s)
411
                              ? 1'b1 :
412
                              (wr_state == EOF_s && wr_nxt_state == DATA_s)
413
                              ? 1'b1 : 1'b0;
414
 
415
  // Pause the AxiStream handshake when the FIFO is full.
416
  assign tx_axis_fifo_tready_int_n = (wr_state == OVFLOW_s) ?
417
                                wr_ovflow_dst_rdy : wr_fifo_full;
418
 
419
  assign tx_axis_fifo_tready = !tx_axis_fifo_tready_int_n;
420
 
421
  // Generate user overflow indicator.
422
  assign fifo_overflow = (wr_state == OVFLOW_s) ? 1'b1 : 1'b0;
423
 
424
  // When in overflow and have captured ovflow EOF, set tx_axis_fifo_tready again.
425
  always @(posedge tx_fifo_aclk)
426
  begin
427
     if (tx_fifo_reset == 1'b1) begin
428
        wr_ovflow_dst_rdy <= 1'b0;
429
     end
430
     else begin
431
        if (wr_fifo_overflow == 1'b1 && wr_state == DATA_s) begin
432
            wr_ovflow_dst_rdy <= 1'b0;
433
        end
434
        else if (tx_axis_fifo_tvalid == 1'b1 && tx_axis_fifo_tlast == 1'b1) begin
435
            wr_ovflow_dst_rdy <= 1'b1;
436
        end
437
     end
438
  end
439
 
440
  // EOF signals for use in overflow logic.
441
  assign wr_eof_state = (wr_state == EOF_s) ? 1'b1 : 1'b0;
442
 
443
  always @(posedge tx_fifo_aclk)
444
  begin
445
     if (tx_fifo_reset == 1'b1) begin
446
        wr_eof_state_reg <= 1'b0;
447
     end
448
     else begin
449
        wr_eof_state_reg <= wr_eof_state;
450
     end
451
  end
452
 
453
 
454
  //----------------------------------------------------------------------------
455
  // Read state machine and control
456
  //----------------------------------------------------------------------------
457
 
458
  // Read state machine.
459
  // States are IDLE, QUEUE1, QUEUE2, QUEUE3, QUEUE_ACK, WAIT_ACK, FRAME,
460
  // HANDSHAKE, FINISH, DROP_ERR, DROP, RETRANSMIT_ERR, RETRANSMIT.
461
  // Clock state to next state.
462
  always @(posedge tx_mac_aclk)
463
  begin
464
     if (tx_mac_reset == 1'b1) begin
465
        rd_state <= IDLE_s;
466
     end
467
     else begin
468
        rd_state <= rd_nxt_state;
469
     end
470
  end
471
 
472
  //----------------------------------------------------------------------------
473
  // Full duplex-only state machine.
474
generate if (FULL_DUPLEX_ONLY == 1) begin : gen_fd_sm
475
  // Decode next state, combinatorial.
476
  always @(rd_state, frame_in_fifo, frames_in_fifo, frame_in_fifo_valid, rd_eof, rd_eof_reg, tx_axis_mac_tready)
477
  begin
478
  case (rd_state)
479
           IDLE_s : begin
480
              // If there is a frame in the FIFO, start to queue the new frame
481
              // to the output.
482
              if ((frame_in_fifo & frame_in_fifo_valid) | frames_in_fifo) begin
483
                 rd_nxt_state <= QUEUE1_s;
484
              end
485
              else begin
486
                 rd_nxt_state <= IDLE_s;
487
              end
488
           end
489
 
490
           // Load the output pipeline, which takes three clock cycles.
491
           QUEUE1_s : begin
492
              rd_nxt_state <= QUEUE2_s;
493
           end
494
 
495
           QUEUE2_s : begin
496
              rd_nxt_state <= QUEUE3_s;
497
           end
498
 
499
           QUEUE3_s : begin
500
              rd_nxt_state <= START_DATA1_s;
501
           end
502
 
503
           START_DATA1_s : begin
504
              // The pipeline is full and the frame output starts now.
505
              rd_nxt_state <= DATA_PRELOAD1_s;
506
           end
507
 
508
           DATA_PRELOAD1_s : begin
509
              // Await the tx_axis_mac_tready acknowledge before moving on.
510
              if (tx_axis_mac_tready == 1'b1) begin
511
                 rd_nxt_state <= FRAME_s;
512
              end
513
              else begin
514
                 rd_nxt_state <= DATA_PRELOAD1_s;
515
              end
516
           end
517
 
518
           FRAME_s : begin
519
              // Read the frame out of the FIFO. If the MAC deasserts
520
              // tx_axis_mac_tready, stall in the handshake state. If the EOF
521
              // flag is encountered, move to the finish state.
522
              if (tx_axis_mac_tready == 1'b0)
523
              begin
524
                 rd_nxt_state <= HANDSHAKE_s;
525
              end
526
              else if (rd_eof == 1'b1) begin
527
                 rd_nxt_state <= FINISH_s;
528
              end
529
              else begin
530
                 rd_nxt_state <= FRAME_s;
531
              end
532
           end
533
 
534
           HANDSHAKE_s : begin
535
              // Await tx_axis_mac_tready before continuing frame transmission.
536
              // If the EOF flag is encountered, move to the finish state.
537
              if (tx_axis_mac_tready == 1'b1 && rd_eof_reg == 1'b1) begin
538
                 rd_nxt_state <= FINISH_s;
539
              end
540
              else if (tx_axis_mac_tready == 1'b1 && rd_eof_reg == 1'b0) begin
541
                 rd_nxt_state <= FRAME_s;
542
              end
543
              else begin
544
                 rd_nxt_state <= HANDSHAKE_s;
545
              end
546
           end
547
 
548
           FINISH_s : begin
549
              // Frame has finished. Assure that the MAC has accepted the final
550
              // byte by transitioning to idle only when tx_axis_mac_tready is high.
551
              if (tx_axis_mac_tready == 1'b1) begin
552
                 rd_nxt_state <= IDLE_s;
553
              end
554
              else begin
555
                 rd_nxt_state <= FINISH_s;
556
              end
557
           end
558
 
559
           default : begin
560
              rd_nxt_state <= IDLE_s;
561
           end
562
        endcase
563
  end
564
 
565
end
566
endgenerate
567
 
568
  //----------------------------------------------------------------------------
569
  // Full and half duplex state machine.
570
generate if (FULL_DUPLEX_ONLY != 1) begin : gen_hd_sm
571
  // Decode the next state, combinatorial.
572
  always @(rd_state, frame_in_fifo, frames_in_fifo, frame_in_fifo_valid, rd_eof_reg,
573
           tx_axis_mac_tready, rd_drop_frame, rd_retransmit)
574
  begin
575
  case (rd_state)
576
           IDLE_s : begin
577
              // If a retransmit request is detected then prepare to retransmit.
578
              if (rd_retransmit == 1'b1) begin
579
                 rd_nxt_state <= RETRANSMIT_ERR_s;
580
              end
581
              // If there is a frame in the FIFO, then queue the new frame to
582
              // the output.
583
              else if ((frame_in_fifo & frame_in_fifo_valid) | frames_in_fifo) begin
584
                 rd_nxt_state <= QUEUE1_s;
585
              end
586
              else begin
587
                 rd_nxt_state <= IDLE_s;
588
              end
589
           end
590
 
591
           // Load the output pipeline, which takes three clock cycles.
592
           QUEUE1_s : begin
593
              if (rd_retransmit == 1'b1) begin
594
                 rd_nxt_state <= RETRANSMIT_ERR_s;
595
              end
596
              else begin
597
                rd_nxt_state <= QUEUE2_s;
598
              end
599
           end
600
 
601
           QUEUE2_s : begin
602
              if (rd_retransmit == 1'b1) begin
603
                 rd_nxt_state <= RETRANSMIT_ERR_s;
604
              end
605
              else begin
606
                 rd_nxt_state <= QUEUE3_s;
607
              end
608
           end
609
 
610
           QUEUE3_s : begin
611
              if (rd_retransmit == 1'b1) begin
612
                 rd_nxt_state <= RETRANSMIT_ERR_s;
613
              end
614
              else begin
615
                 rd_nxt_state <= START_DATA1_s;
616
              end
617
           end
618
 
619
           START_DATA1_s : begin
620
              // The pipeline is full and the frame output starts now.
621
              if (rd_retransmit == 1'b1) begin
622
                 rd_nxt_state <= RETRANSMIT_ERR_s;
623
              end
624
              else begin
625
                 rd_nxt_state <= DATA_PRELOAD1_s;
626
              end
627
           end
628
 
629
           DATA_PRELOAD1_s : begin
630
              // Await the tx_axis_mac_tready acknowledge before moving on.
631
              if (rd_retransmit == 1'b1) begin
632
                 rd_nxt_state <= RETRANSMIT_ERR_s;
633
              end
634
              else if (tx_axis_mac_tready == 1'b1) begin
635
                 rd_nxt_state <= DATA_PRELOAD2_s;
636
              end
637
              else begin
638
                 rd_nxt_state <= DATA_PRELOAD1_s;
639
              end
640
           end
641
 
642
           DATA_PRELOAD2_s : begin
643
              // If a collision-only request, then must drop the rest of the
644
              // current frame. If collision and retransmit, then prepare
645
              // to retransmit the frame.
646
              if (rd_drop_frame == 1'b1) begin
647
                 rd_nxt_state <= DROP_ERR_s;
648
              end
649
              else if (rd_retransmit == 1'b1) begin
650
                 rd_nxt_state <= RETRANSMIT_ERR_s;
651
              end
652
              // Read the frame out of the FIFO. If the MAC deasserts
653
              // tx_axis_mac_tready, stall in the handshake state. If the EOF
654
              // flag is encountered, move to the finish state.
655
              else if (tx_axis_mac_tready == 1'b0) begin
656
                 rd_nxt_state <= WAIT_HANDSHAKE_s;
657
              end
658
              else if (rd_eof_reg == 1'b1) begin
659
                 rd_nxt_state <= FINISH_s;
660
              end
661
              else begin
662
                 rd_nxt_state <= DATA_PRELOAD2_s;
663
              end
664
           end
665
 
666
           WAIT_HANDSHAKE_s : begin
667
              // Await tx_axis_mac_tready before continuing frame transmission.
668
              // If the EOF flag is encountered, move to the finish state.
669
              if (rd_retransmit == 1'b1) begin
670
                 rd_nxt_state <= RETRANSMIT_ERR_s;
671
              end
672
              else if (tx_axis_mac_tready == 1'b1 && rd_eof_reg == 1'b1) begin
673
                 rd_nxt_state <= FINISH_s;
674
              end
675
              else if (tx_axis_mac_tready == 1'b1 && rd_eof_reg == 1'b0) begin
676
                 rd_nxt_state <= FRAME_s;
677
              end
678
              else begin
679
                 rd_nxt_state <= WAIT_HANDSHAKE_s;
680
              end
681
           end
682
 
683
           FRAME_s : begin
684
              // If a collision-only request, then must drop the rest of the
685
              // current frame. If collision and retransmit, then prepare
686
              // to retransmit the frame.
687
              if (rd_drop_frame == 1'b1) begin
688
                 rd_nxt_state <= DROP_ERR_s;
689
              end
690
              else if (rd_retransmit == 1'b1) begin
691
                 rd_nxt_state <= RETRANSMIT_ERR_s;
692
              end
693
              // Read the frame out of the FIFO. If the MAC deasserts
694
              // tx_axis_mac_tready, stall in the handshake state. If the EOF
695
              // flag is encountered, move to the finish state.
696
              else if (tx_axis_mac_tready == 1'b0) begin
697
                 rd_nxt_state <= HANDSHAKE_s;
698
              end
699
              else if (rd_eof_reg == 1'b1) begin
700
                 rd_nxt_state <= FINISH_s;
701
              end
702
              else begin
703
                 rd_nxt_state <= FRAME_s;
704
              end
705
           end
706
 
707
           HANDSHAKE_s : begin
708
              // Await tx_axis_mac_tready before continuing frame transmission.
709
              // If the EOF flag is encountered, move to the finish state.
710
              if (rd_retransmit == 1'b1) begin
711
                 rd_nxt_state <= RETRANSMIT_ERR_s;
712
              end
713
              else if (tx_axis_mac_tready == 1'b1 && rd_eof_reg == 1'b1) begin
714
                 rd_nxt_state <= FINISH_s;
715
              end
716
              else if (tx_axis_mac_tready == 1'b1 && rd_eof_reg == 1'b0) begin
717
                 rd_nxt_state <= FRAME_s;
718
              end
719
              else begin
720
                 rd_nxt_state <= HANDSHAKE_s;
721
              end
722
           end
723
 
724
           FINISH_s : begin
725
              // Frame has finished. Assure that the MAC has accepted the final
726
              // byte by transitioning to idle only when tx_axis_mac_tready is high.
727
              if (rd_retransmit == 1'b1) begin
728
                 rd_nxt_state <= RETRANSMIT_ERR_s;
729
              end
730
              if (tx_axis_mac_tready == 1'b1) begin
731
                 rd_nxt_state <= IDLE_s;
732
              end
733
              else begin
734
                 rd_nxt_state <= FINISH_s;
735
              end
736
           end
737
 
738
           DROP_ERR_s : begin
739
              // FIFO is ready to drop the frame. Assure that the MAC has
740
              // accepted the final byte and err signal before dropping.
741
              if (tx_axis_mac_tready == 1'b1) begin
742
                 rd_nxt_state <= DROP_s;
743
              end
744
              else begin
745
                 rd_nxt_state <= DROP_ERR_s;
746
              end
747
           end
748
 
749
           DROP_s : begin
750
              // Wait until rest of frame has been cleared.
751
              if (rd_eof_reg == 1'b1) begin
752
                 rd_nxt_state <= IDLE_s;
753
              end
754
              else begin
755
                 rd_nxt_state <= DROP_s;
756
              end
757
           end
758
 
759
           RETRANSMIT_ERR_s : begin
760
              // FIFO is ready to retransmit the frame. Assure that the MAC has
761
              // accepted the final byte and err signal before retransmitting.
762
              if (tx_axis_mac_tready == 1'b1) begin
763
                 rd_nxt_state <= RETRANSMIT_s;
764
              end
765
              else begin
766
                 rd_nxt_state <= RETRANSMIT_ERR_s;
767
              end
768
           end
769
 
770
           RETRANSMIT_s : begin
771
              // Reload the data pipeline from the start of the frame.
772
              rd_nxt_state <= QUEUE1_s;
773
           end
774
 
775
           default : begin
776
              rd_nxt_state <= IDLE_s;
777
           end
778
        endcase
779
  end
780
 
781
end
782
endgenerate
783
 
784
  // Combinatorially select tdata candidates.
785
  assign tx_axis_mac_tdata_int_frame = (rd_nxt_state == HANDSHAKE_s || rd_nxt_state == WAIT_HANDSHAKE_s) ?
786
                                      tx_axis_mac_tdata_int : rd_data_pipe;
787
  assign tx_axis_mac_tdata_int_handshake = (rd_nxt_state == FINISH_s)    ?
788
                                      rd_data_pipe : tx_axis_mac_tdata_int;
789
  assign tx_axis_mac_tdata          = tx_axis_mac_tdata_int;
790
 
791
  // Decode output tdata based on current and next read state.
792
  always @(posedge tx_mac_aclk)
793
  begin
794
     if (rd_nxt_state == FRAME_s || rd_nxt_state == DATA_PRELOAD2_s)
795
        tx_axis_mac_tdata_int <= rd_data_pipe;
796
     else if (rd_nxt_state == RETRANSMIT_ERR_s || rd_nxt_state == DROP_ERR_s)
797
        tx_axis_mac_tdata_int <= tx_axis_mac_tdata_int;
798
     else begin
799
        case (rd_state)
800
           START_DATA1_s :
801
              tx_axis_mac_tdata_int <= rd_data_pipe;
802
           FRAME_s, DATA_PRELOAD2_s :
803
              tx_axis_mac_tdata_int <= tx_axis_mac_tdata_int_frame;
804
           HANDSHAKE_s, WAIT_HANDSHAKE_s:
805
              tx_axis_mac_tdata_int <= tx_axis_mac_tdata_int_handshake;
806
           default :
807
              tx_axis_mac_tdata_int <= tx_axis_mac_tdata_int;
808
        endcase
809
     end
810
  end
811
 
812
  // Combinatorially select tvalid candidates.
813
  assign tx_axis_mac_tvalid_int_finish     = (rd_nxt_state == IDLE_s)       ?
814
                                             1'b0 : 1'b1;
815
  assign tx_axis_mac_tvalid_int_droperr  = (rd_nxt_state == DROP_s)       ?
816
                                             1'b0 : 1'b1;
817
  assign tx_axis_mac_tvalid_int_retransmiterr = (rd_nxt_state == RETRANSMIT_s) ?
818
                                             1'b0 : 1'b1;
819
 
820
  // Decode output tvalid based on current and next read state.
821
  always @(posedge tx_mac_aclk)
822
  begin
823
     if (rd_nxt_state == FRAME_s || rd_nxt_state == DATA_PRELOAD2_s)
824
        tx_axis_mac_tvalid <= 1'b1;
825
     else if (rd_nxt_state == RETRANSMIT_ERR_s || rd_nxt_state == DROP_ERR_s)
826
        tx_axis_mac_tvalid <= 1'b1;
827
     else
828
     begin
829
        case (rd_state)
830
           START_DATA1_s :
831
              tx_axis_mac_tvalid <= 1'b1;
832
           DATA_PRELOAD1_s :
833
              tx_axis_mac_tvalid <= 1'b1;
834
           FRAME_s, DATA_PRELOAD2_s :
835
              tx_axis_mac_tvalid <= 1'b1;
836
           HANDSHAKE_s, WAIT_HANDSHAKE_s :
837
              tx_axis_mac_tvalid <= 1'b1;
838
           FINISH_s :
839
              tx_axis_mac_tvalid <= tx_axis_mac_tvalid_int_finish;
840
           DROP_ERR_s :
841
              tx_axis_mac_tvalid <= tx_axis_mac_tvalid_int_droperr;
842
           RETRANSMIT_ERR_s :
843
              tx_axis_mac_tvalid <= tx_axis_mac_tvalid_int_retransmiterr;
844
           default :
845
              tx_axis_mac_tvalid <= 1'b0;
846
        endcase
847
     end
848
  end
849
 
850
  // Combinatorially select tlast candidates.
851
  assign tx_axis_mac_tlast_int_frame_handshake = (rd_nxt_state == FINISH_s)     ?
852
                                            rd_eof_reg : 1'b0;
853
  assign tx_axis_mac_tlast_int_finish     = (rd_nxt_state == IDLE_s)       ?
854
                                            1'b0 : rd_eof_reg;
855
  assign tx_axis_mac_tlast_int_droperr  = (rd_nxt_state == DROP_s)       ?
856
                                            1'b0 : 1'b1;
857
  assign tx_axis_mac_tlast_int_retransmiterr = (rd_nxt_state == RETRANSMIT_s) ?
858
                                            1'b0 : 1'b1;
859
 
860
  // Decode output tlast based on current and next read state.
861
  always @(posedge tx_mac_aclk)
862
  begin
863
     if (rd_nxt_state == FRAME_s || rd_nxt_state == DATA_PRELOAD2_s)
864
        tx_axis_mac_tlast <= rd_eof;
865
     else if (rd_nxt_state == RETRANSMIT_ERR_s || rd_nxt_state == DROP_ERR_s)
866
        tx_axis_mac_tlast <= 1'b1;
867
     else
868
     begin
869
        case (rd_state)
870
           DATA_PRELOAD1_s :
871
              tx_axis_mac_tlast <= rd_eof;
872
           FRAME_s, DATA_PRELOAD2_s :
873
              tx_axis_mac_tlast <= tx_axis_mac_tlast_int_frame_handshake;
874
           HANDSHAKE_s, WAIT_HANDSHAKE_s :
875
              tx_axis_mac_tlast <= tx_axis_mac_tlast_int_frame_handshake;
876
           FINISH_s :
877
              tx_axis_mac_tlast <= tx_axis_mac_tlast_int_finish;
878
           DROP_ERR_s :
879
              tx_axis_mac_tlast <= tx_axis_mac_tlast_int_droperr;
880
           RETRANSMIT_ERR_s :
881
              tx_axis_mac_tlast <= tx_axis_mac_tlast_int_retransmiterr;
882
           default :
883
              tx_axis_mac_tlast <= 1'b0;
884
        endcase
885
     end
886
  end
887
 
888
  // Combinatorially select tuser candidates.
889
  assign tx_axis_mac_tuser_int_droperr = (rd_nxt_state == DROP_s)       ?
890
                                       1'b0 : 1'b1;
891
  assign tx_axis_mac_tuser_int_retransmit = (rd_nxt_state == RETRANSMIT_s) ?
892
                                       1'b0 : 1'b1;
893
 
894
  // Decode output tuser based on current and next read state.
895
  always @(posedge tx_mac_aclk)
896
  begin
897
     if (rd_nxt_state == RETRANSMIT_ERR_s || rd_nxt_state == DROP_ERR_s)
898
        tx_axis_mac_tuser <= 1'b1;
899
     else
900
     begin
901
        case (rd_state)
902
           DROP_ERR_s :
903
              tx_axis_mac_tuser <= tx_axis_mac_tuser_int_droperr;
904
           RETRANSMIT_ERR_s :
905
              tx_axis_mac_tuser <= tx_axis_mac_tuser_int_retransmit;
906
           default :
907
              tx_axis_mac_tuser <= 1'b0;
908
        endcase
909
     end
910
  end
911
 
912
  //----------------------------------------------------------------------------
913
  // Decode full duplex-only control signals.
914
generate if (FULL_DUPLEX_ONLY == 1) begin : gen_fd_decode
915
 
916
  // rd_en is used to enable the BRAM read and load the output pipeline.
917
  assign rd_en = (rd_state == IDLE_s) ? 1'b0 :
918
                 (rd_nxt_state == FRAME_s) ? 1'b1 :
919
                 (rd_state == FRAME_s && rd_nxt_state == HANDSHAKE_s) ? 1'b0 :
920
                 (rd_nxt_state == HANDSHAKE_s) ? 1'b0 :
921
                 (rd_state == FINISH_s) ? 1'b0 :
922
                 (rd_state == DATA_PRELOAD1_s) ? 1'b0 : 1'b1;
923
 
924
  // When the BRAM is being read, enable the read address to be incremented.
925
  assign rd_addr_inc = rd_en;
926
 
927
  assign rd_addr_reload = (rd_state != FINISH_s && rd_nxt_state == FINISH_s)
928
                          ? 1'b1 : 1'b0;
929
 
930
  // Transmit frame pulse must never be more frequent than once per 64 clocks to
931
  // allow toggle to cross clock domain.
932
  assign rd_transmit_frame = (rd_state == FINISH_s && rd_nxt_state == IDLE_s)
933
                             ? 1'b1 : 1'b0;
934
 
935
  // Unused for full duplex only.
936
  assign rd_start_addr_reload = 1'b0;
937
  assign rd_start_addr_load   = 1'b0;
938
  assign rd_retransmit_frame  = 1'b0;
939
 
940
end
941
endgenerate
942
 
943
  //----------------------------------------------------------------------------
944
  // Decode full and half duplex control signals.
945
generate if (FULL_DUPLEX_ONLY != 1) begin : gen_hd_decode
946
 
947
  // rd_en is used to enable the BRAM read and load the output pipeline.
948
  assign rd_en = (rd_state == IDLE_s) ? 1'b0 :
949
                 (rd_nxt_state == DROP_ERR_s) ? 1'b0 :
950
                 (rd_nxt_state == DROP_s && rd_eof == 1'b1) ? 1'b0 :
951
                 (rd_nxt_state == FRAME_s || rd_nxt_state == DATA_PRELOAD2_s) ? 1'b1 :
952
                 (rd_state == DATA_PRELOAD2_s && rd_nxt_state == WAIT_HANDSHAKE_s) ? 1'b0 :
953
                 (rd_state == FRAME_s && rd_nxt_state == HANDSHAKE_s) ? 1'b0 :
954
                 (rd_nxt_state == HANDSHAKE_s || rd_nxt_state == WAIT_HANDSHAKE_s) ? 1'b0 :
955
                 (rd_state == FINISH_s) ? 1'b0 :
956
                 (rd_state == RETRANSMIT_ERR_s) ? 1'b0 :
957
                 (rd_state == RETRANSMIT_s) ? 1'b0 :
958
                 (rd_state == DATA_PRELOAD1_s) ? 1'b0 : 1'b1;
959
 
960
  // When the BRAM is being read, enable the read address to be incremented.
961
  assign rd_addr_inc = rd_en;
962
 
963
  assign rd_addr_reload = (rd_state != FINISH_s && rd_nxt_state == FINISH_s)
964
                          ? 1'b1 :
965
                          (rd_state == DROP_s && rd_nxt_state == IDLE_s)
966
                          ? 1'b1 : 1'b0;
967
 
968
  // Assertion indicates that the starting address must be reloaded to enable
969
  // the current frame to be retransmitted.
970
  assign rd_start_addr_reload = (rd_state == RETRANSMIT_s) ? 1'b1 : 1'b0;
971
 
972
  assign rd_start_addr_load = (rd_state== WAIT_HANDSHAKE_s && rd_nxt_state == FRAME_s)
973
                              ? 1'b1 :
974
                              (rd_col_window_expire == 1'b1) ? 1'b1 : 1'b0;
975
 
976
  // Transmit frame pulse must never be more frequent than once per 64 clocks to
977
  // allow toggle to cross clock domain.
978
  assign rd_transmit_frame = (rd_state == FINISH_s && rd_nxt_state == IDLE_s)
979
                             ? 1'b1 : 1'b0;
980
 
981
  // Retransmit frame pulse must never be more frequent than once per 16 clocks
982
  // to allow toggle to cross clock domain.
983
  assign rd_retransmit_frame = (rd_state == RETRANSMIT_s) ? 1'b1 : 1'b0;
984
 
985
end
986
endgenerate
987
 
988
 
989
  //----------------------------------------------------------------------------
990
  // Frame count
991
  // We need to maintain a count of frames in the FIFO, so that we know when a
992
  // frame is available for transmission. The counter must be held on the write
993
  // clock domain as this is the faster clock if they differ.
994
  //----------------------------------------------------------------------------
995
 
996
  // A frame has been written to the FIFO.
997
  assign wr_store_frame = (wr_state == EOF_s && wr_nxt_state != EOF_s)
998
                          ? 1'b1 : 1'b0;
999
 
1000
  // Generate a toggle to indicate when a frame has been transmitted by the FIFO.
1001
  always @(posedge tx_mac_aclk)
1002
  begin
1003
     if (rd_transmit_frame == 1'b1) begin
1004
        rd_tran_frame_tog <= !rd_tran_frame_tog;
1005
     end
1006
  end
1007
 
1008
  // Synchronize the read transmit frame signal into the write clock domain.
1009
  tri_mode_ethernet_mac_0_sync_block resync_rd_tran_frame_tog
1010
  (
1011
    .clk       (tx_fifo_aclk),
1012
    .data_in   (rd_tran_frame_tog),
1013
    .data_out  (wr_tran_frame_sync)
1014
  );
1015
 
1016
  // Edge-detect of the resynchronized transmit frame signal.
1017
 
1018
  always @(posedge tx_fifo_aclk)
1019
  begin
1020
     wr_tran_frame_delay <= wr_tran_frame_sync;
1021
  end
1022
 
1023
  always @(posedge tx_fifo_aclk)
1024
  begin
1025
      if (tx_fifo_reset == 1'b1) begin
1026
         wr_transmit_frame   <= 1'b0;
1027
      end
1028
      else begin
1029
         // Edge detector
1030
         if ((wr_tran_frame_delay ^ wr_tran_frame_sync) == 1'b1) begin
1031
           wr_transmit_frame <= 1'b1;
1032
         end
1033
         else begin
1034
           wr_transmit_frame <= 1'b0;
1035
         end
1036
      end
1037
  end
1038
 
1039
  always @(posedge tx_fifo_aclk)
1040
  begin
1041
      if (tx_fifo_reset == 1'b1) begin
1042
         wr_transmit_frame_delay   <= 1'b0;
1043
      end
1044
      else begin
1045
         wr_transmit_frame_delay <= wr_transmit_frame;
1046
      end
1047
  end
1048
 
1049
  always @(posedge tx_fifo_aclk)
1050
  begin
1051
      if (wr_transmit_frame_delay) begin
1052
         frame_in_fifo_valid_tog <= !frame_in_fifo_valid_tog;
1053
      end
1054
  end
1055
 
1056
  //----------------------------------------------------------------------------
1057
  // Full duplex-only frame count.
1058
generate if (FULL_DUPLEX_ONLY == 1) begin : gen_fd_count
1059
 
1060
  // Count the number of frames in the FIFO. The counter is incremented when a
1061
  // frame is stored and decremented when a frame is transmitted. Need to keep
1062
  // the counter on the write clock as this is the fastest clock if they differ.
1063
  always @(posedge tx_fifo_aclk)
1064
  begin
1065
     if (tx_fifo_reset == 1'b1) begin
1066
        wr_frames <= 9'b0;
1067
     end
1068
     else begin
1069
        if ((wr_store_frame & !wr_transmit_frame) == 1'b1) begin
1070
           wr_frames <= wr_frames + 9'b1;
1071
        end
1072
        else if ((!wr_store_frame & wr_transmit_frame) == 1'b1) begin
1073
           wr_frames <= wr_frames - 9'b1;
1074
        end
1075
     end
1076
  end
1077
 
1078
end
1079
endgenerate
1080
 
1081
  //----------------------------------------------------------------------------
1082
  // Full and half duplex frame count.
1083
generate if (FULL_DUPLEX_ONLY != 1) begin : gen_hd_count
1084
 
1085
  // Generate a toggle to indicate when a frame has been retransmitted by
1086
  // the FIFO.
1087
  always @(posedge tx_mac_aclk)
1088
  begin  // process
1089
     if (rd_retransmit_frame == 1'b1) begin
1090
        rd_retran_frame_tog <= !rd_retran_frame_tog;
1091
     end
1092
  end
1093
 
1094
  // Synchronize the read retransmit frame signal into the write clock domain.
1095
  tri_mode_ethernet_mac_0_sync_block resync_rd_tran_frame_tog
1096
  (
1097
    .clk       (tx_fifo_aclk),
1098
    .data_in   (rd_retran_frame_tog),
1099
    .data_out  (wr_retran_frame_sync)
1100
  );
1101
 
1102
  // Edge detect of the resynchronized retransmit frame signal.
1103
 
1104
  always @(posedge tx_fifo_aclk)
1105
  begin
1106
     wr_retran_frame_delay <= wr_retran_frame_sync;
1107
  end
1108
 
1109
  always @(posedge tx_fifo_aclk)
1110
  begin
1111
     if (tx_fifo_reset == 1'b1) begin
1112
        wr_retransmit_frame    <= 1'b0;
1113
     end
1114
     else begin
1115
        // Edge detector
1116
        if ((wr_retran_frame_delay ^ wr_retran_frame_sync) == 1'b1) begin
1117
           wr_retransmit_frame <= 1'b1;
1118
        end
1119
        else begin
1120
           wr_retransmit_frame <= 1'b0;
1121
        end
1122
     end
1123
  end
1124
 
1125
  // Count the number of frames in the FIFO. The counter is incremented when a
1126
  // frame is stored or retransmitted and decremented when a frame is
1127
  // transmitted. Need to keep the counter on the write clock as this is the
1128
  // fastest clock if they differ. Logic assumes transmit and retransmit cannot
1129
  // happen at same time.
1130
  always @(posedge tx_fifo_aclk)
1131
  begin
1132
     if (tx_fifo_reset == 1'b1) begin
1133
        wr_frames <= 9'd0;
1134
     end
1135
     else begin
1136
        if ((wr_store_frame & wr_retransmit_frame) == 1'b1) begin
1137
           wr_frames <= wr_frames + 9'd2;
1138
        end
1139
        else if (((wr_store_frame | wr_retransmit_frame)
1140
                 & !wr_transmit_frame) == 1'b1) begin
1141
           wr_frames <= wr_frames + 9'd1;
1142
        end
1143
        else if (wr_transmit_frame == 1'b1 & !wr_store_frame) begin
1144
           wr_frames <= wr_frames - 9'd1;
1145
        end
1146
     end
1147
  end
1148
 
1149
end
1150
endgenerate
1151
 
1152
  // Generate a frame in FIFO signal for use in control logic.
1153
  always @(posedge tx_fifo_aclk)
1154
  begin
1155
      if (tx_fifo_reset == 1'b1) begin
1156
         wr_frame_in_fifo <= 1'b0;
1157
      end
1158
      else begin
1159
         if (wr_frames != 9'b0) begin
1160
            wr_frame_in_fifo <= 1'b1;
1161
         end
1162
         else begin
1163
            wr_frame_in_fifo <= 1'b0;
1164
         end
1165
      end
1166
  end
1167
 
1168
  // Generate a multiple frames in FIFO signal for use in control logic.
1169
  always @(posedge tx_fifo_aclk)
1170
  begin
1171
      if (tx_fifo_reset == 1'b1) begin
1172
         wr_frames_in_fifo <= 1'b0;
1173
      end
1174
      else begin
1175
         if (wr_frames >= 9'h2) begin
1176
            wr_frames_in_fifo <= 1'b1;
1177
         end
1178
         else begin
1179
            wr_frames_in_fifo <= 1'b0;
1180
         end
1181
      end
1182
  end
1183
 
1184
  // Synchronize it back onto read domain for use in the read logic.
1185
  tri_mode_ethernet_mac_0_sync_block resync_wr_frame_in_fifo
1186
  (
1187
    .clk       (tx_mac_aclk),
1188
    .data_in   (wr_frame_in_fifo),
1189
    .data_out  (frame_in_fifo)
1190
  );
1191
 
1192
  // Synchronize it back onto read domain for use in the read logic.
1193
  tri_mode_ethernet_mac_0_sync_block resync_wr_frames_in_fifo
1194
  (
1195
    .clk       (tx_mac_aclk),
1196
    .data_in   (wr_frames_in_fifo),
1197
    .data_out  (frames_in_fifo)
1198
  );
1199
 
1200
  // in he case where only one frame is in the fifo we have to be careful about the faling edge of
1201
  // the frame in fifo signal as for short frames this could occur after the state machine completes
1202
  tri_mode_ethernet_mac_0_sync_block resync_fif_valid_tog
1203
  (
1204
    .clk       (tx_mac_aclk),
1205
    .data_in   (frame_in_fifo_valid_tog),
1206
    .data_out  (frame_in_fifo_valid_sync)
1207
  );
1208
 
1209
  // Edge detect of the re-resynchronized read transmit frame signal.
1210
  always @(posedge tx_mac_aclk)
1211
  begin
1212
     frame_in_fifo_valid_delay <= frame_in_fifo_valid_sync;
1213
  end
1214
 
1215
  always @(posedge tx_mac_aclk)
1216
  begin
1217
     if (tx_mac_reset == 1'b1) begin
1218
        frame_in_fifo_valid = 1'b1;
1219
     end
1220
     else begin
1221
        if (frame_in_fifo_valid_delay ^ frame_in_fifo_valid_sync) begin
1222
           frame_in_fifo_valid <= 1'b1;
1223
        end
1224
        else if (rd_transmit_frame) begin
1225
           frame_in_fifo_valid <= 1'b0;
1226
        end
1227
     end
1228
  end
1229
 
1230
 
1231
  //----------------------------------------------------------------------------
1232
  // Address counters
1233
  //----------------------------------------------------------------------------
1234
 
1235
  // Write address is incremented when write enable signal has been asserted.
1236
  always @(posedge tx_fifo_aclk)
1237
  begin
1238
     if (tx_fifo_reset == 1'b1) begin
1239
        wr_addr <= 12'b0;
1240
     end
1241
     else if (wr_addr_reload == 1'b1) begin
1242
        wr_addr <= wr_start_addr;
1243
     end
1244
     else if (wr_addr_inc == 1'b1) begin
1245
        wr_addr <= wr_addr + 12'b1;
1246
     end
1247
  end
1248
 
1249
  // Store the start address in case the address must be reset.
1250
  always @(posedge tx_fifo_aclk)
1251
  begin
1252
     if (tx_fifo_reset == 1'b1) begin
1253
        wr_start_addr <= 12'b0;
1254
     end
1255
     else if (wr_start_addr_load == 1'b1) begin
1256
        wr_start_addr <= wr_addr + 12'b1;
1257
     end
1258
  end
1259
 
1260
  //----------------------------------------------------------------------------
1261
  // Half duplex-only read address counters.
1262
generate if (FULL_DUPLEX_ONLY == 1) begin : gen_fd_addr
1263
  // Read address is incremented when read enable signal has been asserted.
1264
  always @(posedge tx_mac_aclk)
1265
  begin
1266
     if (tx_mac_reset == 1'b1) begin
1267
        rd_addr <= 12'b0;
1268
     end
1269
     else begin
1270
        if (rd_addr_reload == 1'b1) begin
1271
           rd_addr <= rd_dec_addr;
1272
        end
1273
        else if (rd_addr_inc == 1'b1) begin
1274
           rd_addr <= rd_addr + 12'b1;
1275
        end
1276
     end
1277
  end
1278
 
1279
  // Do not need to keep a start address, but the address is needed to
1280
  // calculate FIFO occupancy.
1281
  always @(posedge tx_mac_aclk)
1282
  begin
1283
     if (tx_mac_reset == 1'b1) begin
1284
        rd_start_addr <= 12'b0;
1285
     end
1286
     else begin
1287
        rd_start_addr <= rd_addr;
1288
     end
1289
  end
1290
 
1291
end
1292
endgenerate
1293
 
1294
  //----------------------------------------------------------------------------
1295
  // Full and half duplex read address counters.
1296
generate if (FULL_DUPLEX_ONLY != 1) begin : gen_hd_addr
1297
  // Read address is incremented when read enable signal has been asserted.
1298
  always @(posedge tx_mac_aclk)
1299
  begin
1300
     if (tx_mac_reset == 1'b1) begin
1301
        rd_addr <= 12'b0;
1302
     end
1303
     else begin
1304
        if (rd_addr_reload == 1'b1) begin
1305
           rd_addr <= rd_dec_addr;
1306
        end
1307
        else if (rd_start_addr_reload == 1'b1) begin
1308
           rd_addr <= rd_start_addr;
1309
        end
1310
        else if (rd_addr_inc == 1'b1) begin
1311
           rd_addr <= rd_addr + 12'b1;
1312
        end
1313
     end
1314
  end
1315
 
1316
  always @(posedge tx_mac_aclk)
1317
  begin
1318
     if (tx_mac_reset == 1'b1) begin
1319
        rd_start_addr <= 12'd0;
1320
     end
1321
     else begin
1322
        if (rd_start_addr_load == 1'b1) begin
1323
           rd_start_addr <= rd_addr - 12'd6;
1324
        end
1325
     end
1326
  end
1327
 
1328
  // Collision window expires after MAC has been transmitting for required slot
1329
  // time. This is 512 clock cycles at 1Gbps. Also if the end of frame has fully
1330
  // been transmitted by the MAC then a collision cannot occur. This collision
1331
  // expiration signal goes high at 768 cycles from the start of the frame.
1332
  // This is inefficient for short frames, however it should be enough to
1333
  // prevent the FIFO from locking up.
1334
  always @(posedge tx_mac_aclk)
1335
  begin
1336
     if (tx_mac_reset == 1'b1) begin
1337
        rd_col_window_expire <= 1'b0;
1338
     end
1339
     else begin
1340
        if (rd_transmit_frame == 1'b1) begin
1341
           rd_col_window_expire <= 1'b0;
1342
        end
1343
        else if (rd_slot_timer[9:7] == 3'b110) begin
1344
           rd_col_window_expire <= 1'b1;
1345
        end
1346
     end
1347
  end
1348
 
1349
  assign rd_idle_state = (rd_state == IDLE_s) ? 1'b1 : 1'b0;
1350
 
1351
  always @(posedge tx_mac_aclk)
1352
  begin
1353
     rd_col_window_pipe[0] <= rd_col_window_expire & rd_idle_state;
1354
     if (rd_txfer_en == 1'b1) begin
1355
        rd_col_window_pipe[1] <= rd_col_window_pipe[0];
1356
     end
1357
  end
1358
 
1359
  always @(posedge tx_mac_aclk)
1360
  begin
1361
     // Will not count until after the first frame is sent.
1362
     if (tx_mac_reset == 1'b1) begin
1363
        rd_slot_timer <= 10'b1111111111;
1364
     end
1365
     else begin
1366
        // Reset counter.
1367
        if (rd_transmit_frame == 1'b1) begin
1368
           rd_slot_timer <= 10'b0;
1369
        end
1370
        // Do not allow counter to roll over, and
1371
        // only count when frame is being transmitted.
1372
        else if (rd_slot_timer != 10'b1111111111) begin
1373
           rd_slot_timer <= rd_slot_timer + 10'b1;
1374
        end
1375
     end
1376
  end
1377
 
1378
end
1379
endgenerate
1380
 
1381
  // Read address generation.
1382
  always @(posedge tx_mac_aclk)
1383
  begin
1384
     if (tx_mac_reset == 1'b1) begin
1385
        rd_dec_addr <= 12'b0;
1386
     end
1387
     else begin
1388
        if (rd_addr_inc == 1'b1) begin
1389
           rd_dec_addr <= rd_addr - 12'b1;
1390
        end
1391
     end
1392
  end
1393
 
1394
 
1395
  //----------------------------------------------------------------------------
1396
  // Data pipelines
1397
  //----------------------------------------------------------------------------
1398
 
1399
 
1400
  // Register data inputs to BRAM.
1401
  // No resets to allow for SRL16 target.
1402
  always @(posedge tx_fifo_aclk)
1403
  begin
1404
     wr_data_pipe[0] <= tx_axis_fifo_tdata;
1405
     if (wr_accept_pipe[0] == 1'b1) begin
1406
        wr_data_pipe[1] <= wr_data_pipe[0];
1407
     end
1408
     if (wr_accept_pipe[1] == 1'b1) begin
1409
        wr_data_bram    <= wr_data_pipe[1];
1410
     end
1411
  end
1412
 
1413
 
1414
 
1415
  // Start of frame set when tvalid is asserted and previous frame has ended.
1416
  assign wr_sof_int = tx_axis_fifo_tvalid & wr_eof_reg;
1417
 
1418
  // Set end of frame flag when tlast and tvalid are asserted together.
1419
  // Reset to logic 1 to enable first frame's start of frame flag.
1420
  always @(posedge tx_fifo_aclk)
1421
  begin
1422
    if (tx_fifo_reset == 1'b1) begin
1423
      wr_eof_reg <= 1'b1;
1424
    end
1425
    else begin
1426
      if (tx_axis_fifo_tvalid == 1'b1 & tx_axis_fifo_tready_int_n == 1'b0) begin
1427
        wr_eof_reg <= tx_axis_fifo_tlast;
1428
      end
1429
    end
1430
  end
1431
 
1432
  // Pipeline the start of frame flag when the pipe is enabled.
1433
  always @(posedge tx_fifo_aclk)
1434
  begin
1435
     wr_sof_pipe[0] <= wr_sof_int & !tx_axis_fifo_tlast;
1436
     if (wr_accept_pipe[0] == 1'b1) begin
1437
        wr_sof_pipe[1] <= wr_sof_pipe[0];
1438
     end
1439
  end
1440
 
1441
  // Pipeline the pipeline enable signal, which is derived from simultaneous
1442
  // assertion of tvalid and tready.
1443
  always @(posedge tx_fifo_aclk)
1444
  begin
1445
     if (tx_fifo_reset == 1'b1) begin
1446
        wr_accept_pipe[0] <= 1'b0;
1447
        wr_accept_pipe[1] <= 1'b0;
1448
        wr_accept_bram    <= 1'b0;
1449
     end
1450
     else begin
1451
        wr_accept_pipe[0] <= tx_axis_fifo_tvalid & !tx_axis_fifo_tready_int_n &
1452
                             !(tx_axis_fifo_tlast & wr_sof_int);
1453
        wr_accept_pipe[1] <= wr_accept_pipe[0];
1454
        wr_accept_bram    <= wr_accept_pipe[1];
1455
     end
1456
  end
1457
 
1458
  // Pipeline the end of frame flag when the pipe is enabled.
1459
  always @(posedge tx_fifo_aclk)
1460
  begin
1461
     wr_eof_pipe[0] <= tx_axis_fifo_tvalid & tx_axis_fifo_tlast & !wr_sof_int;
1462
     if (wr_accept_pipe[0] == 1'b1) begin
1463
        wr_eof_pipe[1] <= wr_eof_pipe[0];
1464
     end
1465
     if (wr_accept_pipe[1] == 1'b1) begin
1466
        wr_eof_bram[0] <= wr_eof_pipe[1];
1467
     end
1468
  end
1469
 
1470
  // Register data outputs from BRAM.
1471
  // No resets to allow for SRL16 target.
1472
 always @(posedge tx_mac_aclk)
1473
  begin
1474
     if (rd_en == 1'b1) begin
1475
           rd_data_delay <= rd_data_bram;
1476
           rd_data_pipe <= rd_data_delay;
1477
      end
1478
  end
1479
 
1480
 always @(posedge tx_mac_aclk)
1481
  begin
1482
     if (rd_en == 1'b1) begin
1483
          rd_eof_pipe <= rd_eof_bram[0];
1484
          rd_eof <= rd_eof_pipe;
1485
          rd_eof_reg <= rd_eof | rd_eof_pipe;
1486
     end
1487
  end
1488
 
1489
  //----------------------------------------------------------------------------
1490
  // Half duplex-only drop and retransmission controls.
1491
generate if (FULL_DUPLEX_ONLY != 1) begin : gen_hd_input
1492
  // Register the collision without retransmit signal, which is a pulse that
1493
  // causes the FIFO to drop the frame.
1494
  always @(posedge tx_mac_aclk)
1495
  begin
1496
     rd_drop_frame <= tx_collision & !tx_retransmit;
1497
  end
1498
 
1499
  // Register the collision with retransmit signal, which is a pulse that
1500
  // causes the FIFO to retransmit the frame.
1501
  always @(posedge tx_mac_aclk)
1502
  begin
1503
     rd_retransmit <= tx_collision & tx_retransmit;
1504
  end
1505
end
1506
endgenerate
1507
 
1508
 
1509
  //----------------------------------------------------------------------------
1510
  // FIFO full functionality
1511
  //----------------------------------------------------------------------------
1512
 
1513
  // Full functionality is the difference between read and write addresses.
1514
  // We cannot use gray code this time as the read address and read start
1515
  // addresses jump by more than 1.
1516
  // We generate an enable pulse for the read side every 16 read clocks. This
1517
  // provides for the worst-case situation where the write clock is 20MHz and
1518
  // read clock is 125MHz.
1519
  always @(posedge tx_mac_aclk)
1520
  begin
1521
     if (tx_mac_reset == 1'b1) begin
1522
        rd_16_count <= 4'b0;
1523
     end
1524
     else begin
1525
        rd_16_count <= rd_16_count + 4'b1;
1526
     end
1527
  end
1528
 
1529
  assign rd_txfer_en = (rd_16_count == 4'b1111) ? 1'b1 : 1'b0;
1530
 
1531
  // Register the start address on the enable pulse.
1532
  always @(posedge tx_mac_aclk)
1533
  begin
1534
     if (tx_mac_reset == 1'b1) begin
1535
        rd_addr_txfer <= 12'b0;
1536
     end
1537
     else begin
1538
        if (rd_txfer_en == 1'b1) begin
1539
           rd_addr_txfer <= rd_start_addr;
1540
        end
1541
     end
1542
  end
1543
 
1544
  // Generate a toggle to indicate that the address has been loaded.
1545
  always @(posedge tx_mac_aclk)
1546
  begin
1547
     if (rd_txfer_en == 1'b1) begin
1548
        rd_txfer_tog <= !rd_txfer_tog;
1549
     end
1550
  end
1551
 
1552
  // Synchronize the toggle to the write side.
1553
  tri_mode_ethernet_mac_0_sync_block resync_rd_txfer_tog
1554
  (
1555
    .clk       (tx_fifo_aclk),
1556
    .data_in   (rd_txfer_tog),
1557
    .data_out  (wr_txfer_tog_sync)
1558
  );
1559
 
1560
  // Delay the synchronized toggle by one cycle.
1561
  always @(posedge tx_fifo_aclk)
1562
  begin
1563
     wr_txfer_tog_delay <= wr_txfer_tog_sync;
1564
  end
1565
 
1566
  // Generate an enable pulse from the toggle. The address should have been
1567
  // steady on the wr clock input for at least one clock.
1568
  assign wr_txfer_en = wr_txfer_tog_delay ^ wr_txfer_tog_sync;
1569
 
1570
  // Capture the address on the write clock when the enable pulse is high.
1571
  always @(posedge tx_fifo_aclk)
1572
  begin
1573
     if (tx_fifo_reset == 1'b1) begin
1574
        wr_rd_addr <= 12'b0;
1575
     end
1576
     else if (wr_txfer_en == 1'b1) begin
1577
        wr_rd_addr <= rd_addr_txfer;
1578
     end
1579
  end
1580
 
1581
  // Obtain the difference between write and read pointers.
1582
  always @(posedge tx_fifo_aclk)
1583
  begin
1584
     if (tx_fifo_reset == 1'b1) begin
1585
        wr_addr_diff <= 12'b0;
1586
     end
1587
     else begin
1588
        wr_addr_diff <= wr_rd_addr - wr_addr;
1589
     end
1590
  end
1591
 
1592
  // Detect when the FIFO is full.
1593
  // The FIFO is considered to be full if the write address pointer is
1594
  // within 0 to 3 of the read address pointer.
1595
  always @(posedge tx_fifo_aclk)
1596
  begin
1597
     if (tx_fifo_reset == 1'b1) begin
1598
        wr_fifo_full <= 1'b0;
1599
     end
1600
     else begin
1601
        if (wr_addr_diff[11:4] == 8'b0 && wr_addr_diff[3:2] != 2'b0) begin
1602
           wr_fifo_full <= 1'b1;
1603
        end
1604
        else begin
1605
           wr_fifo_full <= 1'b0;
1606
        end
1607
     end
1608
  end
1609
 
1610
  // Memory overflow occurs when the FIFO is full and there are no frames
1611
  // available in the FIFO for transmission. If the collision window has
1612
  // expired and there are no frames in the FIFO and the FIFO is full, then the
1613
  // FIFO is in an overflow state. We must accept the rest of the incoming
1614
  // frame in overflow condition.
1615
 
1616
generate if (FULL_DUPLEX_ONLY == 1) begin : gen_fd_ovflow
1617
     // In full duplex mode, the FIFO memory can only overflow if the FIFO goes
1618
     // full but there is no frame available to be retranmsitted. Therefore,
1619
     // prevent signal from being asserted when store_frame signal is high, as
1620
     // frame count is being updated.
1621
     assign wr_fifo_overflow = (wr_fifo_full == 1'b1 && wr_frame_in_fifo == 1'b0
1622
                                   && wr_eof_state == 1'b0
1623
                                   && wr_eof_state_reg == 1'b0)
1624
                                ? 1'b1 : 1'b0;
1625
 
1626
     // Tie off unused half-duplex signals
1627
     always @(posedge tx_fifo_aclk)
1628
     begin
1629
       wr_col_window_pipe[0] <= 1'b0;
1630
       wr_col_window_pipe[1] <= 1'b0;
1631
     end
1632
 
1633
end
1634
endgenerate
1635
 
1636
generate if (FULL_DUPLEX_ONLY != 1) begin : gen_hd_ovflow
1637
    // In half duplex mode, register write collision window to give address
1638
    // counter sufficient time to update. This will prevent the signal from
1639
    // being asserted when the store_frame signal is high, as the frame count
1640
    // is being updated.
1641
    assign wr_fifo_overflow = (wr_fifo_full == 1'b1 && wr_frame_in_fifo == 1'b0
1642
                                  && wr_eof_state == 1'b0
1643
                                  && wr_eof_state_reg == 1'b0
1644
                                  && wr_col_window_expire == 1'b1)
1645
                               ? 1'b1 : 1'b0;
1646
 
1647
    // Register rd_col_window signal.
1648
    // This signal is long, and will remain high until overflow functionality
1649
    // has finished, so save just to register once.
1650
    always @(posedge tx_fifo_aclk)
1651
    begin
1652
       if (tx_fifo_reset == 1'b1) begin
1653
          wr_col_window_pipe[0] <= 1'b0;
1654
          wr_col_window_pipe[1] <= 1'b0;
1655
          wr_col_window_expire  <= 1'b0;
1656
       end
1657
       else begin
1658
          if (wr_txfer_en == 1'b1) begin
1659
             wr_col_window_pipe[0] <= rd_col_window_pipe[1];
1660
          end
1661
          wr_col_window_pipe[1] <= wr_col_window_pipe[0];
1662
          wr_col_window_expire <= wr_col_window_pipe[1];
1663
       end
1664
    end
1665
 
1666
end
1667
endgenerate
1668
 
1669
 
1670
  //----------------------------------------------------------------------------
1671
  // FIFO status signals
1672
  //----------------------------------------------------------------------------
1673
 
1674
  // The FIFO status is four bits which represents the occupancy of the FIFO
1675
  // in sixteenths. To generate this signal we therefore only need to compare
1676
  // the 4 most significant bits of the write address pointer with the 4 most
1677
  // significant bits of the read address pointer.
1678
 
1679
  always @(posedge tx_fifo_aclk)
1680
  begin
1681
     if (tx_fifo_reset == 1'b1) begin
1682
        wr_fifo_status <= 4'b0;
1683
     end
1684
     else begin
1685
        if (wr_addr_diff == 12'b0) begin
1686
           wr_fifo_status <= 4'b0;
1687
        end
1688
        else begin
1689
           wr_fifo_status[3] <= !wr_addr_diff[11];
1690
           wr_fifo_status[2] <= !wr_addr_diff[10];
1691
           wr_fifo_status[1] <= !wr_addr_diff[9];
1692
           wr_fifo_status[0] <= !wr_addr_diff[8];
1693
        end
1694
     end
1695
  end
1696
 
1697
  assign fifo_status = wr_fifo_status;
1698
 
1699
 
1700
  //----------------------------------------------------------------------------
1701
  // Instantiate FIFO block memory
1702
  //----------------------------------------------------------------------------
1703
 
1704
  assign wr_eof_data_bram[8]   = wr_eof_bram[0];
1705
  assign wr_eof_data_bram[7:0] = wr_data_bram;
1706
 
1707
  assign rd_eof_bram[0] = rd_eof_data_bram[8];
1708
  assign rd_data_bram   = rd_eof_data_bram[7:0];
1709
 
1710
tri_mode_ethernet_mac_0_bram_tdp #
1711
  (
1712
     .DATA_WIDTH  (9),
1713
     .ADDR_WIDTH  (12)
1714
  )
1715
  tx_ramgen_i (
1716
     .b_dout  (rd_eof_data_bram),
1717
     .a_addr  (wr_addr[11:0]),
1718
     .b_addr  (rd_addr[11:0]),
1719
     .a_clk   (tx_fifo_aclk),
1720
     .b_clk   (tx_mac_aclk),
1721
     .a_din   (wr_eof_data_bram),
1722
     .b_en    (rd_en),
1723
     .a_rst   (tx_fifo_reset),
1724
     .b_rst   (tx_mac_reset),
1725
     .a_wr    (wr_en)
1726
  );
1727
 
1728
endmodule

powered by: WebSVN 2.1.0

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