width : int
Bit width of data entries.
depth : int
- Depth of the queue.
+ Depth of the queue. If zero, the FIFO cannot be read from or written to.
{parameters}
Attributes
if not isinstance(width, int) or width < 0:
raise TypeError("FIFO width must be a non-negative integer, not '{!r}'"
.format(width))
- if not isinstance(depth, int) or depth <= 0:
- raise TypeError("FIFO depth must be a positive integer, not '{!r}'"
+ if not isinstance(depth, int) or depth < 0:
+ raise TypeError("FIFO depth must be a non-negative integer, not '{!r}'"
.format(depth))
self.width = width
self.depth = depth
self.fwft = fwft
self.w_data = Signal(width, reset_less=True)
- self.w_rdy = Signal() # not full
+ self.w_rdy = Signal() # writable; not full
self.w_en = Signal()
self.r_data = Signal(width, reset_less=True)
- self.r_rdy = Signal() # not empty
+ self.r_rdy = Signal() # readable; not empty
self.r_en = Signal()
# TODO(nmigen-0.2): move this to nmigen.compat and make it a deprecated extension
def elaborate(self, platform):
m = Module()
+ if self.depth == 0:
+ m.d.comb += [
+ self.w_rdy.eq(0),
+ self.r_rdy.eq(0),
+ ]
+ return m
+
m.d.comb += [
self.w_rdy.eq(self.level != self.depth),
self.r_rdy.eq(self.level != 0)
def elaborate(self, platform):
m = Module()
+ if self.depth == 0:
+ m.d.comb += [
+ self.w_rdy.eq(0),
+ self.r_rdy.eq(0),
+ ]
+ return m
# Effectively, this queue treats the output register of the non-FWFT inner queue as
# an additional storage element.
w_attributes="")
def __init__(self, *, width, depth, r_domain="read", w_domain="write", exact_depth=False):
- try:
- depth_bits = log2_int(depth, need_pow2=exact_depth)
- except ValueError as e:
- raise ValueError("AsyncFIFO only supports depths that are powers of 2; requested "
- "exact depth {} is not"
- .format(depth)) from None
- super().__init__(width=width, depth=1 << depth_bits, fwft=True)
+ if depth != 0:
+ try:
+ depth_bits = log2_int(depth, need_pow2=exact_depth)
+ depth = 1 << depth_bits
+ except ValueError as e:
+ raise ValueError("AsyncFIFO only supports depths that are powers of 2; requested "
+ "exact depth {} is not"
+ .format(depth)) from None
+ else:
+ depth_bits = 0
+ super().__init__(width=width, depth=depth, fwft=True)
self._r_domain = r_domain
self._w_domain = w_domain
self._ctr_bits = depth_bits + 1
def elaborate(self, platform):
+ m = Module()
+ if self.depth == 0:
+ m.d.comb += [
+ self.w_rdy.eq(0),
+ self.r_rdy.eq(0),
+ ]
+ return m
+
# The design of this queue is the "style #2" from Clifford E. Cummings' paper "Simulation
# and Synthesis Techniques for Asynchronous FIFO Design":
# http://www.sunburst-design.com/papers/CummingsSNUG2002SJ_FIFO1.pdf
- m = Module()
-
do_write = self.w_rdy & self.w_en
do_read = self.r_rdy & self.r_en
w_attributes="")
def __init__(self, *, width, depth, r_domain="read", w_domain="write", exact_depth=False):
- try:
- depth_bits = log2_int(max(0, depth - 1), need_pow2=exact_depth)
- except ValueError as e:
- raise ValueError("AsyncFIFOBuffered only supports depths that are one higher "
- "than powers of 2; requested exact depth {} is not"
- .format(depth)) from None
- super().__init__(width=width, depth=(1 << depth_bits) + 1, fwft=True)
+ if depth != 0:
+ try:
+ depth_bits = log2_int(max(0, depth - 1), need_pow2=exact_depth)
+ depth = (1 << depth_bits) + 1
+ except ValueError as e:
+ raise ValueError("AsyncFIFOBuffered only supports depths that are one higher "
+ "than powers of 2; requested exact depth {} is not"
+ .format(depth)) from None
+ super().__init__(width=width, depth=depth, fwft=True)
self._r_domain = r_domain
self._w_domain = w_domain
def elaborate(self, platform):
m = Module()
+ if self.depth == 0:
+ m.d.comb += [
+ self.w_rdy.eq(0),
+ self.r_rdy.eq(0),
+ ]
+ return m
+
m.submodules.unbuffered = fifo = AsyncFIFO(width=self.width, depth=self.depth - 1,
r_domain=self._r_domain, w_domain=self._w_domain)
msg="FIFO width must be a non-negative integer, not '-1'"):
FIFOInterface(width=-1, depth=8, fwft=True)
with self.assertRaises(TypeError,
- msg="FIFO depth must be a positive integer, not '0'"):
- FIFOInterface(width=8, depth=0, fwft=True)
+ msg="FIFO depth must be a non-negative integer, not '-1'"):
+ FIFOInterface(width=8, depth=-1, fwft=True)
+
+ def test_sync_depth(self):
+ self.assertEqual(SyncFIFO(width=8, depth=0).depth, 0)
+ self.assertEqual(SyncFIFO(width=8, depth=1).depth, 1)
+ self.assertEqual(SyncFIFO(width=8, depth=2).depth, 2)
+
+ def test_sync_buffered_depth(self):
+ self.assertEqual(SyncFIFOBuffered(width=8, depth=0).depth, 0)
+ self.assertEqual(SyncFIFOBuffered(width=8, depth=1).depth, 1)
+ self.assertEqual(SyncFIFOBuffered(width=8, depth=2).depth, 2)
def test_async_depth(self):
+ self.assertEqual(AsyncFIFO(width=8, depth=0 ).depth, 0)
self.assertEqual(AsyncFIFO(width=8, depth=1 ).depth, 1)
self.assertEqual(AsyncFIFO(width=8, depth=2 ).depth, 2)
self.assertEqual(AsyncFIFO(width=8, depth=3 ).depth, 4)
AsyncFIFO(width=8, depth=15, exact_depth=True)
def test_async_buffered_depth(self):
+ self.assertEqual(AsyncFIFOBuffered(width=8, depth=0 ).depth, 0)
self.assertEqual(AsyncFIFOBuffered(width=8, depth=1 ).depth, 2)
self.assertEqual(AsyncFIFOBuffered(width=8, depth=2 ).depth, 2)
self.assertEqual(AsyncFIFOBuffered(width=8, depth=3 ).depth, 3)