mirror of
https://github.com/enjoy-digital/usb3_pipe.git
synced 2025-01-04 10:18:41 +08:00
usb3_pipe/ordered_set: add OrderedSetTransmitter
This commit is contained in:
parent
cef3189280
commit
43f089281d
@ -6,7 +6,7 @@ import unittest
|
|||||||
from migen import *
|
from migen import *
|
||||||
|
|
||||||
from usb3_pipe.common import TSEQ, TS1
|
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):
|
class TestOrderedSet(unittest.TestCase):
|
||||||
@ -38,7 +38,7 @@ class TestOrderedSet(unittest.TestCase):
|
|||||||
generator(dut, n_loops=32),
|
generator(dut, n_loops=32),
|
||||||
checker(dut, n_loops=32, n_ordered_sets=4),
|
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):
|
def test_ts1_receiver(self):
|
||||||
@ -72,4 +72,75 @@ class TestOrderedSet(unittest.TestCase):
|
|||||||
generator(dut, n_loops=32),
|
generator(dut, n_loops=32),
|
||||||
checker(dut, n_loops=32, n_ordered_sets=4),
|
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)
|
||||||
|
@ -28,7 +28,7 @@ class OrderedSetReceiver(Module):
|
|||||||
port = mem.get_port(async_read=True)
|
port = mem.get_port(async_read=True)
|
||||||
self.specials += mem, port
|
self.specials += mem, port
|
||||||
|
|
||||||
# Error detection --------------------------------------------------------------------------
|
# Data check -------------------------------------------------------------------------------
|
||||||
error = Signal()
|
error = Signal()
|
||||||
error_mask = Signal(data_width, reset=2**data_width-1)
|
error_mask = Signal(data_width, reset=2**data_width-1)
|
||||||
if ordered_set.name in ["TS1", "TS2"]:
|
if ordered_set.name in ["TS1", "TS2"]:
|
||||||
@ -101,3 +101,86 @@ class OrderedSetReceiver(Module):
|
|||||||
|
|
||||||
# Result -----------------------------------------------------------------------------------
|
# Result -----------------------------------------------------------------------------------
|
||||||
self.comb += self.detected.eq(count == (mem_depth*n_ordered_sets - 1))
|
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))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user