//////////////////////////////////////////////////////////////////////
////                                                              ////
////  File name "wishbone.v"                                      ////
////                                                              ////
////  This file is part of the "10GE MAC" project                 ////
////  http://www.opencores.org/cores/xge_mac/                     ////
////                                                              ////
////  Author(s):                                                  ////
////      - A. Tanguay (antanguay@opencores.org)                  ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
////                                                              ////
//// Copyright (C) 2008 AUTHORS. All rights reserved.             ////
////                                                              ////
//// This source file may be used and distributed without         ////
//// restriction provided that this copyright statement is not    ////
//// removed from the file and that any derivative work contains  ////
//// the original copyright notice and the associated disclaimer. ////
////                                                              ////
//// This source file is free software; you can redistribute it   ////
//// and/or modify it under the terms of the GNU Lesser General   ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any   ////
//// later version.                                               ////
////                                                              ////
//// This source 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 Lesser General Public License for more ////
//// details.                                                     ////
////                                                              ////
//// You should have received a copy of the GNU Lesser General    ////
//// Public License along with this source; if not, download it   ////
//// from http://www.opencores.org/lgpl.shtml                     ////
////                                                              ////
//////////////////////////////////////////////////////////////////////

`include "defines.v"
 
module wishbone_if(/*AUTOARG*/
  // Outputs
  wb_dat_o, wb_ack_o, wb_int_o, ctrl_tx_enable, 
  `ifdef MDIO
   mdc, mdio_out, mdio_tri, xge_gpo,
   `endif
		   
  // Inputs
  wb_clk_i, wb_rst_i, wb_adr_i, wb_dat_i, wb_we_i, wb_stb_i, wb_cyc_i,
  status_crc_error, status_fragment_error, status_txdfifo_ovflow,
  status_txdfifo_udflow, status_rxdfifo_ovflow, status_rxdfifo_udflow,
  status_pause_frame_rx, status_local_fault, status_remote_fault
  `ifdef MDIO
  ,mdio_in, xge_gpi
  `endif		   
  );
 
 
input         wb_clk_i;
input         wb_rst_i;
 
input  [7:0]  wb_adr_i;
input  [31:0] wb_dat_i;
input         wb_we_i;
input         wb_stb_i;
input         wb_cyc_i;
 
output [31:0] wb_dat_o;
output        wb_ack_o;
output        wb_int_o;
 
input         status_crc_error;
input         status_fragment_error;
 
input         status_txdfifo_ovflow;
 
input         status_txdfifo_udflow;
 
input         status_rxdfifo_ovflow;
 
input         status_rxdfifo_udflow;
 
input         status_pause_frame_rx;
 
input         status_local_fault;
input         status_remote_fault;
 
output        ctrl_tx_enable;
 
  `ifdef MDIO
   output reg    mdc;
   output reg    mdio_out;
   output reg    mdio_tri;   // Assert to tristate driver.
   input      mdio_in;
   input [7:0] xge_gpi;
   output reg [7:0] xge_gpo;

   //
   // State Declarations
   //
   parameter  IDLE = 0,
		PREAMBLE1 = 1,
		PREAMBLE2 = 2,
		PREAMBLE3 = 3,
		PREAMBLE4 = 4,
		PREAMBLE5 = 5,
		PREAMBLE6 = 6,
		PREAMBLE7 = 7,
		PREAMBLE8 = 8,
		PREAMBLE9 = 9,
		PREAMBLE10 = 10,
		PREAMBLE11 = 11,
		PREAMBLE12 = 12,
		PREAMBLE13 = 13,
		PREAMBLE14 = 14,
		PREAMBLE15 = 15,
		PREAMBLE16 = 16,
		PREAMBLE17 = 17,
		PREAMBLE18 = 18,
		PREAMBLE19 = 19,
		PREAMBLE20 = 20,
		PREAMBLE21 = 21,
		PREAMBLE22 = 22,
		PREAMBLE23 = 23,
		PREAMBLE24 = 24,
		PREAMBLE25 = 25,
		PREAMBLE26 = 26,
		PREAMBLE27 = 27,
		PREAMBLE28 = 28,
		PREAMBLE29 = 29,
		PREAMBLE30 = 30,
		PREAMBLE31 = 31,
		PREAMBLE32 = 32,
		START1 = 33,
		C22_START2 = 34,
		C45_START2 = 35,
		OP1 = 36,
		OP2 = 37,
		PRTAD1 = 38,
		PRTAD2 = 39,
		PRTAD3 = 40,
		PRTAD4 = 41,
		PRTAD5 = 42,
		DEVAD1 = 43,
		DEVAD2 = 44,
		DEVAD3 = 45,
		DEVAD4 = 46,
		DEVAD5 = 47,
		TA1 = 48,
		TA2 = 49,
		TA3 = 50,
		READ1 = 51,
		READ2 = 52,
		READ3 = 53,
		READ4 = 54,
		READ5 = 55,
		READ6 = 56,
		READ7 = 57,
		READ8 = 58,
		READ9 = 59,
		READ10 = 60,
		READ11 = 61,
		READ12 = 62,
		READ13 = 63,
		READ14 = 64,
		READ15 = 65,
		READ16 = 66,
		WRITE1 = 67,
		WRITE2 = 68,
		WRITE3 = 69,
		WRITE4 = 70,
		WRITE5 = 71,
		WRITE6 = 72,
		WRITE7 = 73,
		WRITE8 = 74,
		WRITE9 = 75,
		WRITE10 = 76,
		WRITE11 = 77,
		WRITE12 = 78,
		WRITE13 = 79,
		WRITE14 = 80,
		WRITE15 = 81,
		WRITE16 = 82,
		C45_ADDR1 = 83,
		C45_ADDR2 = 84,
		C45_ADDR3 = 85,
		C45_ADDR4 = 86,
		C45_ADDR5 = 87,
		C45_ADDR6 = 88,
		C45_ADDR7 = 89,
		C45_ADDR8 = 90,
		C45_ADDR9 = 91,
		C45_ADDR10 = 92,
		C45_ADDR11 = 93,
		C45_ADDR12 = 94,
		C45_ADDR13 = 95,
		C45_ADDR14 = 96,
		C45_ADDR15 = 97,
		C45_ADDR16 = 98,
		PREIDLE = 99;
   
       
`endif

   
/*AUTOREG*/
// Beginning of automatic regs (for this module's undeclared outputs)
reg [31:0]              wb_dat_o;
reg                     wb_int_o;
// End of automatics
 
reg  [0:0]              cpureg_config0;
reg  [8:0]              cpureg_int_pending;
reg  [8:0]              cpureg_int_mask;
 
reg                     cpuack;
 
reg                     status_remote_fault_d1;
reg                     status_local_fault_d1;

`ifdef MDIO
   reg [15:0]			mdio_read_data;
   reg [15:0] 			mdio_write_data;
   reg [15:0] 			mdio_address;
   reg [12:0] 			mdio_operation;
   reg 				mdio_control;
   reg [7:0] 			mdc_clk_count;
   reg 				mdc_falling_edge;
   reg 				mdio_running;
   reg 				mdio_done;
   reg [7:0] 			state;
   reg [7:0] 			xge_gpi_reg;
   reg [7:0] 			xge_gpo_reg;
   
`endif
   
 
/*AUTOWIRE*/
 
wire [8:0] 			int_sources;
 
 
//---
// Source of interrupts, some are edge sensitive, others
// expect a pulse signal.
 
assign int_sources = {
                      status_fragment_error,
                      status_crc_error,
 
                      status_pause_frame_rx,
 
                      status_remote_fault ^ status_remote_fault_d1,
                      status_local_fault ^ status_local_fault_d1,
 
                      status_rxdfifo_udflow,
                      status_rxdfifo_ovflow,
                      status_txdfifo_udflow,
                      status_txdfifo_ovflow
                      };
 
//---
// Config Register 0
 
assign ctrl_tx_enable = cpureg_config0[0];
 
 
 
//---
// Wishbone signals
 
assign wb_ack_o = cpuack && wb_stb_i;
 
always @(posedge wb_clk_i or posedge wb_rst_i) begin
 
    if (wb_rst_i == 1'b1) begin
 
        cpureg_config0 <= 1'h1;
        cpureg_int_pending <= 9'b0;
        cpureg_int_mask <= 9'b0;
 
        wb_dat_o <= 32'b0;
        wb_int_o <= 1'b0;
 
        cpuack <= 1'b0;

`ifdef MDIO
       mdio_address <= 0;
       mdio_operation <= 0;
       mdio_write_data <= 0;
       
       mdio_running <= 0;
       xge_gpi_reg <= 0;
       xge_gpo <= 0;
       xge_gpo_reg <= 0;
       

`endif
	 
 
 //       status_remote_fault_d1 <= status_remote_fault;
 //       status_local_fault_d1 <= status_local_fault;
       // IJB. Original code was unsynthesizable and a little bizzare
       // implying reset would latch data.
       status_remote_fault_d1 <= 0;
       status_local_fault_d1 <= 0;
    end
    else begin
 
        wb_int_o <= |(cpureg_int_pending & cpureg_int_mask);
 
        cpureg_int_pending <= cpureg_int_pending | int_sources;
 
        cpuack <= wb_cyc_i && wb_stb_i;
 
        status_remote_fault_d1 <= status_remote_fault;
        status_local_fault_d1 <= status_local_fault;
       
`ifdef MDIO
       // Handshake to MDIO state machine to reset running flag in status.
       // Wait for falling MDC edge to prevent S/W race condition occuring
       // where done flag still asserted but running flag now cleared (repeatedly).
       if (mdio_done && mdc_falling_edge)
	 mdio_running <= 0;

       // Register GPIO to allow regs placed in the I/O cells and provide some metastability prot
       xge_gpi_reg <= xge_gpi;
       xge_gpo <= xge_gpo_reg;
       

`endif
        //---
        // Read access
 
        if (wb_cyc_i && wb_stb_i && !wb_we_i) begin
 
            case ({wb_adr_i[7:2], 2'b0})
 
              `CPUREG_CONFIG0: begin
                  wb_dat_o <= {31'b0, cpureg_config0};
              end
 
              `CPUREG_INT_PENDING: begin
                  wb_dat_o <= {23'b0, cpureg_int_pending};
                  cpureg_int_pending <= int_sources;
                  wb_int_o <= 1'b0;
              end
 
              `CPUREG_INT_STATUS: begin
                  wb_dat_o <= {23'b0, int_sources};
              end
 
              `CPUREG_INT_MASK: begin
                  wb_dat_o <= {23'b0, cpureg_int_mask};
              end

 `ifdef MDIO
	      `CPUREG_MDIO_DATA: begin
		 wb_dat_o <= {16'b0, mdio_read_data};
	      end
	      
	      `CPUREG_MDIO_STATUS: begin
		 wb_dat_o <= {31'b0, mdio_running};
	      end

	      `CPUREG_GPIO: begin
		 wb_dat_o <= {24'b0, xge_gpi_reg};
	      end
	      
 `endif  
	      
              default: begin
              end
 
            endcase
 
        end
 
        //---
        // Write access
 
        if (wb_cyc_i && wb_stb_i && wb_we_i) begin
	   $display("reg write @ addr %x",({wb_adr_i[7:2], 2'b0}));
	   
            case ({wb_adr_i[7:2], 2'b0})
 
              `CPUREG_CONFIG0: begin
                  cpureg_config0 <= wb_dat_i[0:0];
              end
 
              `CPUREG_INT_PENDING: begin
                  cpureg_int_pending <= wb_dat_i[8:0] | cpureg_int_pending | int_sources;
              end
 
              `CPUREG_INT_MASK: begin
                  cpureg_int_mask <= wb_dat_i[8:0];
              end

`ifdef MDIO
	      `CPUREG_MDIO_DATA: begin
		 mdio_write_data <= wb_dat_i[15:0];
	      end

	       `CPUREG_MDIO_ADDR: begin
		 mdio_address <= wb_dat_i[15:0];
	       end
	      
	      `CPUREG_MDIO_OP: begin
		 mdio_operation <= wb_dat_i[12:0];
	       end

	      `CPUREG_MDIO_CONTROL: begin
		 // Trigger mdio operation here. Cleared by state machine at end of bus transaction.
		 if (wb_dat_i[0])
		   mdio_running <= 1;		 
	      end

	      `CPUREG_GPIO: begin
		 xge_gpo_reg <= wb_dat_i[7:0];
	       end
	      
`endif //  `ifdef MDIO
	       
              default: begin
              end
 
            endcase
 
        end
 
    end
 
end // always @ (posedge wb_clk_i or posedge wb_rst_i)

`ifdef MDIO
   //
   // Produce mdc clock as a signal synchronously from Wishbone clock.
   //
   always @(posedge wb_clk_i or posedge wb_rst_i)
     if (wb_rst_i)
       begin
	  mdc_clk_count <= 1;
	  mdc <= 0;
	  mdc_falling_edge <= 0;	  
       end
     else if (mdc_clk_count == `MDC_HALF_PERIOD)
       begin
	  mdc_clk_count <= 1;
	  mdc <= ~mdc;
	  mdc_falling_edge <= mdc;	  
       end
     else
       begin
	  mdc_clk_count <= mdc_clk_count + 1;
	  mdc_falling_edge <= 0;		   
       end
  
   //
   // MDIO state machine
   //
   always @(posedge wb_clk_i or posedge wb_rst_i)
     if (wb_rst_i)
       begin
	  mdio_tri <= 1;
	  mdio_out <= 0;
	  mdio_done <= 0;
	  mdio_read_data <= 0;
	  state <= IDLE;
       end
     else if (mdc_falling_edge)
       //
       // This is the MDIO bus controller. Use falling edge of MDC.
       //      
       begin
	  // Defaults	  
	  mdio_tri <= 1;
	  mdio_out <= 0;
	  mdio_done <= 0;
	  
	  
	  case(state)
	    // IDLE.
	    // In Clause 22 & 45 the master of the MDIO bus is tristate during idle.
	    // 
	    IDLE: begin
	       mdio_tri <= 1;
	       mdio_out <= 0;
	       if (mdio_running)
		 state <= PREAMBLE1;
	    end
	    // Preamble. All MDIO transactions begin witrh 32bits of 1 bits as a preamble.
	    PREAMBLE1: begin
	       mdio_tri <= 0;
	       mdio_out <= 1;  
	       state <= PREAMBLE2;
	    end
	    PREAMBLE2: begin
	       mdio_tri <= 0;
	       mdio_out <= 1;  
	       state <= PREAMBLE3;
	    end 
	    PREAMBLE3: begin
	       mdio_tri <= 0;
	       mdio_out <= 1;  
	       state <= PREAMBLE4;
	    end 
	    PREAMBLE4: begin
	       mdio_tri <= 0;
	       mdio_out <= 1;  
	       state <= PREAMBLE5;
	    end 
	    PREAMBLE5: begin
	       mdio_tri <= 0;
	       mdio_out <= 1;  
	       state <= PREAMBLE6;
	    end
	    PREAMBLE6: begin
	       mdio_tri <= 0;
	       mdio_out <= 1;  
	       state <= PREAMBLE7;
	    end
	    PREAMBLE7: begin
	       mdio_tri <= 0;
	       mdio_out <= 1;  
	       state <= PREAMBLE8;
	    end
	    PREAMBLE8: begin
	       mdio_tri <= 0;
	       mdio_out <= 1;
	       state <= PREAMBLE9;
	    end
	    PREAMBLE9: begin
	       mdio_tri <= 0;
	       mdio_out <= 1;
	       state <= PREAMBLE10;
	    end
	    PREAMBLE10: begin
	       mdio_tri <= 0;
	       mdio_out <= 1;
	       state <= PREAMBLE11;
	    end
	    PREAMBLE11: begin
	       mdio_tri <= 0;
	       mdio_out <= 1;  
	       state <= PREAMBLE12;
	    end
	    PREAMBLE12: begin
	       mdio_tri <= 0;
	       mdio_out <= 1;  
	       state <= PREAMBLE13;
	    end 
	    PREAMBLE13: begin
	       mdio_tri <= 0;
	       mdio_out <= 1;  
	       state <= PREAMBLE14;
	    end 
	    PREAMBLE14: begin
	       mdio_tri <= 0;
	       mdio_out <= 1;  
	       state <= PREAMBLE15;
	    end 
	    PREAMBLE15: begin
	       mdio_tri <= 0;
	       mdio_out <= 1;  
	       state <= PREAMBLE16;
	    end
	    PREAMBLE16: begin
	       mdio_tri <= 0;
	       mdio_out <= 1;  
	       state <= PREAMBLE17;
	    end
	    PREAMBLE17: begin
	       mdio_tri <= 0;
	       mdio_out <= 1;  
	       state <= PREAMBLE18;
	    end
	    PREAMBLE18: begin
	       mdio_tri <= 0;
	       mdio_out <= 1;
	       state <= PREAMBLE19;
	    end
	    PREAMBLE19: begin
	       mdio_tri <= 0;
	       mdio_out <= 1;
	       state <= PREAMBLE20;
	    end
	    PREAMBLE20: begin
	       mdio_tri <= 0;
	       mdio_out <= 1;
	       state <= PREAMBLE21;
	    end
	    PREAMBLE21: begin
	       mdio_tri <= 0;
	       mdio_out <= 1;  
	       state <= PREAMBLE22;
	    end
	    PREAMBLE22: begin
	       mdio_tri <= 0;
	       mdio_out <= 1;  
	       state <= PREAMBLE23;
	    end 
	    PREAMBLE23: begin
	       mdio_tri <= 0;
	       mdio_out <= 1;  
	       state <= PREAMBLE24;
	    end 
	    PREAMBLE24: begin
	       mdio_tri <= 0;
	       mdio_out <= 1;  
	       state <= PREAMBLE25;
	    end 
	    PREAMBLE25: begin
	       mdio_tri <= 0;
	       mdio_out <= 1;  
	       state <= PREAMBLE26;
	    end
	    PREAMBLE26: begin
	       mdio_tri <= 0;
	       mdio_out <= 1;  
	       state <= PREAMBLE27;
	    end
	    PREAMBLE27: begin
	       mdio_tri <= 0;
	       mdio_out <= 1;  
	       state <= PREAMBLE28;
	    end
	    PREAMBLE28: begin
	       mdio_tri <= 0;
	       mdio_out <= 1;
	       state <= PREAMBLE29;
	    end
	    PREAMBLE29: begin
	       mdio_tri <= 0;
	       mdio_out <= 1;
	       state <= PREAMBLE30;
	    end
	    PREAMBLE30: begin
	       mdio_tri <= 0;
	       mdio_out <= 1;
	       state <= PREAMBLE31;
	    end
	    PREAMBLE31: begin
	       mdio_tri <= 0;
	       mdio_out <= 1;
	       state <= PREAMBLE32;
	    end
	    PREAMBLE32: begin
	       mdio_tri <= 0;
	       mdio_out <= 1;
	       state <= START1;
	    end
	    //
	    // Start code for Clause 22 is 01 and Clause 45 is 00
	    //
	    START1: begin
	       mdio_tri <= 0;
	       mdio_out <= 0;
	       if (mdio_operation[12])
		 // Clause 45 bit set.
		 state <= C45_START2;
	       else
		 state <= C22_START2;	       
	    end
	    //
	    // 2nd Clause 22 start bit is a 1
	    //
	    C22_START2: begin
	       mdio_tri <= 0;
	       mdio_out <= 1;
	       state <= OP1;
	    end
	    //
	    // 2nd Clause 45 start bit is a 0
	    //
	    C45_START2: begin
	       mdio_tri <= 0;
	       mdio_out <= 0;
	       state <= OP1;
	    end
	    //
	    // Both Clause 22 & 45 use 2 bits for operation and are compatable.
	    // Note we don't screen here for illegal Clause 22 ops.
	    //
	    OP1: begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_operation[11];
	       state <= OP2;
	    end
	    OP2: begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_operation[10];
	       state <= PRTAD1;
	    end
	    //
	    // Both Clause 22 & 45 use 2 sucsessive 5 bit fields to form a hierarchical address
	    // though it's used slightly different between the 2 standards.
	    //
	    PRTAD1: begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_operation[9];
	       state <= PRTAD2;	       
	    end
	    PRTAD2: begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_operation[8];
	       state <= PRTAD3;	       
	    end
	    PRTAD3: begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_operation[7];
	       state <= PRTAD4;	       
	    end
	    PRTAD4: begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_operation[6];
	       state <= PRTAD5;	       
	    end
	    PRTAD5: begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_operation[5];
	       state <= DEVAD1;	       
	    end
	    DEVAD1: begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_operation[4];
	       state <= DEVAD2;	       
	    end
	    DEVAD2: begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_operation[3];
	       state <= DEVAD3;	       
	    end
	    DEVAD3: begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_operation[2];
	       state <= DEVAD4;	       
	    end
	    DEVAD4: begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_operation[1];
	       state <= DEVAD5;	       
	    end
	    DEVAD5: begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_operation[0];
	       state <= TA1;	       
	    end
	    //
	    // Both Clause 22 & Clause 45 use the same turn around on the bus.
	    // Reads have Z as the first bit and 0 driven by the slave for the 2nd bit.
	    // Note that slaves drive the bus on the rising edge of MDC.
	    // Writes and Address cycles have 10 driven by the master.
	    //
	    TA1: begin
	       if (mdio_operation[11] == 0) // Write/Address
		 begin
		    mdio_tri <= 0;
		    mdio_out <= 1;
		    state <= TA2;
		 end
	       else // Read
		 begin
		    mdio_tri <= 1;
		    state <= TA3;
		 end
	    end
	    TA2: begin
	       mdio_tri <= 0;
	       mdio_out <= 0;
	       if (!mdio_operation[12]) // Clause 22 Write
		 state <= WRITE1;
	       else if (mdio_operation[10]) // Clause 45 Write
		 state <= WRITE1;
	       else // Clause 45 ADDRESS
		 state <= C45_ADDR1;
	    end
	    TA3: begin
	       mdio_tri <= 1;
	       state <= READ1;
	    end
	    //
	    // Clause 22 Reads and both forms of clause 45 Reads have the same bus transaction from here out.
	    //
	    READ1: begin
	       mdio_tri <= 1;	
	       mdio_read_data[15] <= mdio_in;
	       state <= READ2;	    
	    end
	    READ2: begin
	       mdio_tri <= 1;	
	       mdio_read_data[14] <= mdio_in;
	       state <= READ3;	    
	    end
	    READ3: begin
	       mdio_tri <= 1;	
	       mdio_read_data[13] <= mdio_in;
	       state <= READ4;	    
	    end
	    READ4: begin
	       mdio_tri <= 1;	
	       mdio_read_data[12] <= mdio_in;
	       state <= READ5;	    
	    end
	    READ5: begin
	       mdio_tri <= 1;	
	       mdio_read_data[11] <= mdio_in;
	       state <= READ6;	    
	    end
	    READ6: begin
	       mdio_tri <= 1;	
	       mdio_read_data[10] <= mdio_in;
	       state <= READ7;	    
	    end
	    READ7: begin
	       mdio_tri <= 1;	
	       mdio_read_data[9] <= mdio_in;
	       state <= READ8;	    
	    end
	    READ8: begin
	       mdio_tri <= 1;	
	       mdio_read_data[8] <= mdio_in;
	       state <= READ9;	    
	    end
	    READ9: begin
	       mdio_tri <= 1;	
	       mdio_read_data[7] <= mdio_in;
	       state <= READ10;	    
	    end
	    READ10: begin
	       mdio_tri <= 1;	
	       mdio_read_data[6] <= mdio_in;
	       state <= READ11;	    
	    end
	    READ11: begin
	       mdio_tri <= 1;	
	       mdio_read_data[5] <= mdio_in;
	       state <= READ12;	    
	    end
	    READ12: begin
	       mdio_tri <= 1;	
	       mdio_read_data[4] <= mdio_in;
	       state <= READ13;	    
	    end
	    READ13: begin
	       mdio_tri <= 1;	
	       mdio_read_data[3] <= mdio_in;
	       state <= READ14;	    
	    end
	    READ14: begin
	       mdio_tri <= 1;	
	       mdio_read_data[2] <= mdio_in;
	       state <= READ15;	    
	    end
	    READ15: begin
	       mdio_tri <= 1;	
	       mdio_read_data[1] <= mdio_in;
	       state <= READ16;	    
	    end
	    READ16: begin
	       mdio_tri <= 1;	
	       mdio_read_data[0] <= mdio_in;
	       state <= PREIDLE;	 
	       mdio_done <= 1;	          
	    end	    
	    //
	    // Write 16bits of data for all types of Write.
	    //
	    WRITE1:begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_write_data[15];
	       state <= WRITE2;
	    end
	    WRITE2:begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_write_data[14];
	       state <= WRITE3;
	    end
	    WRITE3:begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_write_data[13];
	       state <= WRITE4;
	    end
	    WRITE4:begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_write_data[12];
	       state <= WRITE5;
	    end
	    WRITE5:begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_write_data[11];
	       state <= WRITE6;
	    end
	    WRITE6:begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_write_data[10];
	       state <= WRITE7;
	    end
	    WRITE7:begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_write_data[9];
	       state <= WRITE8;
	    end
	    WRITE8:begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_write_data[8];
	       state <= WRITE9;
	    end
	    WRITE9:begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_write_data[7];
	       state <= WRITE10;
	    end
	    WRITE10:begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_write_data[6];
	       state <= WRITE11;
	    end
	    WRITE11:begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_write_data[5];
	       state <= WRITE12;
	    end
	    WRITE12:begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_write_data[4];
	       state <= WRITE13;
	    end
	    WRITE13:begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_write_data[3];
	       state <= WRITE14;
	    end
	    WRITE14:begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_write_data[2];
	       state <= WRITE15;
	    end
	    WRITE15:begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_write_data[1];
	       state <= WRITE16;
	    end
	    WRITE16:begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_write_data[0];
	       state <= PREIDLE;
	       mdio_done <= 1;	       
	    end
	    //
	    // Write 16bits of address for a Clause 45 Address transaction
	    //
	    C45_ADDR1:begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_address[15];
	       state <= C45_ADDR2;
	    end
	    C45_ADDR2:begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_address[14];
	       state <= C45_ADDR3;
	    end
	    C45_ADDR3:begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_address[13];
	       state <= C45_ADDR4;
	    end
	    C45_ADDR4:begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_address[12];
	       state <= C45_ADDR5;
	    end
	    C45_ADDR5:begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_address[11];
	       state <= C45_ADDR6;
	    end
	    C45_ADDR6:begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_address[10];
	       state <= C45_ADDR7;
	    end
	    C45_ADDR7:begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_address[9];
	       state <= C45_ADDR8;
	    end
	    C45_ADDR8:begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_address[8];
	       state <= C45_ADDR9;
	    end
	    C45_ADDR9:begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_address[7];
	       state <= C45_ADDR10;
	    end
	    C45_ADDR10:begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_address[6];
	       state <= C45_ADDR11;
	    end
	    C45_ADDR11:begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_address[5];
	       state <= C45_ADDR12;
	    end
	    C45_ADDR12:begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_address[4];
	       state <= C45_ADDR13;
	    end
	    C45_ADDR13:begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_address[3];
	       state <= C45_ADDR14;
	    end
	    C45_ADDR14:begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_address[2];
	       state <= C45_ADDR15;
	    end
	    C45_ADDR15:begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_address[1];
	       state <= C45_ADDR16;
	    end
	    C45_ADDR16:begin
	       mdio_tri <= 0;
	       mdio_out <= mdio_address[0];
	       state <= PREIDLE;
	       mdio_done <= 1;	       
	    end
	    //
	    // PREIDLE allows the mdio_running bit to reset.
	    //
	    PREIDLE: begin
	       state <= IDLE;
	    end
	  endcase // case(state)
	  
       end // if (mdc_falling_edge)


   
`endif //  ifdef MDIO
		   
endmodule