forked from M-Labs/artiq-zynq
cxp upconn: refactor fifo into submodule
This commit is contained in:
parent
14a9184fee
commit
98f4d4cea4
|
@ -3,18 +3,16 @@ from migen.genlib.resetsync import AsyncResetSynchronizer
|
||||||
from migen.genlib.coding import PriorityEncoder
|
from migen.genlib.coding import PriorityEncoder
|
||||||
|
|
||||||
from misoc.cores.code_8b10b import SingleEncoder
|
from misoc.cores.code_8b10b import SingleEncoder
|
||||||
from misoc.interconnect.csr import *
|
|
||||||
from misoc.interconnect import stream
|
from misoc.interconnect import stream
|
||||||
|
from misoc.interconnect.csr import *
|
||||||
|
|
||||||
# CXP2.1 section 9.2.5
|
# CXP 2.1 section 9.2.5
|
||||||
IDLE_WORDS = [
|
IDLE_WORDS = [
|
||||||
#[k, data]
|
#[data, k]
|
||||||
[0b10111100, 1], #K28.5
|
[0b10111100, 1], #K28.5
|
||||||
[0b10111100, 1], #K28.5
|
|
||||||
# TODO: fix index error for this crap
|
|
||||||
[0b00111100, 1], #K28.1
|
[0b00111100, 1], #K28.1
|
||||||
[0b00111100, 1], #K28.1
|
[0b00111100, 1], #K28.1
|
||||||
# Cat(0b10111100, 0), #D28.5
|
[0b10111100, 0], #D28.5
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,8 +23,6 @@ class CXP_UpConn(Module, AutoCSR):
|
||||||
self.bitrate2x_enable = CSRStorage()
|
self.bitrate2x_enable = CSRStorage()
|
||||||
self.tx_enable = CSRStorage()
|
self.tx_enable = CSRStorage()
|
||||||
|
|
||||||
self.tx_fifos = []
|
|
||||||
|
|
||||||
# # #
|
# # #
|
||||||
|
|
||||||
pll_locked = Signal()
|
pll_locked = Signal()
|
||||||
|
@ -62,88 +58,59 @@ class CXP_UpConn(Module, AutoCSR):
|
||||||
AsyncResetSynchronizer(self.cd_cxp_upconn, ~pll_locked | self.clk_reset.storage)
|
AsyncResetSynchronizer(self.cd_cxp_upconn, ~pll_locked | self.clk_reset.storage)
|
||||||
]
|
]
|
||||||
|
|
||||||
# self.submodules.phy = UpConnTXPHY(pads)
|
self.submodules.fsm = ClockDomainsRenamer("cxp_upconn")(FSM(reset_state="WAIT_TX_ENABLE"))
|
||||||
|
|
||||||
|
|
||||||
# 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)], 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)
|
|
||||||
|
|
||||||
idle_word_count = Signal(max=len(IDLE_WORDS))
|
|
||||||
|
|
||||||
self.submodules.encoder = ClockDomainsRenamer("cxp_upconn")(SingleEncoder(True))
|
self.submodules.encoder = ClockDomainsRenamer("cxp_upconn")(SingleEncoder(True))
|
||||||
|
self.submodules.tx_fifos = TxFIFOs(nfifos, fifo_depth)
|
||||||
fsm = ClockDomainsRenamer("cxp_upconn")(FSM(reset_state="WAIT_TX_ENABLE"))
|
|
||||||
self.submodules += fsm
|
|
||||||
|
|
||||||
o = Signal()
|
o = Signal()
|
||||||
tx_en = Signal()
|
tx_en = Signal()
|
||||||
tx_bitcount = Signal(max=10)
|
tx_bitcount = Signal(max=10)
|
||||||
tx_reg = Signal(10)
|
tx_reg = Signal(10)
|
||||||
|
idleidx = Signal(max=len(IDLE_WORDS))
|
||||||
|
|
||||||
encoded = Signal()
|
# startup sequence
|
||||||
stb = Signal()
|
self.fsm.act("WAIT_TX_ENABLE",
|
||||||
|
|
||||||
fsm.act("WAIT_TX_ENABLE",
|
|
||||||
If(self.tx_enable.storage,
|
If(self.tx_enable.storage,
|
||||||
NextState("ENCODE_IDLE_WORD")
|
NextState("ENCODE_IDLE_WORD")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
fsm.act("ENCODE_IDLE_WORD",
|
self.fsm.act("ENCODE_IDLE_WORD",
|
||||||
NextValue(self.encoder.d, IDLE_WORDS[0][0]),
|
NextValue(self.encoder.d, IDLE_WORDS[0][0]),
|
||||||
NextValue(self.encoder.k, IDLE_WORDS[0][1]),
|
NextValue(self.encoder.k, IDLE_WORDS[0][1]),
|
||||||
NextValue(self.encoder.disp_in, 0),
|
NextValue(self.encoder.disp_in, 0),
|
||||||
NextValue(idle_word_count, 1),
|
NextValue(idleidx, 1),
|
||||||
NextState("START_TX")
|
NextState("START_TX")
|
||||||
)
|
)
|
||||||
|
|
||||||
fsm.act("START_TX",
|
self.fsm.act("START_TX",
|
||||||
tx_en.eq(1),
|
tx_en.eq(1),
|
||||||
If((~self.tx_enable.storage) & (tx_bitcount == 9),
|
If((~self.tx_enable.storage) & (tx_bitcount == 9),
|
||||||
NextState("WAIT_TX_ENABLE")
|
NextState("WAIT_TX_ENABLE")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
self.sync.cxp_upconn +=[
|
|
||||||
|
# CXP 2.1 section 9.2.4
|
||||||
|
self.sync.cxp_upconn += [
|
||||||
If(tx_en,
|
If(tx_en,
|
||||||
o.eq(tx_reg[0]),
|
o.eq(tx_reg[0]),
|
||||||
tx_reg.eq(Cat(tx_reg[1:], 0)),
|
tx_reg.eq(Cat(tx_reg[1:], 0)),
|
||||||
tx_bitcount.eq(tx_bitcount + 1),
|
tx_bitcount.eq(tx_bitcount + 1),
|
||||||
|
|
||||||
If(tx_bitcount == 8,
|
If(tx_bitcount == 8,
|
||||||
If(~self.pe.n,
|
# TODO: only allow trigger packet to do character interrupt and other priority level to only interrupt word
|
||||||
self.encoder.d.eq(sources_data[self.pe.o][:8]),
|
If(~self.tx_fifos.pe.n,
|
||||||
self.encoder.k.eq(sources_data[self.pe.o][8]),
|
self.encoder.d.eq(self.tx_fifos.source_data[self.tx_fifos.pe.o][:8]),
|
||||||
sources_ack[self.pe.o].eq(1),
|
self.encoder.k.eq(self.tx_fifos.source_data[self.tx_fifos.pe.o][8]),
|
||||||
|
self.tx_fifos.source_ack[self.tx_fifos.pe.o].eq(1),
|
||||||
).Else(
|
).Else(
|
||||||
self.encoder.d.eq(Array(IDLE_WORDS)[idle_word_count][0]),
|
self.encoder.d.eq(Array(IDLE_WORDS)[idleidx][0]),
|
||||||
self.encoder.k.eq(Array(IDLE_WORDS)[idle_word_count][1]),
|
self.encoder.k.eq(Array(IDLE_WORDS)[idleidx][1]),
|
||||||
If(idle_word_count != len(IDLE_WORDS),
|
If(idleidx != len(IDLE_WORDS),
|
||||||
idle_word_count.eq(idle_word_count + 1)
|
idleidx.eq(idleidx + 1)
|
||||||
).Else(
|
).Else(
|
||||||
idle_word_count.eq(0)
|
idleidx.eq(0)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
).Elif(tx_bitcount == 9,
|
).Elif(tx_bitcount == 9,
|
||||||
|
@ -156,9 +123,11 @@ class CXP_UpConn(Module, AutoCSR):
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
# DEBUG: remove pads
|
# DEBUG: remove pads
|
||||||
self.idle_word_index = CSRStatus()
|
self.encoded_data = CSRStatus(10)
|
||||||
self.sync.cxp_upconn +=[
|
self.sync.cxp_upconn +=[
|
||||||
self.idle_word_index.status.eq(idle_word_count)
|
If(tx_bitcount == 9,
|
||||||
|
self.encoded_data.status.eq(self.encoder.output),
|
||||||
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
ninth_bit = Signal()
|
ninth_bit = Signal()
|
||||||
|
@ -169,8 +138,8 @@ class CXP_UpConn(Module, AutoCSR):
|
||||||
self.comb += [
|
self.comb += [
|
||||||
eighth_bit.eq(tx_bitcount == 8),
|
eighth_bit.eq(tx_bitcount == 8),
|
||||||
ninth_bit.eq(tx_bitcount == 9),
|
ninth_bit.eq(tx_bitcount == 9),
|
||||||
idle_3.eq(idle_word_count == 3),
|
idle_3.eq(idleidx == 3),
|
||||||
idle_2.eq(idle_word_count == 2),
|
idle_2.eq(idleidx == 2),
|
||||||
]
|
]
|
||||||
self.specials += [
|
self.specials += [
|
||||||
# debug sma
|
# debug sma
|
||||||
|
@ -180,41 +149,53 @@ class CXP_UpConn(Module, AutoCSR):
|
||||||
# pmod 0-7 pin
|
# pmod 0-7 pin
|
||||||
Instance("OBUF", i_I=o, o_O=pmod[0]),
|
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=self.cd_cxp_upconn.clk, o_O=pmod[1]),
|
||||||
Instance("OBUF", i_I=tx_en, o_O=pmod[2]),
|
Instance("OBUF", i_I=~self.tx_fifos.pe.n, o_O=pmod[2]),
|
||||||
Instance("OBUF", i_I=idle_3, o_O=pmod[3]),
|
Instance("OBUF", i_I=ninth_bit, o_O=pmod[3]),
|
||||||
Instance("OBUF", i_I=idle_2, o_O=pmod[4]),
|
Instance("OBUF", i_I=idle_2, o_O=pmod[4]),
|
||||||
# Instance("OBUF", i_I=eighth_bit, o_O=pmod[3]),
|
Instance("OBUF", i_I=self.tx_fifos.source_ack[0], o_O=pmod[5]),
|
||||||
# Instance("OBUF", i_I=ninth_bit, o_O=pmod[4]),
|
Instance("OBUF", i_I=idle_3, o_O=pmod[6]),
|
||||||
Instance("OBUF", i_I=encoded, o_O=pmod[5]),
|
Instance("OBUF", i_I=tx_en, o_O=pmod[7]),
|
||||||
Instance("OBUF", i_I=~self.pe.n, o_O=pmod[6]),
|
|
||||||
]
|
]
|
||||||
self.symbol0 = CSR(9)
|
self.symbol0 = CSR(9)
|
||||||
self.symbol1 = CSR(9)
|
self.symbol1 = CSR(9)
|
||||||
|
|
||||||
self.sync += [
|
self.sync += [
|
||||||
self.tx_fifos[0].sink.stb.eq(self.symbol0.re),
|
self.tx_fifos.sink_stb[0].eq(self.symbol0.re),
|
||||||
self.tx_fifos[0].sink.data.eq(self.symbol0.r),
|
self.tx_fifos.sink_data[0].eq(self.symbol0.r),
|
||||||
self.tx_fifos[1].sink.stb.eq(self.symbol1.re),
|
self.tx_fifos.sink_stb[1].eq(self.symbol1.re),
|
||||||
self.tx_fifos[1].sink.data.eq(self.symbol1.r),
|
self.tx_fifos.sink_data[1].eq(self.symbol1.r),
|
||||||
# self.fifo_full[i].eq(~fifo.sink.ack),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
class UpConnTXPHY(Module, AutoCSR):
|
class TxFIFOs(Module, AutoCSR):
|
||||||
def __init__(self, pads):
|
def __init__(self, nfifos, fifo_depth):
|
||||||
self.sink = stream.Endpoint([("data", 9)])
|
self.sink_stb = Signal(nfifos)
|
||||||
|
self.sink_ack = Signal(nfifos)
|
||||||
|
self.sink_data = [Signal(9) for _ in range(nfifos)]
|
||||||
|
|
||||||
|
# data & ack will be used dynamically during runtime, cannot use python array
|
||||||
|
self.source_stb = Signal(nfifos)
|
||||||
|
self.source_ack = Array(Signal() for _ in range(nfifos))
|
||||||
|
self.source_data = Array(Signal(9) for _ in range(nfifos))
|
||||||
|
|
||||||
# # #
|
# # #
|
||||||
|
|
||||||
self.submodules.encoder = ClockDomainsRenamer("cxp_upconn")(SingleEncoder(True))
|
for i in range(nfifos):
|
||||||
|
cdr = ClockDomainsRenamer({"write": "sys", "read": "cxp_upconn"})
|
||||||
|
fifo = cdr(stream.AsyncFIFO([("data", 9)], fifo_depth))
|
||||||
|
setattr(self.submodules, "tx_fifo" + str(i), fifo)
|
||||||
self.comb += [
|
self.comb += [
|
||||||
self.encoder.d.eq(self.sink.data[:8]),
|
fifo.sink.stb.eq(self.sink_stb[i]),
|
||||||
self.encoder.k.eq(self.sink.data[8])
|
self.sink_ack[i].eq(fifo.sink.ack),
|
||||||
|
fifo.sink.data.eq(self.sink_data[i]),
|
||||||
|
|
||||||
|
self.source_stb[i].eq(fifo.source.stb),
|
||||||
|
fifo.source.ack.eq(self.source_ack[i]),
|
||||||
|
self.source_data[i].eq(fifo.source.data),
|
||||||
]
|
]
|
||||||
|
# reset ack after asserted
|
||||||
|
self.sync.cxp_upconn += If(self.source_ack[i], self.source_ack[i].eq(0))
|
||||||
|
|
||||||
o = Signal()
|
# For FIFOs transmission priority
|
||||||
tx_en = Signal()
|
self.submodules.pe = PriorityEncoder(nfifos)
|
||||||
tx_bitcount = Signal(max=10)
|
self.comb += self.pe.i.eq(self.source_stb)
|
||||||
tx_reg = Signal(10)
|
|
||||||
|
|
||||||
self.specials += Instance("OBUF", i_I=o, o_O=pads.p_tx)
|
|
||||||
|
|
Loading…
Reference in New Issue