OpenCores
URL https://opencores.org/ocsvn/1000base-x/1000base-x/trunk

Subversion Repositories 1000base-x

[/] [1000base-x/] [trunk/] [rtl/] [verilog/] [ge_1000baseX_mdio.v] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 dwp
//////////////////////////////////////////////////////////////////////
2
////                                                              ////
3
////  File name "ge_1000baseX_mdio.v"                             ////
4
////                                                              ////
5
////  This file is part of the :                                  ////
6
////                                                              ////
7
//// "1000BASE-X IEEE 802.3-2008 Clause 36 - PCS project"         ////
8
////                                                              ////
9
////  http://opencores.org/project,1000base-x                     ////
10
////                                                              ////
11
////  Author(s):                                                  ////
12
////      - D.W.Pegler Cambridge Broadband Networks Ltd           ////
13
////                                                              ////
14
////      { peglerd@gmail.com, dwp@cambridgebroadand.com }        ////
15
////                                                              ////
16
//////////////////////////////////////////////////////////////////////
17
////                                                              ////
18
//// Copyright (C) 2009 AUTHORS. All rights reserved.             ////
19
////                                                              ////
20
//// This source file may be used and distributed without         ////
21
//// restriction provided that this copyright statement is not    ////
22
//// removed from the file and that any derivative work contains  ////
23
//// the original copyright notice and the associated disclaimer. ////
24
////                                                              ////
25
//// This source file is free software; you can redistribute it   ////
26
//// and/or modify it under the terms of the GNU Lesser General   ////
27
//// Public License as published by the Free Software Foundation; ////
28
//// either version 2.1 of the License, or (at your option) any   ////
29
//// later version.                                               ////
30
////                                                              ////
31
//// This source is distributed in the hope that it will be       ////
32
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
33
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
34
//// PURPOSE.  See the GNU Lesser General Public License for more ////
35
//// details.                                                     ////
36
////                                                              ////
37
//// You should have received a copy of the GNU Lesser General    ////
38
//// Public License along with this source; if not, download it   ////
39
//// from http://www.opencores.org/lgpl.shtml                     ////
40
////                                                              ////
41
//////////////////////////////////////////////////////////////////////
42
////                                                              ////
43
//// This module is based on the coding method described in       ////
44
//// IEEE Std 802.3-2008 Clause 22 "Reconcilliation Sublayer (RS) ////
45
//// Media Independent Interface (MII)"; see                      ////
46
////                                                              ////
47
//// http://standards.ieee.org/about/get/802/802.3.html           ////
48
//// and                                                          ////
49
//// doc/802.3-2008_section2.pdf, Clause/Section 36.              ////
50
////                                                              ////
51
//////////////////////////////////////////////////////////////////////
52
 
53
`include "ge_1000baseX_constants.v"
54
 
55
`include "timescale.v"
56
 
57
module ge_1000baseX_mdio #(
58
  parameter PHY_ADDR = 5'b00000
59
) (
60
 
61
   //  reset 
62
   input              reset,
63
   //  clock 
64
   input              mdc,
65
 
66
   input              mdio,
67
   output             mdio_out,
68
   output             mdio_oe,
69
 
70
   output     [4:0]   data_addr,
71
   input     [15:0]   data_rd,
72
   output    [15:0]   data_wr,
73
   output reg         strobe_wr
74
   );
75
 
76
 
77
`ifdef MODEL_TECH
78
  enum logic [3:0] {
79
`else
80
  localparam
81
`endif
82
                    S_PREAMBLE  = 0,
83
                    S_ST        = 1,
84
                    S_OP_CODE   = 2,
85
                    S_PHY_ADDR  = 3,
86
                    S_REG_ADDR  = 4,
87
                    S_TA        = 5,
88
                    S_WR_DATA   = 6,
89
                    S_RD_DATA   = 7,
90
                    S_WR_COMMIT = 8
91
`ifdef MODEL_TECH
92
  } present, next;
93
`else
94
  ; reg [3:0] present, next;
95
`endif
96
 
97
   //////////////////////////////////////////////////////////////////////////////
98
   //
99
   //////////////////////////////////////////////////////////////////////////////   
100
 
101
   reg [5:0] preamble_cnt;
102
 
103
   assign preamble_match = (preamble_cnt == 31);
104
 
105
   always @(posedge mdc or posedge reset)
106
     if (reset)
107
       preamble_cnt = 0;
108
     else
109
       preamble_cnt <= (mdio & ~preamble_match) ? preamble_cnt + 1 :
110
                       (mdio & preamble_match)  ? preamble_cnt : 0;
111
 
112
   //////////////////////////////////////////////////////////////////////////////
113
   //
114
   //////////////////////////////////////////////////////////////////////////////
115
 
116
   reg pos_cnt_inc; reg [4:0] pos_cnt;
117
 
118
   always @(posedge mdc or posedge reset)
119
     if (reset)
120
       pos_cnt <= 0;
121
     else
122
        pos_cnt <= (pos_cnt_inc) ? pos_cnt + 1 : 0;
123
 
124
   assign op_code_done   = (pos_cnt == 1);
125
   assign phy_addr_done  = (pos_cnt == 6);
126
   assign reg_addr_done  = (pos_cnt == 11);
127
   assign ta0_done       = (pos_cnt == 12);
128
   assign ta1_done       = (pos_cnt == 13);
129
   assign data_done      = (pos_cnt == 29);
130
 
131
   //////////////////////////////////////////////////////////////////////////////
132
   //
133
   //////////////////////////////////////////////////////////////////////////////
134
 
135
   reg st; reg st_latch;
136
 
137
   always @(posedge mdc or posedge reset)
138
     if (reset)
139
       st <= 0;
140
     else
141
       if (st_latch) st <= mdio;
142
 
143
   assign st_match = ~st & mdio;
144
 
145
   //////////////////////////////////////////////////////////////////////////////
146
   //
147
   //////////////////////////////////////////////////////////////////////////////  
148
 
149
   reg [1:0] op_code; reg op_code_shift;
150
 
151
   always @(posedge mdc or posedge reset)
152
     if (reset)
153
       op_code <= 0;
154
     else
155
       if (op_code_shift) op_code <= { op_code[0], mdio};
156
 
157
   assign op_is_rd = (op_code == 2'b10); assign op_is_wr = (op_code == 2'b01);
158
 
159
   assign op_is_invalid = ~op_is_rd & ~op_is_wr;
160
 
161
   //////////////////////////////////////////////////////////////////////////////
162
   //
163
   //////////////////////////////////////////////////////////////////////////////  
164
 
165
   reg [4:0] phy_addr; reg phy_addr_shift;
166
 
167
   always @(posedge mdc or posedge reset)
168
     if (reset)
169
       phy_addr <= 0;
170
     else
171
       if (phy_addr_shift) phy_addr <= { phy_addr[3:0], mdio};
172
 
173
   assign phy_addr_match = (phy_addr == PHY_ADDR);
174
 
175
   //////////////////////////////////////////////////////////////////////////////
176
   //
177
   //////////////////////////////////////////////////////////////////////////////  
178
 
179
   reg [4:0] reg_addr; reg reg_addr_shift;
180
 
181
   always @(posedge mdc or posedge reset)
182
     if (reset)
183
       reg_addr <= 0;
184
     else
185
       if (reg_addr_shift) reg_addr <= { reg_addr[3:0], mdio};
186
 
187
   assign data_addr = reg_addr;
188
 
189
   //////////////////////////////////////////////////////////////////////////////
190
   //
191
   ////////////////////////////////////////////////////////////////////////////// 
192
 
193
   reg [15:0] data_in; reg data_in_shift;
194
 
195
   always @(posedge mdc or posedge reset)
196
     if (reset)
197
       data_in <= 0;
198
     else
199
       if (data_in_shift) data_in <= { data_in[14:0], mdio};
200
 
201
   assign data_wr = data_in;
202
 
203
   //////////////////////////////////////////////////////////////////////////////
204
   //
205
   //////////////////////////////////////////////////////////////////////////////
206
 
207
   reg [15:0] data_out; reg data_out_load, data_out_shift;
208
 
209
   always @(posedge mdc or posedge reset)
210
     if (reset)
211
       data_out <= 0;
212
     else
213
       if      (data_out_load)  data_out <= data_rd;
214
       else if (data_out_shift) data_out <= { data_out[14:0], 1'b0 };
215
 
216
   //////////////////////////////////////////////////////////////////////////////
217
   //
218
   //////////////////////////////////////////////////////////////////////////////
219
 
220
   assign mdio_oe = (ta1_done & op_is_rd) | data_out_shift;
221
 
222
   assign mdio_out = (ta1_done & op_is_rd) ? 1'b1 : data_out[15];
223
 
224
   //////////////////////////////////////////////////////////////////////////////
225
   // mdio/mdc state machine registered part.
226
   //////////////////////////////////////////////////////////////////////////////
227
 
228
   always @(posedge mdc or posedge reset)
229
 
230
     present <= (reset) ? S_PREAMBLE : next;
231
 
232
   //////////////////////////////////////////////////////////////////////////////
233
   // IEEE Std 802.3-2008 Clause 22 "Reconcilliation Sublayer (RS) and
234
   // Media Independent Interface (MII)IEEE 802.3-2005 Clause 22 
235
   //////////////////////////////////////////////////////////////////////////////
236
 
237
   always @*
238
     begin
239
        next = present;
240
 
241
        pos_cnt_inc = 0;  st_latch = 0;
242
 
243
        op_code_shift = 0; phy_addr_shift = 0; reg_addr_shift = 0;
244
 
245
        data_in_shift = 0; data_out_load = 0; data_out_shift = 0;
246
 
247
        strobe_wr = 0;
248
 
249
        case (present)
250
 
251
          S_PREAMBLE:
252
            begin
253
               next = (preamble_match & ~mdio) ? S_ST : S_PREAMBLE;
254
            end
255
 
256
          S_ST:
257
            begin
258
               next = (mdio) ? S_OP_CODE: S_PREAMBLE;
259
            end
260
 
261
          S_OP_CODE:
262
            begin
263
               pos_cnt_inc = 1; op_code_shift = 1;
264
 
265
               next = (op_code_done) ? S_PHY_ADDR : S_OP_CODE;
266
            end
267
 
268
          S_PHY_ADDR:
269
            begin
270
               pos_cnt_inc = 1; phy_addr_shift = 1;
271
 
272
               next = (phy_addr_done) ? S_REG_ADDR : S_PHY_ADDR;
273
            end
274
 
275
          S_REG_ADDR:
276
            begin
277
               if (phy_addr_match) begin
278
 
279
                  pos_cnt_inc = 1; reg_addr_shift = 1;
280
 
281
                  next = (reg_addr_done) ? S_TA : S_REG_ADDR;
282
               end
283
               else
284
                 next = S_PREAMBLE;
285
            end
286
 
287
          S_TA:
288
            begin
289
               pos_cnt_inc = 1;
290
 
291
               if (ta1_done) begin
292
 
293
                  data_out_load = op_is_rd;
294
 
295
                  next = (op_is_rd) ? S_RD_DATA :
296
                         (op_is_wr) ? S_WR_DATA : S_PREAMBLE;
297
               end
298
            end
299
 
300
          S_WR_DATA:
301
            begin
302
               pos_cnt_inc = 1; data_in_shift = 1;
303
 
304
               next = (data_done) ? S_WR_COMMIT : S_WR_DATA;
305
            end
306
 
307
          S_RD_DATA:
308
            begin
309
               pos_cnt_inc = 1; data_out_shift = 1;
310
 
311
               next = (data_done) ? S_PREAMBLE : S_RD_DATA;
312
            end
313
 
314
 
315
          S_WR_COMMIT:
316
            begin
317
               strobe_wr = 1; next = S_PREAMBLE;
318
            end
319
        endcase
320
     end
321
 
322
endmodule

powered by: WebSVN 2.1.0

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