Rework resets
This commit is contained in:
@@ -33,6 +33,7 @@ from cocotb.utils import get_sim_time
|
|||||||
|
|
||||||
from .version import __version__
|
from .version import __version__
|
||||||
from .constants import EthPre, ETH_PREAMBLE
|
from .constants import EthPre, ETH_PREAMBLE
|
||||||
|
from .reset import Reset
|
||||||
|
|
||||||
|
|
||||||
class GmiiFrame:
|
class GmiiFrame:
|
||||||
@@ -114,7 +115,7 @@ class GmiiFrame:
|
|||||||
return bytes(self.data)
|
return bytes(self.data)
|
||||||
|
|
||||||
|
|
||||||
class GmiiSource:
|
class GmiiSource(Reset):
|
||||||
|
|
||||||
def __init__(self, data, er, dv, clock, reset=None, enable=None, mii_select=None, *args, **kwargs):
|
def __init__(self, data, er, dv, clock, reset=None, enable=None, mii_select=None, *args, **kwargs):
|
||||||
self.log = logging.getLogger(f"cocotb.{data._path}")
|
self.log = logging.getLogger(f"cocotb.{data._path}")
|
||||||
@@ -145,8 +146,6 @@ class GmiiSource:
|
|||||||
self.width = 8
|
self.width = 8
|
||||||
self.byte_width = 1
|
self.byte_width = 1
|
||||||
|
|
||||||
self.reset = reset
|
|
||||||
|
|
||||||
assert len(self.data) == 8
|
assert len(self.data) == 8
|
||||||
self.data.setimmediatevalue(0)
|
self.data.setimmediatevalue(0)
|
||||||
if self.er is not None:
|
if self.er is not None:
|
||||||
@@ -155,7 +154,9 @@ class GmiiSource:
|
|||||||
assert len(self.dv) == 1
|
assert len(self.dv) == 1
|
||||||
self.dv.setimmediatevalue(0)
|
self.dv.setimmediatevalue(0)
|
||||||
|
|
||||||
cocotb.fork(self._run())
|
self._run_cr = None
|
||||||
|
|
||||||
|
self._init_reset(reset)
|
||||||
|
|
||||||
async def send(self, frame):
|
async def send(self, frame):
|
||||||
self.send_nowait(frame)
|
self.send_nowait(frame)
|
||||||
@@ -179,6 +180,23 @@ class GmiiSource:
|
|||||||
while not self.idle():
|
while not self.idle():
|
||||||
await RisingEdge(self.clock)
|
await RisingEdge(self.clock)
|
||||||
|
|
||||||
|
def _handle_reset(self, state):
|
||||||
|
if state:
|
||||||
|
self.log.info("Reset asserted")
|
||||||
|
if self._run_cr is not None:
|
||||||
|
self._run_cr.kill()
|
||||||
|
self._run_cr = None
|
||||||
|
else:
|
||||||
|
self.log.info("Reset de-asserted")
|
||||||
|
if self._run_cr is None:
|
||||||
|
self._run_cr = cocotb.fork(self._run())
|
||||||
|
|
||||||
|
self.active = False
|
||||||
|
self.data <= 0
|
||||||
|
if self.er is not None:
|
||||||
|
self.er <= 0
|
||||||
|
self.dv <= 0
|
||||||
|
|
||||||
async def _run(self):
|
async def _run(self):
|
||||||
frame = None
|
frame = None
|
||||||
ifg_cnt = 0
|
ifg_cnt = 0
|
||||||
@@ -187,16 +205,6 @@ class GmiiSource:
|
|||||||
while True:
|
while True:
|
||||||
await RisingEdge(self.clock)
|
await RisingEdge(self.clock)
|
||||||
|
|
||||||
if self.reset is not None and self.reset.value:
|
|
||||||
frame = None
|
|
||||||
ifg_cnt = 0
|
|
||||||
self.active = False
|
|
||||||
self.data <= 0
|
|
||||||
if self.er is not None:
|
|
||||||
self.er <= 0
|
|
||||||
self.dv <= 0
|
|
||||||
continue
|
|
||||||
|
|
||||||
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:
|
||||||
# in IFG
|
# in IFG
|
||||||
@@ -243,7 +251,7 @@ class GmiiSource:
|
|||||||
self.active = False
|
self.active = False
|
||||||
|
|
||||||
|
|
||||||
class GmiiSink:
|
class GmiiSink(Reset):
|
||||||
|
|
||||||
def __init__(self, data, er, dv, clock, reset=None, enable=None, mii_select=None, *args, **kwargs):
|
def __init__(self, data, er, dv, clock, reset=None, enable=None, mii_select=None, *args, **kwargs):
|
||||||
self.log = logging.getLogger(f"cocotb.{data._path}")
|
self.log = logging.getLogger(f"cocotb.{data._path}")
|
||||||
@@ -274,15 +282,15 @@ class GmiiSink:
|
|||||||
self.width = 8
|
self.width = 8
|
||||||
self.byte_width = 1
|
self.byte_width = 1
|
||||||
|
|
||||||
self.reset = reset
|
|
||||||
|
|
||||||
assert len(self.data) == 8
|
assert len(self.data) == 8
|
||||||
if self.er is not None:
|
if self.er is not None:
|
||||||
assert len(self.er) == 1
|
assert len(self.er) == 1
|
||||||
if self.dv is not None:
|
if self.dv is not None:
|
||||||
assert len(self.dv) == 1
|
assert len(self.dv) == 1
|
||||||
|
|
||||||
cocotb.fork(self._run())
|
self._run_cr = None
|
||||||
|
|
||||||
|
self._init_reset(reset)
|
||||||
|
|
||||||
async def recv(self, compact=True):
|
async def recv(self, compact=True):
|
||||||
while self.empty():
|
while self.empty():
|
||||||
@@ -316,6 +324,19 @@ class GmiiSink:
|
|||||||
else:
|
else:
|
||||||
await self.sync.wait()
|
await self.sync.wait()
|
||||||
|
|
||||||
|
def _handle_reset(self, state):
|
||||||
|
if state:
|
||||||
|
self.log.info("Reset asserted")
|
||||||
|
if self._run_cr is not None:
|
||||||
|
self._run_cr.kill()
|
||||||
|
self._run_cr = None
|
||||||
|
else:
|
||||||
|
self.log.info("Reset de-asserted")
|
||||||
|
if self._run_cr is None:
|
||||||
|
self._run_cr = cocotb.fork(self._run())
|
||||||
|
|
||||||
|
self.active = False
|
||||||
|
|
||||||
async def _run(self):
|
async def _run(self):
|
||||||
frame = None
|
frame = None
|
||||||
self.active = False
|
self.active = False
|
||||||
@@ -323,11 +344,6 @@ class GmiiSink:
|
|||||||
while True:
|
while True:
|
||||||
await RisingEdge(self.clock)
|
await RisingEdge(self.clock)
|
||||||
|
|
||||||
if self.reset is not None and self.reset.value:
|
|
||||||
frame = None
|
|
||||||
self.active = False
|
|
||||||
continue
|
|
||||||
|
|
||||||
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
|
||||||
dv_val = self.dv.value.integer
|
dv_val = self.dv.value.integer
|
||||||
|
|||||||
@@ -32,9 +32,10 @@ from cocotb.utils import get_sim_time, get_sim_steps
|
|||||||
from .version import __version__
|
from .version import __version__
|
||||||
from .gmii import GmiiFrame
|
from .gmii import GmiiFrame
|
||||||
from .constants import EthPre
|
from .constants import EthPre
|
||||||
|
from .reset import Reset
|
||||||
|
|
||||||
|
|
||||||
class MiiSource:
|
class MiiSource(Reset):
|
||||||
|
|
||||||
def __init__(self, data, er, dv, clock, reset=None, enable=None, *args, **kwargs):
|
def __init__(self, data, er, dv, clock, reset=None, enable=None, *args, **kwargs):
|
||||||
self.log = logging.getLogger(f"cocotb.{data._path}")
|
self.log = logging.getLogger(f"cocotb.{data._path}")
|
||||||
@@ -63,8 +64,6 @@ class MiiSource:
|
|||||||
self.width = 4
|
self.width = 4
|
||||||
self.byte_width = 1
|
self.byte_width = 1
|
||||||
|
|
||||||
self.reset = reset
|
|
||||||
|
|
||||||
assert len(self.data) == 4
|
assert len(self.data) == 4
|
||||||
self.data.setimmediatevalue(0)
|
self.data.setimmediatevalue(0)
|
||||||
if self.er is not None:
|
if self.er is not None:
|
||||||
@@ -73,7 +72,9 @@ class MiiSource:
|
|||||||
assert len(self.dv) == 1
|
assert len(self.dv) == 1
|
||||||
self.dv.setimmediatevalue(0)
|
self.dv.setimmediatevalue(0)
|
||||||
|
|
||||||
cocotb.fork(self._run())
|
self._run_cr = None
|
||||||
|
|
||||||
|
self._init_reset(reset)
|
||||||
|
|
||||||
async def send(self, frame):
|
async def send(self, frame):
|
||||||
self.send_nowait(frame)
|
self.send_nowait(frame)
|
||||||
@@ -97,6 +98,23 @@ class MiiSource:
|
|||||||
while not self.idle():
|
while not self.idle():
|
||||||
await RisingEdge(self.clock)
|
await RisingEdge(self.clock)
|
||||||
|
|
||||||
|
def _handle_reset(self, state):
|
||||||
|
if state:
|
||||||
|
self.log.info("Reset asserted")
|
||||||
|
if self._run_cr is not None:
|
||||||
|
self._run_cr.kill()
|
||||||
|
self._run_cr = None
|
||||||
|
else:
|
||||||
|
self.log.info("Reset de-asserted")
|
||||||
|
if self._run_cr is None:
|
||||||
|
self._run_cr = cocotb.fork(self._run())
|
||||||
|
|
||||||
|
self.active = False
|
||||||
|
self.data <= 0
|
||||||
|
if self.er is not None:
|
||||||
|
self.er <= 0
|
||||||
|
self.dv <= 0
|
||||||
|
|
||||||
async def _run(self):
|
async def _run(self):
|
||||||
frame = None
|
frame = None
|
||||||
ifg_cnt = 0
|
ifg_cnt = 0
|
||||||
@@ -105,16 +123,6 @@ class MiiSource:
|
|||||||
while True:
|
while True:
|
||||||
await RisingEdge(self.clock)
|
await RisingEdge(self.clock)
|
||||||
|
|
||||||
if self.reset is not None and self.reset.value:
|
|
||||||
frame = None
|
|
||||||
ifg_cnt = 0
|
|
||||||
self.active = False
|
|
||||||
self.data <= 0
|
|
||||||
if self.er is not None:
|
|
||||||
self.er <= 0
|
|
||||||
self.dv <= 0
|
|
||||||
continue
|
|
||||||
|
|
||||||
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:
|
||||||
# in IFG
|
# in IFG
|
||||||
@@ -157,7 +165,7 @@ class MiiSource:
|
|||||||
self.active = False
|
self.active = False
|
||||||
|
|
||||||
|
|
||||||
class MiiSink:
|
class MiiSink(Reset):
|
||||||
|
|
||||||
def __init__(self, data, er, dv, clock, reset=None, enable=None, *args, **kwargs):
|
def __init__(self, data, er, dv, clock, reset=None, enable=None, *args, **kwargs):
|
||||||
self.log = logging.getLogger(f"cocotb.{data._path}")
|
self.log = logging.getLogger(f"cocotb.{data._path}")
|
||||||
@@ -185,15 +193,15 @@ class MiiSink:
|
|||||||
self.width = 4
|
self.width = 4
|
||||||
self.byte_width = 1
|
self.byte_width = 1
|
||||||
|
|
||||||
self.reset = reset
|
|
||||||
|
|
||||||
assert len(self.data) == 4
|
assert len(self.data) == 4
|
||||||
if self.er is not None:
|
if self.er is not None:
|
||||||
assert len(self.er) == 1
|
assert len(self.er) == 1
|
||||||
if self.dv is not None:
|
if self.dv is not None:
|
||||||
assert len(self.dv) == 1
|
assert len(self.dv) == 1
|
||||||
|
|
||||||
cocotb.fork(self._run())
|
self._run_cr = None
|
||||||
|
|
||||||
|
self._init_reset(reset)
|
||||||
|
|
||||||
async def recv(self, compact=True):
|
async def recv(self, compact=True):
|
||||||
while self.empty():
|
while self.empty():
|
||||||
@@ -227,6 +235,19 @@ class MiiSink:
|
|||||||
else:
|
else:
|
||||||
await self.sync.wait()
|
await self.sync.wait()
|
||||||
|
|
||||||
|
def _handle_reset(self, state):
|
||||||
|
if state:
|
||||||
|
self.log.info("Reset asserted")
|
||||||
|
if self._run_cr is not None:
|
||||||
|
self._run_cr.kill()
|
||||||
|
self._run_cr = None
|
||||||
|
else:
|
||||||
|
self.log.info("Reset de-asserted")
|
||||||
|
if self._run_cr is None:
|
||||||
|
self._run_cr = cocotb.fork(self._run())
|
||||||
|
|
||||||
|
self.active = False
|
||||||
|
|
||||||
async def _run(self):
|
async def _run(self):
|
||||||
frame = None
|
frame = None
|
||||||
self.active = False
|
self.active = False
|
||||||
@@ -234,11 +255,6 @@ class MiiSink:
|
|||||||
while True:
|
while True:
|
||||||
await RisingEdge(self.clock)
|
await RisingEdge(self.clock)
|
||||||
|
|
||||||
if self.reset is not None and self.reset.value:
|
|
||||||
frame = None
|
|
||||||
self.active = False
|
|
||||||
continue
|
|
||||||
|
|
||||||
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
|
||||||
dv_val = self.dv.value.integer
|
dv_val = self.dv.value.integer
|
||||||
|
|||||||
@@ -30,9 +30,10 @@ import cocotb
|
|||||||
from cocotb.triggers import RisingEdge
|
from cocotb.triggers import RisingEdge
|
||||||
|
|
||||||
from .version import __version__
|
from .version import __version__
|
||||||
|
from .reset import Reset
|
||||||
|
|
||||||
|
|
||||||
class PtpClock:
|
class PtpClock(Reset):
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@@ -87,7 +88,9 @@ class PtpClock:
|
|||||||
if self.pps is not None:
|
if self.pps is not None:
|
||||||
self.pps.setimmediatevalue(0)
|
self.pps.setimmediatevalue(0)
|
||||||
|
|
||||||
cocotb.fork(self._run())
|
self._run_cr = None
|
||||||
|
|
||||||
|
self._init_reset(reset)
|
||||||
|
|
||||||
def set_period(self, ns, fns):
|
def set_period(self, ns, fns):
|
||||||
self.period_ns = int(ns)
|
self.period_ns = int(ns)
|
||||||
@@ -176,27 +179,36 @@ class PtpClock:
|
|||||||
def get_ts_64_s(self):
|
def get_ts_64_s(self):
|
||||||
return self.get_ts_64()*1e-9
|
return self.get_ts_64()*1e-9
|
||||||
|
|
||||||
|
def _handle_reset(self, state):
|
||||||
|
if state:
|
||||||
|
self.log.info("Reset asserted")
|
||||||
|
if self._run_cr is not None:
|
||||||
|
self._run_cr.kill()
|
||||||
|
self._run_cr = None
|
||||||
|
else:
|
||||||
|
self.log.info("Reset de-asserted")
|
||||||
|
if self._run_cr is None:
|
||||||
|
self._run_cr = cocotb.fork(self._run())
|
||||||
|
|
||||||
|
self.ts_96_s = 0
|
||||||
|
self.ts_96_ns = 0
|
||||||
|
self.ts_96_fns = 0
|
||||||
|
self.ts_64_ns = 0
|
||||||
|
self.ts_64_fns = 0
|
||||||
|
self.drift_cnt = 0
|
||||||
|
if self.ts_96 is not None:
|
||||||
|
self.ts_96 <= 0
|
||||||
|
if self.ts_64 is not None:
|
||||||
|
self.ts_64 <= 0
|
||||||
|
if self.ts_step is not None:
|
||||||
|
self.ts_step <= 0
|
||||||
|
if self.pps is not None:
|
||||||
|
self.pps <= 0
|
||||||
|
|
||||||
async def _run(self):
|
async def _run(self):
|
||||||
while True:
|
while True:
|
||||||
await RisingEdge(self.clock)
|
await RisingEdge(self.clock)
|
||||||
|
|
||||||
if self.reset is not None and self.reset.value:
|
|
||||||
self.ts_96_s = 0
|
|
||||||
self.ts_96_ns = 0
|
|
||||||
self.ts_96_fns = 0
|
|
||||||
self.ts_64_ns = 0
|
|
||||||
self.ts_64_fns = 0
|
|
||||||
self.drift_cnt = 0
|
|
||||||
if self.ts_96 is not None:
|
|
||||||
self.ts_96 <= 0
|
|
||||||
if self.ts_64 is not None:
|
|
||||||
self.ts_64 <= 0
|
|
||||||
if self.ts_step is not None:
|
|
||||||
self.ts_step <= 0
|
|
||||||
if self.pps is not None:
|
|
||||||
self.pps <= 0
|
|
||||||
continue
|
|
||||||
|
|
||||||
if self.ts_step is not None:
|
if self.ts_step is not None:
|
||||||
self.ts_step <= self.ts_updated
|
self.ts_step <= self.ts_updated
|
||||||
self.ts_updated = False
|
self.ts_updated = False
|
||||||
|
|||||||
66
cocotbext/eth/reset.py
Normal file
66
cocotbext/eth/reset.py
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
"""
|
||||||
|
|
||||||
|
Copyright (c) 2020 Alex Forencich
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
import cocotb
|
||||||
|
from cocotb.triggers import RisingEdge, FallingEdge
|
||||||
|
|
||||||
|
|
||||||
|
class Reset:
|
||||||
|
def _init_reset(self, reset_signal=None, active_high=True):
|
||||||
|
self._local_reset = False
|
||||||
|
self._ext_reset = False
|
||||||
|
self._reset_state = True
|
||||||
|
|
||||||
|
if reset_signal is not None:
|
||||||
|
cocotb.fork(self._run_reset(reset_signal, active_high))
|
||||||
|
|
||||||
|
self._update_reset()
|
||||||
|
|
||||||
|
def assert_reset(self, val=None):
|
||||||
|
if val is None:
|
||||||
|
self.assert_reset(True)
|
||||||
|
self.assert_reset(False)
|
||||||
|
else:
|
||||||
|
self._local_reset = val
|
||||||
|
self._update_reset()
|
||||||
|
|
||||||
|
def _update_reset(self):
|
||||||
|
new_state = self._local_reset or self._ext_reset
|
||||||
|
if self._reset_state != new_state:
|
||||||
|
self._reset_state = new_state
|
||||||
|
self._handle_reset(new_state)
|
||||||
|
|
||||||
|
def _handle_reset(self, state):
|
||||||
|
pass
|
||||||
|
|
||||||
|
async def _run_reset(self, reset_signal, active_high):
|
||||||
|
while True:
|
||||||
|
if bool(reset_signal.value):
|
||||||
|
await FallingEdge(reset_signal)
|
||||||
|
self._ext_reset = not active_high
|
||||||
|
self._update_reset()
|
||||||
|
else:
|
||||||
|
await RisingEdge(reset_signal)
|
||||||
|
self._ext_reset = active_high
|
||||||
|
self._update_reset()
|
||||||
@@ -32,9 +32,10 @@ from cocotb.utils import get_sim_time, get_sim_steps
|
|||||||
from .version import __version__
|
from .version import __version__
|
||||||
from .gmii import GmiiFrame
|
from .gmii import GmiiFrame
|
||||||
from .constants import EthPre
|
from .constants import EthPre
|
||||||
|
from .reset import Reset
|
||||||
|
|
||||||
|
|
||||||
class RgmiiSource:
|
class RgmiiSource(Reset):
|
||||||
|
|
||||||
def __init__(self, data, ctrl, clock, reset=None, enable=None, mii_select=None, *args, **kwargs):
|
def __init__(self, data, ctrl, clock, reset=None, enable=None, mii_select=None, *args, **kwargs):
|
||||||
self.log = logging.getLogger(f"cocotb.{data._path}")
|
self.log = logging.getLogger(f"cocotb.{data._path}")
|
||||||
@@ -64,14 +65,14 @@ class RgmiiSource:
|
|||||||
self.width = 8
|
self.width = 8
|
||||||
self.byte_width = 1
|
self.byte_width = 1
|
||||||
|
|
||||||
self.reset = reset
|
|
||||||
|
|
||||||
assert len(self.data) == 4
|
assert len(self.data) == 4
|
||||||
self.data.setimmediatevalue(0)
|
self.data.setimmediatevalue(0)
|
||||||
assert len(self.ctrl) == 1
|
assert len(self.ctrl) == 1
|
||||||
self.ctrl.setimmediatevalue(0)
|
self.ctrl.setimmediatevalue(0)
|
||||||
|
|
||||||
cocotb.fork(self._run())
|
self._run_cr = None
|
||||||
|
|
||||||
|
self._init_reset(reset)
|
||||||
|
|
||||||
async def send(self, frame):
|
async def send(self, frame):
|
||||||
self.send_nowait(frame)
|
self.send_nowait(frame)
|
||||||
@@ -95,6 +96,21 @@ class RgmiiSource:
|
|||||||
while not self.idle():
|
while not self.idle():
|
||||||
await RisingEdge(self.clock)
|
await RisingEdge(self.clock)
|
||||||
|
|
||||||
|
def _handle_reset(self, state):
|
||||||
|
if state:
|
||||||
|
self.log.info("Reset asserted")
|
||||||
|
if self._run_cr is not None:
|
||||||
|
self._run_cr.kill()
|
||||||
|
self._run_cr = None
|
||||||
|
else:
|
||||||
|
self.log.info("Reset de-asserted")
|
||||||
|
if self._run_cr is None:
|
||||||
|
self._run_cr = cocotb.fork(self._run())
|
||||||
|
|
||||||
|
self.active = False
|
||||||
|
self.data <= 0
|
||||||
|
self.ctrl <= 0
|
||||||
|
|
||||||
async def _run(self):
|
async def _run(self):
|
||||||
frame = None
|
frame = None
|
||||||
ifg_cnt = 0
|
ifg_cnt = 0
|
||||||
@@ -106,14 +122,6 @@ class RgmiiSource:
|
|||||||
while True:
|
while True:
|
||||||
await RisingEdge(self.clock)
|
await RisingEdge(self.clock)
|
||||||
|
|
||||||
if self.reset is not None and self.reset.value:
|
|
||||||
frame = None
|
|
||||||
ifg_cnt = 0
|
|
||||||
self.active = False
|
|
||||||
self.data <= 0
|
|
||||||
self.ctrl <= 0
|
|
||||||
continue
|
|
||||||
|
|
||||||
if not self.mii_mode:
|
if not self.mii_mode:
|
||||||
# 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 <= d >> 4
|
||||||
@@ -169,7 +177,7 @@ class RgmiiSource:
|
|||||||
self.ctrl <= en
|
self.ctrl <= en
|
||||||
|
|
||||||
|
|
||||||
class RgmiiSink:
|
class RgmiiSink(Reset):
|
||||||
|
|
||||||
def __init__(self, data, ctrl, clock, reset=None, enable=None, mii_select=None, *args, **kwargs):
|
def __init__(self, data, ctrl, clock, reset=None, enable=None, mii_select=None, *args, **kwargs):
|
||||||
self.log = logging.getLogger(f"cocotb.{data._path}")
|
self.log = logging.getLogger(f"cocotb.{data._path}")
|
||||||
@@ -199,12 +207,12 @@ class RgmiiSink:
|
|||||||
self.width = 8
|
self.width = 8
|
||||||
self.byte_width = 1
|
self.byte_width = 1
|
||||||
|
|
||||||
self.reset = reset
|
|
||||||
|
|
||||||
assert len(self.data) == 4
|
assert len(self.data) == 4
|
||||||
assert len(self.ctrl) == 1
|
assert len(self.ctrl) == 1
|
||||||
|
|
||||||
cocotb.fork(self._run())
|
self._run_cr = None
|
||||||
|
|
||||||
|
self._init_reset(reset)
|
||||||
|
|
||||||
async def recv(self, compact=True):
|
async def recv(self, compact=True):
|
||||||
while self.empty():
|
while self.empty():
|
||||||
@@ -238,6 +246,19 @@ class RgmiiSink:
|
|||||||
else:
|
else:
|
||||||
await self.sync.wait()
|
await self.sync.wait()
|
||||||
|
|
||||||
|
def _handle_reset(self, state):
|
||||||
|
if state:
|
||||||
|
self.log.info("Reset asserted")
|
||||||
|
if self._run_cr is not None:
|
||||||
|
self._run_cr.kill()
|
||||||
|
self._run_cr = None
|
||||||
|
else:
|
||||||
|
self.log.info("Reset de-asserted")
|
||||||
|
if self._run_cr is None:
|
||||||
|
self._run_cr = cocotb.fork(self._run())
|
||||||
|
|
||||||
|
self.active = False
|
||||||
|
|
||||||
async def _run(self):
|
async def _run(self):
|
||||||
frame = None
|
frame = None
|
||||||
self.active = False
|
self.active = False
|
||||||
@@ -254,11 +275,6 @@ class RgmiiSink:
|
|||||||
|
|
||||||
await FallingEdge(self.clock)
|
await FallingEdge(self.clock)
|
||||||
|
|
||||||
if self.reset is not None and self.reset.value:
|
|
||||||
frame = None
|
|
||||||
self.active = False
|
|
||||||
continue
|
|
||||||
|
|
||||||
# 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
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ from cocotb.utils import get_sim_time
|
|||||||
|
|
||||||
from .version import __version__
|
from .version import __version__
|
||||||
from .constants import EthPre, ETH_PREAMBLE, XgmiiCtrl
|
from .constants import EthPre, ETH_PREAMBLE, XgmiiCtrl
|
||||||
|
from .reset import Reset
|
||||||
|
|
||||||
|
|
||||||
class XgmiiFrame:
|
class XgmiiFrame:
|
||||||
@@ -117,7 +118,7 @@ class XgmiiFrame:
|
|||||||
return bytes(self.data)
|
return bytes(self.data)
|
||||||
|
|
||||||
|
|
||||||
class XgmiiSource:
|
class XgmiiSource(Reset):
|
||||||
|
|
||||||
def __init__(self, data, ctrl, clock, reset=None, enable=None, *args, **kwargs):
|
def __init__(self, data, ctrl, clock, reset=None, enable=None, *args, **kwargs):
|
||||||
self.log = logging.getLogger(f"cocotb.{data._path}")
|
self.log = logging.getLogger(f"cocotb.{data._path}")
|
||||||
@@ -147,8 +148,6 @@ class XgmiiSource:
|
|||||||
self.width = len(self.data)
|
self.width = len(self.data)
|
||||||
self.byte_width = len(self.ctrl)
|
self.byte_width = len(self.ctrl)
|
||||||
|
|
||||||
self.reset = reset
|
|
||||||
|
|
||||||
assert self.width == self.byte_width * 8
|
assert self.width == self.byte_width * 8
|
||||||
|
|
||||||
self.idle_d = 0
|
self.idle_d = 0
|
||||||
@@ -161,7 +160,9 @@ class XgmiiSource:
|
|||||||
self.data.setimmediatevalue(0)
|
self.data.setimmediatevalue(0)
|
||||||
self.ctrl.setimmediatevalue(0)
|
self.ctrl.setimmediatevalue(0)
|
||||||
|
|
||||||
cocotb.fork(self._run())
|
self._run_cr = None
|
||||||
|
|
||||||
|
self._init_reset(reset)
|
||||||
|
|
||||||
async def send(self, frame):
|
async def send(self, frame):
|
||||||
self.send_nowait(frame)
|
self.send_nowait(frame)
|
||||||
@@ -185,6 +186,21 @@ class XgmiiSource:
|
|||||||
while not self.idle():
|
while not self.idle():
|
||||||
await RisingEdge(self.clock)
|
await RisingEdge(self.clock)
|
||||||
|
|
||||||
|
def _handle_reset(self, state):
|
||||||
|
if state:
|
||||||
|
self.log.info("Reset asserted")
|
||||||
|
if self._run_cr is not None:
|
||||||
|
self._run_cr.kill()
|
||||||
|
self._run_cr = None
|
||||||
|
else:
|
||||||
|
self.log.info("Reset de-asserted")
|
||||||
|
if self._run_cr is None:
|
||||||
|
self._run_cr = cocotb.fork(self._run())
|
||||||
|
|
||||||
|
self.active = False
|
||||||
|
self.data <= 0
|
||||||
|
self.ctrl <= 0
|
||||||
|
|
||||||
async def _run(self):
|
async def _run(self):
|
||||||
frame = None
|
frame = None
|
||||||
ifg_cnt = 0
|
ifg_cnt = 0
|
||||||
@@ -194,15 +210,6 @@ class XgmiiSource:
|
|||||||
while True:
|
while True:
|
||||||
await RisingEdge(self.clock)
|
await RisingEdge(self.clock)
|
||||||
|
|
||||||
if self.reset is not None and self.reset.value:
|
|
||||||
frame = None
|
|
||||||
ifg_cnt = 0
|
|
||||||
deficit_idle_cnt = 0
|
|
||||||
self.active = False
|
|
||||||
self.data <= 0
|
|
||||||
self.ctrl <= 0
|
|
||||||
continue
|
|
||||||
|
|
||||||
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_width-1 or (not self.enable_dic and ifg_cnt > 4):
|
if ifg_cnt + deficit_idle_cnt > self.byte_width-1 or (not self.enable_dic and ifg_cnt > 4):
|
||||||
# in IFG
|
# in IFG
|
||||||
@@ -272,7 +279,7 @@ class XgmiiSource:
|
|||||||
self.active = False
|
self.active = False
|
||||||
|
|
||||||
|
|
||||||
class XgmiiSink:
|
class XgmiiSink(Reset):
|
||||||
|
|
||||||
def __init__(self, data, ctrl, clock, reset=None, enable=None, *args, **kwargs):
|
def __init__(self, data, ctrl, clock, reset=None, enable=None, *args, **kwargs):
|
||||||
self.log = logging.getLogger(f"cocotb.{data._path}")
|
self.log = logging.getLogger(f"cocotb.{data._path}")
|
||||||
@@ -299,11 +306,11 @@ class XgmiiSink:
|
|||||||
self.width = len(self.data)
|
self.width = len(self.data)
|
||||||
self.byte_width = len(self.ctrl)
|
self.byte_width = len(self.ctrl)
|
||||||
|
|
||||||
self.reset = reset
|
|
||||||
|
|
||||||
assert self.width == self.byte_width * 8
|
assert self.width == self.byte_width * 8
|
||||||
|
|
||||||
cocotb.fork(self._run())
|
self._run_cr = None
|
||||||
|
|
||||||
|
self._init_reset(reset)
|
||||||
|
|
||||||
async def recv(self, compact=True):
|
async def recv(self, compact=True):
|
||||||
while self.empty():
|
while self.empty():
|
||||||
@@ -337,6 +344,19 @@ class XgmiiSink:
|
|||||||
else:
|
else:
|
||||||
await self.sync.wait()
|
await self.sync.wait()
|
||||||
|
|
||||||
|
def _handle_reset(self, state):
|
||||||
|
if state:
|
||||||
|
self.log.info("Reset asserted")
|
||||||
|
if self._run_cr is not None:
|
||||||
|
self._run_cr.kill()
|
||||||
|
self._run_cr = None
|
||||||
|
else:
|
||||||
|
self.log.info("Reset de-asserted")
|
||||||
|
if self._run_cr is None:
|
||||||
|
self._run_cr = cocotb.fork(self._run())
|
||||||
|
|
||||||
|
self.active = False
|
||||||
|
|
||||||
async def _run(self):
|
async def _run(self):
|
||||||
frame = None
|
frame = None
|
||||||
self.active = False
|
self.active = False
|
||||||
@@ -344,11 +364,6 @@ class XgmiiSink:
|
|||||||
while True:
|
while True:
|
||||||
await RisingEdge(self.clock)
|
await RisingEdge(self.clock)
|
||||||
|
|
||||||
if self.reset is not None and self.reset.value:
|
|
||||||
frame = None
|
|
||||||
self.active = False
|
|
||||||
continue
|
|
||||||
|
|
||||||
if self.enable is None or self.enable.value:
|
if self.enable is None or self.enable.value:
|
||||||
for offset in range(self.byte_width):
|
for offset in range(self.byte_width):
|
||||||
d_val = (self.data.value.integer >> (offset*8)) & 0xff
|
d_val = (self.data.value.integer >> (offset*8)) & 0xff
|
||||||
|
|||||||
@@ -116,7 +116,6 @@ async def run_load_timestamps(dut):
|
|||||||
tb.ptp_clock.set_ts_96(12345678)
|
tb.ptp_clock.set_ts_96(12345678)
|
||||||
tb.ptp_clock.set_ts_64(12345678)
|
tb.ptp_clock.set_ts_64(12345678)
|
||||||
|
|
||||||
await RisingEdge(dut.clk)
|
|
||||||
await RisingEdge(dut.clk)
|
await RisingEdge(dut.clk)
|
||||||
|
|
||||||
assert dut.ts_96.value.integer == 12345678+((tb.ptp_clock.period_ns << 16) + tb.ptp_clock.period_fns)
|
assert dut.ts_96.value.integer == 12345678+((tb.ptp_clock.period_ns << 16) + tb.ptp_clock.period_fns)
|
||||||
|
|||||||
Reference in New Issue
Block a user