165 lines
5.2 KiB
Python
165 lines
5.2 KiB
Python
from migen import *
|
|
from sync_serdes import *
|
|
from migen.genlib.fifo import SyncFIFO
|
|
from migen.build.platforms.sinara import kasli
|
|
from migen.genlib.misc import WaitTimer
|
|
from kasli_crg import KasliCRG
|
|
from eem_helpers import generate_pads
|
|
from uart import UART
|
|
from io_loopback import SingleIOLoopback
|
|
|
|
|
|
SEPARATOR = Constant(0b0101)
|
|
|
|
class SingleSerDesLoopBack(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.rx = SingleLineRX()
|
|
self.submodules.phase_reader = PhaseReader()
|
|
# self.submodules.delay_optimizer = DelayOptimizer()
|
|
|
|
# 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.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),
|
|
]
|
|
|
|
# Route deserializer to phase_reader & the delay tap optimizer
|
|
self.comb += [
|
|
# Start the reader initially
|
|
self.phase_reader.start.eq(1),
|
|
# Delay tap optimizer will start after the reader is done
|
|
# self.delay_optimizer.start.eq(0),
|
|
|
|
# RXDATA for both reader and optimzer
|
|
self.phase_reader.loopback_rxdata.eq(self.rx.rxdata),
|
|
# TODO: Reconnet
|
|
# self.delay_optimizer.loopback_rxdata.eq(self.rx.rxdata),
|
|
|
|
# Delay tap value
|
|
self.phase_reader.delay_tap.eq(self.rx.cnt_out),
|
|
# TODO: Reconnet
|
|
# self.delay_optimizer.delay_tap.eq(self.rx.cnt_out),
|
|
|
|
# Increment control enable, such that phase_reader can
|
|
# increment tap value after delay measurement
|
|
# Re-assign the incremnet control to the optimizer after the optimizer has started
|
|
# If(self.delay_optimizer.start,
|
|
# self.rx.ce.eq(self.delay_optimizer.inc_en),
|
|
# ).Else(
|
|
# self.rx.ce.eq(self.phase_reader.inc_en),
|
|
# )
|
|
self.rx.ce.eq(self.phase_reader.inc_en),
|
|
]
|
|
|
|
# Show measured result on UART
|
|
delay_tap = Signal(6)
|
|
|
|
fsm = FSM(reset_state="WAIT_DONE")
|
|
self.submodules += fsm
|
|
|
|
fsm.act("WAIT_DONE",
|
|
If(self.phase_reader.done,
|
|
NextState("WRITE_UPPER"),
|
|
),
|
|
)
|
|
|
|
fsm.act("WRITE_UPPER",
|
|
# Exist state if all results are sent
|
|
If(delay_tap == 32,
|
|
NextState("TERMINATE"),
|
|
).Elif(self.tx_fifo.writable,
|
|
self.tx_fifo.we.eq(1),
|
|
self.tx_fifo.din.eq(self.phase_reader.data_result[delay_tap][8:]),
|
|
NextState("WRITE_LOWER"),
|
|
),
|
|
)
|
|
|
|
fsm.act("WRITE_LOWER",
|
|
self.tx_fifo.we.eq(1),
|
|
self.tx_fifo.din.eq(self.phase_reader.data_result[delay_tap][:8]),
|
|
NextValue(delay_tap, delay_tap + 1),
|
|
NextState("WRITE_UPPER"),
|
|
)
|
|
|
|
# fsm.act("FIND_OPT_DELAY",
|
|
# self.delay_optimizer.start.eq(1),
|
|
# self.rx.ce.eq(self.delay_optimizer.inc_en),
|
|
# If(self.delay_optimizer.done,
|
|
# NextState("WRITE_OPT"),
|
|
# ).Else(
|
|
# NextState("FIND_OPT_DELAY")
|
|
# )
|
|
# )
|
|
|
|
# fsm.act("WRITE_OPT",
|
|
# self.tx_fifo.we.eq(1),
|
|
# self.tx_fifo.din.eq(self.delay_optimizer.opt_delay_tap),
|
|
# NextState("TERMINATE")
|
|
# )
|
|
|
|
fsm.act("TERMINATE",
|
|
NextState("TERMINATE"),
|
|
)
|
|
|
|
# # Output control
|
|
# self.sync += [
|
|
# # Send data to FIFO if not repeated
|
|
# If(self.rxdata_r[:5] != self.rx.rxdata,
|
|
# self.rxdata_r.eq(self.rx.rxdata),
|
|
# self.tx_fifo.din.eq(self.rx.rxdata),
|
|
# self.tx_fifo.we.eq(1)
|
|
# ).Else(
|
|
# self.tx_fifo.we.eq(0)
|
|
# )
|
|
# ]
|
|
|
|
|
|
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 = SingleSerDesLoopBack(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)
|