mii_io: Add isolation support
The specification requires that the MII be isolated before the STA clears the BMCR.ISOLATE bit. Add support for this to the MII I/O modules. Signed-off-by: Sean Anderson <seanga2@gmail.com>
This commit is contained in:
parent
ead545e85e
commit
fb751eb7fb
|
@ -7,8 +7,10 @@
|
||||||
`include "io.vh"
|
`include "io.vh"
|
||||||
|
|
||||||
module mii_io_rx (
|
module mii_io_rx (
|
||||||
/* On-chip */
|
|
||||||
input clk,
|
input clk,
|
||||||
|
input isolate,
|
||||||
|
|
||||||
|
/* On-chip */
|
||||||
input ce,
|
input ce,
|
||||||
input valid,
|
input valid,
|
||||||
input err,
|
input err,
|
||||||
|
@ -56,28 +58,31 @@ module mii_io_rx (
|
||||||
|
|
||||||
`ifdef SYNTHESIS
|
`ifdef SYNTHESIS
|
||||||
SB_IO #(
|
SB_IO #(
|
||||||
.PIN_TYPE(`PIN_OUTPUT_ALWAYS | `PIN_OUTPUT_DDR)
|
.PIN_TYPE(`PIN_OUTPUT_ENABLE | `PIN_OUTPUT_DDR)
|
||||||
) rx_clk_pin (
|
) rx_clk_pin (
|
||||||
.PACKAGE_PIN(rx_clk),
|
.PACKAGE_PIN(rx_clk),
|
||||||
.OUTPUT_CLK(clk),
|
.OUTPUT_CLK(clk),
|
||||||
|
.OUTPUT_ENABLE(!isolate),
|
||||||
.D_OUT_0(rx_clk_p_next),
|
.D_OUT_0(rx_clk_p_next),
|
||||||
.D_OUT_1(rx_clk_n)
|
.D_OUT_1(rx_clk_n)
|
||||||
);
|
);
|
||||||
|
|
||||||
SB_IO #(
|
SB_IO #(
|
||||||
.PIN_TYPE(`PIN_OUTPUT_ALWAYS | `PIN_OUTPUT_REGISTERED)
|
.PIN_TYPE(`PIN_OUTPUT_ENABLE | `PIN_OUTPUT_REGISTERED)
|
||||||
) rx_dv_pin (
|
) rx_dv_pin (
|
||||||
.PACKAGE_PIN(rx_dv),
|
.PACKAGE_PIN(rx_dv),
|
||||||
.CLOCK_ENABLE(ce),
|
.CLOCK_ENABLE(ce),
|
||||||
|
.OUTPUT_ENABLE(!isolate),
|
||||||
.OUTPUT_CLK(clk),
|
.OUTPUT_CLK(clk),
|
||||||
.D_OUT_0(valid)
|
.D_OUT_0(valid)
|
||||||
);
|
);
|
||||||
|
|
||||||
SB_IO #(
|
SB_IO #(
|
||||||
.PIN_TYPE(`PIN_OUTPUT_ALWAYS | `PIN_OUTPUT_REGISTERED)
|
.PIN_TYPE(`PIN_OUTPUT_ENABLE | `PIN_OUTPUT_REGISTERED)
|
||||||
) rx_er_pin (
|
) rx_er_pin (
|
||||||
.PACKAGE_PIN(rx_er),
|
.PACKAGE_PIN(rx_er),
|
||||||
.CLOCK_ENABLE(ce),
|
.CLOCK_ENABLE(ce),
|
||||||
|
.OUTPUT_ENABLE(!isolate),
|
||||||
.OUTPUT_CLK(clk),
|
.OUTPUT_CLK(clk),
|
||||||
.D_OUT_0(err)
|
.D_OUT_0(err)
|
||||||
);
|
);
|
||||||
|
@ -85,10 +90,11 @@ module mii_io_rx (
|
||||||
genvar i;
|
genvar i;
|
||||||
generate for (i = 0; i < 4; i = i + 1) begin
|
generate for (i = 0; i < 4; i = i + 1) begin
|
||||||
SB_IO #(
|
SB_IO #(
|
||||||
.PIN_TYPE(`PIN_OUTPUT_ALWAYS | `PIN_OUTPUT_REGISTERED)
|
.PIN_TYPE(`PIN_OUTPUT_ENABLE | `PIN_OUTPUT_REGISTERED)
|
||||||
) rxd_pin (
|
) rxd_pin (
|
||||||
.PACKAGE_PIN(rxd[i]),
|
.PACKAGE_PIN(rxd[i]),
|
||||||
.CLOCK_ENABLE(ce),
|
.CLOCK_ENABLE(ce),
|
||||||
|
.OUTPUT_ENABLE(!isolate),
|
||||||
.OUTPUT_CLK(clk),
|
.OUTPUT_CLK(clk),
|
||||||
.D_OUT_0(data[i])
|
.D_OUT_0(data[i])
|
||||||
);
|
);
|
||||||
|
@ -96,16 +102,23 @@ module mii_io_rx (
|
||||||
endgenerate
|
endgenerate
|
||||||
`else
|
`else
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) begin
|
||||||
rx_clk <= rx_clk_p_next;
|
if (isolate) begin
|
||||||
if (ce) begin
|
rx_dv <= 1'bz;
|
||||||
|
rx_er <= 1'bz;
|
||||||
|
rxd <= 4'bz;
|
||||||
|
end else if (ce) begin
|
||||||
rx_dv <= valid;
|
rx_dv <= valid;
|
||||||
rx_er <= err;
|
rx_er <= err;
|
||||||
rxd <= data;
|
rxd <= data;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
always @(negedge clk)
|
always @(posedge clk, negedge clk) begin
|
||||||
rx_clk <= rx_clk_n;
|
if (isolate)
|
||||||
|
rx_clk <= 1'bz;
|
||||||
|
else
|
||||||
|
rx_clk <= clk ? rx_clk_p_next : rx_clk_n;
|
||||||
|
end
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
`DUMP(0)
|
`DUMP(0)
|
||||||
|
|
|
@ -7,8 +7,10 @@
|
||||||
`include "io.vh"
|
`include "io.vh"
|
||||||
|
|
||||||
module mii_io_tx (
|
module mii_io_tx (
|
||||||
/* On-chip */
|
|
||||||
input clk,
|
input clk,
|
||||||
|
input isolate,
|
||||||
|
|
||||||
|
/* On-chip */
|
||||||
output reg ce,
|
output reg ce,
|
||||||
output reg enable,
|
output reg enable,
|
||||||
output reg err,
|
output reg err,
|
||||||
|
@ -21,7 +23,7 @@ module mii_io_tx (
|
||||||
input [3:0] txd
|
input [3:0] txd
|
||||||
);
|
);
|
||||||
|
|
||||||
reg ce_next;
|
reg ce_next, raw_enable;
|
||||||
reg tx_clk_p_next, tx_clk_n, tx_clk_n_next;
|
reg tx_clk_p_next, tx_clk_n, tx_clk_n_next;
|
||||||
reg [2:0] counter, counter_next;
|
reg [2:0] counter, counter_next;
|
||||||
/* I have no idea why we need to use initial... */
|
/* I have no idea why we need to use initial... */
|
||||||
|
@ -44,6 +46,8 @@ module mii_io_tx (
|
||||||
counter_next = 4;
|
counter_next = 4;
|
||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
|
|
||||||
|
enable = raw_enable && !isolate;
|
||||||
end
|
end
|
||||||
|
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) begin
|
||||||
|
@ -54,10 +58,11 @@ module mii_io_tx (
|
||||||
|
|
||||||
`ifdef SYNTHESIS
|
`ifdef SYNTHESIS
|
||||||
SB_IO #(
|
SB_IO #(
|
||||||
.PIN_TYPE(`PIN_OUTPUT_ALWAYS | `PIN_OUTPUT_DDR)
|
.PIN_TYPE(`PIN_OUTPUT_ENABLE | `PIN_OUTPUT_DDR)
|
||||||
) tx_clk_pin (
|
) tx_clk_pin (
|
||||||
.PACKAGE_PIN(tx_clk),
|
.PACKAGE_PIN(tx_clk),
|
||||||
.OUTPUT_CLK(clk),
|
.OUTPUT_CLK(clk),
|
||||||
|
.OUTPUT_ENABLE(!isolate),
|
||||||
.D_OUT_0(tx_clk_p_next),
|
.D_OUT_0(tx_clk_p_next),
|
||||||
.D_OUT_1(tx_clk_n)
|
.D_OUT_1(tx_clk_n)
|
||||||
);
|
);
|
||||||
|
@ -68,7 +73,7 @@ module mii_io_tx (
|
||||||
.PACKAGE_PIN(tx_en),
|
.PACKAGE_PIN(tx_en),
|
||||||
.CLOCK_ENABLE(ce_next),
|
.CLOCK_ENABLE(ce_next),
|
||||||
.INPUT_CLK(clk),
|
.INPUT_CLK(clk),
|
||||||
.D_IN_0(enable)
|
.D_IN_0(raw_enable)
|
||||||
);
|
);
|
||||||
|
|
||||||
SB_IO #(
|
SB_IO #(
|
||||||
|
@ -94,16 +99,19 @@ module mii_io_tx (
|
||||||
endgenerate
|
endgenerate
|
||||||
`else
|
`else
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) begin
|
||||||
tx_clk <= tx_clk_p_next;
|
|
||||||
if (ce_next) begin
|
if (ce_next) begin
|
||||||
enable <= tx_en;
|
raw_enable <= tx_en;
|
||||||
err <= tx_er;
|
err <= tx_er;
|
||||||
data <= txd;
|
data <= txd;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
always @(negedge clk)
|
always @(posedge clk, negedge clk) begin
|
||||||
tx_clk <= tx_clk_n;
|
if (isolate)
|
||||||
|
tx_clk <= 1'bz;
|
||||||
|
else
|
||||||
|
tx_clk <= clk ? tx_clk_p_next : tx_clk_n;
|
||||||
|
end
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
`DUMP(0)
|
`DUMP(0)
|
||||||
|
|
|
@ -12,10 +12,11 @@ from .util import ClockEnable
|
||||||
|
|
||||||
@cocotb.test(timeout_time=500, timeout_unit='ns')
|
@cocotb.test(timeout_time=500, timeout_unit='ns')
|
||||||
async def test_io(io):
|
async def test_io(io):
|
||||||
|
io.isolate.value = 0
|
||||||
|
io.ce.value = 0
|
||||||
io.valid.value = LogicArray('X')
|
io.valid.value = LogicArray('X')
|
||||||
io.err.value = LogicArray('X')
|
io.err.value = LogicArray('X')
|
||||||
io.data.value = LogicArray('X' * 4)
|
io.data.value = LogicArray('X' * 4)
|
||||||
io.ce.value = 0
|
|
||||||
await Timer(1)
|
await Timer(1)
|
||||||
await cocotb.start(Clock(io.clk, 8, units='ns').start())
|
await cocotb.start(Clock(io.clk, 8, units='ns').start())
|
||||||
await ClockCycles(io.clk, 1)
|
await ClockCycles(io.clk, 1)
|
||||||
|
@ -78,3 +79,10 @@ async def test_io(io):
|
||||||
await recv_datum(0, 1, 8)
|
await recv_datum(0, 1, 8)
|
||||||
await recv_datum(1, 0, 9)
|
await recv_datum(1, 0, 9)
|
||||||
await recv_datum(0, 1, 10)
|
await recv_datum(0, 1, 10)
|
||||||
|
|
||||||
|
io.isolate.value = 1
|
||||||
|
await FallingEdge(io.clk)
|
||||||
|
assert io.rx_clk.value.binstr == 'z'
|
||||||
|
assert io.rx_dv.value.binstr == 'z'
|
||||||
|
assert io.rx_er.value.binstr == 'z'
|
||||||
|
assert io.rxd.value.binstr == 'zzzz'
|
||||||
|
|
|
@ -12,6 +12,7 @@ from .util import ClockEnable
|
||||||
|
|
||||||
@cocotb.test(timeout_time=500, timeout_unit='ns')
|
@cocotb.test(timeout_time=500, timeout_unit='ns')
|
||||||
async def test_io(io):
|
async def test_io(io):
|
||||||
|
io.isolate.value = 0
|
||||||
io.tx_en.value = LogicArray('X')
|
io.tx_en.value = LogicArray('X')
|
||||||
io.tx_er.value = LogicArray('X')
|
io.tx_er.value = LogicArray('X')
|
||||||
io.txd.value = LogicArray('X' * 4)
|
io.txd.value = LogicArray('X' * 4)
|
||||||
|
@ -49,3 +50,10 @@ async def test_io(io):
|
||||||
await recv_datum(0, 1, 3)
|
await recv_datum(0, 1, 3)
|
||||||
await recv_datum(1, 0, 4)
|
await recv_datum(1, 0, 4)
|
||||||
await recv_datum(0, 1, 5)
|
await recv_datum(0, 1, 5)
|
||||||
|
|
||||||
|
io.isolate.value = 1
|
||||||
|
io.tx_en.value = 1
|
||||||
|
await RisingEdge(io.clk)
|
||||||
|
assert io.tx_clk.value.binstr == 'z'
|
||||||
|
await RisingEdge(io.ce)
|
||||||
|
assert not io.enable.value
|
||||||
|
|
Loading…
Reference in New Issue