move some logic outside of GTX
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Thu, 25 Sep 2014 12:52:16 +0000 (14:52 +0200)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Thu, 25 Sep 2014 13:23:56 +0000 (15:23 +0200)
lib/sata/k7sataphy/__init__.py
lib/sata/k7sataphy/ctrl.py
lib/sata/k7sataphy/gtx.py

index 7ea59f904ffe37dd1947071bace9746c7296366a..77d112a52235a0cf8fcdd0ae098fb2e5a91954a2 100644 (file)
@@ -2,7 +2,8 @@ from migen.fhdl.std import *
 from migen.flow.actor import Sink, Source
 
 from lib.sata.k7sataphy.std import *
-from lib.sata.k7sataphy.gtx import GTXE2_CHANNEL
+from lib.sata.k7sataphy.gtx import K7SATAPHYGTX, K7SATAPHYRXAlign
+from lib.sata.k7sataphy.gtx import K7SATAPHYRXConvert, K7SATAPHYTXConvert
 from lib.sata.k7sataphy.clocking import K7SATAPHYClocking
 from lib.sata.k7sataphy.ctrl import K7SATAPHYHostCtrl, K7SATAPHYDeviceCtrl
 
@@ -11,25 +12,40 @@ class K7SATAPHY(Module):
                self.sink = Sink([("d", 32)], True)
                self.source = Source([("d", 32)], True)
 
-               self.submodules.gtx = GTXE2_CHANNEL(pads, "SATA3")
-               self.submodules.clocking = K7SATAPHYClocking(pads, self.gtx)
+               gtx = K7SATAPHYGTX(pads, "SATA3")
+               clocking = K7SATAPHYClocking(pads, gtx)
+               rxalign = K7SATAPHYRXAlign()
+               rxconvert = K7SATAPHYRXConvert()
+               txconvert = K7SATAPHYTXConvert()
+               self.submodules += gtx, clocking, rxalign, rxconvert, txconvert
+               self.comb += [
+                       rxalign.rxdata_i.eq(gtx.rxdata),
+                       rxalign.rxcharisk_i.eq(gtx.rxcharisk),
+                       rxconvert.rxdata.eq(rxalign.rxdata_o),
+                       rxconvert.rxcharisk.eq(rxalign.rxcharisk_o),
+
+                       gtx.txdata.eq(txconvert.txdata),
+                       gtx.txcharisk.eq(txconvert.txcharisk)
+               ]
+
                if host:
-                       self.submodules.ctrl = K7SATAPHYHostCtrl(self.gtx)
+                       ctrl = K7SATAPHYHostCtrl(gtx)
                else:
-                       self.submodules.ctrl = K7SATAPHYDeviceCtrl(self.gtx)
+                       ctrl = K7SATAPHYDeviceCtrl(gtx)
+               self.submodules += ctrl
                self.comb += [
-                       If(self.ctrl.link_up,
-                               self.gtx.sink.stb.eq(self.sink.stb),
-                               self.gtx.sink.data.eq(self.sink.d),
-                               self.gtx.sink.charisk.eq(0),
-                               self.sink.ack.eq(self.gtx.sink.ack),
+                       If(ctrl.link_up,
+                               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(
-                               self.gtx.sink.stb.eq(1),
-                               self.gtx.sink.data.eq(self.ctrl.txdata),
-                               self.gtx.sink.charisk.eq(self.ctrl.txcharisk)
+                               txconvert.sink.stb.eq(1),
+                               txconvert.sink.data.eq(ctrl.txdata),
+                               txconvert.sink.charisk.eq(ctrl.txcharisk)
                        ),
-                       self.source.stb.eq(self.gtx.source.stb),
-                       self.source.payload.eq(self.gtx.source.payload),
-                       self.gtx.source.ack.eq(self.source.ack),
-                       self.ctrl.rxdata.eq(self.gtx.source.data)
+                       self.source.stb.eq(rxconvert.source.stb),
+                       self.source.payload.eq(rxconvert.source.payload),
+                       rxconvert.source.ack.eq(self.source.ack),
+                       ctrl.rxdata.eq(rxconvert.source.data)
                ]
index 7f63b0f3344b1c089d2a69d02b108d7071bc3184..9e60007a030f2ebc4527bf5281d3ec546b03e581 100644 (file)
@@ -120,8 +120,10 @@ class K7SATAPHYHostCtrl(Module):
                txcominit_d = Signal()
                txcomwake_d = Signal()
                self.sync.sata += [
+                       txcominit_d.eq(txcominit),
+                       txcomwake_d.eq(txcomwake),
                        gtx.txcominit.eq(txcominit & ~txcominit_d),
-                       gtx.txcomwake.eq(txcomwake & ~txcomwake),
+                       gtx.txcomwake.eq(txcomwake & ~txcomwake_d),
                ]
                self.comb +=  align_detect.eq(self.rxdata == ALIGN_VAL);
 
@@ -249,6 +251,8 @@ class K7SATAPHYDeviceCtrl(Module):
                txcominit_d = Signal()
                txcomwake_d = Signal()
                self.sync.sata += [
+                       txcominit_d.eq(txcominit),
+                       txcomwake_d.eq(txcomwake),
                        gtx.txcominit.eq(txcominit & ~txcominit_d),
                        gtx.txcomwake.eq(txcomwake & ~txcomwake),
                ]
index 710004afa4d4a5040ff18198c0a58a6118caf98b..ef26ecd9055f396697ade360990ba95de697a142 100644 (file)
@@ -5,14 +5,10 @@ from migen.flow.actor import Sink, Source
 
 from lib.sata.k7sataphy.std import *
 
-class GTXE2_CHANNEL(Module):
+class K7SATAPHYGTX(Module):
        def __init__(self, pads, default_speed="SATA3"):
                self.drp = DRPBus()
 
-               # Channel
-               self.qpllclk = Signal()
-               self.qpllrefclk = Signal()
-
                # Channel - Ref Clock Ports
                self.gtrefclk0 = Signal()
 
@@ -30,6 +26,7 @@ class GTXE2_CHANNEL(Module):
                self.rxuserrdy = Signal()
 
                # Receive Ports - 8b10b Decoder
+               self.rxcharisk = Signal(2)
                self.rxdisperr = Signal(2)
                self.rxnotintable = Signal(2)
 
@@ -39,6 +36,7 @@ class GTXE2_CHANNEL(Module):
 
                # Receive Ports - RX Data Path interface
                self.gtrxreset = Signal()
+               self.rxdata = Signal(16)
                self.rxoutclk = Signal()
                self.rxusrclk = Signal()
                self.rxusrclk2 = Signal()
@@ -69,6 +67,7 @@ class GTXE2_CHANNEL(Module):
                self.txuserrdy = Signal()
 
                # Transmit Ports - 8b10b Encoder Control Ports
+               self.txcharisk = Signal(2)
 
                # Transmit Ports - TX Buffer and Phase Alignment Ports
                self.txdlyen = Signal()
@@ -83,6 +82,7 @@ class GTXE2_CHANNEL(Module):
 
                # Transmit Ports - TX Data Path interface
                self.gttxreset = Signal()
+               self.txdata = Signal()
                self.txoutclk = Signal()
                self.txoutclkfabric = Signal()
                self.txoutclkpcs = Signal()
@@ -122,12 +122,6 @@ class GTXE2_CHANNEL(Module):
                }
                rxcdr_cfg = cdr_config[default_speed]
 
-               rxdata = Signal(16)
-               rxcharisk = Signal(2)
-
-               txdata = Signal(16)
-               txcharisk = Signal(2)
-
                gtxe2_channel_parameters = {
                                # Simulation-Only Attributes
                                        "p_SIM_RECEIVER_DETECT_PASS":"TRUE",
@@ -442,8 +436,8 @@ class GTXE2_CHANNEL(Module):
 
                                # Clocking Ports
                                        #o_GTREFCLKMONITOR=,
-                                       i_QPLLCLK=self.qpllclk,
-                                       i_QPLLREFCLK=self.qpllrefclk,
+                                       i_QPLLCLK=0,
+                                       i_QPLLREFCLK=0,
                                        i_RXSYSCLKSEL=0b00,
                                        i_TXSYSCLKSEL=0b00,
 
@@ -496,7 +490,7 @@ class GTXE2_CHANNEL(Module):
                                        i_RXUSRCLK2=self.rxusrclk2,
 
                                # Receive Ports - FPGA RX interface Ports
-                                       i_RXDATA=rxdata,
+                                       i_RXDATA=self.rxdata,
 
                                # Receive Ports - Pattern Checker Ports
                                        #o_RXPRBSERR=,
@@ -634,7 +628,7 @@ class GTXE2_CHANNEL(Module):
 
                                # Receive Ports - RX8B/10B Decoder Ports
                                        #o_RXCHARISCOMMA=,
-                                       o_RXCHARISK=rxcharisk,
+                                       o_RXCHARISK=self.rxcharisk,
 
                                # Receive Ports - Rx Channel Bonding Ports
                                        i_RXCHBONDI=0,
@@ -716,7 +710,7 @@ class GTXE2_CHANNEL(Module):
                                        i_TXPISOPD=0,
 
                                # Transmit Ports - TX Data Path interface
-                                       i_TXDATA=txdata,
+                                       i_TXDATA=self.txdata,
 
                                # Transmit Ports - TX Driver and OOB signaling
                                        o_GTXTXP=pads.txp,
@@ -729,7 +723,7 @@ class GTXE2_CHANNEL(Module):
                                        i_TXOUTCLKSEL=0b11,
                                        o_TXRATEDONE=self.txratedone,
                                # Transmit Ports - TX Gearbox Ports
-                                       i_TXCHARISK=txcharisk,
+                                       i_TXCHARISK=self.txcharisk,
                                        #o_TXGEARBOXREADY=,
                                        i_TXHEADER=0,
                                        i_TXSEQUENCE=0,
@@ -766,61 +760,64 @@ class GTXE2_CHANNEL(Module):
                                        **gtxe2_channel_parameters
                        )
 
-               # realign rxdata / rxcharisk
-               dw = 16
+class K7SATAPHYRXAlign(Module):
+       def __init__(self, dw=16):
+               self.rxdata_i = Signal(dw)
+               self.rxcharisk_i = Signal(dw//8)
+
+               self.rxdata_o = Signal(dw)
+               self.rxcharisk_o = Signal(dw//8)
+
+               ###
+
                rxdata_r = Signal(dw)
                rxcharisk_r = Signal(dw//8)
-               rxdata_aligned = Signal(dw)
-               rxcharisk_aligned = Signal(dw//8)
                self.sync.sata_rx += [
-                       rxdata_r.eq(rxdata),
-                       rxcharisk_r.eq(rxcharisk)
+                       rxdata_r.eq(self.rxdata_i),
+                       rxcharisk_r.eq(self.rxcharisk_i)
                ]
                cases = {}
                cases[1<<0] = [
-                               rxdata_aligned .eq(rxdata_r[0:dw]),
-                               rxcharisk_aligned .eq(rxcharisk_r[0:dw//8])
+                               self.rxdata_o.eq(rxdata_r[0:dw]),
+                               self.rxcharisk_o.eq(rxcharisk_r[0:dw//8])
                ]
                for i in range(1, dw//8):
                        cases[1<<i] = [
-                               rxdata_aligned .eq(Cat(rxdata[8*i:dw], rxdata_r[0:8*i])),
-                               rxcharisk_aligned .eq(Cat(rxcharisk[i:dw//8], rxcharisk_r[0:i]))
+                               self.rxdata_o.eq(Cat(self.rxdata_i[8*i:dw], rxdata_r[0:8*i])),
+                               self.rxcharisk_o.eq(Cat(self.rxcharisk_i[i:dw//8], rxcharisk_r[0:i]))
                        ]
                self.comb += Case(rxcharisk_r, cases)
 
+class K7SATAPHYRXConvert(Module):
+       def __init__(self):
+               self.rxdata = Signal(16)
+               self.rxcharisk = Signal(2)
+
+               self.source = Source([("data", 32), ("charisk", 4)])
+               ###
 
                # convert data widths
                rx_converter = RenameClockDomains(Converter([("raw", 16+2)], [("raw", 32+4)]), "sata_rx")
-               tx_converter = RenameClockDomains(Converter([("raw", 32+4)], [("raw", 16+2)]), "sata_tx")
-               self.submodules += rx_converter, tx_converter
+               self.submodules += rx_converter
                self.comb += [
                        rx_converter.sink.stb.eq(1),
-                       rx_converter.sink.raw.eq(Cat(rxdata_aligned , rxcharisk_aligned)),
-                       rx_converter.source.ack.eq(1),
-
-                       Cat(txdata, txcharisk).eq(tx_converter.source.raw),
-                       tx_converter.source.ack.eq(1),
+                       rx_converter.sink.raw.eq(Cat(self.rxdata , self.rxcharisk)),
+                       rx_converter.source.ack.eq(1)
                ]
 
+
                # clock domain crossing
                # SATA device is supposed to lock its tx frequency to its received rx frequency, so this
                # ensure that sata_rx and sata_tx clock have the same frequency with only not the same
                # phase and thus ensute the rx_fifo will never be full.
                rx_fifo = AsyncFIFO([("raw", 36)], 16)
                self.submodules.rx_fifo = RenameClockDomains(rx_fifo, {"write": "sata_rx", "read": "sata"})
-               tx_fifo = AsyncFIFO([("raw", 36)], 16)
-               self.submodules.tx_fifo = RenameClockDomains(tx_fifo, {"write": "sata", "read": "sata_tx"})
                self.comb += [
-                       Record.connect(rx_converter.source, self.rx_fifo.sink),
+                       rx_converter.source.connect(self.rx_fifo.sink),
                        self.rx_fifo.source.ack.eq(1),
-                       Record.connect(tx_fifo.source, tx_converter.sink),
-                       self.tx_fifo.sink.stb.eq(1),
                ]
 
-               # Todo:
-               # we can add support to Converter to generate non raw connection (ie keep here convert from
-               # [("data", 16), ("charisk", 2)] to [("data", 32), ("charisk", 4)]
-               self.source = Source([("data", 32), ("charisk", 4)])
+               # rearrange data
                self.comb += [
                        self.source.stb.eq(self.rx_fifo.source.stb),
                        self.source.payload.data.eq(Cat(rx_fifo.source.raw[0:32], rx_fifo.source.raw[36:36+32])),
@@ -828,7 +825,31 @@ class GTXE2_CHANNEL(Module):
                        self.rx_fifo.source.ack.eq(self.source.ack),
                ]
 
+class K7SATAPHYTXConvert(Module):
+       def __init__(self):
                self.sink = Sink([("data", 32), ("charisk", 4)])
+
+               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
+               self.comb += [
+                       Cat(self.txdata, self.txcharisk).eq(tx_converter.source.raw),
+                       tx_converter.source.ack.eq(1),
+               ]
+
+               # clock domain crossing
+               tx_fifo = AsyncFIFO([("raw", 36)], 16)
+               self.submodules.tx_fifo = RenameClockDomains(tx_fifo, {"write": "sata", "read": "sata_tx"})
+               self.comb += [
+                       tx_fifo.source.connect(tx_converter.sink),
+                       self.tx_fifo.sink.stb.eq(1),
+               ]
+
+               # rearrange data
                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],