from migen import * from 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 IOLoopBack SEPARATOR = Constant(0b0101) class SerDesLoopBack(Module): def __init__(self, io_pads, 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 = SerTX() self.submodules.rx = DesRX() # The actual channel self.submodules.channel = IOLoopBack(io_pads) # # Additional timer: Only permit UART transmission when timer is not up # self.submodules.wait_timer = WaitTimer(10) # Memoize the previous rxdata self.rxdata_r = Signal(8) # Attach FIFO to UART TX, send rate is too slow w.r.t sysclk self.submodules.tx_fifo = SyncFIFO(8, 64) self.comb += [ # RX path: From UART to channel # self.rx_buffer.din.eq(self.uart.rx_data), # self.rx_buffer.we.eq(self.uart.rx_stb), self.tx.txdata[:8].eq(Mux(self.uart.rx_stb, self.uart.rx_data, 0)), self.tx.txdata[8:12].eq(Mux(SEPARATOR, self.uart.rx_data, 0)), self.tx.txdata[12:].eq(Mux(self.uart.rx_stb, self.uart.rx_data, 0)), # Loopback channel self.channel.i.eq(self.tx.ser_out), self.rx.ser_in.eq(self.channel.o), self.channel.t.eq(self.tx.t_out), # self.rx.ser_in.eq(self.tx.ser_out), # self.rx.ser_in[3].eq(self.tx.ser_out[3]), # TX path # self.uart.tx_data.eq(self.tx_buffer.dout), # self.uart.tx_stb.eq(self.tx_buffer.readable), # self.tx_buffer.re.eq(self.uart.tx_ack), 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), ] # Timer control self.sync += [ # Send data to FIFO if not repeated If(self.rxdata_r != self.rx.rxdata[:8], 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) ) ] # self.sync.sys5x += [ # self.rx.ser_in.eq(self.tx.ser_out), # ] if __name__ == "__main__": platform = kasli.Platform(hw_rev="v2.0") # Generate pads for the I/O blocks eem = 0 generate_pads(platform, eem) pads = [ platform.request("dio{}".format(eem), i) for i in range(4) ] crg = KasliCRG(platform) top = SerDesLoopBack(pads, 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)