运用加法器实现两个5位有符号数相乘-verilog
module sign_pipline_muli (
clk,rst,mul_a,mul_b,mul_out
);
input clk;
input rst;
input [4:0]mul_a;
input [4:0]mul_b;
output [8:0]mul_out;
reg [8:0]mul_out;
reg mul_out_H; //输出符号位判断
reg mul_out_H0;//输出符号为延时,使其与数据位保持时序一致
reg mul_out_H1;
reg mul_out_H2;
reg mul_out_H3;
reg [4:0]mul_a_1;//判断输入数据是正还是负,正则为其本身;负则保留符号位,数据位转为补码
reg [4:0]mul_b_1;
reg [7:0]stored0;//采用移位相加,流水线设计
reg [7:0]stored1;
reg [7:0]stored2;
reg [7:0]stored3;
reg [7:0]add0;
reg [7:0]add1;
reg [7:0]add2;
always @(posedge clk or negedge rst) begin
if(!rst) begin
mul_out <= 9'b0;
mul_a_1 <= 5'b0;
mul_b_1 <= 5'b0;
mul_out_H <= 1'b0;
mul_out_H0 <= 1'b0;
mul_out_H1 <= 1'b0;
mul_out_H2 <= 1'b0;
mul_out_H3 <= 1'b0;
stored0 <= 8'b0;
stored1 <= 8'b0;
stored2 <= 8'b0;
stored3 <= 8'b0;
add0 <= 8'b0;
add1 <= 8'b0;
add2 <= 8'b0;
end
else begin
mul_out_H0 <= mul_a[4] ^ mul_b[4];
mul_out_H1 <= mul_out_H0;
mul_out_H2 <= mul_out_H1;
mul_out_H <= mul_out_H2;//对符号位进行延时,满足与数据位的时序要求
mul_a_1 <= (mul_a[4]==1'b0)?mul_a:({mul_a[4],~mul_a[3:0]+1'b1});
mul_b_1 <= (mul_b[4]==1'b0)?mul_b:({mul_b[4],~mul_b[3:0]+1'b1});
stored0 <= ((mul_b_1[0]==1'b1)?{4'b0,mul_a_1[3:0]}:8'b0);
stored1 <= ((mul_b_1[1]==1'b1)?{3'b0,mul_a_1[3:0],1'b0}:8'b0);
stored2 <= ((mul_b_1[2]==1'b1)?{2'b0,mul_a_1[3:0],2'b0}:8'b0);
stored3 <= ((mul_b_1[3]==1'b1)?{1'b0,mul_a_1[3:0],3'b0}:8'b0);
add0 <= stored0 + stored1;
add1 <= stored2 + stored3;
add2 <= add1 + add0;
mul_out <= (mul_out_H==1'b0)?({mul_out_H,add2}):({mul_out_H,~add2+1'b1});
end
end
endmodule
tb文件:
`timescale 1ns/1ps
module sign_pipline_muli_tb;
reg clk;
reg rst;
reg [4:0]mul_a;
reg [4:0]mul_b;
wire [8:0]mul_out;
sign_pipline_muli u1(
.clk(clk),
.rst(rst),
.mul_a(mul_a),
.mul_b(mul_b),
.mul_out(mul_out)
);
initial begin
clk = 1'b1;
rst = 1'b0;
#10;
rst = 1'b1;
end
always #5 clk = ~clk;
initial begin
mul_a = 5'b11011;
mul_b = 5'b10011;
#50;
mul_a = 5'b01101;
mul_b = 5'b01001;
#50;
mul_a = 5'b10011;
mul_b = 5'b00101;
#50;
mul_a = 5'b01111;
mul_b = 5'b10101;
#50;
mul_a = 5'b00000;
mul_b = 5'b11000;
#50;
mul_a = 5'b10111;
mul_b = 5'b01101;
#50;
mul_a = 5'b00000;
mul_b = 5'b01000;
#50;
mul_a = 5'b11011;
mul_b = 5'b11001;
#100;
$stop();
end
endmodule
仿真结果:
小结:
1,符号位如果不添加延时,会存在与数据位的时序不符情况,导致结果出错。
2,输出结果,正则为本身,负则以补码的形式输出。
3,这个程序只使用了一个always语句进行处理,也可以使用多个always语句。
4,此程序以流水线方式实现乘法器,但也可通过移位相加实现乘法器(后续会更新)。
5,乘法器的输出位宽为输入的两倍(数据位)。