一、移位相加法实现乘法的原理
从被乘数的左边(最低位)开始,如果第 i 位为 1,则乘数左移 i (i = 0,1,2,······,size -1)位之后与之前的值相加,若最低位为 0 ,则保持不变,直至被乘数的最高位。
如:a = b = 101
a x b = 25
sum = 0;
101 第0位为 1, sum = sum + a << 0
101 第1位为 0 ,sum = sum
101 第3位为 1, sum = sum + a << 2
二、移位相加法实现8bit乘法器源码
1 // ********************************************************************************* 2 // Project Name : mul_add 3 // Email : 4 // Create Time : 2020/07/18 20:20 5 // Module Name : mul_add 6 // editor : qing 7 // Version : Rev1.0.0 8 // ********************************************************************************* 9 10 module mul_add( 11 input sclk , 12 input s_rst_n , 13 14 input start , 15 input [7:0] x , // 乘数 16 input [7:0] y , // 被乘数 17 18 output reg [15:0] result 19 ); 20 21 //======================================================================== 22 // =========== Define Parameter and Internal signals =========== 23 //========================================================================/ 24 reg [7:0] cnt ; 25 reg [15:0] x_r ; // 乘数的中间变量 26 reg flag ; 27 reg [15:0] result_r ; 28 29 //============================================================================= 30 //**************************** Main Code ******************************* 31 //============================================================================= 32 33 always @(*) begin 34 x_r = {8'd0,x}; 35 end 36 37 always @(posedge sclk or negedge s_rst_n) begin // cnt 38 if(!s_rst_n) 39 cnt <= 0; 40 else if(start == 1'b1) 41 cnt <= 7; 42 else if(cnt == 0) 43 cnt <= cnt; 44 else 45 cnt <= cnt - 1'b1; 46 end 47 48 always @(posedge sclk or negedge s_rst_n) begin 49 if(!s_rst_n) 50 flag <= 1'b0; 51 else if(start == 1'b1) 52 flag <= 1'b1; 53 else if(cnt == 0) 54 flag <= 1'b0; 55 end 56 57 always @ (posedge sclk or negedge s_rst_n) begin 58 if(s_rst_n == 1'b0) begin 59 result_r <= 0; 60 end 61 else if(flag == 1'b1)begin 62 case(cnt) 63 8'd7:begin 64 if(y[0] == 1'b1) 65 result_r <= result_r + x_r; 66 else 67 result_r <= result_r; 68 end 69 8'd6:begin 70 if(y[1] == 1'b1) 71 result_r <= result_r + (x_r << 1); 72 else 73 result_r <= result_r; 74 end 75 8'd5:begin 76 if(y[2] == 1'b1) 77 result_r <= result_r + (x_r << 2); 78 else 79 result_r <= result_r; 80 end 81 8'd4:begin 82 if(y[3] == 1'b1) 83 result_r <= result_r + (x_r << 3); 84 else 85 result_r <= result_r; 86 end 87 8'd3:begin 88 if(y[4] == 1'b1) 89 result_r <= result_r + (x_r << 4); 90 else 91 result_r <= result_r; 92 end 93 8'd2:begin 94 if(y[5] == 1'b1) 95 result_r <= result_r + (x_r << 5); 96 else 97 result_r <= result_r; 98 end 99 8'd1:begin 100 if(y[6] == 1'b1) 101 result_r <= result_r + (x_r << 6); 102 else 103 result_r <= result_r; 104 end 105 8'd0:begin 106 if(y[7] == 1'b1) 107 result_r <= result_r + (x_r << 7); 108 else 109 result_r <= result_r; 110 end 111 default:begin 112 result_r <= 0; 113 end 114 endcase 115 end 116 else 117 result_r <= 0; 118 end 119 120 //assign result = ((cnt == 0) && (flag == 1'b1)) ? result_r : result; 121 122 always @(posedge sclk or negedge s_rst_n) begin 123 if(!s_rst_n) 124 result <= 0; 125 else if(cnt == 0 && flag == 1'b1) 126 result <= result_r; 127 end 128 129 130 endmodule
testbench:
1 `timescale 1ns/1ps 2 module mul_add_tb; 3 reg sclk ; 4 reg s_rst_n ; 5 reg start ; 6 reg [7:0] x ; 7 reg [7:0] y ; 8 wire [15:0] result ; 9 10 mul_add mul_add_inst( 11 .sclk (sclk ), 12 .s_rst_n (s_rst_n ), 13 .start (start ), 14 .x (x ), 15 .y (y ), 16 .result (result ) 17 ); 18 19 initial 20 sclk = 1'b0; 21 always #10 sclk = ~sclk; 22 23 initial 24 begin 25 #1; 26 s_rst_n = 1'b0; 27 x = 8'd0; 28 y = 8'd0; 29 start = 1'b0; 30 #21; 31 s_rst_n = 1'b1; 32 #21; 33 34 x = 8'd4; 35 y = 8'd5; 36 start = 1'b1; 37 #25; 38 start = 1'b0; 39 40 #200; 41 x = 8'd22; 42 y = 8'd30; 43 #31; 44 start = 1'b1; 45 #25; 46 start = 1'b0; 47 48 end 49 endmodule
Modelsim仿真结果:
移位相加法实现乘法的优点是占用的资源较少;缺点是速度比较慢,一个结果的输出需要花费多个时钟周期,在高位宽乘法运算中极为明显
该乘法器所占用的资源是所有类型乘法器中最少的,在低速的信号处理中有广泛的使用(还未完全理解)
1 module mul_add( 2 input sclk , 3 input s_rst_n , 4 5 //input start , 6 input [7:0] x , // 乘数 7 input [7:0] y , // 被乘数 8 9 output reg [15:0] result 10 ); 11 12 //======================================================================== 13 // =========== Define Parameter and Internal signals =========== 14 //========================================================================/ 15 reg [7:0] cnt ; 16 reg [15:0] x_r ; // 乘数的中间变量 17 reg [7:0] y_r ; // 被乘数的中间变量 18 reg [15:0] result_r ; // 运算结果的中间变量 19 reg [2:0] state ; // 20 21 parameter S0 = 3'd0 ; 22 parameter S1 = 3'd1 ; 23 parameter S2 = 3'd2 ; 24 25 //============================================================================= 26 //**************************** Main Code ******************************* 27 //============================================================================= 28 29 30 31 always @ (posedge sclk or negedge s_rst_n) begin 32 if(s_rst_n == 1'b0) begin 33 result <= 0; 34 cnt <= 0; 35 y_r <= 0; 36 state <= S0; 37 end 38 else begin 39 case(state) 40 S0:begin 41 x_r <= {8'd0,x}; 42 y_r <= y; 43 cnt <= 0; 44 result_r <= 0; 45 state <= S1; 46 end 47 48 S1:begin 49 if(cnt == 7) 50 state <= S2; 51 else begin 52 if(y_r[0] == 1'b1) 53 result_r <= result_r + x_r; // 和左移零位相似 54 else 55 result_r <= result_r; 56 y_r <= y_r >> 1; // 被乘数右移一位 57 x_r <= x_r << 1; // 乘加一次后,被乘数左移一位 58 cnt <= cnt + 1'b1; 59 state <= S1; 60 end 61 end 62 63 S2:begin 64 result <= result_r; 65 state <= S0; 66 end 67 default:; 68 endcase 69 end 70 end 71 endmodule