From d47917e48043ac39f10696a07c72f0be70b4f22e Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Mon, 29 Sep 2014 18:25:24 +0200 Subject: [PATCH] simplify and clean up --- lib/sata/k7sataphy/__init__.py | 47 ++------- lib/sata/k7sataphy/crg.py | 34 ++----- lib/sata/k7sataphy/ctrl.py | 41 +++++--- lib/sata/k7sataphy/datapath.py | 174 ++++++++++++++++++++++----------- lib/sata/k7sataphy/gtx.py | 20 +++- 5 files changed, 175 insertions(+), 141 deletions(-) diff --git a/lib/sata/k7sataphy/__init__.py b/lib/sata/k7sataphy/__init__.py index 90094e0c..ba4ef1b4 100644 --- a/lib/sata/k7sataphy/__init__.py +++ b/lib/sata/k7sataphy/__init__.py @@ -1,54 +1,23 @@ from migen.fhdl.std import * -from migen.flow.actor import Sink, Source 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 K7SATAPHYRXConvert, K7SATAPHYTXConvert +from lib.sata.k7sataphy.datapath import K7SATAPHYDatapath class K7SATAPHY(Module): - def __init__(self, pads, clk_freq, host=True, default_speed="SATA3"): - self.sink = Sink([("d", 32)]) - self.source = Source([("d", 32)]) - + def __init__(self, pads, clk_freq, host=True, default_speed="SATA1"): # GTX - gtx = K7SATAPHYGTX(pads, default_speed) - self.submodules += gtx + self.submodules.gtx = K7SATAPHYGTX(pads, default_speed) # CRG / CTRL - crg = K7SATAPHYCRG(pads, gtx, clk_freq, default_speed) + self.submodules.crg = K7SATAPHYCRG(pads, self.gtx, clk_freq, default_speed) if host: - ctrl = K7SATAPHYHostCtrl(gtx, crg, clk_freq) + self.submodules.ctrl = K7SATAPHYHostCtrl(self.gtx, self.crg, clk_freq) else: - ctrl = K7SATAPHYDeviceCtrl(gtx, crg, clk_freq) - self.submodules += crg, ctrl + self.submodules.ctrl = K7SATAPHYDeviceCtrl(self.gtx, self.crg, clk_freq) # DATAPATH - rxconvert = K7SATAPHYRXConvert() - txconvert = K7SATAPHYTXConvert() - self.submodules += rxconvert, txconvert - self.comb += [ - rxconvert.rxdata.eq(gtx.rxdata), - rxconvert.rxcharisk.eq(gtx.rxcharisk), - - gtx.txdata.eq(txconvert.txdata), - gtx.txcharisk.eq(txconvert.txcharisk) - ] - - self.comb += [ - If(ctrl.ready, - txconvert.sink.stb.eq(self.sink.stb), - txconvert.sink.data.eq(self.sink.d), - txconvert.sink.charisk.eq(0), - self.sink.ack.eq(txconvert.sink.ack), - ).Else( - txconvert.sink.stb.eq(1), - txconvert.sink.data.eq(ctrl.txdata), - txconvert.sink.charisk.eq(ctrl.txcharisk) - ), - self.source.stb.eq(rxconvert.source.stb), - self.source.payload.eq(rxconvert.source.data), - rxconvert.source.ack.eq(1), - ctrl.rxdata.eq(rxconvert.source.data) - ] + 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 index 3b9a911c..1bbec2cb 100644 --- a/lib/sata/k7sataphy/crg.py +++ b/lib/sata/k7sataphy/crg.py @@ -9,11 +9,8 @@ from lib.sata.k7sataphy.std import * class K7SATAPHYReconfig(Module): def __init__(self, channel_drp, mmcm_drp): self.speed = Signal(3) + ### - speed_r = Signal(3) - speed_change = Signal() - self.sync += speed_r.eq(self.speed) - self.comb += speed_change.eq(self.speed != speed_r) drp_sel = Signal() drp = DRPBus() @@ -23,6 +20,7 @@ class K7SATAPHYReconfig(Module): ).Else( drp.connect(channel_drp) ) + # Todo class K7SATAPHYCRG(Module): def __init__(self, pads, gtx, clk_freq, default_speed): @@ -34,7 +32,7 @@ class K7SATAPHYCRG(Module): # CPLL # (SATA3) 150MHz / VCO @ 3GHz / Line rate @ 6Gbps - # (SATA2 & SATA1) VCO still @ 3 GHz, Line rate is decreased with output divivers. + # (SATA2 & SATA1) VCO still @ 3 GHz, Line rate is decreased with output dividers. # When changing rate, reconfiguration of the CPLL over DRP is needed to: # - update the output divider # - update the equalizer configuration (specific for each line rate). @@ -93,9 +91,9 @@ class K7SATAPHYCRG(Module): ] # RX clocking - # (SATA3) sata_rx recovered clk @ 300MHz from CPLL RXOUTCLK - # (SATA2) sata_rx recovered clk @ 150MHz from CPLL RXOUTCLK - # (SATA1) sata_rx recovered clk @ 150MHz from CPLL RXOUTCLK + # (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), ] @@ -104,25 +102,8 @@ class K7SATAPHYCRG(Module): gtx.rxusrclk2.eq(self.cd_sata_rx.clk) ] - # Bypass TX buffer - self.comb += [ - gtx.txphdlyreset.eq(0), - gtx.txphalignen.eq(0), - gtx.txdlyen.eq(0), - gtx.txphalign.eq(0), - gtx.txphinit.eq(0) - ] - - # Bypass RX buffer - self.comb += [ - gtx.rxphdlyreset.eq(0), - gtx.rxdlyen.eq(0), - gtx.rxphalign.eq(0), - gtx.rxphalignen.eq(0), - ] - # Configuration Reset - # After configuration, GTX resets have to stay low for at least 500ns + # After configuration, GTX's resets have to stay low for at least 500ns # See AR43482 reset_en = Signal() clk_period_ns = 1000000000/clk_freq @@ -227,6 +208,7 @@ class K7SATAPHYCRG(Module): ) ) + # Ready self.comb += self.ready.eq(tx_reset_fsm.ongoing("READY") & rx_reset_fsm.ongoing("READY")) # Reset PLL diff --git a/lib/sata/k7sataphy/ctrl.py b/lib/sata/k7sataphy/ctrl.py index 983980a1..8c2d1eba 100644 --- a/lib/sata/k7sataphy/ctrl.py +++ b/lib/sata/k7sataphy/ctrl.py @@ -19,9 +19,13 @@ class K7SATAPHYHostCtrl(Module): self.rxdata = Signal(32) - align_timeout = Signal() align_detect = Signal() - retry_cnt = Signal(32) + align_timeout_cnt = Signal(32) + align_timeout = Signal() + + retry_timeout_cnt = Signal(32) + retry_timeout = Signal() + non_align_cnt = Signal(4) txcominit = Signal() @@ -48,7 +52,7 @@ class K7SATAPHYHostCtrl(Module): If(gtx.rxcominitdet, NextState("AWAIT_NO_COMINIT") ).Else( - If(retry_cnt == 0, + If(retry_timeout, NextState("RESET") ) ) @@ -75,7 +79,7 @@ class K7SATAPHYHostCtrl(Module): If(gtx.rxcomwakedet, NextState("AWAIT_NO_COMWAKE") ).Else( - If(retry_cnt == 0, + If(retry_timeout, NextState("RESET") ) ) @@ -93,6 +97,8 @@ class K7SATAPHYHostCtrl(Module): ) fsm.act("AWAIT_ALIGN", gtx.txelecidle.eq(0), + self.txdata.eq(0x4A4A4A4A), #D10.2 + self.txcharisk.eq(0b0000), gtx.rxalign.eq(1), If(align_detect & ~align_timeout, NextState("SEND_ALIGN") @@ -104,7 +110,7 @@ class K7SATAPHYHostCtrl(Module): gtx.txelecidle.eq(0), self.txdata.eq(ALIGN_VAL), self.txcharisk.eq(0b0001), - If(non_align_cnt == 15, + If(non_align_cnt == 3, NextState("READY") ) ) @@ -124,9 +130,8 @@ class K7SATAPHYHostCtrl(Module): gtx.txcominit.eq(txcominit & ~txcominit_d), gtx.txcomwake.eq(txcomwake & ~txcomwake_d), ] - self.comb += align_detect.eq(self.rxdata == ALIGN_VAL); - align_timeout_cnt = Signal(16) + self.comb += align_detect.eq(self.rxdata == ALIGN_VAL); self.sync += \ If(fsm.ongoing("RESET"), align_timeout_cnt.eq(us(873, clk_freq)) @@ -137,10 +142,11 @@ class K7SATAPHYHostCtrl(Module): self.sync += \ If(fsm.ongoing("RESET") | fsm.ongoing("AWAIT_NO_COMINIT"), - retry_cnt.eq(us(10000, clk_freq)) + retry_timeout_cnt.eq(us(10000, clk_freq)) ).Elif(fsm.ongoing("AWAIT_COMINIT") | fsm.ongoing("AWAIT_COMWAKE"), - retry_cnt.eq(retry_cnt-1) + retry_timeout_cnt.eq(retry_timeout_cnt-1) ) + self.comb += retry_timeout.eq(retry_timeout_cnt == 0) self.sync += \ If(fsm.ongoing("SEND_ALIGN"), @@ -160,9 +166,12 @@ class K7SATAPHYDeviceCtrl(Module): self.rxdata = Signal(32) - align_timeout = Signal() align_detect = Signal() - retry_cnt = Signal(32) + align_timeout = Signal() + align_timeout_cnt = Signal(32) + + retry_timeout_cnt = Signal(32) + retry_timeout = Signal() txcominit = Signal() txcomwake = Signal() @@ -194,7 +203,7 @@ class K7SATAPHYDeviceCtrl(Module): If(gtx.rxcomwakedet, NextState("AWAIT_NO_COMWAKE") ).Else( - If(retry_cnt == 0, + If(retry_timeout, NextState("RESET") ) ) @@ -253,9 +262,8 @@ class K7SATAPHYDeviceCtrl(Module): gtx.txcominit.eq(txcominit & ~txcominit_d), gtx.txcomwake.eq(txcomwake & ~txcomwake), ] - self.comb += align_detect.eq(self.rxdata == ALIGN_VAL); - align_timeout_cnt = Signal(16) + self.comb += align_detect.eq(self.rxdata == ALIGN_VAL); self.sync += \ If(fsm.ongoing("RESET"), align_timeout_cnt.eq(us(55, clk_freq)) @@ -266,7 +274,8 @@ class K7SATAPHYDeviceCtrl(Module): self.sync += \ If(fsm.ongoing("RESET"), - retry_cnt.eq(us(10000, clk_freq)) + retry_timeout_cnt.eq(us(10000, clk_freq)) ).Elif(fsm.ongoing("AWAIT_COMWAKE"), - retry_cnt.eq(retry_cnt-1) + 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 index d7e4c737..2a607b37 100644 --- a/lib/sata/k7sataphy/datapath.py +++ b/lib/sata/k7sataphy/datapath.py @@ -1,91 +1,151 @@ from migen.fhdl.std import * +from migen.genlib.misc import chooser from migen.actorlib.fifo import AsyncFIFO -from migen.actorlib.structuring import Converter from migen.flow.actor import Sink, Source from lib.sata.k7sataphy.std import * -class K7SATAPHYRXConvert(Module): - def __init__(self, dw=16): - self.rxdata = Signal(dw) - self.rxcharisk = Signal(dw//8) - +class K7SATAPHYDatapathRX(Module): + def __init__(self): + self.sink = Sink([("data", 16), ("charisk", 2)]) self.source = Source([("data", 32), ("charisk", 4)]) ### - # byte alignment - rxdata_r = Signal(2*dw) - rxcharisk_r = Signal((2*dw)//8) - rxalignment = Signal(dw//8) - rxvalid = Signal() + # 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 += [ - rxdata_r.eq(Cat(self.rxdata, rxdata_r[0:dw])), - rxcharisk_r.eq(Cat(self.rxcharisk, rxcharisk_r[0:dw//8])), - If(self.rxcharisk != 0, - rxalignment.eq(self.rxcharisk), - rxvalid.eq(1) + 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( - rxvalid.eq(~rxvalid) + valid.eq(~valid) ) ] - rxdata = Signal(2*dw) - rxcharisk = Signal((2*dw)//8) - cases = {} - cases[1<<0] = [ - rxdata.eq(rxdata_r[0:]), - rxcharisk.eq(rxcharisk_r[0:]) - ] - for i in range(1, dw//8): - cases[1< 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 += [ - Record.connect(rx_fifo.source, self.source) + fifo.sink.stb.eq(valid), + fifo.sink.data.eq(data), + fifo.sink.charisk.eq(charisk), ] + self.comb += Record.connect(fifo.source, self.source) -class K7SATAPHYTXConvert(Module): +class K7SATAPHYDatapathTX(Module): def __init__(self): self.sink = Sink([("data", 32), ("charisk", 4)]) + self.source = Source([("data", 16), ("charisk", 2)]) - self.txdata = Signal(16) - self.txcharisk = Signal(2) ### - # convert data widths - tx_converter = RenameClockDomains(Converter([("raw", 32+4)], [("raw", 16+2)]), "sata_tx") - self.submodules += tx_converter + # 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 += [ - Cat(self.txdata, self.txcharisk).eq(tx_converter.source.raw), - tx_converter.source.ack.eq(1), + 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([("d", 32)]) + self.source = Source([("d", 32)]) - # clock domain crossing - tx_fifo = AsyncFIFO([("raw", 36)], 16) - self.submodules.tx_fifo = RenameClockDomains(tx_fifo, {"write": "sys", "read": "sata_tx"}) + ### + + # change data width & cross domain crossing + rx = K7SATAPHYDatapathRX() + tx = K7SATAPHYDatapathTX() + self.submodules += rx, tx self.comb += [ - tx_fifo.source.connect(tx_converter.sink), - self.tx_fifo.sink.stb.eq(1), + rx.sink.data.eq(gtx.rxdata), + rx.sink.charisk.eq(gtx.rxcharisk), + + gtx.txdata.eq(tx.source.data), + gtx.txcharisk.eq(tx.source.charisk), ] - # rearrange data + # user / ctrl mux self.comb += [ - self.tx_fifo.sink.stb.eq(self.sink.stb), - self.tx_fifo.sink.raw.eq(Cat(self.sink.data[0:16], self.sink.charisk[0:2], - self.sink.data[16:32], self.sink.charisk[2:4])), - self.sink.ack.eq(self.tx_fifo.sink.ack), + # user + If(ctrl.ready, + tx.sink.stb.eq(self.sink.stb), + tx.sink.data.eq(self.sink.d), + tx.sink.charisk.eq(0), + self.sink.ack.eq(tx.sink.ack), + + self.source.stb.eq(rx.source.stb), + self.source.d.eq(rx.source.data), + rx.source.ack.eq(1), + # ctrl + ).Else( + tx.sink.stb.eq(1), + tx.sink.data.eq(ctrl.txdata), + tx.sink.charisk.eq(ctrl.txcharisk), + + ctrl.rxdata.eq(rx.source.data), + rx.source.ack.eq(1), + ) ] diff --git a/lib/sata/k7sataphy/gtx.py b/lib/sata/k7sataphy/gtx.py index b2eed8d2..2ba6f7c5 100644 --- a/lib/sata/k7sataphy/gtx.py +++ b/lib/sata/k7sataphy/gtx.py @@ -1,8 +1,5 @@ from migen.fhdl.std import * from migen.genlib.cdc import * -from migen.actorlib.fifo import AsyncFIFO -from migen.actorlib.structuring import Converter -from migen.flow.actor import Sink, Source from lib.sata.k7sataphy.std import * @@ -213,6 +210,23 @@ class K7SATAPHYGTX(Module): self.rxbyterealign = Signal() self.rxcommadet = Signal() + # Bypass TX buffer + self.comb += [ + self.txphdlyreset.eq(0), + self.txphalignen.eq(0), + self.txdlyen.eq(0), + self.txphalign.eq(0), + self.txphinit.eq(0) + ] + + # Bypass RX buffer + self.comb += [ + self.rxphdlyreset.eq(0), + self.rxdlyen.eq(0), + self.rxphalign.eq(0), + self.rxphalignen.eq(0), + ] + # Instance gtxe2_channel_parameters = { # Simulation-Only Attributes -- 2.30.2