def __init__(self, width, depth): _FIFOInterface.__init__(self, 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) self.specials += [ NoRetiming(produce.q), MultiReg(produce.q, produce_rdomain, "read") ] consume_wdomain = Signal(depth_bits + 1) self.specials += [ NoRetiming(consume.q), 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): _FIFOInterface.__init__(self, 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) self.specials += [ NoRetiming(produce.q), MultiReg(produce.q, produce_rdomain, "read") ] consume_wdomain = Signal(depth_bits+1) self.specials += [ NoRetiming(consume.q), 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, fwft=True): _FIFOInterface.__init__(self, 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) 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) 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 _split_mem(self, mem): depths = [ 1 << i for i in range(log2_int(mem.depth, need_pow2=False)) if mem.depth & (1 << i) ] depths.reverse() inits = None if mem.init is not None: inits = list(mem.init) mems = [] for i, depth in enumerate(depths): init = None if inits is not None: init = inits[:depth] del inits[:depth] name = "{}_part{}".format(mem.name_override, i) mems.append( Memory(width=mem.width, depth=depth, init=init, name=name)) ports = [] comb = [] sync = {} for port in mem.ports: p, c, s = self._split_port(port, mems) ports += p comb += c sy = sync.setdefault(port.clock.cd, []) sy += s return mems + ports, comb, sync
def __init__(self, width, depth, fwft=True): _FIFOInterface.__init__(self, 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) 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) 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 __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) ]
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) ]
def transform_fragment(self, i, f): newspecials = set() for orig in f.specials: 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)