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 10

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

powered by: WebSVN 2.1.0

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