Navigation Menu

Skip to content

Commit

Permalink
add DVI output
Browse files Browse the repository at this point in the history
  • Loading branch information
Sebastien Bourdeauducq committed Sep 18, 2013
1 parent 1898034 commit ea05031
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 20 deletions.
1 change: 1 addition & 0 deletions make.py
Expand Up @@ -17,6 +17,7 @@ def build(platform_name, build_bitstream, build_header, *soc_args, **soc_kwargs)
INST "mxcrg/rd_bufpll" LOC = "BUFPLL_X0Y3";
PIN "mxcrg/bufg_x1.O" CLOCK_DEDICATED_ROUTE = FALSE;
PIN "pix2x_bufg.O" CLOCK_DEDICATED_ROUTE = FALSE;
""")

if hasattr(soc, "fb"):
Expand Down
70 changes: 70 additions & 0 deletions milkymist/framebuffer/dvi.py
Expand Up @@ -83,6 +83,76 @@ def __init__(self):
cnt.eq(0)
)

class _EncoderSerializer(Module):
def __init__(self, serdesstrobe, pad_p, pad_n):
self.submodules.encoder = RenameClockDomains(Encoder(), "pix")
self.d, self.c, self.de = self.encoder.d, self.encoder.c, self.encoder.de

###

# 2X soft serialization
ed_2x = Signal(5)
self.sync.pix2x += ed_2x.eq(Mux(ClockSignal("pix"), self.encoder.out[:5], self.encoder.out[5:]))

# 5X hard serialization
cascade_di = Signal()
cascade_do = Signal()
cascade_ti = Signal()
cascade_to = Signal()
pad_se = Signal()
self.specials += [
Instance("OSERDES2",
p_DATA_WIDTH=5, p_DATA_RATE_OQ="SDR", p_DATA_RATE_OT="SDR",
p_SERDES_MODE="MASTER", p_OUTPUT_MODE="DIFFERENTIAL",

o_OQ=pad_se,
i_OCE=1, i_IOCE=serdesstrobe, i_RST=0,
i_CLK0=ClockSignal("pix10x"), i_CLK1=0, i_CLKDIV=ClockSignal("pix2x"),
i_D1=ed_2x[4], i_D2=0, i_D3=0, i_D4=0,
i_T1=0, i_T2=0, i_T3=0, i_T4=0,
i_TRAIN=0, i_TCE=1,
i_SHIFTIN1=1, i_SHIFTIN2=1,
i_SHIFTIN3=cascade_do, i_SHIFTIN4=cascade_to,
o_SHIFTOUT1=cascade_di, o_SHIFTOUT2=cascade_ti),
Instance("OSERDES2",
p_DATA_WIDTH=5, p_DATA_RATE_OQ="SDR", p_DATA_RATE_OT="SDR",
p_SERDES_MODE="SLAVE", p_OUTPUT_MODE="DIFFERENTIAL",

i_OCE=1, i_IOCE=serdesstrobe, i_RST=0,
i_CLK0=ClockSignal("pix10x"), i_CLK1=0, i_CLKDIV=ClockSignal("pix2x"),
i_D1=ed_2x[0], i_D2=ed_2x[1], i_D3=ed_2x[2], i_D4=ed_2x[3],
i_T1=0, i_T2=0, i_T3=0, i_T4=0,
i_TRAIN=0, i_TCE=1,
i_SHIFTIN1=cascade_di, i_SHIFTIN2=cascade_ti,
i_SHIFTIN3=1, i_SHIFTIN4=1,
o_SHIFTOUT3=cascade_do, o_SHIFTOUT4=cascade_to),
Instance("OBUFDS", i_I=pad_se, o_O=pad_p, o_OB=pad_n)
]


class PHY(Module):
def __init__(self, serdesstrobe, pads):
self.hsync = Signal()
self.vsync = Signal()
self.de = Signal()
self.r = Signal(8)
self.g = Signal(8)
self.b = Signal(8)

###

self.submodules.es0 = _EncoderSerializer(serdesstrobe, pads.data0_p, pads.data0_n)
self.submodules.es1 = _EncoderSerializer(serdesstrobe, pads.data1_p, pads.data1_n)
self.submodules.es2 = _EncoderSerializer(serdesstrobe, pads.data2_p, pads.data2_n)
self.comb += [
self.es0.c.eq(Cat(self.hsync, self.vsync)),
self.es1.c.eq(0),
self.es2.c.eq(0),
self.es0.de.eq(self.de),
self.es1.de.eq(self.de),
self.es2.de.eq(self.de),
]

class _EncoderTB(Module):
def __init__(self, inputs):
self.outs = []
Expand Down
4 changes: 3 additions & 1 deletion milkymist/framebuffer/format.py
Expand Up @@ -28,6 +28,7 @@
phy_layout = [
("hsync", 1),
("vsync", 1),
("de", 1),
("p0", phy_layout_s),
("p1", phy_layout_s)
]
Expand Down Expand Up @@ -75,7 +76,8 @@ def __init__(self):
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"]]
for p in ["p0", "p1"] for c in ["r", "g", "b"]],
self.phy.payload.de.eq(1)
),

generate_en.eq(self.timing.stb & (~active | self.pixels.stb)),
Expand Down
42 changes: 25 additions & 17 deletions milkymist/framebuffer/phy.py
@@ -1,11 +1,11 @@
from migen.fhdl.std import *
from migen.genlib.record import Record
from migen.genlib.fifo import AsyncFIFO
from migen.genlib.cdc import MultiReg
from migen.bank.description import *
from migen.flow.actor import *

from milkymist.framebuffer.format import bpc_phy, phy_layout
from milkymist.framebuffer import dvi

class _FIFO(Module):
def __init__(self):
Expand All @@ -14,39 +14,37 @@ def __init__(self):

self.pix_hsync = Signal()
self.pix_vsync = Signal()
self.pix_de = 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),
fifo = RenameClockDomains(AsyncFIFO(phy_layout, 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),
fifo.din.eq(self.phy.payload),
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),
self.pix_hsync.eq(fifo.dout.hsync),
self.pix_vsync.eq(fifo.dout.vsync),
self.pix_de.eq(fifo.dout.de),
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)
self.pix_r.eq(fifo.dout.p1.r),
self.pix_g.eq(fifo.dout.p1.g),
self.pix_b.eq(fifo.dout.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.pix_r.eq(fifo.dout.p0.r),
self.pix_g.eq(fifo.dout.p0.g),
self.pix_b.eq(fifo.dout.p0.b)
)
]
self.comb += fifo.re.eq(pix_parity)
Expand Down Expand Up @@ -143,7 +141,7 @@ def __init__(self, pads_vga, pads_dvi):
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", name="pix2x_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")
]
Expand All @@ -166,7 +164,7 @@ def __init__(self, pads_vga, pads_dvi):
i_C1=~ClockSignal("pix"),
i_CE=1, i_D0=1, i_D1=0,
i_R=0, i_S=0)
self.specials += Instance("OBUFTDS", i_I=dvi_clk_se,
self.specials += Instance("OBUFDS", i_I=dvi_clk_se,
o_O=pads_dvi.clk_p, o_OB=pads_dvi.clk_n)

class Driver(Module, AutoCSR):
Expand All @@ -187,3 +185,13 @@ def __init__(self, pads_vga, pads_dvi):
pads_vga.b.eq(fifo.pix_b),
pads_vga.psave_n.eq(1)
]
if pads_dvi is not None:
self.submodules.dvi_phy = dvi.PHY(self.clocking.serdesstrobe, pads_dvi)
self.comb += [
self.dvi_phy.hsync.eq(fifo.pix_hsync),
self.dvi_phy.vsync.eq(fifo.pix_vsync),
self.dvi_phy.de.eq(fifo.pix_de),
self.dvi_phy.r.eq(fifo.pix_r),
self.dvi_phy.g.eq(fifo.pix_g),
self.dvi_phy.b.eq(fifo.pix_b)
]
5 changes: 3 additions & 2 deletions top.py
Expand Up @@ -161,13 +161,14 @@ def __init__(self, platform, platform_name, with_memtest):
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_out"), None, lasmim_fb0, lasmim_fb1)
self.submodules.fb = framebuffer.MixFramebuffer(platform.request("vga_out"), platform.request("dvi_out"),
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":
self.submodules.buttons = gpio.GPIOIn(Cat(platform.request("user_btn", 0), platform.request("user_btn", 2)))
self.submodules.leds = gpio.GPIOOut(Cat(*[platform.request("user_led", i) for i in range(2)]))
self.submodules.fb = framebuffer.Framebuffer(platform.request("vga"), lasmim_fb)
self.submodules.fb = framebuffer.Framebuffer(platform.request("vga"), None, lasmim_fb)
if with_memtest:
self.submodules.memtest_w = memtest.MemtestWriter(lasmim_mtw)
self.submodules.memtest_r = memtest.MemtestReader(lasmim_mtr)
Expand Down

0 comments on commit ea05031

Please sign in to comment.