2022-08-27 15:00:37 -05:00
|
|
|
// SPDX-License-Identifier: AGPL-3.0-Only
|
|
|
|
/*
|
|
|
|
* Copyright (C) 2022 Sean Anderson <seanga2@gmail.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
`include "common.vh"
|
|
|
|
`include "io.vh"
|
|
|
|
|
|
|
|
module mdio_io (
|
|
|
|
input clk,
|
|
|
|
|
|
|
|
input mdc,
|
|
|
|
inout mdio,
|
|
|
|
output reg mdio_oe,
|
|
|
|
|
|
|
|
input mdo,
|
|
|
|
input mdo_valid,
|
|
|
|
output reg ce,
|
|
|
|
output reg mdi
|
|
|
|
);
|
|
|
|
|
|
|
|
wire ce_next;
|
|
|
|
reg mdi_next;
|
|
|
|
reg [1:0] last_mdc;
|
|
|
|
/* Two clock delay to allow the level shifter to reverse direction */
|
2022-10-16 16:46:04 -05:00
|
|
|
reg [2:0] oe;
|
|
|
|
initial oe = 0;
|
2022-08-27 15:00:37 -05:00
|
|
|
|
|
|
|
`ifdef SYNTHESIS
|
|
|
|
SB_IO #(
|
|
|
|
.PIN_TYPE(`PIN_OUTPUT_NEVER | `PIN_INPUT_REGISTERED)
|
|
|
|
) mdc_pin (
|
|
|
|
.PACKAGE_PIN(mdc),
|
|
|
|
.INPUT_CLK(clk),
|
|
|
|
.D_IN_0(last_mdc[0])
|
|
|
|
);
|
|
|
|
|
|
|
|
SB_IO #(
|
|
|
|
.PIN_TYPE(`PIN_OUTPUT_REGISTERED | `PIN_OUTPUT_ENABLE | `PIN_INPUT_REGISTERED)
|
|
|
|
) mdio_pin (
|
|
|
|
.PACKAGE_PIN(mdio),
|
|
|
|
.INPUT_CLK(clk),
|
|
|
|
.OUTPUT_CLK(clk),
|
|
|
|
.OUTPUT_ENABLE(oe[2]),
|
|
|
|
.D_OUT_0(mdo),
|
|
|
|
.D_IN_0(mdi_next),
|
|
|
|
);
|
|
|
|
|
|
|
|
SB_IO #(
|
|
|
|
.PIN_TYPE(`PIN_OUTPUT_ALWAYS | `PIN_OUTPUT_REGISTERED)
|
|
|
|
) mdio_oe_pin (
|
|
|
|
.PACKAGE_PIN(mdio_oe),
|
|
|
|
.OUTPUT_CLK(clk),
|
|
|
|
.D_OUT_0(mdo_valid),
|
|
|
|
);
|
|
|
|
`else
|
|
|
|
reg mdio_next;
|
|
|
|
|
|
|
|
always @(posedge clk) begin
|
|
|
|
last_mdc[0] <= mdc;
|
|
|
|
mdi_next <= mdio;
|
|
|
|
mdio_next <= mdo;
|
|
|
|
mdio_oe <= mdo_valid;
|
|
|
|
end
|
|
|
|
|
|
|
|
assign mdio = oe[2] ? mdio_next : 1'bZ;
|
|
|
|
`endif
|
|
|
|
|
|
|
|
assign ce_next = last_mdc[0] && !last_mdc[1];
|
|
|
|
|
|
|
|
always @(posedge clk) begin
|
|
|
|
mdi <= mdi_next;
|
|
|
|
last_mdc[1] <= last_mdc[0];
|
|
|
|
ce <= ce_next;
|
|
|
|
if (mdo_valid)
|
|
|
|
oe <= { oe[1:0], mdo_valid };
|
|
|
|
else
|
|
|
|
oe <= 0;
|
|
|
|
end
|
|
|
|
|
|
|
|
endmodule
|