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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [orpsocv2/] [rtl/] [verilog/] [smii/] [smii_if.v] - Blame information for rev 408

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 408 julius
//////////////////////////////////////////////////////////////////////
2
////                                                              ////
3
////  SMII                                                        ////
4
////                                                              ////
5
////  Description                                                 ////
6
////  Low pin count serial MII ethernet interface                 ////
7
////                                                              ////
8
////  To Do:                                                      ////
9
////   -                                                          ////
10
////                                                              ////
11
////  Author(s):                                                  ////
12
////      - Michael Unneback, unneback@opencores.org              ////
13
////        ORSoC AB          michael.unneback@orsoc.se           ////
14
////      - Julius Baxter,    julius@orsoc.se                     ////
15
////        ORSoC AB                                              ////
16
////                                                              ////
17
//////////////////////////////////////////////////////////////////////
18
////                                                              ////
19
//// Copyright (C) 2009, 2010 Authors and OPENCORES.ORG           ////
20
////                                                              ////
21
//// This source file may be used and distributed without         ////
22
//// restriction provided that this copyright statement is not    ////
23
//// removed from the file and that any derivative work contains  ////
24
//// the original copyright notice and the associated disclaimer. ////
25
////                                                              ////
26
//// This source file is free software; you can redistribute it   ////
27
//// and/or modify it under the terms of the GNU Lesser General   ////
28
//// Public License as published by the Free Software Foundation; ////
29
//// either version 2.1 of the License, or (at your option) any   ////
30
//// later version.                                               ////
31
////                                                              ////
32
//// This source is distributed in the hope that it will be       ////
33
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
34
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
35
//// PURPOSE.  See the GNU Lesser General Public License for more ////
36
//// details.                                                     ////
37
////                                                              ////
38
//// You should have received a copy of the GNU Lesser General    ////
39
//// Public License along with this source; if not, download it   ////
40
//// from http://www.opencores.org/lgpl.shtml                     ////
41
////                                                              ////
42
//////////////////////////////////////////////////////////////////////
43
`include "synthesis-defines.v"
44
`include "orpsoc-defines.v" // To determine synthesis technology.
45
module smii_if
46
  (
47
   // SMII
48
    output     tx,
49
    input      rx,
50
   // MII
51
   // TX
52
    input [3:0] mtxd,
53
    input       mtxen,
54
    input       mtxerr,
55
    output      mtx_clk,
56
   // RX
57
    output [3:0] mrxd,
58
    output       mrxdv,
59
    output       mrxerr,
60
    output       mrx_clk,
61
    output       mcoll,
62
    output reg   mcrs,
63
    output reg   speed,
64
    output reg   duplex,
65
    output reg   link,
66
   // internal
67
    input [10:1] tx_smii_state,
68
    input [10:1] next_tx_smii_state,
69
    input [10:1] rx_smii_state,
70
   // clock and reset
71
    input        eth_clk,
72
    input        eth_rst
73
   );
74
 
75
   reg [7:0]      tx_data_reg;
76
   reg           tx_data_reg_valid;
77
   reg           a0;
78
   reg           state_data;
79
 
80
   reg [3:0]      rx_tmp;
81
 
82
   reg [3:0]      rxd_nib;
83
   reg           rxdv, rxerr;
84
 
85
   reg           jabber;
86
 
87
   reg [10:1]    tx_cnt;
88
   reg [10:1]    rx_cnt;
89
 
90
 
91
   /////////////////////////////////////////////////
92
   // Transmit
93
 
94
   // Tx segment counter when !speed
95
   always @ (posedge eth_clk or posedge eth_rst)
96
     if (eth_rst)
97
       tx_cnt <= 10'b00_0000_0001;
98
     else if (tx_smii_state[10])
99
       tx_cnt <= {tx_cnt[9:1],tx_cnt[10]};
100
 
101
   // MII signals registered in eth_clk domain
102
   reg           txen_r, txerr_r;
103
   // TX clock generation to the MAC
104
   reg           mtx_clk_gen, mtx_clk_gen_reg,
105
                 mtx_clk_gen_reg2, mtx_clk_gen_reg3,
106
                 mtx_clk_gen_reg4, mtx_clk_gen_reg5,
107
                 mtx_clk_gen_reg6, mtx_clk_gen_reg7,
108
                 tx_first_clk_gen,
109
                 tx_first_clk_reg, tx_first_clk_reg2,
110
                 tx_first_clk_reg3, tx_first_clk_reg4,
111
                 tx_first_clk_reg5, tx_first_clk_reg6,
112
                 tx_first_clk_reg7;
113
 
114
   // Generate clocks when state is 2, and 7 when transmitting
115
   // We then sample the MII txen signal, to see if we have a valid data frame
116
   // coming up. We can do this 2 or 3 clocks after the MII tx clk. If we do it
117
   // 2 then we allow 2 cycles for our mtxen_r signal to propegate, doubling the
118
   // period contstraint for the path from mtxen_r to the stuff it controls in
119
   // eth_clk domain. If we allow 3 from the eth MAC, then all stuff on the 
120
   // eth_clk side of mtxen_r must meet the 125MHz timing.
121
   //
122
   // Once the data is sampled at the right times (plenty after they come from
123
   // the eth MAC, should be no issues there), then it all propegates through
124
   // relatively various levels of registering, configured so that the signals
125
   // appear in the tx_bits[] vector at the right time to be registered once
126
   // more before before having its bits AND-OR selected based on the smii state
127
   // The final SMII TX bit is generated from a sync counter that is one ahead
128
   // of the one we output.
129
 
130
   wire          tx_first_clk, tx_second_clk;
131
   assign tx_first_clk = (tx_smii_state[2] &
132
                          ( speed | ( !speed & tx_cnt[10]) ) );
133
   assign tx_second_clk = (tx_smii_state[7] &
134
                           txen_r & ( speed | ( !speed & tx_cnt[1]) ) );
135
 
136
   always @(posedge eth_clk)
137
     if (eth_rst)
138
       mtx_clk_gen <= 1'b0;
139
     else if (mtx_clk_gen)
140
       mtx_clk_gen <= 1'b0;
141
   // Clock high
142
     else if (tx_first_clk | tx_second_clk)
143
       mtx_clk_gen <= 1'b1;
144
 
145
   always @(posedge eth_clk)
146
     mtx_clk_gen_reg <= mtx_clk_gen;
147
 
148
   always @(posedge eth_clk)
149
     mtx_clk_gen_reg2 <= mtx_clk_gen_reg;
150
 
151
   always @(posedge eth_clk)
152
     mtx_clk_gen_reg3 <= mtx_clk_gen_reg2;
153
 
154
   always @(posedge eth_clk)
155
     mtx_clk_gen_reg4 <= mtx_clk_gen_reg3;
156
 
157
   always @(posedge eth_clk)
158
     mtx_clk_gen_reg5 <= mtx_clk_gen_reg4;
159
 
160
   always @(posedge eth_clk)
161
     mtx_clk_gen_reg6 <= mtx_clk_gen_reg5;
162
 
163
   always @(posedge eth_clk)
164
     mtx_clk_gen_reg7 <= mtx_clk_gen_reg6;
165
 
166
   always @(posedge eth_clk)
167
     tx_first_clk_gen <= tx_first_clk;
168
 
169
   always @(posedge eth_clk)
170
     tx_first_clk_reg <= tx_first_clk_gen;
171
 
172
   always @(posedge eth_clk)
173
     tx_first_clk_reg2 <= tx_first_clk_reg;
174
 
175
   always @(posedge eth_clk)
176
     tx_first_clk_reg3 <= tx_first_clk_reg2;
177
 
178
   always @(posedge eth_clk)
179
     tx_first_clk_reg4 <= tx_first_clk_reg3;
180
 
181
   always @(posedge eth_clk)
182
     tx_first_clk_reg5 <= tx_first_clk_reg4;
183
 
184
   always @(posedge eth_clk)
185
     tx_first_clk_reg6 <= tx_first_clk_reg5;
186
 
187
   always @(posedge eth_clk)
188
     tx_first_clk_reg7 <= tx_first_clk_reg6;
189
 
190
 
191
   // Register MII TX enable
192
   always @(posedge eth_clk)
193
     if (eth_rst)
194
       txen_r <= 1'b0;
195
     else if (tx_first_clk_reg3)
196
       txen_r <= mtxen;
197
 
198
   // Register MII TX error
199
   always @(posedge eth_clk)
200
     if (eth_rst)
201
       txerr_r <= 1'b0;
202
     else if (tx_first_clk_reg3)
203
       txerr_r <= mtxerr;
204
 
205
   // Register indicating if we're going to sample the second nibble of data
206
   reg  tx_nib_second;
207
   always @(posedge eth_clk)
208
     if (eth_rst)
209
       tx_nib_second <= 0;
210
     else if (mtx_clk_gen_reg4)
211
       begin
212
          if (!txen_r)
213
            tx_nib_second <= 0;
214
          else
215
            tx_nib_second <= ~tx_nib_second;
216
       end
217
   // Byte register, appropriately storing nibbles as we recieve them from MAC
218
   reg [7:0] mtxd_r;
219
   always @(posedge eth_clk)
220
     if (txen_r & mtx_clk_gen_reg4 & !tx_nib_second)
221
       mtxd_r[3:0] <= mtxd;
222
     else if (txen_r & mtx_clk_gen_reg4 & tx_nib_second)
223
       mtxd_r[7:4] <= mtxd;
224
 
225
   // Sample our registered version of txen_r when we generate our
226
   // "first" of the 2 TX clocks per frame.
227
   reg       tx_state_or_data; // 0 = state, 1 = data
228
   always @ (posedge eth_clk)
229
     if (eth_rst)
230
       tx_state_or_data <= 0;
231
     else if (tx_first_clk_reg4)
232
       tx_state_or_data <= txen_r;
233
 
234
   reg [10:1] tx_bits, tx_bits_reg, tx_bits_reg2;
235
   always @(posedge eth_clk)
236
     begin
237
        tx_bits_reg <= tx_bits;
238
        tx_bits[1] <= txerr_r;
239
        tx_bits[2] <= tx_state_or_data;
240
        tx_bits[3] <= (tx_state_or_data) ? mtxd_r[0] : txerr_r;
241
        tx_bits[4] <= (tx_state_or_data) ? mtxd_r[1] : speed;
242
        tx_bits[5] <= (tx_state_or_data) ? mtxd_r[2] : duplex;
243
        tx_bits[6] <= (tx_state_or_data) ? mtxd_r[3] : link;
244
        tx_bits[7] <= (tx_state_or_data) ? mtxd_r[4] : 0;
245
        tx_bits[8] <= (tx_state_or_data) ? mtxd_r[5] : 1;
246
        tx_bits[9] <= (tx_state_or_data) ? mtxd_r[6] : 1;
247
        tx_bits[10] <= (tx_state_or_data) ? mtxd_r[7] : 1;
248
     end
249
 
250
   // Generate tx output bit one clock infront, because we register
251
   // in the IOB too.
252
   reg tx_bit;
253
   always @(posedge eth_clk)
254
     tx_bit <= |(tx_bits_reg & next_tx_smii_state);
255
 
256
     assign tx = tx_bit;
257
 
258
`ifdef ACTEL
259
 
260
    wire GND;
261
 
262
    GND GND_1_net(.Y(GND));
263
    CLKDLY Inst1(.CLK(mtx_clk_gen), .GL(mtx_clk), .DLYGL0(GND), .DLYGL1(GND),
264
        .DLYGL2(GND), .DLYGL3(GND), .DLYGL4(GND)) /* synthesis black_box */;
265
/*
266
   gbuf mtx_clk_bufg
267
     (
268
      .CLK(mtx_clk_gen),
269
      .GL(mtx_clk)
270
      );
271
*/
272
`else
273
   assign mtx_clk = mtx_clk_gen;
274
`endif
275
 
276
   /////////////////////////////////////////////////
277
   // Receive
278
 
279
`ifndef SYNTHESIS
280
   reg [79:0] rx_statename;
281
   always @* begin
282
      case (1)
283
        rx_smii_state[1]   :
284
          rx_statename = "CRS";
285
        rx_smii_state[2] :
286
          rx_statename = "RX_DV";
287
        rx_smii_state[3]:
288
          rx_statename = "RXD0/RXERR";
289
        rx_smii_state[4]:
290
          rx_statename = "RXD1/Fast";
291
        rx_smii_state[5]:
292
          rx_statename = "RXD2/Dupl";
293
        rx_smii_state[6]:
294
          rx_statename = "RXD3/Link";
295
        rx_smii_state[7]:
296
          rx_statename = "RXD4/Jabb";
297
        rx_smii_state[8]:
298
          rx_statename = "RXD5/UNV";
299
        rx_smii_state[9]:
300
          rx_statename = "RXD6/FCD";
301
        rx_smii_state[10] :
302
          rx_statename = "RXD7/AS1";
303
        default:
304
          rx_statename = "XXXXXXX";
305
      endcase // case (1)
306
   end // always @ *
307
`endif
308
 
309
   reg        rxdv_thisframe;
310
   wire       rxdv_lastframe;
311
   reg       rxdv_lastframe_r;
312
   reg [9:0]  rxd_thisframe;
313
   reg [9:0]  rxd_lastframe;
314
 
315
   // Logic to detect change in ethernet speed
316
   reg        speed_r;
317
   always @(posedge eth_clk)
318
     speed_r <= speed;
319
 
320
   wire       speed_edge;
321
   assign speed_edge = speed_r != speed;
322
 
323
 
324
   always @ (posedge eth_clk or posedge eth_rst)
325
     if (eth_rst)
326
       rx_cnt <= 10'd1;
327
   // Data coming in, or we've changed from fast to slow ethernet
328
     else if ((!rxdv_lastframe & rx_smii_state[8] & rxdv_thisframe) | speed_edge)
329
       rx_cnt[10] <= ~speed; // Will be high if not in 100MBit mode
330
     else if (rx_smii_state[10]) // wrap
331
       if (rx_cnt[10])
332
         rx_cnt[10:1] <= {9'b000000000, ~speed}; // Clears bit when fasteth
333
       else
334
         rx_cnt <= {rx_cnt[9:1],1'b0};
335
 
336
   always @(posedge eth_clk)
337
     if (rx_smii_state[2])
338
       rxdv_thisframe <= rx;
339
 
340
   always @(posedge eth_clk)
341
     if (rx_smii_state[1])
342
       mcrs <= rx;
343
 
344
   always @(posedge eth_clk) // shift register sampling incoming data
345
     rxd_thisframe <= {rx, rxd_thisframe[9:1]};
346
 
347
   always @(posedge eth_clk)
348
     if (rx_smii_state[1])
349
          rxd_lastframe <= rxd_thisframe;
350
 
351
   assign rxdv_lastframe = rxd_lastframe[1];
352
 
353
   // Must remember with rxd_thisframe, data has been registered, so state 
354
   // counter is 1 infront of what we have in it
355
 
356
   always @(posedge eth_clk)
357
     if (eth_rst)
358
       begin
359
          {rxdv, rxerr, speed, duplex, link, jabber} <= 6'b001110;
360
       end
361
     else
362
       begin
363
          if (rx_smii_state[10]) // Look at sampled shift reg
364
            begin
365
               if ((!rxdv_lastframe)) // !RX DV from last frame
366
                 begin
367
                    rxerr <= rxd_lastframe[2];
368
                    speed <= rxd_lastframe[3];
369
                    duplex <= rxd_lastframe[4];
370
                    link <= rxd_lastframe[5];
371
                    jabber <= rxd_lastframe[6];
372
                    // rxd_thisframe[7] should be 1 if
373
                 end
374
            end
375
       end // else: !if(eth_rst)
376
 
377
   // Latch the nibbles at the appropriate moments
378
   always @(posedge eth_clk)
379
     if (rx_smii_state[2])
380
       rxd_nib <= rxd_lastframe[5:2];
381
     else if (rx_smii_state[8])
382
       rxd_nib <= rxd_lastframe[9:6];
383
 
384
   // Nibble write enables 
385
   reg rx_we_nib0, rx_we_nib1;
386
 
387
   always @(posedge eth_clk)
388
     if (eth_rst)
389
       rx_we_nib0 <= 0;
390
     else if (rx_smii_state[3] & rxdv_lastframe &
391
              !(!rxdv_thisframe & rx))
392
       // Check in state 3, if DV was high for buffered frame (lastframe), and
393
       // if the incoming frame doesn't negate it with error being signaled
394
       rx_we_nib0 <= 1;
395
     else
396
       rx_we_nib0 <= 0;
397
 
398
   always @(posedge eth_clk)
399
     if (eth_rst)
400
       rx_we_nib1 <= 0;
401
     else if (rx_smii_state[8] & !(!rxdv_thisframe & (rxd_thisframe[5] | !rx))
402
              & rxdv_lastframe)
403
       // Check in state 8, if DV was high last frame, and this frame isn't a
404
       // status frame indicating either error or not upper nibble valid, in
405
       // which case we do not generate a WE to the FIFO
406
       rx_we_nib1 <= 1;
407
     else
408
       rx_we_nib1 <= 0;
409
 
410
   // Pipelining of clocks to MAC, this should run at 125MHz
411
   reg nib_rx_clock;
412
   always @(posedge eth_clk)
413
     nib_rx_clock <= ((rx_smii_state[4] & rx_we_nib0)|(rx_smii_state[9] & rx_we_nib1));
414
 
415
   // Enable for mrxclk inbetween frame receive
416
   reg inbetween_rx_clock;
417
   always @(posedge eth_clk)
418
     inbetween_rx_clock <= rx_smii_state[4];//(!rxdv_thisframe & !rxdv_lastframe);
419
 
420
   // Enable to clock the segment in the 10MBit mode, change rx_cnt[x] to alter 
421
   // which of the 10 the segments we use
422
   reg thissegment_rx_clock;
423
   always @(posedge eth_clk)
424
     thissegment_rx_clock <= speed | (rx_cnt[6] & !speed);
425
 
426
   reg mrx_clk_gen;
427
   // Receive MII clock generation (very similar to Receive FIFO WE generation)
428
   // This ends up being only about 20MHz when clocking in data
429
   always @(posedge eth_clk)
430
     if (eth_rst)
431
       mrx_clk_gen <= 0;
432
     else if (mrx_clk_gen)
433
       mrx_clk_gen <= 0;
434
     else if ((nib_rx_clock | inbetween_rx_clock) & thissegment_rx_clock )
435
       mrx_clk_gen <= 1;
436
 
437
 `ifdef ACTEL
438
 
439
 
440
    CLKDLY Inst2(.CLK(mrx_clk_gen), .GL(mrx_clk), .DLYGL0(GND), .DLYGL1(GND),
441
        .DLYGL2(GND), .DLYGL3(GND), .DLYGL4(GND)) /* synthesis black_box */;
442
 
443
/*
444
   gbuf mrx_clk_bufg
445
     (
446
      .CLK(mrx_clk_gen),
447
      .GL(mrx_clk)
448
      );
449
*/
450
 `else
451
   assign mrx_clk = mrx_clk_gen;
452
 `endif
453
 
454
   assign mrxd = rxd_nib;
455
   assign mrxdv = rxdv_lastframe;
456
   assign mrxerr = rxerr;
457
 
458
   assign mcoll =  mcrs & mtxen & !duplex;
459
 
460
endmodule // smii_if

powered by: WebSVN 2.1.0

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