class _CRG(Module):
def __init__(self, platform):
self.clock_domains.cd_sys = ClockDomain()
- self.reset = Signal()
clk200 = platform.request("clk200")
clk200_se = Signal()
p_CLKOUT4_DIVIDE=2, p_CLKOUT4_PHASE=0.0, #o_CLKOUT4=
),
Instance("BUFG", i_I=pll_sys, o_O=self.cd_sys.clk),
- AsyncResetSynchronizer(self.cd_sys, ~pll_locked | platform.request("cpu_reset") | self.reset),
+ AsyncResetSynchronizer(self.cd_sys, ~pll_locked | platform.request("cpu_reset")),
]
# SATA PHY/Core/Frontend
self.submodules.sata_phy = LiteSATAPHY(platform.device, platform.request("sata"), "sata_gen2", clk_freq)
- self.comb += self.crg.reset.eq(self.sata_phy.ctrl.need_reset) # XXX FIXME
self.submodules.sata = LiteSATA(self.sata_phy, with_bist=True, with_bist_csr=True)
# Status Leds
print("sector={:d}({:d}MB) wr_speed={:4.2f}MB/s rd_speed={:4.2f}MB/s errors={:d} retry={:d}".format(
sector,
- run_sectors*logical_sector_size/MB,
+ int(run_sectors*logical_sector_size/MB),
write_speed/MB,
read_speed/MB,
write_errors + read_errors,
def __init__(self, device, pads, revision, clk_freq):
self.pads = pads
self.revision = revision
+
# Transceiver / Clocks
if device[:3] == "xc7": # Kintex 7
from misoclib.mem.litesata.phy.k7.trx import K7LiteSATAPHYTRX
self.submodules.trx = K7LiteSATAPHYTRX(pads, revision)
self.submodules.crg = K7LiteSATAPHYCRG(pads, self.trx, revision, clk_freq)
else:
- msg = "Device" + device + "not (yet) supported."
- raise NotImplementedError(msg)
+ raise NotImplementedError
# Control
self.submodules.ctrl = LiteSATAPHYCtrl(self.trx, self.crg, clk_freq)
from misoclib.mem.litesata.common import *
-def us(t, clk_freq):
- clk_period_us = 1000000/clk_freq
- return math.ceil(t/clk_period_us)
-
-
class LiteSATAPHYCtrl(Module):
def __init__(self, trx, crg, clk_freq):
+ self.clk_freq = clk_freq
self.ready = Signal()
- self.need_reset = Signal()
self.sink = sink = Sink(phy_description(32))
self.source = source = Source(phy_description(32))
sink.ack.eq(1)
]
- retry_timeout = Timeout(us(10000, clk_freq))
- align_timeout = Timeout(us(873, clk_freq))
+ retry_timeout = Timeout(self.us(10000))
+ align_timeout = Timeout(self.us(873))
self.submodules += align_timeout, retry_timeout
align_detect = Signal()
non_align_cnt = Signal(4)
+ non_align_counter = Counter(4)
+ self.submodules += non_align_counter
- self.fsm = fsm = FSM(reset_state="RESET")
+ self.fsm = fsm = InsertReset(FSM(reset_state="RESET"))
self.submodules += fsm
+ self.comb += fsm.reset.eq(retry_timeout.reached | align_timeout.reached)
fsm.act("RESET",
trx.tx_idle.eq(1),
retry_timeout.reset.eq(1),
align_timeout.reset.eq(1),
+ non_align_counter.reset.eq(1),
If(crg.ready,
NextState("COMINIT")
- ),
+ )
)
fsm.act("COMINIT",
trx.tx_idle.eq(1),
trx.tx_cominit_stb.eq(1),
If(trx.tx_cominit_ack & ~trx.rx_cominit_stb,
NextState("AWAIT_COMINIT")
- ),
+ )
)
fsm.act("AWAIT_COMINIT",
trx.tx_idle.eq(1),
retry_timeout.ce.eq(1),
If(trx.rx_cominit_stb,
NextState("AWAIT_NO_COMINIT")
- ).Else(
- If(retry_timeout.reached,
- NextState("RESET")
- )
- ),
+ )
)
fsm.act("AWAIT_NO_COMINIT",
trx.tx_idle.eq(1),
retry_timeout.reset.eq(1),
If(~trx.rx_cominit_stb,
NextState("CALIBRATE")
- ),
+ )
)
fsm.act("CALIBRATE",
trx.tx_idle.eq(1),
trx.tx_comwake_stb.eq(1),
If(trx.tx_comwake_ack,
NextState("AWAIT_COMWAKE")
- ),
+ )
)
fsm.act("AWAIT_COMWAKE",
trx.tx_idle.eq(1),
retry_timeout.ce.eq(1),
If(trx.rx_comwake_stb,
NextState("AWAIT_NO_COMWAKE")
- ).Else(
- If(retry_timeout.reached,
- NextState("RESET")
- )
- ),
+ )
)
fsm.act("AWAIT_NO_COMWAKE",
trx.tx_idle.eq(1),
If(~trx.rx_comwake_stb,
NextState("AWAIT_NO_RX_IDLE")
- ),
+ )
)
fsm.act("AWAIT_NO_RX_IDLE",
trx.tx_idle.eq(0),
source.data.eq(0x4A4A4A4A), # D10.2
source.charisk.eq(0b0000),
+ align_timeout.ce.eq(1),
If(~trx.rx_idle,
NextState("AWAIT_ALIGN"),
- crg.reset.eq(1),
- trx.pmarxreset.eq(1)
- ),
+ crg.tx_reset.eq(1),
+ crg.rx_reset.eq(1)
+ )
)
fsm.act("AWAIT_ALIGN",
trx.tx_idle.eq(0),
align_timeout.ce.eq(1),
If(align_detect & ~trx.rx_idle,
NextState("SEND_ALIGN")
- ).Elif(align_timeout.reached,
- NextState("RESET")
- ),
+ )
)
fsm.act("SEND_ALIGN",
trx.tx_idle.eq(0),
trx.rx_align.eq(1),
+ align_timeout.ce.eq(1),
source.data.eq(primitives["ALIGN"]),
source.charisk.eq(0b0001),
- If(non_align_cnt == 3,
- NextState("READY")
+ If(sink.stb,
+ If(sink.data[0:8] == 0x7C,
+ non_align_counter.ce.eq(1)
+ ).Else(
+ non_align_counter.reset.eq(1)
+ )
),
+ If(non_align_counter.value == 3,
+ NextState("READY")
+ )
)
fsm.act("READY",
trx.tx_idle.eq(0),
trx.rx_align.eq(1),
source.data.eq(primitives["SYNC"]),
source.charisk.eq(0b0001),
- If(trx.rx_idle,
- NextState("RESET")
- ),
self.ready.eq(1),
+ If(trx.rx_idle,
+ NextState("RESET"),
+ )
)
- reset_timeout = Timeout(clk_freq//16)
- self.submodules += reset_timeout
- self.comb += [
- reset_timeout.ce.eq(~self.ready),
- self.need_reset.eq(reset_timeout.reached)
- ]
+ self.comb += align_detect.eq(self.sink.stb &
+ (self.sink.data == primitives["ALIGN"]))
- self.comb += \
- align_detect.eq(self.sink.stb &
- (self.sink.data == primitives["ALIGN"]))
- self.sync += \
- If(fsm.ongoing("SEND_ALIGN"),
- If(sink.stb,
- If(sink.data[0:8] == 0x7C,
- non_align_cnt.eq(non_align_cnt + 1)
- ).Else(
- non_align_cnt.eq(0)
- )
- )
- )
+ def us(self, t):
+ clk_period_us = 1000000/self.clk_freq
+ return math.ceil(t/clk_period_us)
# # #
- # width convertion (16 to 32) and byte alignment
+ # width convertion (16 to 32) and byte alignment
byte_alignment = Signal()
last_charisk = Signal(2)
last_data = Signal(16)
converter.reset.eq(converter.source.charisk[2:] != 0)
]
- # clock domain crossing
- # (sata_gen3) 300MHz sata_rx clk to sys_clk
- # (sata_gen2) 150MHz sata_rx clk to sys_clk
- # (sata_gen1) 75MHz sata_rx clk to sys_clk
- # requirements:
- # due to the convertion ratio of 2, sys_clk need to be > sata_rx/2
- # source destination is always able to accept data (ack always 1)
+ # clock domain crossing
+ # (sata_gen3) 300MHz sata_rx clk to sys_clk
+ # (sata_gen2) 150MHz sata_rx clk to sys_clk
+ # (sata_gen1) 75MHz sata_rx clk to sys_clk
+ # requirements:
+ # due to the convertion ratio of 2, sys_clk need to be > sata_rx/2
+ # source destination is always able to accept data (ack always 1)
fifo = AsyncFIFO(phy_description(32), 4)
fifo = RenameClockDomains(fifo, {"write": "sata_rx", "read": "sys"})
self.submodules += fifo
# # #
- # clock domain crossing
- # (sata_gen3) sys_clk to 300MHz sata_tx clk
- # (sata_gen2) sys_clk to 150MHz sata_tx clk
- # (sata_gen1) sys_clk to 75MHz sata_tx clk
- # requirements:
- # source destination is always able to accept data (ack always 1)
+ # clock domain crossing
+ # (sata_gen3) sys_clk to 300MHz sata_tx clk
+ # (sata_gen2) sys_clk to 150MHz sata_tx clk
+ # (sata_gen1) sys_clk to 75MHz sata_tx clk
+ # requirements:
+ # source destination is always able to accept data (ack always 1)
fifo = AsyncFIFO(phy_description(32), 4)
fifo = RenameClockDomains(fifo, {"write": "sys", "read": "sata_tx"})
self.submodules += fifo
self.comb += Record.connect(sink, fifo.sink)
- # width convertion (32 to 16)
+ # width convertion (32 to 16)
converter = Converter(phy_description(32),
phy_description(16),
reverse=False)
# # #
- # TX path
+ # TX path
align_inserter = LiteSATAPHYAlignInserter(ctrl)
mux = Multiplexer(phy_description(32), 2)
tx = LiteSATAPHYDatapathTX()
Record.connect(tx.source, trx.sink)
]
- # RX path
+ # RX path
rx = LiteSATAPHYDatapathRX()
demux = Demultiplexer(phy_description(32), 2)
align_remover = LiteSATAPHYAlignRemover()
class K7LiteSATAPHYCRG(Module):
def __init__(self, pads, gtx, revision, clk_freq):
- self.reset = Signal()
+ self.tx_reset = Signal()
+ self.rx_reset = Signal()
self.ready = Signal()
self.clock_domains.cd_sata_tx = ClockDomain()
self.clock_domains.cd_sata_rx = ClockDomain()
- # CPLL
- # (sata_gen3) 150MHz / VCO @ 3GHz / Line rate @ 6Gbps
- # (sata_gen2 & sata_gen1) VCO still @ 3 GHz, Line rate is decreased with output dividers.
+ # CPLL
+ # (sata_gen3) 150MHz / VCO @ 3GHz / Line rate @ 6Gbps
+ # (sata_gen2 & sata_gen1) VCO still @ 3 GHz, Line rate is
+ # decreased with output dividers.
refclk = Signal()
self.specials += Instance("IBUFDS_GTE2",
i_CEB=0,
)
self.comb += gtx.gtrefclk0.eq(refclk)
- # TX clocking
- # (sata_gen3) 150MHz from CPLL TXOUTCLK, sata_tx clk @ 300MHz (16-bits)
- # (sata_gen2) 150MHz from CPLL TXOUTCLK, sata_tx clk @ 150MHz (16-bits)
- # (sata_gen1) 150MHz from CPLL TXOUTCLK, sata_tx clk @ 75MHz (16-bits)
+ # TX clocking
+ # (sata_gen3) 150MHz from CPLL TXOUTCLK, sata_tx clk @ 300MHz (16-bits)
+ # (sata_gen2) 150MHz from CPLL TXOUTCLK, sata_tx clk @ 150MHz (16-bits)
+ # (sata_gen1) 150MHz from CPLL TXOUTCLK, sata_tx clk @ 75MHz (16-bits)
mmcm_reset = Signal()
mmcm_locked = Signal()
mmcm_fb = Signal()
mmcm_clk_i = Signal()
mmcm_clk0_o = Signal()
mmcm_div_config = {
- "sata_gen1": 16.0,
+ "sata_gen1": 16.0,
"sata_gen2": 8.0,
- "sata_gen3": 4.0
+ "sata_gen3": 4.0
}
mmcm_div = mmcm_div_config[revision]
self.specials += [
gtx.txusrclk2.eq(self.cd_sata_tx.clk)
]
- # RX clocking
- # (sata_gen3) sata_rx recovered clk @ 300MHz from GTX RXOUTCLK
- # (sata_gen2) sata_rx recovered clk @ 150MHz from GTX RXOUTCLK
- # (sata_gen1) sata_rx recovered clk @ 150MHz from GTX RXOUTCLK
+ # RX clocking
+ # (sata_gen3) sata_rx recovered clk @ 300MHz from GTX RXOUTCLK
+ # (sata_gen2) sata_rx recovered clk @ 150MHz from GTX RXOUTCLK
+ # (sata_gen1) sata_rx recovered clk @ 150MHz from GTX RXOUTCLK
self.specials += [
Instance("BUFG", i_I=gtx.rxoutclk, o_O=self.cd_sata_rx.clk),
]
gtx.rxusrclk2.eq(self.cd_sata_rx.clk)
]
- # Configuration Reset
- # After configuration, GTX's resets have to stay low for at least 500ns
- # See AR43482
- reset_en = Signal()
- clk_period_ns = 1000000000/clk_freq
- reset_en_cnt_max = math.ceil(500/clk_period_ns)
- reset_en_cnt = Signal(max=reset_en_cnt_max, reset=reset_en_cnt_max-1)
- self.sync += \
- If(self.reset,
- reset_en_cnt.eq(reset_en_cnt.reset)
- ).Elif(~reset_en,
- reset_en_cnt.eq(reset_en_cnt-1)
+ # Configuration Reset
+ # After configuration, GTX's resets have to stay low for at least 500ns
+ # See AR43482
+ startup_cycles = math.ceil(500*clk_freq/1000000000)
+ startup_wait = Timeout(startup_cycles)
+ self.submodules += startup_wait
+ self.comb += [
+ startup_wait.reset.eq(self.tx_reset | self.rx_reset),
+ startup_wait.ce.eq(1)
+ ]
+
+ # TX Startup FSM
+ self.tx_ready = Signal()
+ tx_startup_fsm = InsertReset(FSM(reset_state="IDLE"))
+ self.submodules += tx_startup_fsm
+ # Wait 500ns of AR43482
+ tx_startup_fsm.act("IDLE",
+ If(startup_wait.reached,
+ NextState("RESET_ALL"),
)
- self.comb += reset_en.eq(reset_en_cnt == 0)
-
- # TX Reset FSM
- tx_reset_fsm = InsertReset(FSM(reset_state="IDLE"))
- self.submodules += tx_reset_fsm
- self.comb += tx_reset_fsm.reset.eq(self.reset)
- tx_reset_fsm.act("IDLE",
- If(reset_en,
- NextState("RESET_GTX"),
+ )
+ # Reset CPLL, MMCM, GTX
+ tx_startup_fsm.act("RESET_ALL",
+ gtx.cpllreset.eq(1),
+ mmcm_reset.eq(1),
+ gtx.gttxreset.eq(1),
+ NextState("RELEASE_CPLL"),
+ )
+ # Release CPLL reset and wait for lock
+ tx_startup_fsm.act("RELEASE_CPLL",
+ mmcm_reset.eq(1),
+ gtx.gttxreset.eq(1),
+ If(gtx.cplllock,
+ NextState("RELEASE_MMCM"),
)
)
- tx_reset_fsm.act("RESET_GTX",
+ # Release MMCM reset and wait for lock
+ tx_startup_fsm.act("RELEASE_MMCM",
gtx.gttxreset.eq(1),
- If(gtx.cplllock & mmcm_locked,
+ If(mmcm_locked,
NextState("RELEASE_GTX")
)
)
- tx_reset_fsm.act("RELEASE_GTX",
+ # Release GTX reset and wait for GTX resetdone
+ # (from UG476, GTX is reseted on falling edge
+ # of gttxreset)
+ tx_startup_fsm.act("RELEASE_GTX",
gtx.txuserrdy.eq(1),
If(gtx.txresetdone,
NextState("READY")
)
)
- tx_reset_fsm.act("READY",
- gtx.txuserrdy.eq(1)
+ # Start Delay alignment (Pulse)
+ tx_startup_fsm.act("ALIGN",
+ gtx.txuserrdy.eq(1),
+ gtx.txdlyreset.eq(1),
+ NextState("WAIT_ALIGN")
)
+ # Wait Delay alignment
+ tx_startup_fsm.act("WAIT_ALIGN",
+ gtx.txuserrdy.eq(1),
+ If(gtx.txdlyresetdone,
+ NextState("READY")
+ )
+ )
+ tx_startup_fsm.act("READY",
+ gtx.txuserrdy.eq(1),
+ self.tx_ready.eq(1)
+ )
+
+ tx_ready_timeout = Timeout(1*clk_freq//1000)
+ self.submodules += tx_ready_timeout
+ self.comb += [
+ tx_ready_timeout.reset.eq(self.tx_reset | self.tx_ready),
+ tx_ready_timeout.ce.eq(~self.tx_ready),
+ tx_startup_fsm.reset.eq(self.tx_reset | tx_ready_timeout.reached),
+ ]
+
+
+ # RX Startup FSM
+ self.rx_ready = Signal()
+ rx_startup_fsm = InsertReset(FSM(reset_state="IDLE"))
+ self.submodules += rx_startup_fsm
- # RX Reset FSM
- rx_reset_fsm = InsertReset(FSM(reset_state="IDLE"))
- self.submodules += rx_reset_fsm
- self.comb += rx_reset_fsm.reset.eq(self.reset)
+ cdr_stable = Timeout(2048)
+ self.submodules += cdr_stable
+ self.comb += cdr_stable.ce.eq(1),
- rx_reset_fsm.act("IDLE",
- If(reset_en,
+ # Wait 500ns of AR43482
+ rx_startup_fsm.act("IDLE",
+ cdr_stable.reset.eq(1),
+ If(startup_wait.reached,
NextState("RESET_GTX"),
)
)
- rx_reset_fsm.act("RESET_GTX",
+ # Reset GTX
+ rx_startup_fsm.act("RESET_GTX",
gtx.gtrxreset.eq(1),
- If(gtx.cplllock & mmcm_locked,
- NextState("RELEASE_GTX")
+ NextState("WAIT_CPLL")
+ )
+ # Wait for CPLL lock
+ rx_startup_fsm.act("WAIT_CPLL",
+ gtx.gtrxreset.eq(1),
+ If(gtx.cplllock,
+ NextState("RELEASE_GTX"),
+ cdr_stable.reset.eq(1)
+ )
+ )
+ # Release GTX reset and wait for GTX resetdone
+ # (from UG476, GTX is reseted on falling edge
+ # of gttxreset)
+ rx_startup_fsm.act("RELEASE_GTX",
+ gtx.rxuserrdy.eq(1),
+ If(gtx.rxresetdone & cdr_stable.reached,
+ NextState("ALIGN")
)
)
- rx_reset_fsm.act("RELEASE_GTX",
+ # Start Delay alignment (Pulse)
+ rx_startup_fsm.act("ALIGN",
gtx.rxuserrdy.eq(1),
- If(gtx.rxresetdone,
+ gtx.rxdlyreset.eq(1),
+ NextState("WAIT_ALIGN")
+ )
+ # Wait Delay alignment
+ rx_startup_fsm.act("WAIT_ALIGN",
+ gtx.rxuserrdy.eq(1),
+ If(gtx.rxdlyresetdone,
NextState("READY")
)
)
- rx_reset_fsm.act("READY",
- gtx.rxuserrdy.eq(1)
+ rx_startup_fsm.act("READY",
+ gtx.rxuserrdy.eq(1),
+ self.rx_ready.eq(1)
)
- # Ready
- self.tx_ready = tx_reset_fsm.ongoing("READY")
- self.rx_ready = rx_reset_fsm.ongoing("READY")
- self.comb += self.ready.eq(self.tx_ready & self.rx_ready)
-
- # Reset PLL
- self.comb += gtx.cpllreset.eq(ResetSignal() | self.reset | ~reset_en)
+ rx_ready_timeout = Timeout(1*clk_freq//1000)
+ self.submodules += rx_ready_timeout
+ self.comb += [
+ rx_ready_timeout.reset.eq(self.rx_reset | self.rx_ready),
+ rx_ready_timeout.ce.eq(~self.rx_ready),
+ rx_startup_fsm.reset.eq(self.rx_reset | rx_ready_timeout.reached),
+ ]
- # Reset MMCM
- self.comb += mmcm_reset.eq(ResetSignal() | self.reset | ~gtx.cplllock)
+ # Ready
+ self.comb += self.ready.eq(self.tx_ready & self.rx_ready)
- # Reset for SATA TX/RX clock domains
+ # Reset for SATA TX/RX clock domains
self.specials += [
- AsyncResetSynchronizer(self.cd_sata_tx, ~self.tx_ready),
- AsyncResetSynchronizer(self.cd_sata_rx, ~self.rx_ready),
+ AsyncResetSynchronizer(self.cd_sata_tx, ~(gtx.cplllock & mmcm_locked) | self.tx_reset),
+ AsyncResetSynchronizer(self.cd_sata_rx, ~gtx.cplllock | self.rx_reset),
]
self.comb += o.eq(i & ~i_d)
+class _LowPassFilter(Module):
+ def __init__(self, i, o, cycles):
+ i_d = Signal()
+ self.submodules.timeout = Timeout(cycles)
+ self.sync += [
+ i_d.eq(i),
+ If(self.timeout.reached,
+ o.eq(i_d)
+ )
+ ]
+ self.comb += [
+ self.timeout.reset.eq(i != i_d),
+ self.timeout.ce.eq(1)
+ ]
+
+
class K7LiteSATAPHYTRX(Module):
def __init__(self, pads, revision):
# Common signals
# control
- self.tx_idle = Signal() #i
+ self.tx_idle = Signal() #i
self.tx_cominit_stb = Signal() #i
self.tx_cominit_ack = Signal() #o
self.tx_comwake_stb = Signal() #i
- self.tx_comwake_ack = Signal() #o
+ self.tx_comwake_ack = Signal() #o
- self.rx_idle = Signal() #o
+ self.rx_idle = Signal() #o
self.rx_align = Signal() #i
- self.rx_cominit_stb = Signal() #o
- self.rx_comwake_stb = Signal() #o
+ self.rx_cominit_stb = Signal() #o
+ self.rx_comwake_stb = Signal() #o
# datapath
self.sink = Sink(phy_description(16))
# Receive Ports
self.rxuserrdy = Signal()
- self.rxalign = Signal()
# Receive Ports - 8b10b Decoder
self.rxcharisk = Signal(2)
- self.rxdisperr = Signal(2)
# Receive Ports - RX Data Path interface
self.gtrxreset = Signal()
- self.pmarxreset = Signal()
self.rxdata = Signal(16)
self.rxoutclk = Signal()
self.rxusrclk = Signal()
# Receive Ports - RX PLL Ports
self.rxresetdone = Signal()
+ self.rxdlyreset = Signal()
+ self.rxdlyresetdone = Signal()
# Receive Ports - RX Ports for SATA
self.rxcominitdet = Signal()
# Transmit Ports - TX PLL Ports
self.txresetdone = Signal()
+ self.txdlyreset = Signal()
+ self.txdlyresetdone = Signal()
# Transmit Ports - TX Ports for PCI Express
self.txelecidle = Signal(reset=1)
self.txcomfinish = Signal()
self.txcominit = Signal()
self.txcomwake = Signal()
- self.txrate = Signal(3)
- self.rxcdrlock = Signal()
# Config at startup
div_config = {
self.tx_cominit_ack.eq(self.tx_cominit_stb & self.txcomfinish),
self.tx_comwake_ack.eq(self.tx_comwake_stb & self.txcomfinish),
self.rx_idle.eq(self.rxelecidle),
- self.rxalign.eq(self.rx_align),
self.rx_cominit_stb.eq(self.rxcominitdet),
self.rx_comwake_stb.eq(self.rxcomwakedet),
]
txelecidle = Signal(reset=1)
txcominit = Signal()
txcomwake = Signal()
- txrate = Signal(3)
+ txdlyreset = Signal()
+ txdlyresetdone = Signal()
+ gttxreset = Signal()
self.specials += [
MultiReg(self.txuserrdy, txuserrdy, "sata_tx"),
MultiReg(self.txelecidle, txelecidle, "sata_tx"),
- MultiReg(self.txrate, txrate, "sata_tx")
+ MultiReg(self.gttxreset, gttxreset, "sata_tx"),
]
self.submodules += [
_PulseSynchronizer(self.txcominit, "sys", txcominit, "sata_tx"),
_PulseSynchronizer(self.txcomwake, "sys", txcomwake, "sata_tx"),
+ _PulseSynchronizer(self.txdlyreset, "sys", txdlyreset, "sata_tx"),
]
# sata_tx clk --> sys clk
self.specials += [
MultiReg(txresetdone, self.txresetdone, "sys"),
+ MultiReg(txdlyresetdone, self.txdlyresetdone, "sys"),
]
self.submodules += [
# sys clk --> sata_rx clk
rxuserrdy = Signal()
+ rxdlyreset = Signal()
self.specials += [
MultiReg(self.rxuserrdy, rxuserrdy, "sata_rx"),
]
+ self.submodules += [
+ _PulseSynchronizer(self.rxdlyreset, "sys", rxdlyreset, "sata_rx"),
+ ]
+
# sata_rx clk --> sys clk
rxelecidle = Signal()
rxelecidle_i = Signal()
- rxelecidle_cnt_i = Signal(9)
rxresetdone = Signal()
rxcominitdet = Signal()
rxcomwakedet = Signal()
rxratedone = Signal()
- rxcdrlock = Signal()
+ rxdlyresetdone = Signal()
self.specials += [
MultiReg(rxelecidle, rxelecidle_i, "sys"),
MultiReg(rxresetdone, self.rxresetdone, "sys"),
MultiReg(rxcominitdet, self.rxcominitdet, "sys"),
MultiReg(rxcomwakedet, self.rxcomwakedet, "sys"),
- MultiReg(rxcdrlock, self.rxcdrlock, "sys"),
- ]
-
- self.sync += [
- If(rxelecidle_i != self.rxelecidle,
- If(rxelecidle_cnt_i == 0,
- self.rxelecidle.eq(rxelecidle_i),
- rxelecidle_cnt_i.eq(255)
- ).Else(
- rxelecidle_cnt_i.eq(rxelecidle_cnt_i-1)
- )
- ).Else(
- rxelecidle_cnt_i.eq(255)
- )
+ MultiReg(rxdlyresetdone, self.rxdlyresetdone, "sys"),
]
- self.rxbyteisaligned = Signal()
+ rxelecidle_filter = _LowPassFilter(rxelecidle_i, self.rxelecidle, 256)
+ self.submodules += rxelecidle_filter
# QPLL input clock
self.qpllclk = Signal()
# RX Byte and Word Alignment Attributes
"p_ALIGN_COMMA_DOUBLE": "FALSE",
"p_ALIGN_COMMA_ENABLE": ones(10),
- "p_ALIGN_COMMA_WORD": 2,
+ "p_ALIGN_COMMA_WORD": 1,
"p_ALIGN_MCOMMA_DET": "TRUE",
"p_ALIGN_MCOMMA_VALUE": 0b1010000011,
"p_ALIGN_PCOMMA_DET": "TRUE",
"p_CLK_CORRECT_USE": "FALSE",
"p_CLK_COR_SEQ_2_ENABLE": ones(4),
"p_CLK_COR_SEQ_2_1": 0b0100000000,
- "p_CLK_COR_SEQ_2_2": 0,
- "p_CLK_COR_SEQ_2_3": 0,
- "p_CLK_COR_SEQ_2_4": 0,
+ "p_CLK_COR_SEQ_2_2": 0b0000000000,
+ "p_CLK_COR_SEQ_2_3": 0b0000000000,
+ "p_CLK_COR_SEQ_2_4": 0b0000000000,
# RX Channel Bonding Attributes
"p_CHAN_BOND_KEEP_ALIGN": "FALSE",
"p_RX_CM_TRIM": 0b010,
"p_RX_DEBUG_CFG": 0,
"p_RX_OS_CFG": 0b10000000,
- "p_TERM_RCAL_CFG": 0,
+ "p_TERM_RCAL_CFG": 0b10000,
"p_TERM_RCAL_OVRD": 0,
"p_TST_RSV": 0,
"p_RX_CLK25_DIV": 6,
# RX Buffer Attributes
"p_RXBUF_ADDR_MODE": "FAST",
"p_RXBUF_EIDLE_HI_CNT": 0b1000,
- "p_RXBUF_EIDLE_LO_CNT": 0,
- "p_RXBUF_EN": "TRUE",
+ "p_RXBUF_EIDLE_LO_CNT": 0b0000,
+ "p_RXBUF_EN": "FALSE",
"p_RX_BUFFER_CFG": 0,
"p_RXBUF_RESET_ON_CB_CHANGE": "TRUE",
"p_RXBUF_RESET_ON_COMMAALIGN": "FALSE",
"p_TRANS_TIME_RATE": 0x0e,
# TX Buffer Attributes
- "p_TXBUF_EN": "TRUE",
+ "p_TXBUF_EN": "FALSE",
"p_TXBUF_RESET_ON_RATE_CHANGE": "TRUE",
"p_TXDLY_CFG": 0x1f,
"p_TXDLY_LCFG": 0x030,
"p_TXPH_CFG": 0x0780,
"p_TXPHDLY_CFG": 0x084020,
"p_TXPH_MONITOR_SEL": 0,
- "p_TX_XCLK_SEL": "TXOUT",
+ "p_TX_XCLK_SEL": "TXUSR",
# FPGA TX Interface Attributes
"p_TX_DATA_WIDTH": 20,
# Receive Ports - CDR Ports
i_RXCDRFREQRESET=0,
i_RXCDRHOLD=0,
- o_RXCDRLOCK=rxcdrlock,
+ #o_RXCDRLOCK=,
i_RXCDROVRDEN=0,
i_RXCDRRESET=0,
i_RXCDRRESETRSV=0,
i_RXPRBSCNTRESET=0,
# Receive Ports - RX Equalizer Ports
- i_RXDFEXYDEN=0,
+ i_RXDFEXYDEN=1,
i_RXDFEXYDHOLD=0,
i_RXDFEXYDOVRDEN=0,
# Receive Ports - RX Buffer Bypass Ports
i_RXBUFRESET=0,
#o_RXBUFSTATUS=,
- i_RXDDIEN=0,
- i_RXDLYBYPASS=1,
+ i_RXDDIEN=1,
+ i_RXDLYBYPASS=0,
i_RXDLYEN=0,
i_RXDLYOVRDEN=0,
- i_RXDLYSRESET=0,
- #o_RXDLYSRESETDONE=0,
+ i_RXDLYSRESET=rxdlyreset,
+ o_RXDLYSRESETDONE=rxdlyresetdone,
i_RXPHALIGN=0,
#o_RXPHALIGNDONE=,
i_RXPHALIGNEN=0,
#o_RXSTATUS=,
# Receive Ports - RX Byte and Word Alignment Ports
- o_RXBYTEISALIGNED=self.rxbyteisaligned,
+ #o_RXBYTEISALIGNED=,
#o_RXBYTEREALIGN=,
#o_RXCOMMADET=,
i_RXCOMMADETEN=1,
i_RXDFEAGCOVRDEN=0,
i_RXDFECM1EN=0,
i_RXDFELFHOLD=0,
- i_RXDFELFOVRDEN=1,
+ i_RXDFELFOVRDEN=0,
i_RXDFELPMRESET=0,
i_RXDFETAP2HOLD=0,
i_RXDFETAP2OVRDEN=0,
i_GTRXRESET=self.gtrxreset,
i_RXOOBRESET=0,
i_RXPCSRESET=0,
- i_RXPMARESET=self.pmarxreset,
+ i_RXPMARESET=0,
# Receive Ports - RX Margin Analysis ports
i_RXLPMEN=0,
# TX Initialization and Reset Ports
i_CFGRESET=0,
- i_GTTXRESET=self.gttxreset,
+ i_GTTXRESET=gttxreset,
#o_PCSRSVDOUT=,
i_TXUSERRDY=txuserrdy,
# Transmit Ports - PCI Express Ports
i_TXELECIDLE=txelecidle,
i_TXMARGIN=0,
- i_TXRATE=txrate,
+ i_TXRATE=0,
i_TXSWING=0,
# Transmit Ports - Pattern Generator Ports
i_TXPRBSFORCEERR=0,
# Transmit Ports - TX Buffer Bypass Ports
- i_TXDLYBYPASS=1,
+ i_TXDLYBYPASS=0,
i_TXDLYEN=0,
i_TXDLYHOLD=0,
i_TXDLYOVRDEN=0,
- i_TXDLYSRESET=0,
- #o_TXDLYSRESETDONE=,
+ i_TXDLYSRESET=txdlyreset,
+ o_TXDLYSRESETDONE=txdlyresetdone,
i_TXDLYUPDOWN=0,
i_TXPHALIGN=0,
#o_TXPHALIGNDONE=txphaligndone,
o_TXOUTCLK=self.txoutclk,
#o_TXOUTCLKFABRIC=,
#o_TXOUTCLKPCS=,
- i_TXOUTCLKSEL=0b11, # ??
+ i_TXOUTCLKSEL=0b11,
#o_TXRATEDONE=,
# Transmit Ports - TX Gearbox Ports
i_TXCHARISK=self.txcharisk,