mirror of
https://github.com/enjoy-digital/litex.git
synced 2025-01-04 09:52:26 -05:00
add tx_reset_fsm and rx_reset_fsm
This commit is contained in:
parent
c27f24c4c0
commit
45f7f8aff5
3 changed files with 137 additions and 63 deletions
|
@ -13,16 +13,28 @@ class K7SATAPHY(Module):
|
|||
self.sink = Sink([("d", 32)], True)
|
||||
self.source = Source([("d", 32)], True)
|
||||
|
||||
# GTX
|
||||
gtx = K7SATAPHYGTX(pads, "SATA3")
|
||||
self.comb += [
|
||||
gtx.rxrate.eq(0b000),
|
||||
gtx.txrate.eq(0b000),
|
||||
]
|
||||
clocking = K7SATAPHYCRG(pads, gtx, clk_freq)
|
||||
self.submodules += gtx
|
||||
|
||||
# CRG / CTRL
|
||||
crg = K7SATAPHYCRG(pads, gtx, clk_freq)
|
||||
if host:
|
||||
ctrl = K7SATAPHYHostCtrl(gtx)
|
||||
else:
|
||||
ctrl = K7SATAPHYDeviceCtrl(gtx)
|
||||
self.submodules += crg, ctrl
|
||||
self.comb += ctrl.start.eq(crg.ready)
|
||||
|
||||
# DATAPATH
|
||||
rxalign = K7SATAPHYRXAlign()
|
||||
rxconvert = K7SATAPHYRXConvert()
|
||||
txconvert = K7SATAPHYTXConvert()
|
||||
self.submodules += gtx, clocking, rxalign, rxconvert, txconvert
|
||||
self.submodules += rxalign, rxconvert, txconvert
|
||||
self.comb += [
|
||||
rxalign.rxdata_i.eq(gtx.rxdata),
|
||||
rxalign.rxcharisk_i.eq(gtx.rxcharisk),
|
||||
|
@ -33,13 +45,8 @@ class K7SATAPHY(Module):
|
|||
gtx.txcharisk.eq(txconvert.txcharisk)
|
||||
]
|
||||
|
||||
if host:
|
||||
ctrl = K7SATAPHYHostCtrl(gtx)
|
||||
else:
|
||||
ctrl = K7SATAPHYDeviceCtrl(gtx)
|
||||
self.submodules += ctrl
|
||||
self.comb += [
|
||||
If(ctrl.link_up,
|
||||
If(ctrl.ready,
|
||||
txconvert.sink.stb.eq(self.sink.stb),
|
||||
txconvert.sink.data.eq(self.sink.d),
|
||||
txconvert.sink.charisk.eq(0),
|
||||
|
|
|
@ -27,6 +27,7 @@ class K7SATAPHYReconfig(Module):
|
|||
class K7SATAPHYCRG(Module):
|
||||
def __init__(self, pads, gtx, clk_freq):
|
||||
self.reset = Signal()
|
||||
self.ready = Signal()
|
||||
|
||||
self.clock_domains.cd_sata_tx = ClockDomain()
|
||||
self.clock_domains.cd_sata_rx = ClockDomain()
|
||||
|
@ -79,7 +80,6 @@ class K7SATAPHYCRG(Module):
|
|||
p_CLKOUT1_DIVIDE=8, p_CLKOUT1_PHASE=0.000, o_CLKOUT1=mmcm_clk1_o,
|
||||
),
|
||||
Instance("BUFG", i_I=mmcm_clk0_o, o_O=self.cd_sata_tx.clk),
|
||||
Instance("BUFG", i_I=mmcm_clk1_o, o_O=self.cd_sata.clk),
|
||||
]
|
||||
self.comb += [
|
||||
gtx.txusrclk.eq(self.cd_sata_tx.clk),
|
||||
|
@ -98,7 +98,7 @@ class K7SATAPHYCRG(Module):
|
|||
gtx.rxusrclk2.eq(self.cd_sata_rx.clk)
|
||||
]
|
||||
|
||||
# TX buffer bypass logic
|
||||
# Bypass TX buffer
|
||||
self.comb += [
|
||||
gtx.txphdlyreset.eq(0),
|
||||
gtx.txphalignen.eq(0),
|
||||
|
@ -107,7 +107,7 @@ class K7SATAPHYCRG(Module):
|
|||
gtx.txphinit.eq(0)
|
||||
]
|
||||
|
||||
# RX buffer bypass logic
|
||||
# Bypass RX buffer
|
||||
self.comb += [
|
||||
gtx.rxphdlyreset.eq(0),
|
||||
gtx.rxdlyen.eq(0),
|
||||
|
@ -115,7 +115,6 @@ class K7SATAPHYCRG(Module):
|
|||
gtx.rxphalignen.eq(0),
|
||||
]
|
||||
|
||||
|
||||
# Configuration Reset
|
||||
# After configuration, GTX resets have to stay low for at least 500ns
|
||||
# See AR43482
|
||||
|
@ -126,57 +125,111 @@ class K7SATAPHYCRG(Module):
|
|||
self.sync += If(~reset_en, reset_en_cnt.eq(reset_en_cnt-1))
|
||||
self.comb += reset_en.eq(reset_en_cnt == 0)
|
||||
|
||||
|
||||
# once channel TX is reseted, reset TX buffer
|
||||
txbuffer_reseted = Signal()
|
||||
self.sync += \
|
||||
If(gtx.txresetdone,
|
||||
If(~txbuffer_reseted,
|
||||
gtx.txdlysreset.eq(1),
|
||||
txbuffer_reseted.eq(1)
|
||||
).Else(
|
||||
gtx.txdlysreset.eq(0)
|
||||
)
|
||||
# TX Reset FSM
|
||||
tx_reset_fsm = FSM(reset_state="IDLE")
|
||||
self.submodules += tx_reset_fsm
|
||||
tx_reset_fsm.act("IDLE",
|
||||
gtx.txuserrdy.eq(0),
|
||||
gtx.gttxreset.eq(0),
|
||||
gtx.txdlysreset.eq(0),
|
||||
If(reset_en,
|
||||
NextState("RESET_ALL"),
|
||||
)
|
||||
|
||||
# once channel RX is reseted, reset RX buffer
|
||||
rxbuffer_reseted = Signal()
|
||||
self.sync += \
|
||||
If(gtx.rxresetdone,
|
||||
If(~rxbuffer_reseted,
|
||||
gtx.rxdlysreset.eq(1),
|
||||
rxbuffer_reseted.eq(1)
|
||||
).Else(
|
||||
gtx.rxdlysreset.eq(0)
|
||||
)
|
||||
)
|
||||
tx_reset_fsm.act("RESET_ALL",
|
||||
gtx.txuserrdy.eq(0),
|
||||
gtx.gttxreset.eq(1),
|
||||
gtx.txdlysreset.eq(1),
|
||||
If(gtx.cplllock & mmcm_locked,
|
||||
NextState("RELEASE_GTXRESET")
|
||||
)
|
||||
|
||||
# Reset
|
||||
# initial reset generation
|
||||
rst_cnt = Signal(8)
|
||||
rst_cnt_done = Signal()
|
||||
self.sync += \
|
||||
If(~rst_cnt_done,
|
||||
rst_cnt.eq(rst_cnt+1)
|
||||
)
|
||||
tx_reset_fsm.act("RELEASE_GTXRESET",
|
||||
gtx.txuserrdy.eq(1),
|
||||
gtx.gttxreset.eq(0),
|
||||
gtx.txdlysreset.eq(1),
|
||||
If(self.reset,
|
||||
NextState("RESET_ALL")
|
||||
).Elif(gtx.txresetdone,
|
||||
NextState("RELEASE_DLYRESET")
|
||||
)
|
||||
self.comb += rst_cnt_done.eq(rst_cnt==255)
|
||||
)
|
||||
tx_reset_fsm.act("RELEASE_DLYRESET",
|
||||
gtx.txuserrdy.eq(1),
|
||||
gtx.gttxreset.eq(0),
|
||||
gtx.txdlysreset.eq(0),
|
||||
If(self.reset,
|
||||
NextState("RESET_ALL")
|
||||
).Elif(gtx.txdlysresetdone,
|
||||
NextState("READY")
|
||||
)
|
||||
)
|
||||
tx_reset_fsm.act("READY",
|
||||
gtx.txuserrdy.eq(1),
|
||||
gtx.gttxreset.eq(0),
|
||||
gtx.txdlysreset.eq(0),
|
||||
If(self.reset,
|
||||
NextState("RESET_ALL")
|
||||
)
|
||||
)
|
||||
|
||||
self.comb += [
|
||||
# GTXE2
|
||||
gtx.rxuserrdy.eq(gtx.cplllock),
|
||||
gtx.txuserrdy.eq(gtx.cplllock),
|
||||
# TX
|
||||
gtx.gttxreset.eq(reset_en & (self.reset | ~gtx.cplllock)),
|
||||
# RX
|
||||
gtx.gtrxreset.eq(reset_en & (self.reset | ~gtx.cplllock)),
|
||||
# PLL
|
||||
gtx.cpllreset.eq(self.reset | ~reset_en)
|
||||
]
|
||||
# SATA TX/RX clock domains
|
||||
# RX Reset FSM
|
||||
rx_reset_fsm = FSM(reset_state="IDLE")
|
||||
self.submodules += rx_reset_fsm
|
||||
rx_reset_fsm.act("IDLE",
|
||||
gtx.rxuserrdy.eq(0),
|
||||
gtx.gtrxreset.eq(0),
|
||||
gtx.rxdlysreset.eq(0),
|
||||
If(reset_en,
|
||||
NextState("RESET_ALL"),
|
||||
)
|
||||
)
|
||||
rx_reset_fsm.act("RESET_ALL",
|
||||
gtx.rxuserrdy.eq(0),
|
||||
gtx.gtrxreset.eq(1),
|
||||
gtx.rxdlysreset.eq(1),
|
||||
If(gtx.cplllock & mmcm_locked,
|
||||
NextState("RELEASE_GTXRESET")
|
||||
)
|
||||
)
|
||||
rx_reset_fsm.act("RELEASE_GTXRESET",
|
||||
gtx.rxuserrdy.eq(1),
|
||||
gtx.gtrxreset.eq(0),
|
||||
gtx.rxdlysreset.eq(1),
|
||||
If(self.reset,
|
||||
NextState("RESET_ALL")
|
||||
).Elif(gtx.rxresetdone,
|
||||
NextState("RELEASE_DLYRESET")
|
||||
)
|
||||
)
|
||||
rx_reset_fsm.act("RELEASE_DLYRESET",
|
||||
gtx.rxuserrdy.eq(1),
|
||||
gtx.gtrxreset.eq(0),
|
||||
gtx.rxdlysreset.eq(0),
|
||||
If(self.reset,
|
||||
NextState("RESET_ALL")
|
||||
).Elif(gtx.rxdlysresetdone,
|
||||
NextState("READY")
|
||||
)
|
||||
)
|
||||
rx_reset_fsm.act("READY",
|
||||
gtx.rxuserrdy.eq(1),
|
||||
gtx.gtrxreset.eq(0),
|
||||
gtx.rxdlysreset.eq(0),
|
||||
If(self.reset,
|
||||
NextState("RESET_ALL")
|
||||
)
|
||||
)
|
||||
|
||||
self.comb += self.ready.eq(tx_reset_fsm.ongoing("READY") & rx_reset_fsm.ongoing("READY"))
|
||||
|
||||
# Reset PLL
|
||||
self.comb += gtx.cpllreset.eq(self.reset | ~reset_en)
|
||||
|
||||
# Reset for SATA TX/RX clock domains
|
||||
self.specials += [
|
||||
AsyncResetSynchronizer(self.cd_sata_tx, ~mmcm_locked | ~gtx.txresetdone),
|
||||
AsyncResetSynchronizer(self.cd_sata_rx, ~gtx.cplllock | ~gtx.rxphaligndone),
|
||||
AsyncResetSynchronizer(self.cd_sata, ResetSignal("sata_tx") | ResetSignal("sata_rx")),
|
||||
AsyncResetSynchronizer(self.cd_sata_tx, ~self.ready),
|
||||
AsyncResetSynchronizer(self.cd_sata_rx, ~self.ready),
|
||||
]
|
||||
|
||||
# Dynamic Reconfiguration
|
||||
|
|
|
@ -20,7 +20,8 @@ def us(t, speed="SATA3"):
|
|||
|
||||
class K7SATAPHYHostCtrl(Module):
|
||||
def __init__(self, gtx):
|
||||
self.link_up = Signal()
|
||||
self.start = Signal()
|
||||
self.ready = Signal()
|
||||
self.speed = Signal(3)
|
||||
|
||||
self.txdata = Signal(32)
|
||||
|
@ -40,6 +41,12 @@ class K7SATAPHYHostCtrl(Module):
|
|||
self.submodules += fsm
|
||||
|
||||
fsm.act("RESET",
|
||||
gtx.txelecidle.eq(1),
|
||||
If(self.start,
|
||||
NextState("COMINIT")
|
||||
)
|
||||
)
|
||||
fsm.act("COMINIT",
|
||||
txcominit.eq(1),
|
||||
gtx.txelecidle.eq(1),
|
||||
If(gtx.txcomfinish & ~gtx.rxcominitdet,
|
||||
|
@ -114,7 +121,7 @@ class K7SATAPHYHostCtrl(Module):
|
|||
If(gtx.rxelecidle,
|
||||
NextState("RESET")
|
||||
),
|
||||
self.link_up.eq(1)
|
||||
self.ready.eq(1)
|
||||
)
|
||||
|
||||
txcominit_d = Signal()
|
||||
|
@ -166,7 +173,8 @@ class K7SATAPHYHostCtrl(Module):
|
|||
|
||||
class K7SATAPHYDeviceCtrl(Module):
|
||||
def __init__(self, gtx):
|
||||
self.link_up = Signal()
|
||||
self.start = Signal()
|
||||
self.ready = Signal()
|
||||
self.speed = Signal(3)
|
||||
|
||||
self.txdata = Signal(32)
|
||||
|
@ -185,6 +193,12 @@ class K7SATAPHYDeviceCtrl(Module):
|
|||
self.submodules += fsm
|
||||
|
||||
fsm.act("RESET",
|
||||
gtx.txelecidle.eq(1),
|
||||
If(self.start,
|
||||
NextState("AWAIT_COMINIT")
|
||||
)
|
||||
)
|
||||
fsm.act("AWAIT_COMINIT",
|
||||
gtx.txelecidle.eq(1),
|
||||
If(gtx.rxcominitdet,
|
||||
NextState("COMINIT")
|
||||
|
@ -241,7 +255,7 @@ class K7SATAPHYDeviceCtrl(Module):
|
|||
If(gtx.rxelecidle,
|
||||
NextState("RESET")
|
||||
),
|
||||
self.link_up.eq(1)
|
||||
self.ready.eq(1)
|
||||
)
|
||||
fsm.act("ERROR",
|
||||
gtx.txelecidle.eq(1),
|
||||
|
|
Loading…
Reference in a new issue