1 from migen
.fhdl
.structure
import *
2 from migen
.fhdl
.specials
import Instance
3 from migen
.fhdl
.module
import Module
4 from migen
.genlib
.record
import Record
5 from migen
.flow
.actor
import *
6 from migen
.flow
.network
import *
7 from migen
.flow
.transactions
import *
8 from migen
.flow
import plumbing
9 from migen
.actorlib
import misc
, dma_asmi
, structuring
, sim
, spi
23 ("p0", _pixel_layout_s
),
24 ("p1", _pixel_layout_s
)
36 ("p0", _dac_layout_s
),
40 class _FrameInitiator(spi
.SingleGenerator
):
41 def __init__(self
, asmi_bits
, length_bits
, alignment_bits
):
43 ("hres", _hbits
, 640, 1),
44 ("hsync_start", _hbits
, 656, 1),
45 ("hsync_end", _hbits
, 752, 1),
46 ("hscan", _hbits
, 800, 1),
48 ("vres", _vbits
, 480),
49 ("vsync_start", _vbits
, 492),
50 ("vsync_end", _vbits
, 494),
51 ("vscan", _vbits
, 525),
53 ("base", asmi_bits
, 0, alignment_bits
),
54 ("length", length_bits
, 640*480*4, alignment_bits
)
56 spi
.SingleGenerator
.__init
__(self
, layout
, spi
.MODE_CONTINUOUS
)
58 class VTG(Module
, Actor
):
63 ("hsync_start", _hbits
),
64 ("hsync_end", _hbits
),
67 ("vsync_start", _vbits
),
68 ("vsync_end", _vbits
),
70 ("pixels", Sink
, _pixel_layout
),
71 ("dac", Source
, _dac_layout
)
78 generate_en
= Signal()
79 hcounter
= Signal(_hbits
)
80 vcounter
= Signal(_vbits
)
82 skip
= _bpc
- _bpc_dac
84 active
.eq(hactive
& vactive
),
86 [getattr(getattr(self
.token("dac"), p
), c
).eq(getattr(getattr(self
.token("pixels"), p
), c
)[skip
:])
87 for p
in ["p0", "p1"] for c
in ["r", "g", "b"]]
90 generate_en
.eq(self
.endpoints
["timing"].stb
& (~active | self
.endpoints
["pixels"].stb
)),
91 self
.endpoints
["pixels"].ack
.eq(self
.endpoints
["dac"].ack
& active
),
92 self
.endpoints
["dac"].stb
.eq(generate_en
)
94 tp
= self
.token("timing")
96 self
.endpoints
["timing"].ack
.eq(0),
97 If(generate_en
& self
.endpoints
["dac"].ack
,
98 hcounter
.eq(hcounter
+ 1),
100 If(hcounter
== 0, hactive
.eq(1)),
101 If(hcounter
== tp
.hres
, hactive
.eq(0)),
102 If(hcounter
== tp
.hsync_start
, self
.token("dac").hsync
.eq(1)),
103 If(hcounter
== tp
.hsync_end
, self
.token("dac").hsync
.eq(0)),
104 If(hcounter
== tp
.hscan
,
106 If(vcounter
== tp
.vscan
,
108 self
.endpoints
["timing"].ack
.eq(1)
110 vcounter
.eq(vcounter
+ 1)
114 If(vcounter
== 0, vactive
.eq(1)),
115 If(vcounter
== tp
.vres
, vactive
.eq(0)),
116 If(vcounter
== tp
.vsync_start
, self
.token("dac").vsync
.eq(1)),
117 If(vcounter
== tp
.vsync_end
, self
.token("dac").vsync
.eq(0))
121 class FIFO(Module
, Actor
):
123 Actor
.__init
__(self
, ("dac", Sink
, _dac_layout
))
125 self
.vga_hsync_n
= Signal()
126 self
.vga_vsync_n
= Signal()
127 self
.vga_r
= Signal(_bpc_dac
)
128 self
.vga_g
= Signal(_bpc_dac
)
129 self
.vga_b
= Signal(_bpc_dac
)
133 data_width
= 2+2*3*_bpc_dac
135 fifo_write_en
= Signal()
136 fifo_read_en
= Signal()
137 fifo_data_out
= Signal(data_width
)
138 fifo_data_in
= Signal(data_width
)
139 self
.specials
+= Instance("asfifo",
140 Instance
.Parameter("data_width", data_width
),
141 Instance
.Parameter("address_width", 8),
143 Instance
.Output("data_out", fifo_data_out
),
144 Instance
.Output("empty"),
145 Instance
.Input("read_en", fifo_read_en
),
146 Instance
.Input("clk_read", ClockSignal("vga")),
148 Instance
.Input("data_in", fifo_data_in
),
149 Instance
.Output("full", fifo_full
),
150 Instance
.Input("write_en", fifo_write_en
),
151 Instance
.Input("clk_write", ClockSignal()),
153 Instance
.Input("rst", 0))
154 fifo_in
= self
.token("dac")
155 fifo_out
= Record(_dac_layout
)
157 self
.endpoints
["dac"].ack
.eq(~fifo_full
),
158 fifo_write_en
.eq(self
.endpoints
["dac"].stb
),
159 fifo_data_in
.eq(Cat(*fifo_in
.flatten())),
160 Cat(*fifo_out
.flatten()).eq(fifo_data_out
),
164 pix_parity
= Signal()
166 pix_parity
.eq(~pix_parity
),
167 self
.vga_hsync_n
.eq(~fifo_out
.hsync
),
168 self
.vga_vsync_n
.eq(~fifo_out
.vsync
),
170 self
.vga_r
.eq(fifo_out
.p1
.r
),
171 self
.vga_g
.eq(fifo_out
.p1
.g
),
172 self
.vga_b
.eq(fifo_out
.p1
.b
)
174 self
.vga_r
.eq(fifo_out
.p0
.r
),
175 self
.vga_g
.eq(fifo_out
.p0
.g
),
176 self
.vga_b
.eq(fifo_out
.p0
.b
)
179 self
.comb
+= fifo_read_en
.eq(pix_parity
)
185 print("H/V:" + str(t
.value
["hsync"]) + str(t
.value
["vsync"])
186 + " " + str(t
.value
["r"]) + " " + str(t
.value
["g"]) + " " + str(t
.value
["b"]))
188 class Framebuffer(Module
):
189 def __init__(self
, pads
, asmiport
, simulation
=False):
190 asmi_bits
= asmiport
.hub
.aw
191 alignment_bits
= bits_for(asmiport
.hub
.dw
//8) - 1
192 length_bits
= _hbits
+ _vbits
+ 2 - alignment_bits
193 pack_factor
= asmiport
.hub
.dw
//(2*_bpp
)
194 packed_pixels
= structuring
.pack_layout(_pixel_layout
, pack_factor
)
196 fi
= _FrameInitiator(asmi_bits
, length_bits
, alignment_bits
)
197 adrloop
= misc
.IntSequence(length_bits
, asmi_bits
)
198 adrbuffer
= AbstractActor(plumbing
.Buffer
)
199 dma
= dma_asmi
.Reader(asmiport
)
200 datbuffer
= AbstractActor(plumbing
.Buffer
)
201 cast
= structuring
.Cast(asmiport
.hub
.dw
, packed_pixels
, reverse_to
=True)
202 unpack
= structuring
.Unpack(pack_factor
, _pixel_layout
)
205 fifo
= sim
.SimActor(sim_fifo_gen(), ("dac", Sink
, _dac_layout
))
210 g
.add_connection(fi
, adrloop
, source_subr
=["length", "base"])
211 g
.add_connection(adrloop
, adrbuffer
)
212 g
.add_connection(adrbuffer
, dma
)
213 g
.add_connection(dma
, datbuffer
)
214 g
.add_connection(datbuffer
, cast
)
215 g
.add_connection(cast
, unpack
)
216 g
.add_connection(unpack
, vtg
, sink_ep
="pixels")
217 g
.add_connection(fi
, vtg
, sink_ep
="timing", source_subr
=[
218 "hres", "hsync_start", "hsync_end", "hscan",
219 "vres", "vsync_start", "vsync_end", "vscan"])
220 g
.add_connection(vtg
, fifo
)
221 self
.submodules
._comp
_actor
= CompositeActor(g
, debugger
=False)
223 self
._registers
= fi
.get_registers() + self
._comp
_actor
.get_registers()
228 pads
.hsync_n
.eq(fifo
.vga_hsync_n
),
229 pads
.vsync_n
.eq(fifo
.vga_vsync_n
),
230 pads
.r
.eq(fifo
.vga_r
),
231 pads
.g
.eq(fifo
.vga_g
),
232 pads
.b
.eq(fifo
.vga_b
)
234 self
.comb
+= pads
.psave_n
.eq(1)
236 def get_registers(self
):
237 return self
._registers