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