init multi loopback
This commit is contained in:
parent
b38a4d6b8c
commit
24e8e9add9
|
@ -0,0 +1,104 @@
|
||||||
|
from migen import *
|
||||||
|
from sync_serdes import SyncSingleRX, SingleLineTX
|
||||||
|
from migen.genlib.fifo import SyncFIFO
|
||||||
|
from migen.build.platforms.sinara import kasli
|
||||||
|
from kasli_crg import KasliCRG
|
||||||
|
from eem_helpers import generate_pads
|
||||||
|
from uart import UART
|
||||||
|
from io_loopback import SingleIOLoopback
|
||||||
|
|
||||||
|
|
||||||
|
class MultiSerDesLoopBack(Module):
|
||||||
|
def __init__(self, io_pad, sys_clk_freq):
|
||||||
|
self.uart_rx = Signal()
|
||||||
|
self.uart_tx = Signal()
|
||||||
|
|
||||||
|
self.submodules.uart = UART(round((115200/sys_clk_freq)*2**32))
|
||||||
|
self.comb += [
|
||||||
|
self.uart.phy_rx.eq(self.uart_rx),
|
||||||
|
self.uart_tx.eq(self.uart.phy_tx),
|
||||||
|
]
|
||||||
|
|
||||||
|
self.submodules.tx = SingleLineTX()
|
||||||
|
self.submodules.sync_rx = SyncSingleRX()
|
||||||
|
|
||||||
|
# The actual channel
|
||||||
|
self.submodules.channel = SingleIOLoopback(io_pad)
|
||||||
|
|
||||||
|
# Attach FIFO to UART TX, send rate is too slow w.r.t sysclk
|
||||||
|
self.submodules.tx_fifo = SyncFIFO(8, 64)
|
||||||
|
|
||||||
|
self.comb += [
|
||||||
|
# Repetitively send 0b00100
|
||||||
|
self.tx.txdata.eq(0b00100),
|
||||||
|
|
||||||
|
# Loopback channel
|
||||||
|
self.channel.i.eq(self.tx.ser_out),
|
||||||
|
self.sync_rx.ser_in_no_dly.eq(self.channel.o),
|
||||||
|
self.channel.t.eq(self.tx.t_out),
|
||||||
|
|
||||||
|
# TX path
|
||||||
|
self.uart.tx_data.eq(self.tx_fifo.dout),
|
||||||
|
self.uart.tx_stb.eq(self.tx_fifo.readable),
|
||||||
|
self.tx_fifo.re.eq(self.uart.tx_ack),
|
||||||
|
]
|
||||||
|
|
||||||
|
self.submodules.fsm = FSM(reset_state="WAIT_SELF_ALIGN")
|
||||||
|
|
||||||
|
self.fsm.act("WAIT_SELF_ALIGN",
|
||||||
|
If(self.sync_rx.align_done,
|
||||||
|
NextState("SAMPLE_RXDATA"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
sampled_rxdata = Signal(5)
|
||||||
|
|
||||||
|
self.fsm.act("SAMPLE_RXDATA",
|
||||||
|
NextValue(sampled_rxdata, self.sync_rx.rxdata),
|
||||||
|
NextState("WRITE_PATTERN_UPPER"),
|
||||||
|
)
|
||||||
|
|
||||||
|
self.fsm.act("WRITE_PATTERN_UPPER",
|
||||||
|
If(self.tx_fifo.writable,
|
||||||
|
self.tx_fifo.we.eq(1),
|
||||||
|
self.tx_fifo.din.eq(sampled_rxdata),
|
||||||
|
NextState("WRITE_PATTERN_LOWER"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
self.fsm.act("WRITE_PATTERN_LOWER",
|
||||||
|
If(self.tx_fifo.writable,
|
||||||
|
self.tx_fifo.we.eq(1),
|
||||||
|
self.tx_fifo.din.eq(sampled_rxdata),
|
||||||
|
NextState("TERMINATE"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
self.fsm.act("TERMINATE",
|
||||||
|
NextState("TERMINATE"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
platform = kasli.Platform(hw_rev="v2.0")
|
||||||
|
|
||||||
|
# Generate pads for the I/O blocks
|
||||||
|
eem = 3
|
||||||
|
generate_pads(platform, eem)
|
||||||
|
# pads = [
|
||||||
|
# platform.request("dio{}".format(eem), i) for i in range(4)
|
||||||
|
# ]
|
||||||
|
pad = platform.request("dio{}".format(eem), 0)
|
||||||
|
|
||||||
|
crg = KasliCRG(platform)
|
||||||
|
top = MultiSerDesLoopBack(pad, crg.sys_clk_freq)
|
||||||
|
|
||||||
|
# Wire up UART core to the pads
|
||||||
|
uart_pads = platform.request("serial")
|
||||||
|
top.comb += [
|
||||||
|
top.uart_rx.eq(uart_pads.rx),
|
||||||
|
uart_pads.tx.eq(top.uart_tx),
|
||||||
|
]
|
||||||
|
|
||||||
|
top.submodules += crg
|
||||||
|
platform.build(top)
|
|
@ -36,7 +36,6 @@ class SingleLineRX(Module):
|
||||||
self.ce = Signal()
|
self.ce = Signal()
|
||||||
self.cnt_in = Signal(5)
|
self.cnt_in = Signal(5)
|
||||||
self.cnt_out = Signal(5)
|
self.cnt_out = Signal(5)
|
||||||
self.opt_delay = Signal(5)
|
|
||||||
self.master_bitslip = Signal()
|
self.master_bitslip = Signal()
|
||||||
self.slave_bitslip = Signal()
|
self.slave_bitslip = Signal()
|
||||||
|
|
||||||
|
@ -560,3 +559,84 @@ class DelayOptimizer(Module):
|
||||||
self.select_odd.eq(self.expected_pulse[0]),
|
self.select_odd.eq(self.expected_pulse[0]),
|
||||||
NextState("TERMINATE"),
|
NextState("TERMINATE"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class SyncSingleRX(Module):
|
||||||
|
def __init__(self):
|
||||||
|
# Ports
|
||||||
|
# IN: Undelayed serial signal
|
||||||
|
self.ser_in_no_dly = Signal()
|
||||||
|
# OUT: Received data after self-alignment, decimation
|
||||||
|
self.rxdata = Signal(5)
|
||||||
|
# OUT: RXDATA from this channel is self-aligned
|
||||||
|
self.align_done = Signal()
|
||||||
|
|
||||||
|
# Components
|
||||||
|
self.submodules.rx = SingleLineRX()
|
||||||
|
self.submodules.slave_aligner = SlaveAligner()
|
||||||
|
self.submodules.delay_solver = DelayOptimizer()
|
||||||
|
|
||||||
|
# Sample decimation
|
||||||
|
select_odd = Signal()
|
||||||
|
decimated_rxdata = Signal(5)
|
||||||
|
|
||||||
|
# Dataflow
|
||||||
|
self.comb += [
|
||||||
|
# Delay and oversample the original signal
|
||||||
|
self.rx.ser_in_no_dly.eq(self.ser_in_no_dly),
|
||||||
|
|
||||||
|
# Use the deserialized signals for alignment
|
||||||
|
self.slave_aligner.loopback_rxdata.eq(self.rx.rxdata),
|
||||||
|
self.delay_solver.loopback_rxdata.eq(self.rx.rxdata),
|
||||||
|
|
||||||
|
# Decimate the oversampled signals
|
||||||
|
If(select_odd,
|
||||||
|
decimated_rxdata.eq(self.rx.rxdata[1::2]),
|
||||||
|
).Else(
|
||||||
|
decimated_rxdata.eq(self.rx.rxdata[::2]),
|
||||||
|
),
|
||||||
|
|
||||||
|
# Send it to the output
|
||||||
|
self.rxdata.eq(decimated_rxdata),
|
||||||
|
]
|
||||||
|
|
||||||
|
# Control signals
|
||||||
|
self.comb += [
|
||||||
|
# Bitslip alignment
|
||||||
|
self.rx.master_bitslip.eq(self.slave_aligner.master_bitslip),
|
||||||
|
self.rx.slave_bitslip.eq(self.slave_aligner.slave_bitslip),
|
||||||
|
|
||||||
|
# Tap delay optimization
|
||||||
|
self.rx.ce.eq(self.delay_solver.inc_en),
|
||||||
|
self.rx.ld.eq(self.delay_solver.ld),
|
||||||
|
self.rx.cnt_in.eq(self.delay_solver.opt_delay_tap),
|
||||||
|
self.delay_solver.delay_tap.eq(self.rx.cnt_out),
|
||||||
|
]
|
||||||
|
|
||||||
|
self.submodules.fsm = FSM(reset_state="WAIT_SIGNAL")
|
||||||
|
|
||||||
|
self.fsm.act("WAIT_SIGNAL",
|
||||||
|
If(self.rx.rxdata != 0,
|
||||||
|
NextState("WAIT_ALIGNER")
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
self.fsm.act("WAIT_ALIGNER",
|
||||||
|
self.slave_aligner.start.eq(1),
|
||||||
|
If(self.slave_aligner.done,
|
||||||
|
NextState("WAIT_DELAY_OPT"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
self.fsm.act("WAIT_DELAY_OPT",
|
||||||
|
self.delay_solver.start.eq(1),
|
||||||
|
If(self.delay_solver.done,
|
||||||
|
NextValue(select_odd, self.delay_solver.select_odd),
|
||||||
|
NextState("INTRA_ALIGN_DONE"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
self.fsm.act("INTRA_ALIGN_DONE",
|
||||||
|
self.align_done.eq(1),
|
||||||
|
NextState("INTRA_ALIGN_DONE"),
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in New Issue