1 from migen
.fhdl
.structure
import *
2 from migen
.flow
.actor
import *
3 from migen
.flow
.network
import *
4 from migen
.flow
import plumbing
5 from migen
.actorlib
import ala
, misc
, dma_asmi
, structuring
6 from migen
.bank
.description
import *
7 from migen
.bank
import csrgen
18 ("pad", BV(_bpp
-3*_bpc
))
30 class _FrameInitiator(Actor
):
31 def __init__(self
, asmi_bits
, length_bits
, alignment_bits
):
32 self
._alignment
_bits
= alignment_bits
34 self
._enable
= RegisterField("enable")
36 self
._hres
= RegisterField("hres", _hbits
, reset
=640)
37 self
._hsync
_start
= RegisterField("hsync_start", _hbits
, reset
=656)
38 self
._hsync
_end
= RegisterField("hsync_end", _hbits
, reset
=752)
39 self
._hscan
= RegisterField("hscan", _hbits
, reset
=799)
41 self
._vres
= RegisterField("vres", _vbits
, reset
=480)
42 self
._vsync
_start
= RegisterField("vsync_start", _vbits
, reset
=492)
43 self
._vsync
_end
= RegisterField("vsync_end", _vbits
, reset
=494)
44 self
._vscan
= RegisterField("vscan", _vbits
, reset
=524)
46 self
._base
= RegisterField("base", asmi_bits
+ self
._alignment
_bits
)
47 self
._length
= RegisterField("length", length_bits
+ self
._alignment
_bits
, reset
=640*480*4)
51 ("hsync_start", BV(_hbits
)),
52 ("hsync_end", BV(_hbits
)),
53 ("hscan", BV(_hbits
)),
55 ("vsync_start", BV(_vbits
)),
56 ("vsync_end", BV(_vbits
)),
57 ("vscan", BV(_vbits
)),
58 ("base", BV(asmi_bits
)),
59 ("length", BV(length_bits
))
61 super().__init
__(("frame", Source
, layout
))
63 def get_registers(self
):
65 self
._hres
, self
._hsync
_start
, self
._hsync
_end
, self
._hscan
,
66 self
._vres
, self
._vsync
_start
, self
._vsync
_end
, self
._vscan
,
67 self
._base
, self
._length
]
69 def get_fragment(self
):
70 # TODO: make address updates atomic
71 token
= self
.token("frame")
74 self
.endpoints
["frame"].stb
.eq(self
._enable
.field
.r
),
75 token
.hres
.eq(self
._hres
.field
.r
),
76 token
.hsync_start
.eq(self
._hsync
_start
.field
.r
),
77 token
.hsync_end
.eq(self
._hsync
_end
.field
.r
),
78 token
.hscan
.eq(self
._hscan
.field
.r
),
79 token
.vres
.eq(self
._vres
.field
.r
),
80 token
.vsync_start
.eq(self
._vsync
_start
.field
.r
),
81 token
.vsync_end
.eq(self
._vsync
_end
.field
.r
),
82 token
.vscan
.eq(self
._vscan
.field
.r
),
83 token
.base
.eq(self
._base
.field
.r
[self
._alignment
_bits
:]),
84 token
.length
.eq(self
._length
.field
.r
[self
._alignment
_bits
:])
93 ("hsync_start", BV(_hbits
)),
94 ("hsync_end", BV(_hbits
)),
95 ("hscan", BV(_hbits
)),
97 ("vsync_start", BV(_vbits
)),
98 ("vsync_end", BV(_vbits
)),
99 ("vscan", BV(_vbits
))]),
100 ("pixels", Sink
, _pixel_layout
),
101 ("dac", Source
, _dac_layout
)
104 def get_fragment(self
):
109 generate_en
= Signal()
110 hcounter
= Signal(BV(_hbits
))
111 vcounter
= Signal(BV(_vbits
))
116 active
.eq(hactive
& vactive
),
118 self
.token("dac").r
.eq(self
.token("pixels").r
[:_bpc_dac
]),
119 self
.token("dac").g
.eq(self
.token("pixels").g
[:_bpc_dac
]),
120 self
.token("dac").b
.eq(self
.token("pixels").b
[:_bpc_dac
])
123 generate_en
.eq(self
.endpoints
["timing"].stb
& self
.endpoints
["dac"].ack \
124 & (~active | self
.endpoints
["pixels"].stb
)),
125 self
.endpoints
["pixels"].ack
.eq(self
.endpoints
["dac"].ack
& active
),
126 self
.endpoints
["dac"].stb
.eq(generate_en
)
128 tp
= self
.token("timing")
130 self
.endpoints
["timing"].ack
.eq(0),
132 hcounter
.eq(hcounter
+ 1),
134 If(hcounter
== 0, hactive
.eq(1)),
135 If(hcounter
== tp
.hres
, hactive
.eq(0)),
136 If(hcounter
== tp
.hsync_start
, hsync
.eq(1)),
137 If(hcounter
== tp
.hsync_end
, hsync
.eq(0)),
138 If(hcounter
== tp
.hscan
,
140 If(vcounter
== tp
.vscan
,
143 vcounter
.eq(vcounter
+ 1)
147 If(vcounter
== 0, vactive
.eq(1)),
148 If(vcounter
== tp
.vres
, vactive
.eq(0)),
149 If(vcounter
== tp
.vsync_start
, vsync
.eq(1)),
150 If(vcounter
== tp
.vsync_end
,
152 self
.endpoints
["timing"].ack
.eq(1)
157 return Fragment(comb
, sync
)
161 super().__init
__(("dac", Sink
, _dac_layout
))
163 self
.vga_clk
= Signal()
164 self
.vga_hsync_n
= Signal()
165 self
.vga_vsync_n
= Signal()
166 self
.vga_r
= Signal(BV(_bpc_dac
))
167 self
.vga_g
= Signal(BV(_bpc_dac
))
168 self
.vga_b
= Signal(BV(_bpc_dac
))
170 def get_fragment(self
):
171 data_width
= 2+3*_bpc_dac
172 asfifo
= Instance("asfifo",
174 ("data_out", BV(data_width
)),
180 ("clk_read", self
.vga_clk
),
182 ("data_in", BV(data_width
)),
188 ("data_width", data_width
),
192 t
= self
.token("dac")
194 Cat(self
.vga_hsync_n
, self
.vga_vsync_n
, self
.vga_r
, self
.vga_g
, self
.vga_b
).eq(asfifo
.outs
["data_out"]),
195 asfifo
.ins
["read_en"].eq(1),
197 self
.endpoints
["dac"].ack
.eq(~asfifo
.outs
["full"]),
198 asfifo
.ins
["write_en"].eq(self
.endpoints
["dac"].stb
),
199 asfifo
.ins
["data_in"].eq(Cat(~t
.hsync
, ~t
.vsync
, t
.r
, t
.g
, t
.b
)),
202 asfifo
.ins
["rst"].eq(0)
203 ], instances
=[asfifo
])
206 def __init__(self
, address
, asmiport
):
207 asmi_bits
= asmiport
.hub
.aw
208 alignment_bits
= bits_for(asmiport
.hub
.dw
//8)
209 length_bits
= _hbits
+ _vbits
+ 2 - alignment_bits
210 pack_factor
= asmiport
.hub
.dw
//_bpp
211 packed_pixels
= structuring
.pack_layout(_pixel_layout
, pack_factor
)
213 fi
= ActorNode(_FrameInitiator(asmi_bits
, length_bits
, alignment_bits
))
214 adrloop
= ActorNode(misc
.IntSequence(length_bits
))
215 adrbase
= ActorNode(ala
.Add(BV(asmi_bits
)))
216 adrbuffer
= ActorNode(plumbing
.Buffer
)
217 dma
= ActorNode(dma_asmi
.SequentialReader(asmiport
))
218 cast
= ActorNode(structuring
.Cast(asmiport
.hub
.dw
, packed_pixels
))
219 unpack
= ActorNode(structuring
.Unpack(pack_factor
, _pixel_layout
))
220 vtg
= ActorNode(VTG())
221 fifo
= ActorNode(FIFO())
224 g
.add_connection(fi
, adrloop
, source_subr
=["length"])
225 g
.add_connection(adrloop
, adrbase
, sink_subr
=["a"])
226 g
.add_connection(fi
, adrbase
, source_subr
=["base"], sink_subr
=["b"])
227 g
.add_connection(adrbase
, adrbuffer
)
228 g
.add_connection(adrbuffer
, dma
)
229 g
.add_connection(dma
, cast
)
230 g
.add_connection(cast
, unpack
)
231 g
.add_connection(unpack
, vtg
, sink_ep
="pixels")
232 g
.add_connection(fi
, vtg
, sink_ep
="timing", source_subr
=[
233 "hres", "hsync_start", "hsync_end", "hscan",
234 "vres", "vsync_start", "vsync_end", "vscan"])
235 g
.add_connection(vtg
, fifo
)
236 self
._comp
_actor
= CompositeActor(g
)
238 self
.bank
= csrgen
.Bank(fi
.actor
.get_registers(), address
=address
)
241 self
.vga_clk
= fifo
.actor
.vga_clk
244 self
.vga_psave_n
= Signal()
245 self
.vga_hsync_n
= fifo
.actor
.vga_hsync_n
246 self
.vga_vsync_n
= fifo
.actor
.vga_vsync_n
247 self
.vga_sync_n
= Signal()
248 self
.vga_blank_n
= Signal()
249 self
.vga_r
= fifo
.actor
.vga_r
250 self
.vga_g
= fifo
.actor
.vga_g
251 self
.vga_b
= fifo
.actor
.vga_b
253 def get_fragment(self
):
255 self
.vga_sync_n
.eq(0),
256 self
.vga_psave_n
.eq(1),
257 self
.vga_blank_n
.eq(1)
259 return self
.bank
.get_fragment() \
260 + self
._comp
_actor
.get_fragment() \