1 from migen
.fhdl
.std
import *
2 from migen
.genlib
.cdc
import MultiReg
, PulseSynchronizer
3 from migen
.genlib
.fifo
import AsyncFIFO
4 from migen
.genlib
.record
import Record
5 from migen
.bank
.description
import *
6 from migen
.flow
.actor
import *
8 from misoclib
.dvisampler
.common
import channel_layout
10 class SyncPolarity(Module
):
12 self
.valid_i
= Signal()
13 self
.data_in0
= Record(channel_layout
)
14 self
.data_in1
= Record(channel_layout
)
15 self
.data_in2
= Record(channel_layout
)
17 self
.valid_o
= Signal()
30 c_polarity
= Signal(2)
35 self
.hsync
.eq(c_out
[0]),
36 self
.vsync
.eq(c_out
[1])
40 self
.valid_o
.eq(self
.valid_i
),
41 self
.r
.eq(self
.data_in2
.d
),
42 self
.g
.eq(self
.data_in1
.d
),
43 self
.b
.eq(self
.data_in0
.d
),
50 c_out
.eq(c ^ c_polarity
)
54 class ResolutionDetection(Module
, AutoCSR
):
55 def __init__(self
, nbits
=11):
56 self
.valid_i
= Signal()
60 self
._hres
= CSRStatus(nbits
)
61 self
._vres
= CSRStatus(nbits
)
65 # Detect DE transitions
68 self
.sync
.pix
+= de_r
.eq(self
.de
)
69 self
.comb
+= pn_de
.eq(~self
.de
& de_r
)
72 hcounter
= Signal(nbits
)
73 self
.sync
.pix
+= If(self
.valid_i
& self
.de
,
74 hcounter
.eq(hcounter
+ 1)
79 hcounter_st
= Signal(nbits
)
80 self
.sync
.pix
+= If(self
.valid_i
,
81 If(pn_de
, hcounter_st
.eq(hcounter
))
85 self
.specials
+= MultiReg(hcounter_st
, self
._hres
.status
)
90 self
.sync
.pix
+= vsync_r
.eq(self
.vsync
),
91 self
.comb
+= p_vsync
.eq(self
.vsync
& ~vsync_r
)
93 vcounter
= Signal(nbits
)
94 self
.sync
.pix
+= If(self
.valid_i
& p_vsync
,
97 vcounter
.eq(vcounter
+ 1)
100 vcounter_st
= Signal(nbits
)
101 self
.sync
.pix
+= If(self
.valid_i
,
102 If(p_vsync
, vcounter_st
.eq(vcounter
))
106 self
.specials
+= MultiReg(vcounter_st
, self
._vres
.status
)
108 class FrameExtraction(Module
, AutoCSR
):
109 def __init__(self
, word_width
):
110 # in pix clock domain
111 self
.valid_i
= Signal()
112 self
.vsync
= Signal()
118 # in sys clock domain
119 word_layout
= [("sof", 1), ("pixels", word_width
)]
120 self
.frame
= Source(word_layout
)
123 self
._r
_overflow
= CSR()
127 # start of frame detection
130 self
.comb
+= new_frame
.eq(self
.vsync
& ~vsync_r
)
131 self
.sync
.pix
+= vsync_r
.eq(self
.vsync
)
133 # pack pixels into words
134 cur_word
= Signal(word_width
)
135 cur_word_valid
= Signal()
136 encoded_pixel
= Signal(24)
137 self
.comb
+= encoded_pixel
.eq(Cat(self
.b
, self
.g
, self
.r
))
138 pack_factor
= word_width
//24
139 assert(pack_factor
& (pack_factor
- 1) == 0) # only support powers of 2
140 pack_counter
= Signal(max=pack_factor
)
142 cur_word_valid
.eq(0),
144 cur_word_valid
.eq(pack_counter
== (pack_factor
- 1)),
146 ).Elif(self
.valid_i
& self
.de
,
147 [If(pack_counter
== (pack_factor
-i
-1),
148 cur_word
[24*i
:24*(i
+1)].eq(encoded_pixel
)) for i
in range(pack_factor
)],
149 cur_word_valid
.eq(pack_counter
== (pack_factor
- 1)),
150 pack_counter
.eq(pack_counter
+ 1)
155 fifo
= RenameClockDomains(AsyncFIFO(word_layout
, 512),
156 {"write": "pix", "read": "sys"})
157 self
.submodules
+= fifo
159 fifo
.din
.pixels
.eq(cur_word
),
160 fifo
.we
.eq(cur_word_valid
)
165 ).Elif(cur_word_valid
,
169 self
.frame
.stb
.eq(fifo
.readable
),
170 self
.frame
.payload
.eq(fifo
.dout
),
171 fifo
.re
.eq(self
.frame
.ack
),
176 pix_overflow
= Signal()
177 pix_overflow_reset
= Signal()
179 If(fifo
.we
& ~fifo
.writable
,
181 ).Elif(pix_overflow_reset
,
186 sys_overflow
= Signal()
187 self
.specials
+= MultiReg(pix_overflow
, sys_overflow
)
188 self
.submodules
.overflow_reset
= PulseSynchronizer("sys", "pix")
189 self
.submodules
.overflow_reset_ack
= PulseSynchronizer("pix", "sys")
191 pix_overflow_reset
.eq(self
.overflow_reset
.o
),
192 self
.overflow_reset_ack
.i
.eq(pix_overflow_reset
)
195 overflow_mask
= Signal()
197 self
._r
_overflow
.w
.eq(sys_overflow
& ~overflow_mask
),
198 self
.overflow_reset
.i
.eq(self
._r
_overflow
.re
)
201 If(self
._r
_overflow
.re
,
203 ).Elif(self
.overflow_reset_ack
.o
,