Skip to content

Commit

Permalink
Some minor BasicFifo tweaks.
Browse files Browse the repository at this point in the history
  • Loading branch information
Lekcyjna committed Nov 19, 2023
1 parent 53c03fb commit 80cb0cd
Showing 1 changed file with 15 additions and 7 deletions.
22 changes: 15 additions & 7 deletions transactron/utils/fifo.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

class BasicFifo(Elaboratable):
"""Transactional FIFO queue
Attributes
----------
read: Method
Expand All @@ -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:
Expand All @@ -30,29 +28,27 @@ 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
self.level = Signal((self.depth).bit_length())

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:
Expand All @@ -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)
Expand All @@ -80,24 +82,30 @@ 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))

@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

Expand Down

0 comments on commit 80cb0cd

Please sign in to comment.