1、原理简介    

       乘法器的另一种实现思想是采用ROM的方式,即将被乘数和乘数连接起来拼成地址,把两者所有可能的乘积按照地址放在ROM的地址空间中,两个数相乘时,根据两者构成的地址从ROM中读取乘积结果。ROM可采用分布式逻辑资源实现(用于存储数据量小的情况比较合适),也可采用嵌入式BRAM实现(用于存储量数据大的情况比较合适)。
       两个N-bit的二进制数相乘,其结果为2N-bit。这意味着ROM的深度为2的2N次方,宽度为2N。以两个4-bit数相乘为例,其存储空间的大小为256x8-bit(256为深度,8为宽度),显然,随着位宽的增加存储空间将以指数速度膨胀。
       改进方法:将被乘数和乘数进行位分解,即将大位宽的数分解为多个小位宽的数来分别相乘。例如两个4-bit数相乘,可将4-bit数分解成两个2-bit数,为了保证最终乘积结果的正确性,需要对中间结果进行移位。为方便起见,以两个无符号二进制数1101(对应十进制为11)和0110(对应十进制数为0110)相乘为例。其相乘位分解处理流程如下图所示。
 

采用的ROM深度为16,宽度为4。存储的内容为两个无符号数相乘的结果。地址及其对应的存储内容如下:

地址
0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
1011
1100
1101
1110
1111
内容(十进制)
0
0
0
0
0
1
2
3
0
2
4
6
0
3
6
9
内容(十进制)
0000
0000
0000
0000
0000
0001
0010
0011
0000
0010
0100
0110
0000
0011
0110
1001
2、verilog代码实现
       2.1节介绍ROM使用Distributed Memory Generator生成的IP核。2.2节介绍使用Xilinx原语生成的ROM(其实使用的也是分布式资源)。Block Memeory Generator生成的IP核使用的是BlockRAM,当存储大量数据时,使用比较方便,和Distributed Memory Generator类似,不再详细介绍。
2.1 ROM采用分布式资源生成的IP核
 

设置ROM的位宽,深度等。
 

ROM进行初始化,采用coe文件。
 

coe文件的内容为:
MEMORY_INITIALIZATION_RADIX=10;
MEMORY_INITIALIZATION_VECTOR=
0,
0,
0,
0,
0,
1,
2,
3,
0,
2,
4,
6,
0,
3,
6,
9;
说明:MEMORY_INITIALIZATION_RADIX=10,表明下面的数据为10进制,还可以取值2,8,16。
MEMORY_INITIALIZATION_VECTOR=,后面的内容依次为地址(0-15)所存储的内容,中间用逗号分隔,最后用分号。
最后生成ROM核。
verilog代码实现
module rom_top(
         input clk,
         input rst_n,
         input [3:0] a,
         input [3:0] b,
         output [7:0] c
         );
         wire [3:0] spo0,spo1,spo2,spo3;
         wire [3:0] a0,a1,a2,a3;
        
         assign a0={a[3:2],b[3:2]};
         assign a1={a[3:2],b[1:0]};
         assign a2={a[1:0],b[3:2]};
         assign a3={a[1:0],b[1:0]};
 
      &nb