From 879478a6e4ff6c8da5e56784b70aca6baeed057b Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Sat, 27 Sep 2014 13:33:43 +0200 Subject: [PATCH] clocking: clean up and add comments --- lib/sata/k7sataphy/__init__.py | 4 +- lib/sata/k7sataphy/clocking.py | 79 ++++++++++++++++++++-------------- targets/test.py | 4 +- 3 files changed, 51 insertions(+), 36 deletions(-) diff --git a/lib/sata/k7sataphy/__init__.py b/lib/sata/k7sataphy/__init__.py index d4494c107..a268d0c70 100644 --- a/lib/sata/k7sataphy/__init__.py +++ b/lib/sata/k7sataphy/__init__.py @@ -8,7 +8,7 @@ from lib.sata.k7sataphy.clocking import K7SATAPHYClocking from lib.sata.k7sataphy.ctrl import K7SATAPHYHostCtrl, K7SATAPHYDeviceCtrl class K7SATAPHY(Module): - def __init__(self, pads, host=True): + def __init__(self, pads, clk_freq, host=True,): self.sink = Sink([("d", 32)], True) self.source = Source([("d", 32)], True) @@ -17,7 +17,7 @@ class K7SATAPHY(Module): gtx.rxrate.eq(0b000), gtx.txrate.eq(0b000), ] - clocking = K7SATAPHYClocking(pads, gtx) + clocking = K7SATAPHYClocking(pads, gtx, clk_freq) rxalign = K7SATAPHYRXAlign() rxconvert = K7SATAPHYRXConvert() txconvert = K7SATAPHYTXConvert() diff --git a/lib/sata/k7sataphy/clocking.py b/lib/sata/k7sataphy/clocking.py index 2192acaef..6a0497d5d 100644 --- a/lib/sata/k7sataphy/clocking.py +++ b/lib/sata/k7sataphy/clocking.py @@ -1,3 +1,5 @@ +from math import ceil + from migen.fhdl.std import * from migen.genlib.resetsync import AsyncResetSynchronizer from migen.genlib.fsm import FSM, NextState @@ -23,15 +25,19 @@ class K7SATAPHYReconfig(Module): ) class K7SATAPHYClocking(Module): - def __init__(self, pads, gtx): + def __init__(self, pads, gtx, clk_freq): self.reset = Signal() - self.gtx_reset = Signal() self.clock_domains.cd_sata = ClockDomain() self.clock_domains.cd_sata_tx = 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() self.specials += Instance("IBUFDS_GTE2", i_CEB=0, @@ -41,6 +47,11 @@ class K7SATAPHYClocking(Module): ) 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_locked = Signal() mmcm_drp = DRPBus() @@ -49,7 +60,7 @@ class K7SATAPHYClocking(Module): mmcm_clk0_o = Signal() mmcm_clk1_o = Signal() 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", p_BANDWIDTH="HIGH", p_COMPENSATION="ZHOLD", i_RST=mmcm_reset, o_LOCKED=mmcm_locked, @@ -59,14 +70,14 @@ class K7SATAPHYClocking(Module): # VCO 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, # 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 - 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_clk1_o, o_O=self.cd_sata.clk), @@ -77,8 +88,11 @@ class K7SATAPHYClocking(Module): ] # 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 += [ - 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 += [ gtx.rxusrclk.eq(self.cd_sata_rx.clk), @@ -94,6 +108,26 @@ class K7SATAPHYClocking(Module): 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 txbuffer_reseted = Signal() self.sync += \ @@ -106,29 +140,10 @@ class K7SATAPHYClocking(Module): ) ) - # RX buffer bypass logic - 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 + # once channel RX is reseted, reset RX buffer rxbuffer_reseted = Signal() self.sync += \ - If(cdr_locked & gtx.rxresetdone, + If(gtx.rxresetdone, If(~rxbuffer_reseted, gtx.rxdlysreset.eq(1), rxbuffer_reseted.eq(1) @@ -152,11 +167,11 @@ class K7SATAPHYClocking(Module): gtx.rxuserrdy.eq(gtx.cplllock), gtx.txuserrdy.eq(gtx.cplllock), # TX - gtx.gttxreset.eq(rst_cnt_done & (self.reset | self.gtx_reset | ~gtx.cplllock )), + gtx.gttxreset.eq(reset_en & (self.reset | ~gtx.cplllock)), # RX - gtx.gtrxreset.eq(rst_cnt_done & (self.reset | self.gtx_reset | ~gtx.cplllock)), + gtx.gtrxreset.eq(reset_en & (self.reset | ~gtx.cplllock)), # PLL - gtx.cpllreset.eq(rst_cnt_done & (self.reset | ~cdr_locked)) + gtx.cpllreset.eq(self.reset | ~reset_en) ] # SATA TX/RX clock domains self.specials += [ diff --git a/targets/test.py b/targets/test.py index c1dd7522f..c6d598dd0 100644 --- a/targets/test.py +++ b/targets/test.py @@ -94,7 +94,7 @@ class TestDesign(UART2WB): UART2WB.__init__(self, platform, clk_freq) self.submodules.crg = _CRG(platform) - self.submodules.sataphy_host = K7SATAPHY(platform.request("sata_host"), host=True) - self.submodules.sataphy_device = K7SATAPHY(platform.request("sata_device"), host=False) + self.submodules.sataphy_host = K7SATAPHY(platform.request("sata_host"), clk_freq, host=True) + self.submodules.sataphy_device = K7SATAPHY(platform.request("sata_device"), clk_freq, host=False) default_subtarget = TestDesign