3 from collections
import namedtuple
7 from litex
.soc
.cores
import code_8b10b
10 Control
= namedtuple("Control", "value")
13 def encode_sequence(seq
):
16 dut
= code_8b10b
.Encoder()
19 if isinstance(w
, Control
):
21 yield dut
.d
[0].eq(w
.value
)
26 output
.append((yield dut
.output
[0]))
29 output
.append((yield dut
.output
[0]))
30 run_simulation(dut
, pump())
35 def decode_sequence(seq
):
38 dut
= code_8b10b
.Decoder()
44 output
.append(Control((yield dut
.d
)))
46 output
.append((yield dut
.d
))
49 output
.append(Control((yield dut
.d
)))
51 output
.append((yield dut
.d
))
52 run_simulation(dut
, pump())
56 class TestLineCoding(unittest
.TestCase
):
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
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
)
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
)
90 def test_running_disparity(self
):
92 for w
in self
.output_sequence
:
93 rd
+= code_8b10b
.disparity(w
, 10)
94 self
.assertIn(rd
, {-1, 1})
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
104 def test_roundtrip(self
):
105 self
.assertEqual(self
.input_sequence
,
106 decode_sequence(self
.output_sequence
))