Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

add DVI output

  • Loading branch information...
commit ea0503173da85f0930eded372a155ddca8ac75e4 1 parent 1898034
Sébastien Bourdeauducq authored September 18, 2013
1  make.py
@@ -17,6 +17,7 @@ def build(platform_name, build_bitstream, build_header, *soc_args, **soc_kwargs)
17 17
 INST "mxcrg/rd_bufpll" LOC = "BUFPLL_X0Y3";
18 18
 
19 19
 PIN "mxcrg/bufg_x1.O" CLOCK_DEDICATED_ROUTE = FALSE;
  20
+PIN "pix2x_bufg.O" CLOCK_DEDICATED_ROUTE = FALSE;
20 21
 """)
21 22
 
22 23
 	if hasattr(soc, "fb"):
70  milkymist/framebuffer/dvi.py
@@ -83,6 +83,76 @@ def __init__(self):
83 83
 				cnt.eq(0)
84 84
 			)
85 85
 
  86
+class _EncoderSerializer(Module):
  87
+	def __init__(self, serdesstrobe, pad_p, pad_n):
  88
+		self.submodules.encoder = RenameClockDomains(Encoder(), "pix")
  89
+		self.d, self.c, self.de = self.encoder.d, self.encoder.c, self.encoder.de
  90
+
  91
+		###
  92
+
  93
+		# 2X soft serialization
  94
+		ed_2x = Signal(5)
  95
+		self.sync.pix2x += ed_2x.eq(Mux(ClockSignal("pix"), self.encoder.out[:5], self.encoder.out[5:]))
  96
+
  97
+		# 5X hard serialization
  98
+		cascade_di = Signal()
  99
+		cascade_do = Signal()
  100
+		cascade_ti = Signal()
  101
+		cascade_to = Signal()
  102
+		pad_se = Signal()
  103
+		self.specials += [
  104
+			Instance("OSERDES2",
  105
+				p_DATA_WIDTH=5, p_DATA_RATE_OQ="SDR", p_DATA_RATE_OT="SDR",
  106
+				p_SERDES_MODE="MASTER", p_OUTPUT_MODE="DIFFERENTIAL",
  107
+
  108
+				o_OQ=pad_se,
  109
+				i_OCE=1, i_IOCE=serdesstrobe, i_RST=0,
  110
+				i_CLK0=ClockSignal("pix10x"), i_CLK1=0, i_CLKDIV=ClockSignal("pix2x"),
  111
+				i_D1=ed_2x[4], i_D2=0, i_D3=0, i_D4=0,
  112
+				i_T1=0, i_T2=0, i_T3=0, i_T4=0,
  113
+				i_TRAIN=0, i_TCE=1,
  114
+				i_SHIFTIN1=1, i_SHIFTIN2=1,
  115
+				i_SHIFTIN3=cascade_do, i_SHIFTIN4=cascade_to,
  116
+				o_SHIFTOUT1=cascade_di, o_SHIFTOUT2=cascade_ti),
  117
+			Instance("OSERDES2",
  118
+				p_DATA_WIDTH=5, p_DATA_RATE_OQ="SDR", p_DATA_RATE_OT="SDR",
  119
+				p_SERDES_MODE="SLAVE", p_OUTPUT_MODE="DIFFERENTIAL",
  120
+
  121
+				i_OCE=1, i_IOCE=serdesstrobe, i_RST=0,
  122
+				i_CLK0=ClockSignal("pix10x"), i_CLK1=0, i_CLKDIV=ClockSignal("pix2x"),
  123
+				i_D1=ed_2x[0], i_D2=ed_2x[1], i_D3=ed_2x[2], i_D4=ed_2x[3],
  124
+				i_T1=0, i_T2=0, i_T3=0, i_T4=0,
  125
+				i_TRAIN=0, i_TCE=1,
  126
+				i_SHIFTIN1=cascade_di, i_SHIFTIN2=cascade_ti,
  127
+				i_SHIFTIN3=1, i_SHIFTIN4=1,
  128
+				o_SHIFTOUT3=cascade_do, o_SHIFTOUT4=cascade_to),
  129
+			Instance("OBUFDS", i_I=pad_se, o_O=pad_p, o_OB=pad_n)
  130
+		]
  131
+
  132
+
  133
+class PHY(Module):
  134
+	def __init__(self, serdesstrobe, pads):
  135
+		self.hsync = Signal()
  136
+		self.vsync = Signal()
  137
+		self.de = Signal()
  138
+		self.r = Signal(8)
  139
+		self.g = Signal(8)
  140
+		self.b = Signal(8)
  141
+
  142
+		###
  143
+
  144
+		self.submodules.es0 = _EncoderSerializer(serdesstrobe, pads.data0_p, pads.data0_n)
  145
+		self.submodules.es1 = _EncoderSerializer(serdesstrobe, pads.data1_p, pads.data1_n)
  146
+		self.submodules.es2 = _EncoderSerializer(serdesstrobe, pads.data2_p, pads.data2_n)
  147
+		self.comb += [
  148
+			self.es0.c.eq(Cat(self.hsync, self.vsync)),
  149
+			self.es1.c.eq(0),
  150
+			self.es2.c.eq(0),
  151
+			self.es0.de.eq(self.de),
  152
+			self.es1.de.eq(self.de),
  153
+			self.es2.de.eq(self.de),
  154
+		]
  155
+
86 156
 class _EncoderTB(Module):
87 157
 	def __init__(self, inputs):
88 158
 		self.outs = []
4  milkymist/framebuffer/format.py
@@ -28,6 +28,7 @@
28 28
 phy_layout = [
29 29
 	("hsync", 1),
30 30
 	("vsync", 1),
  31
+	("de", 1),
31 32
 	("p0", phy_layout_s),
32 33
 	("p1", phy_layout_s)
33 34
 ]
@@ -75,7 +76,8 @@ def __init__(self):
75 76
 			active.eq(hactive & vactive),
76 77
 			If(active,
77 78
 				[getattr(getattr(self.phy.payload, p), c).eq(getattr(getattr(self.pixels.payload, p), c)[skip:])
78  
-					for p in ["p0", "p1"] for c in ["r", "g", "b"]]
  79
+					for p in ["p0", "p1"] for c in ["r", "g", "b"]],
  80
+				self.phy.payload.de.eq(1)
79 81
 			),
80 82
 			
81 83
 			generate_en.eq(self.timing.stb & (~active | self.pixels.stb)),
42  milkymist/framebuffer/phy.py
... ...
@@ -1,11 +1,11 @@
1 1
 from migen.fhdl.std import *
2  
-from migen.genlib.record import Record
3 2
 from migen.genlib.fifo import AsyncFIFO
4 3
 from migen.genlib.cdc import MultiReg
5 4
 from migen.bank.description import *
6 5
 from migen.flow.actor import *
7 6
 
8 7
 from milkymist.framebuffer.format import bpc_phy, phy_layout
  8
+from milkymist.framebuffer import dvi
9 9
 
10 10
 class _FIFO(Module):
11 11
 	def __init__(self):
@@ -14,39 +14,37 @@ def __init__(self):
14 14
 		
15 15
 		self.pix_hsync = Signal()
16 16
 		self.pix_vsync = Signal()
  17
+		self.pix_de = Signal()
17 18
 		self.pix_r = Signal(bpc_phy)
18 19
 		self.pix_g = Signal(bpc_phy)
19 20
 		self.pix_b = Signal(bpc_phy)
20 21
 	
21 22
 		###
22 23
 
23  
-		data_width = 2+2*3*bpc_phy
24  
-		fifo = RenameClockDomains(AsyncFIFO(data_width, 512),
  24
+		fifo = RenameClockDomains(AsyncFIFO(phy_layout, 512),
25 25
 			{"write": "sys", "read": "pix"})
26 26
 		self.submodules += fifo
27  
-		fifo_in = self.phy.payload
28  
-		fifo_out = Record(phy_layout)
29 27
 		self.comb += [
30 28
 			self.phy.ack.eq(fifo.writable),
31 29
 			fifo.we.eq(self.phy.stb),
32  
-			fifo.din.eq(fifo_in.raw_bits()),
33  
-			fifo_out.raw_bits().eq(fifo.dout),
  30
+			fifo.din.eq(self.phy.payload),
34 31
 			self.busy.eq(0)
35 32
 		]
36 33
 
37 34
 		pix_parity = Signal()
38 35
 		self.sync.pix += [
39 36
 			pix_parity.eq(~pix_parity),
40  
-			self.pix_hsync.eq(fifo_out.hsync),
41  
-			self.pix_vsync.eq(fifo_out.vsync),
  37
+			self.pix_hsync.eq(fifo.dout.hsync),
  38
+			self.pix_vsync.eq(fifo.dout.vsync),
  39
+			self.pix_de.eq(fifo.dout.de),
42 40
 			If(pix_parity,
43  
-				self.pix_r.eq(fifo_out.p1.r),
44  
-				self.pix_g.eq(fifo_out.p1.g),
45  
-				self.pix_b.eq(fifo_out.p1.b)
  41
+				self.pix_r.eq(fifo.dout.p1.r),
  42
+				self.pix_g.eq(fifo.dout.p1.g),
  43
+				self.pix_b.eq(fifo.dout.p1.b)
46 44
 			).Else(
47  
-				self.pix_r.eq(fifo_out.p0.r),
48  
-				self.pix_g.eq(fifo_out.p0.g),
49  
-				self.pix_b.eq(fifo_out.p0.b)
  45
+				self.pix_r.eq(fifo.dout.p0.r),
  46
+				self.pix_g.eq(fifo.dout.p0.g),
  47
+				self.pix_b.eq(fifo.dout.p0.b)
50 48
 			)
51 49
 		]
52 50
 		self.comb += fifo.re.eq(pix_parity)
@@ -143,7 +141,7 @@ def __init__(self, pads_vga, pads_dvi):
143 141
 				Instance("BUFPLL", p_DIVIDE=5,
144 142
 					i_PLLIN=pll_clk0, i_GCLK=ClockSignal("pix2x"), i_LOCKED=pll_locked,
145 143
 					o_IOCLK=self.cd_pix10x.clk, o_LOCK=locked_async, o_SERDESSTROBE=self.serdesstrobe),
146  
-				Instance("BUFG", i_I=pll_clk1, o_O=self.cd_pix2x.clk),
  144
+				Instance("BUFG", name="pix2x_bufg", i_I=pll_clk1, o_O=self.cd_pix2x.clk),
147 145
 				Instance("BUFG", i_I=pll_clk2, o_O=self.cd_pix.clk),
148 146
 				MultiReg(locked_async, mult_locked, "sys")
149 147
 			]
@@ -166,7 +164,7 @@ def __init__(self, pads_vga, pads_dvi):
166 164
 				i_C1=~ClockSignal("pix"),
167 165
 				i_CE=1, i_D0=1, i_D1=0,
168 166
 				i_R=0, i_S=0)
169  
-			self.specials += Instance("OBUFTDS", i_I=dvi_clk_se,
  167
+			self.specials += Instance("OBUFDS", i_I=dvi_clk_se,
170 168
 				o_O=pads_dvi.clk_p, o_OB=pads_dvi.clk_n)
171 169
 
172 170
 class Driver(Module, AutoCSR):
@@ -187,3 +185,13 @@ def __init__(self, pads_vga, pads_dvi):
187 185
 				pads_vga.b.eq(fifo.pix_b),
188 186
 				pads_vga.psave_n.eq(1)
189 187
 			]
  188
+		if pads_dvi is not None:
  189
+			self.submodules.dvi_phy = dvi.PHY(self.clocking.serdesstrobe, pads_dvi)
  190
+			self.comb += [
  191
+				self.dvi_phy.hsync.eq(fifo.pix_hsync),
  192
+				self.dvi_phy.vsync.eq(fifo.pix_vsync),
  193
+				self.dvi_phy.de.eq(fifo.pix_de),
  194
+				self.dvi_phy.r.eq(fifo.pix_r),
  195
+				self.dvi_phy.g.eq(fifo.pix_g),
  196
+				self.dvi_phy.b.eq(fifo.pix_b)
  197
+			]
5  top.py
@@ -161,13 +161,14 @@ def __init__(self, platform, platform_name, with_memtest):
161 161
 		self.submodules.timer0 = timer.Timer()
162 162
 		if platform_name == "mixxeo":
163 163
 			self.submodules.leds = gpio.GPIOOut(platform.request("user_led"))
164  
-			self.submodules.fb = framebuffer.MixFramebuffer(platform.request("vga_out"), None, lasmim_fb0, lasmim_fb1)
  164
+			self.submodules.fb = framebuffer.MixFramebuffer(platform.request("vga_out"), platform.request("dvi_out"),
  165
+				lasmim_fb0, lasmim_fb1)
165 166
 			self.submodules.dvisampler0 = dvisampler.DVISampler(platform.request("dvi_in", 0), lasmim_dvi0)
166 167
 			self.submodules.dvisampler1 = dvisampler.DVISampler(platform.request("dvi_in", 1), lasmim_dvi1)
167 168
 		if platform_name == "m1":
168 169
 			self.submodules.buttons = gpio.GPIOIn(Cat(platform.request("user_btn", 0), platform.request("user_btn", 2)))
169 170
 			self.submodules.leds = gpio.GPIOOut(Cat(*[platform.request("user_led", i) for i in range(2)]))
170  
-			self.submodules.fb = framebuffer.Framebuffer(platform.request("vga"), lasmim_fb)
  171
+			self.submodules.fb = framebuffer.Framebuffer(platform.request("vga"), None, lasmim_fb)
171 172
 		if with_memtest:
172 173
 			self.submodules.memtest_w = memtest.MemtestWriter(lasmim_mtw)
173 174
 			self.submodules.memtest_r = memtest.MemtestReader(lasmim_mtr)

0 notes on commit ea05031

Please sign in to comment.
Something went wrong with that request. Please try again.