VGA framebuffer connections
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Sun, 17 Jun 2012 11:41:26 +0000 (13:41 +0200)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Sun, 17 Jun 2012 11:41:26 +0000 (13:41 +0200)
common/csrbase.h
constraints.py
milkymist/framebuffer/__init__.py [new file with mode: 0644]
milkymist/m1crg/__init__.py
top.py
verilog/m1crg/m1crg.v

index cc44fb3c9180b4236172a8742d6dacb6be863687..06f2f5e4acc636124f256c530f399d331a76410c 100644 (file)
@@ -6,5 +6,6 @@
 #define ID_BASE                0xe0001000
 #define TIMER0_BASE    0xe0001800
 #define MINIMAC_BASE   0xe0002000
+#define FB_BASE                0xe0002800
 
 #endif /* __CSRBASE_H */
index ee78a1d0ee6ac6ebbdad60513aa77c1ceebe6b49..75fafc14808e9a34a959886c47516aac862f89ec 100644 (file)
@@ -1,5 +1,5 @@
 class Constraints:
-       def __init__(self, crg0, norflash0, uart0, ddrphy0, minimac0):
+       def __init__(self, crg0, norflash0, uart0, ddrphy0, minimac0, fb0):
                self.constraints = []
                def add(signal, pin, vec=-1, iostandard="LVCMOS33", extra=""):
                        self.constraints.append((signal, vec, pin, iostandard, extra))
@@ -16,6 +16,7 @@ class Constraints:
                add(crg0.flash_rst_n, "P22", extra="SLEW = FAST | DRIVE = 8")
                add(crg0.trigger_reset, "AA4")
                add(crg0.phy_clk, "M20")
+               add(crg0.vga_clk_pad, "A11")
                
                add_vec(norflash0.adr, ["L22", "L20", "K22", "K21", "J19", "H20", "F22",
                        "F21", "K17", "J17", "E22", "E20", "H18", "H19", "F20",
@@ -61,6 +62,13 @@ class Constraints:
                add(minimac0.phy_col, "W20")
                add(minimac0.phy_crs, "W22")
                
+               add_vec(fb0.vga_r, ["C6", "B6", "A6", "C7", "A7", "B8", "A8", "D9"])
+               add_vec(fb0.vga_g, ["C8", "C9", "A9", "D7", "D8", "D10", "C10", "B10"])
+               add_vec(fb0.vga_b, ["D11", "C12", "B12", "A12", "C13", "A13", "D14", "C14"])
+               add(fb0.vga_hsync_n, "A14")
+               add(fb0.vga_vsync_n, "C15")
+               add(fb0.vga_psave_n, "B14")
+               
                self._phy_rx_clk = minimac0.phy_rx_clk
                self._phy_tx_clk = minimac0.phy_tx_clk
 
diff --git a/milkymist/framebuffer/__init__.py b/milkymist/framebuffer/__init__.py
new file mode 100644 (file)
index 0000000..62c03cb
--- /dev/null
@@ -0,0 +1,19 @@
+from migen.fhdl.structure import *
+
+class Framebuffer:
+       def __init__(self, csr_address, asmiport):
+               # VGA clock input
+               self.vga_clk = Signal()
+               
+               # pads
+               self.vga_psave_n = Signal()
+               self.vga_hsync_n = Signal()
+               self.vga_vsync_n = Signal()
+               self.vga_sync_n = Signal()
+               self.vga_blank_n = Signal()
+               self.vga_r = Signal(BV(8))
+               self.vga_g = Signal(BV(8))
+               self.vga_b = Signal(BV(8))
+
+       def get_fragment(self):
+               return Fragment()
index 73e81617d35cbb33d2179d3024a4ef0575087ce3..bb44dcf10f12e90f1bc90614c110e0cd3899089e 100644 (file)
@@ -19,7 +19,9 @@ class M1CRG:
                        "clk4x_wr_strb",
                        "clk4x_rd",
                        "clk4x_rd_strb",
-                       "phy_clk"
+                       "phy_clk",
+                       "vga_clk",
+                       "vga_clk_pad"
                ]:
                        s = Signal(name=name)
                        setattr(self, name, s)
diff --git a/top.py b/top.py
index 0c146287e5b5add7ebbc4ccc8324449d07dcb269..e6ebbed624a268591a0138878b9994b501150ff6 100644 (file)
--- a/top.py
+++ b/top.py
@@ -5,7 +5,8 @@ from migen.fhdl.structure import *
 from migen.fhdl import verilog, autofragment
 from migen.bus import wishbone, wishbone2asmi, csr, wishbone2csr, dfi
 
-from milkymist import m1crg, lm32, norflash, uart, sram, s6ddrphy, dfii, asmicon, identifier, timer, minimac3
+from milkymist import m1crg, lm32, norflash, uart, sram, s6ddrphy, dfii, asmicon, \
+       identifier, timer, minimac3, framebuffer
 from cmacros import get_macros
 from constraints import Constraints
 
@@ -75,6 +76,7 @@ def get():
        #
        asmicon0 = asmicon.ASMIcon(sdram_phy, sdram_geom, sdram_timing)
        asmiport_wb = asmicon0.hub.get_port()
+       asmiport_fb = asmicon0.hub.get_port()
        asmicon0.finalize()
        
        #
@@ -122,12 +124,14 @@ def get():
        uart0 = uart.UART(csr_offset("UART"), clk_freq, baud=115200)
        identifier0 = identifier.Identifier(csr_offset("ID"), 0x4D31, version, int(clk_freq))
        timer0 = timer.Timer(csr_offset("TIMER0"))
+       fb0 = framebuffer.Framebuffer(csr_offset("FB"), asmiport_fb)
        csrcon0 = csr.Interconnect(wishbone2csr0.csr, [
                uart0.bank.interface,
                dfii0.bank.interface,
                identifier0.bank.interface,
                timer0.bank.interface,
-               minimac0.bank.interface
+               minimac0.bank.interface,
+               #fb0.bank.interface
        ])
        
        #
@@ -144,8 +148,14 @@ def get():
        #
        crg0 = m1crg.M1CRG(50*MHz, clk_freq)
        
-       frag = autofragment.from_local() + interrupts + ddrphy_clocking(crg0, ddrphy0)
-       cst = Constraints(crg0, norflash0, uart0, ddrphy0, minimac0)
+       vga_clocking = Fragment([
+               fb0.vga_clk.eq(crg0.vga_clk)
+       ])
+       frag = autofragment.from_local() \
+               + interrupts \
+               + ddrphy_clocking(crg0, ddrphy0) \
+               + vga_clocking
+       cst = Constraints(crg0, norflash0, uart0, ddrphy0, minimac0, fb0)
        src_verilog, vns = verilog.convert(frag,
                cst.get_ios(),
                name="soc",
index ba5519b68e85c60aeb90c0f1dd459f03c32ac0bf..77a7fda8c182ef43cb1dd3dd151f2d987aa866a7 100644 (file)
@@ -23,7 +23,11 @@ module m1crg #(
        output clk4x_rd_strb,
        
        /* Ethernet PHY clock */
-       output reg phy_clk
+       output reg phy_clk,     /* < unbuffered, to I/O */
+       
+       /* VGA clock */
+       output vga_clk,         /* < buffered, to internal clock network */
+       output vga_clk_pad      /* < forwarded through ODDR2, to I/O */
 );
 
 /*
@@ -190,5 +194,45 @@ BUFG bufg_x1(
 /* Ethernet PHY */
 always @(posedge pllout4)
        phy_clk <= ~phy_clk;
+
+/* VGA clock */
+// TODO: hook up the reprogramming interface
+DCM_CLKGEN #(
+       .CLKFXDV_DIVIDE(2),
+       .CLKFX_DIVIDE(4),
+       .CLKFX_MD_MAX(2.0),
+       .CLKFX_MULTIPLY(2),
+       .CLKIN_PERIOD(0.0),
+       .SPREAD_SPECTRUM("NONE"),
+       .STARTUP_WAIT("FALSE")
+) vga_clock_gen (
+       .CLKFX(vga_clk),
+       .CLKFX180(),
+       .CLKFXDV(),
+       .LOCKED(),
+       .PROGDONE(),
+       .STATUS(),
+       .CLKIN(pllout4),
+       .FREEZEDCM(1'b0),
+       .PROGCLK(1'b0),
+       .PROGDATA(),
+       .PROGEN(1'b0),
+       .RST(1'b0)
+);
+
+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