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 21

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

powered by: WebSVN 2.1.0

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