from migen.fhdl.std import *
+from migen.genlib.fsm import FSM, NextState
from lib.sata.std import *
-from lib.sata.link import crc
-from lib.sata.link import scrambler
+from lib.sata.link.crc import SATACRCInserter, SATACRCChecker
+from lib.sata.link.scrambler import SATAScrambler
# Todo:
# - TX: (optional) insert COND and scramble between COND and primitives
# - RX: manage COND, HOLD from device
class SATALinkLayer(Module):
- def __init__(self, phy, dw=32):
- self.sink = Sink(link_layout(dw))
- self.source = Source(link_layout(dw))
+ def __init__(self, phy):
+ self.sink = Sink(link_layout(32))
+ self.source = Source(link_layout(32))
fsm = FSM(reset_state="IDLE")
self.submodules += fsm
# TX
# insert CRC
- crc_inserter = crc.SATACRCInserter(link_layout(dw))
+ crc_inserter = SATACRCInserter(link_layout(32))
self.submodules += crc_inserter
# scramble
- scrambler = scrambler.SATAScrambler(link_layout(dw))
+ scrambler = SATAScrambler(link_layout(32))
self.submodules += scrambler
# graph
self.comb += [
Record.connect(self.sink, crc_inserter.sink),
- Record.connect(crc_inserter, scrambler)
+ Record.connect(crc_inserter.source, scrambler.sink)
]
# datas / primitives mux
phy.sink.stb.eq(1),
phy.sink.data.eq(tx_insert),
phy.sink.charisk.eq(0x0001),
- ).Elsif(fsm.ongoing("H2D_COPY"),
+ ).Elif(fsm.ongoing("H2D_COPY"),
phy.sink.stb.eq(scrambler.source.stb),
- phy.sink.data.eq(scrambler.source.data),
+ phy.sink.data.eq(scrambler.source.d),
scrambler.source.ack.eq(phy.source.ack),
phy.sink.charisk.eq(0)
)
)
# descrambler
- descrambler = descrambler.SATAScrambler(link_layout(dw))
+ descrambler = SATAScrambler(link_layout(32))
self.submodules += descrambler
# check CRC
- crc_checker = crc.SATACRCChecker(link_layout(dw))
+ crc_checker = SATACRCChecker(link_layout(32))
self.submodules += crc_checker
# graph
self.comb += [
If(fsm.ongoing("H2D_COPY") & (rx_det == 0),
- descrambler.sink.stb.eq(phy.source.stb & (phy.charisk == 0)),
- descrambler.sink.d.eq(phy.source.d),
+ descrambler.sink.stb.eq(phy.source.stb & (phy.source.charisk == 0)),
+ descrambler.sink.d.eq(phy.source.data),
),
+ phy.source.ack.eq(1),
Record.connect(descrambler.source, crc_checker.sink),
Record.connect(crc_checker.source, self.source)
]
# FSM
fsm.act("IDLE",
tx_insert.eq(primitives["SYNC"]),
- If(rx_primitive == "X_RDY",
+ If(rx_det == primitives["X_RDY"],
NextState("D2H_RDY")
- ).Elif(scrambler.stb & scrambler.sop,
+ ).Elif(scrambler.source.stb & scrambler.source.sop,
NextState("H2D_RDY")
)
)
# Host to Device
fsm.act("H2D_RDY",
tx_insert.eq(primitives["X_RDY"]),
- If(rx_primitive == primitives["R_RDY"]),
+ If(rx_det == primitives["R_RDY"],
NextState("H2D_SOF")
+ )
)
fsm.act("H2D_SOF",
tx_insert.eq(primitives["SOF"]),
)
)
fsm.act("H2D_COPY",
- If(scrambler.stb & scrambler.ack & scramvbler.eop,
+ If(scrambler.source.stb & scrambler.source.eop & scrambler.source.ack,
NextState("H2D_EOF")
)
)
polynom = 0x04C11DB7
init = 0x52325032
check = 0xC704DD7B
- def __init__(self):
+ def __init__(self, dat_width):
self.d = Signal(self.width)
self.value = Signal(self.width)
self.error = Signal()
from migen.fhdl.std import *
from migen.genlib.misc import optree
+from lib.sata.std import *
+
@DecorateModule(InsertReset)
@DecorateModule(InsertCE)
class Scrambler(Module):
If(sink.stb & sink.ack,
If(sink.eop,
ongoing.eq(0)
- ).Elsif(sink.sop,
+ ).Elif(sink.sop,
ongoing.eq(1)
)
)
$(CC) $(CFLAGS) $(INC) -o scrambler scrambler.c
$(CMD) scrambler_tb.py
+link_tb:
+ $(CMD) link_tb.py
+
all: crc_tb scrambler_tb
clean:
--- /dev/null
+from migen.fhdl.std import *
+
+from lib.sata.std import *
+
+class BFMDword():
+ def __init__(self, dat=0):
+ self.dat = dat
+ self.start = 1
+ self.done = 0
+
+class BFMSource(Module):
+ def __init__(self, dw):
+ self.source = Source(phy_layout(dw))
+ ###
+ self.dwords = []
+ self.dword = BFMDword()
+ self.dword.done = 1
+
+ def send(self, dword, blocking=True):
+ self.dwords.append(dword)
+ if blocking:
+ while dword.done == 0:
+ yield
+
+ def do_simulation(self, selfp):
+ if len(self.dwords) and self.dword.done:
+ self.dword = self.dwords.pop(0)
+ if not self.dword.done:
+ selfp.source.stb = 1
+ selfp.source.charisk = 0b0000
+ for k, v in primitives.items():
+ if v == self.dword.dat:
+ selfp.source.charisk = 0b0001
+ selfp.source.data = self.dword.dat
+ elif selfp.source.stb == 1 and selfp.source.ack == 1:
+ self.dword.done = 1
+ selfp.source.stb = 0
+
+class BFMSink(Module):
+ def __init__(self, dw):
+ self.sink = Sink(phy_layout(dw))
+ ###
+ self.dword = BFMDword()
+
+ def receive(self):
+ self.dword.done = 0
+ while self.dword.done == 0:
+ yield
+
+ def do_simulation(self, selfp):
+ self.dword.done = 0
+ selfp.sink.ack = 1
+ if selfp.sink.stb == 1:
+ self.dword.done = 1
+ self.dword.dat = selfp.sink.data
+
+class BFMPHY(Module):
+ def __init__(self, dw):
+ self.dw = dw
+
+ self.submodules.bfm_sink = BFMSink(dw)
+ self.submodules.bfm_source = BFMSource(dw)
+
+ self.source = self.bfm_source.source
+ self.sink = self.bfm_sink.sink
+
+ self.dword = 0
+
+ def send(self, dword, blocking=True):
+ packet = BFMDword(dword)
+ yield from self.bfm_source.send(dword, blocking)
+
+ def receive(self):
+ yield from self.bfm_sink.receive()
+ self.rx_dword = self.bfm_sink.dword.dat
+
+class BFM(Module):
+ def __init__(self, dw, debug=False):
+ self.debug = debug
+
+ ###
+
+ self.submodules.phy = BFMPHY(dw)
+
+ def gen_simulation(self, selfp):
+ while True:
+ yield from self.phy.receive()
+ print("%08x" %(self.phy.rx_dword))
--- /dev/null
+from migen.fhdl.std import *
+from migen.genlib.record import *
+from migen.sim.generic import run_simulation
+
+from lib.sata.std import *
+from lib.sata.link import SATALinkLayer
+
+from lib.sata.link.test.bfm import *
+
+class LinkPacket():
+ def __init__(self, d=[]):
+ self.d = d
+ self.start = 1
+ self.done = 0
+
+class LinkStreamer(Module):
+ def __init__(self, dw):
+ self.source = Source(link_layout(dw))
+ ###
+ self.packets = []
+ self.packet = LinkPacket()
+ self.packet.done = 1
+
+ def send(self, packet, blocking=True):
+ self.packets.append(packet)
+ if blocking:
+ while packet.done == 0:
+ yield
+
+ def do_simulation(self, selfp):
+ if len(self.packets) and self.packet.done:
+ self.packet = self.packets.pop(0)
+ if self.packet.start and not self.packet.done:
+ selfp.source.stb = 1
+ selfp.source.sop = 1
+ selfp.source.d = self.packet.d.pop(0)
+ self.packet.start = 0
+ elif selfp.source.stb == 1 and selfp.source.ack == 1:
+ selfp.source.sop = 0
+ selfp.source.eop = (len(self.packet.d) == 1)
+ if len(self.packet.d) > 0:
+ selfp.source.stb = 1
+ selfp.source.d = self.packet.d.pop(0)
+ else:
+ self.packet.done = 1
+ selfp.source.stb = 0
+
+class LinkLogger(Module):
+ def __init__(self, dw):
+ self.sink = Sink(link_layout(dw))
+ ###
+ self.packet = LinkPacket()
+
+ def receive(self):
+ self.packet.done = 0
+ while self.packet.done == 0:
+ yield
+
+ def do_simulation(self, selfp):
+ self.packet.done = 0
+ selfp.sink.ack = 1
+ if selfp.sink.stb == 1 and selfp.sink.sop == 1:
+ self.packet.start = 1
+ self.packet.d = [selfp.sink.d]
+ elif selfp.sink.stb:
+ self.packet.start = 0
+ self.packet.d.append(selfp.sink.d)
+ if (selfp.sink.stb ==1 and selfp.sink.eop ==1):
+ self.packet.done = 1
+
+class TB(Module):
+ def __init__(self):
+ self.submodules.bfm = BFM(32, debug=True)
+ self.submodules.link_layer = SATALinkLayer(self.bfm.phy)
+
+ self.submodules.streamer = LinkStreamer(32)
+ self.submodules.logger = LinkLogger(32)
+ self.comb += [
+ self.link_layer.sink.eq(self.streamer.source),
+ self.logger.sink.eq(self.link_layer.source)
+ ]
+
+ def gen_simulation(self, selfp):
+ for i in range(200):
+ yield
+ yield from self.bfm.phy.send(BFMDword(primitives["R_RDY"]), False)
+ yield from self.streamer.send(LinkPacket([0, 1, 2, 3]))
+
+if __name__ == "__main__":
+ run_simulation(TB(), ncycles=5000, vcd_name="my.vcd", keep_files=True)
from migen.fhdl.std import *
from migen.genlib.record import *
-from migen.flow.actor import EndpointDescription
+from migen.flow.actor import EndpointDescription, Sink, Source
primitives = {
"ALIGN" : 0x7B4A4ABC,
def ones(width):
return 2**width-1
-def phy_description(dw):
+def phy_layout(dw):
parameters = {
"packetized": False
}
]
return EndpointDescription(layout, parameters)
-def link_description(dw):
+def link_layout(dw):
parameters = {
"packetized": True
}