Adding testing of cpu variants.
[litex.git] / test / test_code_8b10b.py
1 import unittest
2 import random
3 from collections import namedtuple
4
5 from migen import *
6
7 from litex.soc.cores import code_8b10b
8
9
10 Control = namedtuple("Control", "value")
11
12
13 def encode_sequence(seq):
14 output = []
15
16 dut = code_8b10b.Encoder()
17 def pump():
18 for w in seq:
19 if isinstance(w, Control):
20 yield dut.k[0].eq(1)
21 yield dut.d[0].eq(w.value)
22 else:
23 yield dut.k[0].eq(0)
24 yield dut.d[0].eq(w)
25 yield
26 output.append((yield dut.output[0]))
27 for _ in range(2):
28 yield
29 output.append((yield dut.output[0]))
30 run_simulation(dut, pump())
31
32 return output[2:]
33
34
35 def decode_sequence(seq):
36 output = []
37
38 dut = code_8b10b.Decoder()
39 def pump():
40 for w in seq:
41 yield dut.input.eq(w)
42 yield
43 if (yield dut.k):
44 output.append(Control((yield dut.d)))
45 else:
46 output.append((yield dut.d))
47 yield
48 if (yield dut.k):
49 output.append(Control((yield dut.d)))
50 else:
51 output.append((yield dut.d))
52 run_simulation(dut, pump())
53 return output[1:]
54
55
56 class TestLineCoding(unittest.TestCase):
57 @classmethod
58 def setUpClass(cls):
59 prng = random.Random(42)
60 cls.input_sequence = []
61 for i in 23, 27, 29, 30:
62 cls.input_sequence += [Control((7 << 5) | i)]*2
63 for i in range(8):
64 cls.input_sequence += [Control((i << 5) | 28)]*2
65 cls.input_sequence += [prng.randrange(256) for _ in range(10000)]
66 cls.output_sequence = encode_sequence(cls.input_sequence)
67
68 def test_comma(self):
69 control_chars = [
70 0b1110101000,
71 0b1101101000,
72 0b1011101000,
73 0b0111101000,
74
75 0b0011110100,
76 0b0011111001,
77 0b0011110101,
78 0b0011110011,
79 0b0011110010,
80 0b0011111010,
81 0b0011110110,
82 0b0011111000,
83 ]
84 for i, c in enumerate(control_chars):
85 ok = {c, ~c & 0b1111111111}
86 with self.subTest(i=i):
87 self.assertIn(self.output_sequence[2*i], ok)
88 self.assertIn(self.output_sequence[2*i+1], ok)
89
90 def test_running_disparity(self):
91 rd = -1
92 for w in self.output_sequence:
93 rd += code_8b10b.disparity(w, 10)
94 self.assertIn(rd, {-1, 1})
95
96 def test_no_spurious_commas(self):
97 for w1, w2 in zip(self.output_sequence[16+8:], self.output_sequence[16+8+1:]):
98 for shift in range(10):
99 cw = (w1 << shift) | (w2 >> (10-shift))
100 self.assertNotIn(cw, {0b0011111001, 0b1100000110, # K28.1
101 0b0011111010, 0b1100000101, # K28.5
102 0b0011111000, 0b1100000111}) # K28.7
103
104 def test_roundtrip(self):
105 self.assertEqual(self.input_sequence,
106 decode_sequence(self.output_sequence))