From 7bdcbc94cdcb38fa06bd648ff7b68d30d4cc29ab Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Wed, 6 May 2015 01:33:02 +0200 Subject: [PATCH] litesata: use (some) settings from vivado 2015.1, try to follow all ug476 recommendations to initialize GTX (...), remove automatic reset on top. Works fine @ 3Gbps, still not working @6.0Gbps --- .../litesata/example_designs/targets/bist.py | 4 +- .../mem/litesata/example_designs/test/bist.py | 2 +- misoclib/mem/litesata/phy/__init__.py | 4 +- misoclib/mem/litesata/phy/ctrl.py | 92 ++++---- misoclib/mem/litesata/phy/datapath.py | 34 +-- misoclib/mem/litesata/phy/k7/crg.py | 201 ++++++++++++------ misoclib/mem/litesata/phy/k7/trx.py | 118 +++++----- 7 files changed, 259 insertions(+), 196 deletions(-) diff --git a/misoclib/mem/litesata/example_designs/targets/bist.py b/misoclib/mem/litesata/example_designs/targets/bist.py index 18b5333d..8b28dfe3 100644 --- a/misoclib/mem/litesata/example_designs/targets/bist.py +++ b/misoclib/mem/litesata/example_designs/targets/bist.py @@ -19,7 +19,6 @@ from misoclib.mem.litesata import LiteSATA class _CRG(Module): def __init__(self, platform): self.clock_domains.cd_sys = ClockDomain() - self.reset = Signal() clk200 = platform.request("clk200") clk200_se = Signal() @@ -49,7 +48,7 @@ class _CRG(Module): 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")), ] @@ -106,7 +105,6 @@ class BISTSoC(SoC, AutoCSR): # 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 diff --git a/misoclib/mem/litesata/example_designs/test/bist.py b/misoclib/mem/litesata/example_designs/test/bist.py index 5b55a700..db8f7f86 100644 --- a/misoclib/mem/litesata/example_designs/test/bist.py +++ b/misoclib/mem/litesata/example_designs/test/bist.py @@ -191,7 +191,7 @@ if __name__ == "__main__": 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, diff --git a/misoclib/mem/litesata/phy/__init__.py b/misoclib/mem/litesata/phy/__init__.py index edaea403..4e952d4d 100644 --- a/misoclib/mem/litesata/phy/__init__.py +++ b/misoclib/mem/litesata/phy/__init__.py @@ -7,6 +7,7 @@ class LiteSATAPHY(Module): 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 @@ -14,8 +15,7 @@ class LiteSATAPHY(Module): 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) diff --git a/misoclib/mem/litesata/phy/ctrl.py b/misoclib/mem/litesata/phy/ctrl.py index e73fb258..3c53c6b3 100644 --- a/misoclib/mem/litesata/phy/ctrl.py +++ b/misoclib/mem/litesata/phy/ctrl.py @@ -1,15 +1,10 @@ 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)) @@ -20,47 +15,47 @@ class LiteSATAPHYCtrl(Module): 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), @@ -71,34 +66,31 @@ class LiteSATAPHYCtrl(Module): 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), @@ -108,47 +100,39 @@ class LiteSATAPHYCtrl(Module): 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) diff --git a/misoclib/mem/litesata/phy/datapath.py b/misoclib/mem/litesata/phy/datapath.py index 847a0d8b..f702ace4 100644 --- a/misoclib/mem/litesata/phy/datapath.py +++ b/misoclib/mem/litesata/phy/datapath.py @@ -8,7 +8,7 @@ class LiteSATAPHYDatapathRX(Module): # # # - # 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) @@ -38,13 +38,13 @@ class LiteSATAPHYDatapathRX(Module): 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 @@ -61,18 +61,18 @@ class LiteSATAPHYDatapathTX(Module): # # # - # 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) @@ -143,7 +143,7 @@ class LiteSATAPHYDatapath(Module): # # # - # TX path + # TX path align_inserter = LiteSATAPHYAlignInserter(ctrl) mux = Multiplexer(phy_description(32), 2) tx = LiteSATAPHYDatapathTX() @@ -157,7 +157,7 @@ class LiteSATAPHYDatapath(Module): Record.connect(tx.source, trx.sink) ] - # RX path + # RX path rx = LiteSATAPHYDatapathRX() demux = Demultiplexer(phy_description(32), 2) align_remover = LiteSATAPHYAlignRemover() diff --git a/misoclib/mem/litesata/phy/k7/crg.py b/misoclib/mem/litesata/phy/k7/crg.py index 86aeb86c..73a7d966 100644 --- a/misoclib/mem/litesata/phy/k7/crg.py +++ b/misoclib/mem/litesata/phy/k7/crg.py @@ -3,15 +3,17 @@ from misoclib.mem.litesata.common import * 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, @@ -21,19 +23,19 @@ class K7LiteSATAPHYCRG(Module): ) 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 += [ @@ -60,10 +62,10 @@ class K7LiteSATAPHYCRG(Module): 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), ] @@ -72,85 +74,154 @@ class K7LiteSATAPHYCRG(Module): 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), ] diff --git a/misoclib/mem/litesata/phy/k7/trx.py b/misoclib/mem/litesata/phy/k7/trx.py index 6e3fbc57..628e4506 100644 --- a/misoclib/mem/litesata/phy/k7/trx.py +++ b/misoclib/mem/litesata/phy/k7/trx.py @@ -21,23 +21,39 @@ class _RisingEdge(Module): 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)) @@ -53,15 +69,12 @@ class K7LiteSATAPHYTRX(Module): # 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() @@ -72,6 +85,8 @@ class K7LiteSATAPHYTRX(Module): # Receive Ports - RX PLL Ports self.rxresetdone = Signal() + self.rxdlyreset = Signal() + self.rxdlyresetdone = Signal() # Receive Ports - RX Ports for SATA self.rxcominitdet = Signal() @@ -92,6 +107,8 @@ class K7LiteSATAPHYTRX(Module): # 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) @@ -100,8 +117,6 @@ class K7LiteSATAPHYTRX(Module): self.txcomfinish = Signal() self.txcominit = Signal() self.txcomwake = Signal() - self.txrate = Signal(3) - self.rxcdrlock = Signal() # Config at startup div_config = { @@ -125,7 +140,6 @@ class K7LiteSATAPHYTRX(Module): 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), ] @@ -150,16 +164,19 @@ class K7LiteSATAPHYTRX(Module): 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 @@ -168,6 +185,7 @@ class K7LiteSATAPHYTRX(Module): self.specials += [ MultiReg(txresetdone, self.txresetdone, "sys"), + MultiReg(txdlyresetdone, self.txdlyresetdone, "sys"), ] self.submodules += [ @@ -176,43 +194,35 @@ class K7LiteSATAPHYTRX(Module): # 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() @@ -230,7 +240,7 @@ class K7LiteSATAPHYTRX(Module): # 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", @@ -263,9 +273,9 @@ class K7LiteSATAPHYTRX(Module): "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", @@ -314,7 +324,7 @@ class K7LiteSATAPHYTRX(Module): "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, @@ -330,8 +340,8 @@ class K7LiteSATAPHYTRX(Module): # 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", @@ -397,7 +407,7 @@ class K7LiteSATAPHYTRX(Module): "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, @@ -405,7 +415,7 @@ class K7LiteSATAPHYTRX(Module): "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, @@ -569,7 +579,7 @@ class K7LiteSATAPHYTRX(Module): # Receive Ports - CDR Ports i_RXCDRFREQRESET=0, i_RXCDRHOLD=0, - o_RXCDRLOCK=rxcdrlock, + #o_RXCDRLOCK=, i_RXCDROVRDEN=0, i_RXCDRRESET=0, i_RXCDRRESETRSV=0, @@ -595,7 +605,7 @@ class K7LiteSATAPHYTRX(Module): i_RXPRBSCNTRESET=0, # Receive Ports - RX Equalizer Ports - i_RXDFEXYDEN=0, + i_RXDFEXYDEN=1, i_RXDFEXYDHOLD=0, i_RXDFEXYDOVRDEN=0, @@ -610,12 +620,12 @@ class K7LiteSATAPHYTRX(Module): # 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, @@ -627,7 +637,7 @@ class K7LiteSATAPHYTRX(Module): #o_RXSTATUS=, # Receive Ports - RX Byte and Word Alignment Ports - o_RXBYTEISALIGNED=self.rxbyteisaligned, + #o_RXBYTEISALIGNED=, #o_RXBYTEREALIGN=, #o_RXCOMMADET=, i_RXCOMMADETEN=1, @@ -651,7 +661,7 @@ class K7LiteSATAPHYTRX(Module): i_RXDFEAGCOVRDEN=0, i_RXDFECM1EN=0, i_RXDFELFHOLD=0, - i_RXDFELFOVRDEN=1, + i_RXDFELFOVRDEN=0, i_RXDFELPMRESET=0, i_RXDFETAP2HOLD=0, i_RXDFETAP2OVRDEN=0, @@ -699,7 +709,7 @@ class K7LiteSATAPHYTRX(Module): 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, @@ -750,7 +760,7 @@ class K7LiteSATAPHYTRX(Module): # TX Initialization and Reset Ports i_CFGRESET=0, - i_GTTXRESET=self.gttxreset, + i_GTTXRESET=gttxreset, #o_PCSRSVDOUT=, i_TXUSERRDY=txuserrdy, @@ -769,19 +779,19 @@ class K7LiteSATAPHYTRX(Module): # 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, @@ -815,7 +825,7 @@ class K7LiteSATAPHYTRX(Module): 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, -- 2.30.2