Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2bfe8a0e50 | ||
|
|
9c88b0440e | ||
|
|
37b23c358b | ||
|
|
dd35d734f9 | ||
|
|
45ee1193cb | ||
|
|
5caafbb9e7 | ||
|
|
2d4450e048 | ||
|
|
c5d28182c4 | ||
|
|
79991205b5 | ||
|
|
a22123649c | ||
|
|
b5ba332ecc | ||
|
|
eb62e43fd1 | ||
|
|
5c4ef258ac | ||
|
|
6c5845fad3 | ||
|
|
32f6e449c0 | ||
|
|
2af7852006 | ||
|
|
3325568406 | ||
|
|
6a35c31b4b | ||
|
|
73fe54705f | ||
|
|
448451e274 | ||
|
|
21c2c05c57 | ||
|
|
ab84a3b100 | ||
|
|
0f3060b9ba |
6
.github/workflows/regression-tests.yml
vendored
6
.github/workflows/regression-tests.yml
vendored
@@ -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 }}
|
||||||
|
|
||||||
|
|||||||
@@ -42,12 +42,12 @@ class XgmiiCtrl(enum.IntEnum):
|
|||||||
TERM = 0xfd
|
TERM = 0xfd
|
||||||
ERROR = 0xfe
|
ERROR = 0xfe
|
||||||
SEQ_OS = 0x9c
|
SEQ_OS = 0x9c
|
||||||
RES0 = 0x1c
|
RES_0 = 0x1c
|
||||||
RES1 = 0x3c
|
RES_1 = 0x3c
|
||||||
RES2 = 0x7c
|
RES_2 = 0x7c
|
||||||
RES3 = 0xbc
|
RES_3 = 0xbc
|
||||||
RES4 = 0xdc
|
RES_4 = 0xdc
|
||||||
RES5 = 0xf7
|
RES_5 = 0xf7
|
||||||
SIG_OS = 0x5c
|
SIG_OS = 0x5c
|
||||||
|
|
||||||
|
|
||||||
@@ -93,3 +93,41 @@ class BaseRBlockType(enum.IntEnum):
|
|||||||
TERM_5 = 0xd2 # C7 C6 D4 D3 D2 D1 D0 BT
|
TERM_5 = 0xd2 # C7 C6 D4 D3 D2 D1 D0 BT
|
||||||
TERM_6 = 0xe1 # C7 D5 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
|
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,
|
||||||
|
}
|
||||||
|
|||||||
@@ -253,7 +253,7 @@ class EthMacTx(Reset):
|
|||||||
self._run_ts_cr = None
|
self._run_ts_cr = None
|
||||||
|
|
||||||
if self.ptp_ts_valid:
|
if self.ptp_ts_valid:
|
||||||
self.ptp_ts_valid <= 0
|
self.ptp_ts_valid.value = 0
|
||||||
|
|
||||||
self.active = False
|
self.active = False
|
||||||
|
|
||||||
@@ -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,16 +322,18 @@ 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 <= 0
|
self.ptp_ts_valid.value = 0
|
||||||
|
|
||||||
if not self.ts_queue.empty():
|
if not self.ts_queue.empty():
|
||||||
ts, tag = self.ts_queue.get_nowait()
|
ts, tag = self.ts_queue.get_nowait()
|
||||||
self.ptp_ts <= ts
|
self.ptp_ts.value = ts
|
||||||
if self.ptp_ts_tag is not None:
|
if self.ptp_ts_tag is not None:
|
||||||
self.ptp_ts_tag <= tag
|
self.ptp_ts_tag.value = tag
|
||||||
self.ptp_ts_valid <= 1
|
self.ptp_ts_valid.value = 1
|
||||||
|
|
||||||
|
|
||||||
class EthMacRx(Reset):
|
class EthMacRx(Reset):
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
@@ -239,10 +243,10 @@ class GmiiSource(Reset):
|
|||||||
self._run_cr = None
|
self._run_cr = None
|
||||||
|
|
||||||
self.active = False
|
self.active = False
|
||||||
self.data <= 0
|
self.data.value = 0
|
||||||
if self.er is not None:
|
if self.er is not None:
|
||||||
self.er <= 0
|
self.er.value = 0
|
||||||
self.dv <= 0
|
self.dv.value = 0
|
||||||
|
|
||||||
if self.current_frame:
|
if self.current_frame:
|
||||||
self.log.warning("Flushed transmit frame during reset: %s", 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():
|
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:
|
||||||
@@ -308,10 +319,10 @@ class GmiiSource(Reset):
|
|||||||
d = frame_data[frame_offset]
|
d = frame_data[frame_offset]
|
||||||
if frame.sim_time_sfd is None and d in (EthPre.SFD, 0xD):
|
if frame.sim_time_sfd is None and d in (EthPre.SFD, 0xD):
|
||||||
frame.sim_time_sfd = get_sim_time()
|
frame.sim_time_sfd = get_sim_time()
|
||||||
self.data <= d
|
self.data.value = d
|
||||||
if self.er is not None:
|
if self.er is not None:
|
||||||
self.er <= frame_error[frame_offset]
|
self.er.value = frame_error[frame_offset]
|
||||||
self.dv <= 1
|
self.dv.value = 1
|
||||||
frame_offset += 1
|
frame_offset += 1
|
||||||
|
|
||||||
if frame_offset >= len(frame_data):
|
if frame_offset >= len(frame_data):
|
||||||
@@ -321,12 +332,19 @@ class GmiiSource(Reset):
|
|||||||
frame = None
|
frame = None
|
||||||
self.current_frame = None
|
self.current_frame = None
|
||||||
else:
|
else:
|
||||||
self.data <= 0
|
self.data.value = 0
|
||||||
if self.er is not None:
|
if self.er is not None:
|
||||||
self.er <= 0
|
self.er.value = 0
|
||||||
self.dv <= 0
|
self.dv.value = 0
|
||||||
self.active = False
|
self.active = False
|
||||||
|
|
||||||
|
if ifg_cnt == 0 and self.queue.empty():
|
||||||
self.idle_event.set()
|
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
|
||||||
@@ -536,8 +568,8 @@ class GmiiPhy:
|
|||||||
|
|
||||||
while True:
|
while True:
|
||||||
await t
|
await t
|
||||||
self.rx_clk <= 1
|
self.rx_clk.value = 1
|
||||||
self.tx_clk <= 1
|
self.tx_clk.value = 1
|
||||||
await t
|
await t
|
||||||
self.rx_clk <= 0
|
self.rx_clk.value = 0
|
||||||
self.tx_clk <= 0
|
self.tx_clk.value = 0
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
@@ -140,10 +144,10 @@ class MiiSource(Reset):
|
|||||||
self._run_cr = None
|
self._run_cr = None
|
||||||
|
|
||||||
self.active = False
|
self.active = False
|
||||||
self.data <= 0
|
self.data.value = 0
|
||||||
if self.er is not None:
|
if self.er is not None:
|
||||||
self.er <= 0
|
self.er.value = 0
|
||||||
self.dv <= 0
|
self.dv.value = 0
|
||||||
|
|
||||||
if self.current_frame:
|
if self.current_frame:
|
||||||
self.log.warning("Flushed transmit frame during reset: %s", 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():
|
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:
|
||||||
@@ -202,10 +213,10 @@ class MiiSource(Reset):
|
|||||||
d = frame_data[frame_offset]
|
d = frame_data[frame_offset]
|
||||||
if frame.sim_time_sfd is None and d == 0xD:
|
if frame.sim_time_sfd is None and d == 0xD:
|
||||||
frame.sim_time_sfd = get_sim_time()
|
frame.sim_time_sfd = get_sim_time()
|
||||||
self.data <= d
|
self.data.value = d
|
||||||
if self.er is not None:
|
if self.er is not None:
|
||||||
self.er <= frame_error[frame_offset]
|
self.er.value = frame_error[frame_offset]
|
||||||
self.dv <= 1
|
self.dv.value = 1
|
||||||
frame_offset += 1
|
frame_offset += 1
|
||||||
|
|
||||||
if frame_offset >= len(frame_data):
|
if frame_offset >= len(frame_data):
|
||||||
@@ -215,12 +226,19 @@ class MiiSource(Reset):
|
|||||||
frame = None
|
frame = None
|
||||||
self.current_frame = None
|
self.current_frame = None
|
||||||
else:
|
else:
|
||||||
self.data <= 0
|
self.data.value = 0
|
||||||
if self.er is not None:
|
if self.er is not None:
|
||||||
self.er <= 0
|
self.er.value = 0
|
||||||
self.dv <= 0
|
self.dv.value = 0
|
||||||
self.active = False
|
self.active = False
|
||||||
|
|
||||||
|
if ifg_cnt == 0 and self.queue.empty():
|
||||||
self.idle_event.set()
|
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')
|
||||||
@@ -410,8 +442,8 @@ class MiiPhy:
|
|||||||
|
|
||||||
while True:
|
while True:
|
||||||
await t
|
await t
|
||||||
self.tx_clk <= 1
|
self.tx_clk.value = 1
|
||||||
self.rx_clk <= 1
|
self.rx_clk.value = 1
|
||||||
await t
|
await t
|
||||||
self.tx_clk <= 0
|
self.tx_clk.value = 0
|
||||||
self.rx_clk <= 0
|
self.rx_clk.value = 0
|
||||||
|
|||||||
@@ -195,28 +195,30 @@ class PtpClock(Reset):
|
|||||||
self.ts_64_fns = 0
|
self.ts_64_fns = 0
|
||||||
self.drift_cnt = 0
|
self.drift_cnt = 0
|
||||||
if self.ts_96 is not None:
|
if self.ts_96 is not None:
|
||||||
self.ts_96 <= 0
|
self.ts_96.value = 0
|
||||||
if self.ts_64 is not None:
|
if self.ts_64 is not None:
|
||||||
self.ts_64 <= 0
|
self.ts_64.value = 0
|
||||||
if self.ts_step is not None:
|
if self.ts_step is not None:
|
||||||
self.ts_step <= 0
|
self.ts_step.value = 0
|
||||||
if self.pps is not None:
|
if self.pps is not None:
|
||||||
self.pps <= 0
|
self.pps.value = 0
|
||||||
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 <= self.ts_updated
|
self.ts_step.value = self.ts_updated
|
||||||
self.ts_updated = False
|
self.ts_updated = False
|
||||||
|
|
||||||
if self.pps is not None:
|
if self.pps is not None:
|
||||||
self.pps <= 0
|
self.pps.value = 0
|
||||||
|
|
||||||
# increment 96 bit timestamp
|
# increment 96 bit timestamp
|
||||||
if self.ts_96 is not None or self.pps is not None:
|
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
|
self.ts_96_s += 1
|
||||||
t -= (1000000000 << 16)
|
t -= (1000000000 << 16)
|
||||||
if self.pps is not None:
|
if self.pps is not None:
|
||||||
self.pps <= 1
|
self.pps.value = 1
|
||||||
|
|
||||||
self.ts_96_fns = t & 0xffff
|
self.ts_96_fns = t & 0xffff
|
||||||
self.ts_96_ns = t >> 16
|
self.ts_96_ns = t >> 16
|
||||||
|
|
||||||
if self.ts_96 is not None:
|
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
|
# increment 64 bit timestamp
|
||||||
if self.ts_64 is not None:
|
if self.ts_64 is not None:
|
||||||
@@ -247,7 +249,7 @@ class PtpClock(Reset):
|
|||||||
self.ts_64_fns = t & 0xffff
|
self.ts_64_fns = t & 0xffff
|
||||||
self.ts_64_ns = t >> 16
|
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_rate:
|
||||||
if self.drift_cnt > 0:
|
if self.drift_cnt > 0:
|
||||||
@@ -286,9 +288,9 @@ class PtpClockSimTime:
|
|||||||
if self.ts_64 is not None:
|
if self.ts_64 is not None:
|
||||||
self.ts_64.setimmediatevalue(0)
|
self.ts_64.setimmediatevalue(0)
|
||||||
if self.pps is not None:
|
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):
|
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'))
|
||||||
|
|
||||||
@@ -321,12 +325,12 @@ class PtpClockSimTime:
|
|||||||
self.ts_96_fns = self.ts_64_fns
|
self.ts_96_fns = self.ts_64_fns
|
||||||
|
|
||||||
if self.ts_96 is not None:
|
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:
|
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:
|
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
|
self.last_ts_96_s = self.ts_96_s
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
@@ -140,8 +144,8 @@ class RgmiiSource(Reset):
|
|||||||
self._run_cr = None
|
self._run_cr = None
|
||||||
|
|
||||||
self.active = False
|
self.active = False
|
||||||
self.data <= 0
|
self.data.value = 0
|
||||||
self.ctrl <= 0
|
self.ctrl.value = 0
|
||||||
|
|
||||||
if self.current_frame:
|
if self.current_frame:
|
||||||
self.log.warning("Flushed transmit frame during reset: %s", 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():
|
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 <= d >> 4
|
self.data.value = d >> 4
|
||||||
self.ctrl <= 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
|
||||||
|
|
||||||
|
if not in_ifg and self.queue.empty():
|
||||||
self.idle_event.set()
|
self.idle_event.set()
|
||||||
|
self.active_event.clear()
|
||||||
|
await self.active_event.wait()
|
||||||
|
|
||||||
await FallingEdge(self.clock)
|
elif self.enable is not None and not self.enable.value:
|
||||||
|
await enable_event
|
||||||
# send low nibble after falling edge, leading in to rising edge
|
|
||||||
self.data <= d & 0x0F
|
|
||||||
self.ctrl <= 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
|
||||||
|
|
||||||
|
if self.enable is None or self.enable.value:
|
||||||
|
|
||||||
# capture low nibble on rising edge
|
# capture low nibble on rising edge
|
||||||
d_val = self.data.value.integer
|
d_val = self.data.value.integer
|
||||||
dv_val = self.ctrl.value.integer
|
dv_val = self.ctrl.value.integer
|
||||||
|
|
||||||
await FallingEdge(self.clock)
|
await clock_falling_edge_event
|
||||||
|
|
||||||
# capture high nibble on falling edge
|
# capture high nibble on falling edge
|
||||||
d_val |= self.data.value.integer << 4
|
d_val |= self.data.value.integer << 4
|
||||||
er_val = dv_val ^ self.ctrl.value.integer
|
er_val = dv_val ^ self.ctrl.value.integer
|
||||||
|
|
||||||
if self.enable is None or self.enable.value:
|
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
@@ -448,6 +487,6 @@ class RgmiiPhy:
|
|||||||
|
|
||||||
while True:
|
while True:
|
||||||
await t
|
await t
|
||||||
self.rx_clk <= 1
|
self.rx_clk.value = 1
|
||||||
await t
|
await t
|
||||||
self.rx_clk <= 0
|
self.rx_clk.value = 0
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
__version__ = "0.1.16"
|
__version__ = "0.1.20"
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
@@ -250,8 +254,8 @@ class XgmiiSource(Reset):
|
|||||||
self._run_cr = None
|
self._run_cr = None
|
||||||
|
|
||||||
self.active = False
|
self.active = False
|
||||||
self.data <= 0
|
self.data.value = 0
|
||||||
self.ctrl <= 0
|
self.ctrl.value = 0
|
||||||
|
|
||||||
if self.current_frame:
|
if self.current_frame:
|
||||||
self.log.warning("Flushed transmit frame during reset: %s", 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():
|
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):
|
||||||
@@ -351,13 +362,20 @@ class XgmiiSource(Reset):
|
|||||||
d_val |= XgmiiCtrl.IDLE << k*8
|
d_val |= XgmiiCtrl.IDLE << k*8
|
||||||
c_val |= 1 << k
|
c_val |= 1 << k
|
||||||
|
|
||||||
self.data <= d_val
|
self.data.value = d_val
|
||||||
self.ctrl <= c_val
|
self.ctrl.value = c_val
|
||||||
else:
|
else:
|
||||||
self.data <= self.idle_d
|
self.data.value = self.idle_d
|
||||||
self.ctrl <= self.idle_c
|
self.ctrl.value = self.idle_c
|
||||||
self.active = False
|
self.active = False
|
||||||
|
|
||||||
|
if ifg_cnt == 0 and self.queue.empty():
|
||||||
self.idle_event.set()
|
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
|
||||||
|
|||||||
33
setup.cfg
33
setup.cfg
@@ -17,17 +17,18 @@ long-description-content-type = text/markdown
|
|||||||
platforms = any
|
platforms = any
|
||||||
classifiers =
|
classifiers =
|
||||||
Development Status :: 3 - Alpha
|
Development Status :: 3 - Alpha
|
||||||
Programming Language :: Python :: 3
|
Framework :: cocotb
|
||||||
License :: OSI Approved :: MIT License
|
License :: OSI Approved :: MIT License
|
||||||
Operating System :: OS Independent
|
Operating System :: OS Independent
|
||||||
|
Programming Language :: Python :: 3
|
||||||
Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)
|
Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)
|
||||||
|
|
||||||
[options]
|
[options]
|
||||||
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 =
|
||||||
@@ -46,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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -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())
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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())
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user