usb3_pipe/ordered_set: add OrderedSetTransmitter

This commit is contained in:
Florent Kermarrec 2019-10-03 17:03:53 +02:00
parent cef3189280
commit 43f089281d
2 changed files with 158 additions and 4 deletions

View File

@ -6,7 +6,7 @@ import unittest
from migen import *
from usb3_pipe.common import TSEQ, TS1
from usb3_pipe.ordered_set import OrderedSetReceiver
from usb3_pipe.ordered_set import OrderedSetReceiver, OrderedSetTransmitter
class TestOrderedSet(unittest.TestCase):
@ -38,7 +38,7 @@ class TestOrderedSet(unittest.TestCase):
generator(dut, n_loops=32),
checker(dut, n_loops=32, n_ordered_sets=4),
]
run_simulation(dut, generators, vcd_name="tseq.vcd")
run_simulation(dut, generators)
def test_ts1_receiver(self):
@ -72,4 +72,75 @@ class TestOrderedSet(unittest.TestCase):
generator(dut, n_loops=32),
checker(dut, n_loops=32, n_ordered_sets=4),
]
run_simulation(dut, generators, vcd_name="ts1.vcd")
run_simulation(dut, generators)
def test_tseq_transmitter(self):
tseq_length = len(TSEQ.to_bytes())//4
tseq_words = [int.from_bytes(TSEQ.to_bytes()[4*i:4*(i+1)], "little") for i in range(tseq_length)]
def generator(dut, n_loops):
for i in range(n_loops):
yield dut.send.eq(1)
yield
yield dut.send.eq(0)
yield
while not (yield dut.done):
yield
yield
for i in range(128):
yield
dut.run = False
def checker(dut, n_loops, n_ordered_sets):
words = []
yield dut.source.ready.eq(1)
yield
while dut.run:
if (yield dut.source.valid):
words.append((yield dut.source.data))
yield
self.assertEqual(words, tseq_words*n_loops*n_ordered_sets)
dut = OrderedSetTransmitter(ordered_set=TSEQ, n_ordered_sets=4, data_width=32)
dut.run = True
generators = [
generator(dut, n_loops=32),
checker(dut, n_loops=32, n_ordered_sets=4),
]
run_simulation(dut, generators)
def test_ts1_transmitter(self):
ts1_length = len(TS1.to_bytes())//4
ts1_words = [int.from_bytes(TS1.to_bytes()[4*i:4*(i+1)], "little") for i in range(ts1_length)]
def generator(dut, n_loops):
for i in range(n_loops):
yield dut.send.eq(1)
yield dut.reset.eq(0)
yield dut.loopback.eq(0)
yield dut.scrambling.eq(1)
yield
yield dut.send.eq(0)
yield
while not (yield dut.done):
yield
yield
for i in range(128):
yield
dut.run = False
def checker(dut, n_loops, n_ordered_sets):
words = []
yield dut.source.ready.eq(1)
yield
while dut.run:
if (yield dut.source.valid):
words.append((yield dut.source.data))
yield
self.assertEqual(words, ts1_words*n_loops*n_ordered_sets)
dut = OrderedSetTransmitter(ordered_set=TS1, n_ordered_sets=4, data_width=32)
dut.run = True
generators = [
generator(dut, n_loops=32),
checker(dut, n_loops=32, n_ordered_sets=4),
]
run_simulation(dut, generators)

View File

@ -28,7 +28,7 @@ class OrderedSetReceiver(Module):
port = mem.get_port(async_read=True)
self.specials += mem, port
# Error detection --------------------------------------------------------------------------
# Data check -------------------------------------------------------------------------------
error = Signal()
error_mask = Signal(data_width, reset=2**data_width-1)
if ordered_set.name in ["TS1", "TS2"]:
@ -101,3 +101,86 @@ class OrderedSetReceiver(Module):
# Result -----------------------------------------------------------------------------------
self.comb += self.detected.eq(count == (mem_depth*n_ordered_sets - 1))
# Ordered Set Transmitter --------------------------------------------------------------------------
class OrderedSetTransmitter(Module):
def __init__(self, ordered_set, n_ordered_sets, data_width):
assert data_width in [16, 32]
self.send = Signal() # i
self.done = Signal() # i
self.source = stream.Endpoint([("data", data_width), ("ctrl", data_width//8)])
if ordered_set.name in ["TS1", "TS2"]:
self.reset = Signal() # i
self.loopback = Signal() # i
self.scrambling = Signal() # i
# # #
run = Signal()
# Memory --------------------------------------------------------------------------------
mem_depth = len(ordered_set.to_bytes())//(data_width//8)
mem_init = [int.from_bytes(ordered_set.to_bytes()[4*i:4*(i+1)], "little") for i in range(mem_depth)]
mem = Memory(data_width, mem_depth, mem_init)
port = mem.get_port(async_read=True)
self.specials += mem, port
# Memory address generation ----------------------------------------------------------------
self.sync += [
If(self.source.valid & self.source.ready,
If(port.adr == (mem_depth - 1),
port.adr.eq(0)
).Else(
port.adr.eq(port.adr + 1)
)
).Else(
port.adr.eq(0)
)
]
# Link Config ------------------------------------------------------------------------------
link_config = Signal(8)
if ordered_set.name in ["TS1", "TS2"]:
self.comb += [
link_config[0].eq(self.reset),
link_config[1].eq(self.loopback),
link_config[2].eq(~self.scrambling)
]
# Data generation --------------------------------------------------------------------------
if ordered_set.name in ["TS1", "TS2"]:
first_ctrl = 2**(data_width//8) - 1
else:
first_ctrl = 1
self.comb += [
self.source.valid.eq(self.send | ~self.done),
If(port.adr == 0,
self.source.ctrl.eq(first_ctrl),
).Else(
self.source.ctrl.eq(0)
),
self.source.data.eq(port.dat_r)
]
if ordered_set.name in ["TS1", "TS2"]:
if data_width == 32:
self.comb += If(port.adr == 1, self.source.data[8:16].eq(link_config))
else:
self.comb += If(port.adr == 2, self.source.data[8:16].eq(link_config))
# Count ------------------------------------------------------------------------------------
count = Signal(max=mem_depth*n_ordered_sets)
self.sync += [
If(self.send,
run.eq(1),
count.eq(0),
).Elif(self.done,
run.eq(0),
).Else(
count.eq(count + 1)
)
]
# Result -----------------------------------------------------------------------------------
self.comb += self.done.eq(count == (mem_depth*n_ordered_sets - 1))