From 3ab83fb693e4e5595e518b3e3ba4f79797bcad45 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Thu, 9 May 2013 19:23:22 +0200 Subject: [PATCH] framebuffer: reorganize in preparation for mixer --- milkymist/framebuffer/__init__.py | 172 ++---------------------------- milkymist/framebuffer/lib.py | 167 +++++++++++++++++++++++++++++ 2 files changed, 173 insertions(+), 166 deletions(-) create mode 100644 milkymist/framebuffer/lib.py diff --git a/milkymist/framebuffer/__init__.py b/milkymist/framebuffer/__init__.py index 1a93cad12..830e731d4 100644 --- a/milkymist/framebuffer/__init__.py +++ b/milkymist/framebuffer/__init__.py @@ -1,183 +1,23 @@ from migen.fhdl.structure import * -from migen.fhdl.specials import Instance from migen.fhdl.module import Module -from migen.genlib.record import Record -from migen.genlib.fifo import AsyncFIFO -from migen.flow.actor import * from migen.flow.network import * -from migen.flow.transactions import * from migen.bank.description import CSRStorage from migen.actorlib import dma_asmi, structuring, sim, spi -_hbits = 11 -_vbits = 12 - -_bpp = 32 -_bpc = 10 -_pixel_layout_s = [ - ("pad", _bpp-3*_bpc), - ("r", _bpc), - ("g", _bpc), - ("b", _bpc) -] -_pixel_layout = [ - ("p0", _pixel_layout_s), - ("p1", _pixel_layout_s) -] - -_bpc_dac = 8 -_dac_layout_s = [ - ("r", _bpc_dac), - ("g", _bpc_dac), - ("b", _bpc_dac) -] -_dac_layout = [ - ("hsync", 1), - ("vsync", 1), - ("p0", _dac_layout_s), - ("p1", _dac_layout_s) -] - -class _FrameInitiator(spi.SingleGenerator): - def __init__(self): - layout = [ - ("hres", _hbits, 640, 1), - ("hsync_start", _hbits, 656, 1), - ("hsync_end", _hbits, 752, 1), - ("hscan", _hbits, 800, 1), - - ("vres", _vbits, 480), - ("vsync_start", _vbits, 492), - ("vsync_end", _vbits, 494), - ("vscan", _vbits, 525) - ] - spi.SingleGenerator.__init__(self, layout, spi.MODE_EXTERNAL) - -class VTG(Module): - def __init__(self): - self.timing = Sink([ - ("hres", _hbits), - ("hsync_start", _hbits), - ("hsync_end", _hbits), - ("hscan", _hbits), - ("vres", _vbits), - ("vsync_start", _vbits), - ("vsync_end", _vbits), - ("vscan", _vbits)]) - self.pixels = Sink(_pixel_layout) - self.dac = Source(_dac_layout) - self.busy = Signal() - - hactive = Signal() - vactive = Signal() - active = Signal() - - generate_en = Signal() - hcounter = Signal(_hbits) - vcounter = Signal(_vbits) - - skip = _bpc - _bpc_dac - self.comb += [ - active.eq(hactive & vactive), - If(active, - [getattr(getattr(self.dac.payload, p), c).eq(getattr(getattr(self.pixels.payload, p), c)[skip:]) - for p in ["p0", "p1"] for c in ["r", "g", "b"]] - ), - - generate_en.eq(self.timing.stb & (~active | self.pixels.stb)), - self.pixels.ack.eq(self.dac.ack & active), - self.dac.stb.eq(generate_en), - self.busy.eq(generate_en) - ] - tp = self.timing.payload - self.sync += [ - self.timing.ack.eq(0), - If(generate_en & self.dac.ack, - hcounter.eq(hcounter + 1), - - If(hcounter == 0, hactive.eq(1)), - If(hcounter == tp.hres, hactive.eq(0)), - If(hcounter == tp.hsync_start, self.dac.payload.hsync.eq(1)), - If(hcounter == tp.hsync_end, self.dac.payload.hsync.eq(0)), - If(hcounter == tp.hscan, - hcounter.eq(0), - If(vcounter == tp.vscan, - vcounter.eq(0), - self.timing.ack.eq(1) - ).Else( - vcounter.eq(vcounter + 1) - ) - ), - - If(vcounter == 0, vactive.eq(1)), - If(vcounter == tp.vres, vactive.eq(0)), - If(vcounter == tp.vsync_start, self.dac.payload.vsync.eq(1)), - If(vcounter == tp.vsync_end, self.dac.payload.vsync.eq(0)) - ) - ] - -class FIFO(Module): - def __init__(self): - self.dac = Sink(_dac_layout) - self.busy = Signal() - - self.vga_hsync_n = Signal() - self.vga_vsync_n = Signal() - self.vga_r = Signal(_bpc_dac) - self.vga_g = Signal(_bpc_dac) - self.vga_b = Signal(_bpc_dac) - - ### - - data_width = 2+2*3*_bpc_dac - fifo = AsyncFIFO(data_width, 256) - self.add_submodule(fifo, {"write": "sys", "read": "vga"}) - fifo_in = self.dac.payload - fifo_out = Record(_dac_layout) - self.comb += [ - self.dac.ack.eq(fifo.writable), - fifo.we.eq(self.dac.stb), - fifo.din.eq(fifo_in.raw_bits()), - fifo_out.raw_bits().eq(fifo.dout), - self.busy.eq(0) - ] - - pix_parity = Signal() - self.sync.vga += [ - pix_parity.eq(~pix_parity), - self.vga_hsync_n.eq(~fifo_out.hsync), - self.vga_vsync_n.eq(~fifo_out.vsync), - If(pix_parity, - self.vga_r.eq(fifo_out.p1.r), - self.vga_g.eq(fifo_out.p1.g), - self.vga_b.eq(fifo_out.p1.b) - ).Else( - self.vga_r.eq(fifo_out.p0.r), - self.vga_g.eq(fifo_out.p0.g), - self.vga_b.eq(fifo_out.p0.b) - ) - ] - self.comb += fifo.re.eq(pix_parity) - -def sim_fifo_gen(): - while True: - t = Token("dac") - yield t - print("H/V:" + str(t.value["hsync"]) + str(t.value["vsync"]) - + " " + str(t.value["r"]) + " " + str(t.value["g"]) + " " + str(t.value["b"])) +from milkymist.framebuffer.lib import bpp, pixel_layout, dac_layout, FrameInitiator, VTG, FIFO class Framebuffer(Module): def __init__(self, pads, asmiport, simulation=False): - pack_factor = asmiport.hub.dw//(2*_bpp) - packed_pixels = structuring.pack_layout(_pixel_layout, pack_factor) + pack_factor = asmiport.hub.dw//(2*bpp) + packed_pixels = structuring.pack_layout(pixel_layout, pack_factor) - fi = _FrameInitiator() + fi = FrameInitiator() dma = spi.DMAReadController(dma_asmi.Reader(asmiport), spi.MODE_EXTERNAL, length_reset=640*480*4) cast = structuring.Cast(asmiport.hub.dw, packed_pixels, reverse_to=True) - unpack = structuring.Unpack(pack_factor, _pixel_layout) + unpack = structuring.Unpack(pack_factor, pixel_layout) vtg = VTG() if simulation: - fifo = sim.SimActor(sim_fifo_gen(), ("dac", Sink, _dac_layout)) + fifo = sim.SimActor(sim_fifo_gen(), ("dac", Sink, dac_layout)) else: fifo = FIFO() diff --git a/milkymist/framebuffer/lib.py b/milkymist/framebuffer/lib.py new file mode 100644 index 000000000..e85ed9df1 --- /dev/null +++ b/milkymist/framebuffer/lib.py @@ -0,0 +1,167 @@ +from migen.fhdl.structure import * +from migen.fhdl.module import Module +from migen.genlib.record import Record +from migen.genlib.fifo import AsyncFIFO +from migen.flow.actor import * +from migen.flow.network import * +from migen.flow.transactions import * +from migen.bank.description import CSRStorage +from migen.actorlib import spi + +_hbits = 11 +_vbits = 12 + +bpp = 32 +bpc = 10 +pixel_layout_s = [ + ("pad", bpp-3*bpc), + ("r", bpc), + ("g", bpc), + ("b", bpc) +] +pixel_layout = [ + ("p0", pixel_layout_s), + ("p1", pixel_layout_s) +] + +bpc_dac = 8 +dac_layout_s = [ + ("r", bpc_dac), + ("g", bpc_dac), + ("b", bpc_dac) +] +dac_layout = [ + ("hsync", 1), + ("vsync", 1), + ("p0", dac_layout_s), + ("p1", dac_layout_s) +] + +class FrameInitiator(spi.SingleGenerator): + def __init__(self): + layout = [ + ("hres", _hbits, 640, 1), + ("hsync_start", _hbits, 656, 1), + ("hsync_end", _hbits, 752, 1), + ("hscan", _hbits, 800, 1), + + ("vres", _vbits, 480), + ("vsync_start", _vbits, 492), + ("vsync_end", _vbits, 494), + ("vscan", _vbits, 525) + ] + spi.SingleGenerator.__init__(self, layout, spi.MODE_EXTERNAL) + +class VTG(Module): + def __init__(self): + self.timing = Sink([ + ("hres", _hbits), + ("hsync_start", _hbits), + ("hsync_end", _hbits), + ("hscan", _hbits), + ("vres", _vbits), + ("vsync_start", _vbits), + ("vsync_end", _vbits), + ("vscan", _vbits)]) + self.pixels = Sink(pixel_layout) + self.dac = Source(dac_layout) + self.busy = Signal() + + hactive = Signal() + vactive = Signal() + active = Signal() + + generate_en = Signal() + hcounter = Signal(_hbits) + vcounter = Signal(_vbits) + + skip = bpc - bpc_dac + self.comb += [ + active.eq(hactive & vactive), + If(active, + [getattr(getattr(self.dac.payload, p), c).eq(getattr(getattr(self.pixels.payload, p), c)[skip:]) + for p in ["p0", "p1"] for c in ["r", "g", "b"]] + ), + + generate_en.eq(self.timing.stb & (~active | self.pixels.stb)), + self.pixels.ack.eq(self.dac.ack & active), + self.dac.stb.eq(generate_en), + self.busy.eq(generate_en) + ] + tp = self.timing.payload + self.sync += [ + self.timing.ack.eq(0), + If(generate_en & self.dac.ack, + hcounter.eq(hcounter + 1), + + If(hcounter == 0, hactive.eq(1)), + If(hcounter == tp.hres, hactive.eq(0)), + If(hcounter == tp.hsync_start, self.dac.payload.hsync.eq(1)), + If(hcounter == tp.hsync_end, self.dac.payload.hsync.eq(0)), + If(hcounter == tp.hscan, + hcounter.eq(0), + If(vcounter == tp.vscan, + vcounter.eq(0), + self.timing.ack.eq(1) + ).Else( + vcounter.eq(vcounter + 1) + ) + ), + + If(vcounter == 0, vactive.eq(1)), + If(vcounter == tp.vres, vactive.eq(0)), + If(vcounter == tp.vsync_start, self.dac.payload.vsync.eq(1)), + If(vcounter == tp.vsync_end, self.dac.payload.vsync.eq(0)) + ) + ] + +class FIFO(Module): + def __init__(self): + self.dac = Sink(dac_layout) + self.busy = Signal() + + self.vga_hsync_n = Signal() + self.vga_vsync_n = Signal() + self.vga_r = Signal(bpc_dac) + self.vga_g = Signal(bpc_dac) + self.vga_b = Signal(bpc_dac) + + ### + + data_width = 2+2*3*bpc_dac + fifo = AsyncFIFO(data_width, 256) + self.add_submodule(fifo, {"write": "sys", "read": "vga"}) + fifo_in = self.dac.payload + fifo_out = Record(dac_layout) + self.comb += [ + self.dac.ack.eq(fifo.writable), + fifo.we.eq(self.dac.stb), + fifo.din.eq(fifo_in.raw_bits()), + fifo_out.raw_bits().eq(fifo.dout), + self.busy.eq(0) + ] + + pix_parity = Signal() + self.sync.vga += [ + pix_parity.eq(~pix_parity), + self.vga_hsync_n.eq(~fifo_out.hsync), + self.vga_vsync_n.eq(~fifo_out.vsync), + If(pix_parity, + # FIXME: p0/p1 should be the other way around. Clarify this. + self.vga_r.eq(fifo_out.p0.r), + self.vga_g.eq(fifo_out.p0.g), + self.vga_b.eq(fifo_out.p0.b) + ).Else( + self.vga_r.eq(fifo_out.p1.r), + self.vga_g.eq(fifo_out.p1.g), + self.vga_b.eq(fifo_out.p1.b) + ) + ] + self.comb += fifo.re.eq(pix_parity) + +def sim_fifo_gen(): + while True: + t = Token("dac") + yield t + print("H/V:" + str(t.value["hsync"]) + str(t.value["vsync"]) + + " " + str(t.value["r"]) + " " + str(t.value["g"]) + " " + str(t.value["b"]))