fhdl: memories working
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Fri, 27 Jan 2012 19:22:17 +0000 (20:22 +0100)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Fri, 27 Jan 2012 19:22:17 +0000 (20:22 +0100)
examples/memory.py [new file with mode: 0644]
migen/fhdl/structure.py
migen/fhdl/verilog.py
migen/fhdl/verilog_mem_behavioral.py

diff --git a/examples/memory.py b/examples/memory.py
new file mode 100644 (file)
index 0000000..e8f4531
--- /dev/null
@@ -0,0 +1,21 @@
+from migen.fhdl.structure import *
+from migen.fhdl import verilog
+
+d = 100
+d_b = bits_for(d-1)
+w = 32
+
+a1 = Signal(BV(d_b))
+d1 = Signal(BV(w))
+we1 = Signal(BV(4))
+dw1 = Signal(BV(w))
+p1 = MemoryPort(a1, d1, we1, dw1, we_granularity=8, mode=WRITE_FIRST)
+
+a2 = Signal(BV(d_b))
+d2 = Signal(BV(w))
+p2 = MemoryPort(a2, d2)
+
+mem = Memory(w, d, p1, p2, init=[5, 18, 32])
+f = Fragment(memories=[mem])
+v = verilog.convert(f, ios={a1, d1, we1, dw1, a2, d2})
+print(v)
index b52f4539b208044c5182970a106d69ad0044ce50..c953834d1e0b399d7fa26c871d84d5588d12a065 100644 (file)
@@ -228,8 +228,11 @@ class Instance:
        def __hash__(self):
                return id(self)
 
+(READ_FIRST, WRITE_FIRST, NO_CHANGE) = range(3)
+
 class MemoryPort:
-       def __init__(self, adr, dat_r, we=None, dat_w=None, async_read=False, re=None, we_granularity=0):
+       def __init__(self, adr, dat_r, we=None, dat_w=None,
+         async_read=False, re=None, we_granularity=0, mode=READ_FIRST):
                self.adr = adr
                self.dat_r = dat_r
                self.we = we
@@ -237,6 +240,7 @@ class MemoryPort:
                self.async_read = async_read
                self.re = re
                self.we_granularity = we_granularity
+               self.mode = mode
 
 class Memory:
        def __init__(self, width, depth, *ports, init=None):
index 4c7bc434267c92203a81bf981cf9d1a0604b41ad..f169b508f4c628b40001f70473243ffdde099b7a 100644 (file)
@@ -205,10 +205,10 @@ def _printinstances(f, ns, clk, rst):
                r += ");\n\n"
        return r
 
-def _printmemories(f, ns, handler, clk, rst):
+def _printmemories(f, ns, handler, clk):
        r = ""
        for memory in f.memories:
-               r += handler(memory, ns, clk, rst)
+               r += handler(memory, ns, clk)
        return r
 
 def convert(f, ios=set(), name="top",
@@ -233,7 +233,7 @@ def convert(f, ios=set(), name="top",
        r += _printcomb(f, ns)
        r += _printsync(f, ns, clk_signal, rst_signal)
        r += _printinstances(f, ns, clk_signal, rst_signal)
-       r += _printmemories(f, ns, memory_handler, clk_signal, rst_signal)
+       r += _printmemories(f, ns, memory_handler, clk_signal)
        r += "endmodule\n"
 
        if return_ns:
index 1a820672569ffc90b8498661ba2e269bd7f9b700..31dddfa24a03f2fa4b5bdeabb85f7ca44e022bb4 100644 (file)
@@ -1,2 +1,70 @@
-def handler(memory, ns, clk, rst):
-       return "/* TODO: implement memory */\n"
+from migen.fhdl.structure import *
+
+def handler(memory, ns, clk):
+       r = ""
+       gn = ns.get_name
+       adrbits = bits_for(memory.depth-1)
+       
+       storage = Signal(name_override="mem")
+       r += "reg [" + str(memory.width-1) + ":0] " \
+               + gn(storage) \
+               + "[0:" + str(memory.depth-1) + "];\n"
+
+       adr_regs = {}
+       data_regs = {}
+       for port in memory.ports:
+               if not port.async_read:
+                       if port.mode == WRITE_FIRST and port.we is not None:
+                               adr_reg = Signal(name_override="memadr")
+                               r += "reg [" + str(adrbits-1) + ":0] " \
+                                       + gn(adr_reg) + ";\n"
+                               adr_regs[id(port)] = adr_reg
+                       else:
+                               data_reg = Signal(name_override="memdat")
+                               r += "reg [" + str(memory.width-1) + ":0] " \
+                                       + gn(data_reg) + ";\n"
+                               data_regs[id(port)] = data_reg
+
+       r += "always @(posedge " + gn(clk) + ") begin\n"
+       for port in memory.ports:
+               if port.we is not None:
+                       if port.we_granularity:
+                               n = memory.width//port.we_granularity
+                               for i in range(n):
+                                       m = i*port.we_granularity
+                                       M = (i+1)*port.we_granularity-1
+                                       sl = "[" + str(M) + ":" + str(m) + "]"
+                                       r += "\tif (" + gn(port.we) + "[" + str(i) + "])\n"
+                                       r += "\t\t" + gn(storage) + "[" + gn(port.adr) + "]" + sl + " <= " + gn(port.dat_w) + sl + ";\n"
+                       else:
+                               r += "\tif (" + gn(port.we) + ")\n"
+                               r += "\t\t" + gn(storage) + "[" + gn(port.adr) + "] <= " + gn(port.dat_w) + ";\n"
+               if not port.async_read:
+                       if port.mode == WRITE_FIRST and port.we is not None:
+                               r += "\t" + gn(adr_regs[id(port)]) + " <= " + gn(port.adr) + ";\n"
+                       else:
+                               bassign = gn(data_regs[id(port)]) + " <= " + gn(storage) + "[" + gn(port.adr) + "];\n"
+                               if port.mode == READ_FIRST or port.we is None:
+                                       r += "\t" + bassign
+                               elif port.mode == NO_CHANGE:
+                                       r += "\tif (!" + gn(port.we) + ")\n"
+                                       r += "\t\t" + bassign
+       r += "end\n\n"
+       
+       for port in memory.ports:
+               if port.async_read:
+                       r += "assign " + gn(port.dat_r) + " = " + gn(storage) + "[" + gn(port.adr) + "];\n"
+               else:
+                       if port.mode == WRITE_FIRST and port.we is not None:
+                               r += "assign " + gn(port.dat_r) + " = " + gn(storage) + "[" + gn(adr_regs[id(port)]) + "];\n"
+                       else:
+                               r += "assign " + gn(port.dat_r) + " = " + gn(data_regs[id(port)]) + ";\n"
+       r += "\n"
+       
+       if memory.init is not None:
+               r += "initial begin\n"
+               for i, c in enumerate(memory.init):
+                       r += "\t" + gn(storage) + "[" + str(i) + "] <= " + str(memory.width) + "'d" + str(c) + ";\n"
+               r += "end\n\n"
+       
+       return r