add DVI output

This commit is contained in:
Sebastien Bourdeauducq 2013-09-18 16:56:07 +02:00
parent 189803416b
commit ea0503173d
5 changed files with 102 additions and 20 deletions

View File

@ -17,6 +17,7 @@ INST "mxcrg/wr_bufpll" LOC = "BUFPLL_X0Y2";
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"):

View File

@ -83,6 +83,76 @@ class Encoder(Module):
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 = []

View File

@ -28,6 +28,7 @@ phy_layout_s = [
phy_layout = [
("hsync", 1),
("vsync", 1),
("de", 1),
("p0", phy_layout_s),
("p1", phy_layout_s)
]
@ -75,7 +76,8 @@ class VTG(Module):
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)),

View File

@ -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):
@ -14,39 +14,37 @@ class _FIFO(Module):
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)
@ -143,7 +141,7 @@ class _Clocking(Module, AutoCSR):
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")
]
@ -166,7 +164,7 @@ class _Clocking(Module, AutoCSR):
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):
@ -187,3 +185,13 @@ class Driver(Module, AutoCSR):
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
top.py
View File

@ -161,13 +161,14 @@ 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_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)