Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

add DVI output

  • Loading branch information...
commit ea0503173da85f0930eded372a155ddca8ac75e4 1 parent 1898034
@sbourdeauducq sbourdeauducq authored
View
1  make.py
@@ -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"):
View
70 milkymist/framebuffer/dvi.py
@@ -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 = []
View
4 milkymist/framebuffer/format.py
@@ -28,6 +28,7 @@
phy_layout = [
("hsync", 1),
("vsync", 1),
+ ("de", 1),
("p0", phy_layout_s),
("p1", phy_layout_s)
]
@@ -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)),
View
42 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):
@@ -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)
@@ -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")
]
@@ -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):
@@ -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)
+ ]
View
5 top.py
@@ -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)
Please sign in to comment.
Something went wrong with that request. Please try again.