module multiplier(//global inputs
i_clk,i_rst,
//outputs
o_product,o_done,
//input
i_multiplicant,i_multiplier,i_start
);
//parameter declarations
parameter MULTIPLICANT_WIDTH =5; //width for multiplicant
parameter MULTIPLIER_WIDTH =5; //width for multiplier
parameter TWOSCOMP=0; //'1'=signed multiplication and '0'=unsigned multiplication
parameter PRODUCT_WIDTH =(MULTIPLICANT_WIDTH+MULTIPLIER_WIDTH); //width of the product
parameter NPOWER = 6; //multiplier width<=2**NPOWER
parameter NULL_VECTOR_S = 32'h00000000; //used to fill the upper part of product register with zero at the begining of multiplication
parameter S0= 2'd0;
parameter S1= 2'd1;
parameter S2= 2'd2;
//global inputs
input i_clk;
input i_rst;
//outputs
output reg [PRODUCT_WIDTH-1:0] o_product;
output o_done;
//input
input [MULTIPLICANT_WIDTH-1:0] i_multiplicant;
input [MULTIPLIER_WIDTH-1:0] i_multiplier;
input i_start; //indicates start of multiplication
// reg and wire declarations
reg o_done;
reg sign_i; //sign product
reg [PRODUCT_WIDTH-1:0] product_i;
reg [PRODUCT_WIDTH-1:0] product_ii;
reg [NPOWER-1:0] count_i;
reg [MULTIPLICANT_WIDTH-1:0] multiplicant_i;
reg [MULTIPLIER_WIDTH-1:0] multiplier_i;
reg add_i;
reg shr_i;
reg [1:0] state=2'b00;
reg [1:0] nextstate=2'b00;
//correcting the bits for signed multiplication
/*这是我试图注册输入的地方..我没有收到任何错误,但 FSM 给出了问题。向我添加无符号数字的结果应该比签名产品早 2 个周期。FSM 应该开始在不同的实例和 o_done 应该以不同的方式生成无符号和无符号数。但我不知道该怎么做。有人能帮我吗 */
generate
if(TWOSCOMP==1)
always@(posedge i_clk or posedge i_rst)
begin
if(i_rst)begin
multiplicant_i<=0;
multiplier_i<=0;
end else begin
$display("Testing signed numbers");
sign_i<= i_multiplicant[MULTIPLICANT_WIDTH-1] ^ i_multiplier[MULTIPLIER_WIDTH-1];
multiplicant_i=rectify_multcnd(i_multiplicant,TWOSCOMP);
multiplier_i=rectify_mulplr(i_multiplier,TWOSCOMP);
end
end
endgenerate
generate
if(TWOSCOMP==0)
always@(posedge i_clk or posedge i_rst)
begin
if(i_rst==1) begin
multiplicant_i<=0;
multiplier_i<=0;
end else begin
$display("Testing unsigned numbers");
multiplicant_i<=i_multiplicant;
multiplier_i<=i_multiplier;
end
end
endgenerate
//functionn to correct multiplicant bits
function [MULTIPLICANT_WIDTH-1:0]rectify_multcnd;
input [MULTIPLICANT_WIDTH-1:0]multiplicant;
reg [MULTIPLICANT_WIDTH-1:0] rec_v;
input twoc;
begin
if((multiplicant[MULTIPLICANT_WIDTH-1] & twoc)==1)
rec_v=~(multiplicant);
else
rec_v=multiplicant;
rectify_multcnd=(rec_v+(multiplicant[MULTIPLICANT_WIDTH-1] & twoc));
end
endfunction
//function to correct multipier bits
function [MULTIPLIER_WIDTH-1:0]rectify_mulplr;
input [MULTIPLIER_WIDTH-1:0]multiplier;
reg [MULTIPLIER_WIDTH-1:0] rec_v;
input twoc;
begin
if((multiplier[MULTIPLIER_WIDTH-1] & twoc)==1)
rec_v=~(multiplier);
else
rec_v=multiplier;
rectify_mulplr=(rec_v+(multiplier[MULTIPLIER_WIDTH-1] & twoc));
end
endfunction
//start of multiplication
always@(posedge i_clk or posedge i_rst)
begin
if(i_rst==1)
product_i<=18'd0;
else begin
if(i_start==1) begin
product_i <= {NULL_VECTOR_S[MULTIPLICANT_WIDTH-1:0], multiplier_i};
end else if (add_i==1)
product_i<= {{1'b0, product_i[PRODUCT_WIDTH-1:MULTIPLIER_WIDTH]} + {1'b0,multiplicant_i}, product_i[MULTIPLIER_WIDTH-1:1]};
else if (shr_i==1)
product_i<= {1'b0 , product_i[PRODUCT_WIDTH-1:1]};
end
end // always@ (posedge i_clk or posedge i_rst or posedge i_start)
//always block to transverse through the states
always@(posedge i_clk or posedge i_rst)
begin
if(i_rst==1)begin
state<=S0;
count_i<=0;
end else begin
state<=nextstate;
if(state==S1) begin
count_i<=count_i-1;
end
else if (state==S0) begin
count_i<=(MULTIPLIER_WIDTH-1);
end
end
end // always@ (posedge i_clk or posedge i_rst)
always@(state,i_start,product_i,count_i)
begin
case (state)
S0 :begin
add_i <= 0;
shr_i <= 0;
o_done <= 0;
if (i_start==1)
nextstate <= S1;
else
nextstate <= S1;
end
S1:begin
o_done <= 0;
add_i <= product_i[0];
shr_i <= ~product_i[0];
if (count_i==NULL_VECTOR_S [(MULTIPLIER_WIDTH-1):0])
nextstate <= S2 ;
else
nextstate <= S1;
end
S2 :begin
o_done <= 1;
add_i <= 0;
shr_i <= 0;
nextstate <= S0;
end
default:begin
o_done <= 0;
add_i <= 0;
shr_i <= 0;
nextstate <= S0;
end
endcase // case (state)
end // always@ (state,i_start,product_i,count_i)
generate
if(TWOSCOMP==1)
always@(state,i_start,product_i,count_i)
begin
if(sign_i ==1)
product_ii<=((~(product_i)) + 1);
else
product_ii<=product_i;
end
endgenerate
generate
if(TWOSCOMP==0)
always@(state,i_start,product_i,count_i)
begin
o_product<=product_i;
end
endgenerate
always@(posedge i_clk or posedge i_rst)
begin
if(i_rst==1)
o_product<=0;
else if(TWOSCOMP==1)begin
o_product<=product_ii;
end
end
endmodule // multiplier