FPGA-设计一个定点乘法器(原码一位乘法器)

       定点数指小数点在数中的位置是固定不变的,通常有定点整数和定点小数。在对小数点位置作出选择之后,运算中的所有数均应统一为定点整数或定点小数,在运算中不再考虑小数问题。 

定点数就是指小数点的位置固定不变,小数点的位置通常有两种约定方式:定点整数(纯整数,小数点在最低有效值位之后 比如:100.)和定点小数(纯小数,小数点在最高有(效数值位之前 比如:.101)。
(1)定义:数据中小数点位置固定不变的数 2)种类:定点整数 
(3)小数点在符号位与有效位之间。 
注:定点数受字长的限制,超出范围会有溢出。

首先着手原码的乘法运算设计

1、原码一位乘法:

根据计算机组成原理书上的算法流程结构可以得出:

迭代的过程入下:

1)取最低位进行判断

2)若最低位的值为1.则将上一步的部分积P与X相加,若最低位为0则不操作

3)右移一位,产生本次部分积

module array_multiplier(clk,rst_n,mul_x,mul_y,res
    );
	input              clk    ;//系统时钟
	input             rst_n   ;//复位信号
	input       [3:0] mul_x  ;//被乘数
	input       [3:0] mul_y  ;//乘数
	                           
	output  reg [7:0] res    ;//结果
                          
	reg         [3:0] mul_p  ;//部分积
	reg                c      ;//进位信号
	reg         [3:0] mul_y0 ;//储存乘数
	reg                en     ;//使能信号
	
	//使能信号模块
	always@(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)begin
			en<=1'b0;
		end
		else if(mul_x==1'b0||mul_y==1'b0)begin
			en<=1'b0;
		end
		else if(cnt==8'd3)begin
			en<=1'b1;
		end
		else begin
			en<=en;
		end
	end
	
	//逻辑控制模块(计数)
	reg [7:0] cnt;
	always@(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)begin
			cnt<=1'b0;
		end
		else if(en==1'b1)begin
			cnt<=8'd0;
		end
		else if(cnt==8'd3)begin
			cnt<=8'd0;
		end
		else begin
			cnt<=cnt+1'b1;
		end
	end
	
	//逻辑控制模块(加)
	reg con_add_en;
	always@(*)begin
		if(en==1'b1)begin
			con_add_en=1'b1;
		end
		else if(mul_y0[0]==1'b1)begin
			con_add_en=1'b0;
		end	
		else begin
			con_add_en=1'b1;
		end
	end
	//
	always@(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)begin
			mul_p=1'b0;
			c=1'b0;
			mul_y0=mul_y;
		end
		else if(en==1'b1)begin
			mul_p=mul_p;
			mul_y0=mul_y0;
		end
		else if(con_add_en==1'b0)begin
			{c,mul_p[3:0]}=mul_x[3:0]+{c,mul_p[3:0]};
			{c,mul_p[3:0],mul_y0[3:0]}={c,mul_p[3:0],mul_y0[3:0]}>>1;
		end
		else begin
			{c,mul_p[3:0],mul_y0[3:0]}={c,mul_p[3:0],mul_y0[3:0]}>>1;
		end
	end
	
	always@(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)begin
			res<=1'b0;
		end
		else if(mul_x==1'b0||mul_y==1'b0)begin
			res<=1'b0;
		end
		else if(en==1'b1)begin
			res<={mul_p,mul_y0[3:0]};
		end
		else begin
			res<=res;
		end
	end
	
endmodule
module array_multiplier(clk,rst_n,mul_x,mul_y,res
    );
	input              clk    ;//系统时钟
	input             rst_n   ;//复位信号
	input       [3:0] mul_x  ;//被乘数
	input       [3:0] mul_y  ;//乘数
	                           
	output  reg [7:0] res    ;//结果
                          
	reg         [3:0] mul_p  ;//部分积
	reg                c      ;//进位信号
	reg         [3:0] mul_y0 ;//储存乘数
	reg                en     ;//使能信号
	
	//使能信号模块
	always@(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)begin
			en<=1'b0;
		end
		else if(mul_x==1'b0||mul_y==1'b0)begin
			en<=1'b0;
		end
		else if(cnt==8'd3)begin
			en<=1'b1;
		end
		else begin
			en<=en;
		end
	end
	
	//逻辑控制模块(计数)
	reg [7:0] cnt;
	always@(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)begin
			cnt<=1'b0;
		end
		else if(en==1'b1)begin
			cnt<=8'd0;
		end
		else if(cnt==8'd3)begin
			cnt<=8'd0;
		end
		else begin
			cnt<=cnt+1'b1;
		end
	end
	
	//逻辑控制模块(加)
	reg con_add_en;
	always@(*)begin
		if(en==1'b1)begin
			con_add_en=1'b1;
		end
		else if(mul_y0[0]==1'b1)begin
			con_add_en=1'b0;
		end	
		else begin
			con_add_en=1'b1;
		end
	end
	//
	always@(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)begin
			mul_p=1'b0;
			c=1'b0;
			mul_y0=mul_y;
		end
		else if(en==1'b1)begin
			mul_p=mul_p;
			mul_y0=mul_y0;
		end
		else if(con_add_en==1'b0)begin
			{c,mul_p[3:0]}=mul_x[3:0]+{c,mul_p[3:0]};
			{c,mul_p[3:0],mul_y0[3:0]}={c,mul_p[3:0],mul_y0[3:0]}>>1;
		end
		else begin
			{c,mul_p[3:0],mul_y0[3:0]}={c,mul_p[3:0],mul_y0[3:0]}>>1;
		end
	end
	
	always@(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)begin
			res<=1'b0;
		end
		else if(mul_x==1'b0||mul_y==1'b0)begin
			res<=1'b0;
		end
		else if(en==1'b1)begin
			res<={mul_p,mul_y0[3:0]};
		end
		else begin
			res<=res;
		end
	end
	
endmodule

仿真测试:(13*11)

猜你喜欢

转载自blog.csdn.net/weixin_41445387/article/details/84779695