Skip to content

Commit

Permalink
litesata: use (some) settings from vivado 2015.1, try to follow all u…
Browse files Browse the repository at this point in the history
…g476 recommendations to initialize GTX (...), remove automatic reset on top.

Works fine @ 3Gbps, still not working @6.0Gbps
enjoy-digital committed May 5, 2015
1 parent 5d5d5ed commit 7bdcbc9
Showing 7 changed files with 259 additions and 196 deletions.
4 changes: 1 addition & 3 deletions misoclib/mem/litesata/example_designs/targets/bist.py
Original file line number Diff line number Diff line change
@@ -19,7 +19,6 @@
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 @@ def __init__(self, platform):
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 @@ def __init__(self, platform):

# 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
2 changes: 1 addition & 1 deletion misoclib/mem/litesata/example_designs/test/bist.py
Original file line number Diff line number Diff line change
@@ -191,7 +191,7 @@ def _get_args():

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,
4 changes: 2 additions & 2 deletions misoclib/mem/litesata/phy/__init__.py
Original file line number Diff line number Diff line change
@@ -7,15 +7,15 @@ 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
from misoclib.mem.litesata.phy.k7.crg import K7LiteSATAPHYCRG
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)
92 changes: 38 additions & 54 deletions misoclib/mem/litesata/phy/ctrl.py
Original file line number Diff line number Diff line change
@@ -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 @@ def __init__(self, trx, crg, clk_freq):
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 @@ def __init__(self, trx, crg, clk_freq):
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 @@ def __init__(self, trx, crg, clk_freq):
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)
34 changes: 17 additions & 17 deletions misoclib/mem/litesata/phy/datapath.py
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ def __init__(self):

# # #

# 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 @@ def __init__(self):
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 @@ def __init__(self):

# # #

# 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 @@ def __init__(self, trx, ctrl):

# # #

# TX path
# TX path
align_inserter = LiteSATAPHYAlignInserter(ctrl)
mux = Multiplexer(phy_description(32), 2)
tx = LiteSATAPHYDatapathTX()
@@ -157,7 +157,7 @@ def __init__(self, trx, ctrl):
Record.connect(tx.source, trx.sink)
]

# RX path
# RX path
rx = LiteSATAPHYDatapathRX()
demux = Demultiplexer(phy_description(32), 2)
align_remover = LiteSATAPHYAlignRemover()
201 changes: 136 additions & 65 deletions misoclib/mem/litesata/phy/k7/crg.py
Original file line number Diff line number Diff line change
@@ -3,15 +3,17 @@

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 @@ def __init__(self, pads, gtx, revision, clk_freq):
)
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 @@ def __init__(self, pads, gtx, revision, clk_freq):
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 @@ def __init__(self, pads, gtx, revision, clk_freq):
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),
]
118 changes: 64 additions & 54 deletions misoclib/mem/litesata/phy/k7/trx.py
Original file line number Diff line number Diff line change
@@ -21,23 +21,39 @@ def __init__(self, i, o):
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 @@ def __init__(self, pads, revision):

# 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 @@ def __init__(self, pads, revision):

# 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 @@ def __init__(self, pads, revision):

# 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 @@ def __init__(self, pads, revision):
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 @@ def __init__(self, pads, revision):
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 @@ def __init__(self, pads, revision):
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 @@ def __init__(self, pads, revision):

self.specials += [
MultiReg(txresetdone, self.txresetdone, "sys"),
MultiReg(txdlyresetdone, self.txdlyresetdone, "sys"),
]

self.submodules += [
@@ -176,43 +194,35 @@ def __init__(self, pads, revision):

# 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 @@ def __init__(self, pads, revision):
# 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 @@ def __init__(self, pads, revision):
"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 @@ def __init__(self, pads, revision):
"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 @@ def __init__(self, pads, revision):
# 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,15 +407,15 @@ def __init__(self, pads, revision):
"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_TXDLY_TAP_CFG": 0,
"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 @@ def __init__(self, pads, revision):
# 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 @@ def __init__(self, pads, revision):
i_RXPRBSCNTRESET=0,

# Receive Ports - RX Equalizer Ports
i_RXDFEXYDEN=0,
i_RXDFEXYDEN=1,
i_RXDFEXYDHOLD=0,
i_RXDFEXYDOVRDEN=0,

@@ -610,12 +620,12 @@ def __init__(self, pads, revision):
# 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 @@ def __init__(self, pads, revision):
#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 @@ def __init__(self, pads, revision):
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 @@ def __init__(self, pads, revision):
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 @@ def __init__(self, pads, revision):

# TX Initialization and Reset Ports
i_CFGRESET=0,
i_GTTXRESET=self.gttxreset,
i_GTTXRESET=gttxreset,
#o_PCSRSVDOUT=,
i_TXUSERRDY=txuserrdy,

@@ -769,19 +779,19 @@ def __init__(self, pads, revision):
# 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 @@ def __init__(self, pads, revision):
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,

0 comments on commit 7bdcbc9

Please sign in to comment.