Example #1
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
Example #2
0
    def transform_fragment(self, i, f):
        old_specials, f.specials = f.specials, set()
        old_ports = set()

        for old in old_specials:
            if not isinstance(old, Memory):
                f.specials.add(old)
                continue
            try:
                log2_int(old.depth, need_pow2=True)
                f.specials.add(old)
            except ValueError:
                new, comb, sync = self._split_mem(old)
                old_ports |= set(old.ports)
                f.specials.update(new)
                f.comb += comb
                for cd, sy in sync.items():
                    s = f.sync.setdefault(cd, [])
                    s += sy
        f.specials -= old_ports
Example #3
0
    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)
        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)
        ]
Example #4
0
    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)
        ]