From 96898f1b3906b336a3e3306fc5ba93bf8b9d41b6 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Mon, 24 Apr 2017 18:45:02 +0200 Subject: [PATCH] add test directory with test_code_8b10b.py (from misoc) --- setup.py | 1 + test/__init__.py | 0 test/test_code_8b10b.py | 106 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 107 insertions(+) create mode 100644 test/__init__.py create mode 100644 test/test_code_8b10b.py diff --git a/setup.py b/setup.py index b1db8d9e1..033a196cd 100755 --- a/setup.py +++ b/setup.py @@ -18,6 +18,7 @@ setup( author_email="florent@enjoy-digital.fr", url="http://enjoy-digital.fr", download_url="https://github.com/enjoy-digital/litex", + test_suite="test", license="BSD", platforms=["Any"], keywords="HDL ASIC FPGA hardware design", diff --git a/test/__init__.py b/test/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/test/test_code_8b10b.py b/test/test_code_8b10b.py new file mode 100644 index 000000000..56d847150 --- /dev/null +++ b/test/test_code_8b10b.py @@ -0,0 +1,106 @@ +import unittest +import random +from collections import namedtuple + +from litex.gen import * + +from litex.soc.cores import code_8b10b + + +Control = namedtuple("Control", "value") + + +def encode_sequence(seq): + output = [] + + dut = code_8b10b.Encoder() + def pump(): + for w in seq: + if isinstance(w, Control): + yield dut.k[0].eq(1) + yield dut.d[0].eq(w.value) + else: + yield dut.k[0].eq(0) + yield dut.d[0].eq(w) + yield + output.append((yield dut.output[0])) + for _ in range(2): + yield + output.append((yield dut.output[0])) + run_simulation(dut, pump()) + + return output[2:] + + +def decode_sequence(seq): + output = [] + + dut = code_8b10b.Decoder() + def pump(): + for w in seq: + yield dut.input.eq(w) + yield + if (yield dut.k): + output.append(Control((yield dut.d))) + else: + output.append((yield dut.d)) + yield + if (yield dut.k): + output.append(Control((yield dut.d))) + else: + output.append((yield dut.d)) + run_simulation(dut, pump()) + return output[1:] + + +class TestLineCoding(unittest.TestCase): + @classmethod + def setUpClass(cls): + prng = random.Random(42) + cls.input_sequence = [] + for i in 23, 27, 29, 30: + cls.input_sequence += [Control((7 << 5) | i)]*2 + for i in range(8): + cls.input_sequence += [Control((i << 5) | 28)]*2 + cls.input_sequence += [prng.randrange(256) for _ in range(10000)] + cls.output_sequence = encode_sequence(cls.input_sequence) + + def test_comma(self): + control_chars = [ + 0b1110101000, + 0b1101101000, + 0b1011101000, + 0b0111101000, + + 0b0011110100, + 0b0011111001, + 0b0011110101, + 0b0011110011, + 0b0011110010, + 0b0011111010, + 0b0011110110, + 0b0011111000, + ] + for i, c in enumerate(control_chars): + ok = {c, ~c & 0b1111111111} + with self.subTest(i=i): + self.assertIn(self.output_sequence[2*i], ok) + self.assertIn(self.output_sequence[2*i+1], ok) + + def test_running_disparity(self): + rd = -1 + for w in self.output_sequence: + rd += code_8b10b.disparity(w, 10) + self.assertIn(rd, {-1, 1}) + + def test_no_spurious_commas(self): + for w1, w2 in zip(self.output_sequence[16+8:], self.output_sequence[16+8+1:]): + for shift in range(10): + cw = (w1 << shift) | (w2 >> (10-shift)) + self.assertNotIn(cw, {0b0011111001, 0b1100000110, # K28.1 + 0b0011111010, 0b1100000101, # K28.5 + 0b0011111000, 0b1100000111}) # K28.7 + + def test_roundtrip(self): + self.assertEqual(self.input_sequence, + decode_sequence(self.output_sequence))