基本算法
ROM乘法器的算法比较简单,即使用一个ROM保存乘法的结果,在需要运算的时候直接到相应的地址去查表即可。例如计算两个4位二进制数的乘法a*b
,那么需要一个八位输入八位输出的ROM存储计算结果即可,其地址与存储数据的关系为:地址{a,b}
(位拼接)存储a*b(例如地址为8'b00010010
存储的结果就是0001*0001=8'b00000010
)
这种情况下使用的ROM比较大,所以在时序要求不严格的时候可以用时钟换面积,例如对于8位*8位的ROM乘法器,我们将其拆成乘数1高4位,低4位和乘数2高4位低4位两两相乘。高四位和高四位相乘后结果向左位移4位,高四位和低四位相乘结果往左移2位,低四位和低四位相乘结果不变累加(就是手算乘法常用的套路)可得在四个(最少)时钟周期后得到结果,使用的ROM可由16*16降到4*4
单个ROM乘法器
Python生成器
单个ROM在Verilog中可以使用case语句模拟,手写这种重复化很高的case语句无疑是一种效率很低的方法,本次使用Python语句生成
class ROMGenerator(object):
"""docstring for ROMGenerator"""
def __init__(self, Width):
super(ROMGenerator, self).__init__()
self.Width = Width
def GeneratorROM(self, FileName):
RomContent = ["""
module ROM_%s (
input [%s:0]addr,
output reg [%s:0]dout
);
always @(*) begin
case(addr)\
""" % (self.Width, self.Width * 2 - 1, self.Width * 2 - 1)]
for i in range(2 ** self.Width):
for j in range(2 ** self.Width):
RomContent.append(
"\t\t%s\'d%s:dout = %s\'d%s;" %
(2 * self.Width, i * (2 ** self.Width) + j,
2 * self.Width, i * j))
RomContent.append("""\t\tdefault:dout = \'b0;
endcase
end
endmodule
""")
with open("./%s.v" % FileName, "w") as filepoint:
filepoint.write("\n".join(RomContent))
return "\n".join(RomContent)
if __name__ == '__main__':
test = ROMGenerator(4)
print(test.GeneratorROM("ROM_4"))
代码很简单,除了开头和结尾以外,就是对于批量化生成需要的\t\t%s\'d%s:dout = %s\'d%s;
测试平台
测试时使用Sy