From 3a02524cc7cfec4290e6445973e7444d57fedc22 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sun, 17 Jun 2012 13:41:26 +0200 Subject: [PATCH] VGA framebuffer connections --- common/csrbase.h | 1 + constraints.py | 10 ++++++- milkymist/framebuffer/__init__.py | 19 +++++++++++++ milkymist/m1crg/__init__.py | 4 ++- top.py | 18 +++++++++--- verilog/m1crg/m1crg.v | 46 ++++++++++++++++++++++++++++++- 6 files changed, 91 insertions(+), 7 deletions(-) create mode 100644 milkymist/framebuffer/__init__.py diff --git a/common/csrbase.h b/common/csrbase.h index cc44fb3c9..06f2f5e4a 100644 --- a/common/csrbase.h +++ b/common/csrbase.h @@ -6,5 +6,6 @@ #define ID_BASE 0xe0001000 #define TIMER0_BASE 0xe0001800 #define MINIMAC_BASE 0xe0002000 +#define FB_BASE 0xe0002800 #endif /* __CSRBASE_H */ diff --git a/constraints.py b/constraints.py index ee78a1d0e..75fafc148 100644 --- a/constraints.py +++ b/constraints.py @@ -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 index 000000000..62c03cb48 --- /dev/null +++ b/milkymist/framebuffer/__init__.py @@ -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() diff --git a/milkymist/m1crg/__init__.py b/milkymist/m1crg/__init__.py index 73e81617d..bb44dcf10 100644 --- a/milkymist/m1crg/__init__.py +++ b/milkymist/m1crg/__init__.py @@ -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 0c146287e..e6ebbed62 100644 --- 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", diff --git a/verilog/m1crg/m1crg.v b/verilog/m1crg/m1crg.v index ba5519b68..77a7fda8c 100644 --- a/verilog/m1crg/m1crg.v +++ b/verilog/m1crg/m1crg.v @@ -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