From 80cb0cd3cd6742687d365077f053e988309a7e24 Mon Sep 17 00:00:00 2001 From: Lekcyjna <309016@uwr.edu.pl> Date: Sun, 19 Nov 2023 15:39:11 +0100 Subject: [PATCH] Some minor BasicFifo tweaks. --- transactron/utils/fifo.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/transactron/utils/fifo.py b/transactron/utils/fifo.py index 94e136e13..4332fffb3 100644 --- a/transactron/utils/fifo.py +++ b/transactron/utils/fifo.py @@ -6,7 +6,6 @@ class BasicFifo(Elaboratable): """Transactional FIFO queue - Attributes ---------- read: Method @@ -18,7 +17,6 @@ class BasicFifo(Elaboratable): clear: Method Clears the FIFO entries. Has priority over `read` and `write` methods. Note that, clearing the FIFO doesn't reinitialize it to values passed in `init` parameter. - """ def __init__(self, layout: MethodLayout, depth: int) -> None: @@ -30,22 +28,17 @@ def __init__(self, layout: MethodLayout, depth: int) -> None: If integer is given, Record with field `data` and width of this paramter is used as internal layout. depth: int Size of the FIFO. - """ self.layout = layout self.width = len(Record(self.layout)) self.depth = depth - self.read = Method(o=self.layout) self.write = Method(i=self.layout) self.clear = Method() self.head = Record(self.layout) - self.buff = Memory(width=self.width, depth=self.depth) - self.write_ready = Signal() self.read_ready = Signal() - self.read_idx = Signal((self.depth - 1).bit_length()) self.write_idx = Signal((self.depth - 1).bit_length()) # current fifo depth @@ -53,6 +46,9 @@ def __init__(self, layout: MethodLayout, depth: int) -> None: self.clear.add_conflict(self.read, Priority.LEFT) self.clear.add_conflict(self.write, Priority.LEFT) + # for interface compatibility with MultiportFifo + self.read_methods = [self.read] + self.write_methods = [self.write] def elaborate(self, platform): def mod_incr(sig: Value, mod: int) -> Value: @@ -66,10 +62,16 @@ def mod_incr(sig: Value, mod: int) -> Value: m.submodules.buff_rdport = self.buff_rdport = self.buff.read_port( domain="comb", transparent=True ) # FWFT behaviour + next_read_idx = Signal.like(self.read_idx) + m.d.top_comb += next_read_idx.eq(mod_incr(self.read_idx, self.depth)) + + m.submodules.buff_rdport = self.buff_rdport = self.buff.read_port(domain="sync", transparent=True) m.submodules.buff_wrport = self.buff_wrport = self.buff.write_port() m.d.comb += self.read_ready.eq(self.level > 0) m.d.comb += self.write_ready.eq(self.level < self.depth) + m.d.top_comb += self.read_ready.eq(self.level != 0) + m.d.top_comb += self.write_ready.eq(self.level != self.depth) with m.If(self.read.run & ~self.write.run): m.d.sync += self.level.eq(self.level - 1) @@ -80,11 +82,15 @@ def mod_incr(sig: Value, mod: int) -> Value: m.d.comb += self.buff_rdport.addr.eq(self.read_idx) m.d.comb += self.head.eq(self.buff_rdport.data) + m.d.top_comb += self.buff_rdport.addr.eq(Mux(self.read.run, next_read_idx, self.read_idx)) + m.d.top_comb += self.head.eq(self.buff_rdport.data) @def_method(m, self.write, ready=self.write_ready) def _(arg: Record) -> None: m.d.comb += self.buff_wrport.addr.eq(self.write_idx) m.d.comb += self.buff_wrport.data.eq(arg) + m.d.top_comb += self.buff_wrport.addr.eq(self.write_idx) + m.d.top_comb += self.buff_wrport.data.eq(arg) m.d.comb += self.buff_wrport.en.eq(1) m.d.sync += self.write_idx.eq(mod_incr(self.write_idx, self.depth)) @@ -92,12 +98,14 @@ def _(arg: Record) -> None: @def_method(m, self.read, self.read_ready) def _() -> ValueLike: m.d.sync += self.read_idx.eq(mod_incr(self.read_idx, self.depth)) + m.d.sync += self.read_idx.eq(next_read_idx) return self.head @def_method(m, self.clear) def _() -> None: m.d.sync += self.read_idx.eq(0) m.d.sync += self.write_idx.eq(0) + m.d.sync += self.level.eq(0) return m