From 8c349217994c2d2f188fe32ed014d26b497c8bf3 Mon Sep 17 00:00:00 2001 From: morgan Date: Mon, 17 Jun 2024 13:19:37 +0800 Subject: [PATCH] cxp upconn gw: add low speed serial PHY testing: add debug fifo output b4 encoder cxp upconn: add low speed serial cxp upconn: add reset, tx_busy, tx_enable cxp upconn: add clockgen module for 20.83Mbps & 41.66Mbps using counters cxp upconn: add oserdes using CEInserter --- src/gateware/cxp_upconn.py | 142 +++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 src/gateware/cxp_upconn.py diff --git a/src/gateware/cxp_upconn.py b/src/gateware/cxp_upconn.py new file mode 100644 index 0000000..dd7844c --- /dev/null +++ b/src/gateware/cxp_upconn.py @@ -0,0 +1,142 @@ +from math import ceil + +from migen import * + +from misoc.cores.code_8b10b import SingleEncoder +from misoc.interconnect import stream +from misoc.interconnect.csr import * + +from cxp_pipeline import char_layout + +@ResetInserter() +class ClockGen(Module): + def __init__(self, sys_clk_freq): + self.clk = Signal() + self.clk_10x = Signal() # 20.83MHz 48ns or 41.66MHz 24ns + + self.freq2x_enable = Signal() + # # # + + period = 1e9/sys_clk_freq + max_count = ceil(48/period) + counter = Signal(max=max_count, reset=max_count-1) + + clk_div = Signal(max=10, reset=9) + + self.sync += [ + self.clk.eq(0), + self.clk_10x.eq(0), + + If(counter == 0, + self.clk_10x.eq(1), + If(self.freq2x_enable, + counter.eq(int(max_count/2)-1), + ).Else( + counter.eq(counter.reset), + ), + ).Else( + counter.eq(counter-1), + ), + + If(counter == 0, + If(clk_div == 0, + self.clk.eq(1), + clk_div.eq(clk_div.reset), + ).Else( + clk_div.eq(clk_div-1), + ) + ) + + ] + +@ResetInserter() +@CEInserter() +class SERDES_10bits(Module): + def __init__(self, pad): + self.oe = Signal() + self.d = Signal(10) + + # # # + + tx_bitcount = Signal(max=10) + tx_reg = Signal(10) + + self.sync += [ + If(self.oe, + # send LSB first + pad.eq(tx_reg[0]), + tx_reg.eq(Cat(tx_reg[1:], 0)), + tx_bitcount.eq(tx_bitcount + 1), + + If(tx_bitcount == 9, + tx_bitcount.eq(0), + tx_reg.eq(self.d), + ), + ).Else( + pad.eq(0), + tx_bitcount.eq(0), + ) + ] + +class Transmitter(Module, AutoCSR): + def __init__(self, pad, sys_clk_freq): + self.bitrate2x_enable = Signal() + self.clk_reset = Signal() + self.enable = Signal() + + # # # + + self.sink = stream.Endpoint(char_layout) + + self.submodules.cg = cg = ClockGen(sys_clk_freq) + self.submodules.encoder = encoder = SingleEncoder(True) + + oe = Signal() + self.sync += [ + If(self.enable, + self.sink.ack.eq(0), + If(cg.clk, + oe.eq(1), + encoder.disp_in.eq(encoder.disp_out), + self.sink.ack.eq(1), + encoder.d.eq(self.sink.data), + encoder.k.eq(self.sink.k), + ) + ).Else( + # discard packets until tx is enabled + self.sink.ack.eq(1), + oe.eq(0), + ) + ] + + self.submodules.serdes = serdes = SERDES_10bits(pad) + + self.comb += [ + cg.reset.eq(self.clk_reset), + cg.freq2x_enable.eq(self.bitrate2x_enable), + + serdes.reset.eq(self.clk_reset), + serdes.ce.eq(cg.clk_10x), + serdes.d.eq(encoder.output), + serdes.oe.eq(oe), + ] + +class CXP_TXPHYs(Module, AutoCSR): + def __init__(self, pads, sys_clk_freq): + self.clk_reset = CSR() + self.bitrate2x_enable = CSRStorage() + self.enable = CSRStorage() + + # # # + + + self.phys = [] + for i, pad in enumerate(pads): + tx = Transmitter(pad, sys_clk_freq) + self.phys.append(tx) + setattr(self.submodules, "tx"+str(i), tx) + self.sync += [ + tx.clk_reset.eq(self.clk_reset.re), + tx.bitrate2x_enable.eq(self.bitrate2x_enable.storage), + tx.enable.eq(self.enable.storage), + ]