make ctrl/datapath in phy vendor agnostics and simplify imports
This commit is contained in:
parent
9789a78aab
commit
4f22bc807a
|
@ -1,5 +1,3 @@
|
|||
from migen.fhdl.std import *
|
||||
|
||||
from lib.sata.common import *
|
||||
from lib.sata.link import SATALink
|
||||
from lib.sata.transport import SATATransport
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
from migen.fhdl.std import *
|
||||
from migen.genlib.fsm import FSM, NextState
|
||||
|
||||
from lib.sata.common import *
|
||||
from lib.sata.link.scrambler import Scrambler
|
||||
|
||||
|
|
|
@ -1,7 +1,3 @@
|
|||
from migen.fhdl.std import *
|
||||
from migen.genlib.fsm import FSM, NextState
|
||||
from migen.actorlib.fifo import SyncFIFO as FIFO
|
||||
|
||||
from lib.sata.common import *
|
||||
|
||||
tx_to_rx = [
|
||||
|
@ -122,7 +118,7 @@ class SATACommandRX(Module):
|
|||
|
||||
###
|
||||
|
||||
cmd_fifo = FIFO(command_rx_cmd_description(32), 2) # Note: ideally depth=1
|
||||
cmd_fifo = SyncFIFO(command_rx_cmd_description(32), 2) # Note: ideally depth=1
|
||||
data_fifo = InsertReset(FIFO(command_rx_data_description(32), sector_size*max_count//4, buffered=True))
|
||||
self.submodules += cmd_fifo, data_fifo
|
||||
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
from migen.fhdl.std import *
|
||||
from migen.genlib.resetsync import *
|
||||
from migen.genlib.fsm import *
|
||||
from migen.genlib.record import *
|
||||
from migen.flow.actor import *
|
||||
from migen.actorlib.fifo import *
|
||||
|
||||
# PHY / Link Layers
|
||||
primitives = {
|
||||
|
|
|
@ -1,7 +1,3 @@
|
|||
from migen.fhdl.std import *
|
||||
from migen.genlib.fsm import FSM, NextState
|
||||
from migen.actorlib.fifo import SyncFIFO
|
||||
|
||||
from lib.sata.common import *
|
||||
from lib.sata.link.crc import SATACRCInserter, SATACRCChecker
|
||||
from lib.sata.link.scrambler import SATAScrambler
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
from migen.fhdl.std import *
|
||||
from migen.genlib.misc import optree
|
||||
|
||||
from lib.sata.common import *
|
||||
from lib.sata.link.scrambler import Scrambler
|
||||
|
||||
from migen.genlib.misc import optree
|
||||
|
||||
class SATACONTInserter(Module):
|
||||
def __init__(self, description):
|
||||
self.sink = sink = Sink(description)
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
from migen.fhdl.std import *
|
||||
from lib.sata.common import *
|
||||
|
||||
from migen.genlib.misc import optree
|
||||
from migen.actorlib.crc import CRCInserter, CRCChecker
|
||||
|
||||
from lib.sata.common import *
|
||||
|
||||
class CRCEngine(Module):
|
||||
"""Cyclic Redundancy Check Engine
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
from lib.sata.common import *
|
||||
|
||||
from migen.fhdl.std import *
|
||||
from migen.genlib.misc import optree
|
||||
|
||||
from lib.sata.common import *
|
||||
|
||||
@DecorateModule(InsertCE)
|
||||
class Scrambler(Module):
|
||||
"""SATA Scrambler
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
from lib.sata.common import *
|
||||
from lib.sata.phy.ctrl import SATAPHYHostCtrl, SATAPHYDeviceCtrl
|
||||
from lib.sata.phy.datapath import SATAPHYDatapath
|
||||
|
||||
class SATAPHY(Module):
|
||||
def __init__(self, pads, clk_freq, host=True, device_family="k7", speed="SATA1"):
|
||||
# Transceiver / Clocks
|
||||
if device_family == "k7":
|
||||
from lib.sata.phy.k7.trx import K7SATAPHYTRX
|
||||
from lib.sata.phy.k7.crg import K7SATAPHYCRG
|
||||
self.submodules.trx = K7SATAPHYTRX(pads, speed)
|
||||
self.submodules.crg = K7SATAPHYCRG(pads, self.trx, clk_freq, speed)
|
||||
else:
|
||||
raise NotImplementedError(device_family + "device family not implemented")
|
||||
|
||||
# Control
|
||||
if host:
|
||||
self.submodules.ctrl = SATAPHYHostCtrl(self.trx, self.crg, clk_freq)
|
||||
else:
|
||||
self.submodules.ctrl = SATAPHYDeviceCtrl(self.trx, self.crg, clk_freq)
|
||||
|
||||
# Datapath
|
||||
self.submodules.datapath = SATAPHYDatapath(self.trx, self.ctrl)
|
||||
self.sink, self.source = self.datapath.sink, self.datapath.source
|
|
@ -0,0 +1,271 @@
|
|||
from math import ceil
|
||||
|
||||
from lib.sata.common import *
|
||||
|
||||
def us(t, clk_freq):
|
||||
clk_period_us = 1000000/clk_freq
|
||||
return ceil(t/clk_period_us)
|
||||
|
||||
class SATAPHYHostCtrlTimeout(Module):
|
||||
def __init__(self, load):
|
||||
self.load = Signal()
|
||||
self.dec = Signal()
|
||||
self.reached = Signal()
|
||||
|
||||
cnt = Signal(max=load+1)
|
||||
self.sync += \
|
||||
If(self.load,
|
||||
cnt.eq(load)
|
||||
).Elif(self.dec & ~self.reached,
|
||||
cnt.eq(cnt-1)
|
||||
)
|
||||
self.comb += self.reached.eq(cnt == 0)
|
||||
|
||||
class SATAPHYHostCtrl(Module):
|
||||
def __init__(self, trx, crg, clk_freq):
|
||||
self.ready = Signal()
|
||||
self.sink = sink = Sink(phy_description(32))
|
||||
self.source = source = Source(phy_description(32))
|
||||
|
||||
###
|
||||
self.comb += [
|
||||
source.stb.eq(1),
|
||||
sink.ack.eq(1)
|
||||
]
|
||||
|
||||
retry_timeout = SATAPHYHostCtrlTimeout(us(10000, clk_freq))
|
||||
align_timeout = SATAPHYHostCtrlTimeout(us(873, clk_freq))
|
||||
self.submodules += align_timeout, retry_timeout
|
||||
|
||||
align_detect = Signal()
|
||||
non_align_cnt = Signal(4)
|
||||
|
||||
fsm = FSM(reset_state="RESET")
|
||||
self.submodules += fsm
|
||||
|
||||
fsm.act("RESET",
|
||||
trx.tx_idle.eq(1),
|
||||
retry_timeout.load.eq(1),
|
||||
align_timeout.load.eq(1),
|
||||
If(crg.ready,
|
||||
NextState("COMINIT")
|
||||
),
|
||||
)
|
||||
fsm.act("COMINIT",
|
||||
trx.tx_idle.eq(1),
|
||||
trx.tx_cominit_stb.eq(1),
|
||||
If(trx.tx_cominit_ack & ~trx.rx_cominit_stb,
|
||||
NextState("AWAIT_COMINIT")
|
||||
),
|
||||
)
|
||||
fsm.act("AWAIT_COMINIT",
|
||||
trx.tx_idle.eq(1),
|
||||
retry_timeout.dec.eq(1),
|
||||
If(trx.rx_cominit_stb,
|
||||
NextState("AWAIT_NO_COMINIT")
|
||||
).Else(
|
||||
If(retry_timeout.reached,
|
||||
NextState("RESET")
|
||||
)
|
||||
),
|
||||
)
|
||||
fsm.act("AWAIT_NO_COMINIT",
|
||||
trx.tx_idle.eq(1),
|
||||
retry_timeout.load.eq(1),
|
||||
If(~trx.rx_cominit_stb,
|
||||
NextState("CALIBRATE")
|
||||
),
|
||||
)
|
||||
fsm.act("CALIBRATE",
|
||||
trx.tx_idle.eq(1),
|
||||
NextState("COMWAKE"),
|
||||
)
|
||||
fsm.act("COMWAKE",
|
||||
trx.tx_idle.eq(1),
|
||||
trx.tx_comwake_stb.eq(1),
|
||||
If(trx.tx_comwake_ack,
|
||||
NextState("AWAIT_COMWAKE")
|
||||
),
|
||||
)
|
||||
fsm.act("AWAIT_COMWAKE",
|
||||
trx.tx_idle.eq(1),
|
||||
retry_timeout.dec.eq(1),
|
||||
If(trx.rx_comwake_stb,
|
||||
NextState("AWAIT_NO_COMWAKE")
|
||||
).Else(
|
||||
If(retry_timeout.reached,
|
||||
NextState("RESET")
|
||||
)
|
||||
),
|
||||
)
|
||||
fsm.act("AWAIT_NO_COMWAKE",
|
||||
trx.tx_idle.eq(1),
|
||||
If(~trx.rx_comwake_stb,
|
||||
NextState("AWAIT_NO_RX_IDLE")
|
||||
),
|
||||
)
|
||||
fsm.act("AWAIT_NO_RX_IDLE",
|
||||
trx.tx_idle.eq(0),
|
||||
source.data.eq(0x4A4A4A4A), #D10.2
|
||||
source.charisk.eq(0b0000),
|
||||
If(~trx.rx_idle,
|
||||
NextState("AWAIT_ALIGN"),
|
||||
crg.reset.eq(1),
|
||||
trx.pmarxreset.eq(1)
|
||||
),
|
||||
)
|
||||
fsm.act("AWAIT_ALIGN",
|
||||
trx.tx_idle.eq(0),
|
||||
source.data.eq(0x4A4A4A4A), #D10.2
|
||||
source.charisk.eq(0b0000),
|
||||
trx.rx_align.eq(1),
|
||||
align_timeout.dec.eq(1),
|
||||
If(align_detect & ~trx.rx_idle,
|
||||
NextState("SEND_ALIGN")
|
||||
).Elif(align_timeout.reached,
|
||||
NextState("RESET")
|
||||
),
|
||||
)
|
||||
fsm.act("SEND_ALIGN",
|
||||
trx.tx_idle.eq(0),
|
||||
trx.rx_align.eq(1),
|
||||
source.data.eq(primitives["ALIGN"]),
|
||||
source.charisk.eq(0b0001),
|
||||
If(non_align_cnt == 3,
|
||||
NextState("READY")
|
||||
),
|
||||
)
|
||||
fsm.act("READY",
|
||||
trx.tx_idle.eq(0),
|
||||
trx.rx_align.eq(1),
|
||||
source.data.eq(primitives["SYNC"]),
|
||||
source.charisk.eq(0b0001),
|
||||
If(trx.rx_idle,
|
||||
NextState("RESET")
|
||||
),
|
||||
self.ready.eq(1),
|
||||
)
|
||||
|
||||
self.comb += \
|
||||
align_detect.eq(self.sink.stb & (self.sink.data == primitives["ALIGN"]))
|
||||
self.sync += \
|
||||
If(fsm.ongoing("SEND_ALIGN"),
|
||||
If(sink.stb,
|
||||
If(sink.data[0:8] == 0x7C,
|
||||
non_align_cnt.eq(non_align_cnt + 1)
|
||||
).Else(
|
||||
non_align_cnt.eq(0)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
class SATAPHYDeviceCtrl(Module):
|
||||
def __init__(self, trx, crg, clk_freq):
|
||||
self.ready = Signal()
|
||||
|
||||
sink = Sink(phy_description(32))
|
||||
source = Source(phy_description(32))
|
||||
|
||||
###
|
||||
|
||||
self.comb += [
|
||||
source.stb.eq(1),
|
||||
sink.ack.eq(1)
|
||||
]
|
||||
|
||||
retry_timeout = SATAPHYHostCtrlTimeout(us(10000, clk_freq))
|
||||
align_timeout = SATAPHYHostCtrlTimeout(us(873, clk_freq))
|
||||
self.submodules += align_timeout, retry_timeout
|
||||
|
||||
fsm = FSM(reset_state="RESET")
|
||||
self.submodules += fsm
|
||||
|
||||
fsm.act("RESET",
|
||||
trx.tx_idle.eq(1),
|
||||
retry_timeout.load.eq(1),
|
||||
align_timeout.load.eq(1),
|
||||
If(crg.ready,
|
||||
NextState("AWAIT_COMINIT")
|
||||
)
|
||||
)
|
||||
fsm.act("AWAIT_COMINIT",
|
||||
trx.tx_idle.eq(1),
|
||||
If(trx.rx_cominit_stb,
|
||||
NextState("AWAIT_NO_COMINIT")
|
||||
)
|
||||
)
|
||||
fsm.act("AWAIT_NO_COMINIT",
|
||||
trx.tx_idle.eq(1),
|
||||
If(~trx.rx_cominit_stb,
|
||||
NextState("COMINIT")
|
||||
)
|
||||
)
|
||||
fsm.act("COMINIT",
|
||||
trx.tx_idle.eq(1),
|
||||
trx.tx_cominit_stb.eq(1),
|
||||
If(trx.tx_cominit_ack,
|
||||
NextState("AWAIT_COMWAKE")
|
||||
)
|
||||
)
|
||||
fsm.act("AWAIT_COMWAKE",
|
||||
trx.tx_idle.eq(1),
|
||||
retry_timeout.dec.eq(1),
|
||||
If(trx.rx_comwake_stb,
|
||||
NextState("AWAIT_NO_COMWAKE")
|
||||
).Else(
|
||||
If(retry_timeout.reached,
|
||||
NextState("RESET")
|
||||
)
|
||||
)
|
||||
)
|
||||
fsm.act("AWAIT_NO_COMWAKE",
|
||||
trx.tx_idle.eq(1),
|
||||
If(~trx.rx_comwake_stb,
|
||||
NextState("CALIBRATE")
|
||||
)
|
||||
)
|
||||
fsm.act("CALIBRATE",
|
||||
trx.tx_idle.eq(1),
|
||||
NextState("COMWAKE")
|
||||
)
|
||||
fsm.act("COMWAKE",
|
||||
trx.tx_idle.eq(1),
|
||||
trx.tx_comwake_stb.eq(1),
|
||||
If(trx.tx_comwake_stb,
|
||||
NextState("RESET_CRG"),
|
||||
crg.reset.eq(1),
|
||||
)
|
||||
)
|
||||
fsm.act("RESET_CRG",
|
||||
trx.tx_idle.eq(0),
|
||||
If(crg.ready,
|
||||
NextState("SEND_ALIGN")
|
||||
)
|
||||
)
|
||||
fsm.act("SEND_ALIGN",
|
||||
trx.tx_idle.eq(0),
|
||||
trx.rx_align.eq(1),
|
||||
source.data.eq(primitives["ALIGN"]),
|
||||
source.charisk.eq(0b0001),
|
||||
align_timeout.dec.eq(1),
|
||||
If(align_detect,
|
||||
NextState("READY")
|
||||
).Elif(align_timeout.reached,
|
||||
NextState("ERROR")
|
||||
)
|
||||
)
|
||||
fsm.act("READY",
|
||||
trx.tx_idle.eq(0),
|
||||
NextState("READY"),
|
||||
If(trx.rx_idle,
|
||||
NextState("RESET")
|
||||
),
|
||||
self.ready.eq(1)
|
||||
)
|
||||
fsm.act("ERROR",
|
||||
trx.tx_idle.eq(1),
|
||||
NextState("RESET")
|
||||
)
|
||||
|
||||
self.comb += \
|
||||
align_detect.eq(sink.stb & (sink.data == primitives["ALIGN"]))
|
|
@ -1,11 +1,8 @@
|
|||
from migen.fhdl.std import *
|
||||
from migen.genlib.misc import chooser
|
||||
from migen.actorlib.fifo import AsyncFIFO
|
||||
from migen.flow.actor import Sink, Source
|
||||
|
||||
from lib.sata.common import *
|
||||
|
||||
class K7SATAPHYDatapathRX(Module):
|
||||
from migen.genlib.misc import chooser
|
||||
|
||||
class SATAPHYDatapathRX(Module):
|
||||
def __init__(self):
|
||||
self.sink = Sink(phy_description(16))
|
||||
self.source = Source(phy_description(32))
|
||||
|
@ -69,7 +66,7 @@ class K7SATAPHYDatapathRX(Module):
|
|||
]
|
||||
self.comb += Record.connect(fifo.source, self.source)
|
||||
|
||||
class K7SATAPHYDatapathTX(Module):
|
||||
class SATAPHYDatapathTX(Module):
|
||||
def __init__(self):
|
||||
self.sink = Sink(phy_description(32))
|
||||
self.source = Source(phy_description(16))
|
||||
|
@ -108,23 +105,20 @@ class K7SATAPHYDatapathTX(Module):
|
|||
chooser(fifo.source.charisk, mux, self.source.charisk)
|
||||
]
|
||||
|
||||
class K7SATAPHYDatapath(Module):
|
||||
def __init__(self, gtx, ctrl):
|
||||
class SATAPHYDatapath(Module):
|
||||
def __init__(self, trx, ctrl):
|
||||
self.sink = Sink(phy_description(32))
|
||||
self.source = Source(phy_description(32))
|
||||
|
||||
###
|
||||
|
||||
# change data width & cross domain crossing
|
||||
rx = K7SATAPHYDatapathRX()
|
||||
tx = K7SATAPHYDatapathTX()
|
||||
rx = SATAPHYDatapathRX()
|
||||
tx = SATAPHYDatapathTX()
|
||||
self.submodules += rx, tx
|
||||
self.comb += [
|
||||
rx.sink.data.eq(gtx.rxdata),
|
||||
rx.sink.charisk.eq(gtx.rxcharisk),
|
||||
|
||||
gtx.txdata.eq(tx.source.data),
|
||||
gtx.txcharisk.eq(tx.source.charisk),
|
||||
trx.source.connect(rx.sink),
|
||||
tx.source.connect(trx.sink)
|
||||
]
|
||||
|
||||
# Align cnt (send 2 Align DWORDs every 256 DWORDs)
|
|
@ -1,14 +1,10 @@
|
|||
from math import ceil
|
||||
|
||||
from migen.fhdl.std import *
|
||||
from migen.genlib.resetsync import AsyncResetSynchronizer
|
||||
from migen.genlib.fsm import FSM, NextState
|
||||
|
||||
from lib.sata.common import *
|
||||
from lib.sata.phy.k7sataphy.gtx import GTXE2_COMMON
|
||||
from lib.sata.phy.k7.trx import GTXE2_COMMON
|
||||
|
||||
class K7SATAPHYCRG(Module):
|
||||
def __init__(self, pads, gtx, clk_freq, default_speed):
|
||||
def __init__(self, pads, gtx, clk_freq, speed):
|
||||
self.reset = Signal()
|
||||
self.ready = Signal()
|
||||
|
||||
|
@ -51,7 +47,7 @@ class K7SATAPHYCRG(Module):
|
|||
"SATA2" : 8.0,
|
||||
"SATA3" : 4.0
|
||||
}
|
||||
mmcm_div = mmcm_div_config[default_speed]
|
||||
mmcm_div = mmcm_div_config[speed]
|
||||
self.specials += [
|
||||
Instance("BUFG", i_I=gtx.txoutclk, o_O=mmcm_clk_i),
|
||||
Instance("MMCME2_ADV",
|
|
@ -1,8 +1,7 @@
|
|||
from migen.fhdl.std import *
|
||||
from migen.genlib.cdc import *
|
||||
|
||||
from lib.sata.common import *
|
||||
|
||||
from migen.genlib.cdc import *
|
||||
|
||||
def ones(width):
|
||||
return 2**width-1
|
||||
|
||||
|
@ -14,9 +13,35 @@ class _PulseSynchronizer(PulseSynchronizer):
|
|||
o.eq(self.o)
|
||||
]
|
||||
|
||||
class K7SATAPHYGTX(Module):
|
||||
def __init__(self, pads, default_speed):
|
||||
# Interface
|
||||
class _RisingEdge(Module):
|
||||
def __init__(self, i, o):
|
||||
i_d = Signal()
|
||||
self.sync += i_d.eq(i)
|
||||
self.comb += o.eq(i & ~i_d)
|
||||
|
||||
class K7SATAPHYTRX(Module):
|
||||
def __init__(self, pads, speed):
|
||||
# Common signals
|
||||
|
||||
# control
|
||||
self.tx_idle = Signal() #i
|
||||
|
||||
self.tx_cominit_stb = Signal() #i
|
||||
self.tx_cominit_ack = Signal() #o
|
||||
self.tx_comwake_stb = Signal() #i
|
||||
self.tx_comwake_ack = Signal() #o
|
||||
|
||||
self.rx_idle = Signal() #o
|
||||
self.rx_align = Signal() #i
|
||||
|
||||
self.rx_cominit_stb = Signal() #o
|
||||
self.rx_comwake_stb = Signal() #o
|
||||
|
||||
# datapath
|
||||
self.sink = Sink(phy_description(16))
|
||||
self.source = Source(phy_description(16))
|
||||
|
||||
# K7 specific signals
|
||||
# Channel - Ref Clock Ports
|
||||
self.gtrefclk0 = Signal()
|
||||
|
||||
|
@ -82,15 +107,40 @@ class K7SATAPHYGTX(Module):
|
|||
"SATA2" : 2,
|
||||
"SATA3" : 1
|
||||
}
|
||||
rxout_div = div_config[default_speed]
|
||||
txout_div = div_config[default_speed]
|
||||
rxout_div = div_config[speed]
|
||||
txout_div = div_config[speed]
|
||||
|
||||
cdr_config = {
|
||||
"SATA1" : 0x0380008BFF40100008,
|
||||
"SATA2" : 0x0388008BFF40200008,
|
||||
"SATA3" : 0X0380008BFF10200010
|
||||
}
|
||||
rxcdr_cfg = cdr_config[default_speed]
|
||||
rxcdr_cfg = cdr_config[speed]
|
||||
|
||||
# Specific / Generic signals encoding/decoding
|
||||
self.comb += [
|
||||
self.txelecidle.eq(self.tx_idle),
|
||||
self.tx_cominit_ack.eq(self.tx_cominit_stb & self.txcomfinish),
|
||||
self.tx_comwake_ack.eq(self.tx_comwake_stb & self.txcomfinish),
|
||||
self.rx_idle.eq(self.rxelecidle),
|
||||
self.rxalign.eq(self.rx_align),
|
||||
self.rx_cominit_stb.eq(self.rxcominitdet),
|
||||
self.rx_comwake_stb.eq(self.rxcomwakedet),
|
||||
]
|
||||
self.submodules += [
|
||||
_RisingEdge(self.tx_cominit_stb, self.txcominit),
|
||||
_RisingEdge(self.tx_comwake_stb, self.txcomwake),
|
||||
]
|
||||
|
||||
self.comb += [
|
||||
self.txcharisk.eq(self.sink.charisk),
|
||||
self.txdata.eq(self.sink.data),
|
||||
self.sink.ack.eq(1),
|
||||
|
||||
self.source.stb.eq(1),
|
||||
self.source.charisk.eq(self.rxcharisk),
|
||||
self.source.data.eq(self.rxdata)
|
||||
]
|
||||
|
||||
# Internals and clock domain crossing
|
||||
# sys_clk --> sata_tx clk
|
|
@ -1,23 +0,0 @@
|
|||
from migen.fhdl.std import *
|
||||
|
||||
from lib.sata.common import *
|
||||
from lib.sata.phy.k7sataphy.gtx import K7SATAPHYGTX
|
||||
from lib.sata.phy.k7sataphy.crg import K7SATAPHYCRG
|
||||
from lib.sata.phy.k7sataphy.ctrl import K7SATAPHYHostCtrl, K7SATAPHYDeviceCtrl
|
||||
from lib.sata.phy.k7sataphy.datapath import K7SATAPHYDatapath
|
||||
|
||||
class K7SATAPHY(Module):
|
||||
def __init__(self, pads, clk_freq, host=True, default_speed="SATA1"):
|
||||
# GTX
|
||||
self.submodules.gtx = K7SATAPHYGTX(pads, default_speed)
|
||||
|
||||
# CRG / CTRL
|
||||
self.submodules.crg = K7SATAPHYCRG(pads, self.gtx, clk_freq, default_speed)
|
||||
if host:
|
||||
self.submodules.ctrl = K7SATAPHYHostCtrl(self.gtx, self.crg, clk_freq)
|
||||
else:
|
||||
self.submodules.ctrl = K7SATAPHYDeviceCtrl(self.gtx, self.crg, clk_freq)
|
||||
|
||||
# DATAPATH
|
||||
self.submodules.datapath = K7SATAPHYDatapath(self.gtx, self.ctrl)
|
||||
self.sink, self.source = self.datapath.sink, self.datapath.source
|
|
@ -1,307 +0,0 @@
|
|||
from math import ceil
|
||||
|
||||
from migen.fhdl.std import *
|
||||
from migen.genlib.resetsync import AsyncResetSynchronizer
|
||||
from migen.genlib.fsm import FSM, NextState
|
||||
from migen.flow.actor import Sink, Source
|
||||
|
||||
from lib.sata.common import *
|
||||
|
||||
def us(t, clk_freq):
|
||||
clk_period_us = 1000000/clk_freq
|
||||
return ceil(t/clk_period_us)
|
||||
|
||||
class K7SATAPHYHostCtrl(Module):
|
||||
def __init__(self, gtx, crg, clk_freq):
|
||||
self.ready = Signal()
|
||||
|
||||
self.sink = Sink(phy_description(32))
|
||||
self.source = Source(phy_description(32))
|
||||
|
||||
self.align_detect = align_detect = Signal()
|
||||
align_timeout_cnt = Signal(32)
|
||||
align_timeout = Signal()
|
||||
|
||||
retry_timeout_cnt = Signal(32)
|
||||
retry_timeout = Signal()
|
||||
|
||||
non_align_cnt = Signal(4)
|
||||
|
||||
txcominit = Signal()
|
||||
txcomwake = Signal()
|
||||
|
||||
self.comb += [
|
||||
self.source.stb.eq(1),
|
||||
self.sink.ack.eq(1)
|
||||
]
|
||||
|
||||
fsm = FSM(reset_state="RESET")
|
||||
self.submodules += fsm
|
||||
|
||||
fsm.act("RESET",
|
||||
gtx.txelecidle.eq(1),
|
||||
If(crg.ready,
|
||||
NextState("COMINIT")
|
||||
),
|
||||
)
|
||||
fsm.act("COMINIT",
|
||||
gtx.txelecidle.eq(1),
|
||||
txcominit.eq(1),
|
||||
If(gtx.txcomfinish & ~gtx.rxcominitdet,
|
||||
NextState("AWAIT_COMINIT")
|
||||
),
|
||||
)
|
||||
fsm.act("AWAIT_COMINIT",
|
||||
gtx.txelecidle.eq(1),
|
||||
If(gtx.rxcominitdet,
|
||||
NextState("AWAIT_NO_COMINIT")
|
||||
).Else(
|
||||
If(retry_timeout,
|
||||
NextState("RESET")
|
||||
)
|
||||
),
|
||||
)
|
||||
fsm.act("AWAIT_NO_COMINIT",
|
||||
gtx.txelecidle.eq(1),
|
||||
If(~gtx.rxcominitdet,
|
||||
NextState("CALIBRATE")
|
||||
),
|
||||
)
|
||||
fsm.act("CALIBRATE",
|
||||
gtx.txelecidle.eq(1),
|
||||
NextState("COMWAKE"),
|
||||
)
|
||||
fsm.act("COMWAKE",
|
||||
gtx.txelecidle.eq(1),
|
||||
txcomwake.eq(1),
|
||||
If(gtx.txcomfinish,
|
||||
NextState("AWAIT_COMWAKE")
|
||||
),
|
||||
)
|
||||
fsm.act("AWAIT_COMWAKE",
|
||||
gtx.txelecidle.eq(1),
|
||||
If(gtx.rxcomwakedet,
|
||||
NextState("AWAIT_NO_COMWAKE")
|
||||
).Else(
|
||||
If(retry_timeout,
|
||||
NextState("RESET")
|
||||
)
|
||||
),
|
||||
)
|
||||
fsm.act("AWAIT_NO_COMWAKE",
|
||||
gtx.txelecidle.eq(1),
|
||||
If(~gtx.rxcomwakedet,
|
||||
NextState("AWAIT_NO_RXELECIDLE")
|
||||
),
|
||||
)
|
||||
fsm.act("AWAIT_NO_RXELECIDLE",
|
||||
gtx.txelecidle.eq(0),
|
||||
self.source.data.eq(0x4A4A4A4A), #D10.2
|
||||
self.source.charisk.eq(0b0000),
|
||||
If(~gtx.rxelecidle,
|
||||
NextState("AWAIT_ALIGN"),
|
||||
crg.reset.eq(1),
|
||||
gtx.pmarxreset.eq(1)
|
||||
),
|
||||
)
|
||||
fsm.act("AWAIT_ALIGN",
|
||||
gtx.txelecidle.eq(0),
|
||||
self.source.data.eq(0x4A4A4A4A), #D10.2
|
||||
self.source.charisk.eq(0b0000),
|
||||
gtx.rxalign.eq(1),
|
||||
If((align_detect & ~gtx.rxelecidle) & ~align_timeout,
|
||||
NextState("SEND_ALIGN")
|
||||
).Elif(~align_detect & align_timeout,
|
||||
NextState("RESET")
|
||||
),
|
||||
)
|
||||
fsm.act("SEND_ALIGN",
|
||||
gtx.txelecidle.eq(0),
|
||||
gtx.rxalign.eq(1),
|
||||
self.source.data.eq(primitives["ALIGN"]),
|
||||
self.source.charisk.eq(0b0001),
|
||||
If(non_align_cnt == 3,
|
||||
NextState("READY")
|
||||
),
|
||||
)
|
||||
fsm.act("READY",
|
||||
gtx.txelecidle.eq(0),
|
||||
gtx.rxalign.eq(1),
|
||||
self.source.data.eq(primitives["SYNC"]),
|
||||
self.source.charisk.eq(0b0001),
|
||||
If(gtx.rxelecidle,
|
||||
NextState("RESET")
|
||||
),
|
||||
self.ready.eq(1),
|
||||
)
|
||||
|
||||
txcominit_d = Signal()
|
||||
txcomwake_d = Signal()
|
||||
self.sync += [
|
||||
txcominit_d.eq(txcominit),
|
||||
txcomwake_d.eq(txcomwake),
|
||||
gtx.txcominit.eq(txcominit & ~txcominit_d),
|
||||
gtx.txcomwake.eq(txcomwake & ~txcomwake_d),
|
||||
]
|
||||
|
||||
self.comb += align_detect.eq(self.sink.stb & (self.sink.data == primitives["ALIGN"]));
|
||||
self.sync += \
|
||||
If(fsm.ongoing("RESET"),
|
||||
align_timeout_cnt.eq(us(873, clk_freq))
|
||||
).Elif(fsm.ongoing("AWAIT_ALIGN"),
|
||||
align_timeout_cnt.eq(align_timeout_cnt-1)
|
||||
)
|
||||
self.comb += align_timeout.eq(align_timeout_cnt == 0)
|
||||
|
||||
self.sync += \
|
||||
If(fsm.ongoing("RESET") | fsm.ongoing("AWAIT_NO_COMINIT"),
|
||||
retry_timeout_cnt.eq(us(10000, clk_freq))
|
||||
).Elif(fsm.ongoing("AWAIT_COMINIT") | fsm.ongoing("AWAIT_COMWAKE"),
|
||||
retry_timeout_cnt.eq(retry_timeout_cnt-1)
|
||||
)
|
||||
self.comb += retry_timeout.eq(retry_timeout_cnt == 0)
|
||||
|
||||
self.sync += \
|
||||
If(fsm.ongoing("SEND_ALIGN"),
|
||||
If(self.sink.stb,
|
||||
If(self.sink.data[0:8] == 0x7C,
|
||||
non_align_cnt.eq(non_align_cnt + 1)
|
||||
).Else(
|
||||
non_align_cnt.eq(0)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
class K7SATAPHYDeviceCtrl(Module):
|
||||
def __init__(self, gtx, crg, clk_freq):
|
||||
self.ready = Signal()
|
||||
|
||||
self.sink = Sink(phy_description(32))
|
||||
self.source = Source(phy_description(32))
|
||||
|
||||
align_detect = Signal()
|
||||
align_timeout = Signal()
|
||||
align_timeout_cnt = Signal(32)
|
||||
|
||||
retry_timeout_cnt = Signal(32)
|
||||
retry_timeout = Signal()
|
||||
|
||||
txcominit = Signal()
|
||||
txcomwake = Signal()
|
||||
|
||||
self.comb += [
|
||||
self.source.stb.eq(1),
|
||||
self.sink.ack.eq(1)
|
||||
]
|
||||
|
||||
fsm = FSM(reset_state="RESET")
|
||||
self.submodules += fsm
|
||||
|
||||
fsm.act("RESET",
|
||||
gtx.txelecidle.eq(1),
|
||||
If(crg.ready,
|
||||
NextState("AWAIT_COMINIT")
|
||||
)
|
||||
)
|
||||
fsm.act("AWAIT_COMINIT",
|
||||
gtx.txelecidle.eq(1),
|
||||
If(gtx.rxcominitdet,
|
||||
NextState("AWAIT_NO_COMINIT")
|
||||
)
|
||||
)
|
||||
fsm.act("AWAIT_NO_COMINIT",
|
||||
gtx.txelecidle.eq(1),
|
||||
If(~gtx.rxcominitdet,
|
||||
NextState("COMINIT")
|
||||
)
|
||||
)
|
||||
fsm.act("COMINIT",
|
||||
gtx.txelecidle.eq(1),
|
||||
txcominit.eq(1),
|
||||
If(gtx.txcomfinish,
|
||||
NextState("AWAIT_COMWAKE")
|
||||
)
|
||||
)
|
||||
fsm.act("AWAIT_COMWAKE",
|
||||
gtx.txelecidle.eq(1),
|
||||
If(gtx.rxcomwakedet,
|
||||
NextState("AWAIT_NO_COMWAKE")
|
||||
).Else(
|
||||
If(retry_timeout,
|
||||
NextState("RESET")
|
||||
)
|
||||
)
|
||||
)
|
||||
fsm.act("AWAIT_NO_COMWAKE",
|
||||
gtx.txelecidle.eq(1),
|
||||
If(~gtx.rxcomwakedet,
|
||||
NextState("CALIBRATE")
|
||||
)
|
||||
)
|
||||
fsm.act("CALIBRATE",
|
||||
gtx.txelecidle.eq(1),
|
||||
NextState("COMWAKE")
|
||||
)
|
||||
fsm.act("COMWAKE",
|
||||
gtx.txelecidle.eq(1),
|
||||
txcomwake.eq(1),
|
||||
If(gtx.txcomfinish,
|
||||
NextState("RESET_CRG"),
|
||||
crg.reset.eq(1),
|
||||
)
|
||||
)
|
||||
fsm.act("RESET_CRG",
|
||||
gtx.txelecidle.eq(0),
|
||||
If(crg.ready,
|
||||
NextState("SEND_ALIGN")
|
||||
)
|
||||
)
|
||||
fsm.act("SEND_ALIGN",
|
||||
gtx.txelecidle.eq(0),
|
||||
gtx.rxalign.eq(1),
|
||||
self.source.data.eq(primitives["ALIGN"]),
|
||||
self.source.charisk.eq(0b0001),
|
||||
If(align_detect,
|
||||
NextState("READY")
|
||||
).Elif(align_timeout,
|
||||
NextState("ERROR")
|
||||
)
|
||||
)
|
||||
fsm.act("READY",
|
||||
gtx.txelecidle.eq(0),
|
||||
NextState("READY"),
|
||||
If(gtx.rxelecidle,
|
||||
NextState("RESET")
|
||||
),
|
||||
self.ready.eq(1)
|
||||
)
|
||||
fsm.act("ERROR",
|
||||
gtx.txelecidle.eq(1),
|
||||
NextState("RESET")
|
||||
)
|
||||
|
||||
txcominit_d = Signal()
|
||||
txcomwake_d = Signal()
|
||||
self.sync += [
|
||||
txcominit_d.eq(txcominit),
|
||||
txcomwake_d.eq(txcomwake),
|
||||
gtx.txcominit.eq(txcominit & ~txcominit_d),
|
||||
gtx.txcomwake.eq(txcomwake & ~txcomwake_d),
|
||||
]
|
||||
|
||||
self.comb += align_detect.eq(self.sink.stb & (self.sink.data == primitives["ALIGN"]));
|
||||
self.sync += \
|
||||
If(fsm.ongoing("RESET"),
|
||||
align_timeout_cnt.eq(us(55, clk_freq))
|
||||
).Elif(fsm.ongoing("AWAIT_ALIGN"),
|
||||
align_timeout_cnt.eq(align_timeout_cnt-1)
|
||||
)
|
||||
self.comb += align_timeout.eq(align_timeout_cnt == 0)
|
||||
|
||||
self.sync += \
|
||||
If(fsm.ongoing("RESET"),
|
||||
retry_timeout_cnt.eq(us(10000, clk_freq))
|
||||
).Elif(fsm.ongoing("AWAIT_COMWAKE"),
|
||||
retry_timeout_cnt.eq(retry_timeout_cnt-1)
|
||||
)
|
||||
self.comb += retry_timeout.eq(retry_timeout_cnt == 0)
|
|
@ -1,7 +1,5 @@
|
|||
import random, copy
|
||||
|
||||
from migen.fhdl.std import *
|
||||
from migen.genlib.record import *
|
||||
from migen.sim.generic import run_simulation
|
||||
|
||||
from lib.sata.common import *
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
from migen.fhdl.std import *
|
||||
from migen.genlib.fsm import FSM, NextState
|
||||
|
||||
from lib.sata.common import *
|
||||
|
||||
def _get_item(obj, name, width):
|
||||
|
|
|
@ -9,7 +9,7 @@ from miscope.uart2wishbone import UART2Wishbone
|
|||
|
||||
from misoclib import identifier
|
||||
from lib.sata.common import *
|
||||
from lib.sata.phy.k7sataphy import K7SATAPHY
|
||||
from lib.sata.phy import SATAPHY
|
||||
from lib.sata.link.cont import SATACONTInserter, SATACONTRemover
|
||||
|
||||
from migen.genlib.cdc import *
|
||||
|
@ -111,17 +111,17 @@ class SimDesign(UART2WB):
|
|||
UART2WB.__init__(self, platform, clk_freq)
|
||||
self.submodules.crg = _CRG(platform)
|
||||
|
||||
self.submodules.sataphy_host = K7SATAPHY(platform.request("sata_host"), clk_freq, host=True)
|
||||
self.submodules.sata_phy_host = SATAPHY(platform.request("sata_host"), clk_freq, host=True)
|
||||
self.comb += [
|
||||
self.sataphy_host.sink.stb.eq(1),
|
||||
self.sataphy_host.sink.data.eq(primitives["SYNC"]),
|
||||
self.sataphy_host.sink.charisk.eq(0b0001)
|
||||
self.sata_phy_host.sink.stb.eq(1),
|
||||
self.sata_phy_host.sink.data.eq(primitives["SYNC"]),
|
||||
self.sata_phy_host.sink.charisk.eq(0b0001)
|
||||
]
|
||||
self.submodules.sataphy_device = K7SATAPHY(platform.request("sata_device"), clk_freq, host=False)
|
||||
self.submodules.sata_phy_device = SATAPHY(platform.request("sata_device"), clk_freq, host=False)
|
||||
self.comb += [
|
||||
self.sataphy_device.sink.stb.eq(1),
|
||||
self.sataphy_device.sink.data.eq(primitives["SYNC"]),
|
||||
self.sataphy_device.sink.charisk.eq(0b0001)
|
||||
self.sata_phy_device.sink.stb.eq(1),
|
||||
self.sata_phy_device.sink.data.eq(primitives["SYNC"]),
|
||||
self.sata_phy_device.sink.charisk.eq(0b0001)
|
||||
]
|
||||
|
||||
|
||||
|
@ -187,7 +187,7 @@ class TestDesign(UART2WB, AutoCSR):
|
|||
UART2WB.__init__(self, platform, clk_freq)
|
||||
self.submodules.crg = _CRG(platform)
|
||||
|
||||
self.submodules.sata_phy = K7SATAPHY(platform.request("sata_host"), clk_freq, host=True, default_speed="SATA1")
|
||||
self.submodules.sata_phy = SATAPHY(platform.request("sata_host"), clk_freq, host=True, speed="SATA1")
|
||||
self.submodules.stim = VeryBasicPHYStim(self.sata_phy)
|
||||
|
||||
self.submodules.clock_leds = ClockLeds(platform)
|
||||
|
@ -196,29 +196,28 @@ class TestDesign(UART2WB, AutoCSR):
|
|||
import os
|
||||
from miscope import MiLa, Term, UART2Wishbone
|
||||
|
||||
gtx = self.sata_phy.gtx
|
||||
trx = self.sata_phy.trx
|
||||
ctrl = self.sata_phy.ctrl
|
||||
crg = self.sata_phy.crg
|
||||
|
||||
debug = (
|
||||
gtx.rxresetdone,
|
||||
gtx.txresetdone,
|
||||
trx.rxresetdone,
|
||||
trx.txresetdone,
|
||||
|
||||
gtx.rxuserrdy,
|
||||
gtx.txuserrdy,
|
||||
trx.rxuserrdy,
|
||||
trx.txuserrdy,
|
||||
|
||||
gtx.rxelecidle,
|
||||
gtx.rxcominitdet,
|
||||
gtx.rxcomwakedet,
|
||||
trx.rxelecidle,
|
||||
trx.rxcominitdet,
|
||||
trx.rxcomwakedet,
|
||||
|
||||
gtx.txcomfinish,
|
||||
gtx.txcominit,
|
||||
gtx.txcomwake,
|
||||
trx.txcomfinish,
|
||||
trx.txcominit,
|
||||
trx.txcomwake,
|
||||
|
||||
ctrl.sink.stb,
|
||||
ctrl.ready,
|
||||
ctrl.sink.data,
|
||||
ctrl.sink.charisk,
|
||||
ctrl.align_detect,
|
||||
|
||||
self.sata_phy.source.stb,
|
||||
self.sata_phy.source.data,
|
||||
|
|
|
@ -4,8 +4,8 @@ from miscope.host.drivers import MiLaDriver
|
|||
mila = MiLaDriver(wb.regs, "mila", use_rle=False)
|
||||
wb.open()
|
||||
###
|
||||
trigger0 = mila.gtx_rxelecidle0_o*0
|
||||
mask0 = mila.gtx_rxelecidle0_m
|
||||
trigger0 = mila.trx_rxelecidle0_o*0
|
||||
mask0 = mila.trx_rxelecidle0_m
|
||||
|
||||
#trigger0 = mila.ctrl_align_detect_o
|
||||
#mask0 = mila.ctrl_align_detect_m
|
||||
|
|
Loading…
Reference in New Issue