基於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部落格;