forked from M-Labs/artiq-zynq
cxp upcxp: add tx_enable & startup sequence
This commit is contained in:
parent
ae4bfc40e5
commit
14a9184fee
|
@ -6,17 +6,15 @@ from misoc.cores.code_8b10b import SingleEncoder
|
||||||
from misoc.interconnect.csr import *
|
from misoc.interconnect.csr import *
|
||||||
from misoc.interconnect import stream
|
from misoc.interconnect import stream
|
||||||
|
|
||||||
def K(x, y):
|
# CXP2.1 section 9.2.5
|
||||||
return 1 << 8 | (y << 5) | x
|
IDLE_WORDS = [
|
||||||
|
#[k, data]
|
||||||
def D(x, y):
|
[0b10111100, 1], #K28.5
|
||||||
return (y << 5) | x
|
[0b10111100, 1], #K28.5
|
||||||
|
# TODO: fix index error for this crap
|
||||||
IDLE = [
|
[0b00111100, 1], #K28.1
|
||||||
K(28, 5),
|
[0b00111100, 1], #K28.1
|
||||||
K(28, 1),
|
# Cat(0b10111100, 0), #D28.5
|
||||||
K(28, 1),
|
|
||||||
D(21, 5),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,6 +23,7 @@ class CXP_UpConn(Module, AutoCSR):
|
||||||
self.clock_domains.cd_cxp_upconn = ClockDomain()
|
self.clock_domains.cd_cxp_upconn = ClockDomain()
|
||||||
self.clk_reset = CSRStorage(reset=1)
|
self.clk_reset = CSRStorage(reset=1)
|
||||||
self.bitrate2x_enable = CSRStorage()
|
self.bitrate2x_enable = CSRStorage()
|
||||||
|
self.tx_enable = CSRStorage()
|
||||||
|
|
||||||
self.tx_fifos = []
|
self.tx_fifos = []
|
||||||
|
|
||||||
|
@ -91,87 +90,87 @@ class CXP_UpConn(Module, AutoCSR):
|
||||||
self.submodules.pe = PriorityEncoder(nfifos)
|
self.submodules.pe = PriorityEncoder(nfifos)
|
||||||
self.comb += self.pe.i.eq(sources_stb)
|
self.comb += self.pe.i.eq(sources_stb)
|
||||||
|
|
||||||
p = Signal(max=len(IDLE))
|
idle_word_count = Signal(max=len(IDLE_WORDS))
|
||||||
|
|
||||||
# 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))
|
self.submodules.encoder = ClockDomainsRenamer("cxp_upconn")(SingleEncoder(True))
|
||||||
|
|
||||||
|
fsm = ClockDomainsRenamer("cxp_upconn")(FSM(reset_state="WAIT_TX_ENABLE"))
|
||||||
|
self.submodules += fsm
|
||||||
|
|
||||||
o = Signal()
|
o = Signal()
|
||||||
tx_busy = Signal()
|
tx_en = Signal()
|
||||||
tx_bitcount = Signal(max=10)
|
tx_bitcount = Signal(max=10)
|
||||||
tx_reg = Signal(10)
|
tx_reg = Signal(10)
|
||||||
|
|
||||||
encoded = Signal()
|
encoded = Signal()
|
||||||
stb = Signal()
|
stb = Signal()
|
||||||
|
|
||||||
|
fsm.act("WAIT_TX_ENABLE",
|
||||||
|
If(self.tx_enable.storage,
|
||||||
|
NextState("ENCODE_IDLE_WORD")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
fsm.act("ENCODE_IDLE_WORD",
|
||||||
|
NextValue(self.encoder.d, IDLE_WORDS[0][0]),
|
||||||
|
NextValue(self.encoder.k, IDLE_WORDS[0][1]),
|
||||||
|
NextValue(self.encoder.disp_in, 0),
|
||||||
|
NextValue(idle_word_count, 1),
|
||||||
|
NextState("START_TX")
|
||||||
|
)
|
||||||
|
|
||||||
|
fsm.act("START_TX",
|
||||||
|
tx_en.eq(1),
|
||||||
|
If((~self.tx_enable.storage) & (tx_bitcount == 9),
|
||||||
|
NextState("WAIT_TX_ENABLE")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
self.sync.cxp_upconn +=[
|
self.sync.cxp_upconn +=[
|
||||||
encoded.eq(0),
|
If(tx_en,
|
||||||
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]),
|
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) & ~self.pe.n,
|
If(tx_bitcount == 8,
|
||||||
|
If(~self.pe.n,
|
||||||
self.encoder.d.eq(sources_data[self.pe.o][:8]),
|
self.encoder.d.eq(sources_data[self.pe.o][:8]),
|
||||||
self.encoder.k.eq(sources_data[self.pe.o][8]),
|
self.encoder.k.eq(sources_data[self.pe.o][8]),
|
||||||
sources_ack[self.pe.o].eq(1),
|
sources_ack[self.pe.o].eq(1),
|
||||||
encoded.eq(1),
|
).Else(
|
||||||
|
self.encoder.d.eq(Array(IDLE_WORDS)[idle_word_count][0]),
|
||||||
|
self.encoder.k.eq(Array(IDLE_WORDS)[idle_word_count][1]),
|
||||||
|
If(idle_word_count != len(IDLE_WORDS),
|
||||||
|
idle_word_count.eq(idle_word_count + 1)
|
||||||
|
).Else(
|
||||||
|
idle_word_count.eq(0)
|
||||||
|
)
|
||||||
|
)
|
||||||
).Elif(tx_bitcount == 9,
|
).Elif(tx_bitcount == 9,
|
||||||
If(encoded,
|
|
||||||
tx_bitcount.eq(0),
|
tx_bitcount.eq(0),
|
||||||
tx_reg.eq(self.encoder.output),
|
tx_reg.eq(self.encoder.output),
|
||||||
self.encoder.disp_in.eq(self.encoder.disp_out),
|
self.encoder.disp_in.eq(self.encoder.disp_out),
|
||||||
|
)
|
||||||
).Else(
|
).Else(
|
||||||
tx_busy.eq(0),
|
o.eq(0)
|
||||||
o.eq(0),
|
|
||||||
)
|
|
||||||
|
|
||||||
)
|
|
||||||
|
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
# DEBUG: remove pads
|
# DEBUG: remove pads
|
||||||
|
self.idle_word_index = CSRStatus()
|
||||||
|
self.sync.cxp_upconn +=[
|
||||||
|
self.idle_word_index.status.eq(idle_word_count)
|
||||||
|
]
|
||||||
|
|
||||||
ninth_bit = Signal()
|
ninth_bit = Signal()
|
||||||
eighth_bit = Signal()
|
eighth_bit = Signal()
|
||||||
|
|
||||||
|
idle_3 = Signal()
|
||||||
|
idle_2 = Signal()
|
||||||
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_2.eq(idle_word_count == 2),
|
||||||
]
|
]
|
||||||
self.specials += [
|
self.specials += [
|
||||||
# debug sma
|
# debug sma
|
||||||
|
@ -181,9 +180,11 @@ 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_busy, o_O=pmod[2]),
|
Instance("OBUF", i_I=tx_en, o_O=pmod[2]),
|
||||||
Instance("OBUF", i_I=eighth_bit, o_O=pmod[3]),
|
Instance("OBUF", i_I=idle_3, o_O=pmod[3]),
|
||||||
Instance("OBUF", i_I=ninth_bit, 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=ninth_bit, o_O=pmod[4]),
|
||||||
Instance("OBUF", i_I=encoded, o_O=pmod[5]),
|
Instance("OBUF", i_I=encoded, o_O=pmod[5]),
|
||||||
Instance("OBUF", i_I=~self.pe.n, o_O=pmod[6]),
|
Instance("OBUF", i_I=~self.pe.n, o_O=pmod[6]),
|
||||||
]
|
]
|
||||||
|
@ -212,56 +213,8 @@ class UpConnTXPHY(Module, AutoCSR):
|
||||||
]
|
]
|
||||||
|
|
||||||
o = Signal()
|
o = Signal()
|
||||||
tx_busy = Signal()
|
tx_en = Signal()
|
||||||
tx_bitcount = Signal(max=10)
|
tx_bitcount = Signal(max=10)
|
||||||
tx_reg = Signal(10)
|
tx_reg = Signal(10)
|
||||||
|
|
||||||
self.specials += Instance("OBUF", i_I=o, o_O=pads.p_tx)
|
self.specials += Instance("OBUF", i_I=o, o_O=pads.p_tx)
|
||||||
self.sync.cxp_upconn +=[
|
|
||||||
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),
|
|
||||||
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