zynq-sandbox

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit 336e64a11c05c140869de796d479a5dfe7036c10
parent 527a60a15a47846538e2f0532a1941877c9c2ab0
Author: Brian Swetland <swetland@frotz.net>
Date:   Tue, 22 Jul 2014 07:39:01 -0700

ethernet mdio master

Diffstat:
Ahdl/eth_mdio.sv | 159+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ahdl/test/eth_mdio_test.sv | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 219 insertions(+), 0 deletions(-)

diff --git a/hdl/eth_mdio.sv b/hdl/eth_mdio.sv @@ -0,0 +1,159 @@ +// Copyright 2014 Brian Swetland <swetland@frotz.net> +// +// 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. + +`timescale 1ns / 1ps + +module eth_mdio( + input clk, + + input do_read, + input do_write, + input [31:0]txdata, + output [15:0]rxdata, + output reg busy = 0, + + input i_mdio, + output o_mdio, + output t_mdio, + output reg mdc = 0 + ); + +parameter CLKDIV = 16; + +// ST OP PHYAD REGAD TA DATA IDLE +// PRE 11 11 11111 11111 11 1111111111111111 Z +// READ 01 10 AAAAA RRRRR Z0 DDDDDDDDDDDDDDDD Z // 6 +// WRITE 01 01 AAAAA RRRRR 10 DDDDDDDDDDDDDDDD Z // 5 + +// on phase entry: +// ------------------------- +// .-----. A mdc=0 shift +// | | B mdc=1 +// --' '-- C mdc=1 capture=i_mdio +// A B C D D mdc=0 +// +// always: o_mdio=shift[31] + +typedef enum { IDLE, PHA, PHB, PHC, PHD } state_t; +state_t state = IDLE; +state_t next_state; + +reg next_busy; +reg next_mdc; + +reg [31:0]shift = 0; +reg [31:0]next_shift; +reg [4:0]count = 0; +reg [4:0]next_count; +reg [7:0]clkcnt = 0; +reg [7:0]next_clkcnt; +reg capture0 = 0; +reg next_capture0; +reg capture1 = 0; +reg next_capture1; +reg tristate = 1; +reg next_tristate; +reg op_read = 0; +reg next_op_read; + +reg step; + +assign o_mdio = shift[31]; +assign t_mdio = tristate; +assign rxdata = shift[16:1]; + +always_comb begin + next_tristate = tristate; + next_capture0 = capture0; + next_capture1 = capture1; + next_clkcnt = clkcnt; + next_count = count; + next_op_read = op_read; + next_state = state; + next_shift = shift; + next_busy = busy; + next_mdc = mdc; + step = 0; + + // while txn active, count clocks and advance + // phases every CLKDIV clocks + if (busy) begin + if (clkcnt == CLKDIV) begin + next_clkcnt = 0; + step = 1; + end else begin + next_clkcnt = clkcnt + 1; + step = 0; + end + // debounce input + next_capture0 = i_mdio; + end + + case (state) + IDLE: if (do_read | do_write) begin + next_state = PHA; + next_mdc = 0; + next_busy = 1; + next_tristate = 0; + next_count = 31; + next_shift = txdata; + next_op_read = do_read; + end + PHA: if (step) begin + next_state = PHB; + next_mdc = 1; + end + PHB: if (step) begin + next_state = PHC; + next_mdc = 1; + // acquire debounced input + next_capture1 = capture0; + end + PHC: if (step) begin + next_state = PHD; + next_mdc = 0; + end + PHD: if (step) begin + next_shift = { shift[30:0], capture1 }; + if (op_read & (count == 18)) begin + next_tristate = 1; + end + if (count == 0) begin + next_state = IDLE; + next_tristate = 1; + next_busy = 0; + end else begin + next_state = PHA; + next_count = count - 1; + end + end + default: next_state = IDLE; + endcase +end + +always_ff @(posedge clk) begin + tristate <= next_tristate; + capture0 <= next_capture0; + capture1 <= next_capture1; + op_read <= next_op_read; + clkcnt <= next_clkcnt; + state <= next_state; + shift <= next_shift; + count <= next_count; + busy <= next_busy; + mdc <= next_mdc; +end + +endmodule + diff --git a/hdl/test/eth_mdio_test.sv b/hdl/test/eth_mdio_test.sv @@ -0,0 +1,60 @@ +// Copyright 2014 Brian Swetland <swetland@frotz.net> +// +// 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. + +`timescale 1ns / 1ps + +module testbench(input clk); + +reg do_read = 0; +reg do_write = 0; +reg [31:0]txdata = 32'h80AA0123; +wire [15:0]rxdata; +wire busy; +wire o_dat; +wire t_dat; +wire o_clk; +reg i_raw = 0; +wire i_dat = t_dat ? i_raw : o_dat; + +eth_mdio mdio0( + .clk(clk), + .do_read(do_read), + .do_write(do_write), + .txdata(txdata), + .rxdata(rxdata), + .busy(busy), + .i_mdio(i_dat), + .o_mdio(o_dat), + .t_mdio(t_dat), + .mdc(o_clk) + ); + +integer count = 0; +reg next_rd; +reg next_wr; + +always_comb begin + next_rd = 0; + next_wr = 0; + if (count == 32768) $finish; + if (count == 32) next_rd = 1; +end + +always @(posedge clk) begin + count <= count + 1; + do_read <= next_rd; + do_write <= next_wr; +end + +endmodule