210ec5ce19bd91225fd6a0985b40ab1dea709c01
[litex.git] / litex / soc / misoc / cores / framebuffer / format.py
1 from migen import *
2 from migen.flow.actor import *
3 from migen.bank.description import CSRStorage
4 from migen.genlib.record import Record
5 from migen.genlib.fsm import FSM, NextState
6 from migen.actorlib import spi
7
8 _hbits = 12
9 _vbits = 12
10
11 bpp = 32
12 bpc = 10
13 pixel_layout_s = [
14 ("pad", bpp-3*bpc),
15 ("r", bpc),
16 ("g", bpc),
17 ("b", bpc)
18 ]
19
20
21 def pixel_layout(pack_factor):
22 return [("p"+str(i), pixel_layout_s) for i in range(pack_factor)]
23
24 bpc_phy = 8
25 phy_layout_s = [
26 ("r", bpc_phy),
27 ("g", bpc_phy),
28 ("b", bpc_phy)
29 ]
30
31
32 def phy_layout(pack_factor):
33 r = [("hsync", 1), ("vsync", 1), ("de", 1)]
34 for i in range(pack_factor):
35 r.append(("p"+str(i), phy_layout_s))
36 return r
37
38
39 class FrameInitiator(spi.SingleGenerator):
40 def __init__(self, bus_aw, pack_factor, ndmas=1):
41 h_alignment_bits = log2_int(pack_factor)
42 hbits_dyn = _hbits - h_alignment_bits
43 bus_alignment_bits = h_alignment_bits + log2_int(bpp//8)
44 layout = [
45 ("hres", hbits_dyn, 640, h_alignment_bits),
46 ("hsync_start", hbits_dyn, 656, h_alignment_bits),
47 ("hsync_end", hbits_dyn, 752, h_alignment_bits),
48 ("hscan", hbits_dyn, 800, h_alignment_bits),
49
50 ("vres", _vbits, 480),
51 ("vsync_start", _vbits, 492),
52 ("vsync_end", _vbits, 494),
53 ("vscan", _vbits, 525),
54
55 ("length", bus_aw + bus_alignment_bits, 640*480*bpp//8, bus_alignment_bits)
56 ]
57 layout += [("base"+str(i), bus_aw + bus_alignment_bits, 0, bus_alignment_bits)
58 for i in range(ndmas)]
59 spi.SingleGenerator.__init__(self, layout, spi.MODE_CONTINUOUS)
60
61 timing_subr = ["hres", "hsync_start", "hsync_end", "hscan",
62 "vres", "vsync_start", "vsync_end", "vscan"]
63
64 def dma_subr(self, i=0):
65 return ["length", "base"+str(i)]
66
67
68 class VTG(Module):
69 def __init__(self, pack_factor):
70 hbits_dyn = _hbits - log2_int(pack_factor)
71 timing_layout = [
72 ("hres", hbits_dyn),
73 ("hsync_start", hbits_dyn),
74 ("hsync_end", hbits_dyn),
75 ("hscan", hbits_dyn),
76 ("vres", _vbits),
77 ("vsync_start", _vbits),
78 ("vsync_end", _vbits),
79 ("vscan", _vbits)]
80 self.timing = Sink(timing_layout)
81 self.pixels = Sink(pixel_layout(pack_factor))
82 self.phy = Source(phy_layout(pack_factor))
83 self.busy = Signal()
84
85 ###
86
87 hactive = Signal()
88 vactive = Signal()
89 active = Signal()
90
91 hcounter = Signal(hbits_dyn)
92 vcounter = Signal(_vbits)
93
94 skip = bpc - bpc_phy
95 self.comb += [
96 active.eq(hactive & vactive),
97 If(active,
98 [getattr(getattr(self.phy.payload, p), c).eq(getattr(getattr(self.pixels.payload, p), c)[skip:])
99 for p in ["p"+str(i) for i in range(pack_factor)] for c in ["r", "g", "b"]],
100 self.phy.de.eq(1)
101 ),
102 self.pixels.ack.eq(self.phy.ack & active)
103 ]
104
105 load_timing = Signal()
106 tr = Record(timing_layout)
107 self.sync += If(load_timing, tr.eq(self.timing.payload))
108
109 generate_en = Signal()
110 generate_frame_done = Signal()
111 self.sync += [
112 generate_frame_done.eq(0),
113 If(generate_en,
114 hcounter.eq(hcounter + 1),
115
116 If(hcounter == 0, hactive.eq(1)),
117 If(hcounter == tr.hres, hactive.eq(0)),
118 If(hcounter == tr.hsync_start, self.phy.hsync.eq(1)),
119 If(hcounter == tr.hsync_end, self.phy.hsync.eq(0)),
120 If(hcounter == tr.hscan,
121 hcounter.eq(0),
122 If(vcounter == tr.vscan,
123 vcounter.eq(0),
124 generate_frame_done.eq(1)
125 ).Else(
126 vcounter.eq(vcounter + 1)
127 )
128 ),
129
130 If(vcounter == 0, vactive.eq(1)),
131 If(vcounter == tr.vres, vactive.eq(0)),
132 If(vcounter == tr.vsync_start, self.phy.vsync.eq(1)),
133 If(vcounter == tr.vsync_end, self.phy.vsync.eq(0))
134 )
135 ]
136
137 self.submodules.fsm = FSM()
138 self.fsm.act("GET_TIMING",
139 self.timing.ack.eq(1),
140 load_timing.eq(1),
141 If(self.timing.stb, NextState("GENERATE"))
142 )
143 self.fsm.act("GENERATE",
144 self.busy.eq(1),
145 If(~active | self.pixels.stb,
146 self.phy.stb.eq(1),
147 If(self.phy.ack, generate_en.eq(1))
148 ),
149 If(generate_frame_done, NextState("GET_TIMING"))
150 )