add DVI output
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Wed, 18 Sep 2013 14:56:07 +0000 (16:56 +0200)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Wed, 18 Sep 2013 14:56:07 +0000 (16:56 +0200)
make.py
milkymist/framebuffer/dvi.py
milkymist/framebuffer/format.py
milkymist/framebuffer/phy.py
top.py

diff --git a/make.py b/make.py
index 879b5b9f06045bb42ef214f6e0269463fa075aea..f62dd0e93be35d8d444b3f0e8cc202a4ad90f8ad 100755 (executable)
--- a/make.py
+++ b/make.py
@@ -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"):
index 953ac28061a5d486cbb6a5836ef8963b67c10ef0..5475857be4aae8caf3b9167028da32ae15e12062 100644 (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 = []
index 96ac4543237bd5afd29d546c5f85b1174b92f777..7e4224533e6539c7682bc7b719a56a5b4feb66dc 100644 (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)),
index 2515a918fc58db979dc4da52c1347211488f8a59..90de7b0a954a59336a5547cc2930c6949ea7be79 100644 (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)
+                       ]
diff --git a/top.py b/top.py
index 60f6b33c80c65abfc71817d4d8c79612dcc6273d..69181e5fbdd205c522b475df0f18ea8e5bfe5029 100644 (file)
--- a/top.py
+++ b/top.py
@@ -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)