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))
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):
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()
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)
- ]
--- /dev/null
+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))
+ )
+ ]
+++ /dev/null
-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"]))
--- /dev/null
+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)
+ ]
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()
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),
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))
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)
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);
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
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":
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
);
/*
.O(sys_clk)
);
-wire clk50g;
+wire base50_clk;
BUFG bufg_50(
.I(pllout4),
- .O(clk50g)
+ .O(base50_clk)
);
wire clk2x_off;
* 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