framebuffer/dvi: TMDS encoder test bench
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Mon, 16 Sep 2013 22:25:07 +0000 (00:25 +0200)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Mon, 16 Sep 2013 22:25:07 +0000 (00:25 +0200)
milkymist/framebuffer/dvi.py

index 7f4b2ac7465452c53f68afb2f0ae15db79749521..953ac28061a5d486cbb6a5836ef8963b67c10ef0 100644 (file)
@@ -9,7 +9,7 @@ class Encoder(Module):
                self.c = Signal(2)
                self.de = Signal()
 
-               self.output = Signal(10)
+               self.out = Signal(10)
 
                ###
 
@@ -44,7 +44,7 @@ class Encoder(Module):
                ]
 
                # stage 4 - final encoding
-               cnt = Signal((5, True))
+               cnt = Signal((6, True))
 
                s_c = self.c
                s_de = self.de
@@ -56,33 +56,91 @@ class Encoder(Module):
 
                self.sync += If(s_de,
                                If((cnt == 0) | (n1q_m == n0q_m),
-                                       self.output[9].eq(~q_m_r[8]),
-                                       self.output[8].eq(q_m_r[8]),
+                                       self.out[9].eq(~q_m_r[8]),
+                                       self.out[8].eq(q_m_r[8]),
                                        If(q_m_r[8],
-                                               self.output[:8].eq(q_m_r[:8]),
+                                               self.out[:8].eq(q_m_r[:8]),
                                                cnt.eq(cnt + n1q_m - n0q_m)
                                        ).Else(
-                                               self.output[:8].eq(~q_m_r[:8]),
+                                               self.out[:8].eq(~q_m_r[:8]),
                                                cnt.eq(cnt + n0q_m - n1q_m)
                                        )
                                ).Else(
-                                       If((~cnt[4] & (n1q_m > n0q_m)) | (cnt[4] & (n0q_m > n1q_m)),
-                                               self.output[9].eq(1),
-                                               self.output[8].eq(q_m_r[8]),
-                                               self.output[:8].eq(~q_m_r[:8]),
+                                       If((~cnt[5] & (n1q_m > n0q_m)) | (cnt[5] & (n0q_m > n1q_m)),
+                                               self.out[9].eq(1),
+                                               self.out[8].eq(q_m_r[8]),
+                                               self.out[:8].eq(~q_m_r[:8]),
                                                cnt.eq(cnt + Cat(0, q_m_r[8]) + n0q_m - n1q_m)
                                        ).Else(
-                                               self.output[9].eq(0),
-                                               self.output[8].eq(q_m_r[8]),
-                                               self.output[:8].eq(q_m_r[:8]),
+                                               self.out[9].eq(0),
+                                               self.out[8].eq(q_m_r[8]),
+                                               self.out[:8].eq(q_m_r[:8]),
                                                cnt.eq(cnt - Cat(0, ~q_m_r[8]) + n1q_m - n0q_m)
                                        )
                                )
                        ).Else(
-                               self.output.eq(Array(control_tokens)[s_c]),
+                               self.out.eq(Array(control_tokens)[s_c]),
                                cnt.eq(0)
                        )
 
+class _EncoderTB(Module):
+       def __init__(self, inputs):
+               self.outs = []
+               self._iter_inputs = iter(inputs)
+               self._end_cycle = None
+               self.submodules.dut = Encoder()
+               self.comb += self.dut.de.eq(1)
+
+       def do_simulation(self, s):
+               if self._end_cycle is None:
+                       try:
+                               nv = next(self._iter_inputs)
+                       except StopIteration:
+                               self._end_cycle = s.cycle_counter + 4
+                       else:
+                               s.wr(self.dut.d, nv)
+               if s.cycle_counter == self._end_cycle:
+                       s.interrupt = True
+               if s.cycle_counter > 4:
+                       self.outs.append(s.rd(self.dut.out))
+
+def _bit(i, n):
+       return (i >> n) & 1
+
+def _decode_tmds(b):
+       try:
+               c = control_tokens.index(b)
+               de = False
+       except ValueError:
+               c = 0
+               de = True
+       vsync = bool(c & 2)
+       hsync = bool(c & 1)
+
+       value = _bit(b, 0) ^ _bit(b, 9)
+       for i in range(1, 8):
+               value |= (_bit(b, i) ^ _bit(b, i-1) ^ (~_bit(b, 8) & 1)) << i
+
+       return de, hsync, vsync, value
+
 if __name__ == "__main__":
-       from migen.fhdl import verilog
-       print(verilog.convert(Encoder()))
+       from migen.sim.generic import Simulator
+       from random import Random
+       
+       rng = Random(788)
+       test_list = [rng.randrange(256) for i in range(500)]
+       tb = _EncoderTB(test_list)
+       Simulator(tb).run()
+
+       check = [_decode_tmds(out)[3] for out in tb.outs]
+       assert(check == test_list)
+       
+       nb0 = 0
+       nb1 = 0
+       for out in tb.outs:
+               for i in range(10):
+                       if _bit(out, i):
+                               nb1 += 1
+                       else:
+                               nb0 += 1
+       print("0/1: {}/{} ({:.2f})".format(nb0, nb1, nb0/nb1))