Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | // ========== Copyright Header Begin ========================================== |
2 | // | |
3 | // OpenSPARC T2 Processor File: mdio_mmd_model.v | |
4 | // Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved | |
5 | // 4150 Network Circle, Santa Clara, California 95054, U.S.A. | |
6 | // | |
7 | // * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
8 | // | |
9 | // This program is free software; you can redistribute it and/or modify | |
10 | // it under the terms of the GNU General Public License as published by | |
11 | // the Free Software Foundation; version 2 of the License. | |
12 | // | |
13 | // This program is distributed in the hope that it will be useful, | |
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | // GNU General Public License for more details. | |
17 | // | |
18 | // You should have received a copy of the GNU General Public License | |
19 | // along with this program; if not, write to the Free Software | |
20 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
21 | // | |
22 | // For the avoidance of doubt, and except that if any non-GPL license | |
23 | // choice is available it will apply instead, Sun elects to use only | |
24 | // the General Public License version 2 (GPLv2) at this time for any | |
25 | // software where a choice of GPL license versions is made | |
26 | // available with the language indicating that GPLv2 or any later version | |
27 | // may be used, or where a choice of which version of the GPL is applied is | |
28 | // otherwise unspecified. | |
29 | // | |
30 | // Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
31 | // CA 95054 USA or visit www.sun.com if you need additional information or | |
32 | // have any questions. | |
33 | // | |
34 | // ========== Copyright Header End ============================================ | |
35 | `include "mdio_model_defines.vh" | |
36 | module mdio_mmd_model (reset, mdc, mdio_in, mdio_out, mdio_en); | |
37 | input reset; | |
38 | input mdc; | |
39 | input mdio_in; | |
40 | output mdio_out; | |
41 | output mdio_en; | |
42 | ||
43 | wire mdio_en_id_match_pre; | |
44 | wire mdio_en_id_match_post; | |
45 | wire mdio_en = mdio_en_id_match_post; | |
46 | wire mdio_out; | |
47 | reg mdio_d; | |
48 | ||
49 | integer bit_cnt; | |
50 | integer bit_cnt_preamble; | |
51 | integer bit_cnt_read; | |
52 | reg [3:0] state; | |
53 | reg [3:0] next_state; | |
54 | ||
55 | reg [1:0] st; | |
56 | reg [1:0] op; | |
57 | reg [4:0] prtad; | |
58 | reg [4:0] phyad; | |
59 | reg [4:0] devad; | |
60 | reg [4:0] regad; | |
61 | reg [15:0] addr; | |
62 | reg [1:0] ta; | |
63 | reg [15:0] data; | |
64 | reg write_en_22; | |
65 | reg write_en_45; | |
66 | reg [15:0] read_data; | |
67 | ||
68 | // storage | |
69 | reg [15:0] memory [65535:0]; // supports upto 64K registers | |
70 | // debug | |
71 | wire [15:0] memory0 = memory[0]; | |
72 | wire [15:0] memory1 = memory[1]; | |
73 | wire [15:0] memory2 = memory[2]; | |
74 | wire [15:0] memory3 = memory[3]; | |
75 | wire [15:0] memory4 = memory[4]; | |
76 | wire [15:0] memory5 = memory[5]; | |
77 | wire [15:0] memory6 = memory[6]; | |
78 | wire [15:0] memory7 = memory[7]; | |
79 | wire [15:0] memory8 = memory[8]; | |
80 | wire [15:0] memory9 = memory[9]; | |
81 | wire [15:0] memory100 = memory[100]; | |
82 | wire [15:0] memory200 = memory[200]; | |
83 | ||
84 | parameter MY_PRT_ID = `MDIO_MMD_MODEL_PRT_ID; | |
85 | parameter MY_PHY_ID = `MDIO_MMD_MODEL_PHY_ID; | |
86 | parameter MY_DEV_ID = `MDIO_MMD_MODEL_DEV_ID; | |
87 | ||
88 | parameter | |
89 | IDLE = 0, | |
90 | PREAMBLE= 1, | |
91 | ST = 2, | |
92 | OP = 3, | |
93 | PRTAD = 4, | |
94 | PHYAD = 5, | |
95 | DEVAD = 6, | |
96 | REGAD = 7, | |
97 | TA = 8, | |
98 | ADDR = 9, | |
99 | DATA_RD = 10, | |
100 | DATA_RDP= 11, | |
101 | DATA_WR = 12; | |
102 | ||
103 | assign mdio_out = ((next_state == DATA_RD | next_state == DATA_RDP) && | |
104 | (bit_cnt_read == 17) && (op[1] == 1'b1)) ? | |
105 | 1'bz : ((next_state == DATA_RD | next_state == DATA_RDP) && | |
106 | (bit_cnt_read == 16) && (op[1] == 1'b1)) ? | |
107 | 1'b0 : ((next_state == DATA_RD | next_state == DATA_RDP | | |
108 | state == DATA_RD | state == DATA_RDP) && | |
109 | (op[1] == 1'b1)) ? | |
110 | read_data[bit_cnt_read] : 1'bz; | |
111 | ||
112 | assign mdio_en_id_match_pre = ((next_state == DATA_RD | next_state == DATA_RDP) && | |
113 | (bit_cnt_read == 17) && (op[1] == 1'b1)) ? | |
114 | 1'b1 : ((next_state == DATA_RD | next_state == DATA_RDP) && | |
115 | (bit_cnt_read == 16) && (op[1] == 1'b1)) ? | |
116 | 1'b1 : ((next_state == DATA_RD | next_state == DATA_RDP | | |
117 | state == DATA_RD | state == DATA_RDP) && | |
118 | (op[1] == 1'b1)) ? | |
119 | 1'b1 : 1'b0; | |
120 | ||
121 | assign mdio_en_id_match_post = ((st == 2'b01) && (phyad[4:0] == MY_PHY_ID)) ? // Claus22 | |
122 | mdio_en_id_match_pre : | |
123 | ((st == 2'b00) && (prtad[4:0] == MY_PRT_ID) && (devad[4:0] == MY_DEV_ID)) ? | |
124 | mdio_en_id_match_pre : 1'b0; | |
125 | // combinational logic | |
126 | always @(reset or state or mdio_in or bit_cnt or st or op or bit_cnt_read or bit_cnt_preamble) | |
127 | begin | |
128 | case (state) | |
129 | IDLE : | |
130 | if(reset) | |
131 | next_state = IDLE; | |
132 | else if(mdio_in === 1'b1) | |
133 | next_state = PREAMBLE; | |
134 | else | |
135 | next_state = IDLE; | |
136 | PREAMBLE : | |
137 | if((mdio_in === 1'b0) && (bit_cnt_preamble < 31)) | |
138 | next_state = IDLE; | |
139 | else if((mdio_in == 1'b0) && (bit_cnt_preamble >= 31)) | |
140 | next_state = ST; | |
141 | else | |
142 | next_state = PREAMBLE; | |
143 | ST : | |
144 | if((bit_cnt == 0) && ((st == 2'b11) | (st == 2'b10))) begin | |
145 | $display("<%0d> MDIO_DEBUG: ERROR: Invalid MDIO transaction st:%h , state:%h, next_state:%h %m", | |
146 | $time, st, state, next_state); | |
147 | next_state = IDLE; | |
148 | end | |
149 | else if(bit_cnt == 0) | |
150 | next_state = OP; | |
151 | else | |
152 | next_state = ST; | |
153 | OP : | |
154 | if((bit_cnt == 0) && (st == 2'b01)) | |
155 | next_state = PHYAD; | |
156 | else if((bit_cnt == 0) && (st == 2'b00)) | |
157 | next_state = PRTAD; | |
158 | else | |
159 | next_state = OP; | |
160 | PHYAD : // Claus22 Specific | |
161 | if(bit_cnt == 0) | |
162 | next_state = REGAD; | |
163 | else | |
164 | next_state = PHYAD; | |
165 | PRTAD : // Claus45 specific | |
166 | if(bit_cnt == 0) | |
167 | next_state = DEVAD; | |
168 | else | |
169 | next_state = PRTAD; | |
170 | DEVAD : // Claus45 specific | |
171 | if((bit_cnt == 0) && (op == 2'b00)) | |
172 | next_state = TA; | |
173 | else if((bit_cnt == 0) && (op == 2'b01)) | |
174 | next_state = TA; | |
175 | else if((bit_cnt == 0) && (op == 2'b11)) | |
176 | next_state = DATA_RD; | |
177 | else if((bit_cnt == 0) && (op == 2'b10) && (st == 2'b01)) // Claus22 specific | |
178 | next_state = DATA_RD; | |
179 | else if((bit_cnt == 0) && (op == 2'b10) && (st == 2'b00)) // Claus45 specific | |
180 | next_state = DATA_RDP; | |
181 | else | |
182 | next_state = DEVAD; | |
183 | REGAD : | |
184 | if((bit_cnt == 0) && (op == 2'b00)) | |
185 | next_state = TA; | |
186 | else if((bit_cnt == 0) && (op == 2'b01)) | |
187 | next_state = TA; | |
188 | else if((bit_cnt == 0) && (op == 2'b11)) | |
189 | next_state = DATA_RD; | |
190 | else if((bit_cnt == 0) && (op == 2'b10) && (st == 2'b01)) // Claus22 specific | |
191 | next_state = DATA_RD; | |
192 | else if((bit_cnt == 0) && (op == 2'b10) && (st == 2'b00)) // Claus45 specific | |
193 | next_state = DATA_RDP; | |
194 | else | |
195 | next_state = REGAD; | |
196 | TA : | |
197 | if((bit_cnt == 0) && (op == 2'b00)) | |
198 | next_state = ADDR; | |
199 | else if((bit_cnt == 0) && (op == 2'b01)) | |
200 | next_state = DATA_WR; | |
201 | else | |
202 | next_state = TA; | |
203 | ADDR : | |
204 | if(bit_cnt == 0) | |
205 | next_state = IDLE; | |
206 | else | |
207 | next_state = ADDR; | |
208 | DATA_WR : | |
209 | if(bit_cnt == 0) | |
210 | next_state = IDLE; | |
211 | else | |
212 | next_state = DATA_WR; | |
213 | DATA_RD : | |
214 | if(bit_cnt_read == 0) | |
215 | next_state = IDLE; | |
216 | else | |
217 | next_state = DATA_RD; | |
218 | DATA_RDP : | |
219 | if(bit_cnt_read == 0) | |
220 | next_state = IDLE; | |
221 | else | |
222 | next_state = DATA_RDP; | |
223 | default : | |
224 | next_state = IDLE; | |
225 | endcase | |
226 | end | |
227 | ||
228 | always @(posedge mdc) | |
229 | begin | |
230 | if(reset) begin | |
231 | state <= #1 4'h0; | |
232 | bit_cnt <= #1 7'd31; | |
233 | mdio_d <= #1 1'bz; | |
234 | write_en_22 <= #1 1'b0; | |
235 | write_en_45 <= #1 1'b0; | |
236 | bit_cnt_read <= #1 7'd0; | |
237 | end | |
238 | else begin | |
239 | state <= #1 next_state; | |
240 | mdio_d <= #1 mdio_in; | |
241 | end | |
242 | ||
243 | // default | |
244 | write_en_22 <= #1 1'b0; | |
245 | write_en_45 <= #1 1'b0; | |
246 | bit_cnt_read <= #1 bit_cnt_read - 1; | |
247 | ||
248 | // bit_cnt update | |
249 | if(state == IDLE) begin | |
250 | bit_cnt <= #1 31; | |
251 | bit_cnt_preamble <= #1 0; | |
252 | end | |
253 | else if(state == PREAMBLE) begin | |
254 | bit_cnt_preamble <= #1 bit_cnt_preamble + 1; | |
255 | bit_cnt <= #1 1; | |
256 | end | |
257 | else if((state == ST) && (bit_cnt == 0)) | |
258 | bit_cnt <= #1 1; | |
259 | else if((state == OP) && (bit_cnt == 0)) | |
260 | bit_cnt <= #1 4; | |
261 | else if((state == PHYAD) && (bit_cnt == 0)) | |
262 | bit_cnt <= #1 4; | |
263 | else if((state == PRTAD) && (bit_cnt == 0)) | |
264 | bit_cnt <= #1 4; | |
265 | else if((state == DEVAD) && (bit_cnt == 0)) | |
266 | bit_cnt <= #1 1; | |
267 | else if((state == REGAD) && (bit_cnt == 0)) | |
268 | bit_cnt <= #1 1; | |
269 | else if((state == TA) && (bit_cnt == 0)) | |
270 | bit_cnt <= #1 15; | |
271 | else if((state == ADDR) && (bit_cnt == 0)) | |
272 | bit_cnt <= #1 31; | |
273 | else if((state == DATA_WR) && (bit_cnt == 0)) | |
274 | bit_cnt <= #1 31; | |
275 | else if((state == DATA_RD) && (bit_cnt == 0)) | |
276 | bit_cnt <= #1 31; | |
277 | else if((state == DATA_RDP) && (bit_cnt == 0)) | |
278 | bit_cnt <= #1 31; | |
279 | else | |
280 | bit_cnt <= #1 bit_cnt - 1; | |
281 | ||
282 | // bit_cnt_read | |
283 | if((state == DEVAD) && (bit_cnt == 1)) | |
284 | bit_cnt_read <= #1 17; | |
285 | if((state == REGAD) && (bit_cnt == 1)) | |
286 | bit_cnt_read <= #1 17; | |
287 | ||
288 | // st | |
289 | if(state == IDLE) | |
290 | st <= #1 0; | |
291 | else if(state == ST) | |
292 | st[bit_cnt] <= #1 mdio_d; | |
293 | ||
294 | // op | |
295 | if(state == IDLE) | |
296 | op <= #1 0; | |
297 | else if(state == OP) | |
298 | op[bit_cnt] <= #1 mdio_d; | |
299 | ||
300 | // prtad | |
301 | if(state == IDLE) | |
302 | prtad <= #1 0; | |
303 | else if(state == PRTAD) | |
304 | prtad[bit_cnt]<= #1 mdio_d; | |
305 | ||
306 | // phyad | |
307 | if(state == IDLE) | |
308 | phyad <= #1 0; | |
309 | else if(state == PHYAD) | |
310 | phyad[bit_cnt]<= #1 mdio_d; | |
311 | ||
312 | // devad | |
313 | if(state == IDLE) | |
314 | devad <= #1 0; | |
315 | else if(state == DEVAD) begin | |
316 | devad[bit_cnt]<= #1 mdio_d; | |
317 | read_data <= #1 memory[addr]; | |
318 | end | |
319 | ||
320 | // regad | |
321 | if(state == IDLE) | |
322 | regad <= #1 0; | |
323 | else if(state == REGAD) begin | |
324 | regad[bit_cnt]<= #1 mdio_d; | |
325 | read_data <= #1 memory[{regad[4:1], mdio_d}]; | |
326 | end | |
327 | ||
328 | // ta | |
329 | if(state == IDLE) | |
330 | ta <= #1 0; | |
331 | else if(state == TA) | |
332 | ta[bit_cnt] <= #1 mdio_d; | |
333 | ||
334 | // addr | |
335 | if(state == ADDR) | |
336 | addr[bit_cnt] <= #1 mdio_d; | |
337 | ||
338 | // data | |
339 | if(state == IDLE) | |
340 | data <= #1 0; | |
341 | if(state == DATA_WR) | |
342 | data[bit_cnt] <= #1 mdio_d; | |
343 | ||
344 | ||
345 | // Write | |
346 | if((state == DATA_WR) && (st == 2'b01) && (bit_cnt == 0)) // Claus22 | |
347 | if(phyad[4:0] == MY_PHY_ID) | |
348 | write_en_22 <= #1 1'b1; | |
349 | ||
350 | // Write | |
351 | if((state == DATA_WR) && (st == 2'b00) && (bit_cnt == 0)) // Claus45 | |
352 | if((prtad[4:0] == MY_PRT_ID) && (devad[4:0] == MY_DEV_ID)) begin | |
353 | write_en_45 <= #1 1'b1; | |
354 | regad <= #1 addr; | |
355 | end | |
356 | ||
357 | if(write_en_22 == 1'b1) begin | |
358 | memory[regad] <= #1 data; | |
359 | $display("<%0d> MDIO_DEBUG: Write addr:%h data:%h Claus22 %m", $time, regad, data); | |
360 | end | |
361 | ||
362 | if(write_en_45 == 1'b1) begin | |
363 | memory[addr] <= #1 data; | |
364 | $display("<%0d> MDIO_DEBUG: Write addr:%h data:%h Claus45 %m", $time, addr, data); | |
365 | end | |
366 | ||
367 | // Read | |
368 | if((state == DATA_RD) && (st == 2'b01)) begin // Claus22 | |
369 | if(phyad[4:0] == MY_PHY_ID) begin | |
370 | if(bit_cnt == 0) | |
371 | $display("<%0d> MDIO_DEBUG: Read addr:%h data:%h Claus22 %m", $time, regad, memory[regad]); | |
372 | end | |
373 | end | |
374 | ||
375 | // Read | |
376 | if((state == DATA_RD) && (st == 2'b00)) begin // Claus45 | |
377 | if((prtad[4:0] == MY_PRT_ID) && (devad[4:0] == MY_DEV_ID)) begin | |
378 | if(bit_cnt == 0) | |
379 | $display("<%0d> MDIO_DEBUG: Read addr:%h data:%h Claus45 %m", $time, addr, memory[addr]); | |
380 | end | |
381 | end | |
382 | ||
383 | // Read post-read-increment-address | |
384 | if((state == DATA_RDP) && (st == 2'b00)) begin // Claus45 | |
385 | if((prtad[4:0] == MY_PRT_ID) && (devad[4:0] == MY_DEV_ID)) begin | |
386 | addr <= #1 addr + 1; | |
387 | if(bit_cnt == 0) | |
388 | $display("<%0d> MDIO_DEBUG: Read addr:%h data:%h %m", $time, addr, memory[addr]); | |
389 | end | |
390 | end | |
391 | end // always | |
392 | ||
393 | ||
394 | `ifdef AXIS | |
395 | `else // AXIS | |
396 | // logic to test poll mode in MIF | |
397 | // Provides facilities to modify mmd memory content | |
398 | reg [15:0] modify_mmd_memory_address; | |
399 | reg [15:0] modify_mmd_memory_data; | |
400 | reg [15:0] modify_mmd_memory_time; | |
401 | reg modify_mmd_memory_enable; | |
402 | integer ret_code; | |
403 | initial | |
404 | begin | |
405 | modify_mmd_memory_address = 16'hFFFF; | |
406 | modify_mmd_memory_data = 16'h0; | |
407 | modify_mmd_memory_time = 16'h0; | |
408 | modify_mmd_memory_enable = 1'b0; | |
409 | ||
410 | if ($test$plusargs("MODIFY_MMD_MEMORY_ADDRESS=")) | |
411 | modify_mmd_memory_enable = 1'b1; | |
412 | ||
413 | if ($test$plusargs("MODIFY_MMD_MEMORY_ADDRESS=")) | |
414 | ret_code = $value$plusargs("MODIFY_MMD_MEMORY_ADDRESS=%h", modify_mmd_memory_address); | |
415 | if ($test$plusargs("MODIFY_MMD_MEMORY_DATA=")) | |
416 | ret_code = $value$plusargs("MODIFY_MMD_MEMORY_DATA=%h", modify_mmd_memory_data); | |
417 | if ($test$plusargs("MODIFY_MMD_MEMORY_TIME=")) | |
418 | ret_code = $value$plusargs("MODIFY_MMD_MEMORY_TIME=%d", modify_mmd_memory_time); | |
419 | ||
420 | // corrupt | |
421 | if(modify_mmd_memory_enable) begin | |
422 | $display("<%0d> MDIO_DEBUG: modify mmd memory at time:%0d mdc cycles addr:%h data:%h %m", | |
423 | $time, modify_mmd_memory_time, modify_mmd_memory_address, modify_mmd_memory_data); | |
424 | repeat(modify_mmd_memory_time) @(posedge mdc); | |
425 | $display("<%0d> MDIO_DEBUG: modify mmd memory now time:%0d mdc cycles addr:%h data:%h %m", | |
426 | $time, modify_mmd_memory_time, modify_mmd_memory_address, modify_mmd_memory_data); | |
427 | memory[modify_mmd_memory_address] = modify_mmd_memory_data; | |
428 | end | |
429 | ||
430 | end | |
431 | ||
432 | reg force_mmd_mdio_bus_enable; | |
433 | reg force_mmd_mdio_bus_value; | |
434 | reg [31:0] force_mmd_mdio_bus_time; | |
435 | ||
436 | initial | |
437 | begin | |
438 | if ($test$plusargs("FORCE_MMD_MDIO_BUS_ENABLE")) | |
439 | force_mmd_mdio_bus_enable = 1'b1; | |
440 | else | |
441 | force_mmd_mdio_bus_enable = 1'b0; | |
442 | ||
443 | if ($test$plusargs("FORCE_MMD_MDIO_BUS_VALUE=")) | |
444 | ret_code = $value$plusargs("FORCE_MMD_MDIO_BUS_VALUE=%d", force_mmd_mdio_bus_value); | |
445 | ||
446 | if ($test$plusargs("FORCE_MMD_MDIO_BUS_TIME=")) | |
447 | ret_code = $value$plusargs("FORCE_MMD_MDIO_BUS_TIME=%d", force_mmd_mdio_bus_time); | |
448 | ||
449 | if(force_mmd_mdio_bus_enable) begin | |
450 | $display("<%0d> MDIO_DEBUG: force mmd mdio at time:%0d mdc cycles %m", | |
451 | $time, force_mmd_mdio_bus_time); | |
452 | repeat(force_mmd_mdio_bus_time) @(posedge mdc); | |
453 | force mdio_out = force_mmd_mdio_bus_value; | |
454 | force mdio_en = force_mmd_mdio_bus_value; | |
455 | force mdio_in = force_mmd_mdio_bus_value; | |
456 | $display("<%0d> MDIO_DEBUG: force mmd mdio now time:%0d mdc cycles %m", | |
457 | $time, force_mmd_mdio_bus_time); | |
458 | end | |
459 | end | |
460 | `endif // AXIS | |
461 | ||
462 | endmodule | |
463 |