framebuffer: prepare for DVI out
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Tue, 17 Sep 2013 16:15:22 +0000 (18:15 +0200)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Tue, 17 Sep 2013 16:15:22 +0000 (18:15 +0200)
make.py
milkymist/framebuffer/__init__.py
milkymist/framebuffer/format.py [new file with mode: 0644]
milkymist/framebuffer/lib.py [deleted file]
milkymist/framebuffer/phy.py [new file with mode: 0644]
milkymist/mxcrg/__init__.py
software/videomixer/fb.c
top.py
verilog/mxcrg/mxcrg.v

diff --git a/make.py b/make.py
index c5cce7ebbd308a4e4f30eec1cfaf969b23292f8e..879b5b9f06045bb42ef214f6e0269463fa075aea 100755 (executable)
--- a/make.py
+++ b/make.py
@@ -21,11 +21,11 @@ PIN "mxcrg/bufg_x1.O" CLOCK_DEDICATED_ROUTE = FALSE;
 
        if hasattr(soc, "fb"):
                platform.add_platform_command("""
-NET "vga_clk" TNM_NET = "GRPvga_clk";
+NET "{vga_clk}" TNM_NET = "GRPvga_clk";
 NET "sys_clk" TNM_NET = "GRPsys_clk";
 TIMESPEC "TSise_sucks1" = FROM "GRPvga_clk" TO "GRPsys_clk" TIG;
 TIMESPEC "TSise_sucks2" = FROM "GRPsys_clk" TO "GRPvga_clk" TIG;
-""")
+""", vga_clk=soc.fb.driver.clocking.cd_pix.clk)
 
        for d in ["mxcrg", "minimac3"]:
                platform.add_source_dir(os.path.join("verilog", d))
index 7911b32a946ab0b3fe8e4bdf19a1a57ecf6d4751..eb64208f02ac1a2f870b243240ef9ef43266bd18 100644 (file)
@@ -4,52 +4,35 @@ from migen.flow.network import *
 from migen.bank.description import CSRStorage, AutoCSR
 from migen.actorlib import dma_lasmi, structuring, sim, spi
 
-from milkymist.framebuffer.lib import bpp, pixel_layout, dac_layout, FrameInitiator, VTG, FIFO
+from milkymist.framebuffer.format import bpp, pixel_layout, FrameInitiator, VTG
+from milkymist.framebuffer.phy import Driver
 
-class Framebuffer(Module):
-       def __init__(self, pads, lasmim, simulation=False):
+class Framebuffer(Module, AutoCSR):
+       def __init__(self, pads_vga, pads_dvi, lasmim, simulation=False):
                pack_factor = lasmim.dw//(2*bpp)
                packed_pixels = structuring.pack_layout(pixel_layout, pack_factor)
                
-               fi = FrameInitiator()
-               dma = spi.DMAReadController(dma_lasmi.Reader(lasmim), spi.MODE_EXTERNAL, length_reset=640*480*4)
+               self._enable = CSRStorage()
+               self.fi = FrameInitiator()
+               self.dma = spi.DMAReadController(dma_lasmi.Reader(lasmim), spi.MODE_EXTERNAL, length_reset=640*480*4)
+               self.driver = Driver(pads_vga, pads_dvi)
+
                cast = structuring.Cast(lasmim.dw, packed_pixels, reverse_to=True)
                unpack = structuring.Unpack(pack_factor, pixel_layout)
                vtg = VTG()
-               if simulation:
-                       fifo = sim.SimActor(sim_fifo_gen(), ("dac", Sink, dac_layout))
-               else:
-                       fifo = FIFO()
                
                g = DataFlowGraph()
-               g.add_connection(fi, vtg, sink_ep="timing")
-               g.add_connection(dma, cast)
+               g.add_connection(self.fi, vtg, sink_ep="timing")
+               g.add_connection(self.dma, cast)
                g.add_connection(cast, unpack)
                g.add_connection(unpack, vtg, sink_ep="pixels")
-               g.add_connection(vtg, fifo)
+               g.add_connection(vtg, self.driver)
                self.submodules += CompositeActor(g)
 
-               self._enable = CSRStorage()
                self.comb += [
-                       fi.trigger.eq(self._enable.storage),
-                       dma.generator.trigger.eq(self._enable.storage),
+                       self.fi.trigger.eq(self._enable.storage),
+                       self.dma.generator.trigger.eq(self._enable.storage),
                ]
-               self._fi = fi
-               self._dma = dma
-               
-               # Drive pads
-               if not simulation:
-                       self.comb += [
-                               pads.hsync_n.eq(fifo.vga_hsync_n),
-                               pads.vsync_n.eq(fifo.vga_vsync_n),
-                               pads.r.eq(fifo.vga_r),
-                               pads.g.eq(fifo.vga_g),
-                               pads.b.eq(fifo.vga_b)
-                       ]
-               self.comb += pads.psave_n.eq(1)
-
-       def get_csrs(self):
-               return [self._enable] + self._fi.get_csrs() + self._dma.get_csrs()
 
 class Blender(PipelinedActor, AutoCSR):
        def __init__(self, nimages, latency):
@@ -97,13 +80,14 @@ class Blender(PipelinedActor, AutoCSR):
                self.comb += self.source.payload.eq(outval)
 
 class MixFramebuffer(Module, AutoCSR):
-       def __init__(self, pads, *lasmims, blender_latency=5):
+       def __init__(self, pads_vga, pads_dvi, *lasmims, blender_latency=5):
                pack_factor = lasmims[0].dw//(2*bpp)
                packed_pixels = structuring.pack_layout(pixel_layout, pack_factor)
                
                self._enable = CSRStorage()
                self.fi = FrameInitiator()
                self.blender = Blender(len(lasmims), blender_latency)
+               self.driver = Driver(pads_vga, pads_dvi)
                self.comb += self.fi.trigger.eq(self._enable.storage)
 
                g = DataFlowGraph()
@@ -120,17 +104,7 @@ class MixFramebuffer(Module, AutoCSR):
                        setattr(self, "dma"+str(n), dma)
 
                vtg = VTG()
-               fifo = FIFO()
                g.add_connection(self.fi, vtg, sink_ep="timing")
                g.add_connection(self.blender, vtg, sink_ep="pixels")
-               g.add_connection(vtg, fifo)
+               g.add_connection(vtg, self.driver)
                self.submodules += CompositeActor(g)
-               
-               self.comb += [
-                       pads.hsync_n.eq(fifo.vga_hsync_n),
-                       pads.vsync_n.eq(fifo.vga_vsync_n),
-                       pads.r.eq(fifo.vga_r),
-                       pads.g.eq(fifo.vga_g),
-                       pads.b.eq(fifo.vga_b),
-                       pads.psave_n.eq(1)
-               ]
diff --git a/milkymist/framebuffer/format.py b/milkymist/framebuffer/format.py
new file mode 100644 (file)
index 0000000..96ac454
--- /dev/null
@@ -0,0 +1,111 @@
+from migen.fhdl.std import *
+from migen.flow.actor 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_phy = 8
+phy_layout_s = [
+       ("r", bpc_phy),
+       ("g", bpc_phy),
+       ("b", bpc_phy)
+]
+phy_layout = [
+       ("hsync", 1),
+       ("vsync", 1),
+       ("p0", phy_layout_s),
+       ("p1", phy_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.phy = Source(phy_layout)
+               self.busy = Signal()
+
+               hactive = Signal()
+               vactive = Signal()
+               active = Signal()
+               
+               generate_en = Signal()
+               hcounter = Signal(_hbits)
+               vcounter = Signal(_vbits)
+               
+               skip = bpc - bpc_phy
+               self.comb += [
+                       active.eq(hactive & vactive),
+                       If(active,
+                               [getattr(getattr(self.phy.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.phy.ack & active),
+                       self.phy.stb.eq(generate_en),
+                       self.busy.eq(generate_en)
+               ]
+               tp = self.timing.payload
+               self.sync += [
+                       self.timing.ack.eq(0),
+                       If(generate_en & self.phy.ack,
+                               hcounter.eq(hcounter + 1),
+                       
+                               If(hcounter == 0, hactive.eq(1)),
+                               If(hcounter == tp.hres, hactive.eq(0)),
+                               If(hcounter == tp.hsync_start, self.phy.payload.hsync.eq(1)),
+                               If(hcounter == tp.hsync_end, self.phy.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.phy.payload.vsync.eq(1)),
+                               If(vcounter == tp.vsync_end, self.phy.payload.vsync.eq(0))
+                       )
+               ]
diff --git a/milkymist/framebuffer/lib.py b/milkymist/framebuffer/lib.py
deleted file mode 100644 (file)
index 81bfa44..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-from migen.fhdl.std import *
-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 = RenameClockDomains(AsyncFIFO(data_width, 512),
-                       {"write": "sys", "read": "vga"})
-               self.submodules += fifo
-               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"]))
diff --git a/milkymist/framebuffer/phy.py b/milkymist/framebuffer/phy.py
new file mode 100644 (file)
index 0000000..c8a0699
--- /dev/null
@@ -0,0 +1,182 @@
+from migen.fhdl.std import *
+from migen.genlib.record import Record
+from migen.genlib.fifo import AsyncFIFO
+from migen.bank.description import *
+from migen.flow.actor import *
+
+from milkymist.framebuffer.format import bpc_phy, phy_layout
+
+class _FIFO(Module):
+       def __init__(self):
+               self.phy = Sink(phy_layout)
+               self.busy = Signal()
+               
+               self.pix_hsync = Signal()
+               self.pix_vsync = Signal()
+               self.pix_r = Signal(bpc_phy)
+               self.pix_g = Signal(bpc_phy)
+               self.pix_b = Signal(bpc_phy)
+       
+               ###
+
+               data_width = 2+2*3*bpc_phy
+               fifo = RenameClockDomains(AsyncFIFO(data_width, 512),
+                       {"write": "sys", "read": "pix"})
+               self.submodules += fifo
+               fifo_in = self.phy.payload
+               fifo_out = Record(phy_layout)
+               self.comb += [
+                       self.phy.ack.eq(fifo.writable),
+                       fifo.we.eq(self.phy.stb),
+                       fifo.din.eq(fifo_in.raw_bits()),
+                       fifo_out.raw_bits().eq(fifo.dout),
+                       self.busy.eq(0)
+               ]
+
+               pix_parity = Signal()
+               self.sync.pix += [
+                       pix_parity.eq(~pix_parity),
+                       self.pix_hsync.eq(fifo_out.hsync),
+                       self.pix_vsync.eq(fifo_out.vsync),
+                       If(pix_parity,
+                               self.pix_r.eq(fifo_out.p1.r),
+                               self.pix_g.eq(fifo_out.p1.g),
+                               self.pix_b.eq(fifo_out.p1.b)
+                       ).Else(
+                               self.pix_r.eq(fifo_out.p0.r),
+                               self.pix_g.eq(fifo_out.p0.g),
+                               self.pix_b.eq(fifo_out.p0.b)
+                       )
+               ]
+               self.comb += fifo.re.eq(pix_parity)
+
+# This assumes a 50MHz base clock
+class _Clocking(Module, AutoCSR):
+       def __init__(self, pads_vga, pads_dvi):
+               self._r_cmd_data = CSRStorage(10)
+               self._r_send_cmd_data = CSR()
+               self._r_send_go = CSR()
+               self._r_status = CSRStatus(4)
+
+               self.clock_domains.cd_pix = ClockDomain(reset_less=True)
+               if pads_dvi is not None:
+                       self.clock_domains.cd_pix2x = ClockDomain(reset_less=True)
+                       self.clock_domains.cd_pix10x = ClockDomain(reset_less=True)
+                       self.serdesstrobe = Signal()
+
+               ###
+
+               # Generate 1x pixel clock
+               clk_pix_unbuffered = Signal()
+               pix_progdata = Signal()
+               pix_progen = Signal()
+               pix_progdone = Signal()
+               pix_locked = Signal()
+               self.specials += Instance("DCM_CLKGEN",
+                       p_CLKFXDV_DIVIDE=2, p_CLKFX_DIVIDE=4, p_CLKFX_MD_MAX=3.0, p_CLKFX_MULTIPLY=2,
+                       p_CLKIN_PERIOD=20.0, p_SPREAD_SPECTRUM="NONE", p_STARTUP_WAIT="FALSE",
+               
+                       i_CLKIN=ClockSignal("base50"), o_CLKFX=clk_pix_unbuffered,
+                       i_PROGCLK=ClockSignal(), i_PROGDATA=pix_progdata, i_PROGEN=pix_progen,
+                       o_PROGDONE=pix_progdone, o_LOCKED=pix_locked,
+                       i_FREEZEDCM=0, i_RST=ResetSignal())
+
+               remaining_bits = Signal(max=11)
+               transmitting = Signal()
+               self.comb += transmitting.eq(remaining_bits != 0)
+               sr = Signal(10)
+               self.sync += [
+                       If(self._r_send_cmd_data.re,
+                               remaining_bits.eq(10),
+                               sr.eq(self._r_cmd_data.storage)
+                       ).Elif(transmitting,
+                               remaining_bits.eq(remaining_bits - 1),
+                               sr.eq(sr[1:])
+                       )
+               ]
+               self.comb += [
+                       pix_progdata.eq(transmitting & sr[0]),
+                       pix_progen.eq(transmitting | self._r_send_go.re)
+               ]
+
+               # enforce gap between commands
+               busy_counter = Signal(max=14)
+               busy = Signal()
+               self.comb += busy.eq(busy_counter != 0)
+               self.sync += If(self._r_send_cmd_data.re,
+                               busy_counter.eq(13)
+                       ).Elif(busy,
+                               busy_counter.eq(busy_counter - 1)
+                       )
+
+               mult_locked = Signal()
+               self.comb += self._r_status.status.eq(Cat(busy, pix_progdone, pix_locked, mult_locked))
+
+               # Clock multiplication and buffering
+               if pads_dvi is None:
+                       # Just buffer 1x pixel clock
+                       self.specials += Instance("BUFG", i_I=clk_pix_unbuffered, o_O=self.cd_pix.clk)
+                       self.comb += mult_locked.eq(pix_locked)
+               else:
+                       # Route unbuffered 1x pixel clock to PLL
+                       # Generate 1x, 2x and 10x IO pixel clocks
+                       clkfbout = Signal()
+                       pll_locked = Signal()
+                       pll_clk0 = Signal()
+                       pll_clk1 = Signal()
+                       pll_clk2 = Signal()
+                       locked_async = Signal()
+                       self.specials += [
+                               Instance("PLL_BASE",
+                                       p_CLKIN_PERIOD=26.7,
+                                       p_CLKFBOUT_MULT=20,
+                                       p_CLKOUT0_DIVIDE=2,  # pix10x
+                                       p_CLKOUT1_DIVIDE=10, # pix2x
+                                       p_CLKOUT2_DIVIDE=20, # pix
+                                       p_COMPENSATION="INTERNAL",
+                                       
+                                       i_CLKIN=clk_pix_unbuffered,
+                                       o_CLKOUT0=pll_clk0, o_CLKOUT1=pll_clk1, o_CLKOUT2=pll_clk2,
+                                       o_CLKFBOUT=clkfbout, i_CLKFBIN=clkfbout,
+                                       o_LOCKED=pll_locked, i_RST=~pix_locked),
+                               Instance("BUFPLL", p_DIVIDE=5,
+                                       i_PLLIN=pll_clk0, i_GCLK=ClockSignal("pix2x"), i_LOCKED=pll_locked,
+                                       o_IOCLK=self.cd_pix10x.clk, o_LOCK=locked_async, o_SERDESSTROBE=self.serdesstrobe),
+                               Instance("BUFG", i_I=pll_clk1, o_O=self.cd_pix2x.clk),
+                               Instance("BUFG", i_I=pll_clk2, o_O=self.cd_pix.clk),
+                               MultiReg(locked_async, mult_locked, "sys")
+                       ]
+
+               # Drive VGA/DVI clock pads
+               pix_clk_io = Signal()
+               self.specials += Instance("ODDR2",
+                       p_DDR_ALIGNMENT="NONE", p_INIT=0, p_SRTYPE="SYNC",
+                       o_Q=pix_clk_io,
+                       i_C0=ClockSignal("pix"),
+                       i_C1=~ClockSignal("pix"),
+                       i_CE=1, i_D0=1, i_D1=0,
+                       i_R=0, i_S=0)
+               if pads_vga is not None:
+                       self.comb += pads_vga.clk.eq(pix_clk_io)
+               if pads_dvi is not None:
+                       self.specials += Instance("OBUFDS", i_I=pix_clk_io,
+                               o_O=pads.clk_p, o_OB=pads.clk_n)
+
+class Driver(Module, AutoCSR):
+       def __init__(self, pads_vga, pads_dvi):
+               fifo = _FIFO()
+               self.submodules += fifo
+               self.phy = fifo.phy
+               self.busy = fifo.busy
+
+               self.submodules.clocking = _Clocking(pads_vga, pads_dvi)
+
+               if pads_vga is not None:
+                       self.comb += [
+                               pads_vga.hsync_n.eq(~fifo.pix_hsync),
+                               pads_vga.vsync_n.eq(~fifo.pix_vsync),
+                               pads_vga.r.eq(fifo.pix_r),
+                               pads_vga.g.eq(fifo.pix_g),
+                               pads_vga.b.eq(fifo.pix_b),
+                               pads_vga.psave_n.eq(1)
+                       ]
index c487f07ad27993b96d2bb29b7d9ee036bd11afda..ab110018f0a321d6d52d5c50e9f8becdb101d908 100644 (file)
@@ -1,9 +1,8 @@
 from fractions import Fraction
 
 from migen.fhdl.std import *
-from migen.bank.description import *
 
-class MXCRG(Module, AutoCSR):
+class MXCRG(Module):
        def __init__(self, pads, outfreq1x):
                self.clock_domains.cd_sys = ClockDomain()
                self.clock_domains.cd_sdram_half = ClockDomain()
@@ -11,27 +10,17 @@ class MXCRG(Module, AutoCSR):
                self.clock_domains.cd_sdram_full_rd = ClockDomain()
                self.clock_domains.cd_eth_rx = ClockDomain()
                self.clock_domains.cd_eth_tx = ClockDomain()
-               self.clock_domains.cd_vga = ClockDomain(reset_less=True)
+               self.clock_domains.cd_base50 = ClockDomain(reset_less=True)
 
                self.clk4x_wr_strb = Signal()
                self.clk4x_rd_strb = Signal()
 
-               self._r_cmd_data = CSRStorage(10)
-               self._r_send_cmd_data = CSR()
-               self._r_send_go = CSR()
-               self._r_status = CSRStatus(3)
-
                ###
                
                infreq = 50*1000000
                ratio = Fraction(outfreq1x)/Fraction(infreq)
                in_period = float(Fraction(1000000000)/Fraction(infreq))
 
-               vga_progdata = Signal()
-               vga_progen = Signal()
-               vga_progdone = Signal()
-               vga_locked = Signal()
-
                self.specials += Instance("mxcrg",
                        Instance.Parameter("in_period", in_period),
                        Instance.Parameter("f_mult", ratio.numerator),
@@ -49,48 +38,11 @@ class MXCRG(Module, AutoCSR):
                        Instance.Output("clk4x_rd", self.cd_sdram_full_rd.clk),
                        Instance.Output("eth_rx_clk", self.cd_eth_rx.clk),
                        Instance.Output("eth_tx_clk", self.cd_eth_tx.clk),
-                       Instance.Output("vga_clk", self.cd_vga.clk),
+                       Instance.Output("base50_clk", self.cd_base50.clk),
 
                        Instance.Output("clk4x_wr_strb", self.clk4x_wr_strb),
                        Instance.Output("clk4x_rd_strb", self.clk4x_rd_strb),
                        Instance.Output("norflash_rst_n", pads.norflash_rst_n),
                        Instance.Output("ddr_clk_pad_p", pads.ddr_clk_p),
                        Instance.Output("ddr_clk_pad_n", pads.ddr_clk_n),
-                       Instance.Output("eth_phy_clk_pad", pads.eth_phy_clk),
-                       Instance.Output("vga_clk_pad", pads.vga_clk),
-
-                       Instance.Input("vga_progclk", ClockSignal()),
-                       Instance.Input("vga_progdata", vga_progdata),
-                       Instance.Input("vga_progen", vga_progen),
-                       Instance.Output("vga_progdone", vga_progdone),
-                       Instance.Output("vga_locked", vga_locked))
-
-               remaining_bits = Signal(max=11)
-               transmitting = Signal()
-               self.comb += transmitting.eq(remaining_bits != 0)
-               sr = Signal(10)
-               self.sync += [
-                       If(self._r_send_cmd_data.re,
-                               remaining_bits.eq(10),
-                               sr.eq(self._r_cmd_data.storage)
-                       ).Elif(transmitting,
-                               remaining_bits.eq(remaining_bits - 1),
-                               sr.eq(sr[1:])
-                       )
-               ]
-               self.comb += [
-                       vga_progdata.eq(transmitting & sr[0]),
-                       vga_progen.eq(transmitting | self._r_send_go.re)
-               ]
-
-               # enforce gap between commands
-               busy_counter = Signal(max=14)
-               busy = Signal()
-               self.comb += busy.eq(busy_counter != 0)
-               self.sync += If(self._r_send_cmd_data.re,
-                               busy_counter.eq(13)
-                       ).Elif(busy,
-                               busy_counter.eq(busy_counter - 1)
-                       )
-
-               self.comb += self._r_status.status.eq(Cat(busy, vga_progdone, vga_locked))
+                       Instance.Output("eth_phy_clk_pad", pads.eth_phy_clk))
index 58b90bcae5cf1a73f90a97feca0c6908125f41b4..094cc1f8a690ba8f5e3547fe542f13545f2757dd 100644 (file)
@@ -13,9 +13,9 @@ static void fb_clkgen_write(int cmd, int data)
        int word;
 
        word = (data << 2) | cmd;
-       crg_cmd_data_write(word);
-       crg_send_cmd_data_write(1);
-       while(crg_status_read() & CLKGEN_STATUS_BUSY);
+       fb_driver_clocking_cmd_data_write(word);
+       fb_driver_clocking_send_cmd_data_write(1);
+       while(fb_driver_clocking_status_read() & CLKGEN_STATUS_BUSY);
 }
 
 void fb_set_mode(int mode)
@@ -86,12 +86,12 @@ void fb_set_mode(int mode)
 
        fb_clkgen_write(0x1, clock_d-1);
        fb_clkgen_write(0x3, clock_m-1);
-       crg_send_go_write(1);
+       fb_driver_clocking_send_go_write(1);
        printf("waiting for PROGDONE...");
-       while(!(crg_status_read() & CLKGEN_STATUS_PROGDONE));
+       while(!(fb_driver_clocking_status_read() & CLKGEN_STATUS_PROGDONE));
        printf("ok\n");
        printf("waiting for LOCKED...");
-       while(!(crg_status_read() & CLKGEN_STATUS_LOCKED));
+       while(!(fb_driver_clocking_status_read() & CLKGEN_STATUS_LOCKED));
        printf("ok\n");
 
        printf("VGA: mode set to %dx%d\n", fb_hres, fb_vres);
diff --git a/top.py b/top.py
index 03e0b19ab8bb376e19c2eea26ca84165d71ee2aa..60f6b33c80c65abfc71817d4d8c79612dcc6273d 100644 (file)
--- a/top.py
+++ b/top.py
@@ -51,7 +51,6 @@ class MXClockPads:
                except ConstraintError:
                        pass
                self.norflash_rst_n = platform.request("norflash_rst_n")
-               self.vga_clk = platform.request("vga_clock")
                ddram_clock = platform.request("ddram_clock")
                self.ddr_clk_p = ddram_clock.p
                self.ddr_clk_n = ddram_clock.n
@@ -162,7 +161,7 @@ class SoC(Module):
                self.submodules.timer0 = timer.Timer()
                if platform_name == "mixxeo":
                        self.submodules.leds = gpio.GPIOOut(platform.request("user_led"))
-                       self.submodules.fb = framebuffer.MixFramebuffer(platform.request("vga"), lasmim_fb0, lasmim_fb1)
+                       self.submodules.fb = framebuffer.MixFramebuffer(platform.request("vga_out"), None, lasmim_fb0, lasmim_fb1)
                        self.submodules.dvisampler0 = dvisampler.DVISampler(platform.request("dvi_in", 0), lasmim_dvi0)
                        self.submodules.dvisampler1 = dvisampler.DVISampler(platform.request("dvi_in", 1), lasmim_dvi1)
                if platform_name == "m1":
index a7dee56a774614ee2130a3d871b22dde37994a43..63052eef0a8e4d9c623611dafe4443586a06a6c9 100644 (file)
@@ -31,16 +31,8 @@ module mxcrg #(
        output eth_rx_clk,
        output eth_tx_clk,
        
-       /* VGA clock */
-       output vga_clk,         /* < buffered, to internal clock network */
-       output vga_clk_pad,     /* < forwarded through ODDR2, to I/O */
-
-       /* VGA clock control */
-       input vga_progclk,
-       input vga_progdata,
-       input vga_progen,
-       output vga_progdone,
-       output vga_locked
+       /* Base clock, buffered */
+       output base50_clk
 );
 
 /*
@@ -213,10 +205,10 @@ BUFG bufg_x1(
        .O(sys_clk)
 );
 
-wire clk50g;
+wire base50_clk;
 BUFG bufg_50(
        .I(pllout4),
-       .O(clk50g)
+       .O(base50_clk)
 );
 
 wire clk2x_off;
@@ -263,53 +255,11 @@ ODDR2 #(
  * Ethernet PHY 
  */
 
-always @(posedge clk50g)
+always @(posedge base50_clk)
        eth_phy_clk_pad <= ~eth_phy_clk_pad;
 
 /* Let the synthesizer insert the appropriate buffers */
 assign eth_rx_clk = eth_rx_clk_pad;
 assign eth_tx_clk = eth_tx_clk_pad;
-
-/*
- * VGA clock
- */
-
-DCM_CLKGEN #(
-       .CLKFXDV_DIVIDE(2),
-       .CLKFX_DIVIDE(4),
-       .CLKFX_MD_MAX(3.0),
-       .CLKFX_MULTIPLY(2),
-       .CLKIN_PERIOD(20.0),
-       .SPREAD_SPECTRUM("NONE"),
-       .STARTUP_WAIT("FALSE")
-) vga_clock_gen (
-       .CLKFX(vga_clk),
-       .CLKFX180(),
-       .CLKFXDV(),
-       .STATUS(),
-       .CLKIN(clk50g),
-       .FREEZEDCM(1'b0),
-       .PROGCLK(vga_progclk),
-       .PROGDATA(vga_progdata),
-       .PROGEN(vga_progen),
-       .PROGDONE(vga_progdone),
-       .LOCKED(vga_locked),
-       .RST(~pll_lckd | sys_rst)
-);
-
-ODDR2 #(
-       .DDR_ALIGNMENT("NONE"),
-       .INIT(1'b0),
-       .SRTYPE("SYNC")
-) vga_clock_forward (
-       .Q(vga_clk_pad),
-       .C0(vga_clk),
-       .C1(~vga_clk),
-       .CE(1'b1),
-       .D0(1'b1),
-       .D1(1'b0),
-       .R(1'b0),
-       .S(1'b0)
-);
  
 endmodule