+++ /dev/null
-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
+++ /dev/null
-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),
- ]
+++ /dev/null
-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)
+++ /dev/null
-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),
- )
- ]
+++ /dev/null
-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
- )
+++ /dev/null
-from migen.fhdl.std import *
-from migen.genlib.record import *
-
-ALIGN_VAL = 0x7B4A4ABC
-SYNC_VAL = 0xB5B5957C
-
-def ones(width):
- return 2**width-1
--- /dev/null
+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
--- /dev/null
+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),
+ ]
--- /dev/null
+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)
--- /dev/null
+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),
+ )
+ ]
--- /dev/null
+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
+ )
--- /dev/null
+from migen.fhdl.std import *
+from migen.genlib.record import *
+
+ALIGN_VAL = 0x7B4A4ABC
+SYNC_VAL = 0xB5B5957C
+
+def ones(width):
+ return 2**width-1
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 *