mirror of
https://github.com/enjoy-digital/usb3_pipe.git
synced 2025-01-04 10:18:41 +08:00
216 lines
7.5 KiB
Python
216 lines
7.5 KiB
Python
# This file is Copyright (c) 2019 Florent Kermarrec <florent@enjoy-digital.fr>
|
|
# License: BSD
|
|
|
|
import unittest
|
|
import random
|
|
|
|
from migen import *
|
|
|
|
from usb3_pipe.serdes import RXWordAligner
|
|
from usb3_pipe.serdes import RXSkipRemover, TXSkipInserter
|
|
from usb3_pipe.serdes import SerdesTXDatapath, SerdesRXDatapath
|
|
|
|
|
|
class TestSerDes(unittest.TestCase):
|
|
def test_rx_word_aligner(self):
|
|
datas_input = [
|
|
0x030201bc, 0x07060504, 0x0b0a0908, 0x0f0e0d0c,
|
|
0x0201bc07, 0x0605040b, 0x0a09080f, 0x0e0d0c13,
|
|
0x9cbc1f01, 0x0300202f, 0x8d03a500, 0x00005352,
|
|
0xbc878685, 0x848b8a89, 0x888f8e8d, 0x8c929190,
|
|
0xbcbcbcbc, 0x07060504, 0x0b0a0908, 0x0f0e0d0c,
|
|
0xbcbcbc00, 0x070605bc, 0x0b0a0908, 0x0f0e0d0c,
|
|
0xbcbc0000, 0x0706bcbc, 0x0b0a0908, 0x0f0e0d0c,
|
|
0xbc000000, 0x07bcbcbc, 0x0b0a0908, 0x0f0e0d0c,
|
|
]
|
|
ctrls_input = [
|
|
0x1, 0x0, 0x0, 0x0,
|
|
0x2, 0x0, 0x0, 0x0,
|
|
0x4, 0x0, 0x0, 0x0,
|
|
0x8, 0x0, 0x0, 0x0,
|
|
0xf, 0x0, 0x0, 0x0,
|
|
0xe, 0x1, 0x0, 0x0,
|
|
0xc, 0x3, 0x0, 0x0,
|
|
0x8, 0x7, 0x0, 0x0,
|
|
]
|
|
datas_reference = [
|
|
0x030201bc, 0x07060504, 0x0b0a0908, 0x0f0e0d0c,
|
|
0x0b0201bc, 0x0f060504, 0x130a0908, 0x010e0d0c,
|
|
0x202f9cbc, 0xa5000300, 0x53528d03, 0x86850000,
|
|
0x8b8a89bc, 0x8f8e8d84, 0x92919088, 0xbcbcbc8c,
|
|
0xbcbcbcbc, 0x07060504, 0x0b0a0908, 0x0f0e0d0c,
|
|
0xbcbcbcbc, 0x08070605, 0x0c0b0a09, 0x000f0e0d,
|
|
0xbcbcbcbc, 0x09080706, 0x0d0c0b0a, 0x00000f0e,
|
|
0xbcbcbcbc, 0x0a090807, 0x0e0d0c0b, 0x0e0d0c0f,
|
|
]
|
|
ctrls_reference = [
|
|
0x1, 0x0, 0x0, 0x0,
|
|
0x1, 0x0, 0x0, 0x0,
|
|
0x1, 0x0, 0x0, 0x0,
|
|
0x1, 0x0, 0x0, 0xe,
|
|
0xf, 0x0, 0x0, 0x0,
|
|
0xf, 0x0, 0x0, 0x0,
|
|
0xf, 0x0, 0x0, 0x0,
|
|
0xf, 0x0, 0x0, 0x0,
|
|
]
|
|
|
|
def generator(dut):
|
|
yield dut.sink.valid.eq(1)
|
|
for data, ctrl in zip(datas_input, ctrls_input):
|
|
yield dut.sink.data.eq(data)
|
|
yield dut.sink.ctrl.eq(ctrl)
|
|
yield
|
|
|
|
def checker(dut):
|
|
dut.datas_errors = 0
|
|
dut.ctrls_errors = 0
|
|
yield dut.source.ready.eq(1)
|
|
while not (yield dut.source.valid):
|
|
yield
|
|
for data, ctrl in zip(datas_reference, ctrls_reference):
|
|
#print("{:08x} vs {:08x}".format((yield dut.source.data), data))
|
|
if (yield dut.source.data) != data:
|
|
dut.datas_errors += 1
|
|
if (yield dut.source.ctrl) != ctrl:
|
|
dut.ctrls_errors += 1
|
|
yield
|
|
|
|
dut = RXWordAligner()
|
|
run_simulation(dut, [generator(dut), checker(dut)])
|
|
self.assertEqual(dut.datas_errors, 0)
|
|
self.assertEqual(dut.ctrls_errors, 0)
|
|
|
|
|
|
def test_rx_skip_remover(self):
|
|
datas_input = [
|
|
0x0302013c, 0x07060504, 0x0b0a0908, 0x0f0e0d0c,
|
|
0x02013c07, 0x0605040b, 0x0a09080f, 0x0e0d0c13,
|
|
0x9c3c1f01, 0x0300202f, 0x8d03a500, 0x00005352,
|
|
0x3c878685, 0x848b8a89, 0x888f8e8d, 0x8c929190,
|
|
0xbc3c3c4a, 0x00bcbcbc, 0x4a4a4a00, 0x4a4a4a4a,
|
|
]
|
|
ctrls_input = [
|
|
0x1, 0x0, 0x0, 0x0,
|
|
0x2, 0x0, 0x0, 0x0,
|
|
0x4, 0x0, 0x0, 0x0,
|
|
0x8, 0x0, 0x0, 0x0,
|
|
0xe, 0x7, 0x0, 0x0,
|
|
]
|
|
datas_reference = [
|
|
0x04030201, 0x08070605, 0x0c0b0a09, 0x070f0e0d,
|
|
0x040b0201, 0x080f0605, 0x0c130a09, 0x1f010e0d,
|
|
0x00202f9c, 0x03a50003, 0x0053528d, 0x87868500,
|
|
0x848b8a89, 0x888f8e8d, 0x8c929190,
|
|
0xbcbcbc4a, 0x4a0000bc, 0x4a4a4a4a,
|
|
]
|
|
ctrls_reference = [
|
|
0x0, 0x0, 0x0, 0x0,
|
|
0x0, 0x0, 0x0, 0x0,
|
|
0x0, 0x0, 0x0, 0x0,
|
|
0x0, 0x0, 0x0,
|
|
0xe, 0x1, 0x0,
|
|
]
|
|
|
|
def generator(dut):
|
|
for data, ctrl in zip(datas_input, ctrls_input):
|
|
yield dut.sink.valid.eq(1)
|
|
yield dut.sink.data.eq(data)
|
|
yield dut.sink.ctrl.eq(ctrl)
|
|
yield
|
|
yield dut.sink.valid.eq(0)
|
|
yield
|
|
for i in range(128):
|
|
yield
|
|
|
|
def checker(dut):
|
|
dut.datas_errors = 0
|
|
dut.ctrls_errors = 0
|
|
for data, ctrl in zip(datas_reference, ctrls_reference):
|
|
while not (yield dut.source.valid):
|
|
yield
|
|
yield dut.source.ready.eq(1)
|
|
#print("{:08x} vs {:08x}".format((yield dut.source.data), data))
|
|
if (yield dut.source.data) != data:
|
|
dut.datas_errors += 1
|
|
if (yield dut.source.ctrl) != ctrl:
|
|
dut.ctrls_errors += 1
|
|
yield
|
|
yield dut.source.ready.eq(0)
|
|
yield
|
|
|
|
dut = RXSkipRemover()
|
|
run_simulation(dut, [generator(dut), checker(dut)])
|
|
self.assertEqual(dut.datas_errors, 0)
|
|
self.assertEqual(dut.ctrls_errors, 0)
|
|
|
|
def test_tx_skip_inserter(self):
|
|
def generator(dut):
|
|
for i in range(256):
|
|
yield dut.sink.valid.eq(1)
|
|
yield
|
|
|
|
@passive
|
|
def checker(dut):
|
|
yield dut.source.ready.eq(1)
|
|
dut.ctrl_errors = 0
|
|
dut.data_errors = 0
|
|
while not (yield dut.source.valid):
|
|
yield
|
|
while True:
|
|
for i in range(167):
|
|
yield
|
|
if (yield dut.source.ctrl) != 0b1111:
|
|
dut.ctrl_errors += 1
|
|
if (yield dut.source.data) != 0x3c3c3c3c:
|
|
dut.data_errors += 1
|
|
yield
|
|
yield
|
|
|
|
dut = TXSkipInserter()
|
|
run_simulation(dut, [generator(dut), checker(dut)])
|
|
self.assertEqual(dut.data_errors, 0)
|
|
self.assertEqual(dut.ctrl_errors, 0)
|
|
|
|
def test_datapath_loopback(self):
|
|
prng = random.Random(42)
|
|
datas = [prng.randrange(2**32) for _ in range(64)]
|
|
ctrls = [prng.randrange(2**4) for _ in range(64)]
|
|
|
|
class DUT(Module):
|
|
def __init__(self):
|
|
self.submodules.tx = SerdesTXDatapath("serdes")
|
|
self.submodules.rx = SerdesRXDatapath("serdes")
|
|
self.comb += self.tx.source.connect(self.rx.sink)
|
|
|
|
def generator(dut):
|
|
for data, ctrl in zip(datas, ctrls):
|
|
yield dut.tx.sink.valid.eq(1)
|
|
yield dut.tx.sink.data.eq(data)
|
|
yield dut.tx.sink.ctrl.eq(ctrl)
|
|
yield
|
|
while not (yield dut.tx.sink.ready):
|
|
yield
|
|
yield dut.tx.sink.valid.eq(0)
|
|
|
|
@passive
|
|
def checker(dut):
|
|
dut.data_errors = 0
|
|
dut.ctrl_errors = 0
|
|
yield dut.rx.source.ready.eq(1)
|
|
for data, ctrl in zip(datas, ctrls):
|
|
while not (yield dut.rx.source.valid):
|
|
yield
|
|
if (yield dut.rx.source.data != data):
|
|
dut.data_errors += 1
|
|
if (yield dut.rx.source.ctrl != ctrl):
|
|
dut.ctrl_errors += 1
|
|
yield
|
|
|
|
dut = DUT()
|
|
run_simulation(dut,
|
|
generators = [generator(dut), checker(dut)],
|
|
clocks = {"sys": 1e9/133e6, "serdes": 1e9/125e6},
|
|
)
|
|
self.assertEqual(dut.data_errors, 0)
|
|
self.assertEqual(dut.ctrl_errors, 0)
|