17 Commits

Author SHA1 Message Date
Alex Forencich
2bfe8a0e50 Release v0.1.20
Signed-off-by: Alex Forencich <alex@alexforencich.com>
2023-01-25 18:51:37 -08:00
Alex Forencich
9c88b0440e Update package versions
Signed-off-by: Alex Forencich <alex@alexforencich.com>
2023-01-25 18:28:32 -08:00
Alex Forencich
37b23c358b Put sources and sinks to sleep when idle
Signed-off-by: Alex Forencich <alex@alexforencich.com>
2023-01-24 17:42:05 -08:00
Alex Forencich
dd35d734f9 Put sources and sinks to sleep based on clock enables
Signed-off-by: Alex Forencich <alex@alexforencich.com>
2023-01-24 17:41:36 -08:00
Alex Forencich
45ee1193cb Remove deprecated assignments
Signed-off-by: Alex Forencich <alex@alexforencich.com>
2023-01-24 17:41:12 -08:00
Alex Forencich
5caafbb9e7 Update package versions
Signed-off-by: Alex Forencich <alex@alexforencich.com>
2023-01-24 12:54:08 -08:00
Alex Forencich
2d4450e048 Fix path issue so latest coverage works
Signed-off-by: Alex Forencich <alex@alexforencich.com>
2023-01-20 20:58:13 -08:00
Alex Forencich
c5d28182c4 Update github actions versions
Signed-off-by: Alex Forencich <alex@alexforencich.com>
2023-01-20 15:38:05 -08:00
Alex Forencich
79991205b5 Fix tox config and lock package versions
Signed-off-by: Alex Forencich <alex@alexforencich.com>
2023-01-20 15:37:51 -08:00
Alex Forencich
a22123649c Python 3.6 is EOL; remove from CI tests
Signed-off-by: Alex Forencich <alex@alexforencich.com>
2023-01-18 17:53:30 -08:00
Alex Forencich
b5ba332ecc Specify min package versions 2021-12-27 17:17:40 -08:00
Alex Forencich
eb62e43fd1 Specify min tox and venv versions 2021-12-27 17:17:15 -08:00
Alex Forencich
5c4ef258ac Skip missing interpreters 2021-12-27 17:16:20 -08:00
Alex Forencich
6c5845fad3 Test on Python 3.10 2021-12-27 17:15:11 -08:00
Alex Forencich
32f6e449c0 Use start_soon instead of fork 2021-12-08 21:45:58 -08:00
Alex Forencich
2af7852006 Cache clock edge event objects 2021-12-03 19:06:43 -08:00
Alex Forencich
3325568406 Bump to dev version 2021-11-07 13:19:10 -08:00
20 changed files with 281 additions and 124 deletions

View File

@@ -9,13 +9,13 @@ jobs:
strategy: strategy:
matrix: matrix:
python-version: [3.6, 3.7, 3.8, 3.9] python-version: ["3.7", "3.8", "3.9", "3.10"]
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }} - name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2 uses: actions/setup-python@v4
with: with:
python-version: ${{ matrix.python-version }} python-version: ${{ matrix.python-version }}

View File

@@ -262,9 +262,9 @@ class EthMacTx(Reset):
else: else:
self.log.info("Reset de-asserted") self.log.info("Reset de-asserted")
if self._run_cr is None: if self._run_cr is None:
self._run_cr = cocotb.fork(self._run()) self._run_cr = cocotb.start_soon(self._run())
if self._run_ts_cr is None and self.ptp_ts: if self._run_ts_cr is None and self.ptp_ts:
self._run_ts_cr = cocotb.fork(self._run_ts()) self._run_ts_cr = cocotb.start_soon(self._run_ts())
async def _run(self): async def _run(self):
frame = None frame = None
@@ -322,8 +322,10 @@ class EthMacTx(Reset):
await Timer(self.time_scale*self.ifg*8//self.speed, 'step') await Timer(self.time_scale*self.ifg*8//self.speed, 'step')
async def _run_ts(self): async def _run_ts(self):
clock_edge_event = RisingEdge(self.clock)
while True: while True:
await RisingEdge(self.clock) await clock_edge_event
self.ptp_ts_valid.value = 0 self.ptp_ts_valid.value = 0
if not self.ts_queue.empty(): if not self.ts_queue.empty():
@@ -475,7 +477,7 @@ class EthMacRx(Reset):
else: else:
self.log.info("Reset de-asserted") self.log.info("Reset de-asserted")
if self._run_cr is None: if self._run_cr is None:
self._run_cr = cocotb.fork(self._run()) self._run_cr = cocotb.start_soon(self._run())
async def _run(self): async def _run(self):
frame = None frame = None

View File

@@ -157,6 +157,7 @@ class GmiiSource(Reset):
self.current_frame = None self.current_frame = None
self.idle_event = Event() self.idle_event = Event()
self.idle_event.set() self.idle_event.set()
self.active_event = Event()
self.ifg = 12 self.ifg = 12
self.mii_mode = False self.mii_mode = False
@@ -189,6 +190,7 @@ class GmiiSource(Reset):
frame = GmiiFrame(frame) frame = GmiiFrame(frame)
await self.queue.put(frame) await self.queue.put(frame)
self.idle_event.clear() self.idle_event.clear()
self.active_event.set()
self.queue_occupancy_bytes += len(frame) self.queue_occupancy_bytes += len(frame)
self.queue_occupancy_frames += 1 self.queue_occupancy_frames += 1
@@ -198,6 +200,7 @@ class GmiiSource(Reset):
frame = GmiiFrame(frame) frame = GmiiFrame(frame)
self.queue.put_nowait(frame) self.queue.put_nowait(frame)
self.idle_event.clear() self.idle_event.clear()
self.active_event.set()
self.queue_occupancy_bytes += len(frame) self.queue_occupancy_bytes += len(frame)
self.queue_occupancy_frames += 1 self.queue_occupancy_frames += 1
@@ -225,6 +228,7 @@ class GmiiSource(Reset):
frame.handle_tx_complete() frame.handle_tx_complete()
self.dequeue_event.set() self.dequeue_event.set()
self.idle_event.set() self.idle_event.set()
self.active_event.clear()
self.queue_occupancy_bytes = 0 self.queue_occupancy_bytes = 0
self.queue_occupancy_frames = 0 self.queue_occupancy_frames = 0
@@ -251,10 +255,11 @@ class GmiiSource(Reset):
if self.queue.empty(): if self.queue.empty():
self.idle_event.set() self.idle_event.set()
self.active_event.clear()
else: else:
self.log.info("Reset de-asserted") self.log.info("Reset de-asserted")
if self._run_cr is None: if self._run_cr is None:
self._run_cr = cocotb.fork(self._run()) self._run_cr = cocotb.start_soon(self._run())
async def _run(self): async def _run(self):
frame = None frame = None
@@ -264,8 +269,14 @@ class GmiiSource(Reset):
ifg_cnt = 0 ifg_cnt = 0
self.active = False self.active = False
clock_edge_event = RisingEdge(self.clock)
enable_event = None
if self.enable is not None:
enable_event = RisingEdge(self.enable)
while True: while True:
await RisingEdge(self.clock) await clock_edge_event
if self.enable is None or self.enable.value: if self.enable is None or self.enable.value:
if ifg_cnt > 0: if ifg_cnt > 0:
@@ -326,7 +337,14 @@ class GmiiSource(Reset):
self.er.value = 0 self.er.value = 0
self.dv.value = 0 self.dv.value = 0
self.active = False self.active = False
self.idle_event.set()
if ifg_cnt == 0 and self.queue.empty():
self.idle_event.set()
self.active_event.clear()
await self.active_event.wait()
elif self.enable is not None and not self.enable.value:
await enable_event
class GmiiSink(Reset): class GmiiSink(Reset):
@@ -422,14 +440,22 @@ class GmiiSink(Reset):
else: else:
self.log.info("Reset de-asserted") self.log.info("Reset de-asserted")
if self._run_cr is None: if self._run_cr is None:
self._run_cr = cocotb.fork(self._run()) self._run_cr = cocotb.start_soon(self._run())
async def _run(self): async def _run(self):
frame = None frame = None
self.active = False self.active = False
clock_edge_event = RisingEdge(self.clock)
active_event = RisingEdge(self.dv)
enable_event = None
if self.enable is not None:
enable_event = RisingEdge(self.enable)
while True: while True:
await RisingEdge(self.clock) await clock_edge_event
if self.enable is None or self.enable.value: if self.enable is None or self.enable.value:
d_val = self.data.value.integer d_val = self.data.value.integer
@@ -488,6 +514,12 @@ class GmiiSink(Reset):
frame.data.append(d_val) frame.data.append(d_val)
frame.error.append(er_val) frame.error.append(er_val)
if not dv_val:
await active_event
elif self.enable is not None and not self.enable.value:
await enable_event
class GmiiPhy: class GmiiPhy:
def __init__(self, txd, tx_er, tx_en, tx_clk, gtx_clk, rxd, rx_er, rx_dv, rx_clk, def __init__(self, txd, tx_er, tx_en, tx_clk, gtx_clk, rxd, rx_er, rx_dv, rx_clk,
@@ -517,12 +549,12 @@ class GmiiPhy:
self._clock_cr.kill() self._clock_cr.kill()
if self.speed == 1000e6: if self.speed == 1000e6:
self._clock_cr = cocotb.fork(self._run_clocks(8*1e9/self.speed)) self._clock_cr = cocotb.start_soon(self._run_clocks(8*1e9/self.speed))
self.tx.mii_mode = False self.tx.mii_mode = False
self.rx.mii_mode = False self.rx.mii_mode = False
self.tx.clock = self.gtx_clk self.tx.clock = self.gtx_clk
else: else:
self._clock_cr = cocotb.fork(self._run_clocks(4*1e9/self.speed)) self._clock_cr = cocotb.start_soon(self._run_clocks(4*1e9/self.speed))
self.tx.mii_mode = True self.tx.mii_mode = True
self.rx.mii_mode = True self.rx.mii_mode = True
self.tx.clock = self.tx_clk self.tx.clock = self.tx_clk

View File

@@ -59,6 +59,7 @@ class MiiSource(Reset):
self.current_frame = None self.current_frame = None
self.idle_event = Event() self.idle_event = Event()
self.idle_event.set() self.idle_event.set()
self.active_event = Event()
self.ifg = 12 self.ifg = 12
@@ -90,6 +91,7 @@ class MiiSource(Reset):
frame = GmiiFrame(frame) frame = GmiiFrame(frame)
await self.queue.put(frame) await self.queue.put(frame)
self.idle_event.clear() self.idle_event.clear()
self.active_event.set()
self.queue_occupancy_bytes += len(frame) self.queue_occupancy_bytes += len(frame)
self.queue_occupancy_frames += 1 self.queue_occupancy_frames += 1
@@ -99,6 +101,7 @@ class MiiSource(Reset):
frame = GmiiFrame(frame) frame = GmiiFrame(frame)
self.queue.put_nowait(frame) self.queue.put_nowait(frame)
self.idle_event.clear() self.idle_event.clear()
self.active_event.set()
self.queue_occupancy_bytes += len(frame) self.queue_occupancy_bytes += len(frame)
self.queue_occupancy_frames += 1 self.queue_occupancy_frames += 1
@@ -126,6 +129,7 @@ class MiiSource(Reset):
frame.handle_tx_complete() frame.handle_tx_complete()
self.dequeue_event.set() self.dequeue_event.set()
self.idle_event.set() self.idle_event.set()
self.active_event.clear()
self.queue_occupancy_bytes = 0 self.queue_occupancy_bytes = 0
self.queue_occupancy_frames = 0 self.queue_occupancy_frames = 0
@@ -152,10 +156,11 @@ class MiiSource(Reset):
if self.queue.empty(): if self.queue.empty():
self.idle_event.set() self.idle_event.set()
self.active_event.clear()
else: else:
self.log.info("Reset de-asserted") self.log.info("Reset de-asserted")
if self._run_cr is None: if self._run_cr is None:
self._run_cr = cocotb.fork(self._run()) self._run_cr = cocotb.start_soon(self._run())
async def _run(self): async def _run(self):
frame = None frame = None
@@ -165,8 +170,14 @@ class MiiSource(Reset):
ifg_cnt = 0 ifg_cnt = 0
self.active = False self.active = False
clock_edge_event = RisingEdge(self.clock)
enable_event = None
if self.enable is not None:
enable_event = RisingEdge(self.enable)
while True: while True:
await RisingEdge(self.clock) await clock_edge_event
if self.enable is None or self.enable.value: if self.enable is None or self.enable.value:
if ifg_cnt > 0: if ifg_cnt > 0:
@@ -220,7 +231,14 @@ class MiiSource(Reset):
self.er.value = 0 self.er.value = 0
self.dv.value = 0 self.dv.value = 0
self.active = False self.active = False
self.idle_event.set()
if ifg_cnt == 0 and self.queue.empty():
self.idle_event.set()
self.active_event.clear()
await self.active_event.wait()
elif self.enable is not None and not self.enable.value:
await enable_event
class MiiSink(Reset): class MiiSink(Reset):
@@ -313,14 +331,22 @@ class MiiSink(Reset):
else: else:
self.log.info("Reset de-asserted") self.log.info("Reset de-asserted")
if self._run_cr is None: if self._run_cr is None:
self._run_cr = cocotb.fork(self._run()) self._run_cr = cocotb.start_soon(self._run())
async def _run(self): async def _run(self):
frame = None frame = None
self.active = False self.active = False
clock_edge_event = RisingEdge(self.clock)
active_event = RisingEdge(self.dv)
enable_event = None
if self.enable is not None:
enable_event = RisingEdge(self.enable)
while True: while True:
await RisingEdge(self.clock) await clock_edge_event
if self.enable is None or self.enable.value: if self.enable is None or self.enable.value:
d_val = self.data.value.integer d_val = self.data.value.integer
@@ -374,6 +400,12 @@ class MiiSink(Reset):
frame.data.append(d_val) frame.data.append(d_val)
frame.error.append(er_val) frame.error.append(er_val)
if not dv_val:
await active_event
elif self.enable is not None and not self.enable.value:
await enable_event
class MiiPhy: class MiiPhy:
def __init__(self, txd, tx_er, tx_en, tx_clk, rxd, rx_er, rx_dv, rx_clk, reset=None, def __init__(self, txd, tx_er, tx_en, tx_clk, rxd, rx_er, rx_dv, rx_clk, reset=None,
@@ -402,7 +434,7 @@ class MiiPhy:
if self._clock_cr is not None: if self._clock_cr is not None:
self._clock_cr.kill() self._clock_cr.kill()
self._clock_cr = cocotb.fork(self._run_clocks(4*1e9/self.speed)) self._clock_cr = cocotb.start_soon(self._run_clocks(4*1e9/self.speed))
async def _run_clocks(self, period): async def _run_clocks(self, period):
half_period = get_sim_steps(period / 2.0, 'ns') half_period = get_sim_steps(period / 2.0, 'ns')

View File

@@ -205,11 +205,13 @@ class PtpClock(Reset):
else: else:
self.log.info("Reset de-asserted") self.log.info("Reset de-asserted")
if self._run_cr is None: if self._run_cr is None:
self._run_cr = cocotb.fork(self._run()) self._run_cr = cocotb.start_soon(self._run())
async def _run(self): async def _run(self):
clock_edge_event = RisingEdge(self.clock)
while True: while True:
await RisingEdge(self.clock) await clock_edge_event
if self.ts_step is not None: if self.ts_step is not None:
self.ts_step.value = self.ts_updated self.ts_step.value = self.ts_updated
@@ -288,7 +290,7 @@ class PtpClockSimTime:
if self.pps is not None: if self.pps is not None:
self.pps.value = 0 self.pps.value = 0
self._run_cr = cocotb.fork(self._run()) self._run_cr = cocotb.start_soon(self._run())
def get_ts_96(self): def get_ts_96(self):
return (self.ts_96_s << 48) | (self.ts_96_ns << 16) | self.ts_96_fns return (self.ts_96_s << 48) | (self.ts_96_ns << 16) | self.ts_96_fns
@@ -309,8 +311,10 @@ class PtpClockSimTime:
return self.get_ts_64()*1e-9 return self.get_ts_64()*1e-9
async def _run(self): async def _run(self):
clock_edge_event = RisingEdge(self.clock)
while True: while True:
await RisingEdge(self.clock) await clock_edge_event
self.ts_64_fns, self.ts_64_ns = math.modf(get_sim_time('ns')) self.ts_64_fns, self.ts_64_ns = math.modf(get_sim_time('ns'))

View File

@@ -33,7 +33,7 @@ class Reset:
self._reset_state = True self._reset_state = True
if reset_signal is not None: if reset_signal is not None:
cocotb.fork(self._run_reset(reset_signal, bool(active_level))) cocotb.start_soon(self._run_reset(reset_signal, bool(active_level)))
self._update_reset() self._update_reset()

View File

@@ -61,6 +61,7 @@ class RgmiiSource(Reset):
self.current_frame = None self.current_frame = None
self.idle_event = Event() self.idle_event = Event()
self.idle_event.set() self.idle_event.set()
self.active_event = Event()
self.ifg = 12 self.ifg = 12
self.mii_mode = False self.mii_mode = False
@@ -90,6 +91,7 @@ class RgmiiSource(Reset):
frame = GmiiFrame(frame) frame = GmiiFrame(frame)
await self.queue.put(frame) await self.queue.put(frame)
self.idle_event.clear() self.idle_event.clear()
self.active_event.set()
self.queue_occupancy_bytes += len(frame) self.queue_occupancy_bytes += len(frame)
self.queue_occupancy_frames += 1 self.queue_occupancy_frames += 1
@@ -99,6 +101,7 @@ class RgmiiSource(Reset):
frame = GmiiFrame(frame) frame = GmiiFrame(frame)
self.queue.put_nowait(frame) self.queue.put_nowait(frame)
self.idle_event.clear() self.idle_event.clear()
self.active_event.set()
self.queue_occupancy_bytes += len(frame) self.queue_occupancy_bytes += len(frame)
self.queue_occupancy_frames += 1 self.queue_occupancy_frames += 1
@@ -126,6 +129,7 @@ class RgmiiSource(Reset):
frame.handle_tx_complete() frame.handle_tx_complete()
self.dequeue_event.set() self.dequeue_event.set()
self.idle_event.set() self.idle_event.set()
self.active_event.clear()
self.queue_occupancy_bytes = 0 self.queue_occupancy_bytes = 0
self.queue_occupancy_frames = 0 self.queue_occupancy_frames = 0
@@ -150,10 +154,11 @@ class RgmiiSource(Reset):
if self.queue.empty(): if self.queue.empty():
self.idle_event.set() self.idle_event.set()
self.active_event.clear()
else: else:
self.log.info("Reset de-asserted") self.log.info("Reset de-asserted")
if self._run_cr is None: if self._run_cr is None:
self._run_cr = cocotb.fork(self._run()) self._run_cr = cocotb.start_soon(self._run())
async def _run(self): async def _run(self):
frame = None frame = None
@@ -161,22 +166,39 @@ class RgmiiSource(Reset):
frame_data = None frame_data = None
frame_error = None frame_error = None
ifg_cnt = 0 ifg_cnt = 0
in_ifg = False
self.active = False self.active = False
d = 0 d = 0
er = 0 er = 0
en = 0 en = 0
clock_rising_edge_event = RisingEdge(self.clock)
clock_falling_edge_event = FallingEdge(self.clock)
enable_event = None
if self.enable is not None:
enable_event = RisingEdge(self.enable)
while True: while True:
await RisingEdge(self.clock) await clock_falling_edge_event
# send low nibble after falling edge, leading in to rising edge
self.data.value = d & 0x0F
self.ctrl.value = en
await clock_rising_edge_event
# send high nibble after rising edge, leading in to falling edge # send high nibble after rising edge, leading in to falling edge
self.data.value = d >> 4 self.data.value = d >> 4
self.ctrl.value = en ^ er self.ctrl.value = en ^ er
if self.enable is None or self.enable.value: if self.enable is None or self.enable.value:
in_ifg = False
if ifg_cnt > 0: if ifg_cnt > 0:
# in IFG # in IFG
ifg_cnt -= 1 ifg_cnt -= 1
in_ifg = True
elif frame is None and not self.queue.empty(): elif frame is None and not self.queue.empty():
# send frame # send frame
@@ -221,6 +243,7 @@ class RgmiiSource(Reset):
if frame_offset >= len(frame_data): if frame_offset >= len(frame_data):
ifg_cnt = max(self.ifg, 1) ifg_cnt = max(self.ifg, 1)
in_ifg = True
frame.sim_time_end = get_sim_time() frame.sim_time_end = get_sim_time()
frame.handle_tx_complete() frame.handle_tx_complete()
frame = None frame = None
@@ -230,13 +253,14 @@ class RgmiiSource(Reset):
er = 0 er = 0
en = 0 en = 0
self.active = False self.active = False
self.idle_event.set()
await FallingEdge(self.clock) if not in_ifg and self.queue.empty():
self.idle_event.set()
self.active_event.clear()
await self.active_event.wait()
# send low nibble after falling edge, leading in to rising edge elif self.enable is not None and not self.enable.value:
self.data.value = d & 0x0F await enable_event
self.ctrl.value = en
class RgmiiSink(Reset): class RgmiiSink(Reset):
@@ -330,7 +354,7 @@ class RgmiiSink(Reset):
else: else:
self.log.info("Reset de-asserted") self.log.info("Reset de-asserted")
if self._run_cr is None: if self._run_cr is None:
self._run_cr = cocotb.fork(self._run()) self._run_cr = cocotb.start_soon(self._run())
async def _run(self): async def _run(self):
frame = None frame = None
@@ -339,21 +363,30 @@ class RgmiiSink(Reset):
dv_val = 0 dv_val = 0
er_val = 0 er_val = 0
clock_rising_edge_event = RisingEdge(self.clock)
clock_falling_edge_event = FallingEdge(self.clock)
active_event = RisingEdge(self.ctrl)
enable_event = None
if self.enable is not None:
enable_event = RisingEdge(self.enable)
while True: while True:
await RisingEdge(self.clock) await clock_rising_edge_event
# capture low nibble on rising edge
d_val = self.data.value.integer
dv_val = self.ctrl.value.integer
await FallingEdge(self.clock)
# capture high nibble on falling edge
d_val |= self.data.value.integer << 4
er_val = dv_val ^ self.ctrl.value.integer
if self.enable is None or self.enable.value: if self.enable is None or self.enable.value:
# capture low nibble on rising edge
d_val = self.data.value.integer
dv_val = self.ctrl.value.integer
await clock_falling_edge_event
# capture high nibble on falling edge
d_val |= self.data.value.integer << 4
er_val = dv_val ^ self.ctrl.value.integer
if frame is None: if frame is None:
if dv_val: if dv_val:
# start of frame # start of frame
@@ -406,6 +439,12 @@ class RgmiiSink(Reset):
frame.data.append(d_val) frame.data.append(d_val)
frame.error.append(er_val) frame.error.append(er_val)
if not dv_val:
await active_event
elif self.enable is not None and not self.enable.value:
await enable_event
class RgmiiPhy: class RgmiiPhy:
def __init__(self, txd, tx_ctl, tx_clk, rxd, rx_ctl, rx_clk, reset=None, def __init__(self, txd, tx_ctl, tx_clk, rxd, rx_ctl, rx_clk, reset=None,
@@ -434,11 +473,11 @@ class RgmiiPhy:
self._clock_cr.kill() self._clock_cr.kill()
if self.speed == 1000e6: if self.speed == 1000e6:
self._clock_cr = cocotb.fork(self._run_clock(8*1e9/self.speed)) self._clock_cr = cocotb.start_soon(self._run_clock(8*1e9/self.speed))
self.tx.mii_mode = False self.tx.mii_mode = False
self.rx.mii_mode = False self.rx.mii_mode = False
else: else:
self._clock_cr = cocotb.fork(self._run_clock(4*1e9/self.speed)) self._clock_cr = cocotb.start_soon(self._run_clock(4*1e9/self.speed))
self.tx.mii_mode = True self.tx.mii_mode = True
self.rx.mii_mode = True self.rx.mii_mode = True

View File

@@ -1 +1 @@
__version__ = "0.1.18" __version__ = "0.1.20"

View File

@@ -28,7 +28,7 @@ import zlib
import cocotb import cocotb
from cocotb.queue import Queue, QueueFull from cocotb.queue import Queue, QueueFull
from cocotb.triggers import RisingEdge, Timer, First, Event from cocotb.triggers import Edge, RisingEdge, Timer, First, Event
from cocotb.utils import get_sim_time from cocotb.utils import get_sim_time
from .version import __version__ from .version import __version__
@@ -158,6 +158,7 @@ class XgmiiSource(Reset):
self.current_frame = None self.current_frame = None
self.idle_event = Event() self.idle_event = Event()
self.idle_event.set() self.idle_event.set()
self.active_event = Event()
self.enable_dic = True self.enable_dic = True
self.ifg = 12 self.ifg = 12
@@ -200,6 +201,7 @@ class XgmiiSource(Reset):
frame = XgmiiFrame(frame) frame = XgmiiFrame(frame)
await self.queue.put(frame) await self.queue.put(frame)
self.idle_event.clear() self.idle_event.clear()
self.active_event.set()
self.queue_occupancy_bytes += len(frame) self.queue_occupancy_bytes += len(frame)
self.queue_occupancy_frames += 1 self.queue_occupancy_frames += 1
@@ -209,6 +211,7 @@ class XgmiiSource(Reset):
frame = XgmiiFrame(frame) frame = XgmiiFrame(frame)
self.queue.put_nowait(frame) self.queue.put_nowait(frame)
self.idle_event.clear() self.idle_event.clear()
self.active_event.set()
self.queue_occupancy_bytes += len(frame) self.queue_occupancy_bytes += len(frame)
self.queue_occupancy_frames += 1 self.queue_occupancy_frames += 1
@@ -236,6 +239,7 @@ class XgmiiSource(Reset):
frame.handle_tx_complete() frame.handle_tx_complete()
self.dequeue_event.set() self.dequeue_event.set()
self.idle_event.set() self.idle_event.set()
self.active_event.clear()
self.queue_occupancy_bytes = 0 self.queue_occupancy_bytes = 0
self.queue_occupancy_frames = 0 self.queue_occupancy_frames = 0
@@ -260,10 +264,11 @@ class XgmiiSource(Reset):
if self.queue.empty(): if self.queue.empty():
self.idle_event.set() self.idle_event.set()
self.active_event.clear()
else: else:
self.log.info("Reset de-asserted") self.log.info("Reset de-asserted")
if self._run_cr is None: if self._run_cr is None:
self._run_cr = cocotb.fork(self._run()) self._run_cr = cocotb.start_soon(self._run())
async def _run(self): async def _run(self):
frame = None frame = None
@@ -272,8 +277,14 @@ class XgmiiSource(Reset):
deficit_idle_cnt = 0 deficit_idle_cnt = 0
self.active = False self.active = False
clock_edge_event = RisingEdge(self.clock)
enable_event = None
if self.enable is not None:
enable_event = RisingEdge(self.enable)
while True: while True:
await RisingEdge(self.clock) await clock_edge_event
if self.enable is None or self.enable.value: if self.enable is None or self.enable.value:
if ifg_cnt + deficit_idle_cnt > self.byte_lanes-1 or (not self.enable_dic and ifg_cnt > 4): if ifg_cnt + deficit_idle_cnt > self.byte_lanes-1 or (not self.enable_dic and ifg_cnt > 4):
@@ -357,7 +368,14 @@ class XgmiiSource(Reset):
self.data.value = self.idle_d self.data.value = self.idle_d
self.ctrl.value = self.idle_c self.ctrl.value = self.idle_c
self.active = False self.active = False
self.idle_event.set()
if ifg_cnt == 0 and self.queue.empty():
self.idle_event.set()
self.active_event.clear()
await self.active_event.wait()
elif self.enable is not None and not self.enable.value:
await enable_event
class XgmiiSink(Reset): class XgmiiSink(Reset):
@@ -450,19 +468,32 @@ class XgmiiSink(Reset):
else: else:
self.log.info("Reset de-asserted") self.log.info("Reset de-asserted")
if self._run_cr is None: if self._run_cr is None:
self._run_cr = cocotb.fork(self._run()) self._run_cr = cocotb.start_soon(self._run())
async def _run(self): async def _run(self):
frame = None frame = None
self.active = False self.active = False
clock_edge_event = RisingEdge(self.clock)
active_event = First(Edge(self.data), Edge(self.ctrl))
enable_event = None
if self.enable is not None:
enable_event = RisingEdge(self.enable)
idle_d = sum([XgmiiCtrl.IDLE << n*8 for n in range(self.byte_lanes)])
idle_c = 2**self.byte_lanes-1
while True: while True:
await RisingEdge(self.clock) await clock_edge_event
if self.enable is None or self.enable.value: if self.enable is None or self.enable.value:
data_val = self.data.value.integer
ctrl_val = self.ctrl.value.integer
for offset in range(self.byte_lanes): for offset in range(self.byte_lanes):
d_val = (self.data.value.integer >> (offset*8)) & 0xff d_val = (data_val >> (offset*8)) & 0xff
c_val = (self.ctrl.value.integer >> offset) & 1 c_val = (ctrl_val >> offset) & 1
if frame is None: if frame is None:
if c_val and d_val == XgmiiCtrl.START: if c_val and d_val == XgmiiCtrl.START:
@@ -495,3 +526,9 @@ class XgmiiSink(Reset):
frame.data.append(d_val) frame.data.append(d_val)
frame.ctrl.append(c_val) frame.ctrl.append(c_val)
if data_val == idle_d and ctrl_val == idle_c:
await active_event
elif self.enable is not None and not self.enable.value:
await enable_event

View File

@@ -27,8 +27,8 @@ classifiers =
packages = find_namespace: packages = find_namespace:
python_requires = >=3.6 python_requires = >=3.6
install_requires = install_requires =
cocotb cocotb >= 1.6.0
cocotbext-axi cocotbext-axi >= 0.1.16
[options.extras_require] [options.extras_require]
test = test =
@@ -47,31 +47,39 @@ addopts =
# tox configuration # tox configuration
[tox:tox] [tox:tox]
envlist = py36, py37, py38, py39 envlist = py37, py38, py39, py310
skip_missing_interpreters = true
minversion = 3.18.0
requires = virtualenv >= 16.1
[gh-actions] [gh-actions]
python = python =
3.6: py36
3.7: py37 3.7: py37
3.8: py38 3.8: py38
3.9: py39 3.9: py39
3.10: py310
[testenv] [testenv]
setenv = setenv =
COVERAGE=1 COVERAGE=1
usedevelop = True
deps = deps =
pytest pytest == 7.2.1
pytest-xdist pytest-xdist == 3.1.0
cocotb-test cocotb == 1.7.2
coverage cocotb-bus == 0.2.1
pytest-cov cocotb-test == 0.2.4
cocotbext-axi == 0.1.20
coverage == 7.0.5
pytest-cov == 4.0.0
commands = commands =
pytest --cov=cocotbext --cov=tests --cov-branch -n auto pytest --cov=cocotbext --cov=tests --cov-branch {posargs:-n auto --verbose}
bash -c 'find . -type f -name "\.coverage" | xargs coverage combine --append' bash -c 'find . -type f -name "\.coverage" | xargs coverage combine --append'
coverage report
whitelist_externals = allowlist_externals =
bash bash
# combine if paths are different # combine if paths are different

View File

@@ -45,8 +45,8 @@ class TB:
self.log = logging.getLogger("cocotb.tb") self.log = logging.getLogger("cocotb.tb")
self.log.setLevel(logging.DEBUG) self.log.setLevel(logging.DEBUG)
cocotb.fork(Clock(dut.tx_clk, 6.4, units="ns").start()) cocotb.start_soon(Clock(dut.tx_clk, 6.4, units="ns").start())
cocotb.fork(Clock(dut.rx_clk, 6.4, units="ns").start()) cocotb.start_soon(Clock(dut.rx_clk, 6.4, units="ns").start())
self.mac = EthMac( self.mac = EthMac(
tx_clk=dut.tx_clk, tx_clk=dut.tx_clk,
@@ -81,12 +81,12 @@ class TB:
self.dut.rx_rst.setimmediatevalue(0) self.dut.rx_rst.setimmediatevalue(0)
await RisingEdge(self.dut.tx_clk) await RisingEdge(self.dut.tx_clk)
await RisingEdge(self.dut.tx_clk) await RisingEdge(self.dut.tx_clk)
self.dut.tx_rst <= 1 self.dut.tx_rst.value = 1
self.dut.rx_rst <= 1 self.dut.rx_rst.value = 1
await RisingEdge(self.dut.tx_clk) await RisingEdge(self.dut.tx_clk)
await RisingEdge(self.dut.tx_clk) await RisingEdge(self.dut.tx_clk)
self.dut.tx_rst <= 0 self.dut.tx_rst.value = 0
self.dut.rx_rst <= 0 self.dut.rx_rst.value = 0
await RisingEdge(self.dut.tx_clk) await RisingEdge(self.dut.tx_clk)
await RisingEdge(self.dut.tx_clk) await RisingEdge(self.dut.tx_clk)

View File

@@ -47,7 +47,7 @@ class TB:
self._enable_generator = None self._enable_generator = None
self._enable_cr = None self._enable_cr = None
cocotb.fork(Clock(dut.clk, 2, units="ns").start()) cocotb.start_soon(Clock(dut.clk, 2, units="ns").start())
self.source = GmiiSource(dut.gmii_d, dut.gmii_er, dut.gmii_en, self.source = GmiiSource(dut.gmii_d, dut.gmii_er, dut.gmii_en,
dut.clk, dut.rst, dut.gmii_clk_en, dut.gmii_mii_sel) dut.clk, dut.rst, dut.gmii_clk_en, dut.gmii_mii_sel)
@@ -61,10 +61,10 @@ class TB:
self.dut.rst.setimmediatevalue(0) self.dut.rst.setimmediatevalue(0)
await RisingEdge(self.dut.clk) await RisingEdge(self.dut.clk)
await RisingEdge(self.dut.clk) await RisingEdge(self.dut.clk)
self.dut.rst <= 1 self.dut.rst.value = 1
await RisingEdge(self.dut.clk) await RisingEdge(self.dut.clk)
await RisingEdge(self.dut.clk) await RisingEdge(self.dut.clk)
self.dut.rst <= 0 self.dut.rst.value = 0
await RisingEdge(self.dut.clk) await RisingEdge(self.dut.clk)
await RisingEdge(self.dut.clk) await RisingEdge(self.dut.clk)
@@ -76,15 +76,17 @@ class TB:
self._enable_generator = generator self._enable_generator = generator
if self._enable_generator is not None: if self._enable_generator is not None:
self._enable_cr = cocotb.fork(self._run_enable()) self._enable_cr = cocotb.start_soon(self._run_enable())
def clear_enable_generator(self): def clear_enable_generator(self):
self.set_enable_generator(None) self.set_enable_generator(None)
async def _run_enable(self): async def _run_enable(self):
clock_edge_event = RisingEdge(self.dut.clk)
for val in self._enable_generator: for val in self._enable_generator:
self.dut.gmii_clk_en <= val self.dut.gmii_clk_en.value = val
await RisingEdge(self.dut.clk) await clock_edge_event
async def run_test(dut, payload_lengths=None, payload_data=None, ifg=12, enable_gen=None, mii_sel=False): async def run_test(dut, payload_lengths=None, payload_data=None, ifg=12, enable_gen=None, mii_sel=False):
@@ -92,7 +94,7 @@ async def run_test(dut, payload_lengths=None, payload_data=None, ifg=12, enable_
tb = TB(dut) tb = TB(dut)
tb.source.ifg = ifg tb.source.ifg = ifg
tb.dut.gmii_mii_sel <= mii_sel tb.dut.gmii_mii_sel.value = mii_sel
if enable_gen is not None: if enable_gen is not None:
tb.set_enable_generator(enable_gen()) tb.set_enable_generator(enable_gen())

View File

@@ -44,7 +44,7 @@ class TB:
self.log = logging.getLogger("cocotb.tb") self.log = logging.getLogger("cocotb.tb")
self.log.setLevel(logging.DEBUG) self.log.setLevel(logging.DEBUG)
cocotb.fork(Clock(dut.phy_gtx_clk, 8, units="ns").start()) cocotb.start_soon(Clock(dut.phy_gtx_clk, 8, units="ns").start())
self.gmii_phy = GmiiPhy(dut.phy_txd, dut.phy_tx_er, dut.phy_tx_en, dut.phy_tx_clk, dut.phy_gtx_clk, self.gmii_phy = GmiiPhy(dut.phy_txd, dut.phy_tx_er, dut.phy_tx_en, dut.phy_tx_clk, dut.phy_gtx_clk,
dut.phy_rxd, dut.phy_rx_er, dut.phy_rx_dv, dut.phy_rx_clk, dut.phy_rst, speed=speed) dut.phy_rxd, dut.phy_rx_er, dut.phy_rx_dv, dut.phy_rx_clk, dut.phy_rst, speed=speed)
@@ -64,10 +64,10 @@ class TB:
self.dut.phy_rst.setimmediatevalue(0) self.dut.phy_rst.setimmediatevalue(0)
await RisingEdge(self.dut.phy_tx_clk) await RisingEdge(self.dut.phy_tx_clk)
await RisingEdge(self.dut.phy_tx_clk) await RisingEdge(self.dut.phy_tx_clk)
self.dut.phy_rst <= 1 self.dut.phy_rst.value = 1
await RisingEdge(self.dut.phy_tx_clk) await RisingEdge(self.dut.phy_tx_clk)
await RisingEdge(self.dut.phy_tx_clk) await RisingEdge(self.dut.phy_tx_clk)
self.dut.phy_rst <= 0 self.dut.phy_rst.value = 0
await RisingEdge(self.dut.phy_tx_clk) await RisingEdge(self.dut.phy_tx_clk)
await RisingEdge(self.dut.phy_tx_clk) await RisingEdge(self.dut.phy_tx_clk)

View File

@@ -47,7 +47,7 @@ class TB:
self._enable_generator = None self._enable_generator = None
self._enable_cr = None self._enable_cr = None
cocotb.fork(Clock(dut.clk, 2, units="ns").start()) cocotb.start_soon(Clock(dut.clk, 2, units="ns").start())
self.source = MiiSource(dut.mii_d, dut.mii_er, dut.mii_en, self.source = MiiSource(dut.mii_d, dut.mii_er, dut.mii_en,
dut.clk, dut.rst, dut.mii_clk_en) dut.clk, dut.rst, dut.mii_clk_en)
@@ -60,10 +60,10 @@ class TB:
self.dut.rst.setimmediatevalue(0) self.dut.rst.setimmediatevalue(0)
await RisingEdge(self.dut.clk) await RisingEdge(self.dut.clk)
await RisingEdge(self.dut.clk) await RisingEdge(self.dut.clk)
self.dut.rst <= 1 self.dut.rst.value = 1
await RisingEdge(self.dut.clk) await RisingEdge(self.dut.clk)
await RisingEdge(self.dut.clk) await RisingEdge(self.dut.clk)
self.dut.rst <= 0 self.dut.rst.value = 0
await RisingEdge(self.dut.clk) await RisingEdge(self.dut.clk)
await RisingEdge(self.dut.clk) await RisingEdge(self.dut.clk)
@@ -75,15 +75,17 @@ class TB:
self._enable_generator = generator self._enable_generator = generator
if self._enable_generator is not None: if self._enable_generator is not None:
self._enable_cr = cocotb.fork(self._run_enable()) self._enable_cr = cocotb.start_soon(self._run_enable())
def clear_enable_generator(self): def clear_enable_generator(self):
self.set_enable_generator(None) self.set_enable_generator(None)
async def _run_enable(self): async def _run_enable(self):
clock_edge_event = RisingEdge(self.dut.clk)
for val in self._enable_generator: for val in self._enable_generator:
self.dut.mii_clk_en <= val self.dut.mii_clk_en.value = val
await RisingEdge(self.dut.clk) await clock_edge_event
async def run_test(dut, payload_lengths=None, payload_data=None, ifg=12, enable_gen=None): async def run_test(dut, payload_lengths=None, payload_data=None, ifg=12, enable_gen=None):

View File

@@ -55,10 +55,10 @@ class TB:
self.dut.phy_rst.setimmediatevalue(0) self.dut.phy_rst.setimmediatevalue(0)
await RisingEdge(self.dut.phy_tx_clk) await RisingEdge(self.dut.phy_tx_clk)
await RisingEdge(self.dut.phy_tx_clk) await RisingEdge(self.dut.phy_tx_clk)
self.dut.phy_rst <= 1 self.dut.phy_rst.value = 1
await RisingEdge(self.dut.phy_tx_clk) await RisingEdge(self.dut.phy_tx_clk)
await RisingEdge(self.dut.phy_tx_clk) await RisingEdge(self.dut.phy_tx_clk)
self.dut.phy_rst <= 0 self.dut.phy_rst.value = 0
await RisingEdge(self.dut.phy_tx_clk) await RisingEdge(self.dut.phy_tx_clk)
await RisingEdge(self.dut.phy_tx_clk) await RisingEdge(self.dut.phy_tx_clk)

View File

@@ -30,7 +30,7 @@ import cocotb_test.simulator
import cocotb import cocotb
from cocotb.clock import Clock from cocotb.clock import Clock
from cocotb.triggers import RisingEdge from cocotb.triggers import RisingEdge, ClockCycles
from cocotb.utils import get_sim_time from cocotb.utils import get_sim_time
from cocotbext.eth import PtpClock from cocotbext.eth import PtpClock
@@ -43,7 +43,7 @@ class TB:
self.log = logging.getLogger("cocotb.tb") self.log = logging.getLogger("cocotb.tb")
self.log.setLevel(logging.DEBUG) self.log.setLevel(logging.DEBUG)
cocotb.fork(Clock(dut.clk, 6.4, units="ns").start()) cocotb.start_soon(Clock(dut.clk, 6.4, units="ns").start())
self.ptp_clock = PtpClock( self.ptp_clock = PtpClock(
ts_96=dut.ts_96, ts_96=dut.ts_96,
@@ -59,10 +59,10 @@ class TB:
self.dut.rst.setimmediatevalue(0) self.dut.rst.setimmediatevalue(0)
await RisingEdge(self.dut.clk) await RisingEdge(self.dut.clk)
await RisingEdge(self.dut.clk) await RisingEdge(self.dut.clk)
self.dut.rst <= 1 self.dut.rst.value = 1
await RisingEdge(self.dut.clk) await RisingEdge(self.dut.clk)
await RisingEdge(self.dut.clk) await RisingEdge(self.dut.clk)
self.dut.rst <= 0 self.dut.rst.value = 0
await RisingEdge(self.dut.clk) await RisingEdge(self.dut.clk)
await RisingEdge(self.dut.clk) await RisingEdge(self.dut.clk)
@@ -79,8 +79,7 @@ async def run_default_rate(dut):
start_ts_96 = (dut.ts_96.value.integer >> 48) + ((dut.ts_96.value.integer & 0xffffffffffff)/2**16*1e-9) start_ts_96 = (dut.ts_96.value.integer >> 48) + ((dut.ts_96.value.integer & 0xffffffffffff)/2**16*1e-9)
start_ts_64 = dut.ts_64.value.integer/2**16*1e-9 start_ts_64 = dut.ts_64.value.integer/2**16*1e-9
for k in range(10000): await ClockCycles(dut.clk, 10000)
await RisingEdge(dut.clk)
stop_time = get_sim_time('sec') stop_time = get_sim_time('sec')
stop_ts_96 = (dut.ts_96.value.integer >> 48) + ((dut.ts_96.value.integer & 0xffffffffffff)/2**16*1e-9) stop_ts_96 = (dut.ts_96.value.integer >> 48) + ((dut.ts_96.value.integer & 0xffffffffffff)/2**16*1e-9)
@@ -126,8 +125,7 @@ async def run_load_timestamps(dut):
start_ts_96 = (dut.ts_96.value.integer >> 48) + ((dut.ts_96.value.integer & 0xffffffffffff)/2**16*1e-9) start_ts_96 = (dut.ts_96.value.integer >> 48) + ((dut.ts_96.value.integer & 0xffffffffffff)/2**16*1e-9)
start_ts_64 = dut.ts_64.value.integer/2**16*1e-9 start_ts_64 = dut.ts_64.value.integer/2**16*1e-9
for k in range(2000): await ClockCycles(dut.clk, 2000)
await RisingEdge(dut.clk)
stop_time = get_sim_time('sec') stop_time = get_sim_time('sec')
stop_ts_96 = (dut.ts_96.value.integer >> 48) + ((dut.ts_96.value.integer & 0xffffffffffff)/2**16*1e-9) stop_ts_96 = (dut.ts_96.value.integer >> 48) + ((dut.ts_96.value.integer & 0xffffffffffff)/2**16*1e-9)
@@ -221,8 +219,7 @@ async def run_frequency_adjustment(dut):
start_ts_96 = (dut.ts_96.value.integer >> 48) + ((dut.ts_96.value.integer & 0xffffffffffff)/2**16*1e-9) start_ts_96 = (dut.ts_96.value.integer >> 48) + ((dut.ts_96.value.integer & 0xffffffffffff)/2**16*1e-9)
start_ts_64 = dut.ts_64.value.integer/2**16*1e-9 start_ts_64 = dut.ts_64.value.integer/2**16*1e-9
for k in range(10000): await ClockCycles(dut.clk, 10000)
await RisingEdge(dut.clk)
stop_time = get_sim_time('sec') stop_time = get_sim_time('sec')
stop_ts_96 = (dut.ts_96.value.integer >> 48) + ((dut.ts_96.value.integer & 0xffffffffffff)/2**16*1e-9) stop_ts_96 = (dut.ts_96.value.integer >> 48) + ((dut.ts_96.value.integer & 0xffffffffffff)/2**16*1e-9)
@@ -264,8 +261,7 @@ async def run_drift_adjustment(dut):
start_ts_96 = (dut.ts_96.value.integer >> 48) + ((dut.ts_96.value.integer & 0xffffffffffff)/2**16*1e-9) start_ts_96 = (dut.ts_96.value.integer >> 48) + ((dut.ts_96.value.integer & 0xffffffffffff)/2**16*1e-9)
start_ts_64 = dut.ts_64.value.integer/2**16*1e-9 start_ts_64 = dut.ts_64.value.integer/2**16*1e-9
for k in range(10000): await ClockCycles(dut.clk, 10000)
await RisingEdge(dut.clk)
stop_time = get_sim_time('sec') stop_time = get_sim_time('sec')
stop_ts_96 = (dut.ts_96.value.integer >> 48) + ((dut.ts_96.value.integer & 0xffffffffffff)/2**16*1e-9) stop_ts_96 = (dut.ts_96.value.integer >> 48) + ((dut.ts_96.value.integer & 0xffffffffffff)/2**16*1e-9)

View File

@@ -30,7 +30,7 @@ import cocotb_test.simulator
import cocotb import cocotb
from cocotb.clock import Clock from cocotb.clock import Clock
from cocotb.triggers import RisingEdge from cocotb.triggers import RisingEdge, ClockCycles
from cocotb.utils import get_sim_time from cocotb.utils import get_sim_time
from cocotbext.eth import PtpClockSimTime from cocotbext.eth import PtpClockSimTime
@@ -43,7 +43,7 @@ class TB:
self.log = logging.getLogger("cocotb.tb") self.log = logging.getLogger("cocotb.tb")
self.log.setLevel(logging.DEBUG) self.log.setLevel(logging.DEBUG)
cocotb.fork(Clock(dut.clk, 6.4, units="ns").start()) cocotb.start_soon(Clock(dut.clk, 6.4, units="ns").start())
self.ptp_clock = PtpClockSimTime( self.ptp_clock = PtpClockSimTime(
ts_96=dut.ts_96, ts_96=dut.ts_96,
@@ -66,8 +66,7 @@ async def run_test(dut):
start_ts_96 = (dut.ts_96.value.integer >> 48) + ((dut.ts_96.value.integer & 0xffffffffffff)/2**16*1e-9) start_ts_96 = (dut.ts_96.value.integer >> 48) + ((dut.ts_96.value.integer & 0xffffffffffff)/2**16*1e-9)
start_ts_64 = dut.ts_64.value.integer/2**16*1e-9 start_ts_64 = dut.ts_64.value.integer/2**16*1e-9
for k in range(10000): await ClockCycles(dut.clk, 10000)
await RisingEdge(dut.clk)
stop_time = get_sim_time('sec') stop_time = get_sim_time('sec')
stop_ts_96 = (dut.ts_96.value.integer >> 48) + ((dut.ts_96.value.integer & 0xffffffffffff)/2**16*1e-9) stop_ts_96 = (dut.ts_96.value.integer >> 48) + ((dut.ts_96.value.integer & 0xffffffffffff)/2**16*1e-9)

View File

@@ -47,7 +47,7 @@ class TB:
self._enable_generator = None self._enable_generator = None
self._enable_cr = None self._enable_cr = None
cocotb.fork(Clock(dut.clk, 2, units="ns").start()) cocotb.start_soon(Clock(dut.clk, 2, units="ns").start())
self.source = RgmiiSource(dut.rgmii_d, dut.rgmii_ctl, dut.clk, dut.rst, dut.rgmii_clk_en, dut.rgmii_mii_sel) self.source = RgmiiSource(dut.rgmii_d, dut.rgmii_ctl, dut.clk, dut.rst, dut.rgmii_clk_en, dut.rgmii_mii_sel)
self.sink = RgmiiSink(dut.rgmii_d, dut.rgmii_ctl, dut.clk, dut.rst, dut.rgmii_clk_en, dut.rgmii_mii_sel) self.sink = RgmiiSink(dut.rgmii_d, dut.rgmii_ctl, dut.clk, dut.rst, dut.rgmii_clk_en, dut.rgmii_mii_sel)
@@ -59,10 +59,10 @@ class TB:
self.dut.rst.setimmediatevalue(0) self.dut.rst.setimmediatevalue(0)
await RisingEdge(self.dut.clk) await RisingEdge(self.dut.clk)
await RisingEdge(self.dut.clk) await RisingEdge(self.dut.clk)
self.dut.rst <= 1 self.dut.rst.value = 1
await RisingEdge(self.dut.clk) await RisingEdge(self.dut.clk)
await RisingEdge(self.dut.clk) await RisingEdge(self.dut.clk)
self.dut.rst <= 0 self.dut.rst.value = 0
await RisingEdge(self.dut.clk) await RisingEdge(self.dut.clk)
await RisingEdge(self.dut.clk) await RisingEdge(self.dut.clk)
@@ -74,15 +74,17 @@ class TB:
self._enable_generator = generator self._enable_generator = generator
if self._enable_generator is not None: if self._enable_generator is not None:
self._enable_cr = cocotb.fork(self._run_enable()) self._enable_cr = cocotb.start_soon(self._run_enable())
def clear_enable_generator(self): def clear_enable_generator(self):
self.set_enable_generator(None) self.set_enable_generator(None)
async def _run_enable(self): async def _run_enable(self):
clock_edge_event = RisingEdge(self.dut.clk)
for val in self._enable_generator: for val in self._enable_generator:
self.dut.rgmii_clk_en <= val self.dut.rgmii_clk_en.value = val
await RisingEdge(self.dut.clk) await clock_edge_event
async def run_test(dut, payload_lengths=None, payload_data=None, ifg=12, enable_gen=None, mii_sel=False): async def run_test(dut, payload_lengths=None, payload_data=None, ifg=12, enable_gen=None, mii_sel=False):
@@ -90,7 +92,7 @@ async def run_test(dut, payload_lengths=None, payload_data=None, ifg=12, enable_
tb = TB(dut) tb = TB(dut)
tb.source.ifg = ifg tb.source.ifg = ifg
tb.dut.rgmii_mii_sel <= mii_sel tb.dut.rgmii_mii_sel.value = mii_sel
if enable_gen is not None: if enable_gen is not None:
tb.set_enable_generator(enable_gen()) tb.set_enable_generator(enable_gen())

View File

@@ -45,11 +45,11 @@ class TB:
self.log.setLevel(logging.DEBUG) self.log.setLevel(logging.DEBUG)
if speed == 1000e6: if speed == 1000e6:
cocotb.fork(Clock(dut.phy_tx_clk, 8, units="ns").start()) cocotb.start_soon(Clock(dut.phy_tx_clk, 8, units="ns").start())
elif speed == 100e6: elif speed == 100e6:
cocotb.fork(Clock(dut.phy_tx_clk, 40, units="ns").start()) cocotb.start_soon(Clock(dut.phy_tx_clk, 40, units="ns").start())
elif speed == 10e6: elif speed == 10e6:
cocotb.fork(Clock(dut.phy_tx_clk, 400, units="ns").start()) cocotb.start_soon(Clock(dut.phy_tx_clk, 400, units="ns").start())
self.rgmii_phy = RgmiiPhy(dut.phy_txd, dut.phy_tx_ctl, dut.phy_tx_clk, self.rgmii_phy = RgmiiPhy(dut.phy_txd, dut.phy_tx_ctl, dut.phy_tx_clk,
dut.phy_rxd, dut.phy_rx_ctl, dut.phy_rx_clk, dut.phy_rst, speed=speed) dut.phy_rxd, dut.phy_rx_ctl, dut.phy_rx_clk, dut.phy_rst, speed=speed)
@@ -68,10 +68,10 @@ class TB:
self.dut.phy_rst.setimmediatevalue(0) self.dut.phy_rst.setimmediatevalue(0)
await RisingEdge(self.dut.phy_tx_clk) await RisingEdge(self.dut.phy_tx_clk)
await RisingEdge(self.dut.phy_tx_clk) await RisingEdge(self.dut.phy_tx_clk)
self.dut.phy_rst <= 1 self.dut.phy_rst.value = 1
await RisingEdge(self.dut.phy_tx_clk) await RisingEdge(self.dut.phy_tx_clk)
await RisingEdge(self.dut.phy_tx_clk) await RisingEdge(self.dut.phy_tx_clk)
self.dut.phy_rst <= 0 self.dut.phy_rst.value = 0
await RisingEdge(self.dut.phy_tx_clk) await RisingEdge(self.dut.phy_tx_clk)
await RisingEdge(self.dut.phy_tx_clk) await RisingEdge(self.dut.phy_tx_clk)

View File

@@ -48,7 +48,7 @@ class TB:
self._enable_generator = None self._enable_generator = None
self._enable_cr = None self._enable_cr = None
cocotb.fork(Clock(dut.clk, 2, units="ns").start()) cocotb.start_soon(Clock(dut.clk, 2, units="ns").start())
self.source = XgmiiSource(dut.xgmii_d, dut.xgmii_c, dut.clk, dut.rst, dut.xgmii_clk_en) self.source = XgmiiSource(dut.xgmii_d, dut.xgmii_c, dut.clk, dut.rst, dut.xgmii_clk_en)
self.sink = XgmiiSink(dut.xgmii_d, dut.xgmii_c, dut.clk, dut.rst, dut.xgmii_clk_en) self.sink = XgmiiSink(dut.xgmii_d, dut.xgmii_c, dut.clk, dut.rst, dut.xgmii_clk_en)
@@ -59,10 +59,10 @@ class TB:
self.dut.rst.setimmediatevalue(0) self.dut.rst.setimmediatevalue(0)
await RisingEdge(self.dut.clk) await RisingEdge(self.dut.clk)
await RisingEdge(self.dut.clk) await RisingEdge(self.dut.clk)
self.dut.rst <= 1 self.dut.rst.value = 1
await RisingEdge(self.dut.clk) await RisingEdge(self.dut.clk)
await RisingEdge(self.dut.clk) await RisingEdge(self.dut.clk)
self.dut.rst <= 0 self.dut.rst.value = 0
await RisingEdge(self.dut.clk) await RisingEdge(self.dut.clk)
await RisingEdge(self.dut.clk) await RisingEdge(self.dut.clk)
@@ -74,15 +74,17 @@ class TB:
self._enable_generator = generator self._enable_generator = generator
if self._enable_generator is not None: if self._enable_generator is not None:
self._enable_cr = cocotb.fork(self._run_enable()) self._enable_cr = cocotb.start_soon(self._run_enable())
def clear_enable_generator(self): def clear_enable_generator(self):
self.set_enable_generator(None) self.set_enable_generator(None)
async def _run_enable(self): async def _run_enable(self):
clock_edge_event = RisingEdge(self.dut.clk)
for val in self._enable_generator: for val in self._enable_generator:
self.dut.xgmii_clk_en <= val self.dut.xgmii_clk_en.value = val
await RisingEdge(self.dut.clk) await clock_edge_event
async def run_test(dut, payload_lengths=None, payload_data=None, ifg=12, enable_dic=True, async def run_test(dut, payload_lengths=None, payload_data=None, ifg=12, enable_dic=True,