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

Subversion Repositories xge_mac

[/] [xge_mac/] [trunk/] [rtl/] [verilog/] [tx_dequeue.v] - Blame information for rev 23

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

Line No. Rev Author Line
1 2 antanguay
//////////////////////////////////////////////////////////////////////
2
////                                                              ////
3
////  File name "tx_dequeue.v"                                    ////
4
////                                                              ////
5
////  This file is part of the "10GE MAC" project                 ////
6
////  http://www.opencores.org/cores/xge_mac/                     ////
7
////                                                              ////
8
////  Author(s):                                                  ////
9
////      - A. Tanguay (antanguay@opencores.org)                  ////
10
////                                                              ////
11
//////////////////////////////////////////////////////////////////////
12
////                                                              ////
13
//// Copyright (C) 2008 AUTHORS. All rights reserved.             ////
14
////                                                              ////
15
//// This source file may be used and distributed without         ////
16
//// restriction provided that this copyright statement is not    ////
17
//// removed from the file and that any derivative work contains  ////
18
//// the original copyright notice and the associated disclaimer. ////
19
////                                                              ////
20
//// This source file is free software; you can redistribute it   ////
21
//// and/or modify it under the terms of the GNU Lesser General   ////
22
//// Public License as published by the Free Software Foundation; ////
23
//// either version 2.1 of the License, or (at your option) any   ////
24
//// later version.                                               ////
25
////                                                              ////
26
//// This source is distributed in the hope that it will be       ////
27
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
28
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
29
//// PURPOSE.  See the GNU Lesser General Public License for more ////
30
//// details.                                                     ////
31
////                                                              ////
32
//// You should have received a copy of the GNU Lesser General    ////
33
//// Public License along with this source; if not, download it   ////
34
//// from http://www.opencores.org/lgpl.shtml                     ////
35
////                                                              ////
36
//////////////////////////////////////////////////////////////////////
37
 
38
 
39
`include "defines.v"
40
 
41
module tx_dequeue(/*AUTOARG*/
42
  // Outputs
43 12 antanguay
  txdfifo_ren, txhfifo_ren, txhfifo_wdata, txhfifo_wstatus,
44
  txhfifo_wen, xgmii_txd, xgmii_txc, status_txdfifo_udflow_tog,
45 23 antanguay
  status_good_frame_tx_tog, status_good_frame_tx_size,
46 2 antanguay
  // Inputs
47 12 antanguay
  clk_xgmii_tx, reset_xgmii_tx_n, ctrl_tx_enable_ctx,
48
  status_local_fault_ctx, status_remote_fault_ctx, txdfifo_rdata,
49
  txdfifo_rstatus, txdfifo_rempty, txdfifo_ralmost_empty,
50
  txhfifo_rdata, txhfifo_rstatus, txhfifo_rempty,
51 2 antanguay
  txhfifo_ralmost_empty, txhfifo_wfull, txhfifo_walmost_full
52
  );
53
`include "CRC32_D64.v"
54
`include "CRC32_D8.v"
55
`include "utils.v"
56
 
57
input         clk_xgmii_tx;
58
input         reset_xgmii_tx_n;
59
 
60
input         ctrl_tx_enable_ctx;
61 20 antanguay
 
62 2 antanguay
input         status_local_fault_ctx;
63
input         status_remote_fault_ctx;
64 20 antanguay
 
65 2 antanguay
input  [63:0] txdfifo_rdata;
66
input  [7:0]  txdfifo_rstatus;
67
input         txdfifo_rempty;
68
input         txdfifo_ralmost_empty;
69
 
70
input  [63:0] txhfifo_rdata;
71
input  [7:0]  txhfifo_rstatus;
72
input         txhfifo_rempty;
73
input         txhfifo_ralmost_empty;
74
 
75
input         txhfifo_wfull;
76
input         txhfifo_walmost_full;
77
 
78
output        txdfifo_ren;
79
 
80
output        txhfifo_ren;
81
 
82
output [63:0] txhfifo_wdata;
83
output [7:0]  txhfifo_wstatus;
84 20 antanguay
output        txhfifo_wen;
85 2 antanguay
 
86
output [63:0] xgmii_txd;
87
output [7:0]  xgmii_txc;
88
 
89
output        status_txdfifo_udflow_tog;
90
 
91 23 antanguay
output        status_good_frame_tx_tog;
92
output [13:0] status_good_frame_tx_size;
93 2 antanguay
 
94
 
95
 
96
/*AUTOREG*/
97
// Beginning of automatic regs (for this module's undeclared outputs)
98 23 antanguay
reg [13:0]              status_good_frame_tx_size;
99
reg                     status_good_frame_tx_tog;
100 2 antanguay
reg                     status_txdfifo_udflow_tog;
101
reg                     txdfifo_ren;
102
reg                     txhfifo_ren;
103
reg [63:0]              txhfifo_wdata;
104
reg                     txhfifo_wen;
105
reg [7:0]               txhfifo_wstatus;
106
reg [7:0]               xgmii_txc;
107
reg [63:0]              xgmii_txd;
108
// End of automatics
109
 
110
/*AUTOWIRE*/
111
 
112
 
113
reg   [63:0]    xgxs_txd;
114
reg   [7:0]     xgxs_txc;
115
 
116
reg   [63:0]    next_xgxs_txd;
117
reg   [7:0]     next_xgxs_txc;
118
 
119 10 antanguay
reg   [2:0]     curr_state_enc;
120
reg   [2:0]     next_state_enc;
121 2 antanguay
 
122 10 antanguay
reg   [0:0]     curr_state_pad;
123
reg   [0:0]     next_state_pad;
124 2 antanguay
 
125
reg             start_on_lane0;
126
reg             next_start_on_lane0;
127
 
128
reg   [2:0]     ifg_deficit;
129
reg   [2:0]     next_ifg_deficit;
130
 
131
reg             ifg_4b_add;
132
reg             next_ifg_4b_add;
133
 
134
reg             ifg_8b_add;
135
reg             next_ifg_8b_add;
136
 
137
reg             ifg_8b2_add;
138
reg             next_ifg_8b2_add;
139
 
140 6 antanguay
reg   [7:0]     eop;
141
reg   [7:0]     next_eop;
142
 
143 2 antanguay
reg   [63:32]   xgxs_txd_barrel;
144
reg   [7:4]     xgxs_txc_barrel;
145
 
146
reg   [63:0]    txhfifo_rdata_d1;
147
 
148
reg   [13:0]    byte_cnt;
149
 
150
reg   [31:0]    crc32_d64;
151
reg   [31:0]    crc32_d8;
152
reg   [31:0]    crc32_tx;
153
 
154
reg   [63:0]    shift_crc_data;
155 6 antanguay
reg   [3:0]     shift_crc_eop;
156
reg   [3:0]     shift_crc_cnt;
157 2 antanguay
 
158
reg   [31:0]    crc_data;
159
 
160
reg             frame_available;
161
reg             next_frame_available;
162
 
163
reg   [63:0]    next_txhfifo_wdata;
164
reg   [7:0]     next_txhfifo_wstatus;
165 20 antanguay
reg             next_txhfifo_wen;
166 2 antanguay
 
167 6 antanguay
reg             txdfifo_ren_d1;
168
 
169 23 antanguay
reg             frame_end;
170
 
171 2 antanguay
parameter [2:0]
172
             SM_IDLE      = 3'd0,
173
             SM_PREAMBLE  = 3'd1,
174
             SM_TX        = 3'd2,
175
             SM_EOP       = 3'd3,
176
             SM_TERM      = 3'd4,
177
             SM_TERM_FAIL = 3'd5,
178
             SM_IFG       = 3'd6;
179
 
180 6 antanguay
parameter [0:0]
181 10 antanguay
             SM_PAD_EQ    = 1'd0,
182
             SM_PAD_PAD   = 1'd1;
183 2 antanguay
 
184
 
185
//---
186
// RC layer
187
 
188
always @(posedge clk_xgmii_tx or negedge reset_xgmii_tx_n) begin
189
 
190
    if (reset_xgmii_tx_n == 1'b0) begin
191
 
192
        xgmii_txd <= {8{`IDLE}};
193
        xgmii_txc <= 8'hff;
194
 
195
    end
196
    else begin
197
 
198
 
199
        //---
200
        // RC Layer, insert local or remote fault messages based on status
201
        // of fault state-machine
202
 
203
        if (status_local_fault_ctx) begin
204
 
205
            // If local fault detected, send remote fault message to
206
            // link partner
207 20 antanguay
 
208 2 antanguay
            xgmii_txd <= {`REMOTE_FAULT, 8'h0, 8'h0, `SEQUENCE,
209
                          `REMOTE_FAULT, 8'h0, 8'h0, `SEQUENCE};
210
            xgmii_txc <= {4'b0001, 4'b0001};
211
        end
212
        else if (status_remote_fault_ctx) begin
213
 
214
            // If remote fault detected, inhibit transmission and send
215
            // idle codes
216 20 antanguay
 
217 2 antanguay
            xgmii_txd <= {8{`IDLE}};
218
            xgmii_txc <= 8'hff;
219
        end
220
        else begin
221
            xgmii_txd <= xgxs_txd;
222
            xgmii_txc <= xgxs_txc;
223
        end
224
    end
225
 
226
end
227
 
228
 
229
always @(posedge clk_xgmii_tx or negedge reset_xgmii_tx_n) begin
230
 
231
    if (reset_xgmii_tx_n == 1'b0) begin
232
 
233 10 antanguay
        curr_state_enc <= SM_IDLE;
234 2 antanguay
 
235
        start_on_lane0 <= 1'b1;
236
        ifg_deficit <= 3'b0;
237
        ifg_4b_add <= 1'b0;
238
        ifg_8b_add <= 1'b0;
239
        ifg_8b2_add <= 1'b0;
240
 
241 6 antanguay
        eop <= 8'b0;
242
 
243 2 antanguay
        txhfifo_rdata_d1 <= 64'b0;
244
 
245
        xgxs_txd_barrel <= {4{`IDLE}};
246
        xgxs_txc_barrel <= 4'hf;
247
 
248
        frame_available <= 1'b0;
249
 
250
        xgxs_txd <= {8{`IDLE}};
251
        xgxs_txc <= 8'hff;
252
 
253
        status_txdfifo_udflow_tog <= 1'b0;
254
 
255 23 antanguay
        status_good_frame_tx_tog <= 1'b0;
256
        status_good_frame_tx_size <= 14'b0;
257
 
258 2 antanguay
    end
259
    else begin
260
 
261 10 antanguay
        curr_state_enc <= next_state_enc;
262 2 antanguay
 
263
        start_on_lane0 <= next_start_on_lane0;
264
        ifg_deficit <= next_ifg_deficit;
265
        ifg_4b_add <= next_ifg_4b_add;
266
        ifg_8b_add <= next_ifg_8b_add;
267
        ifg_8b2_add <= next_ifg_8b2_add;
268
 
269 6 antanguay
        eop <= next_eop;
270
 
271 2 antanguay
        txhfifo_rdata_d1 <= txhfifo_rdata;
272
 
273
        xgxs_txd_barrel <= next_xgxs_txd[63:32];
274
        xgxs_txc_barrel <= next_xgxs_txc[7:4];
275
 
276
        frame_available <= next_frame_available;
277
 
278
        //---
279
        // Barrel shifter. Previous stage always align packet with LANE0.
280
        // This stage allow us to shift packet to align with LANE4 if needed
281
        // for correct inter frame gap (IFG).
282
 
283
        if (next_start_on_lane0) begin
284
 
285
            xgxs_txd <= next_xgxs_txd;
286
            xgxs_txc <= next_xgxs_txc;
287
 
288
        end
289
        else begin
290
 
291
            xgxs_txd <= {next_xgxs_txd[31:0], xgxs_txd_barrel};
292
            xgxs_txc <= {next_xgxs_txc[3:0], xgxs_txc_barrel};
293
 
294
        end
295
 
296
        //---
297
        // FIFO errors, used to generate interrupts.
298 20 antanguay
 
299 2 antanguay
        if (txdfifo_ren && txdfifo_rempty) begin
300
            status_txdfifo_udflow_tog <= ~status_txdfifo_udflow_tog;
301
        end
302
 
303 23 antanguay
        //---
304
        // Frame count and size
305
 
306
        if (frame_end) begin
307
            status_good_frame_tx_tog <= ~status_good_frame_tx_tog;
308
            status_good_frame_tx_size <= byte_cnt;
309
        end
310
 
311 2 antanguay
    end
312
 
313
end
314
 
315 10 antanguay
always @(/*AS*/crc32_tx or ctrl_tx_enable_ctx or curr_state_enc or eop
316 2 antanguay
         or frame_available or ifg_4b_add or ifg_8b2_add or ifg_8b_add
317
         or ifg_deficit or start_on_lane0 or status_local_fault_ctx
318 21 antanguay
         or status_remote_fault_ctx or txhfifo_ralmost_empty
319
         or txhfifo_rdata_d1 or txhfifo_rempty or txhfifo_rstatus) begin
320 2 antanguay
 
321 10 antanguay
    next_state_enc = curr_state_enc;
322 2 antanguay
 
323
    next_start_on_lane0 = start_on_lane0;
324
    next_ifg_deficit = ifg_deficit;
325
    next_ifg_4b_add = ifg_4b_add;
326
    next_ifg_8b_add = ifg_8b_add;
327
    next_ifg_8b2_add = ifg_8b2_add;
328
 
329 6 antanguay
    next_eop = eop;
330
 
331 2 antanguay
    next_xgxs_txd = {8{`IDLE}};
332
    next_xgxs_txc = 8'hff;
333
 
334
    txhfifo_ren = 1'b0;
335
 
336
    next_frame_available = frame_available;
337
 
338 10 antanguay
    case (curr_state_enc)
339 2 antanguay
 
340
        SM_IDLE:
341
          begin
342
 
343
              // Wait for frame to be available. There should be a least N bytes in the
344
              // data fifo or a crc in the control fifo. The N bytes in the data fifo
345
              // give time to the enqueue engine to calculate crc and write it to the
346
              // control fifo. If crc is already in control fifo we can start transmitting
347
              // with no concern. Transmission is inhibited if local or remote faults
348
              // are detected.
349
 
350
              if (ctrl_tx_enable_ctx && frame_available &&
351 20 antanguay
                  !status_local_fault_ctx && !status_remote_fault_ctx) begin
352 2 antanguay
 
353
                  txhfifo_ren = 1'b1;
354 10 antanguay
                  next_state_enc = SM_PREAMBLE;
355 2 antanguay
 
356
              end
357
              else begin
358
 
359
                  next_frame_available = !txhfifo_ralmost_empty;
360
                  next_ifg_4b_add = 1'b0;
361
 
362
              end
363
 
364
          end
365
 
366
        SM_PREAMBLE:
367
         begin
368
 
369
             // On reading SOP from fifo, send SFD and preamble characters
370
 
371 6 antanguay
             if (txhfifo_rstatus[`TXSTATUS_SOP]) begin
372 2 antanguay
 
373
                 next_xgxs_txd = {`SFD, {6{`PREAMBLE}}, `START};
374
                 next_xgxs_txc = 8'h01;
375
 
376 6 antanguay
                 txhfifo_ren = 1'b1;
377 2 antanguay
 
378 10 antanguay
                 next_state_enc = SM_TX;
379 2 antanguay
 
380 6 antanguay
             end
381
             else begin
382
 
383
                 next_frame_available = 1'b0;
384 10 antanguay
                 next_state_enc = SM_IDLE;
385 6 antanguay
 
386
             end
387
 
388
 
389 2 antanguay
             // Depending on deficit idle count calculations, add 4 bytes
390
             // or IFG or not. This will determine on which lane start the
391
             // next frame.
392 20 antanguay
 
393 2 antanguay
             if (ifg_4b_add) begin
394
                 next_start_on_lane0 = 1'b0;
395
             end
396
             else begin
397
                 next_start_on_lane0 = 1'b1;
398
             end
399
 
400
          end
401
 
402
        SM_TX:
403
          begin
404
 
405
              next_xgxs_txd = txhfifo_rdata_d1;
406
              next_xgxs_txc = 8'h00;
407
 
408
              txhfifo_ren = 1'b1;
409
 
410
 
411
              // Wait for EOP indication to be read from the fifo, then
412
              // transition to next state.
413
 
414 6 antanguay
              if (txhfifo_rstatus[`TXSTATUS_EOP]) begin
415 20 antanguay
 
416 2 antanguay
                  txhfifo_ren = 1'b0;
417
                  next_frame_available = !txhfifo_ralmost_empty;
418 10 antanguay
                  next_state_enc = SM_EOP;
419 6 antanguay
 
420 2 antanguay
              end
421 6 antanguay
              else if (txhfifo_rempty || txhfifo_rstatus[`TXSTATUS_SOP]) begin
422 2 antanguay
 
423
                  // Failure condition, we did not see EOP and there
424 6 antanguay
                  // is no more data in fifo or SOP, force end of packet transmit.
425 2 antanguay
 
426 10 antanguay
                  next_state_enc = SM_TERM_FAIL;
427 2 antanguay
 
428
              end
429
 
430 6 antanguay
              next_eop[0] = txhfifo_rstatus[2:0] == 3'd1;
431
              next_eop[1] = txhfifo_rstatus[2:0] == 3'd2;
432
              next_eop[2] = txhfifo_rstatus[2:0] == 3'd3;
433
              next_eop[3] = txhfifo_rstatus[2:0] == 3'd4;
434
              next_eop[4] = txhfifo_rstatus[2:0] == 3'd5;
435
              next_eop[5] = txhfifo_rstatus[2:0] == 3'd6;
436
              next_eop[6] = txhfifo_rstatus[2:0] == 3'd7;
437
              next_eop[7] = txhfifo_rstatus[2:0] == 3'd0;
438 20 antanguay
 
439 2 antanguay
          end
440
 
441
        SM_EOP:
442
          begin
443
 
444
              // Insert TERMINATE character in correct lane depending on position
445
              // of EOP read from fifo. Also insert CRC read from control fifo.
446
 
447 6 antanguay
              if (eop[0]) begin
448 20 antanguay
                  next_xgxs_txd = {{2{`IDLE}}, `TERMINATE,
449 2 antanguay
                                   crc32_tx[31:0], txhfifo_rdata_d1[7:0]};
450
                  next_xgxs_txc = 8'b11100000;
451
              end
452
 
453 6 antanguay
              if (eop[1]) begin
454 2 antanguay
                  next_xgxs_txd = {`IDLE, `TERMINATE,
455
                                   crc32_tx[31:0], txhfifo_rdata_d1[15:0]};
456
                  next_xgxs_txc = 8'b11000000;
457
              end
458
 
459 6 antanguay
              if (eop[2]) begin
460 2 antanguay
                  next_xgxs_txd = {`TERMINATE, crc32_tx[31:0], txhfifo_rdata_d1[23:0]};
461
                  next_xgxs_txc = 8'b10000000;
462
              end
463
 
464 6 antanguay
              if (eop[3]) begin
465 2 antanguay
                  next_xgxs_txd = {crc32_tx[31:0], txhfifo_rdata_d1[31:0]};
466
                  next_xgxs_txc = 8'b00000000;
467
              end
468
 
469 6 antanguay
              if (eop[4]) begin
470 2 antanguay
                  next_xgxs_txd = {crc32_tx[23:0], txhfifo_rdata_d1[39:0]};
471
                  next_xgxs_txc = 8'b00000000;
472
              end
473
 
474 6 antanguay
              if (eop[5]) begin
475 2 antanguay
                  next_xgxs_txd = {crc32_tx[15:0], txhfifo_rdata_d1[47:0]};
476
                  next_xgxs_txc = 8'b00000000;
477
              end
478
 
479 6 antanguay
              if (eop[6]) begin
480 2 antanguay
                  next_xgxs_txd = {crc32_tx[7:0], txhfifo_rdata_d1[55:0]};
481
                  next_xgxs_txc = 8'b00000000;
482
              end
483
 
484 6 antanguay
              if (eop[7]) begin
485 2 antanguay
                  next_xgxs_txd = {txhfifo_rdata_d1[63:0]};
486
                  next_xgxs_txc = 8'b00000000;
487
              end
488
 
489
              if (!frame_available) begin
490
 
491
                  // If there is not another frame ready to be transmitted, interface
492
                  // will go idle and idle deficit idle count calculation is irrelevant.
493
                  // Set deficit to 0.
494 20 antanguay
 
495 2 antanguay
                  next_ifg_deficit = 3'b0;
496
 
497
              end
498
              else begin
499
 
500
                  // Idle deficit count calculated based on number of "wasted" bytes
501
                  // between TERMINATE and alignment of next frame in LANE0.
502
 
503
                  next_ifg_deficit = ifg_deficit +
504 6 antanguay
                                     {2'b0, eop[0] | eop[4]} +
505
                                     {1'b0, eop[1] | eop[5], 1'b0} +
506
                                     {1'b0, eop[2] | eop[6],
507
                                      eop[2] | eop[6]};
508 2 antanguay
              end
509
 
510
              // IFG corrections based on deficit count and previous starting lane
511
              // Calculated based on following table:
512
              //
513
              //                 DIC=0          DIC=1          DIC=2          DIC=3
514
              //              -------------  -------------  -------------  -------------
515
              // PktLen       IFG      Next  IFG      Next  IFG      Next  IFG      Next
516
              // Modulus      Length   DIC   Length   DIC   Length   DIC   Length   DIC
517
              // -----------------------------------------------------------------------
518
              //    0           12      0      12      1      12      2      12      3
519
              //    1           11      1      11      2      11      3      15      0
520
              //    2           10      2      10      3      14      0      14      1
521
              //    3            9      3      13      0      13      1      13      2
522
              //
523
              //
524
              // In logic it translates into adding 4, 8, or 12 bytes of IFG relative
525
              // to LANE0.
526
              //   IFG and Add columns assume no deficit applied
527
              //   IFG+DIC and Add+DIC assume deficit must be applied
528
              //
529 20 antanguay
              //                        Start lane 0       Start lane 4
530 2 antanguay
              // EOP Pads IFG  IFG+DIC  Add   Add+DIC      Add    Add IFG
531
              // 0   3    11   15        8     12           12     16
532
              // 1   2    10   14        8     12           12     16
533
              // 2   1    9    13        8     12           12     16
534
              // 3   8    12   12        4     4            8      8
535
              // 4   7    11   15        4     8            8      12
536
              // 5   6    10   14        4     8            8      12
537
              // 6   5    9    13        4     8            8      12
538
              // 7   4    12   12        8     8            12     12
539
 
540
              if (!frame_available) begin
541
 
542
                  // If there is not another frame ready to be transmitted, interface
543
                  // will go idle and idle deficit idle count calculation is irrelevant.
544 20 antanguay
 
545 2 antanguay
                  next_ifg_4b_add = 1'b0;
546
                  next_ifg_8b_add = 1'b0;
547
                  next_ifg_8b2_add = 1'b0;
548
 
549
              end
550
              else if (next_ifg_deficit[2] == ifg_deficit[2]) begin
551
 
552
                  // Add 4 bytes IFG
553 20 antanguay
 
554 6 antanguay
                  next_ifg_4b_add = (eop[0] & !start_on_lane0) |
555
                                    (eop[1] & !start_on_lane0) |
556
                                    (eop[2] & !start_on_lane0) |
557
                                    (eop[3] & start_on_lane0) |
558
                                    (eop[4] & start_on_lane0) |
559
                                    (eop[5] & start_on_lane0) |
560
                                    (eop[6] & start_on_lane0) |
561
                                    (eop[7] & !start_on_lane0);
562 2 antanguay
 
563
                  // Add 8 bytes IFG
564 20 antanguay
 
565 6 antanguay
                  next_ifg_8b_add = (eop[0]) |
566
                                    (eop[1]) |
567
                                    (eop[2]) |
568
                                    (eop[3] & !start_on_lane0) |
569
                                    (eop[4] & !start_on_lane0) |
570
                                    (eop[5] & !start_on_lane0) |
571
                                    (eop[6] & !start_on_lane0) |
572
                                    (eop[7]);
573 2 antanguay
 
574
                  // Add another 8 bytes IFG
575
 
576
                  next_ifg_8b2_add = 1'b0;
577
 
578
              end
579
              else begin
580
 
581
                  // Add 4 bytes IFG
582
 
583 6 antanguay
                  next_ifg_4b_add = (eop[0] & start_on_lane0) |
584
                                    (eop[1] & start_on_lane0) |
585
                                    (eop[2] & start_on_lane0) |
586
                                    (eop[3] &  start_on_lane0) |
587
                                    (eop[4] & !start_on_lane0) |
588
                                    (eop[5] & !start_on_lane0) |
589
                                    (eop[6] & !start_on_lane0) |
590
                                    (eop[7] & !start_on_lane0);
591 2 antanguay
 
592
                  // Add 8 bytes IFG
593 20 antanguay
 
594 6 antanguay
                  next_ifg_8b_add = (eop[0]) |
595
                                    (eop[1]) |
596
                                    (eop[2]) |
597
                                    (eop[3] & !start_on_lane0) |
598
                                    (eop[4]) |
599
                                    (eop[5]) |
600
                                    (eop[6]) |
601
                                    (eop[7]);
602 2 antanguay
 
603
                  // Add another 8 bytes IFG
604
 
605 6 antanguay
                  next_ifg_8b2_add = (eop[0] & !start_on_lane0) |
606
                                     (eop[1] & !start_on_lane0) |
607
                                     (eop[2] & !start_on_lane0);
608 2 antanguay
 
609
              end
610
 
611 6 antanguay
              if (|eop[2:0]) begin
612 2 antanguay
 
613
                  if (frame_available) begin
614
 
615
                      // Next state depends on number of IFG bytes to be inserted.
616
                      // Skip idle state if needed.
617
 
618
                      if (next_ifg_8b2_add) begin
619 10 antanguay
                          next_state_enc = SM_IFG;
620 2 antanguay
                      end
621
                      else if (next_ifg_8b_add) begin
622 10 antanguay
                          next_state_enc = SM_IDLE;
623 2 antanguay
                      end
624
                      else begin
625
                          txhfifo_ren = 1'b1;
626 10 antanguay
                          next_state_enc = SM_PREAMBLE;
627 2 antanguay
                      end
628
 
629
                  end
630
                  else begin
631 10 antanguay
                      next_state_enc = SM_IFG;
632 2 antanguay
                  end
633
              end
634
 
635 6 antanguay
              if (|eop[7:3]) begin
636 10 antanguay
                  next_state_enc = SM_TERM;
637 2 antanguay
              end
638
 
639
          end
640
 
641
        SM_TERM:
642
          begin
643
 
644
              // Insert TERMINATE character in correct lane depending on position
645
              // of EOP read from fifo. Also insert CRC read from control fifo.
646
 
647 6 antanguay
              if (eop[3]) begin
648 2 antanguay
                  next_xgxs_txd = {{7{`IDLE}}, `TERMINATE};
649
                  next_xgxs_txc = 8'b11111111;
650
              end
651
 
652 6 antanguay
              if (eop[4]) begin
653 2 antanguay
                  next_xgxs_txd = {{6{`IDLE}}, `TERMINATE, crc32_tx[31:24]};
654
                  next_xgxs_txc = 8'b11111110;
655
              end
656
 
657 6 antanguay
              if (eop[5]) begin
658 2 antanguay
                  next_xgxs_txd = {{5{`IDLE}}, `TERMINATE, crc32_tx[31:16]};
659
                  next_xgxs_txc = 8'b11111100;
660
              end
661
 
662 6 antanguay
              if (eop[6]) begin
663 2 antanguay
                  next_xgxs_txd = {{4{`IDLE}}, `TERMINATE, crc32_tx[31:8]};
664
                  next_xgxs_txc = 8'b11111000;
665
              end
666
 
667 6 antanguay
              if (eop[7]) begin
668 2 antanguay
                  next_xgxs_txd = {{3{`IDLE}}, `TERMINATE, crc32_tx[31:0]};
669
                  next_xgxs_txc = 8'b11110000;
670
              end
671
 
672
              // Next state depends on number of IFG bytes to be inserted.
673
              // Skip idle state if needed.
674
 
675
              if (frame_available && !ifg_8b_add) begin
676
                  txhfifo_ren = 1'b1;
677 10 antanguay
                  next_state_enc = SM_PREAMBLE;
678 2 antanguay
              end
679
              else if (frame_available) begin
680 10 antanguay
                  next_state_enc = SM_IDLE;
681 2 antanguay
              end
682
              else begin
683 10 antanguay
                  next_state_enc = SM_IFG;
684 2 antanguay
              end
685
 
686
          end
687
 
688
        SM_TERM_FAIL:
689
          begin
690
 
691
              next_xgxs_txd = {{7{`IDLE}}, `TERMINATE};
692
              next_xgxs_txc = 8'b11111111;
693 10 antanguay
              next_state_enc = SM_IFG;
694 2 antanguay
 
695
          end
696
 
697
        SM_IFG:
698
          begin
699
 
700 10 antanguay
              next_state_enc = SM_IDLE;
701 2 antanguay
 
702
          end
703
 
704
        default:
705
          begin
706 10 antanguay
              next_state_enc = SM_IDLE;
707 2 antanguay
          end
708
 
709
    endcase
710
 
711
end
712
 
713
 
714
always @(/*AS*/crc32_d64 or txhfifo_wen or txhfifo_wstatus) begin
715
 
716 6 antanguay
    if (txhfifo_wen && txhfifo_wstatus[`TXSTATUS_SOP]) begin
717 2 antanguay
        crc_data = 32'hffffffff;
718
    end
719
    else begin
720
        crc_data = crc32_d64;
721
    end
722 20 antanguay
 
723 2 antanguay
end
724
 
725 10 antanguay
always @(/*AS*/byte_cnt or curr_state_pad or txdfifo_rdata
726 6 antanguay
         or txdfifo_rempty or txdfifo_ren_d1 or txdfifo_rstatus
727 2 antanguay
         or txhfifo_walmost_full) begin
728
 
729 10 antanguay
    next_state_pad = curr_state_pad;
730 2 antanguay
 
731
    next_txhfifo_wdata = txdfifo_rdata;
732
    next_txhfifo_wstatus = txdfifo_rstatus;
733
 
734
    txdfifo_ren = 1'b0;
735
    next_txhfifo_wen = 1'b0;
736
 
737 10 antanguay
    case (curr_state_pad)
738 2 antanguay
 
739 10 antanguay
      SM_PAD_EQ: begin
740 2 antanguay
 
741
 
742 6 antanguay
          //---
743
          // If room availabe in hoding fifo and data available in
744
          // data fifo, transfer data words. If transmit state machine
745
          // is reading from fifo we can assume room will be available.
746 2 antanguay
 
747 6 antanguay
          if (!txhfifo_walmost_full) begin
748
 
749
              txdfifo_ren = !txdfifo_rempty;
750
 
751 2 antanguay
          end
752
 
753
 
754 6 antanguay
          //---
755
          // This logic dependent on read during previous cycle.
756 2 antanguay
 
757 6 antanguay
          if (txdfifo_ren_d1) begin
758
 
759 2 antanguay
              next_txhfifo_wen = 1'b1;
760
 
761 6 antanguay
              // On EOP, decide if padding is required for this packet.
762 2 antanguay
 
763 6 antanguay
              if (txdfifo_rstatus[`TXSTATUS_EOP]) begin
764 2 antanguay
 
765 23 antanguay
                  if (byte_cnt < 14'd60) begin
766 2 antanguay
 
767
                      next_txhfifo_wstatus = `TXSTATUS_NONE;
768 6 antanguay
                      txdfifo_ren = 1'b0;
769 10 antanguay
                      next_state_pad = SM_PAD_PAD;
770 2 antanguay
 
771
                  end
772 23 antanguay
                  else if (byte_cnt == 14'd60 &&
773 6 antanguay
                           (txdfifo_rstatus[2:0] == 3'd1 ||
774
                            txdfifo_rstatus[2:0] == 3'd2 ||
775
                            txdfifo_rstatus[2:0] == 3'd3)) begin
776 2 antanguay
 
777
                      // Pad up to LANE3, keep the other 4 bytes for crc that will
778
                      // be inserted by dequeue engine.
779 20 antanguay
 
780 6 antanguay
                      next_txhfifo_wstatus[2:0] = 3'd4;
781 2 antanguay
 
782
                      // Pad end bytes with zeros.
783
 
784 6 antanguay
                      if (txdfifo_rstatus[2:0] == 3'd1)
785 2 antanguay
                        next_txhfifo_wdata[31:8] = 24'b0;
786 6 antanguay
                      if (txdfifo_rstatus[2:0] == 3'd2)
787 2 antanguay
                        next_txhfifo_wdata[31:16] = 16'b0;
788 6 antanguay
                      if (txdfifo_rstatus[2:0] == 3'd3)
789 2 antanguay
                        next_txhfifo_wdata[31:24] = 8'b0;
790
 
791 6 antanguay
                      txdfifo_ren = 1'b0;
792 2 antanguay
 
793
                  end
794
                  else begin
795
 
796 6 antanguay
                      txdfifo_ren = 1'b0;
797 20 antanguay
 
798 2 antanguay
                  end
799
 
800
              end
801 20 antanguay
 
802 2 antanguay
          end
803
 
804
      end
805
 
806 10 antanguay
      SM_PAD_PAD: begin
807 2 antanguay
 
808 6 antanguay
          //---
809
          // Pad packet to 64 bytes by writting zeros to holding fifo.
810 2 antanguay
 
811 6 antanguay
          if (!txhfifo_walmost_full) begin
812
 
813 2 antanguay
              next_txhfifo_wdata = 64'b0;
814
              next_txhfifo_wstatus = `TXSTATUS_NONE;
815
              next_txhfifo_wen = 1'b1;
816 20 antanguay
 
817 23 antanguay
              if (byte_cnt == 14'd60) begin
818 2 antanguay
 
819
 
820
                  // Pad up to LANE3, keep the other 4 bytes for crc that will
821
                  // be inserted by dequeue engine.
822
 
823 6 antanguay
                  next_txhfifo_wstatus[`TXSTATUS_EOP] = 1'b1;
824
                  next_txhfifo_wstatus[2:0] = 3'd4;
825 2 antanguay
 
826 10 antanguay
                  next_state_pad = SM_PAD_EQ;
827 2 antanguay
 
828
              end
829
 
830
          end
831
 
832
      end
833
 
834
      default:
835
        begin
836 10 antanguay
            next_state_pad = SM_PAD_EQ;
837 2 antanguay
        end
838
 
839
    endcase
840
 
841
end
842
 
843
 
844
always @(posedge clk_xgmii_tx or negedge reset_xgmii_tx_n) begin
845
 
846
    if (reset_xgmii_tx_n == 1'b0) begin
847
 
848 10 antanguay
        curr_state_pad <= SM_PAD_EQ;
849 2 antanguay
 
850 6 antanguay
        txdfifo_ren_d1 <= 1'b0;
851
 
852 2 antanguay
        txhfifo_wdata <= 64'b0;
853
        txhfifo_wstatus <= 8'b0;
854 20 antanguay
        txhfifo_wen <= 1'b0;
855 2 antanguay
 
856
        byte_cnt <= 14'b0;
857
 
858
        shift_crc_data <= 64'b0;
859 6 antanguay
        shift_crc_eop <= 4'b0;
860
        shift_crc_cnt <= 4'b0;
861 2 antanguay
 
862 20 antanguay
        crc32_d64 <= 32'b0;
863
        crc32_d8 <= 32'b0;
864
        crc32_tx <= 32'b0;
865
 
866 23 antanguay
        frame_end <= 1'b0;
867
 
868 2 antanguay
    end
869
    else begin
870
 
871 10 antanguay
        curr_state_pad <= next_state_pad;
872 2 antanguay
 
873 6 antanguay
        txdfifo_ren_d1 <= txdfifo_ren;
874
 
875 2 antanguay
        txhfifo_wdata <= next_txhfifo_wdata;
876
        txhfifo_wstatus <= next_txhfifo_wstatus;
877
        txhfifo_wen <= next_txhfifo_wen;
878
 
879 23 antanguay
        frame_end <= 1'b0;
880 2 antanguay
 
881 6 antanguay
        //---
882
        // Reset byte count on SOP
883 20 antanguay
 
884 6 antanguay
        if (next_txhfifo_wen) begin
885 2 antanguay
 
886 6 antanguay
            if (next_txhfifo_wstatus[`TXSTATUS_SOP]) begin
887
 
888 23 antanguay
                // Init byte count, 8-bytes + 4-bytes for CRC at the end of frame
889 2 antanguay
 
890 23 antanguay
                byte_cnt <= 14'd12;
891
 
892 2 antanguay
            end
893
            else begin
894
 
895 23 antanguay
                if (next_txhfifo_wstatus[`TXSTATUS_EOP] && next_txhfifo_wstatus[2:0] != 3'b0) begin
896 2 antanguay
 
897 23 antanguay
                    byte_cnt <= byte_cnt + {11'b0, next_txhfifo_wstatus[2:0]};
898
 
899
                end
900
                else begin
901
 
902
                    byte_cnt <= byte_cnt + 14'd8;
903
 
904
                end
905
 
906 2 antanguay
            end
907
 
908 23 antanguay
            frame_end <= next_txhfifo_wstatus[`TXSTATUS_EOP];
909
 
910 2 antanguay
        end
911
 
912 6 antanguay
 
913
        //---
914
        // Calculate CRC as data is written to holding fifo. The holding fifo creates
915
        // a delay that allow the CRC calculation to complete before the end of the frame
916
        // is ready to be transmited.
917
 
918 2 antanguay
        if (txhfifo_wen) begin
919
 
920
            crc32_d64 <= nextCRC32_D64(reverse_64b(txhfifo_wdata), crc_data);
921
 
922
        end
923
 
924 6 antanguay
        if (txhfifo_wen && txhfifo_wstatus[`TXSTATUS_EOP]) begin
925 2 antanguay
 
926
            // Last bytes calculated 8-bit at a time instead of 64-bit. Start
927
            // this process at the end of the frame.
928 20 antanguay
 
929 2 antanguay
            crc32_d8 <= crc32_d64;
930
 
931
            shift_crc_data <= txhfifo_wdata;
932 6 antanguay
            shift_crc_cnt <= 4'd9;
933 2 antanguay
 
934 6 antanguay
            if (txhfifo_wstatus[2:0] == 3'b0) begin
935
              shift_crc_eop <= 4'd8;
936
            end
937
            else begin
938
                shift_crc_eop <= {1'b0, txhfifo_wstatus[2:0]};
939
            end
940
 
941 2 antanguay
        end
942 6 antanguay
        else if (shift_crc_eop != 4'b0) begin
943 2 antanguay
 
944
            // Complete crc calculation 8-bit at a time until finished. This can
945
            // be 1 to 8 bytes long.
946
 
947
            crc32_d8 <= nextCRC32_D8(reverse_8b(shift_crc_data[7:0]), crc32_d8);
948
 
949
            shift_crc_data <= {8'b0, shift_crc_data[63:8]};
950 6 antanguay
            shift_crc_eop <= shift_crc_eop - 4'd1;
951 20 antanguay
 
952 2 antanguay
        end
953
 
954 6 antanguay
 
955
        //---
956
        // Update CRC register at the end of calculation. Always update after 8
957
        // cycles for deterministic results, even if a single byte was present in
958
        // last data word.
959 20 antanguay
 
960 6 antanguay
        if (shift_crc_cnt == 4'b1) begin
961
 
962 2 antanguay
            crc32_tx <= ~reverse_32b(crc32_d8);
963 6 antanguay
 
964 2 antanguay
        end
965
        else begin
966 6 antanguay
 
967
            shift_crc_cnt <= shift_crc_cnt - 4'd1;
968
 
969 2 antanguay
        end
970
 
971
    end
972
 
973
end
974
 
975
endmodule

powered by: WebSVN 2.1.0

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