def __init__(self, width, depth, fwft=True): super().__init__(width, depth) self.level = Signal(max=depth + 1) self.replace = Signal() ### produce = Signal(max=depth) consume = Signal(max=depth) storage = Memory(self.width, depth) self.specials += storage wrport = storage.get_port(write_capable=True, mode=READ_FIRST) self.specials += wrport self.comb += [ If( self.replace, wrport.adr.eq(produce - 1) ).Else( wrport.adr.eq(produce) ), wrport.dat_w.eq(self.din), wrport.we.eq(self.we & (self.writable | self.replace)) ] self.sync += If(self.we & self.writable & ~self.replace, _inc(produce, depth)) do_read = Signal() self.comb += do_read.eq(self.readable & self.re) rdport = storage.get_port(async_read=fwft, has_re=not fwft, mode=READ_FIRST) self.specials += rdport self.comb += [ rdport.adr.eq(consume), self.dout.eq(rdport.dat_r) ] if not fwft: self.comb += rdport.re.eq(do_read) self.sync += If(do_read, _inc(consume, depth)) self.sync += \ If( self.we & self.writable & ~self.replace, If(~do_read, self.level.eq(self.level + 1)) ).Elif( do_read, self.level.eq(self.level - 1) ) self.comb += [ self.writable.eq(self.level != depth), self.readable.eq(self.level != 0) ]
def transform_fragment(self, i, f): newspecials = set() for orig in sorted(f.specials, key=lambda x: x.duid): if not isinstance(orig, Memory): newspecials.add(orig) continue global_granularity = gcd_multiple([ p.we_granularity if p.we_granularity else orig.width for p in orig.ports ]) if global_granularity == orig.width: newspecials.add(orig) # nothing to do else: newmems = [] for i in range(orig.width // global_granularity): if orig.init is None: newinit = None else: newinit = [(v >> i * global_granularity) & (2**global_granularity - 1) for v in orig.init] newmem = Memory(global_granularity, orig.depth, newinit, orig.name_override + "_grain" + str(i)) newspecials.add(newmem) newmems.append(newmem) for port in orig.ports: port_granularity = port.we_granularity if port.we_granularity else orig.width newport = _MemoryPort( adr=port.adr, dat_r=port.dat_r[i * global_granularity:(i + 1) * global_granularity] if port.dat_r is not None else None, we=port.we[i * global_granularity // port_granularity] if port.we is not None else None, dat_w=port.dat_w[i * global_granularity:(i + 1) * global_granularity] if port.dat_w is not None else None, async_read=port.async_read, re=port.re, we_granularity=0, mode=port.mode, clock_domain=port.clock.cd) newmem.ports.append(newport) newspecials.add(newport) self.replacements[orig] = newmems f.specials = newspecials for oldmem in self.replacements.keys(): f.specials -= set(oldmem.ports)
def __init__(self, width, depth): super().__init__(width, depth) ### depth_bits = log2_int(depth, True) produce = ClockDomainsRenamer("write")(GrayCounter(depth_bits + 1)) consume = ClockDomainsRenamer("read")(GrayCounter(depth_bits + 1)) self.submodules += produce, consume self.comb += [ produce.ce.eq(self.writable & self.we), consume.ce.eq(self.readable & self.re) ] produce_rdomain = Signal(depth_bits + 1) produce.q.attr.add("no_retiming") self.specials += MultiReg(produce.q, produce_rdomain, "read") consume_wdomain = Signal(depth_bits + 1) consume.q.attr.add("no_retiming") self.specials += MultiReg(consume.q, consume_wdomain, "write") if depth_bits == 1: self.comb += self.writable.eq( (produce.q[-1] == consume_wdomain[-1]) | (produce.q[-2] == consume_wdomain[-2])) else: self.comb += [ self.writable.eq( (produce.q[-1] == consume_wdomain[-1]) | (produce.q[-2] == consume_wdomain[-2]) | (produce.q[:-2] != consume_wdomain[:-2])) ] self.comb += self.readable.eq(consume.q != produce_rdomain) storage = Memory(self.width, depth) self.specials += storage wrport = storage.get_port(write_capable=True, clock_domain="write") self.specials += wrport self.comb += [ wrport.adr.eq(produce.q_binary[:-1]), wrport.dat_w.eq(self.din), wrport.we.eq(produce.ce) ] rdport = storage.get_port(clock_domain="read") self.specials += rdport self.comb += [ rdport.adr.eq(consume.q_next_binary[:-1]), self.dout.eq(rdport.dat_r) ]
def __init__(self, width, depth, idomain, odomain): self.din = Signal(width) self.dout = Signal(width) # # # reset = Signal() cd_write = ClockDomain() cd_read = ClockDomain() self.comb += [ cd_write.clk.eq(ClockSignal(idomain)), cd_read.clk.eq(ClockSignal(odomain)), reset.eq(ResetSignal(idomain) | ResetSignal(odomain)) ] self.specials += [ AsyncResetSynchronizer(cd_write, reset), AsyncResetSynchronizer(cd_read, reset) ] self.clock_domains += cd_write, cd_read wrpointer = Signal(max=depth, reset=depth//2) rdpointer = Signal(max=depth) storage = Memory(width, depth) self.specials += storage wrport = storage.get_port(write_capable=True, clock_domain="write") rdport = storage.get_port(clock_domain="read") self.specials += wrport, rdport self.sync.write += wrpointer.eq(wrpointer + 1) self.sync.read += rdpointer.eq(rdpointer + 1) self.comb += [ wrport.we.eq(1), wrport.adr.eq(wrpointer), wrport.dat_w.eq(self.din), rdport.adr.eq(rdpointer), self.dout.eq(rdport.dat_r) ]