1
0
Fork 0

cxp upconn: put encoder with tx_fifos

This commit is contained in:
morgan 2024-06-27 16:50:15 +08:00
parent 98f4d4cea4
commit 4eed5e99f4
1 changed files with 55 additions and 25 deletions

View File

@ -10,9 +10,10 @@ from misoc.interconnect.csr import *
IDLE_WORDS = [ IDLE_WORDS = [
#[data, k] #[data, k]
[0b10111100, 1], #K28.5 [0b10111100, 1], #K28.5
[0b00111100, 1], #K28.1 [0b10111100, 1], #K28.5
[0b00111100, 1], #K28.1 # [0b00111100, 1], #K28.1
[0b10111100, 0], #D28.5 # [0b00111100, 1], #K28.1
# [0b10111100, 0], #D28.5
] ]
@ -66,7 +67,7 @@ class CXP_UpConn(Module, AutoCSR):
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)) wordidx = Signal(max=len(IDLE_WORDS))
# startup sequence # startup sequence
self.fsm.act("WAIT_TX_ENABLE", self.fsm.act("WAIT_TX_ENABLE",
@ -79,7 +80,7 @@ class CXP_UpConn(Module, AutoCSR):
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(idleidx, 1), NextValue(wordidx, 1),
NextState("START_TX") NextState("START_TX")
) )
@ -91,32 +92,44 @@ class CXP_UpConn(Module, AutoCSR):
) )
# 0 lv interrupt at char boundary 10bit
# other lv interrupt at word boundary 40bit
cur_disp = Signal()
# TODO: only allow trigger packet to do character interrupt and other priority level to only interrupt word
# ISSUE: what if 2lv is transmitting 2nd char & 1lv interrupt its?
# CXP 2.1 section 9.2.4 # CXP 2.1 section 9.2.4
self.sync.cxp_upconn += [ self.sync.cxp_upconn += [
self.tx_fifos.disp_in.eq(cur_disp),
self.encoder.disp_in.eq(cur_disp),
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,
# TODO: only allow trigger packet to do character interrupt and other priority level to only interrupt word If(self.tx_fifos.pe.n,
If(~self.tx_fifos.pe.n, self.encoder.d.eq(Array(IDLE_WORDS)[wordidx][0]),
self.encoder.d.eq(self.tx_fifos.source_data[self.tx_fifos.pe.o][:8]), self.encoder.k.eq(Array(IDLE_WORDS)[wordidx][1]),
self.encoder.k.eq(self.tx_fifos.source_data[self.tx_fifos.pe.o][8]), If(wordidx != len(IDLE_WORDS),
self.tx_fifos.source_ack[self.tx_fifos.pe.o].eq(1), wordidx.eq(wordidx + 1),
).Else(
self.encoder.d.eq(Array(IDLE_WORDS)[idleidx][0]),
self.encoder.k.eq(Array(IDLE_WORDS)[idleidx][1]),
If(idleidx != len(IDLE_WORDS),
idleidx.eq(idleidx + 1)
).Else( ).Else(
idleidx.eq(0) wordidx.eq(0),
) ),
) ),
).Elif(tx_bitcount == 9, ).Elif(tx_bitcount == 9,
tx_bitcount.eq(0), tx_bitcount.eq(0),
tx_reg.eq(self.encoder.output), If(self.tx_fifos.pe.n,
self.encoder.disp_in.eq(self.encoder.disp_out), # idle word
tx_reg.eq(self.encoder.output),
cur_disp.eq(self.encoder.disp_out),
).Else(
# from fifos
tx_reg.eq(self.tx_fifos.source_data[self.tx_fifos.pe.o]),
self.tx_fifos.source_ack[self.tx_fifos.pe.o].eq(1),
cur_disp.eq(self.tx_fifos.disp_out[self.tx_fifos.pe.o]),
),
) )
).Else( ).Else(
o.eq(0) o.eq(0)
@ -126,7 +139,13 @@ class CXP_UpConn(Module, AutoCSR):
self.encoded_data = CSRStatus(10) self.encoded_data = CSRStatus(10)
self.sync.cxp_upconn +=[ self.sync.cxp_upconn +=[
If(tx_bitcount == 9, If(tx_bitcount == 9,
self.encoded_data.status.eq(self.encoder.output), If(self.tx_fifos.pe.n,
# idle word
self.encoded_data.status.eq(self.encoder.output),
).Else(
# from fifos
self.encoded_data.status.eq(self.tx_fifos.source_data[self.tx_fifos.pe.o]),
),
) )
] ]
@ -138,8 +157,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(idleidx == 3), idle_3.eq(wordidx == 3),
idle_2.eq(idleidx == 2), idle_2.eq(wordidx == 2),
] ]
self.specials += [ self.specials += [
# debug sma # debug sma
@ -168,6 +187,10 @@ class CXP_UpConn(Module, AutoCSR):
class TxFIFOs(Module, AutoCSR): class TxFIFOs(Module, AutoCSR):
def __init__(self, nfifos, fifo_depth): def __init__(self, nfifos, fifo_depth):
self.disp_in = Signal()
self.disp_out = Array(Signal() for _ in range(nfifos))
self.sink_stb = Signal(nfifos) self.sink_stb = Signal(nfifos)
self.sink_ack = Signal(nfifos) self.sink_ack = Signal(nfifos)
self.sink_data = [Signal(9) for _ in range(nfifos)] self.sink_data = [Signal(9) for _ in range(nfifos)]
@ -175,14 +198,16 @@ class TxFIFOs(Module, AutoCSR):
# data & ack will be used dynamically during runtime, cannot use python array # data & ack will be used dynamically during runtime, cannot use python array
self.source_stb = Signal(nfifos) self.source_stb = Signal(nfifos)
self.source_ack = Array(Signal() for _ in range(nfifos)) self.source_ack = Array(Signal() for _ in range(nfifos))
self.source_data = Array(Signal(9) for _ in range(nfifos)) self.source_data = Array(Signal(10) for _ in range(nfifos))
# # # # # #
for i in range(nfifos): for i in range(nfifos):
cdr = ClockDomainsRenamer({"write": "sys", "read": "cxp_upconn"}) cdr = ClockDomainsRenamer({"write": "sys", "read": "cxp_upconn"})
fifo = cdr(stream.AsyncFIFO([("data", 9)], fifo_depth)) fifo = cdr(stream.AsyncFIFO([("data", 9)], fifo_depth))
encoder = ClockDomainsRenamer("cxp_upconn")(SingleEncoder(True))
setattr(self.submodules, "tx_fifo" + str(i), fifo) setattr(self.submodules, "tx_fifo" + str(i), fifo)
setattr(self.submodules, "tx_encoder" + str(i), encoder)
self.comb += [ self.comb += [
fifo.sink.stb.eq(self.sink_stb[i]), fifo.sink.stb.eq(self.sink_stb[i]),
self.sink_ack[i].eq(fifo.sink.ack), self.sink_ack[i].eq(fifo.sink.ack),
@ -190,7 +215,12 @@ class TxFIFOs(Module, AutoCSR):
self.source_stb[i].eq(fifo.source.stb), self.source_stb[i].eq(fifo.source.stb),
fifo.source.ack.eq(self.source_ack[i]), fifo.source.ack.eq(self.source_ack[i]),
self.source_data[i].eq(fifo.source.data),
encoder.d.eq(fifo.source.data[:8]),
encoder.k.eq(fifo.source.data[8]),
encoder.disp_in.eq(self.disp_in),
self.disp_out[i].eq(encoder.disp_out),
self.source_data[i].eq(encoder.output),
] ]
# reset ack after asserted # reset ack after asserted
self.sync.cxp_upconn += If(self.source_ack[i], self.source_ack[i].eq(0)) self.sync.cxp_upconn += If(self.source_ack[i], self.source_ack[i].eq(0))