// ========== Copyright Header Begin ==========================================
// OpenSPARC T2 Processor File: mdio_mmd_model.v
// Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved
// 4150 Network Circle, Santa Clara, California 95054, U.S.A.
// * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// For the avoidance of doubt, and except that if any non-GPL license
// choice is available it will apply instead, Sun elects to use only
// the General Public License version 2 (GPLv2) at this time for any
// software where a choice of GPL license versions is made
// available with the language indicating that GPLv2 or any later version
// may be used, or where a choice of which version of the GPL is applied is
// otherwise unspecified.
// Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
// CA 95054 USA or visit www.sun.com if you need additional information or
// ========== Copyright Header End ============================================
`include "mdio_model_defines.vh"
module mdio_mmd_model (reset, mdc, mdio_in, mdio_out, mdio_en);
wire mdio_en_id_match_pre;
wire mdio_en_id_match_post;
wire mdio_en = mdio_en_id_match_post;
integer bit_cnt_preamble;
reg [15:0] memory [65535:0]; // supports upto 64K registers
wire [15:0] memory0 = memory[0];
wire [15:0] memory1 = memory[1];
wire [15:0] memory2 = memory[2];
wire [15:0] memory3 = memory[3];
wire [15:0] memory4 = memory[4];
wire [15:0] memory5 = memory[5];
wire [15:0] memory6 = memory[6];
wire [15:0] memory7 = memory[7];
wire [15:0] memory8 = memory[8];
wire [15:0] memory9 = memory[9];
wire [15:0] memory100 = memory[100];
wire [15:0] memory200 = memory[200];
parameter MY_PRT_ID = `MDIO_MMD_MODEL_PRT_ID;
parameter MY_PHY_ID = `MDIO_MMD_MODEL_PHY_ID;
parameter MY_DEV_ID = `MDIO_MMD_MODEL_DEV_ID;
assign mdio_out = ((next_state == DATA_RD | next_state == DATA_RDP) &&
(bit_cnt_read == 17) && (op[1] == 1'b1)) ?
1'bz : ((next_state == DATA_RD | next_state == DATA_RDP) &&
(bit_cnt_read == 16) && (op[1] == 1'b1)) ?
1'b0 : ((next_state == DATA_RD | next_state == DATA_RDP |
state == DATA_RD | state == DATA_RDP) &&
read_data[bit_cnt_read] : 1'bz;
assign mdio_en_id_match_pre = ((next_state == DATA_RD | next_state == DATA_RDP) &&
(bit_cnt_read == 17) && (op[1] == 1'b1)) ?
1'b1 : ((next_state == DATA_RD | next_state == DATA_RDP) &&
(bit_cnt_read == 16) && (op[1] == 1'b1)) ?
1'b1 : ((next_state == DATA_RD | next_state == DATA_RDP |
state == DATA_RD | state == DATA_RDP) &&
assign mdio_en_id_match_post = ((st == 2'b01) && (phyad[4:0] == MY_PHY_ID)) ? // Claus22
((st == 2'b00) && (prtad[4:0] == MY_PRT_ID) && (devad[4:0] == MY_DEV_ID)) ?
mdio_en_id_match_pre : 1'b0;
always @(reset or state or mdio_in or bit_cnt or st or op or bit_cnt_read or bit_cnt_preamble)
else if(mdio_in === 1'b1)
if((mdio_in === 1'b0) && (bit_cnt_preamble < 31))
else if((mdio_in == 1'b0) && (bit_cnt_preamble >= 31))
if((bit_cnt == 0) && ((st == 2'b11) | (st == 2'b10))) begin
$display("<%0d> MDIO_DEBUG: ERROR: Invalid MDIO transaction st:%h , state:%h, next_state:%h %m",
$time, st, state, next_state);
if((bit_cnt == 0) && (st == 2'b01))
else if((bit_cnt == 0) && (st == 2'b00))
PHYAD : // Claus22 Specific
PRTAD : // Claus45 specific
DEVAD : // Claus45 specific
if((bit_cnt == 0) && (op == 2'b00))
else if((bit_cnt == 0) && (op == 2'b01))
else if((bit_cnt == 0) && (op == 2'b11))
else if((bit_cnt == 0) && (op == 2'b10) && (st == 2'b01)) // Claus22 specific
else if((bit_cnt == 0) && (op == 2'b10) && (st == 2'b00)) // Claus45 specific
if((bit_cnt == 0) && (op == 2'b00))
else if((bit_cnt == 0) && (op == 2'b01))
else if((bit_cnt == 0) && (op == 2'b11))
else if((bit_cnt == 0) && (op == 2'b10) && (st == 2'b01)) // Claus22 specific
else if((bit_cnt == 0) && (op == 2'b10) && (st == 2'b00)) // Claus45 specific
if((bit_cnt == 0) && (op == 2'b00))
else if((bit_cnt == 0) && (op == 2'b01))
bit_cnt_read <= #1 bit_cnt_read - 1;
bit_cnt_preamble <= #1 0;
else if(state == PREAMBLE) begin
bit_cnt_preamble <= #1 bit_cnt_preamble + 1;
else if((state == ST) && (bit_cnt == 0))
else if((state == OP) && (bit_cnt == 0))
else if((state == PHYAD) && (bit_cnt == 0))
else if((state == PRTAD) && (bit_cnt == 0))
else if((state == DEVAD) && (bit_cnt == 0))
else if((state == REGAD) && (bit_cnt == 0))
else if((state == TA) && (bit_cnt == 0))
else if((state == ADDR) && (bit_cnt == 0))
else if((state == DATA_WR) && (bit_cnt == 0))
else if((state == DATA_RD) && (bit_cnt == 0))
else if((state == DATA_RDP) && (bit_cnt == 0))
bit_cnt <= #1 bit_cnt - 1;
if((state == DEVAD) && (bit_cnt == 1))
if((state == REGAD) && (bit_cnt == 1))
st[bit_cnt] <= #1 mdio_d;
op[bit_cnt] <= #1 mdio_d;
prtad[bit_cnt]<= #1 mdio_d;
phyad[bit_cnt]<= #1 mdio_d;
else if(state == DEVAD) begin
devad[bit_cnt]<= #1 mdio_d;
read_data <= #1 memory[addr];
else if(state == REGAD) begin
regad[bit_cnt]<= #1 mdio_d;
read_data <= #1 memory[{regad[4:1], mdio_d}];
ta[bit_cnt] <= #1 mdio_d;
addr[bit_cnt] <= #1 mdio_d;
data[bit_cnt] <= #1 mdio_d;
if((state == DATA_WR) && (st == 2'b01) && (bit_cnt == 0)) // Claus22
if(phyad[4:0] == MY_PHY_ID)
if((state == DATA_WR) && (st == 2'b00) && (bit_cnt == 0)) // Claus45
if((prtad[4:0] == MY_PRT_ID) && (devad[4:0] == MY_DEV_ID)) begin
if(write_en_22 == 1'b1) begin
memory[regad] <= #1 data;
$display("<%0d> MDIO_DEBUG: Write addr:%h data:%h Claus22 %m", $time, regad, data);
if(write_en_45 == 1'b1) begin
$display("<%0d> MDIO_DEBUG: Write addr:%h data:%h Claus45 %m", $time, addr, data);
if((state == DATA_RD) && (st == 2'b01)) begin // Claus22
if(phyad[4:0] == MY_PHY_ID) begin
$display("<%0d> MDIO_DEBUG: Read addr:%h data:%h Claus22 %m", $time, regad, memory[regad]);
if((state == DATA_RD) && (st == 2'b00)) begin // Claus45
if((prtad[4:0] == MY_PRT_ID) && (devad[4:0] == MY_DEV_ID)) begin
$display("<%0d> MDIO_DEBUG: Read addr:%h data:%h Claus45 %m", $time, addr, memory[addr]);
// Read post-read-increment-address
if((state == DATA_RDP) && (st == 2'b00)) begin // Claus45
if((prtad[4:0] == MY_PRT_ID) && (devad[4:0] == MY_DEV_ID)) begin
$display("<%0d> MDIO_DEBUG: Read addr:%h data:%h %m", $time, addr, memory[addr]);
// logic to test poll mode in MIF
// Provides facilities to modify mmd memory content
reg [15:0] modify_mmd_memory_address;
reg [15:0] modify_mmd_memory_data;
reg [15:0] modify_mmd_memory_time;
reg modify_mmd_memory_enable;
modify_mmd_memory_address = 16'hFFFF;
modify_mmd_memory_data = 16'h0;
modify_mmd_memory_time = 16'h0;
modify_mmd_memory_enable = 1'b0;
if ($test$plusargs("MODIFY_MMD_MEMORY_ADDRESS="))
modify_mmd_memory_enable = 1'b1;
if ($test$plusargs("MODIFY_MMD_MEMORY_ADDRESS="))
ret_code = $value$plusargs("MODIFY_MMD_MEMORY_ADDRESS=%h", modify_mmd_memory_address);
if ($test$plusargs("MODIFY_MMD_MEMORY_DATA="))
ret_code = $value$plusargs("MODIFY_MMD_MEMORY_DATA=%h", modify_mmd_memory_data);
if ($test$plusargs("MODIFY_MMD_MEMORY_TIME="))
ret_code = $value$plusargs("MODIFY_MMD_MEMORY_TIME=%d", modify_mmd_memory_time);
if(modify_mmd_memory_enable) begin
$display("<%0d> MDIO_DEBUG: modify mmd memory at time:%0d mdc cycles addr:%h data:%h %m",
$time, modify_mmd_memory_time, modify_mmd_memory_address, modify_mmd_memory_data);
repeat(modify_mmd_memory_time) @(posedge mdc);
$display("<%0d> MDIO_DEBUG: modify mmd memory now time:%0d mdc cycles addr:%h data:%h %m",
$time, modify_mmd_memory_time, modify_mmd_memory_address, modify_mmd_memory_data);
memory[modify_mmd_memory_address] = modify_mmd_memory_data;
reg force_mmd_mdio_bus_enable;
reg force_mmd_mdio_bus_value;
reg [31:0] force_mmd_mdio_bus_time;
if ($test$plusargs("FORCE_MMD_MDIO_BUS_ENABLE"))
force_mmd_mdio_bus_enable = 1'b1;
force_mmd_mdio_bus_enable = 1'b0;
if ($test$plusargs("FORCE_MMD_MDIO_BUS_VALUE="))
ret_code = $value$plusargs("FORCE_MMD_MDIO_BUS_VALUE=%d", force_mmd_mdio_bus_value);
if ($test$plusargs("FORCE_MMD_MDIO_BUS_TIME="))
ret_code = $value$plusargs("FORCE_MMD_MDIO_BUS_TIME=%d", force_mmd_mdio_bus_time);
if(force_mmd_mdio_bus_enable) begin
$display("<%0d> MDIO_DEBUG: force mmd mdio at time:%0d mdc cycles %m",
$time, force_mmd_mdio_bus_time);
repeat(force_mmd_mdio_bus_time) @(posedge mdc);
force mdio_out = force_mmd_mdio_bus_value;
force mdio_en = force_mmd_mdio_bus_value;
force mdio_in = force_mmd_mdio_bus_value;
$display("<%0d> MDIO_DEBUG: force mmd mdio now time:%0d mdc cycles %m",
$time, force_mmd_mdio_bus_time);