FPGA通过移位相加实现有符号乘法器(参数化,封装成IP可直接调用)

微信公众号获取更多FPGA相关源码:
在这里插入图片描述

1.前言

上一篇博客实现了无符号移位相加乘法器,有符号乘法器和无符号的原理是一样的,只不过需要进行符号位的处理。

2.原理

一些资料中,对于有符号数乘法,是这么处理的:以(-3)x(-6)为例,Verilog中有符号数用补码表示,正数的补码是他本身,负数的补码是符号位不变,其他位的反码加1。(-3)的补码是 1101,(-6)的补码是 1010,为了保证结果的正确,首先要将两个数进行符号位扩展,扩展为8bits。有符号位扩展,高位补1,所以(-3)就变为 11111101 ,(-6)就变为 11111010 。然后其计算步骤与无符号移位相加乘法器计算步骤一致。

有符号数乘法

而我想的是,能不能不进行符号位扩展,先抛开符号位,将负数的补码转换为原码,然后以无符号数乘法的计算方式进行计算。最后再来处理符号位,所谓“同号为正,异号为负”。

3.实现

下面展示了以我的思路设计的有符号移位相加乘法器,是并行计算的,只需要一个周期就能出结果,并且进行了参数化。

module sign_Mult
	#(parameter WIDTH_A = 8,
				WIDTH_B = 8)
(
	input 				clk						 ,
	input 	signed		[WIDTH_A-1:0] 			a,
	input 	signed		[WIDTH_B-1:0] 			b,
	output 	reg	signed	[WIDTH_A+WIDTH_B:0]	  out

    );
	integer 			i							 ;
	reg 	signed		[WIDTH_A+WIDTH_B:0] 	out_r;//考虑结果会有溢出
	wire 	signed		[WIDTH_A:0] 			a_r	 ;
	wire	signed		[WIDTH_B:0] 			b_r	 ;	
always @(a or b) begin
	out_r = 0;
	for(i=0; i<(WIDTH_B); i=i+1)
		if(b_r[i])
			out_r = out_r + (a_r << i);
end
assign a_r = a[WIDTH_A-1] ? {1'b0,~a + 1'b1} : {1'b0,a};//负数取反加一转化为补码
assign b_r = b[WIDTH_B-1] ? {1'b0,~b + 1'b1} : {1'b0,b};//正数保持不变
always @(posedge clk)
	if(a[WIDTH_A-1] == b[WIDTH_B-1])
		out <= out_r;
	else
		out <= ~out_r + 1'b1;
endmodule

测试激励代码:

`timescale 1ns / 1ps
module sign_Mult_tb;
reg 	signed	[11:0] 		a	;
reg		signed	[15:0] 		b	;
wire 	signed	[28:0]		out	;
reg							clk	;
sign_Mult
#(.WIDTH_A(12),
.WIDTH_B(16))
u1(
	.clk(clk),
	.a	(a)	 ,
	.b	(b)	 ,
	.out(out)
 );
 always #10 clk = ~clk;
 initial begin
	clk = 1'b0;
	a = -12'd2;
	b = -16'd3;//计算结果应为6
	#200
	a = -12'd2048;//12bit最小值-2048
	b =  16'd32767;//16bit有符号数最大值//计算结果应为-67_106_816
	#200
	a =  12'd2;
	b = -16'd3;//计算结果应为-6
	#200
	a =  12'd2047;//12bit最大值2047
	b = -16'd32768;//16bit最小值-32768//计算结果应为-67_076_096
 end
endmodule

举了几个比较典型的数进行验证,貌似结果是对的,没有多试,因为都是以前上课的时候做的作业,现在分享出来,自己也懒得去再验证了,有兴趣的朋友可以多去测试。

仿真结果

注意事项:

  1. 无论是有符号数相乘还是无符号数相乘,其乘积的位宽必定位a+b;

  2. 如果被乘数和乘数均为有符号数,那么相乘之前首先要进行符号位扩展,将被乘数和乘数均扩展位a+b位。

  3. 有符号数乘法的最终结果也是补码形式。
    微信公众号获取更多FPGA相关源码:
    在这里插入图片描述

  • 9
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值