Updated Verilog to have multiport. Added 1rw,1rw/1r Verilog testbench.

This commit is contained in:
Matt Guthaus
2019-01-11 14:15:16 -08:00
parent f0ab155172
commit 5de7ff3773
15 changed files with 459 additions and 54 deletions
+1 -2
View File
@@ -10,7 +10,7 @@ from vector import vector
from pin_layout import pin_layout
import lef
class layout(lef.lef):
class layout():
"""
Class consisting of a set of objs and instances for a module
This provides a set of useful generic types for hierarchy
@@ -21,7 +21,6 @@ class layout(lef.lef):
"""
def __init__(self, name):
lef.lef.__init__(self, ["metal1", "metal2", "metal3"])
self.name = name
self.width = None
self.height = None
+1 -2
View File
@@ -2,9 +2,8 @@ import debug
import re
import os
import math
import verilog
class spice(verilog.verilog):
class spice():
"""
This provides a set of useful generic types for hierarchy
management. If a module is a custom designed cell, it will read from
+2 -1
View File
@@ -9,7 +9,8 @@ from collections import defaultdict
class lef:
"""
SRAM LEF Class open GDS file, read pins information, obstruction
and write them to LEF file
and write them to LEF file.
This is inherited by the sram_base class.
"""
def __init__(self,layers):
# LEF db units per micron
+145 -40
View File
@@ -1,60 +1,165 @@
import debug
class verilog:
""" Create a behavioral Verilog file for simulation."""
"""
Create a behavioral Verilog file for simulation.
This is inherited by the sram_base class.
"""
def __init__(self):
pass
def verilog_write(self,verilog_name):
""" Write a behavioral Verilog model. """
self.vf = open(verilog_name, "w")
self.vf.write("// OpenRAM SRAM model\n")
self.vf.write("// Words: {0}\n".format(self.num_words))
self.vf.write("// Word size: {0}\n\n".format(self.word_size))
self.vf.write("module {0}(DATA,ADDR,CSb,WEb,OEb,clk);\n".format(self.name))
self.vf.write("\n")
self.vf.write("module {0}(\n".format(self.name))
for port in self.all_ports:
if port in self.readwrite_ports:
self.vf.write("// Port {0}: RW\n".format(port))
elif port in self.read_ports:
self.vf.write("// Port {0}: R\n".format(port))
elif port in self.write_ports:
self.vf.write("// Port {0}: W\n".format(port))
if port in self.readwrite_ports:
self.vf.write(" clk{0},csb{0},web{0},ADDR{0},DIN{0},DOUT{0}".format(port))
elif port in self.write_ports:
self.vf.write(" clk{0},csb{0},ADDR{0},DIN{0}".format(port))
elif port in self.read_ports:
self.vf.write(" clk{0},csb{0},ADDR{0},DOUT{0}".format(port))
# Continue for every port on a new line
if port != self.all_ports[-1]:
self.vf.write(",\n")
self.vf.write("\n );\n\n")
self.vf.write(" parameter DATA_WIDTH = {0} ;\n".format(self.word_size))
self.vf.write(" parameter ADDR_WIDTH = {0} ;\n".format(self.addr_size))
self.vf.write(" parameter RAM_DEPTH = 1 << ADDR_WIDTH;\n")
self.vf.write(" // FIXME: This delay is arbitrary.\n")
self.vf.write(" parameter DELAY = 3 ;\n")
self.vf.write("\n")
self.vf.write(" inout [DATA_WIDTH-1:0] DATA;\n")
self.vf.write(" input [ADDR_WIDTH-1:0] ADDR;\n")
self.vf.write(" input CSb; // active low chip select\n")
self.vf.write(" input WEb; // active low write control\n")
self.vf.write(" input OEb; // active output enable\n")
self.vf.write(" input clk; // clock\n")
self.vf.write("\n")
self.vf.write(" reg [DATA_WIDTH-1:0] data_out ;\n")
self.vf.write(" reg [DATA_WIDTH-1:0] mem [0:RAM_DEPTH-1];\n")
for port in self.all_ports:
self.add_inputs_outputs(port)
self.vf.write("\n")
self.vf.write(" // Tri-State Buffer control\n")
self.vf.write(" // output : When WEb = 1, oeb = 0, csb = 0\n")
self.vf.write(" assign DATA = (!CSb && !OEb && WEb) ? data_out : {0}'bz;\n".format(self.word_size))
self.vf.write("\n")
self.vf.write(" // Memory Write Block\n")
self.vf.write(" // Write Operation : When WEb = 0, CSb = 0\n")
self.vf.write(" always @ (posedge clk)\n")
self.vf.write(" begin : MEM_WRITE\n")
self.vf.write(" if ( !CSb && !WEb ) begin\n")
self.vf.write(" mem[ADDR] = DATA;\n")
self.vf.write(" $display($time,\" Writing %m ABUS=%b DATA=%b\",ADDR,DATA);\n")
self.vf.write(" end\n")
self.vf.write(" end\n\n")
self.vf.write("\n")
self.vf.write(" // Memory Read Block\n")
self.vf.write(" // Read Operation : When WEb = 1, CSb = 0\n")
self.vf.write(" always @ (posedge clk)\n")
self.vf.write(" begin : MEM_READ\n")
self.vf.write(" if (!CSb && WEb) begin\n")
self.vf.write(" data_out <= #(DELAY) mem[ADDR];\n")
self.vf.write(" $display($time,\" Reading %m ABUS=%b DATA=%b\",ADDR,mem[ADDR]);\n")
self.vf.write(" end\n")
self.vf.write(" end\n")
for port in self.all_ports:
self.register_inputs(port)
# This is the memory array itself
self.vf.write("reg [DATA_WIDTH-1:0] mem [0:RAM_DEPTH-1];\n")
for port in self.all_ports:
if port in self.write_ports:
self.add_write_block(port)
if port in self.read_ports:
self.add_read_block(port)
self.vf.write("\n")
self.vf.write("endmodule\n")
self.vf.close()
def register_inputs(self, port):
"""
Register the control signal, address and data inputs.
"""
self.add_regs(port)
self.add_flops(port)
def add_regs(self, port):
"""
Create the input regs for the given port.
"""
self.vf.write(" reg csb{0}_reg;\n".format(port))
if port in self.readwrite_ports:
self.vf.write(" reg web{0}_reg;\n".format(port))
self.vf.write(" reg [ADDR_WIDTH-1:0] ADDR{0}_reg;\n".format(port))
if port in self.write_ports:
self.vf.write(" reg [DATA_WIDTH-1:0] DIN{0}_reg;\n".format(port))
if port in self.read_ports:
self.vf.write(" reg [DATA_WIDTH-1:0] DOUT{0};\n".format(port))
def add_flops(self, port):
"""
Add the flop behavior logic for a port.
"""
self.vf.write("\n")
self.vf.write(" // All inputs are registers\n")
self.vf.write(" always @(posedge clk{0})\n".format(port))
self.vf.write(" begin\n")
self.vf.write(" csb{0}_reg = csb{0};\n".format(port))
if port in self.readwrite_ports:
self.vf.write(" web{0}_reg = web{0};\n".format(port))
self.vf.write(" ADDR{0}_reg = ADDR{0};\n".format(port))
if port in self.write_ports:
self.vf.write(" DIN{0}_reg = DIN{0};\n".format(port))
if port in self.read_ports:
self.vf.write(" DOUT{0} = {1}'bx;\n".format(port,self.word_size))
if port in self.readwrite_ports:
self.vf.write(" if ( !csb{0}_reg && web{0}_reg ) \n".format(port))
self.vf.write(" $display($time,\" Reading %m ADDR{0}=%b DOUT{0}=%b\",ADDR{0}_reg,mem[ADDR{0}_reg]);\n".format(port))
elif port in self.read_ports:
self.vf.write(" if ( !csb{0}_reg ) \n".format(port))
self.vf.write(" $display($time,\" Reading %m ADDR{0}=%b DOUT{0}=%b\",ADDR{0}_reg,mem[ADDR{0}_reg]);\n".format(port))
if port in self.readwrite_ports:
self.vf.write(" if ( !csb{0}_reg && !web{0}_reg )\n".format(port))
self.vf.write(" $display($time,\" Writing %m ADDR{0}=%b DIN{0}=%b\",ADDR{0}_reg,DIN{0}_reg);\n".format(port))
elif port in self.write_ports:
self.vf.write(" if ( !csb{0}_reg )\n".format(port))
self.vf.write(" $display($time,\" Writing %m ADDR{0}=%b DIN{0}=%b\",ADDR{0}_reg,DIN{0}_reg);\n".format(port))
self.vf.write(" end\n\n")
def add_inputs_outputs(self, port):
"""
Add the module input and output declaration for a port.
"""
self.vf.write(" input clk{0}; // clock\n".format(port))
self.vf.write(" input csb{0}; // active low chip select\n".format(port))
if port in self.readwrite_ports:
self.vf.write(" input web{0}; // active low write control\n".format(port))
self.vf.write(" input [ADDR_WIDTH-1:0] ADDR{0};\n".format(port))
if port in self.write_ports:
self.vf.write(" input [DATA_WIDTH-1:0] DIN{0};\n".format(port))
if port in self.read_ports:
self.vf.write(" output [DATA_WIDTH-1:0] DOUT{0};\n".format(port))
def add_write_block(self, port):
"""
Add a write port block. Multiple simultaneous writes to the same address
have arbitrary priority and are not allowed.
"""
self.vf.write("\n")
self.vf.write(" // Memory Write Block Port {0}\n".format(port))
self.vf.write(" // Write Operation : When web{0} = 0, csb{0} = 0\n".format(port))
self.vf.write(" always @ (negedge clk{0})\n".format(port))
self.vf.write(" begin : MEM_WRITE{0}\n".format(port))
if port in self.readwrite_ports:
self.vf.write(" if ( !csb{0}_reg && !web{0}_reg )\n".format(port))
else:
self.vf.write(" if (!csb{0}_reg)\n".format(port))
self.vf.write(" mem[ADDR{0}_reg] = DIN{0}_reg;\n".format(port))
self.vf.write(" end\n")
def add_read_block(self, port):
"""
Add a read port block.
"""
self.vf.write("\n")
self.vf.write(" // Memory Read Block Port {0}\n".format(port))
self.vf.write(" // Read Operation : When web{0} = 1, csb{0} = 0\n".format(port))
self.vf.write(" always @ (negedge clk{0})\n".format(port))
self.vf.write(" begin : MEM_READ{0}\n".format(port))
if port in self.readwrite_ports:
self.vf.write(" if (!csb{0}_reg && web{0}_reg)\n".format(port))
else:
self.vf.write(" if (!csb{0}_reg)\n".format(port))
self.vf.write(" DOUT{0} <= #(DELAY) mem[ADDR{0}_reg];\n".format(port))
self.vf.write(" end\n")