f2e6b2e5666634263fcdb76981a55144031621bd
[litex.git] / misoclib / video / dvisampler / edid.py
1 from migen.fhdl.std import *
2 from migen.fhdl.specials import Tristate
3 from migen.genlib.cdc import MultiReg
4 from migen.genlib.fsm import FSM, NextState
5 from migen.genlib.misc import chooser
6 from migen.bank.description import CSRStorage, CSRStatus, AutoCSR
7
8 _default_edid = [
9 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x3D, 0x17, 0x32, 0x12, 0x2A, 0x6A, 0xBF, 0x00,
10 0x05, 0x17, 0x01, 0x03, 0x80, 0x28, 0x1E, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
11 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
12 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xB2, 0x0C, 0x00, 0x40, 0x41, 0x00, 0x26, 0x30, 0x18, 0x88,
13 0x36, 0x00, 0x28, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x4D, 0x31, 0x20,
14 0x44, 0x56, 0x49, 0x20, 0x6D, 0x69, 0x78, 0x65, 0x72, 0x0A, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
15 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
16 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34,
17 ]
18
19 class EDID(Module, AutoCSR):
20 def __init__(self, pads, default=_default_edid):
21 self._r_hpd_notif = CSRStatus()
22 self._r_hpd_en = CSRStorage()
23 self.specials.mem = Memory(8, 128, init=default)
24
25 ###
26
27 # HPD
28 if hasattr(pads, "hpd_notif"):
29 self.specials += MultiReg(pads.hpd_notif, self._r_hpd_notif.status)
30 else:
31 self.comb += self._r_hpd_notif.status.eq(1)
32 if hasattr(pads, "hpd_en"):
33 self.comb += pads.hpd_en.eq(self._r_hpd_en.storage)
34
35 # EDID
36 scl_raw = Signal()
37 sda_i = Signal()
38 sda_drv = Signal()
39 _sda_drv_reg = Signal()
40 _sda_i_async = Signal()
41 self.sync += _sda_drv_reg.eq(sda_drv)
42 self.specials += [
43 MultiReg(pads.scl, scl_raw),
44 Tristate(pads.sda, 0, _sda_drv_reg, _sda_i_async),
45 MultiReg(_sda_i_async, sda_i)
46 ]
47
48 scl_i = Signal()
49 samp_count = Signal(6)
50 samp_carry = Signal()
51 self.sync += [
52 Cat(samp_count, samp_carry).eq(samp_count + 1),
53 If(samp_carry, scl_i.eq(scl_raw))
54 ]
55
56 scl_r = Signal()
57 sda_r = Signal()
58 scl_rising = Signal()
59 sda_rising = Signal()
60 sda_falling = Signal()
61 self.sync += [
62 scl_r.eq(scl_i),
63 sda_r.eq(sda_i)
64 ]
65 self.comb += [
66 scl_rising.eq(scl_i & ~scl_r),
67 sda_rising.eq(sda_i & ~sda_r),
68 sda_falling.eq(~sda_i & sda_r)
69 ]
70
71 start = Signal()
72 self.comb += start.eq(scl_i & sda_falling)
73
74 din = Signal(8)
75 counter = Signal(max=9)
76 self.sync += [
77 If(start, counter.eq(0)),
78 If(scl_rising,
79 If(counter == 8,
80 counter.eq(0)
81 ).Else(
82 counter.eq(counter + 1),
83 din.eq(Cat(sda_i, din[:7]))
84 )
85 )
86 ]
87
88 is_read = Signal()
89 update_is_read = Signal()
90 self.sync += If(update_is_read, is_read.eq(din[0]))
91
92 offset_counter = Signal(max=128)
93 oc_load = Signal()
94 oc_inc = Signal()
95 self.sync += [
96 If(oc_load,
97 offset_counter.eq(din)
98 ).Elif(oc_inc,
99 offset_counter.eq(offset_counter + 1)
100 )
101 ]
102 rdport = self.mem.get_port()
103 self.specials += rdport
104 self.comb += rdport.adr.eq(offset_counter)
105 data_bit = Signal()
106
107 zero_drv = Signal()
108 data_drv = Signal()
109 self.comb += If(zero_drv, sda_drv.eq(1)).Elif(data_drv, sda_drv.eq(~data_bit))
110
111 data_drv_en = Signal()
112 data_drv_stop = Signal()
113 self.sync += If(data_drv_en, data_drv.eq(1)).Elif(data_drv_stop, data_drv.eq(0))
114 self.sync += If(data_drv_en, chooser(rdport.dat_r, counter, data_bit, 8, reverse=True))
115
116 fsm = FSM()
117 self.submodules += fsm
118
119 fsm.act("WAIT_START")
120 fsm.act("RCV_ADDRESS",
121 If(counter == 8,
122 If(din[1:] == 0x50,
123 update_is_read.eq(1),
124 NextState("ACK_ADDRESS0")
125 ).Else(
126 NextState("WAIT_START")
127 )
128 )
129 )
130 fsm.act("ACK_ADDRESS0",
131 If(~scl_i, NextState("ACK_ADDRESS1"))
132 )
133 fsm.act("ACK_ADDRESS1",
134 zero_drv.eq(1),
135 If(scl_i, NextState("ACK_ADDRESS2"))
136 )
137 fsm.act("ACK_ADDRESS2",
138 zero_drv.eq(1),
139 If(~scl_i,
140 If(is_read,
141 NextState("READ")
142 ).Else(
143 NextState("RCV_OFFSET")
144 )
145 )
146 )
147
148 fsm.act("RCV_OFFSET",
149 If(counter == 8,
150 oc_load.eq(1),
151 NextState("ACK_OFFSET0")
152 )
153 )
154 fsm.act("ACK_OFFSET0",
155 If(~scl_i, NextState("ACK_OFFSET1"))
156 )
157 fsm.act("ACK_OFFSET1",
158 zero_drv.eq(1),
159 If(scl_i, NextState("ACK_OFFSET2"))
160 )
161 fsm.act("ACK_OFFSET2",
162 zero_drv.eq(1),
163 If(~scl_i, NextState("RCV_ADDRESS"))
164 )
165
166 fsm.act("READ",
167 If(~scl_i,
168 If(counter == 8,
169 data_drv_stop.eq(1),
170 NextState("ACK_READ")
171 ).Else(
172 data_drv_en.eq(1)
173 )
174 )
175 )
176 fsm.act("ACK_READ",
177 If(scl_rising,
178 oc_inc.eq(1),
179 If(sda_i,
180 NextState("WAIT_START")
181 ).Else(
182 NextState("READ")
183 )
184 )
185 )
186
187 for state in fsm.actions.keys():
188 fsm.act(state, If(start, NextState("RCV_ADDRESS")))
189 fsm.act(state, If(~self._r_hpd_en.storage, NextState("WAIT_START")))