From: Florent Kermarrec Date: Mon, 3 Nov 2014 16:38:12 +0000 (+0100) Subject: move code and create a directory for each layer X-Git-Tag: 24jan2021_ls180~2572^2~174 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=47b5ff5e33580082f3f3a8abcdeb8f02c5c89929;p=litex.git move code and create a directory for each layer --- diff --git a/lib/sata/command/.keep_me b/lib/sata/command/.keep_me new file mode 100644 index 00000000..e69de29b diff --git a/lib/sata/k7sataphy/__init__.py b/lib/sata/k7sataphy/__init__.py deleted file mode 100644 index ba4ef1b4..00000000 --- a/lib/sata/k7sataphy/__init__.py +++ /dev/null @@ -1,23 +0,0 @@ -from migen.fhdl.std import * - -from lib.sata.k7sataphy.std import * -from lib.sata.k7sataphy.gtx import K7SATAPHYGTX -from lib.sata.k7sataphy.crg import K7SATAPHYCRG -from lib.sata.k7sataphy.ctrl import K7SATAPHYHostCtrl, K7SATAPHYDeviceCtrl -from lib.sata.k7sataphy.datapath import K7SATAPHYDatapath - -class K7SATAPHY(Module): - def __init__(self, pads, clk_freq, host=True, default_speed="SATA1"): - # GTX - self.submodules.gtx = K7SATAPHYGTX(pads, default_speed) - - # CRG / CTRL - self.submodules.crg = K7SATAPHYCRG(pads, self.gtx, clk_freq, default_speed) - if host: - self.submodules.ctrl = K7SATAPHYHostCtrl(self.gtx, self.crg, clk_freq) - else: - self.submodules.ctrl = K7SATAPHYDeviceCtrl(self.gtx, self.crg, clk_freq) - - # DATAPATH - self.submodules.datapath = K7SATAPHYDatapath(self.gtx, self.ctrl) - self.sink, self.source = self.datapath.sink, self.datapath.source diff --git a/lib/sata/k7sataphy/crg.py b/lib/sata/k7sataphy/crg.py deleted file mode 100644 index 93ac490a..00000000 --- a/lib/sata/k7sataphy/crg.py +++ /dev/null @@ -1,172 +0,0 @@ -from math import ceil - -from migen.fhdl.std import * -from migen.genlib.resetsync import AsyncResetSynchronizer -from migen.genlib.fsm import FSM, NextState - -from lib.sata.k7sataphy.std import * -from lib.sata.k7sataphy.gtx import GTXE2_COMMON - -class K7SATAPHYCRG(Module): - def __init__(self, pads, gtx, clk_freq, default_speed): - self.reset = Signal() - self.ready = Signal() - - self.clock_domains.cd_sata_tx = ClockDomain() - self.clock_domains.cd_sata_rx = ClockDomain() - - # CPLL - # (SATA3) 150MHz / VCO @ 3GHz / Line rate @ 6Gbps - # (SATA2 & SATA1) VCO still @ 3 GHz, Line rate is decreased with output dividers. - refclk = Signal() - self.specials += Instance("IBUFDS_GTE2", - i_CEB=0, - i_I=pads.refclk_p, - i_IB=pads.refclk_n, - o_O=refclk - ) - self.comb += gtx.gtrefclk0.eq(refclk) - - # QPLL - # not used but need to be there... see AR43339... - gtx_common = GTXE2_COMMON() - self.comb += [ - gtx_common.refclk0.eq(refclk), - gtx.qpllclk.eq(gtx_common.qpllclk), - gtx.qpllrefclk.eq(gtx_common.qpllrefclk), - ] - self.submodules += gtx_common - - # TX clocking - # (SATA3) 150MHz from CPLL TXOUTCLK, sata_tx clk @ 300MHz (16-bits) - # (SATA2) 150MHz from CPLL TXOUTCLK, sata_tx clk @ 150MHz (16-bits) - # (SATA1) 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 = { - "SATA1" : 16.0, - "SATA2" : 8.0, - "SATA3" : 4.0 - } - mmcm_div = mmcm_div_config[default_speed] - self.specials += [ - 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, - - # DRP - i_DCLK=0, i_DEN=0, i_DWE=0, #o_DRDY=, - i_DADDR=0, i_DI=0, #o_DO=, - - # 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=1, - i_CLKIN1=mmcm_clk_i, i_CLKFBIN=mmcm_fb, o_CLKFBOUT=mmcm_fb, - - # CLK0 - p_CLKOUT0_DIVIDE_F=mmcm_div, p_CLKOUT0_PHASE=0.000, o_CLKOUT0=mmcm_clk0_o, - ), - Instance("BUFG", i_I=mmcm_clk0_o, o_O=self.cd_sata_tx.clk), - ] - self.comb += [ - gtx.txusrclk.eq(self.cd_sata_tx.clk), - gtx.txusrclk2.eq(self.cd_sata_tx.clk) - ] - - # RX clocking - # (SATA3) sata_rx recovered clk @ 300MHz from GTX RXOUTCLK - # (SATA2) sata_rx recovered clk @ 150MHz from GTX RXOUTCLK - # (SATA1) sata_rx recovered clk @ 150MHz from GTX RXOUTCLK - self.specials += [ - Instance("BUFG", i_I=gtx.rxoutclk, o_O=self.cd_sata_rx.clk), - ] - self.comb += [ - gtx.rxusrclk.eq(self.cd_sata_rx.clk), - 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 = 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) - ) - 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"), - ) - ) - tx_reset_fsm.act("RESET_GTX", - gtx.gttxreset.eq(1), - If(gtx.cplllock & mmcm_locked, - NextState("RELEASE_GTX") - ) - ) - tx_reset_fsm.act("RELEASE_GTX", - gtx.txuserrdy.eq(1), - If(gtx.txresetdone, - NextState("READY") - ) - ) - tx_reset_fsm.act("READY", - gtx.txuserrdy.eq(1) - ) - - # 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) - - 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") - ) - ) - rx_reset_fsm.act("READY", - gtx.rxuserrdy.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) - - # Reset MMCM - self.comb += mmcm_reset.eq(ResetSignal() | self.reset | ~gtx.cplllock) - - # 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), - ] diff --git a/lib/sata/k7sataphy/ctrl.py b/lib/sata/k7sataphy/ctrl.py deleted file mode 100644 index c4ffb463..00000000 --- a/lib/sata/k7sataphy/ctrl.py +++ /dev/null @@ -1,302 +0,0 @@ -from math import ceil - -from migen.fhdl.std import * -from migen.genlib.resetsync import AsyncResetSynchronizer -from migen.genlib.fsm import FSM, NextState -from migen.flow.actor import Sink, Source - -from lib.sata.k7sataphy.std import * - -def us(t, clk_freq): - clk_period_us = 1000000/clk_freq - return ceil(t/clk_period_us) - -class K7SATAPHYHostCtrl(Module): - def __init__(self, gtx, crg, clk_freq): - self.ready = Signal() - - self.sink = Sink([("data", 32), ("charisk", 4)]) - self.source = Source([("data", 32), ("charisk", 4)]) - - self.align_detect = align_detect = Signal() - align_timeout_cnt = Signal(32) - align_timeout = Signal() - - retry_timeout_cnt = Signal(32) - retry_timeout = Signal() - - non_align_cnt = Signal(4) - - txcominit = Signal() - txcomwake = Signal() - - self.comb += [ - self.source.stb.eq(1), - self.sink.ack.eq(1) - ] - - fsm = FSM(reset_state="RESET") - self.submodules += fsm - - fsm.act("RESET", - gtx.txelecidle.eq(1), - If(crg.ready, - NextState("COMINIT") - ), - ) - fsm.act("COMINIT", - gtx.txelecidle.eq(1), - txcominit.eq(1), - If(gtx.txcomfinish & ~gtx.rxcominitdet, - NextState("AWAIT_COMINIT") - ), - ) - fsm.act("AWAIT_COMINIT", - gtx.txelecidle.eq(1), - If(gtx.rxcominitdet, - NextState("AWAIT_NO_COMINIT") - ).Else( - If(retry_timeout, - NextState("RESET") - ) - ), - ) - fsm.act("AWAIT_NO_COMINIT", - gtx.txelecidle.eq(1), - If(~gtx.rxcominitdet, - NextState("CALIBRATE") - ), - ) - fsm.act("CALIBRATE", - gtx.txelecidle.eq(1), - NextState("COMWAKE"), - ) - fsm.act("COMWAKE", - gtx.txelecidle.eq(1), - txcomwake.eq(1), - If(gtx.txcomfinish, - NextState("AWAIT_COMWAKE") - ), - ) - fsm.act("AWAIT_COMWAKE", - gtx.txelecidle.eq(1), - If(gtx.rxcomwakedet, - NextState("AWAIT_NO_COMWAKE") - ).Else( - If(retry_timeout, - NextState("RESET") - ) - ), - ) - fsm.act("AWAIT_NO_COMWAKE", - gtx.txelecidle.eq(1), - If(~gtx.rxcomwakedet, - NextState("AWAIT_NO_RXELECIDLE") - ), - ) - fsm.act("AWAIT_NO_RXELECIDLE", - gtx.txelecidle.eq(0), - self.source.data.eq(0x4A4A4A4A), #D10.2 - self.source.charisk.eq(0b0000), - If(~gtx.rxelecidle, - NextState("AWAIT_ALIGN"), - crg.reset.eq(1), - gtx.pmarxreset.eq(1) - ), - ) - fsm.act("AWAIT_ALIGN", - gtx.txelecidle.eq(0), - self.source.data.eq(0x4A4A4A4A), #D10.2 - self.source.charisk.eq(0b0000), - gtx.rxalign.eq(1), - If((align_detect & ~gtx.rxelecidle) & ~align_timeout, - NextState("SEND_ALIGN") - ).Elif(~align_detect & align_timeout, - NextState("RESET") - ), - ) - fsm.act("SEND_ALIGN", - gtx.txelecidle.eq(0), - self.source.data.eq(ALIGN_VAL), - self.source.charisk.eq(0b0001), - If(non_align_cnt == 3, - NextState("READY") - ), - ) - fsm.act("READY", - gtx.txelecidle.eq(0), - self.source.data.eq(SYNC_VAL), - self.source.charisk.eq(0b0001), - self.ready.eq(1), - ) - - txcominit_d = Signal() - txcomwake_d = Signal() - self.sync += [ - txcominit_d.eq(txcominit), - txcomwake_d.eq(txcomwake), - gtx.txcominit.eq(txcominit & ~txcominit_d), - gtx.txcomwake.eq(txcomwake & ~txcomwake_d), - ] - - self.comb += align_detect.eq(self.sink.stb & (self.sink.data == ALIGN_VAL)); - self.sync += \ - If(fsm.ongoing("RESET"), - align_timeout_cnt.eq(us(873, clk_freq)) - ).Elif(fsm.ongoing("AWAIT_ALIGN"), - align_timeout_cnt.eq(align_timeout_cnt-1) - ) - self.comb += align_timeout.eq(align_timeout_cnt == 0) - - self.sync += \ - If(fsm.ongoing("RESET") | fsm.ongoing("AWAIT_NO_COMINIT"), - retry_timeout_cnt.eq(us(10000, clk_freq)) - ).Elif(fsm.ongoing("AWAIT_COMINIT") | fsm.ongoing("AWAIT_COMWAKE"), - retry_timeout_cnt.eq(retry_timeout_cnt-1) - ) - self.comb += retry_timeout.eq(retry_timeout_cnt == 0) - - self.sync += \ - If(fsm.ongoing("SEND_ALIGN"), - If(self.sink.stb, - If(self.sink.data[0:8] == 0x7C, - non_align_cnt.eq(non_align_cnt + 1) - ).Else( - non_align_cnt.eq(0) - ) - ) - ) - -class K7SATAPHYDeviceCtrl(Module): - def __init__(self, gtx, crg, clk_freq): - self.ready = Signal() - - self.sink = Sink([("data", 32), ("charisk", 4)]) - self.source = Source([("data", 32), ("charisk", 4)]) - - align_detect = Signal() - align_timeout = Signal() - align_timeout_cnt = Signal(32) - - retry_timeout_cnt = Signal(32) - retry_timeout = Signal() - - txcominit = Signal() - txcomwake = Signal() - - self.comb += [ - self.source.stb.eq(1), - self.sink.ack.eq(1) - ] - - fsm = FSM(reset_state="RESET") - self.submodules += fsm - - fsm.act("RESET", - gtx.txelecidle.eq(1), - If(crg.ready, - NextState("AWAIT_COMINIT") - ) - ) - fsm.act("AWAIT_COMINIT", - gtx.txelecidle.eq(1), - If(gtx.rxcominitdet, - NextState("AWAIT_NO_COMINIT") - ) - ) - fsm.act("AWAIT_NO_COMINIT", - gtx.txelecidle.eq(1), - If(~gtx.rxcominitdet, - NextState("COMINIT") - ) - ) - fsm.act("COMINIT", - gtx.txelecidle.eq(1), - txcominit.eq(1), - If(gtx.txcomfinish, - NextState("AWAIT_COMWAKE") - ) - ) - fsm.act("AWAIT_COMWAKE", - gtx.txelecidle.eq(1), - If(gtx.rxcomwakedet, - NextState("AWAIT_NO_COMWAKE") - ).Else( - If(retry_timeout, - NextState("RESET") - ) - ) - ) - fsm.act("AWAIT_NO_COMWAKE", - gtx.txelecidle.eq(1), - If(~gtx.rxcomwakedet, - NextState("CALIBRATE") - ) - ) - fsm.act("CALIBRATE", - gtx.txelecidle.eq(1), - NextState("COMWAKE") - ) - fsm.act("COMWAKE", - gtx.txelecidle.eq(1), - txcomwake.eq(1), - If(gtx.txcomfinish, - NextState("RESET_CRG"), - crg.reset.eq(1), - ) - ) - fsm.act("RESET_CRG", - gtx.txelecidle.eq(0), - If(crg.ready, - NextState("SEND_ALIGN") - ) - ) - fsm.act("SEND_ALIGN", - gtx.txelecidle.eq(0), - gtx.rxalign.eq(1), - self.source.data.eq(ALIGN_VAL), - self.source.charisk.eq(0b0001), - If(align_detect, - NextState("READY") - ).Elif(align_timeout, - NextState("ERROR") - ) - ) - fsm.act("READY", - gtx.txelecidle.eq(0), - NextState("READY"), - If(gtx.rxelecidle, - NextState("RESET") - ), - self.ready.eq(1) - ) - fsm.act("ERROR", - gtx.txelecidle.eq(1), - NextState("RESET") - ) - - txcominit_d = Signal() - txcomwake_d = Signal() - self.sync += [ - txcominit_d.eq(txcominit), - txcomwake_d.eq(txcomwake), - gtx.txcominit.eq(txcominit & ~txcominit_d), - gtx.txcomwake.eq(txcomwake & ~txcomwake_d), - ] - - self.comb += align_detect.eq(self.sink.stb & (self.sink.data == ALIGN_VAL)); - self.sync += \ - If(fsm.ongoing("RESET"), - align_timeout_cnt.eq(us(55, clk_freq)) - ).Elif(fsm.ongoing("AWAIT_ALIGN"), - align_timeout_cnt.eq(align_timeout_cnt-1) - ) - self.comb += align_timeout.eq(align_timeout_cnt == 0) - - self.sync += \ - If(fsm.ongoing("RESET"), - retry_timeout_cnt.eq(us(10000, clk_freq)) - ).Elif(fsm.ongoing("AWAIT_COMWAKE"), - retry_timeout_cnt.eq(retry_timeout_cnt-1) - ) - self.comb += retry_timeout.eq(retry_timeout_cnt == 0) diff --git a/lib/sata/k7sataphy/datapath.py b/lib/sata/k7sataphy/datapath.py deleted file mode 100644 index ef06c09a..00000000 --- a/lib/sata/k7sataphy/datapath.py +++ /dev/null @@ -1,153 +0,0 @@ -from migen.fhdl.std import * -from migen.genlib.misc import chooser -from migen.actorlib.fifo import AsyncFIFO -from migen.flow.actor import Sink, Source - -from lib.sata.k7sataphy.std import * - -class K7SATAPHYDatapathRX(Module): - def __init__(self): - self.sink = Sink([("data", 16), ("charisk", 2)]) - self.source = Source([("data", 32), ("charisk", 4)]) - - ### - - # bytes alignment - - # shift register - data_sr = Signal(32+8) - charisk_sr = Signal(4+1) - data_sr_d = Signal(32+8) - charisk_sr_d = Signal(4+1) - self.comb += [ - data_sr.eq(Cat(self.sink.data, data_sr_d)), - charisk_sr.eq(Cat(self.sink.charisk, charisk_sr_d)) - ] - self.sync.sata_rx += [ - data_sr_d.eq(data_sr), - charisk_sr_d.eq(charisk_sr) - ] - - # alignment - alignment = Signal() - valid = Signal() - self.sync.sata_rx += [ - If(self.sink.charisk !=0, - alignment.eq(self.sink.charisk[1]), - valid.eq(0) - ).Else( - valid.eq(~valid) - ) - ] - - # 16 to 32 - data = Signal(32) - charisk = Signal(4) - self.comb += [ - If(~alignment, - data.eq(data_sr[0:32]), - charisk.eq(charisk_sr[0:4]) - ).Else( - data.eq(data_sr[8:40]), - charisk.eq(charisk_sr[1:5]) - ) - ] - - # clock domain crossing - # (SATA3) 300MHz sata_rx clk to sys_clk - # (SATA2) 150MHz sata_rx clk to sys_clk - # (SATA1) 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([("data", 32), ("charisk", 4)], 16) - self.submodules.fifo = RenameClockDomains(fifo, {"write": "sata_rx", "read": "sys"}) - self.comb += [ - fifo.sink.stb.eq(valid), - fifo.sink.data.eq(data), - fifo.sink.charisk.eq(charisk), - ] - self.comb += Record.connect(fifo.source, self.source) - -class K7SATAPHYDatapathTX(Module): - def __init__(self): - self.sink = Sink([("data", 32), ("charisk", 4)]) - self.source = Source([("data", 16), ("charisk", 2)]) - - ### - - # clock domain crossing - # (SATA3) sys_clk to 300MHz sata_tx clk - # (SATA2) sys_clk to 150MHz sata_tx clk - # (SATA1) sys_clk to 75MHz sata_tx clk - # requirements: - # source destination is always able to accept data (ack always 1) - fifo = AsyncFIFO([("data", 32), ("charisk", 4)], 16) - self.submodules.fifo = RenameClockDomains(fifo, {"write": "sys", "read": "sata_tx"}) - self.comb += Record.connect(self.sink, fifo.sink) - - # 32 to 16 - mux = Signal() - last = Signal() - self.comb += [ - last.eq(mux == 1), - self.source.stb.eq(fifo.source.stb), - fifo.source.ack.eq(last), - ] - self.sync.sata_tx += [ - If(self.source.stb, - If(last, - mux.eq(0) - ).Else( - mux.eq(mux + 1) - ) - ) - ] - self.comb += [ - chooser(fifo.source.data, mux, self.source.data), - chooser(fifo.source.charisk, mux, self.source.charisk) - ] - -class K7SATAPHYDatapath(Module): - def __init__(self, gtx, ctrl): - self.sink = Sink([("data", 32), ("charisk", 4)]) - self.source = Source([("data", 32), ("charisk", 4)]) - - ### - - # change data width & cross domain crossing - rx = K7SATAPHYDatapathRX() - tx = K7SATAPHYDatapathTX() - self.submodules += rx, tx - self.comb += [ - rx.sink.data.eq(gtx.rxdata), - rx.sink.charisk.eq(gtx.rxcharisk), - - gtx.txdata.eq(tx.source.data), - gtx.txcharisk.eq(tx.source.charisk), - ] - - # user / ctrl mux - self.comb += [ - # user - If(ctrl.ready, - tx.sink.stb.eq(self.sink.stb), - tx.sink.data.eq(self.sink.data), - tx.sink.charisk.eq(self.sink.charisk), - self.sink.ack.eq(tx.sink.ack), - - self.source.stb.eq(rx.source.stb), - self.source.data.eq(rx.source.data), - self.source.charisk.eq(rx.source.charisk), - rx.source.ack.eq(1), - # ctrl - ).Else( - tx.sink.stb.eq(ctrl.source.stb), - tx.sink.data.eq(ctrl.source.data), - tx.sink.charisk.eq(ctrl.source.charisk), - - ctrl.sink.stb.eq(rx.source.stb), - ctrl.sink.data.eq(rx.source.data), - rx.source.ack.eq(1), - ) - ] diff --git a/lib/sata/k7sataphy/gtx.py b/lib/sata/k7sataphy/gtx.py deleted file mode 100644 index 982cbb9a..00000000 --- a/lib/sata/k7sataphy/gtx.py +++ /dev/null @@ -1,903 +0,0 @@ -from migen.fhdl.std import * -from migen.genlib.cdc import * - -from lib.sata.k7sataphy.std import * - -class _PulseSynchronizer(PulseSynchronizer): - def __init__(self, i, idomain, o, odomain): - PulseSynchronizer.__init__(self, idomain, odomain) - self.comb += [ - self.i.eq(i), - o.eq(self.o) - ] - -class K7SATAPHYGTX(Module): - def __init__(self, pads, default_speed): - # Interface - # Channel - Ref Clock Ports - self.gtrefclk0 = Signal() - - # Channel PLL - self.cplllock = Signal() - self.cpllreset = Signal() - - # 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() - self.rxusrclk2 = Signal() - - # Receive Ports - RX Driver,OOB signalling,Coupling and Eq.,CDR - self.rxelecidle = Signal() - - # Receive Ports - RX PLL Ports - self.rxresetdone = Signal() - - # Receive Ports - RX Ports for SATA - self.rxcominitdet = Signal() - self.rxcomwakedet = Signal() - - # Transmit Ports - self.txuserrdy = Signal() - - # Transmit Ports - 8b10b Encoder Control Ports - self.txcharisk = Signal(2) - - # Transmit Ports - TX Data Path interface - self.gttxreset = Signal() - self.txdata = Signal(16) - self.txoutclk = Signal() - self.txusrclk = Signal() - self.txusrclk2 = Signal() - - # Transmit Ports - TX PLL Ports - self.txresetdone = Signal() - - # Transmit Ports - TX Ports for PCI Express - self.txelecidle = Signal(reset=1) - - # Transmit Ports - TX Ports for SATA - self.txcomfinish = Signal() - self.txcominit = Signal() - self.txcomwake = Signal() - self.txrate = Signal(3) - self.rxcdrlock = Signal() - - # Config at startup - div_config = { - "SATA1" : 4, - "SATA2" : 2, - "SATA3" : 1 - } - rxout_div = div_config[default_speed] - txout_div = div_config[default_speed] - - cdr_config = { - "SATA1" : 0x0380008BFF40100008, - "SATA2" : 0x0380008BFF40200008, - "SATA3" : 0X0380008BFF10200010 - } - rxcdr_cfg = cdr_config[default_speed] - - # Internals and clock domain crossing - # sys_clk --> sata_tx clk - txuserrdy = Signal() - txelecidle = Signal(reset=1) - txcominit = Signal() - txcomwake = Signal() - txrate = Signal(3) - - self.specials += [ - MultiReg(self.txuserrdy, txuserrdy, "sata_tx"), - MultiReg(self.txelecidle, txelecidle, "sata_tx"), - MultiReg(self.txrate, txrate, "sata_tx") - ] - self.submodules += [ - _PulseSynchronizer(self.txcominit, "sys", txcominit, "sata_tx"), - _PulseSynchronizer(self.txcomwake, "sys", txcomwake, "sata_tx"), - ] - - # sata_tx clk --> sys clk - txresetdone = Signal() - txcomfinish = Signal() - - self.specials += [ - MultiReg(txresetdone, self.txresetdone, "sys"), - ] - - self.submodules += [ - _PulseSynchronizer(txcomfinish, "sata_tx", self.txcomfinish, "sys"), - ] - - # sys clk --> sata_rx clk - rxuserrdy = Signal() - - self.specials += [ - MultiReg(self.rxuserrdy, rxuserrdy, "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() - - 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) - ) - ] - - self.rxbyteisaligned = Signal() - - # QPLL input clock - self.qpllclk = Signal() - self.qpllrefclk = Signal() - - # Instance - gtxe2_channel_parameters = { - # Simulation-Only Attributes - "p_SIM_RECEIVER_DETECT_PASS":"TRUE", - "p_SIM_TX_EIDLE_DRIVE_LEVEL":"X", - "p_SIM_RESET_SPEEDUP":"TRUE", - "p_SIM_CPLLREFCLK_SEL":0b001, - "p_SIM_VERSION":"4.0", - - # RX Byte and Word Alignment Attributes - "p_ALIGN_COMMA_DOUBLE":"FALSE", - "p_ALIGN_COMMA_ENABLE":ones(10), - "p_ALIGN_COMMA_WORD":2, - "p_ALIGN_MCOMMA_DET":"TRUE", - "p_ALIGN_MCOMMA_VALUE":0b1010000011, - "p_ALIGN_PCOMMA_DET":"TRUE", - "p_ALIGN_PCOMMA_VALUE":0b0101111100, - "p_SHOW_REALIGN_COMMA":"FALSE", - "p_RXSLIDE_AUTO_WAIT":7, - "p_RXSLIDE_MODE":"OFF", - "p_RX_SIG_VALID_DLY":10, - - # RX 8B/10B Decoder Attributes - "p_RX_DISPERR_SEQ_MATCH":"TRUE", - "p_DEC_MCOMMA_DETECT":"TRUE", - "p_DEC_PCOMMA_DETECT":"TRUE", - "p_DEC_VALID_COMMA_ONLY":"TRUE", - - # RX Clock Correction Attributes - "p_CBCC_DATA_SOURCE_SEL":"DECODED", - "p_CLK_COR_SEQ_2_USE":"FALSE", - "p_CLK_COR_KEEP_IDLE":"FALSE", - "p_CLK_COR_MAX_LAT":35, - "p_CLK_COR_MIN_LAT":28, - "p_CLK_COR_PRECEDENCE":"TRUE", - "p_CLK_COR_REPEAT_WAIT":0, - "p_CLK_COR_SEQ_LEN":4, - "p_CLK_COR_SEQ_1_ENABLE":ones(4), - "p_CLK_COR_SEQ_1_1":0b0110111100, - "p_CLK_COR_SEQ_1_2":0b0001001010, - "p_CLK_COR_SEQ_1_3":0b0001001010, - "p_CLK_COR_SEQ_1_4":0b0001111011, - "p_CLK_CORRECT_USE":"FALSE", - "p_CLK_COR_SEQ_2_ENABLE":ones(4), - "p_CLK_COR_SEQ_2_1":0, - "p_CLK_COR_SEQ_2_2":0, - "p_CLK_COR_SEQ_2_3":0, - "p_CLK_COR_SEQ_2_4":0, - - # RX Channel Bonding Attributes - "p_CHAN_BOND_KEEP_ALIGN":"FALSE", - "p_CHAN_BOND_MAX_SKEW":1, - "p_CHAN_BOND_SEQ_LEN":1, - "p_CHAN_BOND_SEQ_1_1":0, - "p_CHAN_BOND_SEQ_1_1":0, - "p_CHAN_BOND_SEQ_1_2":0, - "p_CHAN_BOND_SEQ_1_3":0, - "p_CHAN_BOND_SEQ_1_4":0, - "p_CHAN_BOND_SEQ_1_ENABLE":ones(4), - "p_CHAN_BOND_SEQ_2_1":0, - "p_CHAN_BOND_SEQ_2_2":0, - "p_CHAN_BOND_SEQ_2_3":0, - "p_CHAN_BOND_SEQ_2_4":0, - "p_CHAN_BOND_SEQ_2_ENABLE":ones(4), - "p_CHAN_BOND_SEQ_2_USE":"FALSE", - "p_FTS_DESKEW_SEQ_ENABLE":ones(4), - "p_FTS_LANE_DESKEW_CFG":ones(4), - "p_FTS_LANE_DESKEW_EN":"FALSE", - - # RX Margin Analysis Attributes - "p_ES_CONTROL":0, - "p_ES_ERRDET_EN":"FALSE", - "p_ES_EYE_SCAN_EN":"TRUE", - "p_ES_HORZ_OFFSET":0, - "p_ES_PMA_CFG":0, - "p_ES_PRESCALE":0, - "p_ES_QUALIFIER":0, - "p_ES_QUAL_MASK":0, - "p_ES_SDATA_MASK":0, - "p_ES_VERT_OFFSET":0, - - # FPGA RX Interface Attributes - "p_RX_DATA_WIDTH":20, - - # PMA Attributes - "p_OUTREFCLK_SEL_INV":0b11, - "p_PMA_RSV":0x00018480, - "p_PMA_RSV2":0x2050, - "p_PMA_RSV3":0, - "p_PMA_RSV4":0, - "p_RX_BIAS_CFG":0b100, - "p_DMONITOR_CFG":0xA00, - "p_RX_CM_SEL":0b11, - "p_RX_CM_TRIM":0b010, - "p_RX_DEBUG_CFG":0, - "p_RX_OS_CFG":0b10000000, - "p_TERM_RCAL_CFG":0, - "p_TERM_RCAL_OVRD":0, - "p_TST_RSV":0, - "p_RX_CLK25_DIV":6, - "p_TX_CLK25_DIV":6, - "p_UCODEER_CLR":0, - - # PCI Express Attributes - "p_PCS_PCIE_EN":"FALSE", - - # PCS Attributes - "p_PCS_RSVD_ATTR":0x100, - - # 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_RX_BUFFER_CFG":0, - "p_RXBUF_RESET_ON_CB_CHANGE":"TRUE", - "p_RXBUF_RESET_ON_COMMAALIGN":"FALSE", - "p_RXBUF_RESET_ON_EIDLE":"FALSE", - "p_RXBUF_RESET_ON_RATE_CHANGE":"TRUE", - "p_RXBUFRESET_TIME":1, - "p_RXBUF_THRESH_OVFLW":61, - "p_RXBUF_THRESH_OVRD":"FALSE", - "p_RXBUF_THRESH_UNDFLW":4, - "p_RXDLY_CFG":0x1f, - "p_RXDLY_LCFG":0x30, - "p_RXDLY_TAP_CFG":0, - "p_RXPH_CFG":0, - "p_RXPHDLY_CFG":0x084820, - "p_RXPH_MONITOR_SEL":0, - "p_RX_XCLK_SEL":"RXREC", - "p_RX_DDI_SEL":0, - "p_RX_DEFER_RESET_BUF_EN":"TRUE", - - #CDR Attributes - "p_RXCDR_CFG":rxcdr_cfg, - "p_RXCDR_FR_RESET_ON_EIDLE":0, - "p_RXCDR_HOLD_DURING_EIDLE":0, - "p_RXCDR_PH_RESET_ON_EIDLE":0, - "p_RXCDR_LOCK_CFG":0b010101, - - # RX Initialization and Reset Attributes - "p_RXCDRFREQRESET_TIME":1, - "p_RXCDRPHRESET_TIME":1, - "p_RXISCANRESET_TIME":1, - "p_RXPCSRESET_TIME":1, - "p_RXPMARESET_TIME":3, - - # RX OOB Signaling Attributes - "p_RXOOB_CFG":0b0000110, - - # RX Gearbox Attributes - "p_RXGEARBOX_EN":"FALSE", - "p_GEARBOX_MODE":0, - - # PRBS Detection Attribute - "p_RXPRBS_ERR_LOOPBACK":0, - - # Power-Down Attributes - "p_PD_TRANS_TIME_FROM_P2":0x03c, - "p_PD_TRANS_TIME_NONE_P2":0x3c, - "p_PD_TRANS_TIME_TO_P2":0x64, - - # RX OOB Signaling Attributes - "p_SAS_MAX_COM":64, - "p_SAS_MIN_COM":36, - "p_SATA_BURST_SEQ_LEN":0b0101, - "p_SATA_BURST_VAL":0b100, - "p_SATA_EIDLE_VAL":0b100, - "p_SATA_MAX_BURST":8, - "p_SATA_MAX_INIT":21, - "p_SATA_MAX_WAKE":7, - "p_SATA_MIN_BURST":4, - "p_SATA_MIN_INIT":12, - "p_SATA_MIN_WAKE":4, - - # RX Fabric Clock Output Control Attributes - "p_TRANS_TIME_RATE":0x0e, - - # TX Buffer Attributes - "p_TXBUF_EN":"TRUE", - "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", - - # FPGA TX Interface Attributes - "p_TX_DATA_WIDTH":20, - - # TX Configurable Driver Attributes - "p_TX_DEEMPH0":0, - "p_TX_DEEMPH1":0, - "p_TX_EIDLE_ASSERT_DELAY":0b110, - "p_TX_EIDLE_DEASSERT_DELAY":0b100, - "p_TX_LOOPBACK_DRIVE_HIZ":"FALSE", - "p_TX_MAINCURSOR_SEL":0, - "p_TX_DRIVE_MODE":"DIRECT", - "p_TX_MARGIN_FULL_0":0b1001110, - "p_TX_MARGIN_FULL_1":0b1001001, - "p_TX_MARGIN_FULL_2":0b1000101, - "p_TX_MARGIN_FULL_3":0b1000010, - "p_TX_MARGIN_FULL_4":0b1000000, - "p_TX_MARGIN_LOW_0":0b1000110, - "p_TX_MARGIN_LOW_1":0b1000100, - "p_TX_MARGIN_LOW_2":0b1000010, - "p_TX_MARGIN_LOW_3":0b1000000, - "p_TX_MARGIN_LOW_4":0b1000000, - - # TX Gearbox Attributes - "p_TXGEARBOX_EN":"FALSE", - - # TX Initialization and Reset Attributes - "p_TXPCSRESET_TIME":1, - "p_TXPMARESET_TIME":1, - - # TX Receiver Detection Attributes - "p_TX_RXDETECT_CFG":0x1832, - "p_TX_RXDETECT_REF":0b100, - - # CPLL Attributes - "p_CPLL_CFG":0xBC07DC, - "p_CPLL_FBDIV":4, - "p_CPLL_FBDIV_45":5, - "p_CPLL_INIT_CFG":0x00001e, - "p_CPLL_LOCK_CFG":0x01e8, - "p_CPLL_REFCLK_DIV":1, - "p_RXOUT_DIV":rxout_div, - "p_TXOUT_DIV":txout_div, - "p_SATA_CPLL_CFG":"VCO_3000MHZ", - - # RX Initialization and Reset Attributes - "p_RXDFELPMRESET_TIME":0b0001111, - - # RX Equalizer Attributes - "p_RXLPM_HF_CFG":0b00000011110000, - "p_RXLPM_LF_CFG":0b00000011110000, - "p_RX_DFE_GAIN_CFG":0x020fea, - "p_RX_DFE_H2_CFG":0b000000000000, - "p_RX_DFE_H3_CFG":0b000001000000, - "p_RX_DFE_H4_CFG":0b00011110000, - "p_RX_DFE_H5_CFG":0b00011100000, - "p_RX_DFE_KL_CFG":0b0000011111110, - "p_RX_DFE_LPM_CFG":0x0954, - "p_RX_DFE_LPM_HOLD_DURING_EIDLE":0, - "p_RX_DFE_UT_CFG":0b10001111000000000, - "p_RX_DFE_VP_CFG":0b00011111100000011, - - # Power-Down Attributes - "p_RX_CLKMUX_PD":1, - "p_TX_CLKMUX_PD":1, - - # FPGA RX Interface Attribute - "p_RX_INT_DATAWIDTH":0, - - # FPGA TX Interface Attribute - "p_TX_INT_DATAWIDTH":0, - - # TX Configurable Driver Attributes - "p_TX_QPI_STATUS_EN":0, - - # RX Equalizer Attributes - "p_RX_DFE_KL_CFG2":0b00110011000100000001100000001100, - "p_RX_DFE_XYD_CFG":0b0000000000000, - - # TX Configurable Driver Attributes - "p_TX_PREDRIVER_MODE":0, - } - - self.specials += \ - Instance("GTXE2_CHANNEL", - # CPLL Ports - #o_CPLLFBCLKLOST=, - o_CPLLLOCK=self.cplllock, - i_CPLLLOCKDETCLK=0, - i_CPLLLOCKEN=1, - i_CPLLPD=0, - #o_CPLLREFCLKLOST=0, - i_CPLLREFCLKSEL=0b001, - i_CPLLRESET=self.cpllreset, - i_GTRSVD=0, - i_PCSRSVDIN=0, - i_PCSRSVDIN2=0, - i_PMARSVDIN=0, - i_PMARSVDIN2=0, - i_TSTIN=ones(20), - #o_TSTOUT=, - - # Channel - i_CLKRSVD=0, - - # Channel - Clocking Ports - i_GTGREFCLK=0, - i_GTNORTHREFCLK0=0, - i_GTNORTHREFCLK1=0, - i_GTREFCLK0=self.gtrefclk0, - i_GTREFCLK1=0, - i_GTSOUTHREFCLK0=0, - i_GTSOUTHREFCLK1=0, - - # Channel - DRP Ports - i_DRPADDR=0, - i_DRPCLK=0, - i_DRPDI=0, - #o_DRPDO=, - i_DRPEN=0, - #o_DRPRDY=, - i_DRPWE=0, - - # Clocking Ports - #o_GTREFCLKMONITOR=, - i_QPLLCLK=self.qpllclk, - i_QPLLREFCLK=self.qpllrefclk, - i_RXSYSCLKSEL=0b00, - i_TXSYSCLKSEL=0b00, - - # Digital Monitor Ports - #o_DMONITOROUT=, - - # FPGA TX Interface Datapath Configuration - i_TX8B10BEN=1, - - # Loopback Ports - i_LOOPBACK=0, - - # PCI Express Ports - #o_PHYSTATUS=, - i_RXRATE=0, - #o_RXVALID=, - - # Power-Down Ports - i_RXPD=0b00, - i_TXPD=0b00, - - # RX 8B/10B Decoder Ports - i_SETERRSTATUS=0, - - # RX Initialization and Reset Ports - i_EYESCANRESET=0, - i_RXUSERRDY=rxuserrdy, - - # RX Margin Analysis Ports - #o_EYESCANDATAERROR=, - i_EYESCANMODE=0, - i_EYESCANTRIGGER=0, - - # Receive Ports - CDR Ports - i_RXCDRFREQRESET=0, - i_RXCDRHOLD=0, - o_RXCDRLOCK=rxcdrlock, - i_RXCDROVRDEN=0, - i_RXCDRRESET=0, - i_RXCDRRESETRSV=0, - - # Receive Ports - Clock Correction Ports - #o_RXCLKCORCNT=, - - # Receive Ports - FPGA RX Interface Datapath Configuration - i_RX8B10BEN=1, - - # Receive Ports - FPGA RX Interface Ports - i_RXUSRCLK=self.rxusrclk, - i_RXUSRCLK2=self.rxusrclk2, - - # Receive Ports - FPGA RX interface Ports - o_RXDATA=self.rxdata, - - # Receive Ports - Pattern Checker Ports - #o_RXPRBSERR=, - i_RXPRBSSEL=0, - - # Receive Ports - Pattern Checker ports - i_RXPRBSCNTRESET=0, - - # Receive Ports - RX Equalizer Ports - i_RXDFEXYDEN=0, - i_RXDFEXYDHOLD=0, - i_RXDFEXYDOVRDEN=0, - - # Receive Ports - RX 8B/10B Decoder Ports - #o_RXDISPERR=, - #o_RXNOTINTABLE=, - - # Receive Ports - RX AFE - i_GTXRXP=pads.rxp, - i_GTXRXN=pads.rxn, - - # Receive Ports - RX Buffer Bypass Ports - i_RXBUFRESET=0, - #o_RXBUFSTATUS=, - i_RXDDIEN=0, - i_RXDLYBYPASS=1, - i_RXDLYEN=0, - i_RXDLYOVRDEN=0, - i_RXDLYSRESET=0, - #o_RXDLYSRESETDONE=0, - i_RXPHALIGN=0, - #o_RXPHALIGNDONE=, - i_RXPHALIGNEN=0, - i_RXPHDLYPD=0, - i_RXPHDLYRESET=0, - #o_RXPHMONITOR=, - i_RXPHOVRDEN=0, - #o_RXPHSLIPMONITOR=, - #o_RXSTATUS=, - - # Receive Ports - RX Byte and Word Alignment Ports - o_RXBYTEISALIGNED=self.rxbyteisaligned, - #o_RXBYTEREALIGN=, - #o_RXCOMMADET=, - i_RXCOMMADETEN=1, - i_RXMCOMMAALIGNEN=1, - i_RXPCOMMAALIGNEN=1, - - # Receive Ports - RX Channel Bonding Ports - #o_RXCHANBONDSEQ=, - i_RXCHBONDEN=0, - i_RXCHBONDLEVEL=0, - i_RXCHBONDMASTER=0, - #o_RXCHBONDO=, - i_RXCHBONDSLAVE=0, - - # Receive Ports - RX Channel Bonding Ports - #o_RXCHANISALIGNED=, - #o_RXCHANREALIGN=, - - # Receive Ports - RX Equalizer Ports - i_RXDFEAGCHOLD=0, - i_RXDFEAGCOVRDEN=0, - i_RXDFECM1EN=0, - i_RXDFELFHOLD=0, - i_RXDFELFOVRDEN=1, - i_RXDFELPMRESET=0, - i_RXDFETAP2HOLD=0, - i_RXDFETAP2OVRDEN=0, - i_RXDFETAP3HOLD=0, - i_RXDFETAP3OVRDEN=0, - i_RXDFETAP4HOLD=0, - i_RXDFETAP4OVRDEN=0, - i_RXDFETAP5HOLD=0, - i_RXDFETAP5OVRDEN=0, - i_RXDFEUTHOLD=0, - i_RXDFEUTOVRDEN=0, - i_RXDFEVPHOLD=0, - i_RXDFEVPOVRDEN=0, - i_RXDFEVSEN=0, - i_RXLPMLFKLOVRDEN=0, - #o_RXMONITOROUT=, - i_RXMONITORSEL=0b00, - i_RXOSHOLD=0, - i_RXOSOVRDEN=0, - - # Receive Ports - RX Equilizer Ports - i_RXLPMHFHOLD=0, - i_RXLPMHFOVRDEN=0, - i_RXLPMLFHOLD=0, - - # Receive Ports - RX Fabric ClocK Output Control Ports - #o_RXRATEDONE=, - - # Receive Ports - RX Fabric Output Control Ports - o_RXOUTCLK=self.rxoutclk, - #o_RXOUTCLKFABRIC=, - #o_RXOUTCLKPCS=, - i_RXOUTCLKSEL=0b010, - - # Receive Ports - RX Gearbox Ports - #o_RXDATAVALID=, - #o_RXHEADER=, - #o_RXHEADERVALID=, - #o_RXSTARTOFSEQ=, - - # Receive Ports - RX Gearbox Ports - i_RXGEARBOXSLIP=0, - - # Receive Ports - RX Initialization and Reset Ports - i_GTRXRESET=self.gtrxreset, - i_RXOOBRESET=0, - i_RXPCSRESET=0, - i_RXPMARESET=self.pmarxreset, - - # Receive Ports - RX Margin Analysis ports - i_RXLPMEN=0, - - # Receive Ports - RX OOB Signaling ports - #o_RXCOMSASDET=, - o_RXCOMWAKEDET=rxcomwakedet, - - # Receive Ports - RX OOB Signaling ports - o_RXCOMINITDET=rxcominitdet, - - # Receive Ports - RX OOB signalling Ports - o_RXELECIDLE=rxelecidle, - i_RXELECIDLEMODE=0b00, - - # Receive Ports - RX Polarity Control Ports - i_RXPOLARITY=0, - - # Receive Ports - RX gearbox ports - i_RXSLIDE=0, - - # Receive Ports - RX8B/10B Decoder Ports - #o_RXCHARISCOMMA=, - o_RXCHARISK=self.rxcharisk, - - # Receive Ports - Rx Channel Bonding Ports - i_RXCHBONDI=0, - - # Receive Ports -RX Initialization and Reset Ports - o_RXRESETDONE=rxresetdone, - - # Rx AFE Ports - i_RXQPIEN=0, - #o_RXQPISENN=, - #o_RXQPISENP=, - - # TX Buffer Bypass Ports - i_TXPHDLYTSTCLK=0, - - # TX Configurable Driver Ports - i_TXPOSTCURSOR=0, - i_TXPOSTCURSORINV=0, - i_TXPRECURSOR=0, - i_TXPRECURSORINV=0, - i_TXQPIBIASEN=0, - i_TXQPISTRONGPDOWN=0, - i_TXQPIWEAKPUP=0, - - # TX Initialization and Reset Ports - i_CFGRESET=0, - i_GTTXRESET=self.gttxreset, - #o_PCSRSVDOUT=, - i_TXUSERRDY=txuserrdy, - - # Transceiver Reset Mode Operation - i_GTRESETSEL=0, - i_RESETOVRD=0, - - # Transmit Ports - 8b10b Encoder Control Ports - i_TXCHARDISPMODE=0, - i_TXCHARDISPVAL=0, - - # Transmit Ports - FPGA TX Interface Ports - i_TXUSRCLK=self.txusrclk, - i_TXUSRCLK2=self.txusrclk2, - - # Transmit Ports - PCI Express Ports - i_TXELECIDLE=txelecidle, - i_TXMARGIN=0, - i_TXRATE=txrate, - i_TXSWING=0, - - # Transmit Ports - Pattern Generator Ports - i_TXPRBSFORCEERR=0, - - # Transmit Ports - TX Buffer Bypass Ports - i_TXDLYBYPASS=1, - i_TXDLYEN=0, - i_TXDLYHOLD=0, - i_TXDLYOVRDEN=0, - i_TXDLYSRESET=0, - #o_TXDLYSRESETDONE=, - i_TXDLYUPDOWN=0, - i_TXPHALIGN=0, - #o_TXPHALIGNDONE=txphaligndone, - i_TXPHALIGNEN=0, - i_TXPHDLYPD=0, - i_TXPHDLYRESET=0, - i_TXPHINIT=0, - #o_TXPHINITDONE=, - i_TXPHOVRDEN=0, - - # Transmit Ports - TX Buffer Ports - #o_TXBUFSTATUS=, - - # Transmit Ports - TX Configurable Driver Ports - i_TXBUFDIFFCTRL=0b100, - i_TXDEEMPH=0, - i_TXDIFFCTRL=0b1000, - i_TXDIFFPD=0, - i_TXINHIBIT=0, - i_TXMAINCURSOR=0, - i_TXPISOPD=0, - - # Transmit Ports - TX Data Path interface - i_TXDATA=self.txdata, - - # Transmit Ports - TX Driver and OOB signaling - o_GTXTXP=pads.txp, - o_GTXTXN=pads.txn, - - # Transmit Ports - TX Fabric Clock Output Control Ports - o_TXOUTCLK=self.txoutclk, - #o_TXOUTCLKFABRIC=, - #o_TXOUTCLKPCS=, - i_TXOUTCLKSEL=0b11, #?? - #o_TXRATEDONE=, - # Transmit Ports - TX Gearbox Ports - i_TXCHARISK=self.txcharisk, - #o_TXGEARBOXREADY=, - i_TXHEADER=0, - i_TXSEQUENCE=0, - i_TXSTARTSEQ=0, - - # Transmit Ports - TX Initialization and Reset Ports - i_TXPCSRESET=0, - i_TXPMARESET=0, - o_TXRESETDONE=txresetdone, - - # Transmit Ports - TX OOB signalling Ports - o_TXCOMFINISH=txcomfinish, - i_TXCOMINIT=txcominit, - i_TXCOMSAS=0, - i_TXCOMWAKE=txcomwake, - i_TXPDELECIDLEMODE=0, - - # Transmit Ports - TX Polarity Control Ports - i_TXPOLARITY=0, - - # Transmit Ports - TX Receiver Detection Ports - i_TXDETECTRX=0, - - # Transmit Ports - TX8b/10b Encoder Ports - i_TX8B10BBYPASS=0, - - # Transmit Ports - pattern Generator Ports - i_TXPRBSSEL=0, - - # Tx Configurable Driver Ports - #o_TXQPISENN=, - #o_TXQPISENP=, - - **gtxe2_channel_parameters - ) - - -class GTXE2_COMMON(Module): - def __init__(self, fbdiv=16): - self.refclk0 = Signal() - - self.qpllclk = Signal() - self.qpllrefclk = Signal() - - # fbdiv config - fbdiv_in_config = { - 16 : 0b0000100000, - 20 : 0b0000110000, - 32 : 0b0001100000, - 40 : 0b0010000000, - 64 : 0b0011100000, - 66 : 0b0101000000, - 80 : 0b0100100000, - 100 : 0b0101110000 - } - fbdiv_in = fbdiv_in_config[fbdiv] - - fbdiv_ratio_config = { - 16 : 0b1, - 20 : 0b1, - 32 : 0b1, - 40 : 0b1, - 64 : 0b1, - 66 : 0b0, - 80 : 0b1, - 100 : 0b1 - } - fbdiv_ratio = fbdiv_ratio_config[fbdiv] - - self.specials += \ - Instance("GTXE2_COMMON", - # Simulation attributes - p_SIM_RESET_SPEEDUP="TRUE", - p_SIM_QPLLREFCLK_SEL=0b001, - p_SIM_VERSION="4.0", - - # Common block attributes - p_BIAS_CFG=0x0000040000001000, - p_COMMON_CFG=0, - p_QPLL_CFG=0x06801c1, - p_QPLL_CLKOUT_CFG=0, - p_QPLL_COARSE_FREQ_OVRD=0b010000, - p_QPLL_COARSE_FREQ_OVRD_EN=0, - p_QPLL_CP=0b0000011111, - p_QPLL_CP_MONITOR_EN=0, - p_QPLL_DMONITOR_SEL=0, - p_QPLL_FBDIV=fbdiv_in, - p_QPLL_FBDIV_MONITOR_EN=0, - p_QPLL_FBDIV_RATIO=fbdiv_ratio, - p_QPLL_INIT_CFG=0x000006, - p_QPLL_LOCK_CFG=0x21e9, - p_QPLL_LPF=0b1111, - p_QPLL_REFCLK_DIV=1, - - # Common block - Dynamic Reconfiguration Port (DRP) - i_DRPADDR=0, - i_DRPCLK=0, - i_DRPDI=0, - #o_DRPDO=, - i_DRPEN=0, - #o_DRPRDY=, - i_DRPWE=0, - - # Common block - Ref Clock Ports - i_GTGREFCLK=0, - i_GTNORTHREFCLK0=0, - i_GTNORTHREFCLK1=0, - i_GTREFCLK0=self.refclk0, - i_GTREFCLK1=0, - i_GTSOUTHREFCLK0=0, - i_GTSOUTHREFCLK1=0, - - # Common block - QPLL Ports - #o_QPLLDMONITOR=, - #o_QPLLFBCLKLOST=, - #o_QPLLLOCK=, - i_QPLLLOCKDETCLK=0, - i_QPLLLOCKEN=1, - o_QPLLOUTCLK=self.qpllclk, - o_QPLLOUTREFCLK=self.qpllrefclk, - i_QPLLOUTRESET=0, - i_QPLLPD=0, - #o_QPLLREFCLKLOST=, - i_QPLLREFCLKSEL=0b001, - i_QPLLRESET=0, - i_QPLLRSVD1=0, - i_QPLLRSVD2=ones(5), - #o_REFCLKOUTMONITOR=, - - # Common block Ports - i_BGBYPASSB=1, - i_BGMONITORENB=1, - i_BGPDB=1, - i_BGRCALOVRD=0, - i_PMARSVD=0, - i_RCALENB=1 - ) diff --git a/lib/sata/k7sataphy/std.py b/lib/sata/k7sataphy/std.py deleted file mode 100644 index 5a218990..00000000 --- a/lib/sata/k7sataphy/std.py +++ /dev/null @@ -1,8 +0,0 @@ -from migen.fhdl.std import * -from migen.genlib.record import * - -ALIGN_VAL = 0x7B4A4ABC -SYNC_VAL = 0xB5B5957C - -def ones(width): - return 2**width-1 diff --git a/lib/sata/link/.keep_me b/lib/sata/link/.keep_me new file mode 100644 index 00000000..e69de29b diff --git a/lib/sata/phy/k7sataphy/__init__.py b/lib/sata/phy/k7sataphy/__init__.py new file mode 100644 index 00000000..ba4ef1b4 --- /dev/null +++ b/lib/sata/phy/k7sataphy/__init__.py @@ -0,0 +1,23 @@ +from migen.fhdl.std import * + +from lib.sata.k7sataphy.std import * +from lib.sata.k7sataphy.gtx import K7SATAPHYGTX +from lib.sata.k7sataphy.crg import K7SATAPHYCRG +from lib.sata.k7sataphy.ctrl import K7SATAPHYHostCtrl, K7SATAPHYDeviceCtrl +from lib.sata.k7sataphy.datapath import K7SATAPHYDatapath + +class K7SATAPHY(Module): + def __init__(self, pads, clk_freq, host=True, default_speed="SATA1"): + # GTX + self.submodules.gtx = K7SATAPHYGTX(pads, default_speed) + + # CRG / CTRL + self.submodules.crg = K7SATAPHYCRG(pads, self.gtx, clk_freq, default_speed) + if host: + self.submodules.ctrl = K7SATAPHYHostCtrl(self.gtx, self.crg, clk_freq) + else: + self.submodules.ctrl = K7SATAPHYDeviceCtrl(self.gtx, self.crg, clk_freq) + + # DATAPATH + self.submodules.datapath = K7SATAPHYDatapath(self.gtx, self.ctrl) + self.sink, self.source = self.datapath.sink, self.datapath.source diff --git a/lib/sata/phy/k7sataphy/crg.py b/lib/sata/phy/k7sataphy/crg.py new file mode 100644 index 00000000..93ac490a --- /dev/null +++ b/lib/sata/phy/k7sataphy/crg.py @@ -0,0 +1,172 @@ +from math import ceil + +from migen.fhdl.std import * +from migen.genlib.resetsync import AsyncResetSynchronizer +from migen.genlib.fsm import FSM, NextState + +from lib.sata.k7sataphy.std import * +from lib.sata.k7sataphy.gtx import GTXE2_COMMON + +class K7SATAPHYCRG(Module): + def __init__(self, pads, gtx, clk_freq, default_speed): + self.reset = Signal() + self.ready = Signal() + + self.clock_domains.cd_sata_tx = ClockDomain() + self.clock_domains.cd_sata_rx = ClockDomain() + + # CPLL + # (SATA3) 150MHz / VCO @ 3GHz / Line rate @ 6Gbps + # (SATA2 & SATA1) VCO still @ 3 GHz, Line rate is decreased with output dividers. + refclk = Signal() + self.specials += Instance("IBUFDS_GTE2", + i_CEB=0, + i_I=pads.refclk_p, + i_IB=pads.refclk_n, + o_O=refclk + ) + self.comb += gtx.gtrefclk0.eq(refclk) + + # QPLL + # not used but need to be there... see AR43339... + gtx_common = GTXE2_COMMON() + self.comb += [ + gtx_common.refclk0.eq(refclk), + gtx.qpllclk.eq(gtx_common.qpllclk), + gtx.qpllrefclk.eq(gtx_common.qpllrefclk), + ] + self.submodules += gtx_common + + # TX clocking + # (SATA3) 150MHz from CPLL TXOUTCLK, sata_tx clk @ 300MHz (16-bits) + # (SATA2) 150MHz from CPLL TXOUTCLK, sata_tx clk @ 150MHz (16-bits) + # (SATA1) 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 = { + "SATA1" : 16.0, + "SATA2" : 8.0, + "SATA3" : 4.0 + } + mmcm_div = mmcm_div_config[default_speed] + self.specials += [ + 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, + + # DRP + i_DCLK=0, i_DEN=0, i_DWE=0, #o_DRDY=, + i_DADDR=0, i_DI=0, #o_DO=, + + # 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=1, + i_CLKIN1=mmcm_clk_i, i_CLKFBIN=mmcm_fb, o_CLKFBOUT=mmcm_fb, + + # CLK0 + p_CLKOUT0_DIVIDE_F=mmcm_div, p_CLKOUT0_PHASE=0.000, o_CLKOUT0=mmcm_clk0_o, + ), + Instance("BUFG", i_I=mmcm_clk0_o, o_O=self.cd_sata_tx.clk), + ] + self.comb += [ + gtx.txusrclk.eq(self.cd_sata_tx.clk), + gtx.txusrclk2.eq(self.cd_sata_tx.clk) + ] + + # RX clocking + # (SATA3) sata_rx recovered clk @ 300MHz from GTX RXOUTCLK + # (SATA2) sata_rx recovered clk @ 150MHz from GTX RXOUTCLK + # (SATA1) sata_rx recovered clk @ 150MHz from GTX RXOUTCLK + self.specials += [ + Instance("BUFG", i_I=gtx.rxoutclk, o_O=self.cd_sata_rx.clk), + ] + self.comb += [ + gtx.rxusrclk.eq(self.cd_sata_rx.clk), + 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 = 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) + ) + 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"), + ) + ) + tx_reset_fsm.act("RESET_GTX", + gtx.gttxreset.eq(1), + If(gtx.cplllock & mmcm_locked, + NextState("RELEASE_GTX") + ) + ) + tx_reset_fsm.act("RELEASE_GTX", + gtx.txuserrdy.eq(1), + If(gtx.txresetdone, + NextState("READY") + ) + ) + tx_reset_fsm.act("READY", + gtx.txuserrdy.eq(1) + ) + + # 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) + + 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") + ) + ) + rx_reset_fsm.act("READY", + gtx.rxuserrdy.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) + + # Reset MMCM + self.comb += mmcm_reset.eq(ResetSignal() | self.reset | ~gtx.cplllock) + + # 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), + ] diff --git a/lib/sata/phy/k7sataphy/ctrl.py b/lib/sata/phy/k7sataphy/ctrl.py new file mode 100644 index 00000000..c4ffb463 --- /dev/null +++ b/lib/sata/phy/k7sataphy/ctrl.py @@ -0,0 +1,302 @@ +from math import ceil + +from migen.fhdl.std import * +from migen.genlib.resetsync import AsyncResetSynchronizer +from migen.genlib.fsm import FSM, NextState +from migen.flow.actor import Sink, Source + +from lib.sata.k7sataphy.std import * + +def us(t, clk_freq): + clk_period_us = 1000000/clk_freq + return ceil(t/clk_period_us) + +class K7SATAPHYHostCtrl(Module): + def __init__(self, gtx, crg, clk_freq): + self.ready = Signal() + + self.sink = Sink([("data", 32), ("charisk", 4)]) + self.source = Source([("data", 32), ("charisk", 4)]) + + self.align_detect = align_detect = Signal() + align_timeout_cnt = Signal(32) + align_timeout = Signal() + + retry_timeout_cnt = Signal(32) + retry_timeout = Signal() + + non_align_cnt = Signal(4) + + txcominit = Signal() + txcomwake = Signal() + + self.comb += [ + self.source.stb.eq(1), + self.sink.ack.eq(1) + ] + + fsm = FSM(reset_state="RESET") + self.submodules += fsm + + fsm.act("RESET", + gtx.txelecidle.eq(1), + If(crg.ready, + NextState("COMINIT") + ), + ) + fsm.act("COMINIT", + gtx.txelecidle.eq(1), + txcominit.eq(1), + If(gtx.txcomfinish & ~gtx.rxcominitdet, + NextState("AWAIT_COMINIT") + ), + ) + fsm.act("AWAIT_COMINIT", + gtx.txelecidle.eq(1), + If(gtx.rxcominitdet, + NextState("AWAIT_NO_COMINIT") + ).Else( + If(retry_timeout, + NextState("RESET") + ) + ), + ) + fsm.act("AWAIT_NO_COMINIT", + gtx.txelecidle.eq(1), + If(~gtx.rxcominitdet, + NextState("CALIBRATE") + ), + ) + fsm.act("CALIBRATE", + gtx.txelecidle.eq(1), + NextState("COMWAKE"), + ) + fsm.act("COMWAKE", + gtx.txelecidle.eq(1), + txcomwake.eq(1), + If(gtx.txcomfinish, + NextState("AWAIT_COMWAKE") + ), + ) + fsm.act("AWAIT_COMWAKE", + gtx.txelecidle.eq(1), + If(gtx.rxcomwakedet, + NextState("AWAIT_NO_COMWAKE") + ).Else( + If(retry_timeout, + NextState("RESET") + ) + ), + ) + fsm.act("AWAIT_NO_COMWAKE", + gtx.txelecidle.eq(1), + If(~gtx.rxcomwakedet, + NextState("AWAIT_NO_RXELECIDLE") + ), + ) + fsm.act("AWAIT_NO_RXELECIDLE", + gtx.txelecidle.eq(0), + self.source.data.eq(0x4A4A4A4A), #D10.2 + self.source.charisk.eq(0b0000), + If(~gtx.rxelecidle, + NextState("AWAIT_ALIGN"), + crg.reset.eq(1), + gtx.pmarxreset.eq(1) + ), + ) + fsm.act("AWAIT_ALIGN", + gtx.txelecidle.eq(0), + self.source.data.eq(0x4A4A4A4A), #D10.2 + self.source.charisk.eq(0b0000), + gtx.rxalign.eq(1), + If((align_detect & ~gtx.rxelecidle) & ~align_timeout, + NextState("SEND_ALIGN") + ).Elif(~align_detect & align_timeout, + NextState("RESET") + ), + ) + fsm.act("SEND_ALIGN", + gtx.txelecidle.eq(0), + self.source.data.eq(ALIGN_VAL), + self.source.charisk.eq(0b0001), + If(non_align_cnt == 3, + NextState("READY") + ), + ) + fsm.act("READY", + gtx.txelecidle.eq(0), + self.source.data.eq(SYNC_VAL), + self.source.charisk.eq(0b0001), + self.ready.eq(1), + ) + + txcominit_d = Signal() + txcomwake_d = Signal() + self.sync += [ + txcominit_d.eq(txcominit), + txcomwake_d.eq(txcomwake), + gtx.txcominit.eq(txcominit & ~txcominit_d), + gtx.txcomwake.eq(txcomwake & ~txcomwake_d), + ] + + self.comb += align_detect.eq(self.sink.stb & (self.sink.data == ALIGN_VAL)); + self.sync += \ + If(fsm.ongoing("RESET"), + align_timeout_cnt.eq(us(873, clk_freq)) + ).Elif(fsm.ongoing("AWAIT_ALIGN"), + align_timeout_cnt.eq(align_timeout_cnt-1) + ) + self.comb += align_timeout.eq(align_timeout_cnt == 0) + + self.sync += \ + If(fsm.ongoing("RESET") | fsm.ongoing("AWAIT_NO_COMINIT"), + retry_timeout_cnt.eq(us(10000, clk_freq)) + ).Elif(fsm.ongoing("AWAIT_COMINIT") | fsm.ongoing("AWAIT_COMWAKE"), + retry_timeout_cnt.eq(retry_timeout_cnt-1) + ) + self.comb += retry_timeout.eq(retry_timeout_cnt == 0) + + self.sync += \ + If(fsm.ongoing("SEND_ALIGN"), + If(self.sink.stb, + If(self.sink.data[0:8] == 0x7C, + non_align_cnt.eq(non_align_cnt + 1) + ).Else( + non_align_cnt.eq(0) + ) + ) + ) + +class K7SATAPHYDeviceCtrl(Module): + def __init__(self, gtx, crg, clk_freq): + self.ready = Signal() + + self.sink = Sink([("data", 32), ("charisk", 4)]) + self.source = Source([("data", 32), ("charisk", 4)]) + + align_detect = Signal() + align_timeout = Signal() + align_timeout_cnt = Signal(32) + + retry_timeout_cnt = Signal(32) + retry_timeout = Signal() + + txcominit = Signal() + txcomwake = Signal() + + self.comb += [ + self.source.stb.eq(1), + self.sink.ack.eq(1) + ] + + fsm = FSM(reset_state="RESET") + self.submodules += fsm + + fsm.act("RESET", + gtx.txelecidle.eq(1), + If(crg.ready, + NextState("AWAIT_COMINIT") + ) + ) + fsm.act("AWAIT_COMINIT", + gtx.txelecidle.eq(1), + If(gtx.rxcominitdet, + NextState("AWAIT_NO_COMINIT") + ) + ) + fsm.act("AWAIT_NO_COMINIT", + gtx.txelecidle.eq(1), + If(~gtx.rxcominitdet, + NextState("COMINIT") + ) + ) + fsm.act("COMINIT", + gtx.txelecidle.eq(1), + txcominit.eq(1), + If(gtx.txcomfinish, + NextState("AWAIT_COMWAKE") + ) + ) + fsm.act("AWAIT_COMWAKE", + gtx.txelecidle.eq(1), + If(gtx.rxcomwakedet, + NextState("AWAIT_NO_COMWAKE") + ).Else( + If(retry_timeout, + NextState("RESET") + ) + ) + ) + fsm.act("AWAIT_NO_COMWAKE", + gtx.txelecidle.eq(1), + If(~gtx.rxcomwakedet, + NextState("CALIBRATE") + ) + ) + fsm.act("CALIBRATE", + gtx.txelecidle.eq(1), + NextState("COMWAKE") + ) + fsm.act("COMWAKE", + gtx.txelecidle.eq(1), + txcomwake.eq(1), + If(gtx.txcomfinish, + NextState("RESET_CRG"), + crg.reset.eq(1), + ) + ) + fsm.act("RESET_CRG", + gtx.txelecidle.eq(0), + If(crg.ready, + NextState("SEND_ALIGN") + ) + ) + fsm.act("SEND_ALIGN", + gtx.txelecidle.eq(0), + gtx.rxalign.eq(1), + self.source.data.eq(ALIGN_VAL), + self.source.charisk.eq(0b0001), + If(align_detect, + NextState("READY") + ).Elif(align_timeout, + NextState("ERROR") + ) + ) + fsm.act("READY", + gtx.txelecidle.eq(0), + NextState("READY"), + If(gtx.rxelecidle, + NextState("RESET") + ), + self.ready.eq(1) + ) + fsm.act("ERROR", + gtx.txelecidle.eq(1), + NextState("RESET") + ) + + txcominit_d = Signal() + txcomwake_d = Signal() + self.sync += [ + txcominit_d.eq(txcominit), + txcomwake_d.eq(txcomwake), + gtx.txcominit.eq(txcominit & ~txcominit_d), + gtx.txcomwake.eq(txcomwake & ~txcomwake_d), + ] + + self.comb += align_detect.eq(self.sink.stb & (self.sink.data == ALIGN_VAL)); + self.sync += \ + If(fsm.ongoing("RESET"), + align_timeout_cnt.eq(us(55, clk_freq)) + ).Elif(fsm.ongoing("AWAIT_ALIGN"), + align_timeout_cnt.eq(align_timeout_cnt-1) + ) + self.comb += align_timeout.eq(align_timeout_cnt == 0) + + self.sync += \ + If(fsm.ongoing("RESET"), + retry_timeout_cnt.eq(us(10000, clk_freq)) + ).Elif(fsm.ongoing("AWAIT_COMWAKE"), + retry_timeout_cnt.eq(retry_timeout_cnt-1) + ) + self.comb += retry_timeout.eq(retry_timeout_cnt == 0) diff --git a/lib/sata/phy/k7sataphy/datapath.py b/lib/sata/phy/k7sataphy/datapath.py new file mode 100644 index 00000000..ef06c09a --- /dev/null +++ b/lib/sata/phy/k7sataphy/datapath.py @@ -0,0 +1,153 @@ +from migen.fhdl.std import * +from migen.genlib.misc import chooser +from migen.actorlib.fifo import AsyncFIFO +from migen.flow.actor import Sink, Source + +from lib.sata.k7sataphy.std import * + +class K7SATAPHYDatapathRX(Module): + def __init__(self): + self.sink = Sink([("data", 16), ("charisk", 2)]) + self.source = Source([("data", 32), ("charisk", 4)]) + + ### + + # bytes alignment + + # shift register + data_sr = Signal(32+8) + charisk_sr = Signal(4+1) + data_sr_d = Signal(32+8) + charisk_sr_d = Signal(4+1) + self.comb += [ + data_sr.eq(Cat(self.sink.data, data_sr_d)), + charisk_sr.eq(Cat(self.sink.charisk, charisk_sr_d)) + ] + self.sync.sata_rx += [ + data_sr_d.eq(data_sr), + charisk_sr_d.eq(charisk_sr) + ] + + # alignment + alignment = Signal() + valid = Signal() + self.sync.sata_rx += [ + If(self.sink.charisk !=0, + alignment.eq(self.sink.charisk[1]), + valid.eq(0) + ).Else( + valid.eq(~valid) + ) + ] + + # 16 to 32 + data = Signal(32) + charisk = Signal(4) + self.comb += [ + If(~alignment, + data.eq(data_sr[0:32]), + charisk.eq(charisk_sr[0:4]) + ).Else( + data.eq(data_sr[8:40]), + charisk.eq(charisk_sr[1:5]) + ) + ] + + # clock domain crossing + # (SATA3) 300MHz sata_rx clk to sys_clk + # (SATA2) 150MHz sata_rx clk to sys_clk + # (SATA1) 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([("data", 32), ("charisk", 4)], 16) + self.submodules.fifo = RenameClockDomains(fifo, {"write": "sata_rx", "read": "sys"}) + self.comb += [ + fifo.sink.stb.eq(valid), + fifo.sink.data.eq(data), + fifo.sink.charisk.eq(charisk), + ] + self.comb += Record.connect(fifo.source, self.source) + +class K7SATAPHYDatapathTX(Module): + def __init__(self): + self.sink = Sink([("data", 32), ("charisk", 4)]) + self.source = Source([("data", 16), ("charisk", 2)]) + + ### + + # clock domain crossing + # (SATA3) sys_clk to 300MHz sata_tx clk + # (SATA2) sys_clk to 150MHz sata_tx clk + # (SATA1) sys_clk to 75MHz sata_tx clk + # requirements: + # source destination is always able to accept data (ack always 1) + fifo = AsyncFIFO([("data", 32), ("charisk", 4)], 16) + self.submodules.fifo = RenameClockDomains(fifo, {"write": "sys", "read": "sata_tx"}) + self.comb += Record.connect(self.sink, fifo.sink) + + # 32 to 16 + mux = Signal() + last = Signal() + self.comb += [ + last.eq(mux == 1), + self.source.stb.eq(fifo.source.stb), + fifo.source.ack.eq(last), + ] + self.sync.sata_tx += [ + If(self.source.stb, + If(last, + mux.eq(0) + ).Else( + mux.eq(mux + 1) + ) + ) + ] + self.comb += [ + chooser(fifo.source.data, mux, self.source.data), + chooser(fifo.source.charisk, mux, self.source.charisk) + ] + +class K7SATAPHYDatapath(Module): + def __init__(self, gtx, ctrl): + self.sink = Sink([("data", 32), ("charisk", 4)]) + self.source = Source([("data", 32), ("charisk", 4)]) + + ### + + # change data width & cross domain crossing + rx = K7SATAPHYDatapathRX() + tx = K7SATAPHYDatapathTX() + self.submodules += rx, tx + self.comb += [ + rx.sink.data.eq(gtx.rxdata), + rx.sink.charisk.eq(gtx.rxcharisk), + + gtx.txdata.eq(tx.source.data), + gtx.txcharisk.eq(tx.source.charisk), + ] + + # user / ctrl mux + self.comb += [ + # user + If(ctrl.ready, + tx.sink.stb.eq(self.sink.stb), + tx.sink.data.eq(self.sink.data), + tx.sink.charisk.eq(self.sink.charisk), + self.sink.ack.eq(tx.sink.ack), + + self.source.stb.eq(rx.source.stb), + self.source.data.eq(rx.source.data), + self.source.charisk.eq(rx.source.charisk), + rx.source.ack.eq(1), + # ctrl + ).Else( + tx.sink.stb.eq(ctrl.source.stb), + tx.sink.data.eq(ctrl.source.data), + tx.sink.charisk.eq(ctrl.source.charisk), + + ctrl.sink.stb.eq(rx.source.stb), + ctrl.sink.data.eq(rx.source.data), + rx.source.ack.eq(1), + ) + ] diff --git a/lib/sata/phy/k7sataphy/gtx.py b/lib/sata/phy/k7sataphy/gtx.py new file mode 100644 index 00000000..982cbb9a --- /dev/null +++ b/lib/sata/phy/k7sataphy/gtx.py @@ -0,0 +1,903 @@ +from migen.fhdl.std import * +from migen.genlib.cdc import * + +from lib.sata.k7sataphy.std import * + +class _PulseSynchronizer(PulseSynchronizer): + def __init__(self, i, idomain, o, odomain): + PulseSynchronizer.__init__(self, idomain, odomain) + self.comb += [ + self.i.eq(i), + o.eq(self.o) + ] + +class K7SATAPHYGTX(Module): + def __init__(self, pads, default_speed): + # Interface + # Channel - Ref Clock Ports + self.gtrefclk0 = Signal() + + # Channel PLL + self.cplllock = Signal() + self.cpllreset = Signal() + + # 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() + self.rxusrclk2 = Signal() + + # Receive Ports - RX Driver,OOB signalling,Coupling and Eq.,CDR + self.rxelecidle = Signal() + + # Receive Ports - RX PLL Ports + self.rxresetdone = Signal() + + # Receive Ports - RX Ports for SATA + self.rxcominitdet = Signal() + self.rxcomwakedet = Signal() + + # Transmit Ports + self.txuserrdy = Signal() + + # Transmit Ports - 8b10b Encoder Control Ports + self.txcharisk = Signal(2) + + # Transmit Ports - TX Data Path interface + self.gttxreset = Signal() + self.txdata = Signal(16) + self.txoutclk = Signal() + self.txusrclk = Signal() + self.txusrclk2 = Signal() + + # Transmit Ports - TX PLL Ports + self.txresetdone = Signal() + + # Transmit Ports - TX Ports for PCI Express + self.txelecidle = Signal(reset=1) + + # Transmit Ports - TX Ports for SATA + self.txcomfinish = Signal() + self.txcominit = Signal() + self.txcomwake = Signal() + self.txrate = Signal(3) + self.rxcdrlock = Signal() + + # Config at startup + div_config = { + "SATA1" : 4, + "SATA2" : 2, + "SATA3" : 1 + } + rxout_div = div_config[default_speed] + txout_div = div_config[default_speed] + + cdr_config = { + "SATA1" : 0x0380008BFF40100008, + "SATA2" : 0x0380008BFF40200008, + "SATA3" : 0X0380008BFF10200010 + } + rxcdr_cfg = cdr_config[default_speed] + + # Internals and clock domain crossing + # sys_clk --> sata_tx clk + txuserrdy = Signal() + txelecidle = Signal(reset=1) + txcominit = Signal() + txcomwake = Signal() + txrate = Signal(3) + + self.specials += [ + MultiReg(self.txuserrdy, txuserrdy, "sata_tx"), + MultiReg(self.txelecidle, txelecidle, "sata_tx"), + MultiReg(self.txrate, txrate, "sata_tx") + ] + self.submodules += [ + _PulseSynchronizer(self.txcominit, "sys", txcominit, "sata_tx"), + _PulseSynchronizer(self.txcomwake, "sys", txcomwake, "sata_tx"), + ] + + # sata_tx clk --> sys clk + txresetdone = Signal() + txcomfinish = Signal() + + self.specials += [ + MultiReg(txresetdone, self.txresetdone, "sys"), + ] + + self.submodules += [ + _PulseSynchronizer(txcomfinish, "sata_tx", self.txcomfinish, "sys"), + ] + + # sys clk --> sata_rx clk + rxuserrdy = Signal() + + self.specials += [ + MultiReg(self.rxuserrdy, rxuserrdy, "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() + + 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) + ) + ] + + self.rxbyteisaligned = Signal() + + # QPLL input clock + self.qpllclk = Signal() + self.qpllrefclk = Signal() + + # Instance + gtxe2_channel_parameters = { + # Simulation-Only Attributes + "p_SIM_RECEIVER_DETECT_PASS":"TRUE", + "p_SIM_TX_EIDLE_DRIVE_LEVEL":"X", + "p_SIM_RESET_SPEEDUP":"TRUE", + "p_SIM_CPLLREFCLK_SEL":0b001, + "p_SIM_VERSION":"4.0", + + # RX Byte and Word Alignment Attributes + "p_ALIGN_COMMA_DOUBLE":"FALSE", + "p_ALIGN_COMMA_ENABLE":ones(10), + "p_ALIGN_COMMA_WORD":2, + "p_ALIGN_MCOMMA_DET":"TRUE", + "p_ALIGN_MCOMMA_VALUE":0b1010000011, + "p_ALIGN_PCOMMA_DET":"TRUE", + "p_ALIGN_PCOMMA_VALUE":0b0101111100, + "p_SHOW_REALIGN_COMMA":"FALSE", + "p_RXSLIDE_AUTO_WAIT":7, + "p_RXSLIDE_MODE":"OFF", + "p_RX_SIG_VALID_DLY":10, + + # RX 8B/10B Decoder Attributes + "p_RX_DISPERR_SEQ_MATCH":"TRUE", + "p_DEC_MCOMMA_DETECT":"TRUE", + "p_DEC_PCOMMA_DETECT":"TRUE", + "p_DEC_VALID_COMMA_ONLY":"TRUE", + + # RX Clock Correction Attributes + "p_CBCC_DATA_SOURCE_SEL":"DECODED", + "p_CLK_COR_SEQ_2_USE":"FALSE", + "p_CLK_COR_KEEP_IDLE":"FALSE", + "p_CLK_COR_MAX_LAT":35, + "p_CLK_COR_MIN_LAT":28, + "p_CLK_COR_PRECEDENCE":"TRUE", + "p_CLK_COR_REPEAT_WAIT":0, + "p_CLK_COR_SEQ_LEN":4, + "p_CLK_COR_SEQ_1_ENABLE":ones(4), + "p_CLK_COR_SEQ_1_1":0b0110111100, + "p_CLK_COR_SEQ_1_2":0b0001001010, + "p_CLK_COR_SEQ_1_3":0b0001001010, + "p_CLK_COR_SEQ_1_4":0b0001111011, + "p_CLK_CORRECT_USE":"FALSE", + "p_CLK_COR_SEQ_2_ENABLE":ones(4), + "p_CLK_COR_SEQ_2_1":0, + "p_CLK_COR_SEQ_2_2":0, + "p_CLK_COR_SEQ_2_3":0, + "p_CLK_COR_SEQ_2_4":0, + + # RX Channel Bonding Attributes + "p_CHAN_BOND_KEEP_ALIGN":"FALSE", + "p_CHAN_BOND_MAX_SKEW":1, + "p_CHAN_BOND_SEQ_LEN":1, + "p_CHAN_BOND_SEQ_1_1":0, + "p_CHAN_BOND_SEQ_1_1":0, + "p_CHAN_BOND_SEQ_1_2":0, + "p_CHAN_BOND_SEQ_1_3":0, + "p_CHAN_BOND_SEQ_1_4":0, + "p_CHAN_BOND_SEQ_1_ENABLE":ones(4), + "p_CHAN_BOND_SEQ_2_1":0, + "p_CHAN_BOND_SEQ_2_2":0, + "p_CHAN_BOND_SEQ_2_3":0, + "p_CHAN_BOND_SEQ_2_4":0, + "p_CHAN_BOND_SEQ_2_ENABLE":ones(4), + "p_CHAN_BOND_SEQ_2_USE":"FALSE", + "p_FTS_DESKEW_SEQ_ENABLE":ones(4), + "p_FTS_LANE_DESKEW_CFG":ones(4), + "p_FTS_LANE_DESKEW_EN":"FALSE", + + # RX Margin Analysis Attributes + "p_ES_CONTROL":0, + "p_ES_ERRDET_EN":"FALSE", + "p_ES_EYE_SCAN_EN":"TRUE", + "p_ES_HORZ_OFFSET":0, + "p_ES_PMA_CFG":0, + "p_ES_PRESCALE":0, + "p_ES_QUALIFIER":0, + "p_ES_QUAL_MASK":0, + "p_ES_SDATA_MASK":0, + "p_ES_VERT_OFFSET":0, + + # FPGA RX Interface Attributes + "p_RX_DATA_WIDTH":20, + + # PMA Attributes + "p_OUTREFCLK_SEL_INV":0b11, + "p_PMA_RSV":0x00018480, + "p_PMA_RSV2":0x2050, + "p_PMA_RSV3":0, + "p_PMA_RSV4":0, + "p_RX_BIAS_CFG":0b100, + "p_DMONITOR_CFG":0xA00, + "p_RX_CM_SEL":0b11, + "p_RX_CM_TRIM":0b010, + "p_RX_DEBUG_CFG":0, + "p_RX_OS_CFG":0b10000000, + "p_TERM_RCAL_CFG":0, + "p_TERM_RCAL_OVRD":0, + "p_TST_RSV":0, + "p_RX_CLK25_DIV":6, + "p_TX_CLK25_DIV":6, + "p_UCODEER_CLR":0, + + # PCI Express Attributes + "p_PCS_PCIE_EN":"FALSE", + + # PCS Attributes + "p_PCS_RSVD_ATTR":0x100, + + # 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_RX_BUFFER_CFG":0, + "p_RXBUF_RESET_ON_CB_CHANGE":"TRUE", + "p_RXBUF_RESET_ON_COMMAALIGN":"FALSE", + "p_RXBUF_RESET_ON_EIDLE":"FALSE", + "p_RXBUF_RESET_ON_RATE_CHANGE":"TRUE", + "p_RXBUFRESET_TIME":1, + "p_RXBUF_THRESH_OVFLW":61, + "p_RXBUF_THRESH_OVRD":"FALSE", + "p_RXBUF_THRESH_UNDFLW":4, + "p_RXDLY_CFG":0x1f, + "p_RXDLY_LCFG":0x30, + "p_RXDLY_TAP_CFG":0, + "p_RXPH_CFG":0, + "p_RXPHDLY_CFG":0x084820, + "p_RXPH_MONITOR_SEL":0, + "p_RX_XCLK_SEL":"RXREC", + "p_RX_DDI_SEL":0, + "p_RX_DEFER_RESET_BUF_EN":"TRUE", + + #CDR Attributes + "p_RXCDR_CFG":rxcdr_cfg, + "p_RXCDR_FR_RESET_ON_EIDLE":0, + "p_RXCDR_HOLD_DURING_EIDLE":0, + "p_RXCDR_PH_RESET_ON_EIDLE":0, + "p_RXCDR_LOCK_CFG":0b010101, + + # RX Initialization and Reset Attributes + "p_RXCDRFREQRESET_TIME":1, + "p_RXCDRPHRESET_TIME":1, + "p_RXISCANRESET_TIME":1, + "p_RXPCSRESET_TIME":1, + "p_RXPMARESET_TIME":3, + + # RX OOB Signaling Attributes + "p_RXOOB_CFG":0b0000110, + + # RX Gearbox Attributes + "p_RXGEARBOX_EN":"FALSE", + "p_GEARBOX_MODE":0, + + # PRBS Detection Attribute + "p_RXPRBS_ERR_LOOPBACK":0, + + # Power-Down Attributes + "p_PD_TRANS_TIME_FROM_P2":0x03c, + "p_PD_TRANS_TIME_NONE_P2":0x3c, + "p_PD_TRANS_TIME_TO_P2":0x64, + + # RX OOB Signaling Attributes + "p_SAS_MAX_COM":64, + "p_SAS_MIN_COM":36, + "p_SATA_BURST_SEQ_LEN":0b0101, + "p_SATA_BURST_VAL":0b100, + "p_SATA_EIDLE_VAL":0b100, + "p_SATA_MAX_BURST":8, + "p_SATA_MAX_INIT":21, + "p_SATA_MAX_WAKE":7, + "p_SATA_MIN_BURST":4, + "p_SATA_MIN_INIT":12, + "p_SATA_MIN_WAKE":4, + + # RX Fabric Clock Output Control Attributes + "p_TRANS_TIME_RATE":0x0e, + + # TX Buffer Attributes + "p_TXBUF_EN":"TRUE", + "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", + + # FPGA TX Interface Attributes + "p_TX_DATA_WIDTH":20, + + # TX Configurable Driver Attributes + "p_TX_DEEMPH0":0, + "p_TX_DEEMPH1":0, + "p_TX_EIDLE_ASSERT_DELAY":0b110, + "p_TX_EIDLE_DEASSERT_DELAY":0b100, + "p_TX_LOOPBACK_DRIVE_HIZ":"FALSE", + "p_TX_MAINCURSOR_SEL":0, + "p_TX_DRIVE_MODE":"DIRECT", + "p_TX_MARGIN_FULL_0":0b1001110, + "p_TX_MARGIN_FULL_1":0b1001001, + "p_TX_MARGIN_FULL_2":0b1000101, + "p_TX_MARGIN_FULL_3":0b1000010, + "p_TX_MARGIN_FULL_4":0b1000000, + "p_TX_MARGIN_LOW_0":0b1000110, + "p_TX_MARGIN_LOW_1":0b1000100, + "p_TX_MARGIN_LOW_2":0b1000010, + "p_TX_MARGIN_LOW_3":0b1000000, + "p_TX_MARGIN_LOW_4":0b1000000, + + # TX Gearbox Attributes + "p_TXGEARBOX_EN":"FALSE", + + # TX Initialization and Reset Attributes + "p_TXPCSRESET_TIME":1, + "p_TXPMARESET_TIME":1, + + # TX Receiver Detection Attributes + "p_TX_RXDETECT_CFG":0x1832, + "p_TX_RXDETECT_REF":0b100, + + # CPLL Attributes + "p_CPLL_CFG":0xBC07DC, + "p_CPLL_FBDIV":4, + "p_CPLL_FBDIV_45":5, + "p_CPLL_INIT_CFG":0x00001e, + "p_CPLL_LOCK_CFG":0x01e8, + "p_CPLL_REFCLK_DIV":1, + "p_RXOUT_DIV":rxout_div, + "p_TXOUT_DIV":txout_div, + "p_SATA_CPLL_CFG":"VCO_3000MHZ", + + # RX Initialization and Reset Attributes + "p_RXDFELPMRESET_TIME":0b0001111, + + # RX Equalizer Attributes + "p_RXLPM_HF_CFG":0b00000011110000, + "p_RXLPM_LF_CFG":0b00000011110000, + "p_RX_DFE_GAIN_CFG":0x020fea, + "p_RX_DFE_H2_CFG":0b000000000000, + "p_RX_DFE_H3_CFG":0b000001000000, + "p_RX_DFE_H4_CFG":0b00011110000, + "p_RX_DFE_H5_CFG":0b00011100000, + "p_RX_DFE_KL_CFG":0b0000011111110, + "p_RX_DFE_LPM_CFG":0x0954, + "p_RX_DFE_LPM_HOLD_DURING_EIDLE":0, + "p_RX_DFE_UT_CFG":0b10001111000000000, + "p_RX_DFE_VP_CFG":0b00011111100000011, + + # Power-Down Attributes + "p_RX_CLKMUX_PD":1, + "p_TX_CLKMUX_PD":1, + + # FPGA RX Interface Attribute + "p_RX_INT_DATAWIDTH":0, + + # FPGA TX Interface Attribute + "p_TX_INT_DATAWIDTH":0, + + # TX Configurable Driver Attributes + "p_TX_QPI_STATUS_EN":0, + + # RX Equalizer Attributes + "p_RX_DFE_KL_CFG2":0b00110011000100000001100000001100, + "p_RX_DFE_XYD_CFG":0b0000000000000, + + # TX Configurable Driver Attributes + "p_TX_PREDRIVER_MODE":0, + } + + self.specials += \ + Instance("GTXE2_CHANNEL", + # CPLL Ports + #o_CPLLFBCLKLOST=, + o_CPLLLOCK=self.cplllock, + i_CPLLLOCKDETCLK=0, + i_CPLLLOCKEN=1, + i_CPLLPD=0, + #o_CPLLREFCLKLOST=0, + i_CPLLREFCLKSEL=0b001, + i_CPLLRESET=self.cpllreset, + i_GTRSVD=0, + i_PCSRSVDIN=0, + i_PCSRSVDIN2=0, + i_PMARSVDIN=0, + i_PMARSVDIN2=0, + i_TSTIN=ones(20), + #o_TSTOUT=, + + # Channel + i_CLKRSVD=0, + + # Channel - Clocking Ports + i_GTGREFCLK=0, + i_GTNORTHREFCLK0=0, + i_GTNORTHREFCLK1=0, + i_GTREFCLK0=self.gtrefclk0, + i_GTREFCLK1=0, + i_GTSOUTHREFCLK0=0, + i_GTSOUTHREFCLK1=0, + + # Channel - DRP Ports + i_DRPADDR=0, + i_DRPCLK=0, + i_DRPDI=0, + #o_DRPDO=, + i_DRPEN=0, + #o_DRPRDY=, + i_DRPWE=0, + + # Clocking Ports + #o_GTREFCLKMONITOR=, + i_QPLLCLK=self.qpllclk, + i_QPLLREFCLK=self.qpllrefclk, + i_RXSYSCLKSEL=0b00, + i_TXSYSCLKSEL=0b00, + + # Digital Monitor Ports + #o_DMONITOROUT=, + + # FPGA TX Interface Datapath Configuration + i_TX8B10BEN=1, + + # Loopback Ports + i_LOOPBACK=0, + + # PCI Express Ports + #o_PHYSTATUS=, + i_RXRATE=0, + #o_RXVALID=, + + # Power-Down Ports + i_RXPD=0b00, + i_TXPD=0b00, + + # RX 8B/10B Decoder Ports + i_SETERRSTATUS=0, + + # RX Initialization and Reset Ports + i_EYESCANRESET=0, + i_RXUSERRDY=rxuserrdy, + + # RX Margin Analysis Ports + #o_EYESCANDATAERROR=, + i_EYESCANMODE=0, + i_EYESCANTRIGGER=0, + + # Receive Ports - CDR Ports + i_RXCDRFREQRESET=0, + i_RXCDRHOLD=0, + o_RXCDRLOCK=rxcdrlock, + i_RXCDROVRDEN=0, + i_RXCDRRESET=0, + i_RXCDRRESETRSV=0, + + # Receive Ports - Clock Correction Ports + #o_RXCLKCORCNT=, + + # Receive Ports - FPGA RX Interface Datapath Configuration + i_RX8B10BEN=1, + + # Receive Ports - FPGA RX Interface Ports + i_RXUSRCLK=self.rxusrclk, + i_RXUSRCLK2=self.rxusrclk2, + + # Receive Ports - FPGA RX interface Ports + o_RXDATA=self.rxdata, + + # Receive Ports - Pattern Checker Ports + #o_RXPRBSERR=, + i_RXPRBSSEL=0, + + # Receive Ports - Pattern Checker ports + i_RXPRBSCNTRESET=0, + + # Receive Ports - RX Equalizer Ports + i_RXDFEXYDEN=0, + i_RXDFEXYDHOLD=0, + i_RXDFEXYDOVRDEN=0, + + # Receive Ports - RX 8B/10B Decoder Ports + #o_RXDISPERR=, + #o_RXNOTINTABLE=, + + # Receive Ports - RX AFE + i_GTXRXP=pads.rxp, + i_GTXRXN=pads.rxn, + + # Receive Ports - RX Buffer Bypass Ports + i_RXBUFRESET=0, + #o_RXBUFSTATUS=, + i_RXDDIEN=0, + i_RXDLYBYPASS=1, + i_RXDLYEN=0, + i_RXDLYOVRDEN=0, + i_RXDLYSRESET=0, + #o_RXDLYSRESETDONE=0, + i_RXPHALIGN=0, + #o_RXPHALIGNDONE=, + i_RXPHALIGNEN=0, + i_RXPHDLYPD=0, + i_RXPHDLYRESET=0, + #o_RXPHMONITOR=, + i_RXPHOVRDEN=0, + #o_RXPHSLIPMONITOR=, + #o_RXSTATUS=, + + # Receive Ports - RX Byte and Word Alignment Ports + o_RXBYTEISALIGNED=self.rxbyteisaligned, + #o_RXBYTEREALIGN=, + #o_RXCOMMADET=, + i_RXCOMMADETEN=1, + i_RXMCOMMAALIGNEN=1, + i_RXPCOMMAALIGNEN=1, + + # Receive Ports - RX Channel Bonding Ports + #o_RXCHANBONDSEQ=, + i_RXCHBONDEN=0, + i_RXCHBONDLEVEL=0, + i_RXCHBONDMASTER=0, + #o_RXCHBONDO=, + i_RXCHBONDSLAVE=0, + + # Receive Ports - RX Channel Bonding Ports + #o_RXCHANISALIGNED=, + #o_RXCHANREALIGN=, + + # Receive Ports - RX Equalizer Ports + i_RXDFEAGCHOLD=0, + i_RXDFEAGCOVRDEN=0, + i_RXDFECM1EN=0, + i_RXDFELFHOLD=0, + i_RXDFELFOVRDEN=1, + i_RXDFELPMRESET=0, + i_RXDFETAP2HOLD=0, + i_RXDFETAP2OVRDEN=0, + i_RXDFETAP3HOLD=0, + i_RXDFETAP3OVRDEN=0, + i_RXDFETAP4HOLD=0, + i_RXDFETAP4OVRDEN=0, + i_RXDFETAP5HOLD=0, + i_RXDFETAP5OVRDEN=0, + i_RXDFEUTHOLD=0, + i_RXDFEUTOVRDEN=0, + i_RXDFEVPHOLD=0, + i_RXDFEVPOVRDEN=0, + i_RXDFEVSEN=0, + i_RXLPMLFKLOVRDEN=0, + #o_RXMONITOROUT=, + i_RXMONITORSEL=0b00, + i_RXOSHOLD=0, + i_RXOSOVRDEN=0, + + # Receive Ports - RX Equilizer Ports + i_RXLPMHFHOLD=0, + i_RXLPMHFOVRDEN=0, + i_RXLPMLFHOLD=0, + + # Receive Ports - RX Fabric ClocK Output Control Ports + #o_RXRATEDONE=, + + # Receive Ports - RX Fabric Output Control Ports + o_RXOUTCLK=self.rxoutclk, + #o_RXOUTCLKFABRIC=, + #o_RXOUTCLKPCS=, + i_RXOUTCLKSEL=0b010, + + # Receive Ports - RX Gearbox Ports + #o_RXDATAVALID=, + #o_RXHEADER=, + #o_RXHEADERVALID=, + #o_RXSTARTOFSEQ=, + + # Receive Ports - RX Gearbox Ports + i_RXGEARBOXSLIP=0, + + # Receive Ports - RX Initialization and Reset Ports + i_GTRXRESET=self.gtrxreset, + i_RXOOBRESET=0, + i_RXPCSRESET=0, + i_RXPMARESET=self.pmarxreset, + + # Receive Ports - RX Margin Analysis ports + i_RXLPMEN=0, + + # Receive Ports - RX OOB Signaling ports + #o_RXCOMSASDET=, + o_RXCOMWAKEDET=rxcomwakedet, + + # Receive Ports - RX OOB Signaling ports + o_RXCOMINITDET=rxcominitdet, + + # Receive Ports - RX OOB signalling Ports + o_RXELECIDLE=rxelecidle, + i_RXELECIDLEMODE=0b00, + + # Receive Ports - RX Polarity Control Ports + i_RXPOLARITY=0, + + # Receive Ports - RX gearbox ports + i_RXSLIDE=0, + + # Receive Ports - RX8B/10B Decoder Ports + #o_RXCHARISCOMMA=, + o_RXCHARISK=self.rxcharisk, + + # Receive Ports - Rx Channel Bonding Ports + i_RXCHBONDI=0, + + # Receive Ports -RX Initialization and Reset Ports + o_RXRESETDONE=rxresetdone, + + # Rx AFE Ports + i_RXQPIEN=0, + #o_RXQPISENN=, + #o_RXQPISENP=, + + # TX Buffer Bypass Ports + i_TXPHDLYTSTCLK=0, + + # TX Configurable Driver Ports + i_TXPOSTCURSOR=0, + i_TXPOSTCURSORINV=0, + i_TXPRECURSOR=0, + i_TXPRECURSORINV=0, + i_TXQPIBIASEN=0, + i_TXQPISTRONGPDOWN=0, + i_TXQPIWEAKPUP=0, + + # TX Initialization and Reset Ports + i_CFGRESET=0, + i_GTTXRESET=self.gttxreset, + #o_PCSRSVDOUT=, + i_TXUSERRDY=txuserrdy, + + # Transceiver Reset Mode Operation + i_GTRESETSEL=0, + i_RESETOVRD=0, + + # Transmit Ports - 8b10b Encoder Control Ports + i_TXCHARDISPMODE=0, + i_TXCHARDISPVAL=0, + + # Transmit Ports - FPGA TX Interface Ports + i_TXUSRCLK=self.txusrclk, + i_TXUSRCLK2=self.txusrclk2, + + # Transmit Ports - PCI Express Ports + i_TXELECIDLE=txelecidle, + i_TXMARGIN=0, + i_TXRATE=txrate, + i_TXSWING=0, + + # Transmit Ports - Pattern Generator Ports + i_TXPRBSFORCEERR=0, + + # Transmit Ports - TX Buffer Bypass Ports + i_TXDLYBYPASS=1, + i_TXDLYEN=0, + i_TXDLYHOLD=0, + i_TXDLYOVRDEN=0, + i_TXDLYSRESET=0, + #o_TXDLYSRESETDONE=, + i_TXDLYUPDOWN=0, + i_TXPHALIGN=0, + #o_TXPHALIGNDONE=txphaligndone, + i_TXPHALIGNEN=0, + i_TXPHDLYPD=0, + i_TXPHDLYRESET=0, + i_TXPHINIT=0, + #o_TXPHINITDONE=, + i_TXPHOVRDEN=0, + + # Transmit Ports - TX Buffer Ports + #o_TXBUFSTATUS=, + + # Transmit Ports - TX Configurable Driver Ports + i_TXBUFDIFFCTRL=0b100, + i_TXDEEMPH=0, + i_TXDIFFCTRL=0b1000, + i_TXDIFFPD=0, + i_TXINHIBIT=0, + i_TXMAINCURSOR=0, + i_TXPISOPD=0, + + # Transmit Ports - TX Data Path interface + i_TXDATA=self.txdata, + + # Transmit Ports - TX Driver and OOB signaling + o_GTXTXP=pads.txp, + o_GTXTXN=pads.txn, + + # Transmit Ports - TX Fabric Clock Output Control Ports + o_TXOUTCLK=self.txoutclk, + #o_TXOUTCLKFABRIC=, + #o_TXOUTCLKPCS=, + i_TXOUTCLKSEL=0b11, #?? + #o_TXRATEDONE=, + # Transmit Ports - TX Gearbox Ports + i_TXCHARISK=self.txcharisk, + #o_TXGEARBOXREADY=, + i_TXHEADER=0, + i_TXSEQUENCE=0, + i_TXSTARTSEQ=0, + + # Transmit Ports - TX Initialization and Reset Ports + i_TXPCSRESET=0, + i_TXPMARESET=0, + o_TXRESETDONE=txresetdone, + + # Transmit Ports - TX OOB signalling Ports + o_TXCOMFINISH=txcomfinish, + i_TXCOMINIT=txcominit, + i_TXCOMSAS=0, + i_TXCOMWAKE=txcomwake, + i_TXPDELECIDLEMODE=0, + + # Transmit Ports - TX Polarity Control Ports + i_TXPOLARITY=0, + + # Transmit Ports - TX Receiver Detection Ports + i_TXDETECTRX=0, + + # Transmit Ports - TX8b/10b Encoder Ports + i_TX8B10BBYPASS=0, + + # Transmit Ports - pattern Generator Ports + i_TXPRBSSEL=0, + + # Tx Configurable Driver Ports + #o_TXQPISENN=, + #o_TXQPISENP=, + + **gtxe2_channel_parameters + ) + + +class GTXE2_COMMON(Module): + def __init__(self, fbdiv=16): + self.refclk0 = Signal() + + self.qpllclk = Signal() + self.qpllrefclk = Signal() + + # fbdiv config + fbdiv_in_config = { + 16 : 0b0000100000, + 20 : 0b0000110000, + 32 : 0b0001100000, + 40 : 0b0010000000, + 64 : 0b0011100000, + 66 : 0b0101000000, + 80 : 0b0100100000, + 100 : 0b0101110000 + } + fbdiv_in = fbdiv_in_config[fbdiv] + + fbdiv_ratio_config = { + 16 : 0b1, + 20 : 0b1, + 32 : 0b1, + 40 : 0b1, + 64 : 0b1, + 66 : 0b0, + 80 : 0b1, + 100 : 0b1 + } + fbdiv_ratio = fbdiv_ratio_config[fbdiv] + + self.specials += \ + Instance("GTXE2_COMMON", + # Simulation attributes + p_SIM_RESET_SPEEDUP="TRUE", + p_SIM_QPLLREFCLK_SEL=0b001, + p_SIM_VERSION="4.0", + + # Common block attributes + p_BIAS_CFG=0x0000040000001000, + p_COMMON_CFG=0, + p_QPLL_CFG=0x06801c1, + p_QPLL_CLKOUT_CFG=0, + p_QPLL_COARSE_FREQ_OVRD=0b010000, + p_QPLL_COARSE_FREQ_OVRD_EN=0, + p_QPLL_CP=0b0000011111, + p_QPLL_CP_MONITOR_EN=0, + p_QPLL_DMONITOR_SEL=0, + p_QPLL_FBDIV=fbdiv_in, + p_QPLL_FBDIV_MONITOR_EN=0, + p_QPLL_FBDIV_RATIO=fbdiv_ratio, + p_QPLL_INIT_CFG=0x000006, + p_QPLL_LOCK_CFG=0x21e9, + p_QPLL_LPF=0b1111, + p_QPLL_REFCLK_DIV=1, + + # Common block - Dynamic Reconfiguration Port (DRP) + i_DRPADDR=0, + i_DRPCLK=0, + i_DRPDI=0, + #o_DRPDO=, + i_DRPEN=0, + #o_DRPRDY=, + i_DRPWE=0, + + # Common block - Ref Clock Ports + i_GTGREFCLK=0, + i_GTNORTHREFCLK0=0, + i_GTNORTHREFCLK1=0, + i_GTREFCLK0=self.refclk0, + i_GTREFCLK1=0, + i_GTSOUTHREFCLK0=0, + i_GTSOUTHREFCLK1=0, + + # Common block - QPLL Ports + #o_QPLLDMONITOR=, + #o_QPLLFBCLKLOST=, + #o_QPLLLOCK=, + i_QPLLLOCKDETCLK=0, + i_QPLLLOCKEN=1, + o_QPLLOUTCLK=self.qpllclk, + o_QPLLOUTREFCLK=self.qpllrefclk, + i_QPLLOUTRESET=0, + i_QPLLPD=0, + #o_QPLLREFCLKLOST=, + i_QPLLREFCLKSEL=0b001, + i_QPLLRESET=0, + i_QPLLRSVD1=0, + i_QPLLRSVD2=ones(5), + #o_REFCLKOUTMONITOR=, + + # Common block Ports + i_BGBYPASSB=1, + i_BGMONITORENB=1, + i_BGPDB=1, + i_BGRCALOVRD=0, + i_PMARSVD=0, + i_RCALENB=1 + ) diff --git a/lib/sata/phy/k7sataphy/std.py b/lib/sata/phy/k7sataphy/std.py new file mode 100644 index 00000000..5a218990 --- /dev/null +++ b/lib/sata/phy/k7sataphy/std.py @@ -0,0 +1,8 @@ +from migen.fhdl.std import * +from migen.genlib.record import * + +ALIGN_VAL = 0x7B4A4ABC +SYNC_VAL = 0xB5B5957C + +def ones(width): + return 2**width-1 diff --git a/lib/sata/transport/.keep_me b/lib/sata/transport/.keep_me new file mode 100644 index 00000000..e69de29b diff --git a/targets/test.py b/targets/test.py index cd51ca2b..1cb99610 100644 --- a/targets/test.py +++ b/targets/test.py @@ -8,8 +8,8 @@ from migen.bank.description import * from miscope.uart2wishbone import UART2Wishbone from misoclib import identifier -from lib.sata.k7sataphy.std import * -from lib.sata.k7sataphy import K7SATAPHY +from lib.sata.phy.k7sataphy.std import * +from lib.sata.phy.k7sataphy import K7SATAPHY from migen.genlib.cdc import *