Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

framebuffer: prepare for DVI out

  • Loading branch information...
commit e6e04a2e3a8fd08a150ce5a2302f1ffa8a728465 1 parent 20b758d
Sébastien Bourdeauducq authored September 17, 2013
4  make.py
@@ -21,11 +21,11 @@ def build(platform_name, build_bitstream, build_header, *soc_args, **soc_kwargs)
21 21
 
22 22
 	if hasattr(soc, "fb"):
23 23
 		platform.add_platform_command("""
24  
-NET "vga_clk" TNM_NET = "GRPvga_clk";
  24
+NET "{vga_clk}" TNM_NET = "GRPvga_clk";
25 25
 NET "sys_clk" TNM_NET = "GRPsys_clk";
26 26
 TIMESPEC "TSise_sucks1" = FROM "GRPvga_clk" TO "GRPsys_clk" TIG;
27 27
 TIMESPEC "TSise_sucks2" = FROM "GRPsys_clk" TO "GRPvga_clk" TIG;
28  
-""")
  28
+""", vga_clk=soc.fb.driver.clocking.cd_pix.clk)
29 29
 
30 30
 	for d in ["mxcrg", "minimac3"]:
31 31
 		platform.add_source_dir(os.path.join("verilog", d))
60  milkymist/framebuffer/__init__.py
@@ -4,52 +4,35 @@
4 4
 from migen.bank.description import CSRStorage, AutoCSR
5 5
 from migen.actorlib import dma_lasmi, structuring, sim, spi
6 6
 
7  
-from milkymist.framebuffer.lib import bpp, pixel_layout, dac_layout, FrameInitiator, VTG, FIFO
  7
+from milkymist.framebuffer.format import bpp, pixel_layout, FrameInitiator, VTG
  8
+from milkymist.framebuffer.phy import Driver
8 9
 
9  
-class Framebuffer(Module):
10  
-	def __init__(self, pads, lasmim, simulation=False):
  10
+class Framebuffer(Module, AutoCSR):
  11
+	def __init__(self, pads_vga, pads_dvi, lasmim, simulation=False):
11 12
 		pack_factor = lasmim.dw//(2*bpp)
12 13
 		packed_pixels = structuring.pack_layout(pixel_layout, pack_factor)
13 14
 		
14  
-		fi = FrameInitiator()
15  
-		dma = spi.DMAReadController(dma_lasmi.Reader(lasmim), spi.MODE_EXTERNAL, length_reset=640*480*4)
  15
+		self._enable = CSRStorage()
  16
+		self.fi = FrameInitiator()
  17
+		self.dma = spi.DMAReadController(dma_lasmi.Reader(lasmim), spi.MODE_EXTERNAL, length_reset=640*480*4)
  18
+		self.driver = Driver(pads_vga, pads_dvi)
  19
+
16 20
 		cast = structuring.Cast(lasmim.dw, packed_pixels, reverse_to=True)
17 21
 		unpack = structuring.Unpack(pack_factor, pixel_layout)
18 22
 		vtg = VTG()
19  
-		if simulation:
20  
-			fifo = sim.SimActor(sim_fifo_gen(), ("dac", Sink, dac_layout))
21  
-		else:
22  
-			fifo = FIFO()
23 23
 		
24 24
 		g = DataFlowGraph()
25  
-		g.add_connection(fi, vtg, sink_ep="timing")
26  
-		g.add_connection(dma, cast)
  25
+		g.add_connection(self.fi, vtg, sink_ep="timing")
  26
+		g.add_connection(self.dma, cast)
27 27
 		g.add_connection(cast, unpack)
28 28
 		g.add_connection(unpack, vtg, sink_ep="pixels")
29  
-		g.add_connection(vtg, fifo)
  29
+		g.add_connection(vtg, self.driver)
30 30
 		self.submodules += CompositeActor(g)
31 31
 
32  
-		self._enable = CSRStorage()
33 32
 		self.comb += [
34  
-			fi.trigger.eq(self._enable.storage),
35  
-			dma.generator.trigger.eq(self._enable.storage),
  33
+			self.fi.trigger.eq(self._enable.storage),
  34
+			self.dma.generator.trigger.eq(self._enable.storage),
36 35
 		]
37  
-		self._fi = fi
38  
-		self._dma = dma
39  
-		
40  
-		# Drive pads
41  
-		if not simulation:
42  
-			self.comb += [
43  
-				pads.hsync_n.eq(fifo.vga_hsync_n),
44  
-				pads.vsync_n.eq(fifo.vga_vsync_n),
45  
-				pads.r.eq(fifo.vga_r),
46  
-				pads.g.eq(fifo.vga_g),
47  
-				pads.b.eq(fifo.vga_b)
48  
-			]
49  
-		self.comb += pads.psave_n.eq(1)
50  
-
51  
-	def get_csrs(self):
52  
-		return [self._enable] + self._fi.get_csrs() + self._dma.get_csrs()
53 36
 
54 37
 class Blender(PipelinedActor, AutoCSR):
55 38
 	def __init__(self, nimages, latency):
@@ -97,13 +80,14 @@ def __init__(self, nimages, latency):
97 80
 		self.comb += self.source.payload.eq(outval)
98 81
 
99 82
 class MixFramebuffer(Module, AutoCSR):
100  
-	def __init__(self, pads, *lasmims, blender_latency=5):
  83
+	def __init__(self, pads_vga, pads_dvi, *lasmims, blender_latency=5):
101 84
 		pack_factor = lasmims[0].dw//(2*bpp)
102 85
 		packed_pixels = structuring.pack_layout(pixel_layout, pack_factor)
103 86
 		
104 87
 		self._enable = CSRStorage()
105 88
 		self.fi = FrameInitiator()
106 89
 		self.blender = Blender(len(lasmims), blender_latency)
  90
+		self.driver = Driver(pads_vga, pads_dvi)
107 91
 		self.comb += self.fi.trigger.eq(self._enable.storage)
108 92
 
109 93
 		g = DataFlowGraph()
@@ -120,17 +104,7 @@ def __init__(self, pads, *lasmims, blender_latency=5):
120 104
 			setattr(self, "dma"+str(n), dma)
121 105
 
122 106
 		vtg = VTG()
123  
-		fifo = FIFO()
124 107
 		g.add_connection(self.fi, vtg, sink_ep="timing")
125 108
 		g.add_connection(self.blender, vtg, sink_ep="pixels")
126  
-		g.add_connection(vtg, fifo)
  109
+		g.add_connection(vtg, self.driver)
127 110
 		self.submodules += CompositeActor(g)
128  
-		
129  
-		self.comb += [
130  
-			pads.hsync_n.eq(fifo.vga_hsync_n),
131  
-			pads.vsync_n.eq(fifo.vga_vsync_n),
132  
-			pads.r.eq(fifo.vga_r),
133  
-			pads.g.eq(fifo.vga_g),
134  
-			pads.b.eq(fifo.vga_b),
135  
-			pads.psave_n.eq(1)
136  
-		]
111  milkymist/framebuffer/format.py
... ...
@@ -0,0 +1,111 @@
  1
+from migen.fhdl.std import *
  2
+from migen.flow.actor import *
  3
+from migen.bank.description import CSRStorage
  4
+from migen.actorlib import spi
  5
+
  6
+_hbits = 11
  7
+_vbits = 12
  8
+
  9
+bpp = 32
  10
+bpc = 10
  11
+pixel_layout_s = [
  12
+	("pad", bpp-3*bpc),
  13
+	("r", bpc),
  14
+	("g", bpc),
  15
+	("b", bpc)
  16
+]
  17
+pixel_layout = [
  18
+	("p0", pixel_layout_s),
  19
+	("p1", pixel_layout_s)
  20
+]
  21
+
  22
+bpc_phy = 8
  23
+phy_layout_s = [
  24
+	("r", bpc_phy),
  25
+	("g", bpc_phy),
  26
+	("b", bpc_phy)
  27
+]
  28
+phy_layout = [
  29
+	("hsync", 1),
  30
+	("vsync", 1),
  31
+	("p0", phy_layout_s),
  32
+	("p1", phy_layout_s)
  33
+]
  34
+
  35
+class FrameInitiator(spi.SingleGenerator):
  36
+	def __init__(self):
  37
+		layout = [
  38
+			("hres", _hbits, 640, 1),
  39
+			("hsync_start", _hbits, 656, 1),
  40
+			("hsync_end", _hbits, 752, 1),
  41
+			("hscan", _hbits, 800, 1),
  42
+			
  43
+			("vres", _vbits, 480),
  44
+			("vsync_start", _vbits, 492),
  45
+			("vsync_end", _vbits, 494),
  46
+			("vscan", _vbits, 525)
  47
+		]
  48
+		spi.SingleGenerator.__init__(self, layout, spi.MODE_EXTERNAL)
  49
+
  50
+class VTG(Module):
  51
+	def __init__(self):
  52
+		self.timing = Sink([
  53
+				("hres", _hbits),
  54
+				("hsync_start", _hbits),
  55
+				("hsync_end", _hbits),
  56
+				("hscan", _hbits),
  57
+				("vres", _vbits),
  58
+				("vsync_start", _vbits),
  59
+				("vsync_end", _vbits),
  60
+				("vscan", _vbits)])
  61
+		self.pixels = Sink(pixel_layout)
  62
+		self.phy = Source(phy_layout)
  63
+		self.busy = Signal()
  64
+
  65
+		hactive = Signal()
  66
+		vactive = Signal()
  67
+		active = Signal()
  68
+		
  69
+		generate_en = Signal()
  70
+		hcounter = Signal(_hbits)
  71
+		vcounter = Signal(_vbits)
  72
+		
  73
+		skip = bpc - bpc_phy
  74
+		self.comb += [
  75
+			active.eq(hactive & vactive),
  76
+			If(active,
  77
+				[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
+			),
  80
+			
  81
+			generate_en.eq(self.timing.stb & (~active | self.pixels.stb)),
  82
+			self.pixels.ack.eq(self.phy.ack & active),
  83
+			self.phy.stb.eq(generate_en),
  84
+			self.busy.eq(generate_en)
  85
+		]
  86
+		tp = self.timing.payload
  87
+		self.sync += [
  88
+			self.timing.ack.eq(0),
  89
+			If(generate_en & self.phy.ack,
  90
+				hcounter.eq(hcounter + 1),
  91
+			
  92
+				If(hcounter == 0, hactive.eq(1)),
  93
+				If(hcounter == tp.hres, hactive.eq(0)),
  94
+				If(hcounter == tp.hsync_start, self.phy.payload.hsync.eq(1)),
  95
+				If(hcounter == tp.hsync_end, self.phy.payload.hsync.eq(0)),
  96
+				If(hcounter == tp.hscan,
  97
+					hcounter.eq(0),
  98
+					If(vcounter == tp.vscan,
  99
+						vcounter.eq(0),
  100
+						self.timing.ack.eq(1)
  101
+					).Else(
  102
+						vcounter.eq(vcounter + 1)
  103
+					)
  104
+				),
  105
+				
  106
+				If(vcounter == 0, vactive.eq(1)),
  107
+				If(vcounter == tp.vres, vactive.eq(0)),
  108
+				If(vcounter == tp.vsync_start, self.phy.payload.vsync.eq(1)),
  109
+				If(vcounter == tp.vsync_end, self.phy.payload.vsync.eq(0))
  110
+			)
  111
+		]
166  milkymist/framebuffer/lib.py
... ...
@@ -1,166 +0,0 @@
1  
-from migen.fhdl.std import *
2  
-from migen.genlib.record import Record
3  
-from migen.genlib.fifo import AsyncFIFO
4  
-from migen.flow.actor import *
5  
-from migen.flow.network import *
6  
-from migen.flow.transactions import *
7  
-from migen.bank.description import CSRStorage
8  
-from migen.actorlib import spi
9  
-
10  
-_hbits = 11
11  
-_vbits = 12
12  
-
13  
-bpp = 32
14  
-bpc = 10
15  
-pixel_layout_s = [
16  
-	("pad", bpp-3*bpc),
17  
-	("r", bpc),
18  
-	("g", bpc),
19  
-	("b", bpc)
20  
-]
21  
-pixel_layout = [
22  
-	("p0", pixel_layout_s),
23  
-	("p1", pixel_layout_s)
24  
-]
25  
-
26  
-bpc_dac = 8
27  
-dac_layout_s = [
28  
-	("r", bpc_dac),
29  
-	("g", bpc_dac),
30  
-	("b", bpc_dac)
31  
-]
32  
-dac_layout = [
33  
-	("hsync", 1),
34  
-	("vsync", 1),
35  
-	("p0", dac_layout_s),
36  
-	("p1", dac_layout_s)
37  
-]
38  
-
39  
-class FrameInitiator(spi.SingleGenerator):
40  
-	def __init__(self):
41  
-		layout = [
42  
-			("hres", _hbits, 640, 1),
43  
-			("hsync_start", _hbits, 656, 1),
44  
-			("hsync_end", _hbits, 752, 1),
45  
-			("hscan", _hbits, 800, 1),
46  
-			
47  
-			("vres", _vbits, 480),
48  
-			("vsync_start", _vbits, 492),
49  
-			("vsync_end", _vbits, 494),
50  
-			("vscan", _vbits, 525)
51  
-		]
52  
-		spi.SingleGenerator.__init__(self, layout, spi.MODE_EXTERNAL)
53  
-
54  
-class VTG(Module):
55  
-	def __init__(self):
56  
-		self.timing = Sink([
57  
-				("hres", _hbits),
58  
-				("hsync_start", _hbits),
59  
-				("hsync_end", _hbits),
60  
-				("hscan", _hbits),
61  
-				("vres", _vbits),
62  
-				("vsync_start", _vbits),
63  
-				("vsync_end", _vbits),
64  
-				("vscan", _vbits)])
65  
-		self.pixels = Sink(pixel_layout)
66  
-		self.dac = Source(dac_layout)
67  
-		self.busy = Signal()
68  
-
69  
-		hactive = Signal()
70  
-		vactive = Signal()
71  
-		active = Signal()
72  
-		
73  
-		generate_en = Signal()
74  
-		hcounter = Signal(_hbits)
75  
-		vcounter = Signal(_vbits)
76  
-		
77  
-		skip = bpc - bpc_dac
78  
-		self.comb += [
79  
-			active.eq(hactive & vactive),
80  
-			If(active,
81  
-				[getattr(getattr(self.dac.payload, p), c).eq(getattr(getattr(self.pixels.payload, p), c)[skip:])
82  
-					for p in ["p0", "p1"] for c in ["r", "g", "b"]]
83  
-			),
84  
-			
85  
-			generate_en.eq(self.timing.stb & (~active | self.pixels.stb)),
86  
-			self.pixels.ack.eq(self.dac.ack & active),
87  
-			self.dac.stb.eq(generate_en),
88  
-			self.busy.eq(generate_en)
89  
-		]
90  
-		tp = self.timing.payload
91  
-		self.sync += [
92  
-			self.timing.ack.eq(0),
93  
-			If(generate_en & self.dac.ack,
94  
-				hcounter.eq(hcounter + 1),
95  
-			
96  
-				If(hcounter == 0, hactive.eq(1)),
97  
-				If(hcounter == tp.hres, hactive.eq(0)),
98  
-				If(hcounter == tp.hsync_start, self.dac.payload.hsync.eq(1)),
99  
-				If(hcounter == tp.hsync_end, self.dac.payload.hsync.eq(0)),
100  
-				If(hcounter == tp.hscan,
101  
-					hcounter.eq(0),
102  
-					If(vcounter == tp.vscan,
103  
-						vcounter.eq(0),
104  
-						self.timing.ack.eq(1)
105  
-					).Else(
106  
-						vcounter.eq(vcounter + 1)
107  
-					)
108  
-				),
109  
-				
110  
-				If(vcounter == 0, vactive.eq(1)),
111  
-				If(vcounter == tp.vres, vactive.eq(0)),
112  
-				If(vcounter == tp.vsync_start, self.dac.payload.vsync.eq(1)),
113  
-				If(vcounter == tp.vsync_end, self.dac.payload.vsync.eq(0))
114  
-			)
115  
-		]
116  
-
117  
-class FIFO(Module):
118  
-	def __init__(self):
119  
-		self.dac = Sink(dac_layout)
120  
-		self.busy = Signal()
121  
-		
122  
-		self.vga_hsync_n = Signal()
123  
-		self.vga_vsync_n = Signal()
124  
-		self.vga_r = Signal(bpc_dac)
125  
-		self.vga_g = Signal(bpc_dac)
126  
-		self.vga_b = Signal(bpc_dac)
127  
-	
128  
-		###
129  
-
130  
-		data_width = 2+2*3*bpc_dac
131  
-		fifo = RenameClockDomains(AsyncFIFO(data_width, 512),
132  
-			{"write": "sys", "read": "vga"})
133  
-		self.submodules += fifo
134  
-		fifo_in = self.dac.payload
135  
-		fifo_out = Record(dac_layout)
136  
-		self.comb += [
137  
-			self.dac.ack.eq(fifo.writable),
138  
-			fifo.we.eq(self.dac.stb),
139  
-			fifo.din.eq(fifo_in.raw_bits()),
140  
-			fifo_out.raw_bits().eq(fifo.dout),
141  
-			self.busy.eq(0)
142  
-		]
143  
-
144  
-		pix_parity = Signal()
145  
-		self.sync.vga += [
146  
-			pix_parity.eq(~pix_parity),
147  
-			self.vga_hsync_n.eq(~fifo_out.hsync),
148  
-			self.vga_vsync_n.eq(~fifo_out.vsync),
149  
-			If(pix_parity,
150  
-				self.vga_r.eq(fifo_out.p1.r),
151  
-				self.vga_g.eq(fifo_out.p1.g),
152  
-				self.vga_b.eq(fifo_out.p1.b)
153  
-			).Else(
154  
-				self.vga_r.eq(fifo_out.p0.r),
155  
-				self.vga_g.eq(fifo_out.p0.g),
156  
-				self.vga_b.eq(fifo_out.p0.b)
157  
-			)
158  
-		]
159  
-		self.comb += fifo.re.eq(pix_parity)
160  
-
161  
-def sim_fifo_gen():
162  
-	while True:
163  
-		t = Token("dac")
164  
-		yield t
165  
-		print("H/V:" + str(t.value["hsync"]) + str(t.value["vsync"])
166  
-			+ " " + str(t.value["r"]) + " " + str(t.value["g"]) + " " + str(t.value["b"]))
182  milkymist/framebuffer/phy.py
... ...
@@ -0,0 +1,182 @@
  1
+from migen.fhdl.std import *
  2
+from migen.genlib.record import Record
  3
+from migen.genlib.fifo import AsyncFIFO
  4
+from migen.bank.description import *
  5
+from migen.flow.actor import *
  6
+
  7
+from milkymist.framebuffer.format import bpc_phy, phy_layout
  8
+
  9
+class _FIFO(Module):
  10
+	def __init__(self):
  11
+		self.phy = Sink(phy_layout)
  12
+		self.busy = Signal()
  13
+		
  14
+		self.pix_hsync = Signal()
  15
+		self.pix_vsync = Signal()
  16
+		self.pix_r = Signal(bpc_phy)
  17
+		self.pix_g = Signal(bpc_phy)
  18
+		self.pix_b = Signal(bpc_phy)
  19
+	
  20
+		###
  21
+
  22
+		data_width = 2+2*3*bpc_phy
  23
+		fifo = RenameClockDomains(AsyncFIFO(data_width, 512),
  24
+			{"write": "sys", "read": "pix"})
  25
+		self.submodules += fifo
  26
+		fifo_in = self.phy.payload
  27
+		fifo_out = Record(phy_layout)
  28
+		self.comb += [
  29
+			self.phy.ack.eq(fifo.writable),
  30
+			fifo.we.eq(self.phy.stb),
  31
+			fifo.din.eq(fifo_in.raw_bits()),
  32
+			fifo_out.raw_bits().eq(fifo.dout),
  33
+			self.busy.eq(0)
  34
+		]
  35
+
  36
+		pix_parity = Signal()
  37
+		self.sync.pix += [
  38
+			pix_parity.eq(~pix_parity),
  39
+			self.pix_hsync.eq(fifo_out.hsync),
  40
+			self.pix_vsync.eq(fifo_out.vsync),
  41
+			If(pix_parity,
  42
+				self.pix_r.eq(fifo_out.p1.r),
  43
+				self.pix_g.eq(fifo_out.p1.g),
  44
+				self.pix_b.eq(fifo_out.p1.b)
  45
+			).Else(
  46
+				self.pix_r.eq(fifo_out.p0.r),
  47
+				self.pix_g.eq(fifo_out.p0.g),
  48
+				self.pix_b.eq(fifo_out.p0.b)
  49
+			)
  50
+		]
  51
+		self.comb += fifo.re.eq(pix_parity)
  52
+
  53
+# This assumes a 50MHz base clock
  54
+class _Clocking(Module, AutoCSR):
  55
+	def __init__(self, pads_vga, pads_dvi):
  56
+		self._r_cmd_data = CSRStorage(10)
  57
+		self._r_send_cmd_data = CSR()
  58
+		self._r_send_go = CSR()
  59
+		self._r_status = CSRStatus(4)
  60
+
  61
+		self.clock_domains.cd_pix = ClockDomain(reset_less=True)
  62
+		if pads_dvi is not None:
  63
+			self.clock_domains.cd_pix2x = ClockDomain(reset_less=True)
  64
+			self.clock_domains.cd_pix10x = ClockDomain(reset_less=True)
  65
+			self.serdesstrobe = Signal()
  66
+
  67
+		###
  68
+
  69
+		# Generate 1x pixel clock
  70
+		clk_pix_unbuffered = Signal()
  71
+		pix_progdata = Signal()
  72
+		pix_progen = Signal()
  73
+		pix_progdone = Signal()
  74
+		pix_locked = Signal()
  75
+		self.specials += Instance("DCM_CLKGEN",
  76
+			p_CLKFXDV_DIVIDE=2, p_CLKFX_DIVIDE=4, p_CLKFX_MD_MAX=3.0, p_CLKFX_MULTIPLY=2,
  77
+			p_CLKIN_PERIOD=20.0, p_SPREAD_SPECTRUM="NONE", p_STARTUP_WAIT="FALSE",
  78
+		
  79
+			i_CLKIN=ClockSignal("base50"), o_CLKFX=clk_pix_unbuffered,
  80
+			i_PROGCLK=ClockSignal(), i_PROGDATA=pix_progdata, i_PROGEN=pix_progen,
  81
+			o_PROGDONE=pix_progdone, o_LOCKED=pix_locked,
  82
+			i_FREEZEDCM=0, i_RST=ResetSignal())
  83
+
  84
+		remaining_bits = Signal(max=11)
  85
+		transmitting = Signal()
  86
+		self.comb += transmitting.eq(remaining_bits != 0)
  87
+		sr = Signal(10)
  88
+		self.sync += [
  89
+			If(self._r_send_cmd_data.re,
  90
+				remaining_bits.eq(10),
  91
+				sr.eq(self._r_cmd_data.storage)
  92
+			).Elif(transmitting,
  93
+				remaining_bits.eq(remaining_bits - 1),
  94
+				sr.eq(sr[1:])
  95
+			)
  96
+		]
  97
+		self.comb += [
  98
+			pix_progdata.eq(transmitting & sr[0]),
  99
+			pix_progen.eq(transmitting | self._r_send_go.re)
  100
+		]
  101
+
  102
+		# enforce gap between commands
  103
+		busy_counter = Signal(max=14)
  104
+		busy = Signal()
  105
+		self.comb += busy.eq(busy_counter != 0)
  106
+		self.sync += If(self._r_send_cmd_data.re,
  107
+				busy_counter.eq(13)
  108
+			).Elif(busy,
  109
+				busy_counter.eq(busy_counter - 1)
  110
+			)
  111
+
  112
+		mult_locked = Signal()
  113
+		self.comb += self._r_status.status.eq(Cat(busy, pix_progdone, pix_locked, mult_locked))
  114
+
  115
+		# Clock multiplication and buffering
  116
+		if pads_dvi is None:
  117
+			# Just buffer 1x pixel clock
  118
+			self.specials += Instance("BUFG", i_I=clk_pix_unbuffered, o_O=self.cd_pix.clk)
  119
+			self.comb += mult_locked.eq(pix_locked)
  120
+		else:
  121
+			# Route unbuffered 1x pixel clock to PLL
  122
+			# Generate 1x, 2x and 10x IO pixel clocks
  123
+			clkfbout = Signal()
  124
+			pll_locked = Signal()
  125
+			pll_clk0 = Signal()
  126
+			pll_clk1 = Signal()
  127
+			pll_clk2 = Signal()
  128
+			locked_async = Signal()
  129
+			self.specials += [
  130
+				Instance("PLL_BASE",
  131
+					p_CLKIN_PERIOD=26.7,
  132
+					p_CLKFBOUT_MULT=20,
  133
+					p_CLKOUT0_DIVIDE=2,  # pix10x
  134
+					p_CLKOUT1_DIVIDE=10, # pix2x
  135
+					p_CLKOUT2_DIVIDE=20, # pix
  136
+					p_COMPENSATION="INTERNAL",
  137
+					
  138
+					i_CLKIN=clk_pix_unbuffered,
  139
+					o_CLKOUT0=pll_clk0, o_CLKOUT1=pll_clk1, o_CLKOUT2=pll_clk2,
  140
+					o_CLKFBOUT=clkfbout, i_CLKFBIN=clkfbout,
  141
+					o_LOCKED=pll_locked, i_RST=~pix_locked),
  142
+				Instance("BUFPLL", p_DIVIDE=5,
  143
+					i_PLLIN=pll_clk0, i_GCLK=ClockSignal("pix2x"), i_LOCKED=pll_locked,
  144
+					o_IOCLK=self.cd_pix10x.clk, o_LOCK=locked_async, o_SERDESSTROBE=self.serdesstrobe),
  145
+				Instance("BUFG", i_I=pll_clk1, o_O=self.cd_pix2x.clk),
  146
+				Instance("BUFG", i_I=pll_clk2, o_O=self.cd_pix.clk),
  147
+				MultiReg(locked_async, mult_locked, "sys")
  148
+			]
  149
+
  150
+		# Drive VGA/DVI clock pads
  151
+		pix_clk_io = Signal()
  152
+		self.specials += Instance("ODDR2",
  153
+			p_DDR_ALIGNMENT="NONE", p_INIT=0, p_SRTYPE="SYNC",
  154
+			o_Q=pix_clk_io,
  155
+			i_C0=ClockSignal("pix"),
  156
+			i_C1=~ClockSignal("pix"),
  157
+			i_CE=1, i_D0=1, i_D1=0,
  158
+			i_R=0, i_S=0)
  159
+		if pads_vga is not None:
  160
+			self.comb += pads_vga.clk.eq(pix_clk_io)
  161
+		if pads_dvi is not None:
  162
+			self.specials += Instance("OBUFDS", i_I=pix_clk_io,
  163
+				o_O=pads.clk_p, o_OB=pads.clk_n)
  164
+
  165
+class Driver(Module, AutoCSR):
  166
+	def __init__(self, pads_vga, pads_dvi):
  167
+		fifo = _FIFO()
  168
+		self.submodules += fifo
  169
+		self.phy = fifo.phy
  170
+		self.busy = fifo.busy
  171
+
  172
+		self.submodules.clocking = _Clocking(pads_vga, pads_dvi)
  173
+
  174
+		if pads_vga is not None:
  175
+			self.comb += [
  176
+				pads_vga.hsync_n.eq(~fifo.pix_hsync),
  177
+				pads_vga.vsync_n.eq(~fifo.pix_vsync),
  178
+				pads_vga.r.eq(fifo.pix_r),
  179
+				pads_vga.g.eq(fifo.pix_g),
  180
+				pads_vga.b.eq(fifo.pix_b),
  181
+				pads_vga.psave_n.eq(1)
  182
+			]
56  milkymist/mxcrg/__init__.py
... ...
@@ -1,9 +1,8 @@
1 1
 from fractions import Fraction
2 2
 
3 3
 from migen.fhdl.std import *
4  
-from migen.bank.description import *
5 4
 
6  
-class MXCRG(Module, AutoCSR):
  5
+class MXCRG(Module):
7 6
 	def __init__(self, pads, outfreq1x):
8 7
 		self.clock_domains.cd_sys = ClockDomain()
9 8
 		self.clock_domains.cd_sdram_half = ClockDomain()
@@ -11,27 +10,17 @@ def __init__(self, pads, outfreq1x):
11 10
 		self.clock_domains.cd_sdram_full_rd = ClockDomain()
12 11
 		self.clock_domains.cd_eth_rx = ClockDomain()
13 12
 		self.clock_domains.cd_eth_tx = ClockDomain()
14  
-		self.clock_domains.cd_vga = ClockDomain(reset_less=True)
  13
+		self.clock_domains.cd_base50 = ClockDomain(reset_less=True)
15 14
 
16 15
 		self.clk4x_wr_strb = Signal()
17 16
 		self.clk4x_rd_strb = Signal()
18 17
 
19  
-		self._r_cmd_data = CSRStorage(10)
20  
-		self._r_send_cmd_data = CSR()
21  
-		self._r_send_go = CSR()
22  
-		self._r_status = CSRStatus(3)
23  
-
24 18
 		###
25 19
 		
26 20
 		infreq = 50*1000000
27 21
 		ratio = Fraction(outfreq1x)/Fraction(infreq)
28 22
 		in_period = float(Fraction(1000000000)/Fraction(infreq))
29 23
 
30  
-		vga_progdata = Signal()
31  
-		vga_progen = Signal()
32  
-		vga_progdone = Signal()
33  
-		vga_locked = Signal()
34  
-
35 24
 		self.specials += Instance("mxcrg",
36 25
 			Instance.Parameter("in_period", in_period),
37 26
 			Instance.Parameter("f_mult", ratio.numerator),
@@ -49,48 +38,11 @@ def __init__(self, pads, outfreq1x):
49 38
 			Instance.Output("clk4x_rd", self.cd_sdram_full_rd.clk),
50 39
 			Instance.Output("eth_rx_clk", self.cd_eth_rx.clk),
51 40
 			Instance.Output("eth_tx_clk", self.cd_eth_tx.clk),
52  
-			Instance.Output("vga_clk", self.cd_vga.clk),
  41
+			Instance.Output("base50_clk", self.cd_base50.clk),
53 42
 
54 43
 			Instance.Output("clk4x_wr_strb", self.clk4x_wr_strb),
55 44
 			Instance.Output("clk4x_rd_strb", self.clk4x_rd_strb),
56 45
 			Instance.Output("norflash_rst_n", pads.norflash_rst_n),
57 46
 			Instance.Output("ddr_clk_pad_p", pads.ddr_clk_p),
58 47
 			Instance.Output("ddr_clk_pad_n", pads.ddr_clk_n),
59  
-			Instance.Output("eth_phy_clk_pad", pads.eth_phy_clk),
60  
-			Instance.Output("vga_clk_pad", pads.vga_clk),
61  
-
62  
-			Instance.Input("vga_progclk", ClockSignal()),
63  
-			Instance.Input("vga_progdata", vga_progdata),
64  
-			Instance.Input("vga_progen", vga_progen),
65  
-			Instance.Output("vga_progdone", vga_progdone),
66  
-			Instance.Output("vga_locked", vga_locked))
67  
-
68  
-		remaining_bits = Signal(max=11)
69  
-		transmitting = Signal()
70  
-		self.comb += transmitting.eq(remaining_bits != 0)
71  
-		sr = Signal(10)
72  
-		self.sync += [
73  
-			If(self._r_send_cmd_data.re,
74  
-				remaining_bits.eq(10),
75  
-				sr.eq(self._r_cmd_data.storage)
76  
-			).Elif(transmitting,
77  
-				remaining_bits.eq(remaining_bits - 1),
78  
-				sr.eq(sr[1:])
79  
-			)
80  
-		]
81  
-		self.comb += [
82  
-			vga_progdata.eq(transmitting & sr[0]),
83  
-			vga_progen.eq(transmitting | self._r_send_go.re)
84  
-		]
85  
-
86  
-		# enforce gap between commands
87  
-		busy_counter = Signal(max=14)
88  
-		busy = Signal()
89  
-		self.comb += busy.eq(busy_counter != 0)
90  
-		self.sync += If(self._r_send_cmd_data.re,
91  
-				busy_counter.eq(13)
92  
-			).Elif(busy,
93  
-				busy_counter.eq(busy_counter - 1)
94  
-			)
95  
-
96  
-		self.comb += self._r_status.status.eq(Cat(busy, vga_progdone, vga_locked))
  48
+			Instance.Output("eth_phy_clk_pad", pads.eth_phy_clk))
12  software/videomixer/fb.c
@@ -13,9 +13,9 @@ static void fb_clkgen_write(int cmd, int data)
13 13
 	int word;
14 14
 
15 15
 	word = (data << 2) | cmd;
16  
-	crg_cmd_data_write(word);
17  
-	crg_send_cmd_data_write(1);
18  
-	while(crg_status_read() & CLKGEN_STATUS_BUSY);
  16
+	fb_driver_clocking_cmd_data_write(word);
  17
+	fb_driver_clocking_send_cmd_data_write(1);
  18
+	while(fb_driver_clocking_status_read() & CLKGEN_STATUS_BUSY);
19 19
 }
20 20
 
21 21
 void fb_set_mode(int mode)
@@ -86,12 +86,12 @@ void fb_set_mode(int mode)
86 86
 
87 87
 	fb_clkgen_write(0x1, clock_d-1);
88 88
 	fb_clkgen_write(0x3, clock_m-1);
89  
-	crg_send_go_write(1);
  89
+	fb_driver_clocking_send_go_write(1);
90 90
 	printf("waiting for PROGDONE...");
91  
-	while(!(crg_status_read() & CLKGEN_STATUS_PROGDONE));
  91
+	while(!(fb_driver_clocking_status_read() & CLKGEN_STATUS_PROGDONE));
92 92
 	printf("ok\n");
93 93
 	printf("waiting for LOCKED...");
94  
-	while(!(crg_status_read() & CLKGEN_STATUS_LOCKED));
  94
+	while(!(fb_driver_clocking_status_read() & CLKGEN_STATUS_LOCKED));
95 95
 	printf("ok\n");
96 96
 
97 97
 	printf("VGA: mode set to %dx%d\n", fb_hres, fb_vres);
3  top.py
@@ -51,7 +51,6 @@ def __init__(self, platform):
51 51
 		except ConstraintError:
52 52
 			pass
53 53
 		self.norflash_rst_n = platform.request("norflash_rst_n")
54  
-		self.vga_clk = platform.request("vga_clock")
55 54
 		ddram_clock = platform.request("ddram_clock")
56 55
 		self.ddr_clk_p = ddram_clock.p
57 56
 		self.ddr_clk_n = ddram_clock.n
@@ -162,7 +161,7 @@ def __init__(self, platform, platform_name, with_memtest):
162 161
 		self.submodules.timer0 = timer.Timer()
163 162
 		if platform_name == "mixxeo":
164 163
 			self.submodules.leds = gpio.GPIOOut(platform.request("user_led"))
165  
-			self.submodules.fb = framebuffer.MixFramebuffer(platform.request("vga"), lasmim_fb0, lasmim_fb1)
  164
+			self.submodules.fb = framebuffer.MixFramebuffer(platform.request("vga_out"), None, lasmim_fb0, lasmim_fb1)
166 165
 			self.submodules.dvisampler0 = dvisampler.DVISampler(platform.request("dvi_in", 0), lasmim_dvi0)
167 166
 			self.submodules.dvisampler1 = dvisampler.DVISampler(platform.request("dvi_in", 1), lasmim_dvi1)
168 167
 		if platform_name == "m1":
60  verilog/mxcrg/mxcrg.v
@@ -31,16 +31,8 @@ module mxcrg #(
31 31
 	output eth_rx_clk,
32 32
 	output eth_tx_clk,
33 33
 	
34  
-	/* VGA clock */
35  
-	output vga_clk,		/* < buffered, to internal clock network */
36  
-	output vga_clk_pad,	/* < forwarded through ODDR2, to I/O */
37  
-
38  
-	/* VGA clock control */
39  
-	input vga_progclk,
40  
-	input vga_progdata,
41  
-	input vga_progen,
42  
-	output vga_progdone,
43  
-	output vga_locked
  34
+	/* Base clock, buffered */
  35
+	output base50_clk
44 36
 );
45 37
 
46 38
 /*
@@ -213,10 +205,10 @@ BUFG bufg_x1(
213 205
 	.O(sys_clk)
214 206
 );
215 207
 
216  
-wire clk50g;
  208
+wire base50_clk;
217 209
 BUFG bufg_50(
218 210
 	.I(pllout4),
219  
-	.O(clk50g)
  211
+	.O(base50_clk)
220 212
 );
221 213
 
222 214
 wire clk2x_off;
@@ -263,53 +255,11 @@ ODDR2 #(
263 255
  * Ethernet PHY 
264 256
  */
265 257
 
266  
-always @(posedge clk50g)
  258
+always @(posedge base50_clk)
267 259
 	eth_phy_clk_pad <= ~eth_phy_clk_pad;
268 260
 
269 261
 /* Let the synthesizer insert the appropriate buffers */
270 262
 assign eth_rx_clk = eth_rx_clk_pad;
271 263
 assign eth_tx_clk = eth_tx_clk_pad;
272  
-
273  
-/*
274  
- * VGA clock
275  
- */
276  
-
277  
-DCM_CLKGEN #(
278  
-	.CLKFXDV_DIVIDE(2),
279  
-	.CLKFX_DIVIDE(4),
280  
-	.CLKFX_MD_MAX(3.0),
281  
-	.CLKFX_MULTIPLY(2),
282  
-	.CLKIN_PERIOD(20.0),
283  
-	.SPREAD_SPECTRUM("NONE"),
284  
-	.STARTUP_WAIT("FALSE")
285  
-) vga_clock_gen (
286  
-	.CLKFX(vga_clk),
287  
-	.CLKFX180(),
288  
-	.CLKFXDV(),
289  
-	.STATUS(),
290  
-	.CLKIN(clk50g),
291  
-	.FREEZEDCM(1'b0),
292  
-	.PROGCLK(vga_progclk),
293  
-	.PROGDATA(vga_progdata),
294  
-	.PROGEN(vga_progen),
295  
-	.PROGDONE(vga_progdone),
296  
-	.LOCKED(vga_locked),
297  
-	.RST(~pll_lckd | sys_rst)
298  
-);
299  
-
300  
-ODDR2 #(
301  
-	.DDR_ALIGNMENT("NONE"),
302  
-	.INIT(1'b0),
303  
-	.SRTYPE("SYNC")
304  
-) vga_clock_forward (
305  
-	.Q(vga_clk_pad),
306  
-	.C0(vga_clk),
307  
-	.C1(~vga_clk),
308  
-	.CE(1'b1),
309  
-	.D0(1'b1),
310  
-	.D1(1'b0),
311  
-	.R(1'b0),
312  
-	.S(1'b0)
313  
-);
314 264
  
315 265
 endmodule

0 notes on commit e6e04a2

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