diff --git a/comm.py b/comm.py index 03f72e7..bae3183 100644 --- a/comm.py +++ b/comm.py @@ -1,8 +1,8 @@ import serial -def main(): - comm = serial.Serial("/dev/ttyUSB3", 115200) +def main(serial_port): + comm = serial.Serial(serial_port, 115200) # comm.write(b"Hello World!") # for _ in range(32): @@ -19,4 +19,15 @@ def main(): # print(f'{byte[0]:0>8b}') if __name__ == "__main__": - main() + import argparse + + parser = argparse.ArgumentParser() + parser.add_argument("platform") + args = parser.parse_args() + + port_dict = { + "kasli": "/dev/ttyUSB3", + "efc": "/dev/ttyACM1", + } + + main(port_dict[args.platform]) diff --git a/kasli_crg.py b/kasli_crg.py index 50407bf..a76ae4c 100644 --- a/kasli_crg.py +++ b/kasli_crg.py @@ -3,8 +3,8 @@ from migen.build.platforms.sinara import kasli from migen.genlib.resetsync import AsyncResetSynchronizer -class KasliCRG(Module): - def __init__(self, platform): +class TransceiverCRG(Module): + def __init__(self, platform, clk125): self.platform = platform # Generated clock domains @@ -16,7 +16,6 @@ class KasliCRG(Module): # Configure system clock using GTP ports self.sys_clk_freq = 125e6 - clk125 = self.platform.request("clk125_gtp") clk125_buf = Signal() clk125_div2 = Signal() diff --git a/multi_serdes_loopback.py b/multi_serdes_loopback.py index d56c676..f968854 100644 --- a/multi_serdes_loopback.py +++ b/multi_serdes_loopback.py @@ -1,8 +1,8 @@ from migen import * from sync_serdes import MultiLineRX, MultiLineTX from migen.genlib.fifo import SyncFIFO -from migen.build.platforms.sinara import kasli -from kasli_crg import KasliCRG +from migen.build.platforms.sinara import kasli, efc +from kasli_crg import TransceiverCRG from eem_helpers import generate_pads from uart import UART from io_loopback import SingleIOLoopback, IOLoopBack @@ -47,11 +47,16 @@ class MultiSerDesLoopBack(Module): self.submodules.rx_fsm = FSM(reset_state="WAIT_GROUP_ALIGN") + sampled_rxdata = Array(Signal(20) for _ in range(16)) + sample_idx = Signal(4) + self.rx_fsm.act("WAIT_GROUP_ALIGN", If(self.rx.err, - NextState("WRITE_ERR_UPPER") + NextState("WRITE_ERR_UPPER"), ).Elif(self.rx.rxdata == 0b11111111111111111111, - NextState("SAMPLE_RXDATA") + NextValue(sampled_rxdata[0], self.rx.rxdata), + NextValue(sample_idx, 1), + NextState("SAMPLE_RXDATA"), ), ) @@ -71,23 +76,27 @@ class MultiSerDesLoopBack(Module): ), ) - sampled_rxdata = Array(Signal(20) for _ in range(5)) - sample_idx = Signal(3) - self.rx_fsm.act("SAMPLE_RXDATA", - If((sample_idx != 0) | (self.rx.rxdata != 0), - If(sample_idx == 5, - NextValue(sample_idx, 0), - NextState("WRITE_PATTERN_FIRST_UPPER"), - ).Else( - NextValue(sampled_rxdata[sample_idx], self.rx.rxdata), - NextValue(sample_idx, sample_idx + 1), - ), + # If((sample_idx != 0) | (self.rx.rxdata != 0), + # If(sample_idx == 15, + # NextValue(sample_idx, 0), + # NextState("WRITE_PATTERN_FIRST_UPPER"), + # ).Else( + # NextValue(sampled_rxdata[sample_idx], self.rx.rxdata), + # NextValue(sample_idx, sample_idx + 1), + # ), + # ), + If(sample_idx == 15, + NextValue(sample_idx, 0), + NextState("WRITE_PATTERN_FIRST_UPPER"), + ).Else( + NextValue(sampled_rxdata[sample_idx], self.rx.rxdata), + NextValue(sample_idx, sample_idx + 1), ), ) self.rx_fsm.act("WRITE_PATTERN_FIRST_UPPER", - If(sample_idx == 5, + If(sample_idx == 15, NextState("TERMINATE"), ).Elif(self.tx_fifo.writable, self.tx_fifo.we.eq(1), @@ -134,11 +143,11 @@ class MultiSerDesLoopBack(Module): ), ) - send_zero_duration = Signal(4) + send_zero_duration = Signal(2) self.tx_fsm.act("SEND_ZERO", self.tx.txdata.eq(0), - If(send_zero_duration == 0b1111, + If(send_zero_duration == 0b11, NextState("SEND_PULSE"), ).Else( NextValue(send_zero_duration, send_zero_duration + 1), @@ -158,7 +167,7 @@ class MultiSerDesLoopBack(Module): ) self.tx_fsm.act("SEND_ARB_DATA", - self.tx.txdata.eq(0xDEADB), + self.tx.txdata.eq(0b00111001110011100111), NextState("TERMINATE"), ) @@ -169,17 +178,36 @@ class MultiSerDesLoopBack(Module): if __name__ == "__main__": - platform = kasli.Platform(hw_rev="v2.0") + import argparse + + parser = argparse.ArgumentParser() + parser.add_argument("platform") + args = parser.parse_args() + + platform_dict = { + "kasli": kasli.Platform(hw_rev="v2.0"), + "efc": efc.Platform(), + } + + sysclk_name = { + "kasli": "clk125_gtp", + "efc": "gtp_clk", + } + + platform = platform_dict[args.platform] + sysclk = platform.request(sysclk_name[args.platform]) # Generate pads for the I/O blocks - eem = 3 + # Using EEM1 for both as both EFC and Kasli has EEM1 + # EEM1 are not interconnected + eem = 1 generate_pads(platform, eem) pads = [ - platform.request("dio{}".format(eem), i) for i in range(4) + platform.request("dio{}".format(eem), i+4) for i in range(4) ] # pad = platform.request("dio{}".format(eem), 0) - crg = KasliCRG(platform) + crg = TransceiverCRG(platform, sysclk) top = MultiSerDesLoopBack(pads, crg.sys_clk_freq) # Wire up UART core to the pads diff --git a/single_serdes_loopback.py b/single_serdes_loopback.py index 607bbff..73ac078 100644 --- a/single_serdes_loopback.py +++ b/single_serdes_loopback.py @@ -3,7 +3,7 @@ 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 kasli_crg import TransceiverCRG from eem_helpers import generate_pads from uart import UART from io_loopback import SingleIOLoopback @@ -82,11 +82,6 @@ class SingleSerDesLoopBack(Module): # Debugging logics if debug: self.comb += [ - # Start the reader initially - self.bitslip_reader.start.eq(1), - self.post_align_reader.start.eq(0), - self.phase_reader.start.eq(0), - self.bitslip_reader.loopback_rxdata.eq(self.rx.rxdata), self.post_align_reader.loopback_rxdata.eq(self.rx.rxdata), self.phase_reader.loopback_rxdata.eq(self.rx.rxdata), @@ -212,7 +207,9 @@ class SingleSerDesLoopBack(Module): self.submodules += fsm fsm.act("WAIT_DONE", + self.bitslip_reader.start.eq(1), If(self.bitslip_reader.done, + NextValue(bitslip_count, 0), NextState("WRITE_UPPER"), ), ) @@ -229,10 +226,12 @@ class SingleSerDesLoopBack(Module): ) fsm.act("WRITE_LOWER", - self.tx_fifo.we.eq(1), - self.tx_fifo.din.eq(self.bitslip_reader.data_result[bitslip_count][:8]), - NextValue(bitslip_count, bitslip_count + 1), - NextState("WRITE_UPPER"), + If(self.tx_fifo.writable, + self.tx_fifo.we.eq(1), + self.tx_fifo.din.eq(self.bitslip_reader.data_result[bitslip_count][:8]), + NextValue(bitslip_count, bitslip_count + 1), + NextState("WRITE_UPPER"), + ) ) fsm.act("START_SLAVE_ALIGNER", @@ -373,6 +372,12 @@ class SingleSerDesLoopBack(Module): If(self.tx_fifo.writable, self.tx_fifo.we.eq(1), self.tx_fifo.din.eq(self.delay_solver.opt_delay_tap), + NextState("WAIT_OPT_DELAY_ACTIVE"), + ), + ) + + fsm.act("WAIT_OPT_DELAY_ACTIVE", + If(self.rx.cnt_out == self.delay_solver.opt_delay_tap, NextState("RESAMPLE_RXDATA_UPPER"), ), ) @@ -468,15 +473,12 @@ if __name__ == "__main__": platform = kasli.Platform(hw_rev="v2.0") # Generate pads for the I/O blocks - eem = 3 + eem = 2 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, False) + crg = TransceiverCRG(platform, platform.request("clk125_gtp")) + top = SingleSerDesLoopBack(pad, crg.sys_clk_freq, True) # Wire up UART core to the pads uart_pads = platform.request("serial") diff --git a/sync_serdes.py b/sync_serdes.py index 17cffbe..0070f48 100644 --- a/sync_serdes.py +++ b/sync_serdes.py @@ -207,7 +207,6 @@ class SlaveAligner(Module): 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) @@ -314,7 +313,7 @@ class SlaveAligner(Module): # After eliminating the potentially duplicating pattern, # Shift the entire output pattern for delay tap optimization # Ideally, the optimized first edge would be the middle pair - # So, shift it until bit 4/5 is set and bit 6 is not set + # So, shift it until bit 3/4 is set but bit 5 is not set fsm.act("SHIFT_WAIT_TIMER", self.stab_timer.wait.eq(1), If(self.stab_timer.done, @@ -323,7 +322,7 @@ class SlaveAligner(Module): ) fsm.act("SHIFT_SAMPLE_PATTERN", - If((self.loopback_rxdata[4:6] != 0) & ~self.loopback_rxdata[6], + If((self.loopback_rxdata[3:4] != 0) & ~self.loopback_rxdata[5], NextState("TERMINATE"), ).Else( NextState("SHIFT_HIGH_BITSLIP_FIRST"), @@ -552,7 +551,13 @@ class DelayOptimizer(Module): fsm.act("LOAD_OPT_DELAY", self.ld.eq(1), # The optimal delay tap is prepared in the SAMPLE_PULSE_OUT state - NextState("TERMINATE"), + NextState("WAIT_DELAY_LOAD"), + ) + + fsm.act("WAIT_DELAY_LOAD", + If(self.delay_tap == self.opt_delay_tap, + NextState("TERMINATE"), + ), ) fsm.act("TERMINATE", @@ -698,7 +703,7 @@ class MultiLineRX(Module): # Signal from each OSERDES group can have a different delay # So, add delay to the groups that receives the pulse early # Maximum delay = 8 - channel_buffer = SyncFIFO(5, 8) + channel_buffer = SyncFIFO(5, 16) self.comb += [ # Allow data go through the FIFO unless aligning