diff --git a/single_serdes_loopback.py b/single_serdes_loopback.py index a7ecf6a..2ad07a1 100644 --- a/single_serdes_loopback.py +++ b/single_serdes_loopback.py @@ -34,8 +34,6 @@ class SingleSerDesLoopBack(Module): self.submodules.phase_reader = PhaseReader() self.submodules.delay_solver = DelayOptimizer() - # self.submodules.delay_optimizer = DelayOptimizer() - # The actual channel self.submodules.channel = SingleIOLoopback(io_pad) @@ -102,6 +100,8 @@ class SingleSerDesLoopBack(Module): delay_tap_count = Signal(6) bitslip_count = Signal(3) post_align_bitslip_count = Signal(3) + rx_intra_aligned = Signal() + select_odd = Signal() fsm = FSM(reset_state="WAIT_DONE") self.submodules += fsm @@ -249,6 +249,7 @@ class SingleSerDesLoopBack(Module): fsm.act("WAIT_DELAY_SOLVER", If(self.delay_solver.done, + NextValue(select_odd, self.delay_solver.select_odd), NextState("WRITE_UPPER_ZERO"), ).Else( NextState("WAIT_DELAY_SOLVER"), @@ -283,6 +284,52 @@ class SingleSerDesLoopBack(Module): If(self.tx_fifo.writable, self.tx_fifo.we.eq(1), self.tx_fifo.din.eq(self.rx.rxdata[:8]), + NextState("INTRA_ALIGN_DONE"), + ) + ) + + fsm.act("INTRA_ALIGN_DONE", + rx_intra_aligned.eq(1), + NextState("WAIT_TX_ZERO"), + ) + + rxdata_decimated = Signal(5) + + self.comb += [ + If(select_odd, + rxdata_decimated.eq(self.rx.rxdata[1::2]), + ).Else( + rxdata_decimated.eq(self.rx.rxdata[::2]), + ), + ] + + fsm.act("WAIT_TX_ZERO", + If(rxdata_decimated == 0, + NextState("WAIT_PULSE"), + ), + ) + + rxdata_pulse_read = Signal(10) + + fsm.act("WAIT_PULSE", + If(rxdata_decimated != 0, + NextValue(rxdata_pulse_read, rxdata_decimated), + NextState("WRITE_PULSE_UPPER"), + ) + ) + + fsm.act("WRITE_PULSE_UPPER", + If(self.tx_fifo.writable, + self.tx_fifo.we.eq(1), + self.tx_fifo.din.eq(rxdata_pulse_read[8:]), + NextState("WRITE_PULSE_LOWER"), + ) + ) + + fsm.act("WRITE_PULSE_LOWER", + If(self.tx_fifo.writable, + self.tx_fifo.we.eq(1), + self.tx_fifo.din.eq(rxdata_pulse_read[:8]), NextState("TERMINATE"), ) ) @@ -291,17 +338,37 @@ class SingleSerDesLoopBack(Module): 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) - # ) - # ] + tx_fsm = FSM(reset_state="SEND_TRAINING") + self.submodules += tx_fsm + + tx_fsm.act("SEND_TRAINING", + self.tx.txdata.eq(0b00100), + If(rx_intra_aligned, + NextState("TX_ZERO"), + ), + ) + + # Intra-ISERDES alignment done, investigate group delay + # TX is first set zero for around 16 cycles. + tx_zero_counter = Signal(5) + + tx_fsm.act("TX_ZERO", + self.tx.txdata.eq(0b00000), + If(tx_zero_counter == 15, + NextState("TX_HIGH"), + ).Else( + NextValue(tx_zero_counter, tx_zero_counter + 1), + ), + ) + + tx_fsm.act("TX_HIGH", + self.tx.txdata.eq(0b11111), + NextState("TX_LOW"), + ) + + tx_fsm.act("TX_LOW", + self.tx.txdata.eq(0b00000), + ) if __name__ == "__main__": diff --git a/sync_serdes.py b/sync_serdes.py index 5c99505..fd87ead 100644 --- a/sync_serdes.py +++ b/sync_serdes.py @@ -444,6 +444,10 @@ class DelayOptimizer(Module): # The optimal delay self.opt_delay_tap = Signal(5) + # OUT + # Keep even/odd indices, decimate the other + self.select_odd = Signal() + # OUT # Optimal delay is calculated self.done = Signal() @@ -553,5 +557,6 @@ class DelayOptimizer(Module): fsm.act("TERMINATE", self.done.eq(1), + self.select_odd.eq(self.expected_pulse[0]), NextState("TERMINATE"), )