23 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
Alex Forencich
6a35c31b4b Release v0.1.18 2021-11-07 12:40:42 -08:00
Alex Forencich
73fe54705f Remove deprecated assignments 2021-11-07 01:21:39 -08:00
Alex Forencich
448451e274 Add BASE-R related mappings 2021-10-15 02:00:03 -07:00
Alex Forencich
21c2c05c57 Normalize names 2021-10-14 19:13:51 -07:00
Alex Forencich
ab84a3b100 Add cocotb framework classifier 2021-08-31 14:43:03 -07:00
Alex Forencich
0f3060b9ba Bump to dev version 2021-08-31 01:04:20 -07:00
21 changed files with 383 additions and 187 deletions

View File

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

View File

@@ -42,12 +42,12 @@ class XgmiiCtrl(enum.IntEnum):
TERM = 0xfd
ERROR = 0xfe
SEQ_OS = 0x9c
RES0 = 0x1c
RES1 = 0x3c
RES2 = 0x7c
RES3 = 0xbc
RES4 = 0xdc
RES5 = 0xf7
RES_0 = 0x1c
RES_1 = 0x3c
RES_2 = 0x7c
RES_3 = 0xbc
RES_4 = 0xdc
RES_5 = 0xf7
SIG_OS = 0x5c
@@ -93,3 +93,41 @@ class BaseRBlockType(enum.IntEnum):
TERM_5 = 0xd2 # C7 C6 D4 D3 D2 D1 D0 BT
TERM_6 = 0xe1 # C7 D5 D4 D3 D2 D1 D0 BT
TERM_7 = 0xff # D6 D5 D4 D3 D2 D1 D0 BT
xgmii_ctrl_to_baser_mapping = {
XgmiiCtrl.IDLE: BaseRCtrl.IDLE,
XgmiiCtrl.LPI: BaseRCtrl.LPI,
XgmiiCtrl.ERROR: BaseRCtrl.ERROR,
XgmiiCtrl.RES_0: BaseRCtrl.RES_0,
XgmiiCtrl.RES_1: BaseRCtrl.RES_1,
XgmiiCtrl.RES_2: BaseRCtrl.RES_2,
XgmiiCtrl.RES_3: BaseRCtrl.RES_3,
XgmiiCtrl.RES_4: BaseRCtrl.RES_4,
XgmiiCtrl.RES_5: BaseRCtrl.RES_5,
}
baser_ctrl_to_xgmii_mapping = {
BaseRCtrl.IDLE: XgmiiCtrl.IDLE,
BaseRCtrl.LPI: XgmiiCtrl.LPI,
BaseRCtrl.ERROR: XgmiiCtrl.ERROR,
BaseRCtrl.RES_0: XgmiiCtrl.RES_0,
BaseRCtrl.RES_1: XgmiiCtrl.RES_1,
BaseRCtrl.RES_2: XgmiiCtrl.RES_2,
BaseRCtrl.RES_3: XgmiiCtrl.RES_3,
BaseRCtrl.RES_4: XgmiiCtrl.RES_4,
BaseRCtrl.RES_5: XgmiiCtrl.RES_5,
}
block_type_term_lane_mapping = {
BaseRBlockType.TERM_0: 0,
BaseRBlockType.TERM_1: 1,
BaseRBlockType.TERM_2: 2,
BaseRBlockType.TERM_3: 3,
BaseRBlockType.TERM_4: 4,
BaseRBlockType.TERM_5: 5,
BaseRBlockType.TERM_6: 6,
BaseRBlockType.TERM_7: 7,
}

View File

@@ -253,7 +253,7 @@ class EthMacTx(Reset):
self._run_ts_cr = None
if self.ptp_ts_valid:
self.ptp_ts_valid <= 0
self.ptp_ts_valid.value = 0
self.active = False
@@ -262,9 +262,9 @@ class EthMacTx(Reset):
else:
self.log.info("Reset de-asserted")
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:
self._run_ts_cr = cocotb.fork(self._run_ts())
self._run_ts_cr = cocotb.start_soon(self._run_ts())
async def _run(self):
frame = None
@@ -322,16 +322,18 @@ class EthMacTx(Reset):
await Timer(self.time_scale*self.ifg*8//self.speed, 'step')
async def _run_ts(self):
clock_edge_event = RisingEdge(self.clock)
while True:
await RisingEdge(self.clock)
self.ptp_ts_valid <= 0
await clock_edge_event
self.ptp_ts_valid.value = 0
if not self.ts_queue.empty():
ts, tag = self.ts_queue.get_nowait()
self.ptp_ts <= ts
self.ptp_ts.value = ts
if self.ptp_ts_tag is not None:
self.ptp_ts_tag <= tag
self.ptp_ts_valid <= 1
self.ptp_ts_tag.value = tag
self.ptp_ts_valid.value = 1
class EthMacRx(Reset):
@@ -475,7 +477,7 @@ class EthMacRx(Reset):
else:
self.log.info("Reset de-asserted")
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):
frame = None

View File

@@ -157,6 +157,7 @@ class GmiiSource(Reset):
self.current_frame = None
self.idle_event = Event()
self.idle_event.set()
self.active_event = Event()
self.ifg = 12
self.mii_mode = False
@@ -189,6 +190,7 @@ class GmiiSource(Reset):
frame = GmiiFrame(frame)
await self.queue.put(frame)
self.idle_event.clear()
self.active_event.set()
self.queue_occupancy_bytes += len(frame)
self.queue_occupancy_frames += 1
@@ -198,6 +200,7 @@ class GmiiSource(Reset):
frame = GmiiFrame(frame)
self.queue.put_nowait(frame)
self.idle_event.clear()
self.active_event.set()
self.queue_occupancy_bytes += len(frame)
self.queue_occupancy_frames += 1
@@ -225,6 +228,7 @@ class GmiiSource(Reset):
frame.handle_tx_complete()
self.dequeue_event.set()
self.idle_event.set()
self.active_event.clear()
self.queue_occupancy_bytes = 0
self.queue_occupancy_frames = 0
@@ -239,10 +243,10 @@ class GmiiSource(Reset):
self._run_cr = None
self.active = False
self.data <= 0
self.data.value = 0
if self.er is not None:
self.er <= 0
self.dv <= 0
self.er.value = 0
self.dv.value = 0
if self.current_frame:
self.log.warning("Flushed transmit frame during reset: %s", self.current_frame)
@@ -251,10 +255,11 @@ class GmiiSource(Reset):
if self.queue.empty():
self.idle_event.set()
self.active_event.clear()
else:
self.log.info("Reset de-asserted")
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):
frame = None
@@ -264,8 +269,14 @@ class GmiiSource(Reset):
ifg_cnt = 0
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:
await RisingEdge(self.clock)
await clock_edge_event
if self.enable is None or self.enable.value:
if ifg_cnt > 0:
@@ -308,10 +319,10 @@ class GmiiSource(Reset):
d = frame_data[frame_offset]
if frame.sim_time_sfd is None and d in (EthPre.SFD, 0xD):
frame.sim_time_sfd = get_sim_time()
self.data <= d
self.data.value = d
if self.er is not None:
self.er <= frame_error[frame_offset]
self.dv <= 1
self.er.value = frame_error[frame_offset]
self.dv.value = 1
frame_offset += 1
if frame_offset >= len(frame_data):
@@ -321,12 +332,19 @@ class GmiiSource(Reset):
frame = None
self.current_frame = None
else:
self.data <= 0
self.data.value = 0
if self.er is not None:
self.er <= 0
self.dv <= 0
self.er.value = 0
self.dv.value = 0
self.active = False
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):
@@ -422,14 +440,22 @@ class GmiiSink(Reset):
else:
self.log.info("Reset de-asserted")
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):
frame = None
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:
await RisingEdge(self.clock)
await clock_edge_event
if self.enable is None or self.enable.value:
d_val = self.data.value.integer
@@ -488,6 +514,12 @@ class GmiiSink(Reset):
frame.data.append(d_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:
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()
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.rx.mii_mode = False
self.tx.clock = self.gtx_clk
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.rx.mii_mode = True
self.tx.clock = self.tx_clk
@@ -536,8 +568,8 @@ class GmiiPhy:
while True:
await t
self.rx_clk <= 1
self.tx_clk <= 1
self.rx_clk.value = 1
self.tx_clk.value = 1
await t
self.rx_clk <= 0
self.tx_clk <= 0
self.rx_clk.value = 0
self.tx_clk.value = 0

View File

@@ -59,6 +59,7 @@ class MiiSource(Reset):
self.current_frame = None
self.idle_event = Event()
self.idle_event.set()
self.active_event = Event()
self.ifg = 12
@@ -90,6 +91,7 @@ class MiiSource(Reset):
frame = GmiiFrame(frame)
await self.queue.put(frame)
self.idle_event.clear()
self.active_event.set()
self.queue_occupancy_bytes += len(frame)
self.queue_occupancy_frames += 1
@@ -99,6 +101,7 @@ class MiiSource(Reset):
frame = GmiiFrame(frame)
self.queue.put_nowait(frame)
self.idle_event.clear()
self.active_event.set()
self.queue_occupancy_bytes += len(frame)
self.queue_occupancy_frames += 1
@@ -126,6 +129,7 @@ class MiiSource(Reset):
frame.handle_tx_complete()
self.dequeue_event.set()
self.idle_event.set()
self.active_event.clear()
self.queue_occupancy_bytes = 0
self.queue_occupancy_frames = 0
@@ -140,10 +144,10 @@ class MiiSource(Reset):
self._run_cr = None
self.active = False
self.data <= 0
self.data.value = 0
if self.er is not None:
self.er <= 0
self.dv <= 0
self.er.value = 0
self.dv.value = 0
if self.current_frame:
self.log.warning("Flushed transmit frame during reset: %s", self.current_frame)
@@ -152,10 +156,11 @@ class MiiSource(Reset):
if self.queue.empty():
self.idle_event.set()
self.active_event.clear()
else:
self.log.info("Reset de-asserted")
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):
frame = None
@@ -165,8 +170,14 @@ class MiiSource(Reset):
ifg_cnt = 0
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:
await RisingEdge(self.clock)
await clock_edge_event
if self.enable is None or self.enable.value:
if ifg_cnt > 0:
@@ -202,10 +213,10 @@ class MiiSource(Reset):
d = frame_data[frame_offset]
if frame.sim_time_sfd is None and d == 0xD:
frame.sim_time_sfd = get_sim_time()
self.data <= d
self.data.value = d
if self.er is not None:
self.er <= frame_error[frame_offset]
self.dv <= 1
self.er.value = frame_error[frame_offset]
self.dv.value = 1
frame_offset += 1
if frame_offset >= len(frame_data):
@@ -215,12 +226,19 @@ class MiiSource(Reset):
frame = None
self.current_frame = None
else:
self.data <= 0
self.data.value = 0
if self.er is not None:
self.er <= 0
self.dv <= 0
self.er.value = 0
self.dv.value = 0
self.active = False
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):
@@ -313,14 +331,22 @@ class MiiSink(Reset):
else:
self.log.info("Reset de-asserted")
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):
frame = None
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:
await RisingEdge(self.clock)
await clock_edge_event
if self.enable is None or self.enable.value:
d_val = self.data.value.integer
@@ -374,6 +400,12 @@ class MiiSink(Reset):
frame.data.append(d_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:
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:
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):
half_period = get_sim_steps(period / 2.0, 'ns')
@@ -410,8 +442,8 @@ class MiiPhy:
while True:
await t
self.tx_clk <= 1
self.rx_clk <= 1
self.tx_clk.value = 1
self.rx_clk.value = 1
await t
self.tx_clk <= 0
self.rx_clk <= 0
self.tx_clk.value = 0
self.rx_clk.value = 0

View File

@@ -195,28 +195,30 @@ class PtpClock(Reset):
self.ts_64_fns = 0
self.drift_cnt = 0
if self.ts_96 is not None:
self.ts_96 <= 0
self.ts_96.value = 0
if self.ts_64 is not None:
self.ts_64 <= 0
self.ts_64.value = 0
if self.ts_step is not None:
self.ts_step <= 0
self.ts_step.value = 0
if self.pps is not None:
self.pps <= 0
self.pps.value = 0
else:
self.log.info("Reset de-asserted")
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):
clock_edge_event = RisingEdge(self.clock)
while True:
await RisingEdge(self.clock)
await clock_edge_event
if self.ts_step is not None:
self.ts_step <= self.ts_updated
self.ts_step.value = self.ts_updated
self.ts_updated = False
if self.pps is not None:
self.pps <= 0
self.pps.value = 0
# increment 96 bit timestamp
if self.ts_96 is not None or self.pps is not None:
@@ -229,13 +231,13 @@ class PtpClock(Reset):
self.ts_96_s += 1
t -= (1000000000 << 16)
if self.pps is not None:
self.pps <= 1
self.pps.value = 1
self.ts_96_fns = t & 0xffff
self.ts_96_ns = t >> 16
if self.ts_96 is not None:
self.ts_96 <= (self.ts_96_s << 48) | (self.ts_96_ns << 16) | (self.ts_96_fns)
self.ts_96.value = (self.ts_96_s << 48) | (self.ts_96_ns << 16) | (self.ts_96_fns)
# increment 64 bit timestamp
if self.ts_64 is not None:
@@ -247,7 +249,7 @@ class PtpClock(Reset):
self.ts_64_fns = t & 0xffff
self.ts_64_ns = t >> 16
self.ts_64 <= (self.ts_64_ns << 16) | self.ts_64_fns
self.ts_64.value = (self.ts_64_ns << 16) | self.ts_64_fns
if self.drift_rate:
if self.drift_cnt > 0:
@@ -286,9 +288,9 @@ class PtpClockSimTime:
if self.ts_64 is not None:
self.ts_64.setimmediatevalue(0)
if self.pps is not None:
self.pps <= 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):
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
async def _run(self):
clock_edge_event = RisingEdge(self.clock)
while True:
await RisingEdge(self.clock)
await clock_edge_event
self.ts_64_fns, self.ts_64_ns = math.modf(get_sim_time('ns'))
@@ -321,12 +325,12 @@ class PtpClockSimTime:
self.ts_96_fns = self.ts_64_fns
if self.ts_96 is not None:
self.ts_96 <= (self.ts_96_s << 48) | (self.ts_96_ns << 16) | self.ts_96_fns
self.ts_96.value = (self.ts_96_s << 48) | (self.ts_96_ns << 16) | self.ts_96_fns
if self.ts_64 is not None:
self.ts_64 <= (self.ts_64_ns << 16) | self.ts_64_fns
self.ts_64.value = (self.ts_64_ns << 16) | self.ts_64_fns
if self.pps is not None:
self.pps <= int(self.last_ts_96_s != self.ts_96_s)
self.pps.value = int(self.last_ts_96_s != self.ts_96_s)
self.last_ts_96_s = self.ts_96_s

View File

@@ -33,7 +33,7 @@ class Reset:
self._reset_state = True
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()

View File

@@ -61,6 +61,7 @@ class RgmiiSource(Reset):
self.current_frame = None
self.idle_event = Event()
self.idle_event.set()
self.active_event = Event()
self.ifg = 12
self.mii_mode = False
@@ -90,6 +91,7 @@ class RgmiiSource(Reset):
frame = GmiiFrame(frame)
await self.queue.put(frame)
self.idle_event.clear()
self.active_event.set()
self.queue_occupancy_bytes += len(frame)
self.queue_occupancy_frames += 1
@@ -99,6 +101,7 @@ class RgmiiSource(Reset):
frame = GmiiFrame(frame)
self.queue.put_nowait(frame)
self.idle_event.clear()
self.active_event.set()
self.queue_occupancy_bytes += len(frame)
self.queue_occupancy_frames += 1
@@ -126,6 +129,7 @@ class RgmiiSource(Reset):
frame.handle_tx_complete()
self.dequeue_event.set()
self.idle_event.set()
self.active_event.clear()
self.queue_occupancy_bytes = 0
self.queue_occupancy_frames = 0
@@ -140,8 +144,8 @@ class RgmiiSource(Reset):
self._run_cr = None
self.active = False
self.data <= 0
self.ctrl <= 0
self.data.value = 0
self.ctrl.value = 0
if self.current_frame:
self.log.warning("Flushed transmit frame during reset: %s", self.current_frame)
@@ -150,10 +154,11 @@ class RgmiiSource(Reset):
if self.queue.empty():
self.idle_event.set()
self.active_event.clear()
else:
self.log.info("Reset de-asserted")
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):
frame = None
@@ -161,22 +166,39 @@ class RgmiiSource(Reset):
frame_data = None
frame_error = None
ifg_cnt = 0
in_ifg = False
self.active = False
d = 0
er = 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:
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
self.data <= d >> 4
self.ctrl <= en ^ er
self.data.value = d >> 4
self.ctrl.value = en ^ er
if self.enable is None or self.enable.value:
in_ifg = False
if ifg_cnt > 0:
# in IFG
ifg_cnt -= 1
in_ifg = True
elif frame is None and not self.queue.empty():
# send frame
@@ -221,6 +243,7 @@ class RgmiiSource(Reset):
if frame_offset >= len(frame_data):
ifg_cnt = max(self.ifg, 1)
in_ifg = True
frame.sim_time_end = get_sim_time()
frame.handle_tx_complete()
frame = None
@@ -230,13 +253,14 @@ class RgmiiSource(Reset):
er = 0
en = 0
self.active = False
if not in_ifg and self.queue.empty():
self.idle_event.set()
self.active_event.clear()
await self.active_event.wait()
await FallingEdge(self.clock)
# send low nibble after falling edge, leading in to rising edge
self.data <= d & 0x0F
self.ctrl <= en
elif self.enable is not None and not self.enable.value:
await enable_event
class RgmiiSink(Reset):
@@ -330,7 +354,7 @@ class RgmiiSink(Reset):
else:
self.log.info("Reset de-asserted")
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):
frame = None
@@ -339,21 +363,30 @@ class RgmiiSink(Reset):
dv_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:
await RisingEdge(self.clock)
await clock_rising_edge_event
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 FallingEdge(self.clock)
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 self.enable is None or self.enable.value:
if frame is None:
if dv_val:
# start of frame
@@ -406,6 +439,12 @@ class RgmiiSink(Reset):
frame.data.append(d_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:
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()
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.rx.mii_mode = False
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.rx.mii_mode = True
@@ -448,6 +487,6 @@ class RgmiiPhy:
while True:
await t
self.rx_clk <= 1
self.rx_clk.value = 1
await t
self.rx_clk <= 0
self.rx_clk.value = 0

View File

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

View File

@@ -28,7 +28,7 @@ import zlib
import cocotb
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 .version import __version__
@@ -158,6 +158,7 @@ class XgmiiSource(Reset):
self.current_frame = None
self.idle_event = Event()
self.idle_event.set()
self.active_event = Event()
self.enable_dic = True
self.ifg = 12
@@ -200,6 +201,7 @@ class XgmiiSource(Reset):
frame = XgmiiFrame(frame)
await self.queue.put(frame)
self.idle_event.clear()
self.active_event.set()
self.queue_occupancy_bytes += len(frame)
self.queue_occupancy_frames += 1
@@ -209,6 +211,7 @@ class XgmiiSource(Reset):
frame = XgmiiFrame(frame)
self.queue.put_nowait(frame)
self.idle_event.clear()
self.active_event.set()
self.queue_occupancy_bytes += len(frame)
self.queue_occupancy_frames += 1
@@ -236,6 +239,7 @@ class XgmiiSource(Reset):
frame.handle_tx_complete()
self.dequeue_event.set()
self.idle_event.set()
self.active_event.clear()
self.queue_occupancy_bytes = 0
self.queue_occupancy_frames = 0
@@ -250,8 +254,8 @@ class XgmiiSource(Reset):
self._run_cr = None
self.active = False
self.data <= 0
self.ctrl <= 0
self.data.value = 0
self.ctrl.value = 0
if self.current_frame:
self.log.warning("Flushed transmit frame during reset: %s", self.current_frame)
@@ -260,10 +264,11 @@ class XgmiiSource(Reset):
if self.queue.empty():
self.idle_event.set()
self.active_event.clear()
else:
self.log.info("Reset de-asserted")
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):
frame = None
@@ -272,8 +277,14 @@ class XgmiiSource(Reset):
deficit_idle_cnt = 0
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:
await RisingEdge(self.clock)
await clock_edge_event
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):
@@ -351,13 +362,20 @@ class XgmiiSource(Reset):
d_val |= XgmiiCtrl.IDLE << k*8
c_val |= 1 << k
self.data <= d_val
self.ctrl <= c_val
self.data.value = d_val
self.ctrl.value = c_val
else:
self.data <= self.idle_d
self.ctrl <= self.idle_c
self.data.value = self.idle_d
self.ctrl.value = self.idle_c
self.active = False
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):
@@ -450,19 +468,32 @@ class XgmiiSink(Reset):
else:
self.log.info("Reset de-asserted")
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):
frame = None
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:
await RisingEdge(self.clock)
await clock_edge_event
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):
d_val = (self.data.value.integer >> (offset*8)) & 0xff
c_val = (self.ctrl.value.integer >> offset) & 1
d_val = (data_val >> (offset*8)) & 0xff
c_val = (ctrl_val >> offset) & 1
if frame is None:
if c_val and d_val == XgmiiCtrl.START:
@@ -495,3 +526,9 @@ class XgmiiSink(Reset):
frame.data.append(d_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

@@ -17,17 +17,18 @@ long-description-content-type = text/markdown
platforms = any
classifiers =
Development Status :: 3 - Alpha
Programming Language :: Python :: 3
Framework :: cocotb
License :: OSI Approved :: MIT License
Operating System :: OS Independent
Programming Language :: Python :: 3
Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)
[options]
packages = find_namespace:
python_requires = >=3.6
install_requires =
cocotb
cocotbext-axi
cocotb >= 1.6.0
cocotbext-axi >= 0.1.16
[options.extras_require]
test =
@@ -46,31 +47,39 @@ addopts =
# tox configuration
[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]
python =
3.6: py36
3.7: py37
3.8: py38
3.9: py39
3.10: py310
[testenv]
setenv =
COVERAGE=1
usedevelop = True
deps =
pytest
pytest-xdist
cocotb-test
coverage
pytest-cov
pytest == 7.2.1
pytest-xdist == 3.1.0
cocotb == 1.7.2
cocotb-bus == 0.2.1
cocotb-test == 0.2.4
cocotbext-axi == 0.1.20
coverage == 7.0.5
pytest-cov == 4.0.0
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'
coverage report
whitelist_externals =
allowlist_externals =
bash
# combine if paths are different

View File

@@ -45,8 +45,8 @@ class TB:
self.log = logging.getLogger("cocotb.tb")
self.log.setLevel(logging.DEBUG)
cocotb.fork(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.tx_clk, 6.4, units="ns").start())
cocotb.start_soon(Clock(dut.rx_clk, 6.4, units="ns").start())
self.mac = EthMac(
tx_clk=dut.tx_clk,
@@ -81,12 +81,12 @@ class TB:
self.dut.rx_rst.setimmediatevalue(0)
await RisingEdge(self.dut.tx_clk)
await RisingEdge(self.dut.tx_clk)
self.dut.tx_rst <= 1
self.dut.rx_rst <= 1
self.dut.tx_rst.value = 1
self.dut.rx_rst.value = 1
await RisingEdge(self.dut.tx_clk)
await RisingEdge(self.dut.tx_clk)
self.dut.tx_rst <= 0
self.dut.rx_rst <= 0
self.dut.tx_rst.value = 0
self.dut.rx_rst.value = 0
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_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,
dut.clk, dut.rst, dut.gmii_clk_en, dut.gmii_mii_sel)
@@ -61,10 +61,10 @@ class TB:
self.dut.rst.setimmediatevalue(0)
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)
self.dut.rst <= 0
self.dut.rst.value = 0
await RisingEdge(self.dut.clk)
await RisingEdge(self.dut.clk)
@@ -76,15 +76,17 @@ class TB:
self._enable_generator = generator
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):
self.set_enable_generator(None)
async def _run_enable(self):
clock_edge_event = RisingEdge(self.dut.clk)
for val in self._enable_generator:
self.dut.gmii_clk_en <= val
await RisingEdge(self.dut.clk)
self.dut.gmii_clk_en.value = val
await clock_edge_event
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.source.ifg = ifg
tb.dut.gmii_mii_sel <= mii_sel
tb.dut.gmii_mii_sel.value = mii_sel
if enable_gen is not None:
tb.set_enable_generator(enable_gen())

View File

@@ -44,7 +44,7 @@ class TB:
self.log = logging.getLogger("cocotb.tb")
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,
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)
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)
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)

View File

@@ -47,7 +47,7 @@ class TB:
self._enable_generator = 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,
dut.clk, dut.rst, dut.mii_clk_en)
@@ -60,10 +60,10 @@ class TB:
self.dut.rst.setimmediatevalue(0)
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)
self.dut.rst <= 0
self.dut.rst.value = 0
await RisingEdge(self.dut.clk)
await RisingEdge(self.dut.clk)
@@ -75,15 +75,17 @@ class TB:
self._enable_generator = generator
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):
self.set_enable_generator(None)
async def _run_enable(self):
clock_edge_event = RisingEdge(self.dut.clk)
for val in self._enable_generator:
self.dut.mii_clk_en <= val
await RisingEdge(self.dut.clk)
self.dut.mii_clk_en.value = val
await clock_edge_event
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)
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)
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)

View File

@@ -30,7 +30,7 @@ import cocotb_test.simulator
import cocotb
from cocotb.clock import Clock
from cocotb.triggers import RisingEdge
from cocotb.triggers import RisingEdge, ClockCycles
from cocotb.utils import get_sim_time
from cocotbext.eth import PtpClock
@@ -43,7 +43,7 @@ class TB:
self.log = logging.getLogger("cocotb.tb")
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(
ts_96=dut.ts_96,
@@ -59,10 +59,10 @@ class TB:
self.dut.rst.setimmediatevalue(0)
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)
self.dut.rst <= 0
self.dut.rst.value = 0
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_64 = dut.ts_64.value.integer/2**16*1e-9
for k in range(10000):
await RisingEdge(dut.clk)
await ClockCycles(dut.clk, 10000)
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)
@@ -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_64 = dut.ts_64.value.integer/2**16*1e-9
for k in range(2000):
await RisingEdge(dut.clk)
await ClockCycles(dut.clk, 2000)
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)
@@ -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_64 = dut.ts_64.value.integer/2**16*1e-9
for k in range(10000):
await RisingEdge(dut.clk)
await ClockCycles(dut.clk, 10000)
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)
@@ -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_64 = dut.ts_64.value.integer/2**16*1e-9
for k in range(10000):
await RisingEdge(dut.clk)
await ClockCycles(dut.clk, 10000)
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)

View File

@@ -30,7 +30,7 @@ import cocotb_test.simulator
import cocotb
from cocotb.clock import Clock
from cocotb.triggers import RisingEdge
from cocotb.triggers import RisingEdge, ClockCycles
from cocotb.utils import get_sim_time
from cocotbext.eth import PtpClockSimTime
@@ -43,7 +43,7 @@ class TB:
self.log = logging.getLogger("cocotb.tb")
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(
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_64 = dut.ts_64.value.integer/2**16*1e-9
for k in range(10000):
await RisingEdge(dut.clk)
await ClockCycles(dut.clk, 10000)
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)

View File

@@ -47,7 +47,7 @@ class TB:
self._enable_generator = 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.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)
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)
self.dut.rst <= 0
self.dut.rst.value = 0
await RisingEdge(self.dut.clk)
await RisingEdge(self.dut.clk)
@@ -74,15 +74,17 @@ class TB:
self._enable_generator = generator
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):
self.set_enable_generator(None)
async def _run_enable(self):
clock_edge_event = RisingEdge(self.dut.clk)
for val in self._enable_generator:
self.dut.rgmii_clk_en <= val
await RisingEdge(self.dut.clk)
self.dut.rgmii_clk_en.value = val
await clock_edge_event
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.source.ifg = ifg
tb.dut.rgmii_mii_sel <= mii_sel
tb.dut.rgmii_mii_sel.value = mii_sel
if enable_gen is not None:
tb.set_enable_generator(enable_gen())

View File

@@ -45,11 +45,11 @@ class TB:
self.log.setLevel(logging.DEBUG)
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:
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:
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,
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)
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)
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)

View File

@@ -48,7 +48,7 @@ class TB:
self._enable_generator = 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.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)
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)
self.dut.rst <= 0
self.dut.rst.value = 0
await RisingEdge(self.dut.clk)
await RisingEdge(self.dut.clk)
@@ -74,15 +74,17 @@ class TB:
self._enable_generator = generator
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):
self.set_enable_generator(None)
async def _run_enable(self):
clock_edge_event = RisingEdge(self.dut.clk)
for val in self._enable_generator:
self.dut.xgmii_clk_en <= val
await RisingEdge(self.dut.clk)
self.dut.xgmii_clk_en.value = val
await clock_edge_event
async def run_test(dut, payload_lengths=None, payload_data=None, ifg=12, enable_dic=True,