axis_mii_tx: Add support for half duplex

This adds support for half-duplex. This is mostly done by predicating
col and crs on half_duplex. In one place we need to go to IPG_LATE
directly (although we could go to IPG_LATE like FCS with no loss of
standard compliance).

Signed-off-by: Sean Anderson <seanga2@gmail.com>
This commit is contained in:
Sean Anderson 2023-01-14 00:08:38 -05:00
parent 2fd6dedddb
commit 798968d3d6
2 changed files with 29 additions and 4 deletions

View File

@ -37,6 +37,8 @@ module axis_mii_tx (
/* Use a slot time of one octet for backoff; test purposes only */
input short_backoff,
/* Enable Half-Duplex */
input half_duplex,
/* Clause 4 TransmitStatus */
output reg transmit_ok,
@ -237,7 +239,7 @@ module axis_mii_tx (
replay_next = 0;
done_next = 0;
retries_next = retries;
collision_next = collision || mii_col;
collision_next = collision || (half_duplex && mii_col);
case (state)
IPG_EARLY: begin
collision_next = 0;
@ -262,7 +264,7 @@ module axis_mii_tx (
if (buf_valid) begin
state_next = PREAMBLE;
state_counter_next = PREAMBLE_BYTES - 1;
end else if (mii_crs) begin
end else if (half_duplex && mii_crs) begin
state_next = IPG_EARLY;
state_counter_next = IPG_EARLY_BYTES - 1;
end
@ -472,8 +474,13 @@ module axis_mii_tx (
end
DRAIN: begin
if (buf_ready && buf_valid && buf_last) begin
state_next = IPG_EARLY;
state_counter_next = IPG_EARLY_BYTES - 1;
if (half_duplex) begin
state_next = IPG_EARLY;
state_counter_next = IPG_EARLY_BYTES - 1;
end else begin
state_next = IPG_LATE;
state_counter_next = IPG_BYTES - 1;
end
end else begin
buf_ready_next = 1;
end

View File

@ -28,6 +28,7 @@ async def init(mac):
mac.axis_valid.value = 0
mac.axis_err.value = 0
mac.short_backoff.value = 1
mac.half_duplex.value = 1
await Timer(1)
mac.rst.value = 0
await cocotb.start(Clock(mac.clk, 8, units='ns').start())
@ -325,3 +326,20 @@ async def test_collision(mac):
await late(mac, packet, 64 * BYTE_TIME_NS)
await late(mac, packet, randtime(64, 256))
await late(mac, packet, 72 * BYTE_TIME_NS - 1)
@cocotb.test(timeout_time=10, timeout_unit='us')
async def test_full_duplex(mac):
await init(mac)
mac.half_duplex.value = 0
# Skip to the end of IPG_LATE
await Timer(13 * BYTE_TIME_NS, 'ns')
mac.mii_crs.value = 1
packet = list(range(32))
send, status = await start(mac, packet)
recv = await cocotb.start(ok(mac, packet, status, 16 * BYTE_TIME_NS))
# No deferral
await Timer(13 * BYTE_TIME_NS, 'ns')
assert mac.mii_tx_en.value
# No collision
await recv