diff --git a/milkymist/framebuffer/dvi.py b/milkymist/framebuffer/dvi.py index 7f4b2ac74..953ac2806 100644 --- a/milkymist/framebuffer/dvi.py +++ b/milkymist/framebuffer/dvi.py @@ -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))