+++ /dev/null
-from migen.fhdl.std import *
-
-class ReorderSlot:
- def __init__(self, tag_width, data_width):
- self.wait_data = Signal()
- self.has_data = Signal()
- self.tag = Signal(tag_width)
- self.data = Signal(data_width)
-
-class ReorderBuffer:
- def __init__(self, tag_width, data_width, depth):
- self.depth = depth
-
- # issue
- self.can_issue = Signal()
- self.issue = Signal()
- self.tag_issue = Signal(tag_width)
-
- # call
- self.call = Signal()
- self.tag_call = Signal(tag_width)
- self.data_call = Signal(data_width)
-
- # readback
- self.can_read = Signal()
- self.read = Signal()
- self.data_read = Signal(data_width)
-
- self._empty_count = Signal(max=self.depth+1, reset=self.depth)
- self._produce = Signal(max=self.depth)
- self._consume = Signal(max=self.depth)
- self._slots = Array(ReorderSlot(tag_width, data_width)
- for n in range(self.depth))
-
- def get_fragment(self):
- # issue
- comb = [
- self.can_issue.eq(self._empty_count != 0)
- ]
- sync = [
- If(self.issue & self.can_issue,
- self._empty_count.eq(self._empty_count - 1),
- If(self._produce == self.depth - 1,
- self._produce.eq(0)
- ).Else(
- self._produce.eq(self._produce + 1)
- ),
- self._slots[self._produce].wait_data.eq(1),
- self._slots[self._produce].tag.eq(self.tag_issue)
- )
- ]
-
- # call
- for n, slot in enumerate(self._slots):
- sync.append(
- If(self.call & slot.wait_data & (self.tag_call == slot.tag),
- slot.wait_data.eq(0),
- slot.has_data.eq(1),
- slot.data.eq(self.data_call)
- )
- )
-
- # readback
- comb += [
- self.can_read.eq(self._slots[self._consume].has_data),
- self.data_read.eq(self._slots[self._consume].data)
- ]
- sync += [
- If(self.read & self.can_read,
- self._empty_count.eq(self._empty_count + 1),
- If(self._consume == self.depth - 1,
- self._consume.eq(0)
- ).Else(
- self._consume.eq(self._consume + 1)
- ),
- self._slots[self._consume].has_data.eq(0)
- )
- ]
-
- # do not touch empty count when issuing and reading at the same time
- sync += [
- If(self.issue & self.can_issue & self.read & self.can_read,
- self._empty_count.eq(self._empty_count)
- )
- ]
-
- return Fragment(comb, sync)
def lower(dr):
return MultiRegImpl(dr.i, dr.o, dr.odomain, dr.n)
-class PulseSynchronizer:
+class PulseSynchronizer(Module):
def __init__(self, idomain, odomain):
- self.idomain = idomain
- self.odomain = odomain
self.i = Signal()
self.o = Signal()
- def get_fragment(self):
+ ###
+
toggle_i = Signal()
toggle_o = Signal()
toggle_o_r = Signal()
- sync_i = [
- If(self.i, toggle_i.eq(~toggle_i))
- ]
- sync_o = [
- toggle_o_r.eq(toggle_o)
- ]
- comb = [
- self.o.eq(toggle_o ^ toggle_o_r)
- ]
- return Fragment(comb,
- {self.idomain: sync_i, self.odomain: sync_o},
- specials={MultiReg(toggle_i, toggle_o, self.odomain)})
+
+ sync_i = getattr(self.sync, idomain)
+ sync_o = getattr(self.sync, odomain)
+
+ sync_i += If(self.i, toggle_i.eq(~toggle_i))
+ self.specials += MultiReg(toggle_i, toggle_o, odomain)
+ sync_o += toggle_o_r.eq(toggle_o)
+ self.comb += self.o.eq(toggle_o ^ toggle_o_r)
class GrayCounter(Module):
def __init__(self, width):
--- /dev/null
+from migen.fhdl.std import *
+
+class ReorderSlot:
+ def __init__(self, tag_width, data_width):
+ self.wait_data = Signal()
+ self.has_data = Signal()
+ self.tag = Signal(tag_width)
+ self.data = Signal(data_width)
+
+class ReorderBuffer(Module):
+ def __init__(self, tag_width, data_width, depth):
+ # issue
+ self.can_issue = Signal()
+ self.issue = Signal()
+ self.tag_issue = Signal(tag_width)
+
+ # call
+ self.call = Signal()
+ self.tag_call = Signal(tag_width)
+ self.data_call = Signal(data_width)
+
+ # readback
+ self.can_read = Signal()
+ self.read = Signal()
+ self.data_read = Signal(data_width)
+
+ ###
+
+ empty_count = Signal(max=depth+1, reset=depth)
+ produce = Signal(max=depth)
+ consume = Signal(max=depth)
+ slots = Array(ReorderSlot(tag_width, data_width)
+ for n in range(depth))
+
+ # issue
+ self.comb += self.can_issue.eq(empty_count != 0)
+ self.sync += If(self.issue & self.can_issue,
+ empty_count.eq(empty_count - 1),
+ If(produce == depth - 1,
+ produce.eq(0)
+ ).Else(
+ produce.eq(produce + 1)
+ ),
+ slots[produce].wait_data.eq(1),
+ slots[produce].tag.eq(self.tag_issue)
+ )
+
+ # call
+ for n, slot in enumerate(slots):
+ self.sync += If(self.call & slot.wait_data & (self.tag_call == slot.tag),
+ slot.wait_data.eq(0),
+ slot.has_data.eq(1),
+ slot.data.eq(self.data_call)
+ )
+
+ # readback
+ self.comb += [
+ self.can_read.eq(slots[consume].has_data),
+ self.data_read.eq(slots[consume].data)
+ ]
+ self.sync += [
+ If(self.read & self.can_read,
+ empty_count.eq(empty_count + 1),
+ If(consume == depth - 1,
+ consume.eq(0)
+ ).Else(
+ consume.eq(consume + 1)
+ ),
+ slots[consume].has_data.eq(0)
+ )
+ ]
+
+ # do not touch empty count when issuing and reading at the same time
+ self.sync += If(self.issue & self.can_issue & self.read & self.can_read,
+ empty_count.eq(empty_count)
+ )