add phy_datapath_tb and start datapath simplification

This commit is contained in:
Florent Kermarrec 2014-12-19 16:48:22 +01:00
parent 9728a97834
commit 8bb40241fa
3 changed files with 158 additions and 53 deletions

View File

@ -1,6 +1,7 @@
from lib.sata.common import *
from migen.genlib.misc import chooser
from migen.flow.plumbing import Multiplexer, Demultiplexer
class SATAPHYDatapathRX(Module):
def __init__(self):
@ -105,6 +106,52 @@ class SATAPHYDatapathTX(Module):
chooser(fifo.source.charisk, mux, self.source.charisk)
]
class SATAPHYAlignInserter(Module):
def __init__(self, ctrl):
self.sink = sink = Sink(phy_description(32))
self.source = source = Source(phy_description(32))
###
# send 2 ALIGN every 256 DWORDs
# used for clock compensation between
# HOST and device
cnt = Signal(8)
send = Signal()
self.sync += \
If(~ctrl.ready,
cnt.eq(0)
).Elif(source.stb & source.ack,
cnt.eq(cnt+1)
)
self.comb += [
send.eq(cnt < 2),
If(send,
source.stb.eq(1),
source.charisk.eq(0b0001),
source.data.eq(primitives["ALIGN"]),
sink.ack.eq(0)
).Else(
source.stb.eq(sink.stb),
source.data.eq(sink.data),
source.charisk.eq(sink.charisk),
sink.ack.eq(source.ack)
)
]
class SATAPHYAlignRemover(Module):
def __init__(self):
self.sink = sink = Sink(phy_description(32))
self.source = source = Source(phy_description(32))
###
charisk_match = sink.charisk == 0b0001
data_match = sink.data == primitives["ALIGN"]
self.comb += \
If(sink.stb & charisk_match & data_match,
sink.ack.eq(1),
).Else(
Record.connect(sink, source)
)
class SATAPHYDatapath(Module):
def __init__(self, trx, ctrl):
self.sink = Sink(phy_description(32))
@ -112,61 +159,28 @@ class SATAPHYDatapath(Module):
###
# change data width & cross domain crossing
rx = SATAPHYDatapathRX()
tx = SATAPHYDatapathTX()
self.submodules += rx, tx
# TX path
self.align_inserter = SATAPHYAlignInserter(ctrl)
self.mux = Multiplexer(phy_description(32), 2)
self.tx = SATAPHYDatapathTX()
self.comb += [
trx.source.connect(rx.sink),
tx.source.connect(trx.sink)
self.mux.sel.eq(ctrl.ready),
Record.connect(self.sink, self.align_inserter.sink),
Record.connect(ctrl.source, self.mux.sink0),
Record.connect(self.align_inserter.source, self.mux.sink1),
Record.connect(self.mux.source, self.tx.sink),
Record.connect(self.tx.source, trx.sink)
]
# Align cnt (send 2 Align DWORDs every 256 DWORDs)
align_cnt = Signal(8)
self.sync += \
If(~ctrl.ready,
align_cnt.eq(0)
).Elif(tx.sink.stb & tx.sink.ack,
align_cnt.eq(align_cnt+1)
)
send_align = (align_cnt < 2)
receive_align = Signal()
self.comb += receive_align.eq(rx.source.stb &
(rx.source.charisk == 0b0001) &
(rx.source.data == primitives["ALIGN"]))
# user / ctrl mux
# RX path
self.rx = SATAPHYDatapathRX()
self.demux = Demultiplexer(phy_description(32), 2)
self.align_remover = SATAPHYAlignRemover()
self.comb += [
# user
If(ctrl.ready,
If(send_align,
tx.sink.stb.eq(1),
tx.sink.data.eq(primitives["ALIGN"]),
tx.sink.charisk.eq(0b0001),
self.sink.ack.eq(0)
).Else(
tx.sink.stb.eq(self.sink.stb),
tx.sink.data.eq(self.sink.data),
tx.sink.charisk.eq(self.sink.charisk),
self.sink.ack.eq(tx.sink.ack)
),
If(receive_align,
rx.source.ack.eq(1)
).Else(
self.source.stb.eq(rx.source.stb),
self.source.data.eq(rx.source.data),
self.source.charisk.eq(rx.source.charisk),
rx.source.ack.eq(1)
)
# ctrl
).Else(
tx.sink.stb.eq(ctrl.source.stb),
tx.sink.data.eq(ctrl.source.data),
tx.sink.charisk.eq(ctrl.source.charisk),
ctrl.sink.stb.eq(rx.source.stb),
ctrl.sink.data.eq(rx.source.data),
rx.source.ack.eq(1),
)
self.demux.sel.eq(ctrl.ready),
Record.connect(trx.source, self.rx.sink),
Record.connect(self.rx.source, self.demux.sink),
Record.connect(self.demux.source0, ctrl.sink),
Record.connect(self.demux.source1, self.align_remover.sink),
Record.connect(self.align_remover.source, self.source)
]

View File

@ -6,6 +6,9 @@ CMD = PYTHONPATH=$(MSCDIR) $(PYTHON)
CC=gcc
CFLAGS =-Wall -O0
phy_datapath_tb:
$(CMD) phy_datapath_tb.py
crc_tb:
$(CC) $(CFLAGS) $(INC) -o crc crc.c
$(CMD) crc_tb.py

View File

@ -0,0 +1,88 @@
from lib.sata.common import *
from lib.sata.phy.datapath import SATAPHYDatapath
from lib.sata.test.common import *
class DataPacket(list):
def __init__(self, data=[]):
self.ongoing = False
self.done = False
for d in data:
self.append(d)
class DataStreamer(PacketStreamer):
def __init__(self):
PacketStreamer.__init__(self, phy_description(32), DataPacket)
def do_simulation(self, selfp):
PacketStreamer.do_simulation(self, selfp)
selfp.source.charisk = 0
# Note: for simplicity we generate charisk by detecting
# primitives in data
for k, v in primitives.items():
try:
if self.source_data == v:
selfp.source.charisk = 0b0001
except:
pass
class DataLogger(PacketLogger):
def __init__(self):
PacketLogger.__init__(self, phy_description(32), DataPacket)
class TRX(Module):
def __init__(self):
self.sink = Sink(phy_description(32))
self.source = Source(phy_description(32))
self.comb += Record.connect(self.sink, self.source)
class CTRL(Module):
def __init__(self):
self.sink = Sink(phy_description(32))
self.source = Source(phy_description(32))
self.ready = Signal(reset=1)
class TB(Module):
def __init__(self):
# use sys_clk for each clock_domain
self.clock_domains.cd_sata_rx = ClockDomain()
self.clock_domains.cd_sata_tx = ClockDomain()
self.comb += [
self.cd_sata_rx.clk.eq(ClockSignal()),
self.cd_sata_rx.rst.eq(ResetSignal()),
self.cd_sata_tx.clk.eq(ClockSignal()),
self.cd_sata_tx.rst.eq(ResetSignal()),
]
self.streamer = DataStreamer()
self.streamer_randomizer = Randomizer(phy_description(32), level=0)
self.trx = TRX()
self.ctrl = CTRL()
self.datapath = SATAPHYDatapath(self.trx, self.ctrl)
self.logger_randomizer = Randomizer(phy_description(32), level=0)
self.logger = DataLogger()
self.pipeline = Pipeline(
self.streamer,
self.streamer_randomizer,
self.datapath,
self.logger_randomizer,
self.logger
)
def gen_simulation(self, selfp):
streamer_packet = DataPacket([seed_to_data(i, False) for i in range(512)])
yield from self.streamer.send(streamer_packet)
yield from self.logger.receive(512)
for d in self.logger.packet:
r = "%08x " %d
r +=decode_primitive(d)
print(r)
# check results
#s, l, e = check(streamer_packet, self.logger.packet)
#print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
if __name__ == "__main__":
run_simulation(TB(), ncycles=4096, vcd_name="my.vcd", keep_files=True)