forked from M-Labs/artiq-zynq
cxp upconn: add priority packet
This commit is contained in:
parent
cdc7294e99
commit
ae4bfc40e5
|
@ -1,12 +1,27 @@
|
|||
from migen import *
|
||||
from migen.genlib.resetsync import AsyncResetSynchronizer
|
||||
from migen.genlib.coding import PriorityEncoder
|
||||
|
||||
from misoc.cores.code_8b10b import SingleEncoder
|
||||
from misoc.interconnect.csr import *
|
||||
from misoc.interconnect import stream
|
||||
|
||||
def K(x, y):
|
||||
return 1 << 8 | (y << 5) | x
|
||||
|
||||
def D(x, y):
|
||||
return (y << 5) | x
|
||||
|
||||
IDLE = [
|
||||
K(28, 5),
|
||||
K(28, 1),
|
||||
K(28, 1),
|
||||
D(21, 5),
|
||||
]
|
||||
|
||||
|
||||
class CXP_UpConn(Module, AutoCSR):
|
||||
def __init__(self, pads, sys_clk_freq, tx_fifo_depth=32):
|
||||
def __init__(self, pads, sys_clk_freq, pmod, nfifos=3, fifo_depth=32):
|
||||
self.clock_domains.cd_cxp_upconn = ClockDomain()
|
||||
self.clk_reset = CSRStorage(reset=1)
|
||||
self.bitrate2x_enable = CSRStorage()
|
||||
|
@ -48,37 +63,130 @@ class CXP_UpConn(Module, AutoCSR):
|
|||
AsyncResetSynchronizer(self.cd_cxp_upconn, ~pll_locked | self.clk_reset.storage)
|
||||
]
|
||||
|
||||
self.submodules.phy = UpConnTXPHY(pads)
|
||||
# self.submodules.phy = UpConnTXPHY(pads)
|
||||
|
||||
nfifos = 2
|
||||
|
||||
# FIFOs with transmission priority
|
||||
# 0: Trigger packet
|
||||
# 1: IO acknowledgment for trigger packet
|
||||
# 2: All other packets
|
||||
sinks_full = Signal(nfifos)
|
||||
sources_stb = Signal(nfifos)
|
||||
sources_ack = Array(Signal() for _ in range(nfifos))
|
||||
sources_data = Array(Signal(9) for _ in range(nfifos))
|
||||
for i in range(nfifos):
|
||||
cdr = ClockDomainsRenamer({"write": "sys", "read": "cxp_upconn"})
|
||||
fifo = cdr(stream.AsyncFIFO([("data", 9)], tx_fifo_depth))
|
||||
fifo = cdr(stream.AsyncFIFO([("data", 9)], fifo_depth))
|
||||
self.tx_fifos.append(fifo)
|
||||
setattr(self.submodules, "tx_fifo" + str(i), fifo)
|
||||
self.comb += [
|
||||
sinks_full[i].eq(fifo.sink.ack),
|
||||
fifo.source.ack.eq(sources_ack[i]),
|
||||
sources_stb[i].eq(fifo.source.stb),
|
||||
sources_data[i].eq(fifo.source.data),
|
||||
]
|
||||
# setup pulse ack
|
||||
self.sync.cxp_upconn += sources_ack[i].eq(0)
|
||||
|
||||
self.submodules.pe = PriorityEncoder(nfifos)
|
||||
self.comb += self.pe.i.eq(sources_stb)
|
||||
|
||||
p = Signal(max=len(IDLE))
|
||||
|
||||
# self.sync.cxp_upconn +=[
|
||||
# # TODO: use reduce(or, tx_fifos_stbs)
|
||||
# # self.phy.sink.stb.eq(self.tx_fifos[0].source.stb | self.tx_fifos[1].source.stb | self.tx_fifos[2].source.stb),
|
||||
# # TODO: add tx_enable like gtx?
|
||||
# # self.phy.sink.stb.eq(1),
|
||||
# self.phy.sink.stb.eq(0),
|
||||
# If(~self.phy.sink.ack, #PHY sink not full i.e. ready to receive data
|
||||
# If(~self.pe.n,
|
||||
# self.phy.sink.data.eq(tx_fifos_datas[self.pe.o]),
|
||||
# tx_fifos_ack[self.pe.o].eq(1),
|
||||
# self.phy.sink.stb.eq(1),
|
||||
# )
|
||||
# # ).Else(
|
||||
# # self.phy.sink.data.eq(Array(IDLE)[p]),
|
||||
# # If(p != len(IDLE),
|
||||
# # p.eq(p+1)
|
||||
# # ).Else(
|
||||
# # p.eq(0),
|
||||
# # )
|
||||
# # ),
|
||||
# ),
|
||||
# ]
|
||||
|
||||
self.submodules.encoder = ClockDomainsRenamer("cxp_upconn")(SingleEncoder(True))
|
||||
|
||||
o = Signal()
|
||||
tx_busy = Signal()
|
||||
tx_bitcount = Signal(max=10)
|
||||
tx_reg = Signal(10)
|
||||
|
||||
encoded = Signal()
|
||||
stb = Signal()
|
||||
|
||||
self.sync.cxp_upconn +=[
|
||||
self.phy.sink.stb.eq(self.tx_fifos[0].source.stb | self.tx_fifos[1].source.stb),
|
||||
self.tx_fifos[0].source.ack.eq(0),
|
||||
self.tx_fifos[1].source.ack.eq(0),
|
||||
If(self.phy.sink.ack,
|
||||
If(self.tx_fifos[0].source.stb,
|
||||
self.phy.sink.data.eq(self.tx_fifos[0].source.data),
|
||||
self.tx_fifos[0].source.ack.eq(1),
|
||||
).Elif(self.tx_fifos[1].source.stb,
|
||||
self.phy.sink.data.eq(self.tx_fifos[1].source.data),
|
||||
self.tx_fifos[1].source.ack.eq(1),
|
||||
),
|
||||
),
|
||||
]
|
||||
encoded.eq(0),
|
||||
If(~tx_busy & ~encoded & ~self.pe.n,
|
||||
self.encoder.d.eq(sources_data[self.pe.o][:8]),
|
||||
self.encoder.k.eq(sources_data[self.pe.o][8]),
|
||||
sources_ack[self.pe.o].eq(1),
|
||||
encoded.eq(1),
|
||||
|
||||
).Elif(~tx_busy & encoded,
|
||||
tx_bitcount.eq(0),
|
||||
tx_reg.eq(self.encoder.output),
|
||||
self.encoder.disp_in.eq(self.encoder.disp_out),
|
||||
tx_busy.eq(1),
|
||||
|
||||
).Elif(tx_busy,
|
||||
o.eq(tx_reg[0]),
|
||||
tx_reg.eq(Cat(tx_reg[1:], 0)),
|
||||
tx_bitcount.eq(tx_bitcount + 1),
|
||||
|
||||
If((tx_bitcount == 8) & ~self.pe.n,
|
||||
self.encoder.d.eq(sources_data[self.pe.o][:8]),
|
||||
self.encoder.k.eq(sources_data[self.pe.o][8]),
|
||||
sources_ack[self.pe.o].eq(1),
|
||||
encoded.eq(1),
|
||||
|
||||
).Elif(tx_bitcount == 9,
|
||||
If(encoded,
|
||||
tx_bitcount.eq(0),
|
||||
tx_reg.eq(self.encoder.output),
|
||||
self.encoder.disp_in.eq(self.encoder.disp_out),
|
||||
|
||||
).Else(
|
||||
tx_busy.eq(0),
|
||||
o.eq(0),
|
||||
)
|
||||
|
||||
)
|
||||
|
||||
)
|
||||
]
|
||||
# DEBUG: remove pads
|
||||
self.specials += Instance("OBUF", i_I=self.cd_cxp_upconn.clk, o_O=pads.n_rx)
|
||||
ninth_bit = Signal()
|
||||
eighth_bit = Signal()
|
||||
self.comb += [
|
||||
eighth_bit.eq(tx_bitcount == 8),
|
||||
ninth_bit.eq(tx_bitcount == 9),
|
||||
]
|
||||
self.specials += [
|
||||
# debug sma
|
||||
Instance("OBUF", i_I=o, o_O=pads.p_tx),
|
||||
Instance("OBUF", i_I=self.cd_cxp_upconn.clk, o_O=pads.n_rx),
|
||||
|
||||
# pmod 0-7 pin
|
||||
Instance("OBUF", i_I=o, o_O=pmod[0]),
|
||||
Instance("OBUF", i_I=self.cd_cxp_upconn.clk, o_O=pmod[1]),
|
||||
Instance("OBUF", i_I=tx_busy, o_O=pmod[2]),
|
||||
Instance("OBUF", i_I=eighth_bit, o_O=pmod[3]),
|
||||
Instance("OBUF", i_I=ninth_bit, o_O=pmod[4]),
|
||||
Instance("OBUF", i_I=encoded, o_O=pmod[5]),
|
||||
Instance("OBUF", i_I=~self.pe.n, o_O=pmod[6]),
|
||||
]
|
||||
self.symbol0 = CSR(9)
|
||||
self.symbol1 = CSR(9)
|
||||
|
||||
|
@ -110,21 +218,50 @@ class UpConnTXPHY(Module, AutoCSR):
|
|||
|
||||
self.specials += Instance("OBUF", i_I=o, o_O=pads.p_tx)
|
||||
self.sync.cxp_upconn +=[
|
||||
self.sink.ack.eq(0),
|
||||
If(tx_busy,
|
||||
o.eq(tx_reg[0]),
|
||||
tx_reg.eq(Cat(tx_reg[1:], 0))
|
||||
),
|
||||
If(tx_bitcount != 9,
|
||||
tx_bitcount.eq(tx_bitcount + 1),
|
||||
).Elif(self.sink.stb,
|
||||
tx_busy.eq(1),
|
||||
If(~tx_busy & ~self.sink.stb,
|
||||
self.sink.ack.eq(0),
|
||||
).Elif(~tx_busy & self.sink.stb,
|
||||
self.sink.ack.eq(1),
|
||||
tx_bitcount.eq(0),
|
||||
tx_reg.eq(self.encoder.output),
|
||||
self.encoder.disp_in.eq(self.encoder.disp_out),
|
||||
self.sink.ack.eq(1),
|
||||
).Else(
|
||||
tx_busy.eq(0),
|
||||
o.eq(0)
|
||||
tx_busy.eq(1),
|
||||
).Elif(tx_busy,
|
||||
# outputing data
|
||||
o.eq(tx_reg[0]),
|
||||
tx_reg.eq(Cat(tx_reg[1:], 0)),
|
||||
tx_bitcount.eq(tx_bitcount + 1),
|
||||
If(tx_bitcount == 7,
|
||||
self.sink.ack.eq(0), # ready to receive data
|
||||
).Elif(tx_bitcount == 9,
|
||||
If(self.sink.stb,
|
||||
# got stb signal i.e. is full
|
||||
self.sink.ack.eq(1),
|
||||
tx_bitcount.eq(0),
|
||||
tx_reg.eq(self.encoder.output),
|
||||
self.encoder.disp_in.eq(self.encoder.disp_out),
|
||||
).Else(
|
||||
tx_busy.eq(0),
|
||||
o.eq(0),
|
||||
)
|
||||
|
||||
)
|
||||
|
||||
)
|
||||
|
||||
|
||||
|
||||
# If(tx_bitcount != 9,
|
||||
# tx_bitcount.eq(tx_bitcount + 1),
|
||||
# ).Elif(self.sink.stb,
|
||||
# tx_busy.eq(1),
|
||||
# tx_bitcount.eq(0),
|
||||
# tx_reg.eq(self.encoder.output),
|
||||
# self.encoder.disp_in.eq(self.encoder.disp_out),
|
||||
# self.sink.ack.eq(1),
|
||||
# ).Else(
|
||||
# self.sink.ack.eq(1), # sink is empty
|
||||
# tx_busy.eq(0),
|
||||
# o.eq(0)
|
||||
# )
|
||||
]
|
||||
|
|
Loading…
Reference in New Issue