#! /usr/bin/env python # See LICENSE for license details. import sys import math use_latches = 0 def parse_line(line): name = '' width = 0 depth = 0 ports = '' mask_gran = 1 tokens = line.split() i = 0 for i in xrange(0,len(tokens),2): s = tokens[i] if s == 'name': name = tokens[i+1] elif s == 'width': width = int(tokens[i+1]) elif s == 'depth': depth = int(tokens[i+1]) elif s == 'ports': ports = tokens[i+1].split(',') elif s == 'mask_gran': # currently used only for fpga, but here for .conf format compatability mask_gran = int(tokens[i+1]) else: sys.exit('%s: unknown argument %s' % (sys.argv[0], a)) return (name, width, depth, ports) 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)) decl.append('`ifndef SYNTHESIS') decl.append(' integer initvar;') decl.append(' initial begin') decl.append(' #0.002;') decl.append(' for (initvar = 0; initvar < %d; initvar = initvar+1)' % depth) decl.append(' ram[initvar] = {%d {$random}};' % ((width-1)/32+1)) decl.append(' end') decl.append('`endif') 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 def main(): if len(sys.argv) < 2: sys.exit('Please give a .conf file as input') for line in open(sys.argv[1]): print gen_mem(*parse_line(line)) if __name__ == '__main__': main()