litesata: do some cleanup and prepare for RAID
This commit is contained in:
parent
d9b15e6ef6
commit
5daba9af68
|
@ -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)
|
|
@ -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)
|
||||
|
|
|
@ -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"],
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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]
|
||||
""")
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue