clocking: clean up and add comments
This commit is contained in:
parent
387cf90cf8
commit
879478a6e4
|
@ -8,7 +8,7 @@ from lib.sata.k7sataphy.clocking import K7SATAPHYClocking
|
||||||
from lib.sata.k7sataphy.ctrl import K7SATAPHYHostCtrl, K7SATAPHYDeviceCtrl
|
from lib.sata.k7sataphy.ctrl import K7SATAPHYHostCtrl, K7SATAPHYDeviceCtrl
|
||||||
|
|
||||||
class K7SATAPHY(Module):
|
class K7SATAPHY(Module):
|
||||||
def __init__(self, pads, host=True):
|
def __init__(self, pads, clk_freq, host=True,):
|
||||||
self.sink = Sink([("d", 32)], True)
|
self.sink = Sink([("d", 32)], True)
|
||||||
self.source = Source([("d", 32)], True)
|
self.source = Source([("d", 32)], True)
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ class K7SATAPHY(Module):
|
||||||
gtx.rxrate.eq(0b000),
|
gtx.rxrate.eq(0b000),
|
||||||
gtx.txrate.eq(0b000),
|
gtx.txrate.eq(0b000),
|
||||||
]
|
]
|
||||||
clocking = K7SATAPHYClocking(pads, gtx)
|
clocking = K7SATAPHYClocking(pads, gtx, clk_freq)
|
||||||
rxalign = K7SATAPHYRXAlign()
|
rxalign = K7SATAPHYRXAlign()
|
||||||
rxconvert = K7SATAPHYRXConvert()
|
rxconvert = K7SATAPHYRXConvert()
|
||||||
txconvert = K7SATAPHYTXConvert()
|
txconvert = K7SATAPHYTXConvert()
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
from math import ceil
|
||||||
|
|
||||||
from migen.fhdl.std import *
|
from migen.fhdl.std import *
|
||||||
from migen.genlib.resetsync import AsyncResetSynchronizer
|
from migen.genlib.resetsync import AsyncResetSynchronizer
|
||||||
from migen.genlib.fsm import FSM, NextState
|
from migen.genlib.fsm import FSM, NextState
|
||||||
|
@ -23,15 +25,19 @@ class K7SATAPHYReconfig(Module):
|
||||||
)
|
)
|
||||||
|
|
||||||
class K7SATAPHYClocking(Module):
|
class K7SATAPHYClocking(Module):
|
||||||
def __init__(self, pads, gtx):
|
def __init__(self, pads, gtx, clk_freq):
|
||||||
self.reset = Signal()
|
self.reset = Signal()
|
||||||
self.gtx_reset = Signal()
|
|
||||||
|
|
||||||
self.clock_domains.cd_sata = ClockDomain()
|
self.clock_domains.cd_sata = ClockDomain()
|
||||||
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()
|
||||||
|
|
||||||
# TX clocking
|
# CPLL
|
||||||
|
# (SATA3) 150MHz / VCO @ 3GHz / Line rate @ 6Gbps
|
||||||
|
# (SATA2 & SATA1) VCO still @ 3 GHz, Line rate is decreased with output divivers.
|
||||||
|
# When changing rate, reconfiguration of the CPLL over DRP is needed to:
|
||||||
|
# - update the output divider
|
||||||
|
# - update the equalizer configuration (specific for each line rate).
|
||||||
refclk = Signal()
|
refclk = Signal()
|
||||||
self.specials += Instance("IBUFDS_GTE2",
|
self.specials += Instance("IBUFDS_GTE2",
|
||||||
i_CEB=0,
|
i_CEB=0,
|
||||||
|
@ -41,6 +47,11 @@ class K7SATAPHYClocking(Module):
|
||||||
)
|
)
|
||||||
self.comb += gtx.gtrefclk0.eq(refclk)
|
self.comb += gtx.gtrefclk0.eq(refclk)
|
||||||
|
|
||||||
|
# TX clocking
|
||||||
|
# (SATA3) 150MHz from CPLL TXOUTCLK, sata_tx clk @ 300MHz (16-bits), sata clk @ 150MHz (32-bits)
|
||||||
|
# (SATA2) 150MHz from CPLL TXOUTCLK, sata_tx clk @ 150MHz (16-bits), sata clk @ 75MHz (32-bits)
|
||||||
|
# (SATA1) 150MHz from CPLL TXOUTCLK, sata_tx clk @ 75MHz (16-bits), sata clk @ 37.5MHz (32-bits)
|
||||||
|
# When changing rate, reconfiguration of the MMCM is needed to update the output divider.
|
||||||
mmcm_reset = Signal()
|
mmcm_reset = Signal()
|
||||||
mmcm_locked = Signal()
|
mmcm_locked = Signal()
|
||||||
mmcm_drp = DRPBus()
|
mmcm_drp = DRPBus()
|
||||||
|
@ -49,7 +60,7 @@ class K7SATAPHYClocking(Module):
|
||||||
mmcm_clk0_o = Signal()
|
mmcm_clk0_o = Signal()
|
||||||
mmcm_clk1_o = Signal()
|
mmcm_clk1_o = Signal()
|
||||||
self.specials += [
|
self.specials += [
|
||||||
Instance("BUFG", i_I=refclk, o_O=mmcm_clk_i),
|
Instance("BUFG", i_I=gtx.txoutclk, o_O=mmcm_clk_i),
|
||||||
Instance("MMCME2_ADV",
|
Instance("MMCME2_ADV",
|
||||||
p_BANDWIDTH="HIGH", p_COMPENSATION="ZHOLD", i_RST=mmcm_reset, o_LOCKED=mmcm_locked,
|
p_BANDWIDTH="HIGH", p_COMPENSATION="ZHOLD", i_RST=mmcm_reset, o_LOCKED=mmcm_locked,
|
||||||
|
|
||||||
|
@ -59,14 +70,14 @@ class K7SATAPHYClocking(Module):
|
||||||
|
|
||||||
# VCO
|
# VCO
|
||||||
p_REF_JITTER1=0.01, p_CLKIN1_PERIOD=6.666,
|
p_REF_JITTER1=0.01, p_CLKIN1_PERIOD=6.666,
|
||||||
p_CLKFBOUT_MULT_F=8.000, p_CLKFBOUT_PHASE=0.000, p_DIVCLK_DIVIDE=2,
|
p_CLKFBOUT_MULT_F=8.000, p_CLKFBOUT_PHASE=0.000, p_DIVCLK_DIVIDE=1,
|
||||||
i_CLKIN1=mmcm_clk_i, i_CLKFBIN=mmcm_fb, o_CLKFBOUT=mmcm_fb,
|
i_CLKIN1=mmcm_clk_i, i_CLKFBIN=mmcm_fb, o_CLKFBOUT=mmcm_fb,
|
||||||
|
|
||||||
# CLK0
|
# CLK0
|
||||||
p_CLKOUT0_DIVIDE_F=2.000, p_CLKOUT0_PHASE=0.000, o_CLKOUT0=mmcm_clk0_o,
|
p_CLKOUT0_DIVIDE_F=4.000, p_CLKOUT0_PHASE=0.000, o_CLKOUT0=mmcm_clk0_o,
|
||||||
|
|
||||||
# CLK1
|
# CLK1
|
||||||
p_CLKOUT1_DIVIDE=4, p_CLKOUT1_PHASE=0.000, o_CLKOUT1=mmcm_clk1_o,
|
p_CLKOUT1_DIVIDE=8, p_CLKOUT1_PHASE=0.000, o_CLKOUT1=mmcm_clk1_o,
|
||||||
),
|
),
|
||||||
Instance("BUFG", i_I=mmcm_clk0_o, o_O=self.cd_sata_tx.clk),
|
Instance("BUFG", i_I=mmcm_clk0_o, o_O=self.cd_sata_tx.clk),
|
||||||
Instance("BUFG", i_I=mmcm_clk1_o, o_O=self.cd_sata.clk),
|
Instance("BUFG", i_I=mmcm_clk1_o, o_O=self.cd_sata.clk),
|
||||||
|
@ -77,8 +88,11 @@ class K7SATAPHYClocking(Module):
|
||||||
]
|
]
|
||||||
|
|
||||||
# RX clocking
|
# RX clocking
|
||||||
|
# (SATA3) sata_rx recovered clk @ 300MHz from CPLL RXOUTCLK
|
||||||
|
# (SATA2) sata_rx recovered clk @ 150MHz from CPLL RXOUTCLK
|
||||||
|
# (SATA1) sata_rx recovered clk @ 150MHz from CPLL RXOUTCLK
|
||||||
self.specials += [
|
self.specials += [
|
||||||
Instance("BUFG", i_I=mmcm_clk0_o, o_O=self.cd_sata_rx.clk),
|
Instance("BUFG", i_I=gtx.rxoutclk, o_O=self.cd_sata_rx.clk),
|
||||||
]
|
]
|
||||||
self.comb += [
|
self.comb += [
|
||||||
gtx.rxusrclk.eq(self.cd_sata_rx.clk),
|
gtx.rxusrclk.eq(self.cd_sata_rx.clk),
|
||||||
|
@ -94,6 +108,26 @@ class K7SATAPHYClocking(Module):
|
||||||
gtx.txphinit.eq(0)
|
gtx.txphinit.eq(0)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# RX buffer bypass logic
|
||||||
|
self.comb += [
|
||||||
|
gtx.rxphdlyreset.eq(0),
|
||||||
|
gtx.rxdlyen.eq(0),
|
||||||
|
gtx.rxphalign.eq(0),
|
||||||
|
gtx.rxphalignen.eq(0),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# Configuration Reset
|
||||||
|
# After configuration, GTX resets can not be asserted for 500ns
|
||||||
|
# See AR43482
|
||||||
|
reset_en = Signal()
|
||||||
|
clk_period_ns = 1000000000/clk_freq
|
||||||
|
reset_en_cnt_max = ceil(500/clk_period_ns)
|
||||||
|
reset_en_cnt = Signal(max=reset_en_cnt_max, reset=reset_en_cnt_max-1)
|
||||||
|
self.sync += If(~reset_en, reset_en_cnt.eq(reset_en_cnt-1))
|
||||||
|
self.comb += reset_en.eq(reset_en_cnt == 0)
|
||||||
|
|
||||||
|
|
||||||
# once channel TX is reseted, reset TX buffer
|
# once channel TX is reseted, reset TX buffer
|
||||||
txbuffer_reseted = Signal()
|
txbuffer_reseted = Signal()
|
||||||
self.sync += \
|
self.sync += \
|
||||||
|
@ -106,29 +140,10 @@ class K7SATAPHYClocking(Module):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
# RX buffer bypass logic
|
# once channel RX is reseted, reset RX buffer
|
||||||
self.comb += [
|
|
||||||
gtx.rxphdlyreset.eq(0),
|
|
||||||
gtx.rxdlyen.eq(0),
|
|
||||||
gtx.rxphalign.eq(0),
|
|
||||||
gtx.rxphalignen.eq(0),
|
|
||||||
]
|
|
||||||
|
|
||||||
# wait till CDR is locked
|
|
||||||
# cdr_cnt = Signal(14, reset=0b10011100010000)
|
|
||||||
cdr_cnt = Signal(14, reset=1024)
|
|
||||||
cdr_locked = Signal()
|
|
||||||
self.sync += \
|
|
||||||
If(cdr_cnt != 0,
|
|
||||||
cdr_cnt.eq(cdr_cnt - 1)
|
|
||||||
).Else(
|
|
||||||
cdr_locked.eq(1)
|
|
||||||
)
|
|
||||||
|
|
||||||
# once CDR is locked and channel RX reseted, reset RX buffer
|
|
||||||
rxbuffer_reseted = Signal()
|
rxbuffer_reseted = Signal()
|
||||||
self.sync += \
|
self.sync += \
|
||||||
If(cdr_locked & gtx.rxresetdone,
|
If(gtx.rxresetdone,
|
||||||
If(~rxbuffer_reseted,
|
If(~rxbuffer_reseted,
|
||||||
gtx.rxdlysreset.eq(1),
|
gtx.rxdlysreset.eq(1),
|
||||||
rxbuffer_reseted.eq(1)
|
rxbuffer_reseted.eq(1)
|
||||||
|
@ -152,11 +167,11 @@ class K7SATAPHYClocking(Module):
|
||||||
gtx.rxuserrdy.eq(gtx.cplllock),
|
gtx.rxuserrdy.eq(gtx.cplllock),
|
||||||
gtx.txuserrdy.eq(gtx.cplllock),
|
gtx.txuserrdy.eq(gtx.cplllock),
|
||||||
# TX
|
# TX
|
||||||
gtx.gttxreset.eq(rst_cnt_done & (self.reset | self.gtx_reset | ~gtx.cplllock )),
|
gtx.gttxreset.eq(reset_en & (self.reset | ~gtx.cplllock)),
|
||||||
# RX
|
# RX
|
||||||
gtx.gtrxreset.eq(rst_cnt_done & (self.reset | self.gtx_reset | ~gtx.cplllock)),
|
gtx.gtrxreset.eq(reset_en & (self.reset | ~gtx.cplllock)),
|
||||||
# PLL
|
# PLL
|
||||||
gtx.cpllreset.eq(rst_cnt_done & (self.reset | ~cdr_locked))
|
gtx.cpllreset.eq(self.reset | ~reset_en)
|
||||||
]
|
]
|
||||||
# SATA TX/RX clock domains
|
# SATA TX/RX clock domains
|
||||||
self.specials += [
|
self.specials += [
|
||||||
|
|
|
@ -94,7 +94,7 @@ class TestDesign(UART2WB):
|
||||||
UART2WB.__init__(self, platform, clk_freq)
|
UART2WB.__init__(self, platform, clk_freq)
|
||||||
self.submodules.crg = _CRG(platform)
|
self.submodules.crg = _CRG(platform)
|
||||||
|
|
||||||
self.submodules.sataphy_host = K7SATAPHY(platform.request("sata_host"), host=True)
|
self.submodules.sataphy_host = K7SATAPHY(platform.request("sata_host"), clk_freq, host=True)
|
||||||
self.submodules.sataphy_device = K7SATAPHY(platform.request("sata_device"), host=False)
|
self.submodules.sataphy_device = K7SATAPHY(platform.request("sata_device"), clk_freq, host=False)
|
||||||
|
|
||||||
default_subtarget = TestDesign
|
default_subtarget = TestDesign
|
||||||
|
|
Loading…
Reference in New Issue