align master/slave pair
This commit is contained in:
parent
7f23de0ce8
commit
e2a8433f83
@ -24,7 +24,9 @@ class SingleSerDesLoopBack(Module):
|
|||||||
|
|
||||||
self.submodules.tx = SingleLineTX()
|
self.submodules.tx = SingleLineTX()
|
||||||
self.submodules.rx = SingleLineRX()
|
self.submodules.rx = SingleLineRX()
|
||||||
self.submodules.phase_reader = PhaseReader()
|
self.submodules.bitslip_reader = BitSlipReader()
|
||||||
|
self.submodules.slave_aligner = SlaveAligner()
|
||||||
|
self.submodules.post_align_reader = BitSlipReader()
|
||||||
# self.submodules.delay_optimizer = DelayOptimizer()
|
# self.submodules.delay_optimizer = DelayOptimizer()
|
||||||
|
|
||||||
# The actual channel
|
# The actual channel
|
||||||
@ -51,17 +53,21 @@ class SingleSerDesLoopBack(Module):
|
|||||||
# Route deserializer to phase_reader & the delay tap optimizer
|
# Route deserializer to phase_reader & the delay tap optimizer
|
||||||
self.comb += [
|
self.comb += [
|
||||||
# Start the reader initially
|
# Start the reader initially
|
||||||
self.phase_reader.start.eq(1),
|
self.bitslip_reader.start.eq(1),
|
||||||
# Delay tap optimizer will start after the reader is done
|
# Delay tap optimizer will start after the reader is done
|
||||||
# self.delay_optimizer.start.eq(0),
|
# self.delay_optimizer.start.eq(0),
|
||||||
|
self.slave_aligner.start.eq(0),
|
||||||
|
self.post_align_reader.start.eq(0),
|
||||||
|
|
||||||
# RXDATA for both reader and optimzer
|
# RXDATA for both reader and optimzer
|
||||||
self.phase_reader.loopback_rxdata.eq(self.rx.rxdata),
|
self.bitslip_reader.loopback_rxdata.eq(self.rx.rxdata),
|
||||||
# TODO: Reconnet
|
# TODO: Reconnet
|
||||||
# self.delay_optimizer.loopback_rxdata.eq(self.rx.rxdata),
|
# self.delay_optimizer.loopback_rxdata.eq(self.rx.rxdata),
|
||||||
|
self.slave_aligner.loopback_rxdata.eq(self.rx.rxdata),
|
||||||
|
self.post_align_reader.loopback_rxdata.eq(self.rx.rxdata),
|
||||||
|
|
||||||
# Delay tap value
|
# Delay tap value
|
||||||
self.phase_reader.delay_tap.eq(self.rx.cnt_out),
|
# self.phase_reader.delay_tap.eq(self.rx.cnt_out),
|
||||||
# TODO: Reconnet
|
# TODO: Reconnet
|
||||||
# self.delay_optimizer.delay_tap.eq(self.rx.cnt_out),
|
# self.delay_optimizer.delay_tap.eq(self.rx.cnt_out),
|
||||||
|
|
||||||
@ -73,54 +79,104 @@ class SingleSerDesLoopBack(Module):
|
|||||||
# ).Else(
|
# ).Else(
|
||||||
# self.rx.ce.eq(self.phase_reader.inc_en),
|
# self.rx.ce.eq(self.phase_reader.inc_en),
|
||||||
# )
|
# )
|
||||||
self.rx.ce.eq(self.phase_reader.inc_en),
|
# self.rx.ce.eq(self.phase_reader.inc_en),
|
||||||
|
self.rx.master_bitslip.eq(
|
||||||
|
self.bitslip_reader.bitslip |
|
||||||
|
self.slave_aligner.master_bitslip |
|
||||||
|
self.post_align_reader.bitslip
|
||||||
|
),
|
||||||
|
self.rx.slave_bitslip.eq(
|
||||||
|
self.bitslip_reader.bitslip |
|
||||||
|
self.slave_aligner.slave_bitslip |
|
||||||
|
self.post_align_reader.bitslip
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
# Show measured result on UART
|
# Show measured result on UART
|
||||||
delay_tap = Signal(6)
|
delay_tap = Signal(6)
|
||||||
|
bitslip_count = Signal(3)
|
||||||
|
post_align_bitslip_count = Signal(3)
|
||||||
|
|
||||||
fsm = FSM(reset_state="WAIT_DONE")
|
fsm = FSM(reset_state="WAIT_DONE")
|
||||||
self.submodules += fsm
|
self.submodules += fsm
|
||||||
|
|
||||||
fsm.act("WAIT_DONE",
|
fsm.act("WAIT_DONE",
|
||||||
If(self.phase_reader.done,
|
If(self.bitslip_reader.done,
|
||||||
NextState("WRITE_UPPER"),
|
NextState("WRITE_UPPER"),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
fsm.act("WRITE_UPPER",
|
fsm.act("WRITE_UPPER",
|
||||||
# Exist state if all results are sent
|
# Exist state if all results are sent
|
||||||
If(delay_tap == 32,
|
If(bitslip_count == 5,
|
||||||
NextState("TERMINATE"),
|
NextState("FIND_OPT_DELAY"),
|
||||||
).Elif(self.tx_fifo.writable,
|
).Elif(self.tx_fifo.writable,
|
||||||
self.tx_fifo.we.eq(1),
|
self.tx_fifo.we.eq(1),
|
||||||
self.tx_fifo.din.eq(self.phase_reader.data_result[delay_tap][8:]),
|
self.tx_fifo.din.eq(self.bitslip_reader.data_result[bitslip_count][8:]),
|
||||||
NextState("WRITE_LOWER"),
|
NextState("WRITE_LOWER"),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
fsm.act("WRITE_LOWER",
|
fsm.act("WRITE_LOWER",
|
||||||
self.tx_fifo.we.eq(1),
|
self.tx_fifo.we.eq(1),
|
||||||
self.tx_fifo.din.eq(self.phase_reader.data_result[delay_tap][:8]),
|
self.tx_fifo.din.eq(self.bitslip_reader.data_result[bitslip_count][:8]),
|
||||||
NextValue(delay_tap, delay_tap + 1),
|
NextValue(bitslip_count, bitslip_count + 1),
|
||||||
NextState("WRITE_UPPER"),
|
NextState("WRITE_UPPER"),
|
||||||
)
|
)
|
||||||
|
|
||||||
# fsm.act("FIND_OPT_DELAY",
|
fsm.act("FIND_OPT_DELAY",
|
||||||
# self.delay_optimizer.start.eq(1),
|
self.slave_aligner.start.eq(1),
|
||||||
# self.rx.ce.eq(self.delay_optimizer.inc_en),
|
# self.rx.ce.eq(self.delay_optimizer.inc_en),
|
||||||
# If(self.delay_optimizer.done,
|
If(self.slave_aligner.done,
|
||||||
# NextState("WRITE_OPT"),
|
NextState("WRITE_DONE_UPPER"),
|
||||||
# ).Else(
|
).Else(
|
||||||
# NextState("FIND_OPT_DELAY")
|
NextState("FIND_OPT_DELAY")
|
||||||
# )
|
)
|
||||||
# )
|
)
|
||||||
|
|
||||||
# fsm.act("WRITE_OPT",
|
fsm.act("WRITE_DONE_UPPER",
|
||||||
# self.tx_fifo.we.eq(1),
|
self.post_align_reader.start.eq(1),
|
||||||
# self.tx_fifo.din.eq(self.delay_optimizer.opt_delay_tap),
|
If(self.tx_fifo.writable,
|
||||||
# NextState("TERMINATE")
|
self.tx_fifo.we.eq(1),
|
||||||
# )
|
self.tx_fifo.din.eq(0xFF),
|
||||||
|
NextState("WRITE_DONE_LOWER")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
fsm.act("WRITE_DONE_LOWER",
|
||||||
|
self.post_align_reader.start.eq(1),
|
||||||
|
If(self.tx_fifo.writable,
|
||||||
|
self.tx_fifo.we.eq(1),
|
||||||
|
self.tx_fifo.din.eq(0xFF),
|
||||||
|
NextState("REREAD_BITSLIP")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
fsm.act("REREAD_BITSLIP",
|
||||||
|
If(self.post_align_reader.done,
|
||||||
|
NextState("REWRITE_UPPER"),
|
||||||
|
).Else(
|
||||||
|
NextState("REREAD_BITSLIP"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
fsm.act("REWRITE_UPPER",
|
||||||
|
# Exist state if all results are sent
|
||||||
|
If(post_align_bitslip_count == 5,
|
||||||
|
NextState("TERMINATE"),
|
||||||
|
).Elif(self.tx_fifo.writable,
|
||||||
|
self.tx_fifo.we.eq(1),
|
||||||
|
self.tx_fifo.din.eq(self.post_align_reader.data_result[post_align_bitslip_count][8:]),
|
||||||
|
NextState("REWRITE_LOWER"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
fsm.act("REWRITE_LOWER",
|
||||||
|
self.tx_fifo.we.eq(1),
|
||||||
|
self.tx_fifo.din.eq(self.post_align_reader.data_result[post_align_bitslip_count][:8]),
|
||||||
|
NextValue(post_align_bitslip_count, post_align_bitslip_count + 1),
|
||||||
|
NextState("REWRITE_UPPER"),
|
||||||
|
)
|
||||||
|
|
||||||
fsm.act("TERMINATE",
|
fsm.act("TERMINATE",
|
||||||
NextState("TERMINATE"),
|
NextState("TERMINATE"),
|
||||||
|
129
sync_serdes.py
129
sync_serdes.py
@ -35,6 +35,8 @@ class SingleLineRX(Module):
|
|||||||
self.ce = Signal()
|
self.ce = Signal()
|
||||||
self.cnt_out = Signal(5)
|
self.cnt_out = Signal(5)
|
||||||
self.opt_delay = Signal(5)
|
self.opt_delay = Signal(5)
|
||||||
|
self.master_bitslip = Signal()
|
||||||
|
self.slave_bitslip = Signal()
|
||||||
|
|
||||||
ser_in = Signal()
|
ser_in = Signal()
|
||||||
shifts = Signal(2)
|
shifts = Signal(2)
|
||||||
@ -59,7 +61,7 @@ class SingleLineRX(Module):
|
|||||||
o_SHIFTOUT1=shifts[0],
|
o_SHIFTOUT1=shifts[0],
|
||||||
o_SHIFTOUT2=shifts[1],
|
o_SHIFTOUT2=shifts[1],
|
||||||
i_DDLY=ser_in,
|
i_DDLY=ser_in,
|
||||||
i_BITSLIP=0,
|
i_BITSLIP=self.master_bitslip,
|
||||||
i_CLK=ClockSignal("rx_sys5x"),
|
i_CLK=ClockSignal("rx_sys5x"),
|
||||||
i_CLKB=~ClockSignal("rx_sys5x"),
|
i_CLKB=~ClockSignal("rx_sys5x"),
|
||||||
i_CE1=1,
|
i_CE1=1,
|
||||||
@ -77,7 +79,7 @@ class SingleLineRX(Module):
|
|||||||
o_Q3=self.rxdata[1],
|
o_Q3=self.rxdata[1],
|
||||||
o_Q4=self.rxdata[0],
|
o_Q4=self.rxdata[0],
|
||||||
# i_DDLY=ser_in,
|
# i_DDLY=ser_in,
|
||||||
i_BITSLIP=0,
|
i_BITSLIP=self.slave_bitslip,
|
||||||
i_CLK=ClockSignal("rx_sys5x"),
|
i_CLK=ClockSignal("rx_sys5x"),
|
||||||
i_CLKB=~ClockSignal("rx_sys5x"),
|
i_CLKB=~ClockSignal("rx_sys5x"),
|
||||||
i_CE1=1,
|
i_CE1=1,
|
||||||
@ -189,6 +191,129 @@ class BitSlipReader(Module):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class SlaveAligner(Module):
|
||||||
|
def __init__(self):
|
||||||
|
# IN
|
||||||
|
self.loopback_rxdata = Signal(10)
|
||||||
|
self.start = Signal()
|
||||||
|
|
||||||
|
# Wait for stabilization after bitslip
|
||||||
|
self.submodules.stab_timer = WaitTimer(511)
|
||||||
|
|
||||||
|
# OUT
|
||||||
|
self.done = Signal()
|
||||||
|
self.master_bitslip = Signal()
|
||||||
|
self.slave_bitslip = Signal()
|
||||||
|
# self.data_result = Array(Signal(10) for _ in range(5))
|
||||||
|
|
||||||
|
self.slip_count = Signal(3)
|
||||||
|
|
||||||
|
check_odd = Signal()
|
||||||
|
check_even = Signal()
|
||||||
|
|
||||||
|
fsm = FSM(reset_state="WAIT_START")
|
||||||
|
self.submodules += fsm
|
||||||
|
|
||||||
|
fsm.act("WAIT_START",
|
||||||
|
If(self.start,
|
||||||
|
NextState("WAIT_TIMER"),
|
||||||
|
).Else(
|
||||||
|
NextState("WAIT_START"),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
fsm.act("WAIT_TIMER",
|
||||||
|
self.stab_timer.wait.eq(1),
|
||||||
|
If(self.stab_timer.done,
|
||||||
|
NextState("SAMPLE"),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
fsm.act("SAMPLE",
|
||||||
|
# Wait is reset now
|
||||||
|
# Explicit assignment is unnecessary, as combinatorial statement
|
||||||
|
# falls back to he default value when not driven
|
||||||
|
|
||||||
|
# Detect the last 2 bits
|
||||||
|
# If signal is received, detune the master bitslip if necessary
|
||||||
|
If(self.loopback_rxdata[0] | self.loopback_rxdata[1],
|
||||||
|
NextValue(check_odd, self.loopback_rxdata[1]),
|
||||||
|
NextValue(check_even, self.loopback_rxdata[0]),
|
||||||
|
NextState("CHECK_MASTER_BITSLIP"),
|
||||||
|
).Else(
|
||||||
|
NextValue(self.slip_count, self.slip_count + 1),
|
||||||
|
NextState("HIGH_BITSLIP_FIRST"),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Pulsing BITSLIP alternate between 1 right shift and 3 left shifts
|
||||||
|
# We are trying to figure out which 2-bits are the slave copying from
|
||||||
|
# Hence, we only want shifts by 2. Pulsing twice does exactly that.
|
||||||
|
fsm.act("HIGH_BITSLIP_FIRST",
|
||||||
|
self.master_bitslip.eq(1),
|
||||||
|
self.slave_bitslip.eq(1),
|
||||||
|
NextState("LOW_BITSLIP"),
|
||||||
|
)
|
||||||
|
|
||||||
|
fsm.act("LOW_BITSLIP",
|
||||||
|
# bitslip signal is auto-reset
|
||||||
|
NextState("HIGH_BITSLIP_SECOND"),
|
||||||
|
)
|
||||||
|
|
||||||
|
fsm.act("HIGH_BITSLIP_SECOND",
|
||||||
|
self.master_bitslip.eq(1),
|
||||||
|
self.slave_bitslip.eq(1),
|
||||||
|
If(self.slip_count == 5,
|
||||||
|
NextState("TERMINATE"),
|
||||||
|
).Else(
|
||||||
|
NextState("WAIT_TIMER"),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
odd_master_rxdata = self.loopback_rxdata[3::2]
|
||||||
|
even_master_rxdata = self.loopback_rxdata[2::2]
|
||||||
|
|
||||||
|
# Alternatively, we align the master with the slave
|
||||||
|
fsm.act("CHECK_MASTER_BITSLIP",
|
||||||
|
# At any point if the odd and/or even bits from the master reads 0
|
||||||
|
# It implies the detuning is completed
|
||||||
|
NextState("TERMINATE"),
|
||||||
|
If(check_odd & (odd_master_rxdata != 0),
|
||||||
|
NextState("MASTER_HIGH_BITSLIP_FIRST"),
|
||||||
|
),
|
||||||
|
If(check_even & (even_master_rxdata != 0),
|
||||||
|
NextState("MASTER_HIGH_BITSLIP_FIRST"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
fsm.act("MASTER_HIGH_BITSLIP_FIRST",
|
||||||
|
self.master_bitslip.eq(1),
|
||||||
|
NextState("MASTER_LOW_BITSLIP"),
|
||||||
|
)
|
||||||
|
|
||||||
|
fsm.act("MASTER_LOW_BITSLIP",
|
||||||
|
# bitslip signal is auto-reset
|
||||||
|
NextState("MASTER_HIGH_BITSLIP_SECOND"),
|
||||||
|
)
|
||||||
|
|
||||||
|
fsm.act("MASTER_HIGH_BITSLIP_SECOND",
|
||||||
|
self.master_bitslip.eq(1),
|
||||||
|
NextState("MASTER_WAIT_TIMER"),
|
||||||
|
)
|
||||||
|
|
||||||
|
fsm.act("MASTER_WAIT_TIMER",
|
||||||
|
self.stab_timer.wait.eq(1),
|
||||||
|
If(self.stab_timer.done,
|
||||||
|
NextState("CHECK_MASTER_BITSLIP"),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
fsm.act("TERMINATE",
|
||||||
|
self.done.eq(1),
|
||||||
|
NextState("TERMINATE"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class PhaseReader(Module):
|
class PhaseReader(Module):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
146
test_aligner.py
146
test_aligner.py
@ -1,5 +1,5 @@
|
|||||||
from migen import *
|
from migen import *
|
||||||
from sync_serdes import PhaseReader, DelayOptimizer, BitSlipReader
|
from sync_serdes import PhaseReader, DelayOptimizer, BitSlipReader, SlaveAligner
|
||||||
import random
|
import random
|
||||||
|
|
||||||
|
|
||||||
@ -131,6 +131,73 @@ def bitslip_reader_tb(dut, rxdata_list):
|
|||||||
yield
|
yield
|
||||||
|
|
||||||
|
|
||||||
|
def bitslip_aligner_tb(dut, rxdata_list, adjust_list):
|
||||||
|
# Start the module
|
||||||
|
yield dut.start.eq(1)
|
||||||
|
assert (yield dut.stab_timer.wait) == 0
|
||||||
|
|
||||||
|
for i in range(len(rxdata_list)):
|
||||||
|
yield dut.loopback_rxdata.eq(rxdata_list[i])
|
||||||
|
yield
|
||||||
|
yield
|
||||||
|
assert (yield dut.stab_timer.wait) == 1
|
||||||
|
|
||||||
|
# Wait until the timer runs out
|
||||||
|
while (yield dut.stab_timer.done) == 0:
|
||||||
|
yield
|
||||||
|
|
||||||
|
# There will not be unnecessary pulses
|
||||||
|
if i == (len(rxdata_list) - 1):
|
||||||
|
break
|
||||||
|
|
||||||
|
# Keep yielding until the DUT gives BITSLIP signal
|
||||||
|
while (((yield dut.master_bitslip) == 0) and ((yield dut.slave_bitslip) == 0)):
|
||||||
|
yield
|
||||||
|
|
||||||
|
# There will be 2 BITSLIP pulses
|
||||||
|
# Both BITSLIP pulses should last for 1 cycle
|
||||||
|
assert (yield dut.master_bitslip) == 1
|
||||||
|
assert (yield dut.slave_bitslip) == 1
|
||||||
|
yield
|
||||||
|
assert (yield dut.master_bitslip) == 0
|
||||||
|
assert (yield dut.slave_bitslip) == 0
|
||||||
|
yield
|
||||||
|
assert (yield dut.master_bitslip) == 1
|
||||||
|
assert (yield dut.slave_bitslip) == 1
|
||||||
|
yield
|
||||||
|
assert (yield dut.master_bitslip) == 0
|
||||||
|
assert (yield dut.slave_bitslip) == 0
|
||||||
|
|
||||||
|
# Skip ahead 2 cycles for state transitions
|
||||||
|
yield
|
||||||
|
yield
|
||||||
|
|
||||||
|
for i in range(len(adjust_list)):
|
||||||
|
# Eventually the master bitslip signal will be pulled up
|
||||||
|
while (yield dut.master_bitslip) == 0:
|
||||||
|
yield
|
||||||
|
|
||||||
|
assert (yield dut.master_bitslip) == 1
|
||||||
|
assert (yield dut.slave_bitslip) == 0
|
||||||
|
yield
|
||||||
|
assert (yield dut.master_bitslip) == 0
|
||||||
|
assert (yield dut.slave_bitslip) == 0
|
||||||
|
yield
|
||||||
|
assert (yield dut.master_bitslip) == 1
|
||||||
|
assert (yield dut.slave_bitslip) == 0
|
||||||
|
yield
|
||||||
|
assert (yield dut.master_bitslip) == 0
|
||||||
|
assert (yield dut.slave_bitslip) == 0
|
||||||
|
|
||||||
|
# Give the new rxdata
|
||||||
|
yield dut.loopback_rxdata.eq(adjust_list[i])
|
||||||
|
while (yield dut.stab_timer.done) == 0:
|
||||||
|
yield
|
||||||
|
|
||||||
|
yield
|
||||||
|
yield
|
||||||
|
assert (yield dut.done) == 1
|
||||||
|
|
||||||
# # Random testing for delay reader
|
# # Random testing for delay reader
|
||||||
# for _ in range(32):
|
# for _ in range(32):
|
||||||
# rxdata_list = [ random.getrandbits(10) for _ in range(32) ]
|
# rxdata_list = [ random.getrandbits(10) for _ in range(32) ]
|
||||||
@ -191,8 +258,75 @@ def bitslip_reader_tb(dut, rxdata_list):
|
|||||||
# vcd_name="delay_opt.vcd"
|
# vcd_name="delay_opt.vcd"
|
||||||
# )
|
# )
|
||||||
|
|
||||||
# Random test for bitslip reader
|
# # Random test for bitslip reader
|
||||||
for _ in range(32):
|
# for _ in range(32):
|
||||||
rxdata_list = [ random.getrandbits(10) for _ in range(5) ]
|
# rxdata_list = [ random.getrandbits(10) for _ in range(5) ]
|
||||||
dut = BitSlipReader()
|
# dut = BitSlipReader()
|
||||||
run_simulation(dut, bitslip_reader_tb(dut, rxdata_list), vcd_name="bitslip_reader.vcd")
|
# run_simulation(dut, bitslip_reader_tb(dut, rxdata_list), vcd_name="bitslip_reader.vcd")
|
||||||
|
|
||||||
|
# Test for bitslip alignment
|
||||||
|
def generate_aligner_tb_list(mocked_pair, start_pair):
|
||||||
|
print("Mocked pair", str(mocked_pair))
|
||||||
|
print("Start pair", str(start_pair))
|
||||||
|
double_bit_pattern = bool(random.randint(0, 1))
|
||||||
|
pulsed_indices = [ random.randint(0, 9) ]
|
||||||
|
print("Pulsed indices", str(pulsed_indices))
|
||||||
|
|
||||||
|
if double_bit_pattern:
|
||||||
|
pulsed_indices.append((pulsed_indices[0] + 1) % 10)
|
||||||
|
|
||||||
|
def generate_rxdata(pair_shift):
|
||||||
|
mocked_data = 0
|
||||||
|
|
||||||
|
rxdata = 0
|
||||||
|
for index in pulsed_indices:
|
||||||
|
rxdata |= (1 << ((index + 2*pair_shift) % 10))
|
||||||
|
|
||||||
|
mocking_mask = (1 << (2*mocked_pair)) | (1 << ((2*mocked_pair) + 1))
|
||||||
|
mocked_data = ((rxdata & mocking_mask) >> (2*mocked_pair))
|
||||||
|
|
||||||
|
# Wipe out the 2 lsb
|
||||||
|
rxdata &= 0x3FC
|
||||||
|
# Copy the mocked data to the 2 lsb
|
||||||
|
rxdata |= mocked_data
|
||||||
|
return mocked_data, rxdata
|
||||||
|
|
||||||
|
rxdata_list = []
|
||||||
|
for i in range(5):
|
||||||
|
mocked_data, rxdata = generate_rxdata((start_pair + i) % 5)
|
||||||
|
rxdata_list.append(rxdata)
|
||||||
|
if mocked_data:
|
||||||
|
break
|
||||||
|
|
||||||
|
print("Mocked data", str(mocked_data))
|
||||||
|
|
||||||
|
def is_mocking(original):
|
||||||
|
if original == 0:
|
||||||
|
return False
|
||||||
|
if (original & 0b11) == mocked_data:
|
||||||
|
return True
|
||||||
|
return is_mocking(original >> 2)
|
||||||
|
|
||||||
|
adjust_list = []
|
||||||
|
master_rxdata = rxdata_list[-1] & 0x3FC
|
||||||
|
if mocked_data and is_mocking(master_rxdata):
|
||||||
|
# Keep adding shifted variant to the adjust_list
|
||||||
|
# Until the 2 lsb is not mocking other pairs
|
||||||
|
while True:
|
||||||
|
master_rxdata <<= 2
|
||||||
|
master_rxdata &= 0x3FF
|
||||||
|
adjust_list.append(master_rxdata | mocked_data)
|
||||||
|
if not is_mocking(master_rxdata):
|
||||||
|
break
|
||||||
|
|
||||||
|
return rxdata_list, adjust_list
|
||||||
|
|
||||||
|
for mocked_pair in range(5):
|
||||||
|
for start_pair in range(5):
|
||||||
|
for _ in range(12):
|
||||||
|
rxdata_list, adjust_list = generate_aligner_tb_list(mocked_pair, start_pair)
|
||||||
|
print(rxdata_list)
|
||||||
|
print(adjust_list)
|
||||||
|
dut = SlaveAligner()
|
||||||
|
run_simulation(dut, bitslip_aligner_tb(dut, rxdata_list, adjust_list), vcd_name="bitslip_aligner.vcd")
|
||||||
|
print(mocked_pair, start_pair)
|
||||||
|
Loading…
Reference in New Issue
Block a user