基于查找表的4位二进制数乘法器设计
1. 设计要求:
设计一个4位二进制数乘法器,采用查找表实现。
2. 设计分析
2.1 架构设计
4位乘法器的框图如下图所示。其中,a[3:0]为被乘数,b[3:0]为乘数,m[7:0]为积,即乘法结果。
2.2 查找表
查表法,就是建一个表,里面存放了所有的乘法结果,乘数和被乘数用来作为地址去里面的乘积,此种方法可以大大提高乘法的速率,但是当乘法位数很大时会要求产生很大的表格,所以此种方法适合位数较小的乘法,特别适合有一个乘数为固定的乘法,如滤波器中的乘法就可以采用此种方法设计…
具体操作如下:设 A,B 为两个 4 位二进制数,则 A,B 各有16种取值可能,乘积有 16*16=256 种可能。我们先将{A,B}对应的 256 种可能结果存储起来,然后对于每一特点的输入组合{A,B},找到对应的输出即可。该方式速度很快,只取决于读取存储器的速度,但是预存结果要占用较多资源,因此是面积换取速度思想的体现。同时,随着乘数位宽的增加,需要存储的结果迅速增加,不利于实现,因此该方式适用于位宽很小的情况。但是我们可以将高位宽的数据分解成低位宽的数据再调用查找表乘法器。
3. 设计实现
1 module rom_mult_4bit( 2 input wire clk, 3 input wire [3:0] a, 4 input wire [3:0] b, 5 6 output wire [7:0] m 7 ); 8 9 rom_mult_data rom_mult_data_inst( 10 .address ({a,b}), 11 .clock (clk), 12 .q (m) 13 ); 14 15 endmodule
MATLAB生成16*16的乘法口诀表,对ROM_IP进行初始化。
1 clear all;clc;close all; 2 depth = 256; %存储器的深度 3 width = 8; %存储器的宽度 4 fid = fopen('rom_mult_4bit.mif','w');%fopen函数以写方式打开文件,如不存在,自动创建 5 fprintf(fid, 'DEPTH=%d;\n', depth); %fprintf函数可以将数据按指定格式写入到文本文件中 6 fprintf(fid, 'WIDTH=%d;\n', width); %数据的格式化输出:fprintf(fid, format, variables) 7 fprintf(fid, 'ADDRESS_RADIX=UNS;\n');%\n是换行,使光标下移一格 8 fprintf(fid, 'DATA_RADIX=UNS;\n'); 9 fprintf(fid, 'CONTENT BEGIN\n'); 10 for a = 0 : 15 11 for b = 0 : 15 12 addr = a * 16 + b; %在Verilog中,等价于{a[3:0],b[3:0]} 13 num = a * b; 14 fprintf(fid, '%d : %d;\n',addr,num); 15 end 16 end 17 fprintf(fid, 'END;'); 18 fclose(fid);
4. 仿真测试
1 `timescale 1ns/1ps 2 3 module rom_mult_4bit_tb(); 4 5 reg clk; 6 reg [3:0] a; 7 reg [3:0] b; 8 9 wire [7:0] m; 10 wire [7:0] tb_m; 11 reg [7:0] tb_m_r; 12 reg [7:0] tb_m_rr; 13 14 assign tb_m = a * b; 15 16 always@(posedge clk)begin 17 tb_m_r <= tb_m; 18 tb_m_rr <= tb_m_r; 19 end 20 21 rom_mult_4bit rom_mult_4bit_inst( 22 .clk (clk), 23 .a (a), 24 .b (b), 25 26 .m (m) 27 ); 28 29 initial clk = 1'b0; 30 always #10 clk = ~clk; 31 32 initial begin 33 a = 4'd0; b = 4'd0; 34 #20; 35 repeat(10)begin 36 a = {$random}%16; 37 b = {$random}%16; 38 #20; 39 end 40 #50; 41 $stop; 42 end 43 44 endmodule