137 lines
4.3 KiB
Python
Executable File
137 lines
4.3 KiB
Python
Executable File
#!/usr/bin/env python
|
|
import sys
|
|
import math
|
|
|
|
use_latches = 0
|
|
|
|
def gen_mem(name, width, depth, ports):
|
|
addr_width = max(math.ceil(math.log(depth)/math.log(2)),1)
|
|
port_spec = ['input CLK', 'input RST', 'input init']
|
|
readports = []
|
|
writeports = []
|
|
latchports = []
|
|
rwports = []
|
|
decl = []
|
|
combinational = []
|
|
sequential = []
|
|
maskedports = {}
|
|
for pid in range(len(ports)):
|
|
ptype = ports[pid]
|
|
if ptype[0:1] == 'm':
|
|
ptype = ptype[1:]
|
|
maskedports[pid] = pid
|
|
|
|
if ptype == 'read':
|
|
port_spec.append('input [%d:0] R%dA' % (addr_width-1, pid))
|
|
port_spec.append('input R%dE' % pid)
|
|
port_spec.append('output [%d:0] R%dO' % (width-1, pid))
|
|
readports.append(pid)
|
|
elif ptype == 'write':
|
|
port_spec.append('input [%d:0] W%dA' % (addr_width-1, pid))
|
|
port_spec.append('input W%dE' % pid)
|
|
port_spec.append('input [%d:0] W%dI' % (width-1, pid))
|
|
if pid in maskedports:
|
|
port_spec.append('input [%d:0] W%dM' % (width-1, pid))
|
|
if not use_latches or pid in maskedports:
|
|
writeports.append(pid)
|
|
else:
|
|
latchports.append(pid)
|
|
elif ptype == 'rw':
|
|
port_spec.append('input [%d:0] RW%dA' % (addr_width-1, pid))
|
|
port_spec.append('input RW%dE' % pid)
|
|
port_spec.append('input RW%dW' % pid)
|
|
if pid in maskedports:
|
|
port_spec.append('input [%d:0] RW%dM' % (width-1, pid))
|
|
port_spec.append('input [%d:0] RW%dI' % (width-1, pid))
|
|
port_spec.append('output [%d:0] RW%dO' % (width-1, pid))
|
|
rwports.append(pid)
|
|
else:
|
|
sys.exit('%s: unknown port type %s' % (sys.argv[0], ptype))
|
|
|
|
nr = len(readports)
|
|
nw = len(writeports)
|
|
nrw = len(rwports)
|
|
masked = len(maskedports)>0
|
|
tup = (depth, width, nr, nw, nrw, masked)
|
|
|
|
decl.append('reg [%d:0] ram [%d:0];' % (width-1, depth-1))
|
|
|
|
for pid in readports:
|
|
decl.append('reg [%d:0] reg_R%dA;' % (addr_width-1, pid))
|
|
sequential.append('if (R%dE) reg_R%dA <= R%dA;' % (pid, pid, pid))
|
|
combinational.append('assign R%dO = ram[reg_R%dA];' % (pid, pid))
|
|
|
|
for pid in rwports:
|
|
decl.append('reg [%d:0] reg_RW%dA;' % (addr_width-1, pid))
|
|
sequential.append('if (RW%dE && !RW%dW) reg_RW%dA <= RW%dA;' % (pid, pid, pid, pid))
|
|
combinational.append('assign RW%dO = ram[reg_RW%dA];' % (pid, pid))
|
|
|
|
for pid in latchports:
|
|
decl.append('reg [%d:0] latch_W%dA;' % (addr_width-1, pid))
|
|
decl.append('reg [%d:0] latch_W%dI;' % (width-1, pid))
|
|
decl.append('reg latch_W%dE;' % (pid))
|
|
combinational.append('always @(*) begin')
|
|
combinational.append(' if (!CLK && W%dE) latch_W%dA <= W%dA;' % (pid, pid, pid))
|
|
combinational.append(' if (!CLK && W%dE) latch_W%dI <= W%dI;' % (pid, pid, pid))
|
|
combinational.append(' if (!CLK) latch_W%dE <= W%dE;' % (pid, pid))
|
|
combinational.append('end')
|
|
combinational.append('always @(*)')
|
|
combinational.append(' if (CLK && latch_W%dE)' % (pid))
|
|
combinational.append(' ram[latch_W%dA] <= latch_W%dI;' % (pid, pid))
|
|
|
|
decl.append("integer i;")
|
|
sequential.append("for (i = 0; i < %d; i=i+1) begin" % width)
|
|
for pid in writeports:
|
|
mask = (' && W%dM[i]' % pid) if pid in maskedports else ''
|
|
sequential.append(" if (W%dE%s) ram[W%dA][i] <= W%dI[i];" % (pid, mask, pid, pid))
|
|
for pid in rwports:
|
|
mask = (' && RW%dM[i]' % pid) if pid in maskedports else ''
|
|
sequential.append(" if (RW%dE && RW%dW%s) ram[RW%dA][i] <= RW%dI[i];" % (pid, pid, mask, pid, pid))
|
|
sequential.append("end")
|
|
body = "\
|
|
%s\n\
|
|
always @(posedge CLK) begin\n\
|
|
%s\n\
|
|
end\n\
|
|
%s\n" % ('\n '.join(decl), '\n '.join(sequential), '\n '.join(combinational))
|
|
|
|
s = "module %s(\n\
|
|
%s\n\
|
|
);\n\
|
|
\n\
|
|
%s\
|
|
\n\
|
|
endmodule\n" % (name, ',\n '.join(port_spec), body)
|
|
return s
|
|
|
|
name = ''
|
|
width = 0
|
|
depth = 0
|
|
ports = ''
|
|
|
|
tokens = sys.argv[1:len(sys.argv)]
|
|
i = 0
|
|
while i < len(tokens):
|
|
a = tokens[i]
|
|
if a == 'name':
|
|
name = tokens[i+1]
|
|
i += 1
|
|
elif a == 'width':
|
|
width = int(tokens[i+1])
|
|
i += 1
|
|
elif a == 'depth':
|
|
depth = int(tokens[i+1])
|
|
i += 1
|
|
elif a == 'ports':
|
|
ports = tokens[i+1].split(',')
|
|
i += 1
|
|
elif a == 'mask_gran':
|
|
# currently used only for fpga, but here for .conf format compatability
|
|
mask_gran = int(tokens[i+1])
|
|
i += 1
|
|
else:
|
|
sys.exit('%s: unknown argument %s' % (sys.argv[0], a))
|
|
i += 1
|
|
|
|
print gen_mem(name, width, depth, ports)
|