litesata: do some cleanup and prepare for RAID
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Sat, 23 May 2015 12:08:56 +0000 (14:08 +0200)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Sat, 23 May 2015 12:08:56 +0000 (14:08 +0200)
21 files changed:
misoclib/mem/litesata/__init__.py
misoclib/mem/litesata/core/__init__.py
misoclib/mem/litesata/core/link/__init__.py
misoclib/mem/litesata/example_designs/make.py
misoclib/mem/litesata/example_designs/platforms/kc705.py
misoclib/mem/litesata/example_designs/targets/bist.py
misoclib/mem/litesata/example_designs/targets/core.py
misoclib/mem/litesata/example_designs/test/bist.py
misoclib/mem/litesata/example_designs/test/test_la.py
misoclib/mem/litesata/example_designs/test/tools.py
misoclib/mem/litesata/frontend/bist.py
misoclib/mem/litesata/frontend/crossbar.py
misoclib/mem/litesata/phy/__init__.py
misoclib/mem/litesata/phy/ctrl.py
misoclib/mem/litesata/phy/k7/crg.py
misoclib/mem/litesata/phy/k7/trx.py
misoclib/mem/litesata/test/bist_tb.py
misoclib/mem/litesata/test/model/command.py
misoclib/mem/litesata/test/model/hdd.py
misoclib/mem/litesata/test/model/link.py
misoclib/mem/litesata/test/model/transport.py

index 21b64293ea1136fc3071b3a897e9b37868a3b529..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,21 +0,0 @@
-from misoclib.mem.litesata.common import *
-from misoclib.mem.litesata.phy import *
-from misoclib.mem.litesata.core import *
-from misoclib.mem.litesata.frontend import *
-
-from migen.bank.description import *
-
-
-class LiteSATA(Module, AutoCSR):
-    def __init__(self, phy, buffer_depth=2*fis_max_dwords,
-            with_bist=False, with_bist_csr=False):
-        # phy
-        self.phy = phy
-
-        # core
-        self.submodules.core = LiteSATACore(self.phy, buffer_depth)
-
-        # frontend
-        self.submodules.crossbar = LiteSATACrossbar(self.core)
-        if with_bist:
-            self.submodules.bist = LiteSATABIST(self.crossbar, with_bist_csr)
index e6834910337bfaaf3195dea8cbebf2c35478eb72..a3136f1baeed0418c78487085d87c3ab02e59573 100644 (file)
@@ -5,7 +5,7 @@ from misoclib.mem.litesata.core.command import LiteSATACommand
 
 
 class LiteSATACore(Module):
-    def __init__(self, phy, buffer_depth):
+    def __init__(self, phy, buffer_depth=2*fis_max_dwords):
         self.submodules.link = LiteSATALink(phy, buffer_depth)
         self.submodules.transport = LiteSATATransport(self.link)
         self.submodules.command = LiteSATACommand(self.transport)
index 5c8ec6e25ab04583bfb672efb0a6b8f2cb6d96dc..a723112e4a190773a22ded7b396d0d567cf52ed4 100644 (file)
@@ -41,6 +41,7 @@ class LiteSATALinkTX(Module):
 
         # datas / primitives mux
         insert = Signal(32)
+        copy = Signal()
         self.comb += [
             If(self.from_rx.insert,
                 cont.sink.stb.eq(1),
@@ -51,7 +52,7 @@ class LiteSATALinkTX(Module):
                 cont.sink.stb.eq(1),
                 cont.sink.data.eq(insert),
                 cont.sink.charisk.eq(0x0001),
-            ).Elif(fsm.ongoing("COPY"),
+            ).Elif(copy,
                 cont.sink.stb.eq(scrambler.source.stb),
                 cont.sink.data.eq(scrambler.source.d),
                 scrambler.source.ack.eq(cont.sink.ack),
@@ -87,6 +88,7 @@ class LiteSATALinkTX(Module):
             )
         )
         fsm.act("COPY",
+            copy.eq(1),
             If(self.from_rx.det == primitives["HOLD"],
                 insert.eq(primitives["HOLDA"]),
             ).Elif(~scrambler.source.stb,
@@ -145,12 +147,15 @@ class LiteSATALinkRX(Module):
         crc = LiteSATACRCChecker(link_description(32))
         self.submodules += crc
 
+        idle = Signal()
+        copy = Signal()
+
         sop = Signal()
         eop = Signal()
         self.sync += \
-            If(fsm.ongoing("IDLE"),
+            If(idle,
                 sop.eq(1),
-            ).Elif(fsm.ongoing("COPY"),
+            ).Elif(copy,
                 If(scrambler.sink.stb & scrambler.sink.ack,
                     sop.eq(0)
                 )
@@ -177,6 +182,7 @@ class LiteSATALinkRX(Module):
 
         # FSM
         fsm.act("IDLE",
+            idle.eq(1),
             scrambler.reset.eq(1),
             If(det == primitives["X_RDY"],
                 NextState("RDY")
@@ -199,6 +205,7 @@ class LiteSATALinkRX(Module):
             scrambler.sink.eop.eq(eop)
         ]
         fsm.act("COPY",
+            copy.eq(1),
             scrambler.sink.stb.eq(cont.source.stb & ((det == 0) | eop)),
             insert.eq(primitives["R_IP"]),
             If(det == primitives["HOLD"],
index 2a8b5829dc696b7ed65e9f2aae196c4ec8a43f7e..7bc247e20611273addb15c07426ca6fcaef7feb6 100755 (executable)
@@ -94,10 +94,10 @@ if __name__ == "__main__":
                 print("  "+a)
             sys.exit(1)
 
-
-    revision = soc.sata_phy.revision
-    has_bist = hasattr(soc.sata, "bist")
-    user_ports = len(soc.sata.crossbar.users)
+    try:
+        revision = soc.sata_phy.revision
+    except:
+        revision = soc.sata_phy0.revision
 
     print("""
        __   _ __      _______ _________
@@ -111,13 +111,9 @@ A small footprint and configurable SATA core
 ====== Building options: ======
 {} / {} Gbps
 System Clk: {} MHz (min: {} MHz)
-User ports: {}
-BIST: {}
 ===============================""".format(
     revision.replace("sata_", "SATA "), bitrates[revision],
-    soc.clk_freq/1000000, frequencies[revision],
-    user_ports,
-    has_bist
+    soc.clk_freq/1000000, frequencies[revision]
     )
 )
 
@@ -145,9 +141,9 @@ BIST: {}
             soc = soc.get_fragment()
         platform.finalize(soc)
         so = {
-            NoRetiming:                    XilinxNoRetiming,
-            MultiReg:                    XilinxMultiReg,
-            AsyncResetSynchronizer:        XilinxAsyncResetSynchronizer
+            NoRetiming:             XilinxNoRetiming,
+            MultiReg:               XilinxMultiReg,
+            AsyncResetSynchronizer: XilinxAsyncResetSynchronizer
         }
         v_output = verilog.convert(soc, ios, special_overrides=so)
         v_output.write("build/litesata.v")
index 0b22e643f54c62c5fdcc4082c83ec6fee48404fd..5ec1909618016fb2b70e324a597ce5d050ed1d7c 100644 (file)
@@ -2,13 +2,33 @@ from mibuild.generic_platform import *
 from mibuild.platforms import kc705
 
 _sata_io = [
-    ("sata", 0,
+    ("sata_clocks", 0,
         Subsignal("refclk_p", Pins("HPC:GBTCLK0_M2C_P")),
-        Subsignal("refclk_n", Pins("HPC:GBTCLK0_M2C_N")),
+        Subsignal("refclk_n", Pins("HPC:GBTCLK0_M2C_N"))
+    ),
+    ("sata", 0,
         Subsignal("txp", Pins("HPC:DP0_C2M_P")),
         Subsignal("txn", Pins("HPC:DP0_C2M_N")),
         Subsignal("rxp", Pins("HPC:DP0_M2C_P")),
-        Subsignal("rxn", Pins("HPC:DP0_M2C_N")),
+        Subsignal("rxn", Pins("HPC:DP0_M2C_N"))
+    ),
+    ("sata", 1,
+        Subsignal("txp", Pins("HPC:DP1_C2M_P")),
+        Subsignal("txn", Pins("HPC:DP1_C2M_N")),
+        Subsignal("rxp", Pins("HPC:DP1_M2C_P")),
+        Subsignal("rxn", Pins("HPC:DP1_M2C_N"))
+    ),
+    ("sata", 2,
+        Subsignal("txp", Pins("HPC:DP2_C2M_P")),
+        Subsignal("txn", Pins("HPC:DP2_C2M_N")),
+        Subsignal("rxp", Pins("HPC:DP2_M2C_P")),
+        Subsignal("rxn", Pins("HPC:DP2_M2C_N"))
+    ),
+    ("sata", 3,
+        Subsignal("txp", Pins("HPC:DP3_C2M_P")),
+        Subsignal("txn", Pins("HPC:DP3_C2M_N")),
+        Subsignal("rxp", Pins("HPC:DP3_M2C_P")),
+        Subsignal("rxn", Pins("HPC:DP3_M2C_N"))
     )
 ]
 
@@ -28,15 +48,6 @@ class Platform(kc705.Platform):
             except ConstraintError:
                 pass
             self.add_platform_command("""
-create_clock -name sys_clk -period 6 [get_nets sys_clk]
-create_clock -name sata_rx_clk -period 3.33 [get_nets sata_rx_clk]
-create_clock -name sata_tx_clk -period 3.33 [get_nets sata_tx_clk]
-
-set_false_path -from [get_clocks sys_clk] -to [get_clocks sata_rx_clk]
-set_false_path -from [get_clocks sys_clk] -to [get_clocks sata_tx_clk]
-set_false_path -from [get_clocks sata_rx_clk] -to [get_clocks sys_clk]
-set_false_path -from [get_clocks sata_tx_clk] -to [get_clocks sys_clk]
-
 set_property CFGBVS VCCO [current_design]
 set_property CONFIG_VOLTAGE 2.5 [current_design]
 """)
index 60f7fcd96bdc7157ce4f26ff3c79345307b27df9..2a1258ad57c25818ee3039a62ee751eff2b917d6 100644 (file)
@@ -13,7 +13,9 @@ from misoclib.com.uart.bridge import UARTWishboneBridge
 
 from misoclib.mem.litesata.common import *
 from misoclib.mem.litesata.phy import LiteSATAPHY
-from misoclib.mem.litesata import LiteSATA
+from misoclib.mem.litesata.core import LiteSATACore
+from misoclib.mem.litesata.frontend.crossbar import LiteSATACrossbar
+from misoclib.mem.litesata.frontend.bist import LiteSATABIST
 
 
 class _CRG(Module):
@@ -53,41 +55,31 @@ class _CRG(Module):
 
 
 class BISTLeds(Module):
-    def __init__(self, platform, sata_phy):
-        # 1Hz blinking leds (sata_rx and sata_tx clocks)
-        sata_rx_led = platform.request("user_led", 0)
-        sata_tx_led = platform.request("user_led", 1)
+    def __init__(self, platform, sata_phys):
+        for i, sata_phy in enumerate(sata_phys):
+            # 1Hz blinking leds (sata_rx and sata_tx clocks)
+            rx_led = platform.request("user_led", 2*i)
 
-        sata_rx_cnt = Signal(32)
-        sata_tx_cnt = Signal(32)
+            rx_cnt = Signal(32)
 
-        sata_freq = int(frequencies[sata_phy.revision]*1000*1000)
+            freq = int(frequencies[sata_phy.revision]*1000*1000)
 
-        self.sync.sata_rx += \
-            If(sata_rx_cnt == 0,
-                sata_rx_led.eq(~sata_rx_led),
-                sata_rx_cnt.eq(sata_freq//2)
-            ).Else(
-                sata_rx_cnt.eq(sata_rx_cnt-1)
-            )
+            self.sync.sata_rx += \
+                If(rx_cnt == 0,
+                    rx_led.eq(~rx_led),
+                    rx_cnt.eq(freq//2)
+                ).Else(
+                    rx_cnt.eq(rx_cnt-1)
+                )
 
-        self.sync.sata_tx += \
-            If(sata_tx_cnt == 0,
-                sata_tx_led.eq(~sata_tx_led),
-                sata_tx_cnt.eq(sata_freq//2)
-            ).Else(
-                sata_tx_cnt.eq(sata_tx_cnt-1)
-            )
-
-        # ready leds (crg and ctrl)
-        self.comb += platform.request("user_led", 2).eq(sata_phy.crg.ready)
-        self.comb += platform.request("user_led", 3).eq(sata_phy.ctrl.ready)
+            # ready leds
+            self.comb += platform.request("user_led", 2*i+1).eq(sata_phy.ctrl.ready)
 
 
 class BISTSoC(SoC, AutoCSR):
     default_platform = "kc705"
     csr_map = {
-        "sata":        10,
+        "sata_bist": 16
     }
     csr_map.update(SoC.csr_map)
     def __init__(self, platform):
@@ -104,16 +96,29 @@ class BISTSoC(SoC, AutoCSR):
         self.submodules.crg = _CRG(platform)
 
         # SATA PHY/Core/Frontend
-        self.submodules.sata_phy = LiteSATAPHY(platform.device, platform.request("sata"), "sata_gen2", clk_freq)
-        self.submodules.sata = LiteSATA(self.sata_phy, with_bist=True, with_bist_csr=True)
+        self.submodules.sata_phy = LiteSATAPHY(platform.device, platform.request("sata_clocks"), platform.request("sata", 0), "sata_gen2", clk_freq)
+        self.submodules.sata_core = LiteSATACore(self.sata_phy)
+        self.submodules.sata_crossbar = LiteSATACrossbar(self.sata_core)
+        self.submodules.sata_bist = LiteSATABIST(self.sata_crossbar, with_csr=True)
 
         # Status Leds
-        self.submodules.leds = BISTLeds(platform, self.sata_phy)
+        self.submodules.leds = BISTLeds(platform, [self.sata_phy])
+
+        platform.add_platform_command("""
+create_clock -name sys_clk -period 6 [get_nets sys_clk]
+
+create_clock -name sata_rx_clk -period 6.66 [get_nets sata_rx_clk]
+create_clock -name sata_tx_clk -period 6.66 [get_nets sata_tx_clk]
 
+set_false_path -from [get_clocks sys_clk] -to [get_clocks sata_rx_clk]
+set_false_path -from [get_clocks sys_clk] -to [get_clocks sata_tx_clk]
+set_false_path -from [get_clocks sata_rx_clk] -to [get_clocks sys_clk]
+set_false_path -from [get_clocks sata_tx_clk] -to [get_clocks sys_clk]
+""")
 
 class BISTSoCDevel(BISTSoC, AutoCSR):
     csr_map = {
-        "la":            20
+        "la": 17
     }
     csr_map.update(BISTSoC.csr_map)
     def __init__(self, platform):
index 67d7426ac1d18b6b21b75891a5a1c08a05e103b5..d841d4ecd944a6114fdd8f994c8c30d28da917d2 100644 (file)
@@ -2,22 +2,31 @@ from migen.genlib.resetsync import AsyncResetSynchronizer
 
 from targets import *
 
+from misoclib.soc import SoC
+
 from misoclib.mem.litesata.common import *
 from misoclib.mem.litesata.phy import LiteSATAPHY
-from misoclib.mem.litesata import LiteSATA
+from misoclib.mem.litesata.core import LiteSATACore
+from misoclib.mem.litesata.frontend.crossbar import LiteSATACrossbar
+from misoclib.mem.litesata.frontend.bist import LiteSATABIST
 
 
-class LiteSATACore(Module):
+class Core(Module):
     default_platform = "verilog_backend"
-    def __init__(self, platform, clk_freq=166*1000000, nports=4):
+    def __init__(self, platform, clk_freq=166*1000000, with_bist=True, nports=4):
         self.clk_freq = clk_freq
 
         # SATA PHY/Core/Frontend
         self.submodules.sata_phy = LiteSATAPHY(platform.device, platform.request("sata"), "sata_gen2", clk_freq)
-        self.submodules.sata = LiteSATA(self.sata_phy, with_bist=True)
+        self.submodules.sata_core = LiteSATACore(self.sata_phy)
+        self.submodules.sata_crossbar = LiteSATACrossbar(self.sata_core)
+
+        # BIST
+        if with_bist:
+            self.submodules.sata_bist = LiteSATABIST(self.sata_crossbar)
 
         # Get user ports from crossbar
-        self.user_ports = self.sata.crossbar.get_ports(nports)
+        self.user_ports = self.sata_crossbar.get_ports(nports)
 
     def get_ios(self):
         ios = set()
@@ -35,16 +44,16 @@ class LiteSATACore(Module):
         })
 
         # BIST
-        if hasattr(self.sata, "bist"):
+        if hasattr(self, "sata_bist"):
             for bist_unit in ["generator", "checker"]:
                 for signal in ["start", "sector", "count", "random", "done", "aborted", "errors"]:
-                    ios = ios.union({getattr(getattr(self.sata.bist, bist_unit), signal)})
+                    ios = ios.union({getattr(getattr(self.sata_bist, bist_unit), signal)})
             ios = ios.union({
-                self.sata.bist.identify.start,
-                self.sata.bist.identify.done,
-                self.sata.bist.identify.source.stb,
-                self.sata.bist.identify.source.data,
-                self.sata.bist.identify.source.ack
+                self.sata_bist.identify.start,
+                self.sata_bist.identify.done,
+                self.sata_bist.identify.source.stb,
+                self.sata_bist.identify.source.data,
+                self.sata_bist.identify.source.ack
             })
 
         # User ports
@@ -62,4 +71,4 @@ class LiteSATACore(Module):
                     ios = ios.union({obj})
         return ios
 
-default_subtarget = LiteSATACore
+default_subtarget = Core
index db8f7f86fd080562dcf154025033aa7c5caa54ab..7c843c49b68880e190a2be73a41d99d7ff70ed4d 100644 (file)
@@ -72,7 +72,7 @@ class LiteSATABISTIdentifyDriver:
     def __init__(self, regs, name):
         self.regs = regs
         self.name = name
-        for s in ["start", "done", "source_stb", "source_ack", "source_data"]:
+        for s in ["start", "done", "data_width", "source_stb", "source_ack", "source_data"]:
             setattr(self, s, getattr(regs, name + "_identify_" + s))
         self.data = []
 
@@ -189,11 +189,12 @@ if __name__ == "__main__":
                     if not read_done:
                         retry += 1
 
+                ratio = identify.data_width.read()//32
                 print("sector={:d}({:d}MB) wr_speed={:4.2f}MB/s rd_speed={:4.2f}MB/s errors={:d} retry={:d}".format(
                     sector,
-                    int(run_sectors*logical_sector_size/MB),
-                    write_speed/MB,
-                    read_speed/MB,
+                    int(run_sectors*logical_sector_size/MB)*ratio,
+                    write_speed/MB*ratio,
+                    read_speed/MB*ratio,
                     write_errors + read_errors,
                     retry))
                 if random_addressing:
index 10f3a214e71700e29a45bb2dc87d5a81ee318a95..f399290db5e2ee43220a1d9285d4c7b6a41155d1 100644 (file)
@@ -1,11 +1,11 @@
 import sys
 from tools import *
-from test_bist import *
-from litescope.software.driver.la import LiteScopeLADriver
+from bist import *
+from misoclib.tools.litescope.software.driver.la import LiteScopeLADriver
 
 
 def main(wb):
-    la = LiteScopeLADriver(wb.regs, "la")
+    la = LiteScopeLADriver(wb.regs, "la", debug=True)
     identify = LiteSATABISTIdentifyDriver(wb.regs, "sata_bist")
     generator = LiteSATABISTGeneratorDriver(wb.regs, "sata_bist")
     checker = LiteSATABISTCheckerDriver(wb.regs, "sata_bist")
index 845ab12873d1a4be51c5b12eaeaee607dc278c24..ec24ad0f8d69174d2465102a94a46235e92a5a9f 100644 (file)
@@ -1,4 +1,4 @@
-from litescope.software.dump import *
+from misoclib.tools.litescope.software.dump import *
 
 primitives = {
     "ALIGN":  0x7B4A4ABC,
@@ -25,10 +25,10 @@ def decode_primitive(dword):
     return ""
 
 
-def link_trace(mila, tx_data_name, rx_data_name):
+def link_trace(la, tx_data_name, rx_data_name):
     r = ""
     dump = Dump()
-    dump.add_from_layout(mila.layout, mila.dat)
+    dump.add_from_layout(la.layout, la.data)
 
     for var in dump.vars:
         if var.name == tx_data_name:
index 4655cf01578a30752c3cfcdee721db128622ab6d..dba00bd19e80356177338ba212588f31f07866c5 100644 (file)
@@ -17,6 +17,8 @@ class LiteSATABISTGenerator(Module):
 
         # # #
 
+        n = flen(user_port.sink.data)//32
+
         source, sink = user_port.sink, user_port.source
 
         counter = Counter(32)
@@ -45,9 +47,9 @@ class LiteSATABISTGenerator(Module):
             source.sector.eq(self.sector),
             source.count.eq(self.count),
             If(self.random,
-                source.data.eq(scrambler.value)
+                source.data.eq(Replicate(scrambler.value, n))
             ).Else(
-                source.data.eq(counter.value)
+                source.data.eq(Replicate(counter.value, n))
             )
         ]
         fsm.act("SEND_CMD_AND_DATA",
@@ -81,6 +83,8 @@ class LiteSATABISTChecker(Module):
 
         # # #
 
+        n = flen(user_port.sink.data)//32
+
         source, sink = user_port.sink, user_port.source
 
         counter = Counter(32)
@@ -124,12 +128,12 @@ class LiteSATABISTChecker(Module):
                 NextState("RECEIVE_DATA")
             )
         )
-        expected_data = Signal(32)
+        expected_data = Signal(n*32)
         self.comb += \
             If(self.random,
-                expected_data.eq(scrambler.value)
+                expected_data.eq(Replicate(scrambler.value, n))
             ).Else(
-                expected_data.eq(counter.value)
+                expected_data.eq(Replicate(counter.value, n))
             )
         fsm.act("RECEIVE_DATA",
             sink.ack.eq(1),
@@ -221,6 +225,7 @@ class LiteSATABISTIdentify(Module):
     def __init__(self, user_port):
         self.start = Signal()
         self.done  = Signal()
+        self.data_width = flen(user_port.sink.data)
 
         fifo = SyncFIFO([("data", 32)], 512, buffered=True)
         self.submodules += fifo
@@ -270,6 +275,7 @@ class LiteSATABISTIdentifyCSR(Module, AutoCSR):
     def __init__(self, bist_identify):
         self._start = CSR()
         self._done = CSRStatus()
+        self._data_width = CSRStatus(16, reset=bist_identify.data_width)
         self._source_stb = CSRStatus()
         self._source_ack = CSR()
         self._source_data = CSRStatus(32)
index ba6db6ad650fade125e0213eac05ed44f0727c99..a2ac790b39768376e2e2cfef077b42445269d762 100644 (file)
@@ -4,16 +4,17 @@ from misoclib.mem.litesata.frontend.arbiter import LiteSATAArbiter
 
 
 class LiteSATACrossbar(Module):
-    def __init__(self, core):
+    def __init__(self, controller):
+        self.dw = flen(controller.sink.data)
         self.users = []
-        self.master = LiteSATAMasterPort(32)
+        self.master = LiteSATAMasterPort(self.dw)
         self.comb += [
-            self.master.source.connect(core.sink),
-            core.source.connect(self.master.sink)
+            self.master.source.connect(controller.sink),
+            controller.source.connect(self.master.sink)
         ]
 
     def get_port(self):
-        port = LiteSATAUserPort(32)
+        port = LiteSATAUserPort(self.dw)
         self.users += [port]
         return port
 
index 4e952d4dea5af10e6dc234362f106ee7261973be..3f9b1a7cccb458b0fdbb0e4ede499eed120c8e98 100644 (file)
@@ -4,7 +4,7 @@ from misoclib.mem.litesata.phy.datapath import *
 
 
 class LiteSATAPHY(Module):
-    def __init__(self, device, pads, revision, clk_freq):
+    def __init__(self, device, clock_pads_or_refclk, pads, revision, clk_freq):
         self.pads = pads
         self.revision = revision
 
@@ -13,7 +13,7 @@ class LiteSATAPHY(Module):
             from misoclib.mem.litesata.phy.k7.trx import K7LiteSATAPHYTRX
             from misoclib.mem.litesata.phy.k7.crg import K7LiteSATAPHYCRG
             self.submodules.trx = K7LiteSATAPHYTRX(pads, revision)
-            self.submodules.crg = K7LiteSATAPHYCRG(pads, self.trx, revision, clk_freq)
+            self.submodules.crg = K7LiteSATAPHYCRG(clock_pads_or_refclk, pads, self.trx, revision, clk_freq)
         else:
             raise NotImplementedError
 
index 755f5271b911f77ad2b77f23f79b19f1d4d4022f..7e26ee716aa6b5acda3b4552b112f737f5371663 100644 (file)
@@ -19,11 +19,19 @@ class LiteSATAPHYCtrl(Module):
         align_timer = WaitTimer(self.us(873))
         self.submodules += align_timer, retry_timer
 
-        align_detect = Signal()
-        non_align_cnt = Signal(4)
+        align_det = Signal()
+        misalign_det = Signal()
         non_align_counter = Counter(4)
         self.submodules += non_align_counter
 
+        self.comb +=  [
+            If(sink.stb,
+                align_det.eq((self.sink.charisk == 0b0001) &
+                                (self.sink.data == primitives["ALIGN"])),
+                misalign_det.eq((self.sink.charisk & 0b1010) != 0)
+            )
+        ]
+
         self.fsm = fsm = InsertReset(FSM(reset_state="RESET"))
         self.submodules += fsm
         self.comb += fsm.reset.eq(retry_timer.done | align_timer.done)
@@ -96,7 +104,7 @@ class LiteSATAPHYCtrl(Module):
             source.charisk.eq(0b0000),
             trx.rx_align.eq(1),
             align_timer.wait.eq(1),
-            If(align_detect & ~trx.rx_idle,
+            If(align_det & ~trx.rx_idle,
                 NextState("SEND_ALIGN")
             )
         )
@@ -117,19 +125,33 @@ class LiteSATAPHYCtrl(Module):
                 NextState("READY")
             )
         )
+
+        # wait alignement stability for 100ms before declaring ctrl is ready,
+        # reset the RX part of the transceiver when misalignment is detected.
+        stability_timer = WaitTimer(100*clk_freq//1000)
+        self.submodules += stability_timer
+
         fsm.act("READY",
             trx.tx_idle.eq(0),
             trx.rx_align.eq(1),
             source.data.eq(primitives["SYNC"]),
             source.charisk.eq(0b0001),
-            self.ready.eq(1),
+            stability_timer.wait.eq(1),
+            self.ready.eq(stability_timer.done),
             If(trx.rx_idle,
-               NextState("RESET"),
-                       )
+                NextState("RESET"),
+            ).Elif(misalign_det,
+                crg.rx_reset.eq(1),
+                NextState("REALIGN")
+            )
+        )
+        fsm.act("REALIGN",
+            If(crg.ready,
+                NextState("READY")
+            )
         )
 
-        self.comb +=  align_detect.eq(self.sink.stb &
-                                     (self.sink.data == primitives["ALIGN"]))
+
 
     def us(self, t):
         clk_period_us = 1000000/self.clk_freq
index bd853af5bdebbe828dd8d348a3f6587b07826ff2..7e849c92c20906027e4dd64950facd82ea5934fa 100644 (file)
@@ -2,7 +2,7 @@ from misoclib.mem.litesata.common import *
 
 
 class K7LiteSATAPHYCRG(Module):
-    def __init__(self, pads, gtx, revision, clk_freq):
+    def __init__(self, clock_pads_or_refclk, pads, gtx, revision, clk_freq):
         self.tx_reset = Signal()
         self.rx_reset = Signal()
         self.ready = Signal()
@@ -14,14 +14,19 @@ class K7LiteSATAPHYCRG(Module):
         #   (sata_gen3) 150MHz / VCO @ 3GHz / Line rate @ 6Gbps
         #   (sata_gen2 & sata_gen1) 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)
+        if isinstance(clock_pads_or_refclk, Signal):
+            self.refclk = clock_pads_or_refclk
+        else:
+            self.refclk = Signal()
+            clock_pads = clock_pads_or_refclk
+            self.specials += Instance("IBUFDS_GTE2",
+                i_CEB=0,
+                i_I=clock_pads.refclk_p,
+                i_IB=clock_pads.refclk_n,
+                o_O=self.refclk
+            )
+
+        self.comb += gtx.gtrefclk0.eq(self.refclk)
 
         # TX clocking
         #   (sata_gen3) 150MHz from CPLL TXOUTCLK, sata_tx clk @ 300MHz (16-bits)
index d3a34ca01090022eda85aacbfc982462f0764a35..1ca9c9f475ff85fe7d4696df705db010ae25cea3 100644 (file)
@@ -127,7 +127,7 @@ class K7LiteSATAPHYTRX(Module):
         cdr_config = {
             "sata_gen1": 0x0380008BFF40100008,
             "sata_gen2": 0x0388008BFF40200008,
-            "sata_gen3": 0X0380008BFF10200010
+            "sata_gen3": 0x0380008BFF10200010
         }
         rxcdr_cfg = cdr_config[revision]
 
@@ -352,7 +352,7 @@ class K7LiteSATAPHYTRX(Module):
                     "p_RXDLY_LCFG": 0x30,
                     "p_RXDLY_TAP_CFG": 0,
                     "p_RXPH_CFG": 0,
-                    "p_RXPHDLY_CFG": 0x084820,
+                    "p_RXPHDLY_CFG": 0x084020,
                     "p_RXPH_MONITOR_SEL": 0,
                     "p_RX_XCLK_SEL": "RXUSR",
                     "p_RX_DDI_SEL": 0,
@@ -405,7 +405,7 @@ class K7LiteSATAPHYTRX(Module):
 
                 # TX Buffer Attributes
                     "p_TXBUF_EN": "FALSE",
-                    "p_TXBUF_RESET_ON_RATE_CHANGE": "TRUE",
+                    "p_TXBUF_RESET_ON_RATE_CHANGE": "FALSE",
                     "p_TXDLY_CFG": 0x1f,
                     "p_TXDLY_LCFG": 0x030,
                     "p_TXDLY_TAP_CFG": 0,
@@ -471,7 +471,7 @@ class K7LiteSATAPHYTRX(Module):
                     "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_LPM_HOLD_DURING_EIDLE": 1,
                     "p_RX_DFE_UT_CFG": 0b10001111000000000,
                     "p_RX_DFE_VP_CFG": 0b00011111100000011,
 
index 2b89c5fa0211b2861f8ff557b1e6a9e983e560c1..230753c78f0ce53790a85d2988c1b707808fe7d2 100644 (file)
@@ -1,5 +1,6 @@
 from misoclib.mem.litesata.common import *
-from misoclib.mem.litesata import LiteSATA
+from misoclib.mem.litesata.core import LiteSATACore
+from misoclib.mem.litesata.frontend.crossbar import LiteSATACrossbar
 from misoclib.mem.litesata.frontend.bist import LiteSATABISTGenerator, LiteSATABISTChecker
 
 from misoclib.mem.litesata.test.common import *
@@ -12,35 +13,43 @@ class TB(Module):
                 link_debug=False, link_random_level=0,
                 transport_debug=False, transport_loopback=False,
                 hdd_debug=True)
-        self.submodules.controller = LiteSATA(self.hdd.phy)
-        self.submodules.generator = LiteSATABISTGenerator(self.controller.crossbar.get_port())
-        self.submodules.checker = LiteSATABISTChecker(self.controller.crossbar.get_port())
+        self.submodules.core = LiteSATACore(self.hdd.phy)
+        self.submodules.crossbar = LiteSATACrossbar(self.core)
+        self.submodules.generator = LiteSATABISTGenerator(self.crossbar.get_port())
+        self.submodules.checker = LiteSATABISTChecker(self.crossbar.get_port())
 
     def gen_simulation(self, selfp):
         hdd = self.hdd
         hdd.malloc(0, 64)
-        selfp.generator.sector = 0
-        selfp.generator.count = 17
-        selfp.checker.sector = 0
-        selfp.checker.count = 17
+        sector = 0
+        count = 17
+        generator = selfp.generator
+        checker = selfp.checker
         while True:
-            selfp.generator.start = 1
+            # write data
+            generator.sector = sector
+            generator.count = count
+            generator.start = 1
             yield
-            selfp.generator.start = 0
+            generator.start = 0
             yield
-            while selfp.generator.done == 0:
+            while generator.done == 0:
                 yield
-            selfp.checker.start = 1
+
+            # verify data
+            checker.sector = sector
+            checker.count = count
+            checker.start = 1
             yield
-            selfp.checker.start = 0
+            checker.start = 0
             yield
-            while selfp.checker.done == 0:
+            while checker.done == 0:
                 yield
-            print("errors {}".format(selfp.checker.errors))
-            selfp.generator.sector += 1
-            selfp.generator.count = max((selfp.generator.count + 1)%8, 1)
-            selfp.checker.sector += 1
-            selfp.checker.count = max((selfp.checker.count + 1)%8, 1)
+            print("errors {}".format(checker.errors))
+
+            # prepare next iteration
+            sector += 1
+            count = max((count + 1)%8, 1)
 
 if __name__ == "__main__":
     run_simulation(TB(), ncycles=8192*2, vcd_name="my.vcd", keep_files=True)
index e718c12ce14bd2e78f317dddbca4dc1e727a13ed..4304fb98ff825b519776dc5952bf55f9dc8adde0 100644 (file)
@@ -3,15 +3,19 @@ from misoclib.mem.litesata.test.common import *
 
 from misoclib.mem.litesata.test.model.transport import FIS_REG_H2D, FIS_DATA
 
+
 class CommandLayer(Module):
     def __init__(self, transport):
         self.transport = transport
-        self.transport.set_command_callback(self.callback)
+        self.transport.set_command(self)
 
         self.hdd = None
+        self.n = None
 
     def set_hdd(self, hdd):
         self.hdd = hdd
+        self.transport.n = hdd.n
+        self.transport.link.n = hdd.n
 
     def callback(self, fis):
         resp = None
index 2f884f5d4a350eb51f50553a915acd2aadd32b16..ad564c8208725ccc5ca95d2ca21160c9b8ac96b9 100644 (file)
@@ -8,8 +8,9 @@ from misoclib.mem.litesata.test.model.link import *
 from misoclib.mem.litesata.test.model.transport import *
 from misoclib.mem.litesata.test.model.command import *
 
-def print_hdd(s):
-    print_with_prefix(s, "[HDD]: ")
+
+def print_hdd(s, n=None):
+    print_with_prefix(s, "[HDD{}]: ".format("" if n is None else str(n)))
 
 
 class HDDMemRegion:
@@ -20,11 +21,12 @@ class HDDMemRegion:
 
 
 class HDD(Module):
-    def __init__(self,
+    def __init__(self, n=None,
             link_debug=False, link_random_level=0,
             transport_debug=False, transport_loopback=False,
             hdd_debug=False,
             ):
+        self.n = n
         self.submodules.phy = PHYLayer()
         self.submodules.link = LinkLayer(self.phy, link_debug, link_random_level)
         self.submodules.transport = TransportLayer(self.link, transport_debug, transport_loopback)
@@ -43,7 +45,7 @@ class HDD(Module):
         if self.debug:
             s = "Allocating {n} sectors: {s} to {e}".format(n=count, s=sector, e=sector+count-1)
             s += " ({} KB)".format(count*logical_sector_size//1024)
-            print_hdd(s)
+            print_hdd(s, self.n)
         self.mem = HDDMemRegion(sector, count, logical_sector_size)
 
     def write(self, sector, data):
@@ -53,7 +55,7 @@ class HDD(Module):
                 s = "{}".format(sector)
             else:
                 s = "{s} to {e}".format(s=sector, e=sector+n-1)
-            print_hdd("Writing sector " + s)
+            print_hdd("Writing sector " + s, self.n)
         for i in range(len(data)):
             offset = sectors2dwords(sector)
             self.mem.data[offset+i] = data[i]
@@ -64,7 +66,7 @@ class HDD(Module):
                 s = "{}".format(sector)
             else:
                 s = "{s} to {e}".format(s=sector, e=sector+count-1)
-            print_hdd("Reading sector " + s)
+            print_hdd("Reading sector " + s, self.n)
         data = []
         for i in range(sectors2dwords(count)):
             data.append(self.mem.data[sectors2dwords(sector)+i])
index a97816d0ecc1754ccab25ca23648d99e5b57a487..8ad2a5f54bf7b3c5704edaf009106c9a9e5a69be 100644 (file)
@@ -4,8 +4,9 @@ import math
 from misoclib.mem.litesata.common import *
 from misoclib.mem.litesata.test.common import *
 
-def print_link(s):
-    print_with_prefix(s, "[LNK]: ")
+
+def print_link(s, n=None):
+    print_with_prefix(s, "[LNK{}]: ".format("" if n is None else str(n)))
 
 
 def import_scrambler_datas():
@@ -91,13 +92,14 @@ class LinkLayer(Module):
 
         self.scrambled_datas = import_scrambler_datas()
 
-        self.transport_callback = None
+        self.transport = None
+        self.n = None
 
         self.send_state = ""
         self.send_states = ["RDY", "SOF", "DATA", "EOF", "WTRM"]
 
-    def set_transport_callback(self, callback):
-        self.transport_callback = callback
+    def set_transport(self, transport):
+        self.transport = transport
 
     def send(self, dword):
         if self.send_state == "RDY":
@@ -164,8 +166,8 @@ class LinkLayer(Module):
             self.phy.send(primitives["R_OK"])
             if self.rx_packet.ongoing:
                 self.rx_packet.decode()
-                if self.transport_callback is not None:
-                    self.transport_callback(self.rx_packet)
+                if self.transport is not None:
+                    self.transport.callback(self.rx_packet)
                 self.rx_packet.ongoing = False
         elif dword == primitives["HOLD"]:
             self.phy.send(primitives["HOLDA"])
@@ -190,7 +192,7 @@ class LinkLayer(Module):
         while True:
             yield from self.phy.receive()
             if self.debug:
-                print_link(self.phy)
+                print_link(self.phy, self.n)
             self.phy.send(primitives["SYNC"])
             rx_dword = self.phy.rx.dword.dat
             rx_dword = self.remove_cont(rx_dword)
index 830c2f72628317bc0788e79bcd3fc0308e3d1434..97cdaaf73822e6b39cf6d84046ef9565c05385f0 100644 (file)
@@ -3,8 +3,9 @@ from misoclib.mem.litesata.test.common import *
 
 from misoclib.mem.litesata.test.model.link import LinkTXPacket
 
-def print_transport(s):
-    print_with_prefix(s, "[TRN]: ")
+
+def print_transport(s, n=None):
+    print_with_prefix(s, "[TRN{}]: ".format("" if n is None else str(n)))
 
 
 def get_field_data(field, packet):
@@ -105,17 +106,20 @@ class TransportLayer(Module):
         self.link = link
         self.debug = debug
         self.loopback = loopback
-        self.link.set_transport_callback(self.callback)
+        self.link.set_transport(self)
+
+        self.command = None
+        self.n = None
 
-    def set_command_callback(self, callback):
-        self.command_callback = callback
+    def set_command(self, command):
+        self.command = command
 
     def send(self, fis):
         fis.encode()
         packet = LinkTXPacket(fis.packet)
         self.link.tx_packets.append(packet)
         if self.debug and not self.loopback:
-            print_transport(fis)
+            print_transport(fis, self.n)
 
     def callback(self, packet):
         fis_type = packet[0] & 0xff
@@ -130,8 +134,8 @@ class TransportLayer(Module):
         else:
             fis = FIS_UNKNOWN(packet, direction="H2D")
         if self.debug:
-            print_transport(fis)
+            print_transport(fis, self.n)
         if self.loopback:
             self.send(fis)
         else:
-            self.command_callback(fis)
+            self.command.callback(fis)