From 5723ec1a34181f1cfef9b8e870ab2e9a0362487c Mon Sep 17 00:00:00 2001 From: mindchasers Date: Wed, 1 May 2019 18:16:45 -0400 Subject: initial commit, all basic functions work on Darsena V02 --- source/mdio.v | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 source/mdio.v (limited to 'source/mdio.v') diff --git a/source/mdio.v b/source/mdio.v new file mode 100644 index 0000000..3339dcc --- /dev/null +++ b/source/mdio.v @@ -0,0 +1,146 @@ +/* + * mdio.v + * + * Copyright (C) 2018, 2019 Mind Chasers Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * function: MDIO HW driver / bit banger + * + */ + + +`timescale 1ns /10ps + +module mdio( + input rstn, + input mdc, // clock + + // mdio + input mdi, + output reg mdo, + output reg mdo_oe, + + // mdio_controller interface + input rwn, // read / write not + input [4:0] phy_addr, + input [4:0] reg_addr, + input [15:0] di, + input ld, // load, start + output reg run, + output done, // mdio xfer is done + + // output port to converter + output reg [15:0] dout, + output we +); + + reg [5:0] state; + reg [15:0] d; + + // run state machine + // run starts when ld is asserted and finishes when done is asserted + always @(negedge mdc or negedge rstn) + begin + if ( !rstn) + run <= 1'b0; + else if ( ld ) + run <= 1'b1; + else if ( done ) + run <= 1'b0; + end + + + // increment state during run + always @(negedge mdc or negedge rstn) + begin + if ( !rstn ) + state <= 0; + else if ( ld ) + state <= 0; + else if ( run ) + state <= state + 1; + end + + // register data for MDIO TX + always @(negedge mdc or negedge rstn) + begin + if ( !rstn ) + d <= 0; + else if ( ld ) + d <= di; + end + + // done combo logic + assign done = ( state == 6'd36 ) ? 1'b1 : 1'b0; + + // only assert we on mdio reads + assign we = done && rwn; + + // mdo_oe logic + always @(*) + begin + mdo_oe = 1'b0; + if ( run && !rwn && state < 6'd36 ) + mdo_oe = 1'b1; + else if ( run && rwn && state < 6'd14 ) + mdo_oe = 1'b1; + end + + // mdo mux + always @(*) + begin + mdo = 1'b0; + casez(state) + 6'h0: mdo = 1'b0; + 6'h1: mdo = 1'b1; + 6'h2: if (rwn) + mdo = 1'b1; + else + mdo = 1'b0; + 6'h3: if (rwn) + mdo = 1'b0; + else + mdo = 1'b1; + 6'h4: mdo = phy_addr[4]; + 6'h5: mdo = phy_addr[3]; + 6'h6: mdo = phy_addr[2]; + 6'h7: mdo = phy_addr[1]; + 6'h8: mdo = phy_addr[0]; + 6'h9: mdo = reg_addr[4]; + 6'ha: mdo = reg_addr[3]; + 6'hb: mdo = reg_addr[2]; + 6'hc: mdo = reg_addr[1]; + 6'hd: mdo = reg_addr[0]; + 6'he: mdo = 1'b1; // it's a don't care if we're doing a read + 6'hf: mdo = 1'b0; + 6'h1?: mdo = rwn ? 1'b1 : d[31-state]; // msbit + default: mdo = 1'b1; + endcase + end + + + /* + * capture mdi on rising edge + * data out shift register + * ( shift into it from mdio to parallel reg ) + */ + always @(posedge mdc or negedge rstn) + begin + if ( !rstn ) + dout <= 16'h0; + else if ( rwn && run && ( state >= 16 && state <= 31 )) + dout <= { dout[14:0], mdi }; + end + +endmodule -- cgit v1.2.3-8-gadcc