From 798968d3d68862e683e7f4173a2e60225c15aa74 Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Sat, 14 Jan 2023 00:08:38 -0500 Subject: [PATCH] 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 --- rtl/axis_mii_tx.v | 15 +++++++++++---- tb/axis_mii_tx.py | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/rtl/axis_mii_tx.v b/rtl/axis_mii_tx.v index ca7c5ba..278cd69 100644 --- a/rtl/axis_mii_tx.v +++ b/rtl/axis_mii_tx.v @@ -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 diff --git a/tb/axis_mii_tx.py b/tb/axis_mii_tx.py index 15571cd..b397968 100644 --- a/tb/axis_mii_tx.py +++ b/tb/axis_mii_tx.py @@ -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