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
This commit is contained in:
morgan 2024-06-17 13:19:37 +08:00
parent f158aaf975
commit 8c34921799

142
src/gateware/cxp_upconn.py Normal file
View File

@ -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),
]