import migen in litex/gen
[litex.git] / litex / soc / misoc / cores / framebuffer / dvi.py
1 from functools import reduce
2 from operator import add
3
4 from migen import *
5
6
7 control_tokens = [0b1101010100, 0b0010101011, 0b0101010100, 0b1010101011]
8
9
10 class Encoder(Module):
11 def __init__(self):
12 self.d = Signal(8)
13 self.c = Signal(2)
14 self.de = Signal()
15
16 self.out = Signal(10)
17
18 ###
19
20 # stage 1 - count number of 1s in data
21 d = Signal(8)
22 n1d = Signal(max=9)
23 self.sync += [
24 n1d.eq(reduce(add, [self.d[i] for i in range(8)])),
25 d.eq(self.d)
26 ]
27
28 # stage 2 - add 9th bit
29 q_m = Signal(9)
30 q_m8_n = Signal()
31 self.comb += q_m8_n.eq((n1d > 4) | ((n1d == 4) & ~d[0]))
32 for i in range(8):
33 if i:
34 curval = curval ^ d[i] ^ q_m8_n
35 else:
36 curval = d[0]
37 self.sync += q_m[i].eq(curval)
38 self.sync += q_m[8].eq(~q_m8_n)
39
40 # stage 3 - count number of 1s and 0s in q_m[:8]
41 q_m_r = Signal(9)
42 n0q_m = Signal(max=9)
43 n1q_m = Signal(max=9)
44 self.sync += [
45 n0q_m.eq(reduce(add, [~q_m[i] for i in range(8)])),
46 n1q_m.eq(reduce(add, [q_m[i] for i in range(8)])),
47 q_m_r.eq(q_m)
48 ]
49
50 # stage 4 - final encoding
51 cnt = Signal((6, True))
52
53 s_c = self.c
54 s_de = self.de
55 for p in range(3):
56 new_c = Signal(2)
57 new_de = Signal()
58 self.sync += new_c.eq(s_c), new_de.eq(s_de)
59 s_c, s_de = new_c, new_de
60
61 self.sync += If(s_de,
62 If((cnt == 0) | (n1q_m == n0q_m),
63 self.out[9].eq(~q_m_r[8]),
64 self.out[8].eq(q_m_r[8]),
65 If(q_m_r[8],
66 self.out[:8].eq(q_m_r[:8]),
67 cnt.eq(cnt + n1q_m - n0q_m)
68 ).Else(
69 self.out[:8].eq(~q_m_r[:8]),
70 cnt.eq(cnt + n0q_m - n1q_m)
71 )
72 ).Else(
73 If((~cnt[5] & (n1q_m > n0q_m)) | (cnt[5] & (n0q_m > n1q_m)),
74 self.out[9].eq(1),
75 self.out[8].eq(q_m_r[8]),
76 self.out[:8].eq(~q_m_r[:8]),
77 cnt.eq(cnt + Cat(0, q_m_r[8]) + n0q_m - n1q_m)
78 ).Else(
79 self.out[9].eq(0),
80 self.out[8].eq(q_m_r[8]),
81 self.out[:8].eq(q_m_r[:8]),
82 cnt.eq(cnt - Cat(0, ~q_m_r[8]) + n1q_m - n0q_m)
83 )
84 )
85 ).Else(
86 self.out.eq(Array(control_tokens)[s_c]),
87 cnt.eq(0)
88 )
89
90
91 class _EncoderSerializer(Module):
92 def __init__(self, serdesstrobe, pad_p, pad_n):
93 self.submodules.encoder = RenameClockDomains(Encoder(), "pix")
94 self.d, self.c, self.de = self.encoder.d, self.encoder.c, self.encoder.de
95
96 ###
97
98 # 2X soft serialization
99 ed_2x = Signal(5)
100 self.sync.pix2x += ed_2x.eq(Mux(ClockSignal("pix"), self.encoder.out[:5], self.encoder.out[5:]))
101
102 # 5X hard serialization
103 cascade_di = Signal()
104 cascade_do = Signal()
105 cascade_ti = Signal()
106 cascade_to = Signal()
107 pad_se = Signal()
108 self.specials += [
109 Instance("OSERDES2",
110 p_DATA_WIDTH=5, p_DATA_RATE_OQ="SDR", p_DATA_RATE_OT="SDR",
111 p_SERDES_MODE="MASTER", p_OUTPUT_MODE="DIFFERENTIAL",
112
113 o_OQ=pad_se,
114 i_OCE=1, i_IOCE=serdesstrobe, i_RST=0,
115 i_CLK0=ClockSignal("pix10x"), i_CLK1=0, i_CLKDIV=ClockSignal("pix2x"),
116 i_D1=ed_2x[4], i_D2=0, i_D3=0, i_D4=0,
117 i_T1=0, i_T2=0, i_T3=0, i_T4=0,
118 i_TRAIN=0, i_TCE=1,
119 i_SHIFTIN1=1, i_SHIFTIN2=1,
120 i_SHIFTIN3=cascade_do, i_SHIFTIN4=cascade_to,
121 o_SHIFTOUT1=cascade_di, o_SHIFTOUT2=cascade_ti),
122 Instance("OSERDES2",
123 p_DATA_WIDTH=5, p_DATA_RATE_OQ="SDR", p_DATA_RATE_OT="SDR",
124 p_SERDES_MODE="SLAVE", p_OUTPUT_MODE="DIFFERENTIAL",
125
126 i_OCE=1, i_IOCE=serdesstrobe, i_RST=0,
127 i_CLK0=ClockSignal("pix10x"), i_CLK1=0, i_CLKDIV=ClockSignal("pix2x"),
128 i_D1=ed_2x[0], i_D2=ed_2x[1], i_D3=ed_2x[2], i_D4=ed_2x[3],
129 i_T1=0, i_T2=0, i_T3=0, i_T4=0,
130 i_TRAIN=0, i_TCE=1,
131 i_SHIFTIN1=cascade_di, i_SHIFTIN2=cascade_ti,
132 i_SHIFTIN3=1, i_SHIFTIN4=1,
133 o_SHIFTOUT3=cascade_do, o_SHIFTOUT4=cascade_to),
134 Instance("OBUFDS", i_I=pad_se, o_O=pad_p, o_OB=pad_n)
135 ]
136
137
138 class PHY(Module):
139 def __init__(self, serdesstrobe, pads):
140 self.hsync = Signal()
141 self.vsync = Signal()
142 self.de = Signal()
143 self.r = Signal(8)
144 self.g = Signal(8)
145 self.b = Signal(8)
146
147 ###
148
149 self.submodules.es0 = _EncoderSerializer(serdesstrobe, pads.data0_p, pads.data0_n)
150 self.submodules.es1 = _EncoderSerializer(serdesstrobe, pads.data1_p, pads.data1_n)
151 self.submodules.es2 = _EncoderSerializer(serdesstrobe, pads.data2_p, pads.data2_n)
152 self.comb += [
153 self.es0.d.eq(self.r),
154 self.es1.d.eq(self.g),
155 self.es2.d.eq(self.b),
156 self.es0.c.eq(Cat(self.hsync, self.vsync)),
157 self.es1.c.eq(0),
158 self.es2.c.eq(0),
159 self.es0.de.eq(self.de),
160 self.es1.de.eq(self.de),
161 self.es2.de.eq(self.de),
162 ]
163
164
165 class _EncoderTB(Module):
166 def __init__(self, inputs):
167 self.outs = []
168 self._iter_inputs = iter(inputs)
169 self._end_cycle = None
170 self.submodules.dut = Encoder()
171 self.comb += self.dut.de.eq(1)
172
173 def do_simulation(self, selfp):
174 if self._end_cycle is None:
175 try:
176 nv = next(self._iter_inputs)
177 except StopIteration:
178 self._end_cycle = selfp.simulator.cycle_counter + 4
179 else:
180 selfp.dut.d = nv
181 if selfp.simulator.cycle_counter == self._end_cycle:
182 raise StopSimulation
183 if selfp.simulator.cycle_counter > 4:
184 self.outs.append(selfp.dut.out)
185
186
187 def _bit(i, n):
188 return (i >> n) & 1
189
190
191 def _decode_tmds(b):
192 try:
193 c = control_tokens.index(b)
194 de = False
195 except ValueError:
196 c = 0
197 de = True
198 vsync = bool(c & 2)
199 hsync = bool(c & 1)
200
201 value = _bit(b, 0) ^ _bit(b, 9)
202 for i in range(1, 8):
203 value |= (_bit(b, i) ^ _bit(b, i-1) ^ (~_bit(b, 8) & 1)) << i
204
205 return de, hsync, vsync, value
206
207 if __name__ == "__main__":
208 from migen.sim.generic import run_simulation
209 from random import Random
210
211 rng = Random(788)
212 test_list = [rng.randrange(256) for i in range(500)]
213 tb = _EncoderTB(test_list)
214 run_simulation(tb)
215
216 check = [_decode_tmds(out)[3] for out in tb.outs]
217 assert(check == test_list)
218
219 nb0 = 0
220 nb1 = 0
221 for out in tb.outs:
222 for i in range(10):
223 if _bit(out, i):
224 nb1 += 1
225 else:
226 nb0 += 1
227 print("0/1: {}/{} ({:.2f})".format(nb0, nb1, nb0/nb1))