Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
  • 4 commits
  • 4 files changed
  • 0 comments
  • 1 contributor
19  examples/basic/graycounter.py
... ...
@@ -0,0 +1,19 @@
  1
+from random import Random
  2
+
  3
+from migen.fhdl.module import Module
  4
+from migen.genlib.cdc import GrayCounter
  5
+from migen.sim.generic import Simulator
  6
+
  7
+class TB(Module):
  8
+	def __init__(self, width=3):
  9
+		self.width = width
  10
+		self.submodules.gc = GrayCounter(self.width)
  11
+		self.prng = Random(7345)
  12
+
  13
+	def do_simulation(self, s):
  14
+		print("{0:0{1}b} CE={2} bin={3}".format(s.rd(self.gc.q),
  15
+			self.width, s.rd(self.gc.ce), s.rd(self.gc.q_binary)))
  16
+		s.wr(self.gc.ce, self.prng.getrandbits(1))
  17
+
  18
+sim = Simulator(TB())
  19
+sim.run(35)
10  migen/fhdl/specials.py
@@ -258,11 +258,11 @@ def emit_verilog(memory, ns):
258 258
 					elif port.mode == NO_CHANGE:
259 259
 						rd = "\tif (!" + gn(port.we) + ")\n" \
260 260
 						  + "\t\t" + bassign
261  
-			if port.re is None:
262  
-				r += rd
263  
-			else:
264  
-				r += "\tif (" + gn(port.re) + ")\n"
265  
-				r += "\t" + rd.replace("\n\t", "\n\t\t")
  261
+				if port.re is None:
  262
+					r += rd
  263
+				else:
  264
+					r += "\tif (" + gn(port.re) + ")\n"
  265
+					r += "\t" + rd.replace("\n\t", "\n\t\t")
266 266
 			r += "end\n\n"
267 267
 		
268 268
 		for port in memory.ports:
24  migen/genlib/cdc.py
... ...
@@ -1,4 +1,5 @@
1 1
 from migen.fhdl.structure import *
  2
+from migen.fhdl.module import Module
2 3
 from migen.fhdl.specials import Special
3 4
 from migen.fhdl.tools import list_signals
4 5
 
@@ -71,3 +72,26 @@ def get_fragment(self):
71 72
 		return Fragment(comb, 
72 73
 			{self.idomain: sync_i, self.odomain: sync_o},
73 74
 			specials={MultiReg(toggle_i, toggle_o, self.odomain)})
  75
+
  76
+class GrayCounter(Module):
  77
+	def __init__(self, width):
  78
+		self.ce = Signal()
  79
+		self.q = Signal(width)
  80
+		self.q_next = Signal(width)
  81
+		self.q_binary = Signal(width)
  82
+		self.q_next_binary = Signal(width)
  83
+
  84
+		###
  85
+
  86
+		self.comb += [
  87
+			If(self.ce,
  88
+				self.q_next_binary.eq(self.q_binary + 1)
  89
+			).Else(
  90
+				self.q_next_binary.eq(self.q_binary)
  91
+			),
  92
+			self.q_next.eq(self.q_next_binary ^ self.q_next_binary[1:])
  93
+		]
  94
+		self.sync += [
  95
+			self.q_binary.eq(self.q_next_binary),
  96
+			self.q.eq(self.q_next)
  97
+		]
51  migen/genlib/fifo.py
... ...
@@ -1,6 +1,7 @@
1 1
 from migen.fhdl.structure import *
2 2
 from migen.fhdl.specials import Memory
3 3
 from migen.fhdl.module import Module
  4
+from migen.genlib.cdc import MultiReg, GrayCounter
4 5
 
5 6
 def _inc(signal, modulo):
6 7
 	if modulo == 2**len(signal):
@@ -12,7 +13,7 @@ def _inc(signal, modulo):
12 13
 			signal.eq(signal + 1)
13 14
 		)
14 15
 
15  
-class SyncFIFO(Module):
  16
+class _FIFOInterface:
16 17
 	def __init__(self, width, depth):
17 18
 		self.din = Signal(width)
18 19
 		self.we = Signal()
@@ -21,6 +22,10 @@ def __init__(self, width, depth):
21 22
 		self.re = Signal()
22 23
 		self.readable = Signal() # not empty
23 24
 
  25
+class SyncFIFO(Module, _FIFOInterface):
  26
+	def __init__(self, width, depth):
  27
+		_FIFOInterface.__init__(self, width, depth)
  28
+
24 29
 		###
25 30
 
26 31
 		do_write = Signal()
@@ -62,3 +67,47 @@ def __init__(self, width, depth):
62 67
 			self.writable.eq(level != depth),
63 68
 			self.readable.eq(level != 0)
64 69
 		]
  70
+
  71
+class AsyncFIFO(Module, _FIFOInterface):
  72
+	def __init__(self, width, depth):
  73
+		_FIFOInterface.__init__(self, width, depth)
  74
+
  75
+		###
  76
+
  77
+		depth_bits = log2_int(depth, True)
  78
+
  79
+		produce = GrayCounter(depth_bits+1)
  80
+		self.add_submodule(produce, "write")
  81
+		consume = GrayCounter(depth_bits+1)
  82
+		self.add_submodule(consume, "read")
  83
+		self.comb += [
  84
+			produce.ce.eq(self.writable & self.we),
  85
+			consume.ce.eq(self.readable & self.re)
  86
+		]
  87
+
  88
+		# TODO: disable retiming on produce.q and consume.q
  89
+
  90
+		produce_rdomain = Signal(depth_bits+1)
  91
+		self.specials += MultiReg(produce.q, produce_rdomain, "read")
  92
+		consume_wdomain = Signal(depth_bits+1)
  93
+		self.specials += MultiReg(consume.q, consume_wdomain, "write")
  94
+		self.comb += [
  95
+			self.writable.eq((produce.q[-1] == consume_wdomain[-1])
  96
+			 | (produce.q[-2] == consume_wdomain[-2])
  97
+			 | (produce.q[:-2] != consume_wdomain[:-2])),
  98
+			self.readable.eq(consume.q != produce_rdomain)
  99
+		]
  100
+
  101
+		storage = Memory(width, depth)
  102
+		self.specials += storage
  103
+		wrport = storage.get_port(write_capable=True, clock_domain="write")
  104
+		self.comb += [
  105
+			wrport.adr.eq(produce.q_binary[:-1]),
  106
+			wrport.dat_w.eq(self.din),
  107
+			wrport.we.eq(produce.ce)
  108
+		]
  109
+		rdport = storage.get_port(clock_domain="read")
  110
+		self.comb += [
  111
+			rdport.adr.eq(consume.q_binary[:-1]),
  112
+			self.dout.eq(rdport.dat_r)
  113
+		]

No commit comments for this range

Something went wrong with that request. Please try again.