`timescale 1ns / 1ps //0.建议每个模块加timescale
/*-------------------------------------------------------------------------------------------------
This confidential and proprietary software may be only used asauthorized
by a licensing agreement from XXX Inc.
(C) COPYRIGHT 2007 XXX INC. ALL RIGHTS RESERVED
Filename : .v
Author :
Data : 2014-05-21
Version : 0.1
Description : 用移位相加的方式来实现4位的乘法器
multa:被乘数。multb: 乘
Modification History:
Data By Version Change Description
========================================================
2014/05/21 0.1 Original
….
-------------------------------------------------------------------------------------------------*/
module FPGA_Shift_Mult(
// clk,
// rst_n,
in_en,
multa,
multb,
multc,
multd,
multout,
mout_yuanm,
mult_value
);
/*-----------------------------------------------------------------------------------------------*/
parameter WIDTH=8;
/*-----------------------------------------------------------------------------------------------*/
//input clk; //
//input rst_n; //
input in_en; //
input[WIDTH-1:0] multa; //multa:被乘数。multb:乘数
input[WIDTH-1:0] multb; //multa:被乘数。multb:乘数
input[WIDTH-1:0] multc; //输入(补码)
input[WIDTH-1:0] multd; //输入(补码)
/*-----------------------------------------------------------------------------------------------*/
output[WIDTH*2-1:0] multout;
output[WIDTH*2-1:0] mout_yuanm;
output[WIDTH*2-1:0] mult_value;
/*-----------------------------------------------------------------------------------------------*/
reg[WIDTH*2-1:0] shift_a;//注意这里的位数,与输出的位数大小一样
reg[WIDTH*2-1:0] shift_b;//注意这里的位数,与输出的位数大小一样
reg[WIDTH*2-1:0] multout; //无符号乘法数据输出
reg[WIDTH*2-1:0] mout_yuanm; //有符号乘法输出数据输出(以补码输出)
reg[WIDTH*2-1:0] mult_value; //有符号乘法输出数据输出(以补码输出)
/*-----------------------------------------------------------------------------------------------*/
//1.无符号数的移位相乘
always@(multa or multb)
begin
shift_a=multa;
shift_b=multb;
multout=0;
repeat(WIDTH)
begin
if(shift_a[0])//第一次移位0位
multout=multout+shift_b;
shift_b=shift_b<<1;//移位相加
shift_a=shift_a>>1;//被乘数实行移位
end
end
/*-----------------------------------------------------------------------------------------------*/
reg[WIDTH-1:0] xin_yuanma; //Original code
reg[WIDTH-1:0] yin_yuanma; //Original code
reg[WIDTH-1:0] xin_reg1; //数据输入寄存器
reg[WIDTH-1:0] yin_reg2; //数据输入寄存器
reg[WIDTH*2-3:0] mout_reg1; //数据输出寄存器
reg[WIDTH*2-1:0] mout_reg2; //数据输出寄存器
reg flag;
//2.有符号数乘法运算.有符号小数乘法器
always@(multc or multd)
begin
flag =0;
xin_yuanma =0;
yin_yuanma =0;
mout_yuanm =0;
xin_reg1 =0;
yin_reg2 =0;
mout_reg1 =0;
mout_reg2 =0;
xin_reg1=multc;
yin_reg2=multd;
if(in_en==1'b1)
begin
//mult_value=Mult_Signed_Decimal(xin_reg1,yin_reg2);
//正数的反码和补码都是和原码相同。负数的反码是将其原码除符号位之外的各位求反;
//负数的补码是将其原码除符号位之外的各位求反之后在末位再加1。
//特别注意,如果+1之后有进位的,要一直往前进位,包括符号位!
//1.补码变原码 :包括正数的原码与负数的原码表示;
xin_yuanma=(xin_reg1[WIDTH-1]==1)?{xin_reg1[WIDTH-1],~xin_reg1[WIDTH-2:0]+1'b1}:xin_reg1;
yin_yuanma=(yin_reg2[WIDTH-1]==1)?{yin_reg2[WIDTH-1],~yin_reg2[WIDTH-2:0]+1'b1}:yin_reg2;
//2.判断乘积的正负
flag=xin_yuanma[WIDTH-1]^yin_yuanma[WIDTH-1];
//mout_reg1=mult_shift(xin_yuanma[WIDTH-2:0],yin_yuanma[WIDTH-2:0]);
//3.计算小数
mout_reg1=xin_yuanma[WIDTH-2:0]*yin_yuanma[WIDTH-2:0];//
//4.原码表示的积,第一位为符号位,其它位为数据位
//1.如果是整数,则是往高位走,无关为位放在高位
//2.如果是小数,则是往低位长,无关位放置最低位
if(mout_reg1==0)
mout_yuanm=0;
else
begin
mout_reg2={flag,1'b0,mout_reg1};
//5.所得积为用补码表示的有符号数
mout_yuanm= (mout_reg2[WIDTH*2-1]==1)?{mout_reg2[WIDTH*2-1],~mout_reg2[(WIDTH*2-2):0]+1'b1}:mout_reg2;
end
end
else
begin
flag =0;
xin_yuanma =0;
yin_yuanma =0;
mout_yuanm =0;
xin_reg1 =0;
yin_reg2 =0;
mout_reg1 =0;
mout_reg2 =0;
end
end
endmodule