From 5daba9af68e8577c3933fd63eab1f273b43e14ab Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Sat, 23 May 2015 14:08:56 +0200 Subject: [PATCH] litesata: do some cleanup and prepare for RAID --- misoclib/mem/litesata/__init__.py | 21 ------ misoclib/mem/litesata/core/__init__.py | 2 +- misoclib/mem/litesata/core/link/__init__.py | 13 +++- misoclib/mem/litesata/example_designs/make.py | 20 +++--- .../example_designs/platforms/kc705.py | 35 ++++++---- .../litesata/example_designs/targets/bist.py | 67 ++++++++++--------- .../litesata/example_designs/targets/core.py | 35 ++++++---- .../mem/litesata/example_designs/test/bist.py | 9 +-- .../litesata/example_designs/test/test_la.py | 6 +- .../litesata/example_designs/test/tools.py | 6 +- misoclib/mem/litesata/frontend/bist.py | 16 +++-- misoclib/mem/litesata/frontend/crossbar.py | 11 +-- misoclib/mem/litesata/phy/__init__.py | 4 +- misoclib/mem/litesata/phy/ctrl.py | 38 ++++++++--- misoclib/mem/litesata/phy/k7/crg.py | 23 ++++--- misoclib/mem/litesata/phy/k7/trx.py | 8 +-- misoclib/mem/litesata/test/bist_tb.py | 47 +++++++------ misoclib/mem/litesata/test/model/command.py | 6 +- misoclib/mem/litesata/test/model/hdd.py | 14 ++-- misoclib/mem/litesata/test/model/link.py | 18 ++--- misoclib/mem/litesata/test/model/transport.py | 20 +++--- 21 files changed, 241 insertions(+), 178 deletions(-) diff --git a/misoclib/mem/litesata/__init__.py b/misoclib/mem/litesata/__init__.py index 21b64293e..e69de29bb 100644 --- a/misoclib/mem/litesata/__init__.py +++ b/misoclib/mem/litesata/__init__.py @@ -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) diff --git a/misoclib/mem/litesata/core/__init__.py b/misoclib/mem/litesata/core/__init__.py index e68349103..a3136f1ba 100644 --- a/misoclib/mem/litesata/core/__init__.py +++ b/misoclib/mem/litesata/core/__init__.py @@ -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) diff --git a/misoclib/mem/litesata/core/link/__init__.py b/misoclib/mem/litesata/core/link/__init__.py index 5c8ec6e25..a723112e4 100644 --- a/misoclib/mem/litesata/core/link/__init__.py +++ b/misoclib/mem/litesata/core/link/__init__.py @@ -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"], diff --git a/misoclib/mem/litesata/example_designs/make.py b/misoclib/mem/litesata/example_designs/make.py index 2a8b5829d..7bc247e20 100755 --- a/misoclib/mem/litesata/example_designs/make.py +++ b/misoclib/mem/litesata/example_designs/make.py @@ -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") diff --git a/misoclib/mem/litesata/example_designs/platforms/kc705.py b/misoclib/mem/litesata/example_designs/platforms/kc705.py index 0b22e643f..5ec190961 100644 --- a/misoclib/mem/litesata/example_designs/platforms/kc705.py +++ b/misoclib/mem/litesata/example_designs/platforms/kc705.py @@ -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] """) diff --git a/misoclib/mem/litesata/example_designs/targets/bist.py b/misoclib/mem/litesata/example_designs/targets/bist.py index 60f7fcd96..2a1258ad5 100644 --- a/misoclib/mem/litesata/example_designs/targets/bist.py +++ b/misoclib/mem/litesata/example_designs/targets/bist.py @@ -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): diff --git a/misoclib/mem/litesata/example_designs/targets/core.py b/misoclib/mem/litesata/example_designs/targets/core.py index 67d7426ac..d841d4ecd 100644 --- a/misoclib/mem/litesata/example_designs/targets/core.py +++ b/misoclib/mem/litesata/example_designs/targets/core.py @@ -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 diff --git a/misoclib/mem/litesata/example_designs/test/bist.py b/misoclib/mem/litesata/example_designs/test/bist.py index db8f7f86f..7c843c49b 100644 --- a/misoclib/mem/litesata/example_designs/test/bist.py +++ b/misoclib/mem/litesata/example_designs/test/bist.py @@ -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: diff --git a/misoclib/mem/litesata/example_designs/test/test_la.py b/misoclib/mem/litesata/example_designs/test/test_la.py index 10f3a214e..f399290db 100644 --- a/misoclib/mem/litesata/example_designs/test/test_la.py +++ b/misoclib/mem/litesata/example_designs/test/test_la.py @@ -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") diff --git a/misoclib/mem/litesata/example_designs/test/tools.py b/misoclib/mem/litesata/example_designs/test/tools.py index 845ab1287..ec24ad0f8 100644 --- a/misoclib/mem/litesata/example_designs/test/tools.py +++ b/misoclib/mem/litesata/example_designs/test/tools.py @@ -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: diff --git a/misoclib/mem/litesata/frontend/bist.py b/misoclib/mem/litesata/frontend/bist.py index 4655cf015..dba00bd19 100644 --- a/misoclib/mem/litesata/frontend/bist.py +++ b/misoclib/mem/litesata/frontend/bist.py @@ -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) diff --git a/misoclib/mem/litesata/frontend/crossbar.py b/misoclib/mem/litesata/frontend/crossbar.py index ba6db6ad6..a2ac790b3 100644 --- a/misoclib/mem/litesata/frontend/crossbar.py +++ b/misoclib/mem/litesata/frontend/crossbar.py @@ -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 diff --git a/misoclib/mem/litesata/phy/__init__.py b/misoclib/mem/litesata/phy/__init__.py index 4e952d4de..3f9b1a7cc 100644 --- a/misoclib/mem/litesata/phy/__init__.py +++ b/misoclib/mem/litesata/phy/__init__.py @@ -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 diff --git a/misoclib/mem/litesata/phy/ctrl.py b/misoclib/mem/litesata/phy/ctrl.py index 755f5271b..7e26ee716 100644 --- a/misoclib/mem/litesata/phy/ctrl.py +++ b/misoclib/mem/litesata/phy/ctrl.py @@ -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 diff --git a/misoclib/mem/litesata/phy/k7/crg.py b/misoclib/mem/litesata/phy/k7/crg.py index bd853af5b..7e849c92c 100644 --- a/misoclib/mem/litesata/phy/k7/crg.py +++ b/misoclib/mem/litesata/phy/k7/crg.py @@ -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) diff --git a/misoclib/mem/litesata/phy/k7/trx.py b/misoclib/mem/litesata/phy/k7/trx.py index d3a34ca01..1ca9c9f47 100644 --- a/misoclib/mem/litesata/phy/k7/trx.py +++ b/misoclib/mem/litesata/phy/k7/trx.py @@ -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, diff --git a/misoclib/mem/litesata/test/bist_tb.py b/misoclib/mem/litesata/test/bist_tb.py index 2b89c5fa0..230753c78 100644 --- a/misoclib/mem/litesata/test/bist_tb.py +++ b/misoclib/mem/litesata/test/bist_tb.py @@ -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) diff --git a/misoclib/mem/litesata/test/model/command.py b/misoclib/mem/litesata/test/model/command.py index e718c12ce..4304fb98f 100644 --- a/misoclib/mem/litesata/test/model/command.py +++ b/misoclib/mem/litesata/test/model/command.py @@ -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 diff --git a/misoclib/mem/litesata/test/model/hdd.py b/misoclib/mem/litesata/test/model/hdd.py index 2f884f5d4..ad564c820 100644 --- a/misoclib/mem/litesata/test/model/hdd.py +++ b/misoclib/mem/litesata/test/model/hdd.py @@ -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]) diff --git a/misoclib/mem/litesata/test/model/link.py b/misoclib/mem/litesata/test/model/link.py index a97816d0e..8ad2a5f54 100644 --- a/misoclib/mem/litesata/test/model/link.py +++ b/misoclib/mem/litesata/test/model/link.py @@ -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) diff --git a/misoclib/mem/litesata/test/model/transport.py b/misoclib/mem/litesata/test/model/transport.py index 830c2f726..97cdaaf73 100644 --- a/misoclib/mem/litesata/test/model/transport.py +++ b/misoclib/mem/litesata/test/model/transport.py @@ -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) - def set_command_callback(self, callback): - self.command_callback = callback + self.command = None + self.n = None + + 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)