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)