Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Use new module, autoreg and eventmanager Migen APIs

  • Loading branch information...
commit a9b723568a7d5b84859687a07b8283e22b12ea39 1 parent 2059592
Sébastien Bourdeauducq authored March 10, 2013
14  common/csrbase.h
... ...
@@ -1,12 +1,12 @@
1 1
 #ifndef __CSRBASE_H
2 2
 #define __CSRBASE_H
3 3
 
4  
-#define UART_BASE	0xe0000000
5  
-#define DFII_BASE	0xe0000800
6  
-#define ID_BASE		0xe0001000
7  
-#define TIMER0_BASE	0xe0001800
8  
-#define MINIMAC_BASE	0xe0002000
9  
-#define FB_BASE		0xe0002800
10  
-#define ASMIPROBE_BASE	0xe0003000
  4
+#define UART_BASE		0xe0000000
  5
+#define DFII_BASE		0xe0000800
  6
+#define IDENTIFIER_BASE		0xe0001000
  7
+#define TIMER0_BASE		0xe0001800
  8
+#define MINIMAC_BASE		0xe0002000
  9
+#define FB_BASE			0xe0002800
  10
+#define ASMIPROBE_BASE		0xe0003000
11 11
 
12 12
 #endif /* __CSRBASE_H */
26  milkymist/asmicon/__init__.py
... ...
@@ -1,4 +1,5 @@
1 1
 from migen.fhdl.structure import *
  2
+from migen.fhdl.module import Module
2 3
 from migen.bus import dfi, asmibus
3 4
 
4 5
 from milkymist.asmicon.refresher import *
@@ -34,13 +35,12 @@ def __init__(self, tRP, tRCD, tWR, tREFI, tRFC, CL, rd_delay, read_time, write_t
34 35
 		self.write_time = write_time
35 36
 		self.slot_time = slot_time
36 37
 
37  
-class ASMIcon:
  38
+class ASMIcon(Module):
38 39
 	def __init__(self, phy_settings, geom_settings, timing_settings, full_selector=False):
39 40
 		self.phy_settings = phy_settings
40 41
 		self.geom_settings = geom_settings
41 42
 		self.timing_settings = timing_settings
42 43
 		self.full_selector = full_selector
43  
-		self.finalized = False
44 44
 		
45 45
 		self.dfi = dfi.Interface(self.geom_settings.mux_a,
46 46
 			self.geom_settings.bank_a,
@@ -50,26 +50,14 @@ def __init__(self, phy_settings, geom_settings, timing_settings, full_selector=F
50 50
 		self.address_align = log2_int(burst_length)
51 51
 		aw = self.geom_settings.bank_a + self.geom_settings.row_a + self.geom_settings.col_a - self.address_align
52 52
 		dw = self.phy_settings.dfi_d*self.phy_settings.nphases
53  
-		self.hub = asmibus.Hub(aw, dw, self.timing_settings.slot_time)
  53
+		self.submodules.hub = asmibus.Hub(aw, dw, self.timing_settings.slot_time)
54 54
 	
55  
-	def finalize(self):
56  
-		if self.finalized:
57  
-			raise FinalizeError
58  
-		self.finalized = True
59  
-		self.hub.finalize()
  55
+	def do_finalize(self):
60 56
 		slots = self.hub.get_slots()
61  
-		self.refresher = Refresher(self.geom_settings.mux_a, self.geom_settings.bank_a,
  57
+		self.submodules.refresher = Refresher(self.geom_settings.mux_a, self.geom_settings.bank_a,
62 58
 			self.timing_settings.tRP, self.timing_settings.tREFI, self.timing_settings.tRFC)
63  
-		self.bank_machines = [BankMachine(self.geom_settings, self.timing_settings, self.address_align, i, slots, self.full_selector)
  59
+		self.submodules.bank_machines = [BankMachine(self.geom_settings, self.timing_settings, self.address_align, i, slots, self.full_selector)
64 60
 			for i in range(2**self.geom_settings.bank_a)]
65  
-		self.multiplexer = Multiplexer(self.phy_settings, self.geom_settings, self.timing_settings,
  61
+		self.submodules.multiplexer = Multiplexer(self.phy_settings, self.geom_settings, self.timing_settings,
66 62
 			self.bank_machines, self.refresher,
67 63
 			self.dfi, self.hub)
68  
-	
69  
-	def get_fragment(self):
70  
-		if not self.finalized:
71  
-			raise FinalizeError
72  
-		return self.hub.get_fragment() + \
73  
-			self.refresher.get_fragment() + \
74  
-			sum([bm.get_fragment() for bm in self.bank_machines], Fragment()) + \
75  
-			self.multiplexer.get_fragment()
185  milkymist/asmicon/bankmachine.py
... ...
@@ -1,4 +1,5 @@
1 1
 from migen.fhdl.structure import *
  2
+from migen.fhdl.module import Module
2 3
 from migen.bus.asmibus import *
3 4
 from migen.genlib.roundrobin import *
4 5
 from migen.genlib.fsm import FSM
@@ -33,97 +34,81 @@ def col(self, address):
33 34
 		else:
34 35
 			return Cat(Replicate(0, self.address_align), address[:self._b1])
35 36
 
36  
-class _Selector:
  37
+class _Selector(Module):
37 38
 	def __init__(self, slicer, bankn, slots):
38  
-		self.slicer = slicer
39  
-		self.bankn = bankn
40  
-		self.slots = slots
41  
-		
42  
-		self.nslots = len(self.slots)
  39
+		nslots = len(slots)
43 40
 		self.stb = Signal()
44 41
 		self.ack = Signal()
45  
-		self.tag = Signal(max=self.nslots)
46  
-		self.adr = Signal(self.slots[0].adr.nbits)
  42
+		self.tag = Signal(max=nslots)
  43
+		self.adr = Signal(slots[0].adr.nbits)
47 44
 		self.we = Signal()
48 45
 		
49 46
 		# derived classes should drive rr.request
50  
-		self.rr = RoundRobin(self.nslots, SP_CE)
  47
+		self.submodules.rr = RoundRobin(nslots, SP_CE)
51 48
 	
52  
-	def get_fragment(self):
53  
-		comb = []
54  
-		rr = self.rr
55  
-		
  49
+		###
  50
+
56 51
 		# Multiplex
  52
+		rr = self.rr
57 53
 		state = Signal(2)
58  
-		comb += [
59  
-			state.eq(Array(slot.state for slot in self.slots)[rr.grant]),
60  
-			self.adr.eq(Array(slot.adr for slot in self.slots)[rr.grant]),
61  
-			self.we.eq(Array(slot.we for slot in self.slots)[rr.grant]),
  54
+		self.comb += [
  55
+			state.eq(Array(slot.state for slot in slots)[rr.grant]),
  56
+			self.adr.eq(Array(slot.adr for slot in slots)[rr.grant]),
  57
+			self.we.eq(Array(slot.we for slot in slots)[rr.grant]),
62 58
 			self.stb.eq(
63  
-				(self.slicer.bank(self.adr) == self.bankn) \
  59
+				(slicer.bank(self.adr) == bankn) \
64 60
 				& (state == SLOT_PENDING)),
65 61
 			rr.ce.eq(self.ack | ~self.stb),
66 62
 			self.tag.eq(rr.grant)
67 63
 		]
68  
-		comb += [If((rr.grant == i) & self.stb & self.ack, slot.process.eq(1))
69  
-			for i, slot in enumerate(self.slots)]
70  
-			
71  
-		return Fragment(comb) + rr.get_fragment()
  64
+		self.comb += [If((rr.grant == i) & self.stb & self.ack, slot.process.eq(1))
  65
+			for i, slot in enumerate(slots)]
  66
+
  67
+		self.complete_selector(slicer, bankn, slots)
72 68
 
73 69
 class _SimpleSelector(_Selector):
74  
-	def get_fragment(self):
75  
-		comb = []
76  
-		for i, slot in enumerate(self.slots):
77  
-			comb.append(self.rr.request[i].eq(
78  
-				(self.slicer.bank(slot.adr) == self.bankn) & \
79  
-				(slot.state == SLOT_PENDING)
80  
-			))
81  
-	
82  
-		return Fragment(comb) + _Selector.get_fragment(self)
  70
+	def complete_selector(self, slicer, bankn, slots):
  71
+		for i, slot in enumerate(slots):
  72
+			self.comb += self.rr.request[i].eq(
  73
+				(slicer.bank(slot.adr) == bankn) & \
  74
+				(slot.state == SLOT_PENDING))
83 75
 
84 76
 class _FullSelector(_Selector):
85  
-	def get_fragment(self):
86  
-		comb = []
87  
-		sync = []
  77
+	def complete_selector(self, slicer, bankn, slots):
88 78
 		rr = self.rr
89 79
 
90 80
 		# List outstanding requests for our bank
91 81
 		outstandings = []
92  
-		for slot in self.slots:
  82
+		for slot in slots:
93 83
 			outstanding = Signal()
94  
-			comb.append(outstanding.eq(
95  
-				(self.slicer.bank(slot.adr) == self.bankn) & \
96  
-				(slot.state == SLOT_PENDING)
97  
-			))
  84
+			self.comb += outstanding.eq(
  85
+				(slicer.bank(slot.adr) == bankn) & \
  86
+				(slot.state == SLOT_PENDING))
98 87
 			outstandings.append(outstanding)
99 88
 		
100 89
 		# Row tracking
101  
-		openrow_r = Signal(self.slicer.geom_settings.row_a)
102  
-		openrow_n = Signal(self.slicer.geom_settings.row_a)
103  
-		openrow = Signal(self.slicer.geom_settings.row_a)
104  
-		comb += [
105  
-			openrow_n.eq(self.slicer.row(self.adr)),
  90
+		openrow_r = Signal(slicer.geom_settings.row_a)
  91
+		openrow_n = Signal(slicer.geom_settings.row_a)
  92
+		openrow = Signal(slicer.geom_settings.row_a)
  93
+		self.comb += [
  94
+			openrow_n.eq(slicer.row(self.adr)),
106 95
 			If(self.stb,
107 96
 				openrow.eq(openrow_n)
108 97
 			).Else(
109 98
 				openrow.eq(openrow_r)
110 99
 			)
111 100
 		]
112  
-		sync += [
113  
-			If(self.stb & self.ack,
114  
-				openrow_r.eq(openrow_n)
115  
-			)
116  
-		]
  101
+		self.sync += If(self.stb & self.ack, openrow_r.eq(openrow_n))
117 102
 		hits = []
118  
-		for slot, os in zip(self.slots, outstandings):
  103
+		for slot, os in zip(slots, outstandings):
119 104
 			hit = Signal()
120  
-			comb.append(hit.eq((self.slicer.row(slot.adr) == openrow) & os))
  105
+			self.comb += hit.eq((slicer.row(slot.adr) == openrow) & os)
121 106
 			hits.append(hit)
122 107
 		
123 108
 		# Determine best request
124 109
 		rr = RoundRobin(self.nslots, SP_CE)
125 110
 		has_hit = Signal()
126  
-		comb.append(has_hit.eq(optree("|", hits)))
  111
+		self.comb += has_hit.eq(optree("|", hits))
127 112
 		
128 113
 		best_hit = [rr.request[i].eq(hit)
129 114
 			for i, hit in enumerate(hits)]
@@ -135,84 +120,72 @@ def get_fragment(self):
135 120
 				*best_fallback
136 121
 			)
137 122
 		
138  
-		if self.slots[0].time:
  123
+		if slots[0].time:
139 124
 			# Implement anti-starvation timer
140 125
 			matures = []
141  
-			for slot, os in zip(self.slots, outstandings):
  126
+			for slot, os in zip(slots, outstandings):
142 127
 				mature = Signal()
143 128
 				comb.append(mature.eq(slot.mature & os))
144 129
 				matures.append(mature)
145 130
 			has_mature = Signal()
146  
-			comb.append(has_mature.eq(optree("|", matures)))
  131
+			self.comb += has_mature.eq(optree("|", matures))
147 132
 			best_mature = [rr.request[i].eq(mature)
148 133
 				for i, mature in enumerate(matures)]
149 134
 			select_stmt = If(has_mature, *best_mature).Else(select_stmt)
150  
-		comb.append(select_stmt)
151  
-		
152  
-		return Fragment(comb, sync) + _Selector.get_fragment(self)
  135
+		self.comb += select_stmt
153 136
 
154  
-class _Buffer:
  137
+class _Buffer(Module):
155 138
 	def __init__(self, source):
156  
-		self.source = source
157  
-		
158 139
 		self.stb = Signal()
159 140
 		self.ack = Signal()
160  
-		self.tag = Signal(self.source.tag.bv)
161  
-		self.adr = Signal(self.source.adr.bv)
  141
+		self.tag = Signal(source.tag.bv)
  142
+		self.adr = Signal(source.adr.bv)
162 143
 		self.we = Signal()
163 144
 	
164  
-	def get_fragment(self):
  145
+		###
  146
+
165 147
 		en = Signal()
166  
-		comb = [
  148
+		self.comb += [
167 149
 			en.eq(self.ack | ~self.stb),
168  
-			self.source.ack.eq(en)
  150
+			source.ack.eq(en)
169 151
 		]
170  
-		sync = [
  152
+		self.sync += [
171 153
 			If(en,
172  
-				self.stb.eq(self.source.stb),
173  
-				self.tag.eq(self.source.tag),
174  
-				self.adr.eq(self.source.adr),
175  
-				self.we.eq(self.source.we)
  154
+				self.stb.eq(source.stb),
  155
+				self.tag.eq(source.tag),
  156
+				self.adr.eq(source.adr),
  157
+				self.we.eq(source.we)
176 158
 			)
177 159
 		]
178  
-		return Fragment(comb, sync)
179 160
 	
180  
-class BankMachine:
  161
+class BankMachine(Module):
181 162
 	def __init__(self, geom_settings, timing_settings, address_align, bankn, slots, full_selector):
182  
-		self.geom_settings = geom_settings
183  
-		self.timing_settings = timing_settings
184  
-		self.address_align = address_align
185  
-		self.bankn = bankn
186  
-		self.slots = slots
187  
-		self.full_selector = full_selector
188  
-		
189 163
 		self.refresh_req = Signal()
190 164
 		self.refresh_gnt = Signal()
191 165
 		self.cmd = CommandRequestRW(geom_settings.mux_a, geom_settings.bank_a,
192 166
 			bits_for(len(slots)-1))
193 167
 
194  
-	def get_fragment(self):
195  
-		comb = []
196  
-		sync = []
197  
-		
  168
+		###
  169
+
198 170
 		# Sub components
199  
-		slicer = _AddressSlicer(self.geom_settings, self.address_align)
200  
-		if self.full_selector:
201  
-			selector = _FullSelector(slicer, self.bankn, self.slots)
202  
-			buf = _Buffer(selector)
203  
-			cmdsource = buf
  171
+		slicer = _AddressSlicer(geom_settings, address_align)
  172
+		if full_selector:
  173
+			selector = _FullSelector(slicer, bankn, slots)
  174
+			self.submodules.buf = _Buffer(selector)
  175
+			cmdsource = self.buf
204 176
 		else:
205  
-			selector = _SimpleSelector(slicer, self.bankn, self.slots)
  177
+			selector = _SimpleSelector(slicer, bankn, slots)
206 178
 			cmdsource = selector
  179
+		self.submodules += selector
207 180
 		
208 181
 		# Row tracking
209 182
 		has_openrow = Signal()
210  
-		openrow = Signal(self.geom_settings.row_a)
  183
+		openrow = Signal(geom_settings.row_a)
211 184
 		hit = Signal()
212  
-		comb.append(hit.eq(openrow == slicer.row(cmdsource.adr)))
  185
+		self.comb += hit.eq(openrow == slicer.row(cmdsource.adr))
213 186
 		track_open = Signal()
214 187
 		track_close = Signal()
215  
-		sync += [
  188
+		self.sync += [
216 189
 			If(track_open,
217 190
 				has_openrow.eq(1),
218 191
 				openrow.eq(slicer.row(cmdsource.adr))
@@ -224,8 +197,8 @@ def get_fragment(self):
224 197
 		
225 198
 		# Address generation
226 199
 		s_row_adr = Signal()
227  
-		comb += [
228  
-			self.cmd.ba.eq(self.bankn),
  200
+		self.comb += [
  201
+			self.cmd.ba.eq(bankn),
229 202
 			If(s_row_adr,
230 203
 				self.cmd.a.eq(slicer.row(cmdsource.adr))
231 204
 			).Else(
@@ -233,14 +206,14 @@ def get_fragment(self):
233 206
 			)
234 207
 		]
235 208
 		
236  
-		comb.append(self.cmd.tag.eq(cmdsource.tag))
  209
+		self.comb += self.cmd.tag.eq(cmdsource.tag)
237 210
 		
238 211
 		# Respect write-to-precharge specification
239 212
 		precharge_ok = Signal()
240  
-		t_unsafe_precharge = 2 + self.timing_settings.tWR - 1
  213
+		t_unsafe_precharge = 2 + timing_settings.tWR - 1
241 214
 		unsafe_precharge_count = Signal(max=t_unsafe_precharge+1)
242  
-		comb.append(precharge_ok.eq(unsafe_precharge_count == 0))
243  
-		sync += [
  215
+		self.comb += precharge_ok.eq(unsafe_precharge_count == 0)
  216
+		self.sync += [
244 217
 			If(self.cmd.stb & self.cmd.ack & self.cmd.is_write,
245 218
 				unsafe_precharge_count.eq(t_unsafe_precharge)
246 219
 			).Elif(~precharge_ok,
@@ -250,9 +223,10 @@ def get_fragment(self):
250 223
 		
251 224
 		# Control and command generation FSM
252 225
 		fsm = FSM("REGULAR", "PRECHARGE", "ACTIVATE", "REFRESH", delayed_enters=[
253  
-			("TRP", "ACTIVATE", self.timing_settings.tRP-1),
254  
-			("TRCD", "REGULAR", self.timing_settings.tRCD-1)
  226
+			("TRP", "ACTIVATE", timing_settings.tRP-1),
  227
+			("TRCD", "REGULAR", timing_settings.tRCD-1)
255 228
 		])
  229
+		self.submodules += fsm
256 230
 		fsm.act(fsm.REGULAR,
257 231
 			If(self.refresh_req,
258 232
 				fsm.next_state(fsm.REFRESH)
@@ -298,12 +272,3 @@ def get_fragment(self):
298 272
 			track_close.eq(1),
299 273
 			If(~self.refresh_req, fsm.next_state(fsm.REGULAR))
300 274
 		)
301  
-		
302  
-		if self.full_selector:
303  
-			buf_fragment = buf.get_fragment()
304  
-		else:
305  
-			buf_fragment = Fragment()
306  
-		return Fragment(comb, sync) + \
307  
-			selector.get_fragment() + \
308  
-			buf_fragment + \
309  
-			fsm.get_fragment()
208  milkymist/asmicon/multiplexer.py
... ...
@@ -1,4 +1,5 @@
1 1
 from migen.fhdl.structure import *
  2
+from migen.fhdl.module import Module
2 3
 from migen.genlib.roundrobin import *
3 4
 from migen.genlib.misc import optree
4 5
 from migen.genlib.fsm import FSM
@@ -20,171 +21,141 @@ def __init__(self, a, ba, tagbits):
20 21
 		self.is_write = Signal()
21 22
 		self.tag = Signal(tagbits)
22 23
 
23  
-class _CommandChooser:
  24
+class _CommandChooser(Module):
24 25
 	def __init__(self, requests, tagbits):
25  
-		self.requests = requests
26  
-		
27 26
 		self.want_reads = Signal()
28 27
 		self.want_writes = Signal()
29 28
 		# NB: cas_n/ras_n/we_n are 1 when stb is inactive
30  
-		self.cmd = CommandRequestRW(len(self.requests[0].a), len(self.requests[0].ba), tagbits)
  29
+		self.cmd = CommandRequestRW(len(requests[0].a), len(requests[0].ba), tagbits)
31 30
 	
32  
-	def get_fragment(self):
33  
-		comb = []
34  
-		sync = []
35  
-		
36  
-		rr = RoundRobin(len(self.requests), SP_CE)
  31
+		###
  32
+
  33
+		rr = RoundRobin(len(requests), SP_CE)
  34
+		self.submodules += rr
37 35
 		
38  
-		comb += [rr.request[i].eq(req.stb & ((req.is_read == self.want_reads) | (req.is_write == self.want_writes)))
39  
-			for i, req in enumerate(self.requests)]
  36
+		self.comb += [rr.request[i].eq(req.stb & ((req.is_read == self.want_reads) | (req.is_write == self.want_writes)))
  37
+			for i, req in enumerate(requests)]
40 38
 		
41 39
 		stb = Signal()
42  
-		comb.append(stb.eq(Array(req.stb for req in self.requests)[rr.grant]))
  40
+		self.comb += stb.eq(Array(req.stb for req in requests)[rr.grant])
43 41
 		for name in ["a", "ba", "is_read", "is_write", "tag"]:
44  
-			choices = Array(getattr(req, name) for req in self.requests)
45  
-			comb.append(getattr(self.cmd, name).eq(choices[rr.grant]))
  42
+			choices = Array(getattr(req, name) for req in requests)
  43
+			self.comb += getattr(self.cmd, name).eq(choices[rr.grant])
46 44
 		for name in ["cas_n", "ras_n", "we_n"]:
47 45
 			# we should only assert those signals when stb is 1
48  
-			choices = Array(getattr(req, name) for req in self.requests)
49  
-			comb.append(If(self.cmd.stb, getattr(self.cmd, name).eq(choices[rr.grant])))
50  
-		comb.append(self.cmd.stb.eq(stb \
  46
+			choices = Array(getattr(req, name) for req in requests)
  47
+			self.comb += If(self.cmd.stb, getattr(self.cmd, name).eq(choices[rr.grant]))
  48
+		self.comb += self.cmd.stb.eq(stb \
51 49
 			& (self.cmd.is_read == self.want_reads) \
52  
-			& (self.cmd.is_write == self.want_writes)))
  50
+			& (self.cmd.is_write == self.want_writes))
53 51
 		
54  
-		comb += [If(self.cmd.stb & self.cmd.ack & (rr.grant == i), req.ack.eq(1))
55  
-			for i, req in enumerate(self.requests)]
56  
-		comb.append(rr.ce.eq(self.cmd.ack))
57  
-		
58  
-		return Fragment(comb, sync) + rr.get_fragment()
  52
+		self.comb += [If(self.cmd.stb & self.cmd.ack & (rr.grant == i), req.ack.eq(1))
  53
+			for i, req in enumerate(requests)]
  54
+		self.comb += rr.ce.eq(self.cmd.ack)
59 55
 
60  
-class _Steerer:
  56
+class _Steerer(Module):
61 57
 	def __init__(self, commands, dfi):
62  
-		self.commands = commands
63  
-		self.dfi = dfi
64  
-		
65  
-		ncmd = len(self.commands)
66  
-		nph = len(self.dfi.phases)
  58
+		ncmd = len(commands)
  59
+		nph = len(dfi.phases)
67 60
 		self.sel = [Signal(max=ncmd) for i in range(nph)]
68 61
 	
69  
-	def get_fragment(self):
70  
-		comb = []
71  
-		sync = []
  62
+		###
  63
+	
72 64
 		def stb_and(cmd, attr):
73 65
 			if not hasattr(cmd, "stb"):
74 66
 				return 0
75 67
 			else:
76 68
 				return cmd.stb & getattr(cmd, attr)
77  
-		for phase, sel in zip(self.dfi.phases, self.sel):
78  
-			comb += [
  69
+		for phase, sel in zip(dfi.phases, self.sel):
  70
+			self.comb += [
79 71
 				phase.cke.eq(1),
80 72
 				phase.cs_n.eq(0)
81 73
 			]
82  
-			sync += [
83  
-				phase.address.eq(Array(cmd.a for cmd in self.commands)[sel]),
84  
-				phase.bank.eq(Array(cmd.ba for cmd in self.commands)[sel]),
85  
-				phase.cas_n.eq(Array(cmd.cas_n for cmd in self.commands)[sel]),
86  
-				phase.ras_n.eq(Array(cmd.ras_n for cmd in self.commands)[sel]),
87  
-				phase.we_n.eq(Array(cmd.we_n for cmd in self.commands)[sel]),
88  
-				phase.rddata_en.eq(Array(stb_and(cmd, "is_read") for cmd in self.commands)[sel]),
89  
-				phase.wrdata_en.eq(Array(stb_and(cmd, "is_write") for cmd in self.commands)[sel])
  74
+			self.sync += [
  75
+				phase.address.eq(Array(cmd.a for cmd in commands)[sel]),
  76
+				phase.bank.eq(Array(cmd.ba for cmd in commands)[sel]),
  77
+				phase.cas_n.eq(Array(cmd.cas_n for cmd in commands)[sel]),
  78
+				phase.ras_n.eq(Array(cmd.ras_n for cmd in commands)[sel]),
  79
+				phase.we_n.eq(Array(cmd.we_n for cmd in commands)[sel]),
  80
+				phase.rddata_en.eq(Array(stb_and(cmd, "is_read") for cmd in commands)[sel]),
  81
+				phase.wrdata_en.eq(Array(stb_and(cmd, "is_write") for cmd in commands)[sel])
90 82
 			]
91  
-		return Fragment(comb, sync)
92 83
 
93  
-class _Datapath:
  84
+class _Datapath(Module):
94 85
 	def __init__(self, timing_settings, command, dfi, hub):
95  
-		self.timing_settings = timing_settings
96  
-		self.command = command
97  
-		self.dfi = dfi
98  
-		self.hub = hub
99  
-	
100  
-	def get_fragment(self):
101  
-		comb = []
102  
-		sync = []
103  
-		tagbits = len(self.hub.tag_call)
  86
+		tagbits = len(hub.tag_call)
104 87
 		
105 88
 		rd_valid = Signal()
106 89
 		rd_tag = Signal(tagbits)
107 90
 		wr_valid = Signal()
108 91
 		wr_tag = Signal(tagbits)
109  
-		comb += [
110  
-			self.hub.call.eq(rd_valid | wr_valid),
  92
+		self.comb += [
  93
+			hub.call.eq(rd_valid | wr_valid),
111 94
 			If(wr_valid,
112  
-				self.hub.tag_call.eq(wr_tag)
  95
+				hub.tag_call.eq(wr_tag)
113 96
 			).Else(
114  
-				self.hub.tag_call.eq(rd_tag)
  97
+				hub.tag_call.eq(rd_tag)
115 98
 			)
116 99
 		]
117 100
 		
118  
-		rd_delay = self.timing_settings.rd_delay + 1
  101
+		rd_delay = timing_settings.rd_delay + 1
119 102
 		rd_valid_d = [Signal() for i in range(rd_delay)]
120 103
 		rd_tag_d = [Signal(tagbits) for i in range(rd_delay)]
121 104
 		for i in range(rd_delay):
122 105
 			if i:
123  
-				sync += [
  106
+				self.sync += [
124 107
 					rd_valid_d[i].eq(rd_valid_d[i-1]),
125 108
 					rd_tag_d[i].eq(rd_tag_d[i-1])
126 109
 				]
127 110
 			else:
128  
-				sync += [
129  
-					rd_valid_d[i].eq(self.command.stb & self.command.ack & self.command.is_read),
130  
-					rd_tag_d[i].eq(self.command.tag)
  111
+				self.sync += [
  112
+					rd_valid_d[i].eq(command.stb & command.ack & command.is_read),
  113
+					rd_tag_d[i].eq(command.tag)
131 114
 				]		
132  
-		comb += [
  115
+		self.comb += [
133 116
 			rd_valid.eq(rd_valid_d[-1]),
134 117
 			rd_tag.eq(rd_tag_d[-1]),
135  
-			wr_valid.eq(self.command.stb & self.command.ack & self.command.is_write),
136  
-			wr_tag.eq(self.command.tag),
  118
+			wr_valid.eq(command.stb & command.ack & command.is_write),
  119
+			wr_tag.eq(command.tag),
137 120
 		]
138 121
 		
139  
-		all_rddata = [p.rddata for p in self.dfi.phases]
140  
-		all_wrdata = [p.wrdata for p in self.dfi.phases]
141  
-		all_wrdata_mask = [p.wrdata_mask for p in self.dfi.phases]
142  
-		comb += [
143  
-			self.hub.dat_r.eq(Cat(*all_rddata)),
144  
-			Cat(*all_wrdata).eq(self.hub.dat_w),
145  
-			Cat(*all_wrdata_mask).eq(self.hub.dat_wm)
  122
+		all_rddata = [p.rddata for p in dfi.phases]
  123
+		all_wrdata = [p.wrdata for p in dfi.phases]
  124
+		all_wrdata_mask = [p.wrdata_mask for p in dfi.phases]
  125
+		self.comb += [
  126
+			hub.dat_r.eq(Cat(*all_rddata)),
  127
+			Cat(*all_wrdata).eq(hub.dat_w),
  128
+			Cat(*all_wrdata_mask).eq(hub.dat_wm)
146 129
 		]
147  
-		
148  
-		return Fragment(comb, sync)
149 130
 
150  
-class Multiplexer:
  131
+class Multiplexer(Module):
151 132
 	def __init__(self, phy_settings, geom_settings, timing_settings, bank_machines, refresher, dfi, hub):
152  
-		self.phy_settings = phy_settings
153  
-		self.geom_settings = geom_settings
154  
-		self.timing_settings = timing_settings
155  
-		self.bank_machines = bank_machines
156  
-		self.refresher = refresher
157  
-		self.dfi = dfi
158  
-		self.hub = hub
159  
-		
160  
-		assert(self.phy_settings.nphases == len(dfi.phases))
161  
-		if self.phy_settings.nphases != 2:
  133
+		assert(phy_settings.nphases == len(dfi.phases))
  134
+		if phy_settings.nphases != 2:
162 135
 			raise NotImplementedError("TODO: multiplexer only supports 2 phases")
163 136
 	
164  
-	def get_fragment(self):
165  
-		comb = []
166  
-		sync = []
167  
-		
168 137
 		# Command choosing
169  
-		requests = [bm.cmd for bm in self.bank_machines]
170  
-		tagbits = len(self.hub.tag_call)
  138
+		requests = [bm.cmd for bm in bank_machines]
  139
+		tagbits = len(hub.tag_call)
171 140
 		choose_cmd = _CommandChooser(requests, tagbits)
172 141
 		choose_req = _CommandChooser(requests, tagbits)
173  
-		comb += [
  142
+		self.comb += [
174 143
 			choose_cmd.want_reads.eq(0),
175 144
 			choose_cmd.want_writes.eq(0)
176 145
 		]
  146
+		self.submodules += choose_cmd, choose_req
177 147
 		
178 148
 		# Command steering
179  
-		nop = CommandRequest(self.geom_settings.mux_a, self.geom_settings.bank_a)
180  
-		commands = [nop, choose_cmd.cmd, choose_req.cmd, self.refresher.cmd] # nop must be 1st
  149
+		nop = CommandRequest(geom_settings.mux_a, geom_settings.bank_a)
  150
+		commands = [nop, choose_cmd.cmd, choose_req.cmd, refresher.cmd] # nop must be 1st
181 151
 		(STEER_NOP, STEER_CMD, STEER_REQ, STEER_REFRESH) = range(4)
182  
-		steerer = _Steerer(commands, self.dfi)
  152
+		steerer = _Steerer(commands, dfi)
  153
+		self.submodules += steerer
183 154
 		
184 155
 		# Read/write turnaround
185 156
 		read_available = Signal()
186 157
 		write_available = Signal()
187  
-		comb += [
  158
+		self.comb += [
188 159
 			read_available.eq(optree("|", [req.stb & req.is_read for req in requests])),
189 160
 			write_available.eq(optree("|", [req.stb & req.is_write for req in requests]))
190 161
 		]
@@ -195,42 +166,40 @@ def anti_starvation(timeout):
195 166
 			if timeout:
196 167
 				t = timeout - 1
197 168
 				time = Signal(max=t+1)
198  
-				comb.append(max_time.eq(time == 0))
199  
-				sync.append(
200  
-					If(~en,
  169
+				self.comb += max_time.eq(time == 0)
  170
+				self.sync += If(~en,
201 171
 						time.eq(t)
202 172
 					).Elif(~max_time,
203 173
 						time.eq(time - 1)
204 174
 					)
205  
-				)
206 175
 			else:
207  
-				comb.append(max_time.eq(0))
  176
+				self.comb += max_time.eq(0)
208 177
 			return en, max_time
209  
-		read_time_en, max_read_time = anti_starvation(self.timing_settings.read_time)
210  
-		write_time_en, max_write_time = anti_starvation(self.timing_settings.write_time)
  178
+		read_time_en, max_read_time = anti_starvation(timing_settings.read_time)
  179
+		write_time_en, max_write_time = anti_starvation(timing_settings.write_time)
211 180
 		
212 181
 		# Refresh
213  
-		comb += [bm.refresh_req.eq(self.refresher.req)
214  
-			for bm in self.bank_machines]
  182
+		self.comb += [bm.refresh_req.eq(refresher.req) for bm in bank_machines]
215 183
 		go_to_refresh = Signal()
216  
-		comb.append(go_to_refresh.eq(
217  
-			optree("&", [bm.refresh_gnt for bm in self.bank_machines])))
  184
+		self.comb += go_to_refresh.eq(optree("&", [bm.refresh_gnt for bm in bank_machines]))
218 185
 		
219 186
 		# Datapath
220  
-		datapath = _Datapath(self.timing_settings, choose_req.cmd, self.dfi, self.hub)
  187
+		datapath = _Datapath(timing_settings, choose_req.cmd, dfi, hub)
  188
+		self.submodules += datapath
221 189
 		
222 190
 		# Control FSM
223 191
 		fsm = FSM("READ", "WRITE", "REFRESH", delayed_enters=[
224  
-			("RTW", "WRITE", self.timing_settings.rd_delay),
225  
-			("WTR", "READ", self.timing_settings.tWR)
  192
+			("RTW", "WRITE", timing_settings.rd_delay),
  193
+			("WTR", "READ", timing_settings.tWR)
226 194
 		])
  195
+		self.submodules += fsm
227 196
 		fsm.act(fsm.READ,
228 197
 			read_time_en.eq(1),
229 198
 			choose_req.want_reads.eq(1),
230 199
 			choose_cmd.cmd.ack.eq(1),
231 200
 			choose_req.cmd.ack.eq(1),
232  
-			steerer.sel[1-self.phy_settings.rdphase].eq(STEER_CMD),
233  
-			steerer.sel[self.phy_settings.rdphase].eq(STEER_REQ),
  201
+			steerer.sel[1-phy_settings.rdphase].eq(STEER_CMD),
  202
+			steerer.sel[phy_settings.rdphase].eq(STEER_REQ),
234 203
 			If(write_available,
235 204
 				# TODO: switch only after several cycles of ~read_available?
236 205
 				If(~read_available | max_read_time, fsm.next_state(fsm.RTW))
@@ -242,8 +211,8 @@ def anti_starvation(timeout):
242 211
 			choose_req.want_writes.eq(1),
243 212
 			choose_cmd.cmd.ack.eq(1),
244 213
 			choose_req.cmd.ack.eq(1),
245  
-			steerer.sel[1-self.phy_settings.wrphase].eq(STEER_CMD),
246  
-			steerer.sel[self.phy_settings.wrphase].eq(STEER_REQ),
  214
+			steerer.sel[1-phy_settings.wrphase].eq(STEER_CMD),
  215
+			steerer.sel[phy_settings.wrphase].eq(STEER_REQ),
247 216
 			If(read_available,
248 217
 				If(~write_available | max_write_time, fsm.next_state(fsm.WTR))
249 218
 			),
@@ -251,14 +220,7 @@ def anti_starvation(timeout):
251 220
 		)
252 221
 		fsm.act(fsm.REFRESH,
253 222
 			steerer.sel[0].eq(STEER_REFRESH),
254  
-			If(~self.refresher.req, fsm.next_state(fsm.READ))
  223
+			If(~refresher.req, fsm.next_state(fsm.READ))
255 224
 		)
256 225
 		# FIXME: workaround for zero-delay loop simulation problem with Icarus Verilog
257  
-		comb.append(self.refresher.ack.eq(fsm._state == fsm.REFRESH))
258  
-		
259  
-		return Fragment(comb, sync) + \
260  
-			choose_cmd.get_fragment() + \
261  
-			choose_req.get_fragment() + \
262  
-			steerer.get_fragment() + \
263  
-			datapath.get_fragment() + \
264  
-			fsm.get_fragment()
  226
+		self.comb += refresher.ack.eq(fsm._state == fsm.REFRESH)
30  milkymist/asmicon/refresher.py
... ...
@@ -1,28 +1,23 @@
1 1
 from migen.fhdl.structure import *
  2
+from migen.fhdl.module import Module
2 3
 from migen.genlib.misc import timeline
3 4
 from migen.genlib.fsm import FSM
4 5
 
5 6
 from milkymist.asmicon.multiplexer import *
6 7
 
7  
-class Refresher:
  8
+class Refresher(Module):
8 9
 	def __init__(self, a, ba, tRP, tREFI, tRFC):
9  
-		self.tRP = tRP
10  
-		self.tREFI = tREFI
11  
-		self.tRFC = tRFC
12  
-		
13 10
 		self.req = Signal()
14 11
 		self.ack = Signal() # 1st command 1 cycle after assertion of ack
15 12
 		self.cmd = CommandRequest(a, ba)
16 13
 	
17  
-	def get_fragment(self):
18  
-		comb = []
19  
-		sync = []
20  
-		
  14
+		###
  15
+
21 16
 		# Refresh sequence generator:
22 17
 		# PRECHARGE ALL --(tRP)--> AUTO REFRESH --(tRFC)--> done
23 18
 		seq_start = Signal()
24 19
 		seq_done = Signal()
25  
-		sync += [
  20
+		self.sync += [
26 21
 			self.cmd.a.eq(2**10),
27 22
 			self.cmd.ba.eq(0),
28 23
 			self.cmd.cas_n.eq(1),
@@ -30,28 +25,28 @@ def get_fragment(self):
30 25
 			self.cmd.we_n.eq(1),
31 26
 			seq_done.eq(0)
32 27
 		]
33  
-		sync += timeline(seq_start, [
  28
+		self.sync += timeline(seq_start, [
34 29
 			(1, [
35 30
 				self.cmd.ras_n.eq(0),
36 31
 				self.cmd.we_n.eq(0)
37 32
 			]),
38  
-			(1+self.tRP, [
  33
+			(1+tRP, [
39 34
 				self.cmd.cas_n.eq(0),
40 35
 				self.cmd.ras_n.eq(0)
41 36
 			]),
42  
-			(1+self.tRP+self.tRFC, [
  37
+			(1+tRP+tRFC, [
43 38
 				seq_done.eq(1)
44 39
 			])
45 40
 		])
46 41
 		
47 42
 		# Periodic refresh counter
48  
-		counter = Signal(max=self.tREFI)
  43
+		counter = Signal(max=tREFI)
49 44
 		start = Signal()
50  
-		sync += [
  45
+		self.sync += [
51 46
 			start.eq(0),
52 47
 			If(counter == 0,
53 48
 				start.eq(1),
54  
-				counter.eq(self.tREFI - 1)
  49
+				counter.eq(tREFI - 1)
55 50
 			).Else(
56 51
 				counter.eq(counter - 1)
57 52
 			)
@@ -59,6 +54,7 @@ def get_fragment(self):
59 54
 		
60 55
 		# Control FSM
61 56
 		fsm = FSM("IDLE", "WAIT_GRANT", "WAIT_SEQ")
  57
+		self.submodules += fsm
62 58
 		fsm.act(fsm.IDLE, If(start, fsm.next_state(fsm.WAIT_GRANT)))
63 59
 		fsm.act(fsm.WAIT_GRANT,
64 60
 			self.req.eq(1),
@@ -71,5 +67,3 @@ def get_fragment(self):
71 67
 			self.req.eq(1),
72 68
 			If(seq_done, fsm.next_state(fsm.IDLE))
73 69
 		)
74  
-		
75  
-		return Fragment(comb, sync) + fsm.get_fragment()
43  milkymist/asmiprobe/__init__.py
... ...
@@ -1,36 +1,33 @@
1 1
 from migen.fhdl.structure import *
  2
+from migen.fhdl.module import Module
2 3
 from migen.bank.description import *
3  
-from migen.bank import csrgen
4 4
 
5  
-class ASMIprobe:
6  
-	def __init__(self, address, hub, trace_depth=16):
7  
-		self.hub = hub
8  
-		self.trace_depth = trace_depth
9  
-		
10  
-		slot_count = len(self.hub.get_slots())
11  
-		assert(self.trace_depth < 256)
  5
+class ASMIprobe(Module):
  6
+	def __init__(self, hub, trace_depth=16):
  7
+		slots = hub.get_slots()
  8
+		slot_count = len(slots)
  9
+		assert(trace_depth < 256)
12 10
 		assert(slot_count < 256)
13 11
 		
14 12
 		self._slot_count = RegisterField("slot_count", 8, access_bus=READ_ONLY, access_dev=WRITE_ONLY)
15 13
 		self._trace_depth = RegisterField("trace_depth", 8, access_bus=READ_ONLY, access_dev=WRITE_ONLY)
16  
-		self._slot_status = [RegisterField("slot_status", 2, access_bus=READ_ONLY, access_dev=WRITE_ONLY)
  14
+		self._slot_status = [RegisterField("slot_status" + str(i), 2, access_bus=READ_ONLY, access_dev=WRITE_ONLY)
17 15
 			for i in range(slot_count)]
18  
-		self._trace = [RegisterField("trace", 8, access_bus=READ_ONLY, access_dev=WRITE_ONLY)
19  
-			for i in range(self.trace_depth)]
  16
+		self._trace = [RegisterField("trace" + str(i), 8, access_bus=READ_ONLY, access_dev=WRITE_ONLY)
  17
+			for i in range(trace_depth)]
20 18
 
21  
-		self.bank = csrgen.Bank([self._slot_count, self._trace_depth]
22  
-			+ self._slot_status + self._trace, address=address)
23  
-	
24  
-	def get_fragment(self):
25  
-		slots = self.hub.get_slots()
26  
-		comb = [
27  
-			self._slot_count.field.w.eq(len(slots)),
28  
-			self._trace_depth.field.w.eq(self.trace_depth)
  19
+		###
  20
+		
  21
+		self.comb += [
  22
+			self._slot_count.field.w.eq(slot_count),
  23
+			self._trace_depth.field.w.eq(trace_depth)
29 24
 		]
30 25
 		for slot, status in zip(slots, self._slot_status):
31  
-			comb.append(status.field.w.eq(slot.state))
  26
+			self.comb += status.field.w.eq(slot.state)
32 27
 		shift_tags = [self._trace[n].field.w.eq(self._trace[n+1].field.w)
33 28
 			for n in range(len(self._trace) - 1)]
34  
-		shift_tags.append(self._trace[-1].field.w.eq(self.hub.tag_call))
35  
-		sync = [If(self.hub.call, *shift_tags)]
36  
-		return Fragment(comb, sync) + self.bank.get_fragment()
  29
+		shift_tags.append(self._trace[-1].field.w.eq(hub.tag_call))
  30
+		self.sync += If(hub.call, *shift_tags)
  31
+
  32
+	def get_registers(self):
  33
+		return [self._slot_count, self._trace_depth] + self._slot_status + self._trace
84  milkymist/dfii/__init__.py
... ...
@@ -1,12 +1,10 @@
1 1
 from migen.fhdl.structure import *
  2
+from migen.fhdl.module import Module
2 3
 from migen.bus import dfi
3 4
 from migen.bank.description import *
4  
-from migen.bank import csrgen
5 5
 
6  
-class PhaseInjector:
  6
+class PhaseInjector(Module, AutoReg):
7 7
 	def __init__(self, phase):
8  
-		self.phase = phase
9  
-		
10 8
 		self._cs = Field("cs", 1, WRITE_ONLY, READ_ONLY)
11 9
 		self._we = Field("we", 1, WRITE_ONLY, READ_ONLY)
12 10
 		self._cas = Field("cas", 1, WRITE_ONLY, READ_ONLY)
@@ -17,45 +15,38 @@ def __init__(self, phase):
17 15
 			[self._cs, self._we, self._cas, self._ras, self._wren, self._rden])
18 16
 		self._command_issue = RegisterRaw("command_issue")
19 17
 		
20  
-		self._address = RegisterField("address", len(self.phase.address))
21  
-		self._baddress = RegisterField("baddress", len(self.phase.bank))
  18
+		self._address = RegisterField("address", len(phase.address))
  19
+		self._baddress = RegisterField("baddress", len(phase.bank))
22 20
 		
23  
-		self._wrdata = RegisterField("wrdata", len(self.phase.wrdata))
24  
-		self._rddata = RegisterField("rddata", len(self.phase.rddata), READ_ONLY, WRITE_ONLY)
  21
+		self._wrdata = RegisterField("wrdata", len(phase.wrdata))
  22
+		self._rddata = RegisterField("rddata", len(phase.rddata), READ_ONLY, WRITE_ONLY)
25 23
 	
26  
-	def get_registers(self):
27  
-		return [self._command, self._command_issue,
28  
-			self._address, self._baddress,
29  
-			self._wrdata, self._rddata]
30  
-		
31  
-	def get_fragment(self):
32  
-		comb = [
  24
+		###
  25
+
  26
+		self.comb += [
33 27
 			If(self._command_issue.re,
34  
-				self.phase.cs_n.eq(~self._cs.r),
35  
-				self.phase.we_n.eq(~self._we.r),
36  
-				self.phase.cas_n.eq(~self._cas.r),
37  
-				self.phase.ras_n.eq(~self._ras.r)
  28
+				phase.cs_n.eq(~self._cs.r),
  29
+				phase.we_n.eq(~self._we.r),
  30
+				phase.cas_n.eq(~self._cas.r),
  31
+				phase.ras_n.eq(~self._ras.r)
38 32
 			).Else(
39  
-				self.phase.cs_n.eq(1),
40  
-				self.phase.we_n.eq(1),
41  
-				self.phase.cas_n.eq(1),
42  
-				self.phase.ras_n.eq(1)
  33
+				phase.cs_n.eq(1),
  34
+				phase.we_n.eq(1),
  35
+				phase.cas_n.eq(1),
  36
+				phase.ras_n.eq(1)
43 37
 			),
44  
-			self.phase.address.eq(self._address.field.r),
45  
-			self.phase.bank.eq(self._baddress.field.r),
46  
-			self.phase.wrdata_en.eq(self._command_issue.re & self._wren.r),
47  
-			self.phase.rddata_en.eq(self._command_issue.re & self._rden.r),
48  
-			self.phase.wrdata.eq(self._wrdata.field.r),
49  
-			self.phase.wrdata_mask.eq(0)
50  
-		]
51  
-		sync = [
52  
-			If(self.phase.rddata_valid, self._rddata.field.w.eq(self.phase.rddata))
  38
+			phase.address.eq(self._address.field.r),
  39
+			phase.bank.eq(self._baddress.field.r),
  40
+			phase.wrdata_en.eq(self._command_issue.re & self._wren.r),
  41
+			phase.rddata_en.eq(self._command_issue.re & self._rden.r),
  42
+			phase.wrdata.eq(self._wrdata.field.r),
  43
+			phase.wrdata_mask.eq(0)
53 44
 		]
54  
-		return Fragment(comb, sync)
  45
+		self.sync += If(phase.rddata_valid, self._rddata.field.w.eq(phase.rddata))
55 46
 
56  
-class DFIInjector:
57  
-	def __init__(self, csr_address, a, ba, d, nphases=1):
58  
-		self._int = dfi.Interface(a, ba, d, nphases)
  47
+class DFIInjector(Module, AutoReg):
  48
+	def __init__(self, a, ba, d, nphases=1):
  49
+		inti = dfi.Interface(a, ba, d, nphases)
59 50
 		self.slave = dfi.Interface(a, ba, d, nphases)
60 51
 		self.master = dfi.Interface(a, ba, d, nphases)
61 52
 		
@@ -63,19 +54,12 @@ def __init__(self, csr_address, a, ba, d, nphases=1):
63 54
 		self._cke = Field("cke")
64 55
 		self._control = RegisterFields("control", [self._sel, self._cke])
65 56
 		
66  
-		self._phase_injectors = [PhaseInjector(phase) for phase in self._int.phases]
67  
-		
68  
-		registers = sum([pi.get_registers() for pi in self._phase_injectors], [self._control])
69  
-		self.bank = csrgen.Bank(registers, address=csr_address)
  57
+		for n, phase in enumerate(inti.phases):
  58
+			setattr(self.submodules, "pi" + str(n), PhaseInjector(phase))
  59
+	
  60
+		###
70 61
 	
71  
-	def get_fragment(self):
72  
-		connect_int = dfi.interconnect_stmts(self._int, self.master)
  62
+		connect_inti = dfi.interconnect_stmts(inti, self.master)
73 63
 		connect_slave = dfi.interconnect_stmts(self.slave, self.master)
74  
-		comb = [
75  
-			If(self._sel.r, *connect_slave).Else(*connect_int)
76  
-		]
77  
-		comb += [phase.cke.eq(self._cke.r) for phase in self._int.phases]
78  
-		
79  
-		return Fragment(comb) \
80  
-			+ sum([pi.get_fragment() for pi in self._phase_injectors], Fragment()) \
81  
-			+ self.bank.get_fragment()
  64
+		self.comb += If(self._sel.r, *connect_slave).Else(*connect_inti)
  65
+		self.comb += [phase.cke.eq(self._cke.r) for phase in inti.phases]
59  milkymist/framebuffer/__init__.py
... ...
@@ -1,12 +1,12 @@
1 1
 from migen.fhdl.structure import *
2 2
 from migen.fhdl.specials import Instance
  3
+from migen.fhdl.module import Module
3 4
 from migen.flow.actor import *
4 5
 from migen.flow.network import *
5 6
 from migen.flow.transactions import *
6 7
 from migen.flow import plumbing
7 8
 from migen.actorlib import misc, dma_asmi, structuring, sim, spi
8 9
 from migen.bank.description import *
9  
-from migen.bank import csrgen
10 10
 
11 11
 _hbits = 11
12 12
 _vbits = 11
@@ -47,7 +47,7 @@ def __init__(self, asmi_bits, length_bits, alignment_bits):
47 47
 		]
48 48
 		spi.SingleGenerator.__init__(self, layout, spi.MODE_CONTINUOUS)
49 49
 
50  
-class VTG(Actor):
  50
+class VTG(Module, Actor):
51 51
 	def __init__(self):
52 52
 		Actor.__init__(self,
53 53
 			("timing", Sink, [
@@ -62,8 +62,7 @@ def __init__(self):
62 62
 			("pixels", Sink, _pixel_layout),
63 63
 			("dac", Source, _dac_layout)
64 64
 		)
65  
-	
66  
-	def get_fragment(self):
  65
+
67 66
 		hactive = Signal()
68 67
 		vactive = Signal()
69 68
 		active = Signal()
@@ -73,7 +72,7 @@ def get_fragment(self):
73 72
 		vcounter = Signal(_vbits)
74 73
 		
75 74
 		skip = _bpc - _bpc_dac
76  
-		comb = [
  75
+		self.comb += [
77 76
 			active.eq(hactive & vactive),
78 77
 			If(active,
79 78
 				self.token("dac").r.eq(self.token("pixels").r[skip:]),
@@ -86,7 +85,7 @@ def get_fragment(self):
86 85
 			self.endpoints["dac"].stb.eq(generate_en)
87 86
 		]
88 87
 		tp = self.token("timing")
89  
-		sync = [
  88
+		self.sync += [
90 89
 			self.endpoints["timing"].ack.eq(0),
91 90
 			If(generate_en & self.endpoints["dac"].ack,
92 91
 				hcounter.eq(hcounter + 1),
@@ -111,10 +110,8 @@ def get_fragment(self):
111 110
 				If(vcounter == tp.vsync_end, self.token("dac").vsync.eq(0))
112 111
 			)
113 112
 		]
114  
-		
115  
-		return Fragment(comb, sync)
116 113
 
117  
-class FIFO(Actor):
  114
+class FIFO(Module, Actor):
118 115
 	def __init__(self):
119 116
 		Actor.__init__(self, ("dac", Sink, _dac_layout))
120 117
 		
@@ -124,13 +121,14 @@ def __init__(self):
124 121
 		self.vga_g = Signal(_bpc_dac)
125 122
 		self.vga_b = Signal(_bpc_dac)
126 123
 	
127  
-	def get_fragment(self):
  124
+		###
  125
+
128 126
 		data_width = 2+3*_bpc_dac
129 127
 		fifo_full = Signal()
130 128
 		fifo_write_en = Signal()
131 129
 		fifo_data_out = Signal(data_width)
132 130
 		fifo_data_in = Signal(data_width)
133  
-		asfifo = Instance("asfifo",
  131
+		self.specials += Instance("asfifo",
134 132
 			Instance.Parameter("data_width", data_width),
135 133
 			Instance.Parameter("address_width", 8),
136 134
 	
@@ -146,17 +144,15 @@ def get_fragment(self):
146 144
 			
147 145
 			Instance.Input("rst", 0))
148 146
 		t = self.token("dac")
149  
-		return Fragment(
150  
-			[
151  
-				Cat(self.vga_hsync_n, self.vga_vsync_n, self.vga_r, self.vga_g, self.vga_b).eq(asfifo.get_io("data_out")),
152  
-				
153  
-				self.endpoints["dac"].ack.eq(~fifo_full),
154  
-				fifo_write_en.eq(self.endpoints["dac"].stb),
155  
-				fifo_data_in.eq(Cat(~t.hsync, ~t.vsync, t.r, t.g, t.b)),
156  
-				
157  
-				self.busy.eq(0)
158  
-			],
159  
-			specials={asfifo})
  147
+		self.comb += [
  148
+			Cat(self.vga_hsync_n, self.vga_vsync_n, self.vga_r, self.vga_g, self.vga_b).eq(fifo_data_out),
  149
+			
  150
+			self.endpoints["dac"].ack.eq(~fifo_full),
  151
+			fifo_write_en.eq(self.endpoints["dac"].stb),
  152
+			fifo_data_in.eq(Cat(~t.hsync, ~t.vsync, t.r, t.g, t.b)),
  153
+			
  154
+			self.busy.eq(0)