基于ROM的位分解4位二进制数乘法器设计
1 设计要求
设计一个4位二进制数乘法器,采用查找表实现(这里将高位宽的数据分解成低位宽的数据再调用查找表乘法器)。
2 设计分析
2.1 架构设计
4位乘法器的框图如下图所示。其中,clk为系统时钟,rst_n系统复位,低电平有效,a[3:0]为被乘数,b[3:0]为乘数,out[7:0]为积。
2.2 原理分析
(1)ROM原理
乘法器的一种实现思想是采用ROM的方式,即将被乘数和乘数连接起来拼成地址,把两者所有可能的乘积按照地址号存放在ROM的地址空间中,两个数相乘时,根据两者构成的地址从ROM索取乘积结果。
如两个1bit的数相乘,可能的相乘方式有0x1,0x0,1x1,1x0,一共四种相乘方式,其对应的结果也有四种,即0,0,1,0。那么如果将这四个结果存在ROM中,其实正好用01,00,11,10四个地址来寻址。因此是可以把所有的乘积结果都包含在内的。
通俗的来说,两个Nbit二进制数相乘,其结果为2Nbit,这意味着ROM的深度为2^(2N),宽度为(2N),占用的空间大小为2^(2N)x2N。以两个4bit 的数相乘例子,其存储空间大小为256x8bit。显然随着位宽的增长,存贮空间将以指数速度膨胀,这是这个方法的一个弊端。
(2)位分解原理
由于上述弊端的存在 ,一种改进方法就是进行位分解,将两个大位宽的数相乘分解为多个小位宽的数相乘。例如,设 A,B 为两个 8 位数据,可将 A 分解为 A=A1×16+A2,其中 A1 为高 4 位,A2 为低 4 位;同理 B=B1×16+B2,然后A×B=(A1×16+A2)×(B1×16+B2)=A1*B1*16*16 + A1*B2*16 + A2*B1*16 + A2*B2(此处可以用左移来表示)。这样就将两个 8 位数的相乘转化为 4 组 4 位数相乘,然后再相加,其中乘以常数可以通过移位运算实现,大大地缩减了存储空间,其硬件结构如下图所示:
(3)4位二进制数乘法器
根据公式 A=A1×2^N+A2 可得知 N=2;最后得到式子:
A*B=(A1*4+A2)*(B1*4+B2)=A1*B1*4*4+A1*B2*4+A2*B1*4+A2*B3
A[3:0]×B[3:0] = A[3:2]×B[3:2]+ A[1:0]×B[3:2] +
A[3:2]×B[1:0] + A[1:0]×B[1:0] = (outa *16) + (outb *4)+ (outc *4) + outd= (outa << 4) + (outb << 2) + (outc << 2) + outd;
2.3 架构设计
3 设计实现
3.1 顶层设计
1 module rom_mult_4bit( 2 input wire clk, 3 input wire rst_n, 4 input wire [3:0] a, 5 input wire [3:0] b, 6 7 output reg [7:0] out 8 ); 9 10 wire [3:0] outa; 11 wire [3:0] outb; 12 wire [3:0] outc; 13 wire [3:0] outd; 14 15 rom_mult_2bit rom_mult_2bit0( 16 .clk (clk), 17 .rst_n (rst_n), 18 .a (a[3:2]), 19 .b (b[3:2]), 20 .out (outa) 21 ); 22 23 rom_mult_2bit rom_mult_2bit1( 24 .clk (clk), 25 .rst_n (rst_n), 26 .a (a[3:2]), 27 .b (b[1:0]), 28 .out (outb) 29 ); 30 31 rom_mult_2bit rom_mult_2bit2( 32 .clk (clk), 33 .rst_n (rst_n), 34 .a (a[1:0]), 35 .b (b[3:2]), 36 .out (outc) 37 ); 38 39 rom_mult_2bit rom_mult_2bit3( 40 .clk (clk), 41 .rst_n (rst_n), 42 .a (a[1:0]), 43 .b (b[1:0]), 44 .out (outd) 45 ); 46 47 always@(posedge clk or negedge rst_n)begin 48 if(rst_n == 1'b0) 49 out <= 8'd0; 50 else 51 out <= (outa << 4) + (outb << 2) + (outc << 2) + outd; 52 end 53 54 endmodule
3.2 基于rom的2位乘法器设计
1 module rom_mult_2bit( 2 input wire clk, 3 input wire rst_n, 4 input wire [1:0] a, 5 input wire [1:0] b, 6 7 output reg [3:0] out 8 ); 9 10 always@(posedge clk or negedge rst_n)begin 11 if(rst_n == 1'b0) 12 out <= 4'd0; 13 else begin 14 case({a,b}) 15 4'b0000 : out <= 4'd0; 16 4'b0001 : out <= 4'd0; 17 4'b0010 : out <= 4'd0; 18 4'b0011 : out <= 4'd0; 19 20 4'b0100 : out <= 4'd0; 21 4'b0101 : out <= 4'd1; 22 4'b0110 : out <= 4'd2; 23 4'b0111 : out <= 4'd3; 24 25 4'b1000 : out <= 4'd0; 26 4'b1001 : out <= 4'd2; 27 4'b1010 : out <= 4'd4; 28 4'b1011 : out <= 4'd6; 29 30 4'b1100 : out <= 4'd0; 31 4'b1101 : out <= 4'd3; 32 4'b1110 : out <= 4'd6; 33 4'b1111 : out <= 4'd9; 34 default : out <= 4'd0; 35 endcase 36 end 37 end 38 39 endmodule
4 仿真验证
1 `timescale 1ns/1ps 2 3 module rom_mult_4bit_tb(); 4 5 reg clk; 6 reg rst_n; 7 reg [3:0] a; 8 reg [3:0] b; 9 10 wire [7:0] out; 11 12 wire [7:0] tb_out; 13 reg [7:0] tb_out_r; 14 reg [7:0] tb_out_rr; 15 16 assign tb_out = a * b; 17 18 always@(posedge clk)begin 19 tb_out_r <= tb_out; 20 tb_out_rr <= tb_out_r; 21 end 22 23 rom_mult_4bit rom_mult_4bit_inst( 24 .clk (clk), 25 .rst_n (rst_n), 26 .a (a), 27 .b (b), 28 29 .out (out) 30 ); 31 32 initial clk = 1'b0; 33 always #10 clk = ~clk; 34 35 initial begin 36 rst_n = 1'b0; a = 4'd0; b = 4'd0; 37 #21; rst_n = 1'b1; 38 #20; 39 repeat(10)begin 40 a = {$random}%16; 41 b = {$random}%16; 42 #20; 43 end 44 #50; 45 $stop; 46 end 47 48 endmodule
5 参考文献:
(1)(49条消息) 乘法器设计(二):基于ROM的乘法器设计_MaoChuangAn的博客-CSDN博客;