【Verilog】布斯算法(Booth Algorithm)乘法器的 Verilog 实现

 

目录

布斯算法介绍

计算步骤

计算流程图

举个栗子

Verilog 实现

设计思想

Verilog 代码

TestBench 代码

仿真波形


 

布斯算法介绍

Booth 的算法检查有符号二的补码表示中 'N'位乘数 Y 的相邻位对,包括低于最低有效位 y−1 = 0 的隐式位。对于每个位 yi,对于从 0 到 N − 1 的 i,考虑位 yi 和 yi−1。当这两个位相等时,乘积累加器P保持不变。其中 yi = 0 且 yi−1 = 1,乘以 2i 添加到 P;其中 yi = 1 且 yi−1 = 0,则从 P 中减去乘以 2iP 的最终值为有符号产品。

未指定乘数和乘积的表示形式;通常,这些也都在二的补码表示中,就像乘数一样,但是任何支持加法和减法的数字系统也可以工作。如此处所述,步骤的顺序尚未确定。通常,它从LSB到MSB,从i = 0开始;然后乘以2i通常被P累加器在步长之间向右的增量移位所取代;低位可以移出,然后可以在P的最高N位上进行后续的加法和减法。

该算法通常被描述为将乘数中 1 的字符串转换为字符串末端的高阶 +1 和低阶 −1。当字符串通过 MSB 运行时,没有高阶 +1,并且净效应被解释为相应值的负数。

计算步骤

使用的寄存器:A,M,Q,Qres(Qres是Q右移后的残余位),n(计数器)
 
第 1 步: 加载寄存器的初始值。
A = 0(累加器),Qres = 0,M = 乘法,Q = 乘法器,n是等于乘法器位数的计数值。
第 2 步:检查 {Q0,Qres} 的值。如果为 00 或 11,请转到步骤 5。如果为01,转到步骤3。如果为 10,转到步骤 4。
第 3 步:执行 A = A + M,转到步骤 5。       
第 4 步:执行 A = A - M。
第 5 步:执行 {A,Q,Qres} 的算术位移和递减计数。
第 6 步: 检查计数器值 n 是否为零。如果是,请转到下一步。否则转到步骤 2。
第 7 步:停止计算,输出计算结果。
 

计算流程图

以下是布斯计算的流程图,从图中可以清楚的看出计算的过程,简单的来说就是判定乘数的最低位和次低位,如果两位相同则直接执行移位操作,如果两者不同,如为“10”则将原始值减去被乘数,如为“01”则将原始值加上被乘数

bad7d628bf6b4624a5333b9df6ddbdda.png

举个栗子

下面就以被乘数为6,乘数为-4为例,做一个计算过程的举例。

df001b6900a841f88829bcdd6361b497.jpeg

  1. 将所有寄存器初始化,累加器A初始化为0,乘数加载寄存,最低位移出位设定位0。
  2. 判定最低位和移出位为“00”,不进行加减操作,将结果结果值右移一位。
  3. 判定最低位和移出位为“00”,不进行加减操作,将结果结果值右移一位。
  4. 判定最低位和移出位为“10”,对累加器减去被乘数,并将结果结果值右移一位,注意此时累加器A为负数。
  5. 判定最低位和移出位为“10”,不进行加减操作,将结果结果值右移一位,此时累加器为负数,因此右移最高位补1。
  6. 判定最低位和移出位为“10”,不进行加减操作,将结果结果值右移一位,此时累加器为负数,因此右移最高位补1。
  7. 计数器为0表示计算完成,停止计算并输出计算结果值。

Verilog 实现

设计思想

总的来说和上面提到的计算步骤是一致的,利用三段状态机实现,分别为空闲状态、计算状态和完成状态,其中空闲状态等待开始计算信号的到来,计算状态完成布斯计算步骤,完成状态输出结果数据以及同步的有效标志信号。

Verilog 代码

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/* Engineer    : Linest-5                                                         
/* File        : booth_multiple.v                                                         
/* Create      : 2022-08-27 16:40:34
/* Revise      : 2022-08-27 16:40:34                                                  
/* Module Name : booth_multiple                                                  
/* Description : 基于布斯算法的乘法器设计                                                                         
/* Editor : sublime text3, tab size (4)                                                                                
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

module booth_multiple(
	input                     clk,
	input                     rst,
	input                     start,
	input      signed [3:0]   X,
	input      signed [3:0]   Y,
	output reg signed [7:0]   Z,
	output                    valid
	);

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*      参数和信号申明                                                              */
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
parameter  IDLE      =  3'b001;
parameter  CACULATE  =  3'b010;
parameter  FINISH    =  3'b100;

reg        [2:0]   state;
reg        [2:0]   next_state;
reg        [1:0]   q_reg;           //右移最后两位寄存 
reg        [2:0]   cnt;             //右移次数计数信号  

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*      三段状态机                                                                  */
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
//状态机第一段,状态初始化,时序逻辑非阻塞赋值
always @(posedge clk or posedge rst) begin
	if (rst) begin
		state <= IDLE;
	end
	else begin
		state <= next_state;
	end
end

//状态机第二段,状态跳转,组合逻辑阻塞赋值
always @(*) begin
	next_state = state;
	case(state)
		IDLE: begin
			if (start) begin
				next_state = CACULATE;
			end
			else begin
				next_state = IDLE;
			end
		end
		CACULATE: begin
			if (cnt == 'd3) begin
				next_state = FINISH;
			end
			else begin
				next_state = CACULATE;
			end
		end
		FINISH: begin
			next_state = IDLE;
		end
	endcase
end

//状态机第三段,结果输出,时序逻辑非阻塞赋值
always @(posedge clk or posedge rst) begin
	if (rst) begin
		cnt   <= 'd0;
		q_reg <= 'd0;
		Z     <= 'd0;
	end
	else begin
		case(state)
			IDLE: begin
				cnt   <= 'd0;
				q_reg <= {Y[cnt],1'b0};
				Z     <= {4'b0000,Y};
			end
			CACULATE: begin
				cnt   <= cnt + 'd1;
				q_reg <= {Y[cnt+1],Y[cnt]};
				case(q_reg)
					2'b00,2'b11: begin
						Z <= $signed(Z)>>>1;
					end
					2'b10: begin
						Z <= $signed({Z[7:4]-X,Z[3:0]})>>>1;
					end
					2'b01: begin
						Z <= $signed({Z[7:4]+X,Z[3:0]})>>>1;						
					end
				endcase
			end
			FINISH: begin
				cnt   <= 'd0;
				q_reg <= 'd0;
				Z     <= Z;				
			end					
		endcase
	end
end

assign valid = (state==FINISH);

endmodule

TestBench 代码

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/* Engineer    : Linest-5                                                         
/* File        : tb_booth_multiple.v                                                         
/* Create      : 2022-08-27 19:22:46
/* Revise      : 2022-08-27 20:21:49                                                  
/* Module Name : tb_booth_multiple                                                  
/* Description : 基于布斯算法的乘法器仿真模块                                                                         
/* Editor : sublime text3, tab size (4)                                                                                
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

`timescale 1ns/1ns
module tb_booth_multiple();
	reg                 clk;
	reg                 rst;
	reg                 start;
	reg  signed [3:0]   X;
	reg  signed [3:0]   Y;
	wire signed [7:0]   Z;
	wire                valid;

	initial begin
		clk = 'd0;
		rst = 'd1;
		#20
		rst = 'd0;
	end

	always #10 clk = ~clk;

	initial begin
		#20
		X = 6;
		Y = -4;
		start = 'd0;
		#50
		start = 'd1;
		#20
		start = 'd0;
		#200
		X = 7;
		Y = -5;
		start = 'd1;
		#20
		start = 'd0;
		#200
		X = 7;
		Y = 5;
		start = 'd1;
		#20
		start = 'd0;
	end


booth_multiple inst_booth_multiple (
	.clk   (clk),
	.rst   (rst),
	.start (start),
	.X     (X),
	.Y     (Y),
	.Z     (Z),
	.valid (valid)
);

endmodule

仿真波形

分别进行有符号的乘法,6和-4、7和-5、7和5,可以看到仿真波形中,正确的得到了计算结果,并且有效标志信号也同步输出。

验证成功!

3a895b8051804f9592de9331e0ef2785.png

 

  • 15
    点赞
  • 74
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
### 回答1: 16位Booth乘法器Verilog的代码如下: module booth_multiplier(input signed [15:0] multiplicand, input signed [15:0] multiplier, output signed [31:0] product); reg signed [15:0] A; reg signed [15:0] S; reg signed [31:0] P; assign product = P; always @(*) begin A = multiplicand; S = -multiplicand; P = 0; for (int i = 0; i < 16; i = i + 1) begin if (multiplier[0] == 1 && P[0] == 0) begin P = P + A; end else if (multiplier[0] == 0 && P[0] == 1) begin P = P + S; end A = A << 1; S = S << 1; multiplier = multiplier >> 1; end end endmodule 这个模块接受两个16位有符号整数作为输入,使用Booth算法计算它们的乘积,并将结果作为一个32位有符号整数输出。Booth算法是一种快速的乘法算法,它利用了二进制补码的特性,可以在较短的时间内完成大数乘法运算。 ### 回答2: 16位booth乘法器verilog可以基于booth算法实现booth算法是一种利用位移操作的乘法算法,它可以将n位数乘以m位数的运算,转换为n+m位数的加法运算,从而提高运算速度。 在verilog中,可以定义输入端口A、B和输出端口P。首先需要将乘数A和被乘数B扩展为32位有符号整数,然后根据booth算法进行运算。 verilog代码如下: module booth_multi(input signed [15:0] A, input signed [15:0] B, output signed [31:0] P); reg signed [31:0] P_reg; reg [4:0] count; always @(A or B) begin count <= 0; P_reg <= {16'b0, A}; repeat(16) begin if ((P_reg[1:0] == 2'b01) || (P_reg[1:0] == 2'b10)) begin P_reg <= P_reg + (B << 1); end else if ((P_reg[1:0] == 2'b11) || (P_reg[1:0] == 2'b00)) begin P_reg <= P_reg - (B << 1); end P_reg[31:17] <= P_reg[30]; P_reg[30] <= P_reg[29]; P_reg[29:0] <= P_reg[28:1]; count <= count + 1; end P <= P_reg; end endmodule 这段代码实现了16位booth乘法器,输入为16位有符号整数A和B,输出为32位有符号整数P。首先,通过repeat语句循环16次,对输入的乘数和被乘数进行位移和加减操作,最终得到32位的结果。同时,根据booth算法的特点,通过移位操作还可以保留16位的结果,再通过输出P_reg实现结果的输出。最后,通过count统计循环次数,有效地进行n+m位数的加法运算。 ### 回答3: Booth乘法器是一种用于高速乘法的电路,常用于数字信号处理器、FPGA、ASIC数字电路设计中。其主要原理是通过改变乘数的每一位,将乘法运算转化成加法运算。而16位Booth乘法器则是指将两个16位的二进制数进行乘法运算。 在Verilog中,可以利用多个模块实现16位Booth乘法器。其中,最主要的是16位二进制乘法器模块,它可以将两个16位的二进制数相乘,并输出一个32位的结果。此外,还需要一个模块对输入的乘数进行扩展,使之成为带符号的二进制数。接着,还需要一个计算器模块,对输入信号进行相加减,从而实现Booth算法中的乘法器。最后,还要一个模块,将输出的32位二进制数进行截取和舍入,得到16位的结果。 以下是一个可能的Verilog代码实现: module booth16x16(input signed [15:0] a,b,CLK,RESET,output reg signed [31:0] pro); reg [15:0] A; reg [15:0] B; wire temp_in; reg [4:0] cnt; reg [32:0] pres; initial begin cnt=0; pres=33'b0; end always @(a,b,RESET) begin if(RESET) begin pres=0; cnt=0; end else if(CLK) begin A=a; B=b; cnt<=cnt+1; if(cnt<=16) begin if(B[0]==1) pres<=pres-(A<<(cnt-1)); else pres<=pres+(A<<(cnt-1)); end temp_in<=B[0]; B<={B[15],B[15:1]}; end end assign pro=pres[31:16]; endmodule 该代码中,输入参数a和b为16位有符号的二进制数,CLK为时钟信号,RESET为复位信号,pro为输出的16位乘积结果。 在always块中,首先检查RESET信号是否为真,若为真则将计数器cnt和结果寄存器pres清零;接着检查CLK信号是否为真,若为真则开始计算。 在计算时,先对输入的乘数进行扩展(由于上述代码输入的已经是有符号的16位二进制数,所以这个过程被省略了),然后根据Booth算法的规则进行乘法运算。在每次计算过程中,将乘数向右移动一位,并通过模拟电路将得到的乘积结果加到结果寄存器中。最后,根据组合逻辑实现,输出结果。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Linest-5

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值