Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ee51890f5 | ||
|
|
fbdf4149b3 | ||
|
|
03156ff759 | ||
|
|
8956de42b5 |
15
README.md
15
README.md
@@ -467,6 +467,7 @@ To use these modules, import the one you need and connect it to the DUT:
|
||||
tx_bus=AxiStreamBus.from_prefix(dut, "tx_axis"),
|
||||
tx_ptp_time=dut.tx_ptp_time,
|
||||
tx_ptp_ts=dut.tx_ptp_ts,
|
||||
tx_ptp_ts_tag=dut.tx_ptp_ts_tag,
|
||||
tx_ptp_ts_valid=dut.tx_ptp_ts_valid,
|
||||
rx_clk=dut.rx_clk,
|
||||
rx_rst=dut.rx_rst,
|
||||
@@ -492,6 +493,8 @@ To receive data, call `recv()` or `recv_nowait()`. Optionally call `wait()` to
|
||||
|
||||
data = await mac.tx.recv()
|
||||
|
||||
PTP timestamping requires free-running PTP clocks driving the PTP time inputs, synchronous with the corresponding MAC clocks. The values of these fields are then captured when the frame SFD is transferred and returned either on tuser (for received frames) or on a separate streaming interface (for transmitted frames). Additionally, on the transmit path, a tag value from tuser is returned along with the timestamp.
|
||||
|
||||
#### Signals
|
||||
|
||||
* `tdata`: payload data, must be a multiple of 8 bits
|
||||
@@ -499,9 +502,10 @@ To receive data, call `recv()` or `recv_nowait()`. Optionally call `wait()` to
|
||||
* `tready`: indicates sink is ready for data (tx only)
|
||||
* `tlast`: marks the last cycle of a frame
|
||||
* `tkeep`: qualifies data byte, data bus width must be evenly divisible by `tkeep` signal width
|
||||
* `tuser`: user data, carries frame error mark and captured receive PTP timestamp
|
||||
* `ptp_time`: PTP time input from PHC, captured into `ptp_timestamp` field coincident with transfer of frame SFD and output on `ptp_ts`
|
||||
* `tuser`: user data, carries frame error mark and captured receive PTP timestamp (RX) or PTP timestamp tag (TX)
|
||||
* `ptp_time`: PTP time input from PHC, captured into `ptp_timestamp` field coincident with transfer of frame SFD and output on `ptp_ts` (TX) or `tuser` (RX)
|
||||
* `ptp_ts`: captured transmit PTP timestamp
|
||||
* `ptp_ts_tag`: captured transmit PTP timestamp tag
|
||||
* `ptp_ts_valid`: qualifies captured transmit PTP timestamp
|
||||
|
||||
#### Constructor parameters (`EthMacRx` and `EthMacTx`):
|
||||
@@ -510,7 +514,8 @@ To receive data, call `recv()` or `recv_nowait()`. Optionally call `wait()` to
|
||||
* _clock_: clock signal
|
||||
* _reset_: reset signal (optional)
|
||||
* _ptp_time_: PTP time input from PHC (optional)
|
||||
* _ptp_ts_: PTP timestamp output (optional) (tx)
|
||||
* _ptp_ts_: PTP timestamp (optional) (tx)
|
||||
* _ptp_ts_tag_: PTP timestamp tag (optional) (tx)
|
||||
* _ptp_ts_valid_: PTP timestamp valid (optional) (tx)
|
||||
* _reset_active_level_: reset active level (optional, default `True`)
|
||||
* _ifg_: IFG size in byte times (optional, default `12`)
|
||||
@@ -522,7 +527,8 @@ To receive data, call `recv()` or `recv_nowait()`. Optionally call `wait()` to
|
||||
* _tx_clk_: transmit clock
|
||||
* _tx_rst_: transmit reset (optional)
|
||||
* _tx_ptp_time_: transmit PTP time input from PHC (optional)
|
||||
* _tx_ptp_ts_: transmit PTP timestamp output (optional)
|
||||
* _tx_ptp_ts_: transmit PTP timestamp (optional)
|
||||
* _tx_ptp_ts_tag_: transmit PTP timestamp tag (optional)
|
||||
* _tx_ptp_ts_valid_: transmit PTP timestamp valid (optional)
|
||||
* _rx_bus_: `AxiStreamBus` object containing receive AXI stream interface signals
|
||||
* _rx_clk_: receive clock
|
||||
@@ -565,6 +571,7 @@ Attributes:
|
||||
* `sim_time_start`: simulation time of first transfer cycle of frame.
|
||||
* `sim_time_sfd`: simulation time at which the SFD was transferred.
|
||||
* `sim_time_end`: simulation time of last transfer cycle of frame.
|
||||
* `ptp_tag`: PTP timestamp tag for transmitted frames.
|
||||
* `ptp_timestamp`: captured value of `ptp_time` at frame SFD
|
||||
* `tx_complete`: event or callable triggered when frame is transmitted.
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ class EthMacFrame:
|
||||
self.sim_time_sfd = None
|
||||
self.sim_time_end = None
|
||||
self.ptp_timestamp = None
|
||||
self.ptp_tag = None
|
||||
self.tx_complete = None
|
||||
|
||||
if type(data) is EthMacFrame:
|
||||
@@ -57,6 +58,7 @@ class EthMacFrame:
|
||||
self.sim_time_sfd = data.sim_time_sfd
|
||||
self.sim_time_end = data.sim_time_end
|
||||
self.ptp_timestamp = data.ptp_timestamp
|
||||
self.ptp_tag = data.ptp_tag
|
||||
self.tx_complete = data.tx_complete
|
||||
else:
|
||||
self.data = bytearray(data)
|
||||
@@ -104,7 +106,8 @@ class EthMacFrame:
|
||||
f"sim_time_start={self.sim_time_start!r}, "
|
||||
f"sim_time_sfd={self.sim_time_sfd!r}, "
|
||||
f"sim_time_end={self.sim_time_end!r}, "
|
||||
f"ptp_timestamp={self.ptp_timestamp!r})"
|
||||
f"ptp_timestamp={self.ptp_timestamp!r}, "
|
||||
f"ptp_tag={self.ptp_tag!r})"
|
||||
)
|
||||
|
||||
def __len__(self):
|
||||
@@ -118,7 +121,7 @@ class EthMacFrame:
|
||||
|
||||
|
||||
class EthMacTx(Reset):
|
||||
def __init__(self, bus, clock, reset=None, ptp_time=None, ptp_ts=None, ptp_ts_valid=None,
|
||||
def __init__(self, bus, clock, reset=None, ptp_time=None, ptp_ts=None, ptp_ts_tag=None, ptp_ts_valid=None,
|
||||
reset_active_level=True, ifg=12, speed=1000e6, *args, **kwargs):
|
||||
|
||||
self.bus = bus
|
||||
@@ -126,6 +129,7 @@ class EthMacTx(Reset):
|
||||
self.reset = reset
|
||||
self.ptp_time = ptp_time
|
||||
self.ptp_ts = ptp_ts
|
||||
self.ptp_ts_tag = ptp_ts_tag
|
||||
self.ptp_ts_valid = ptp_ts_valid
|
||||
self.ifg = ifg
|
||||
self.speed = speed
|
||||
@@ -189,6 +193,8 @@ class EthMacTx(Reset):
|
||||
|
||||
if self.ptp_ts:
|
||||
self.ptp_ts.setimmediatevalue(0)
|
||||
if self.ptp_ts_tag:
|
||||
self.ptp_ts_tag.setimmediatevalue(0)
|
||||
if self.ptp_ts_valid:
|
||||
self.ptp_ts_valid.setimmediatevalue(0)
|
||||
|
||||
@@ -278,7 +284,8 @@ class EthMacTx(Reset):
|
||||
|
||||
if self.ptp_time:
|
||||
frame.ptp_timestamp = self.ptp_time.value.integer
|
||||
self.ts_queue.put_nowait(frame.ptp_timestamp)
|
||||
frame.ptp_tag = cycle.tuser.integer >> 1
|
||||
self.ts_queue.put_nowait((frame.ptp_timestamp, frame.ptp_tag))
|
||||
|
||||
# process frame data
|
||||
while True:
|
||||
@@ -320,8 +327,10 @@ class EthMacTx(Reset):
|
||||
self.ptp_ts_valid <= 0
|
||||
|
||||
if not self.ts_queue.empty():
|
||||
ts = self.ts_queue.get_nowait()
|
||||
ts, tag = self.ts_queue.get_nowait()
|
||||
self.ptp_ts <= ts
|
||||
if self.ptp_ts_tag is not None:
|
||||
self.ptp_ts_tag <= tag
|
||||
self.ptp_ts_valid <= 1
|
||||
|
||||
|
||||
@@ -532,13 +541,13 @@ class EthMacRx(Reset):
|
||||
|
||||
|
||||
class EthMac:
|
||||
def __init__(self, tx_bus=None, tx_clk=None, tx_rst=None, tx_ptp_time=None, tx_ptp_ts=None, tx_ptp_ts_valid=None,
|
||||
rx_bus=None, rx_clk=None, rx_rst=None, rx_ptp_time=None,
|
||||
def __init__(self, tx_bus=None, tx_clk=None, tx_rst=None, tx_ptp_time=None, tx_ptp_ts=None, tx_ptp_ts_tag=None,
|
||||
tx_ptp_ts_valid=None, rx_bus=None, rx_clk=None, rx_rst=None, rx_ptp_time=None,
|
||||
reset_active_level=True, ifg=12, speed=1000e6, *args, **kwargs):
|
||||
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self.tx = EthMacTx(tx_bus, tx_clk, tx_rst, tx_ptp_time, tx_ptp_ts, tx_ptp_ts_valid,
|
||||
self.tx = EthMacTx(tx_bus, tx_clk, tx_rst, tx_ptp_time, tx_ptp_ts, tx_ptp_ts_tag, tx_ptp_ts_valid,
|
||||
reset_active_level=reset_active_level, ifg=ifg, speed=speed)
|
||||
self.rx = EthMacRx(rx_bus, rx_clk, rx_rst, rx_ptp_time,
|
||||
reset_active_level=reset_active_level, ifg=ifg, speed=speed)
|
||||
|
||||
@@ -1 +1 @@
|
||||
__version__ = "0.1.14"
|
||||
__version__ = "0.1.16"
|
||||
|
||||
@@ -54,6 +54,7 @@ class TB:
|
||||
tx_bus=AxiStreamBus.from_prefix(dut, "tx_axis"),
|
||||
tx_ptp_time=dut.tx_ptp_time,
|
||||
tx_ptp_ts=dut.tx_ptp_ts,
|
||||
tx_ptp_ts_tag=dut.tx_ptp_ts_tag,
|
||||
tx_ptp_ts_valid=dut.tx_ptp_ts_valid,
|
||||
rx_clk=dut.rx_clk,
|
||||
rx_rst=dut.rx_rst,
|
||||
|
||||
@@ -36,11 +36,12 @@ module test_eth_mac
|
||||
inout wire [63:0] tx_axis_tdata,
|
||||
inout wire [7:0] tx_axis_tkeep,
|
||||
inout wire tx_axis_tlast,
|
||||
inout wire tx_axis_tuser,
|
||||
inout wire [16:0] tx_axis_tuser,
|
||||
inout wire tx_axis_tvalid,
|
||||
inout wire tx_axis_tready,
|
||||
inout wire [95:0] tx_ptp_time,
|
||||
inout wire [95:0] tx_ptp_ts,
|
||||
inout wire [15:0] tx_ptp_ts_tag,
|
||||
inout wire tx_ptp_ts_valid,
|
||||
|
||||
inout wire rx_clk,
|
||||
|
||||
Reference in New Issue
Block a user