如何使用signed wire/reg 进行乘法器设计
Index
纯组合逻辑
使用独立的signed wire
module name#(
parameter LOCAL_PRECISION = 16
)(
input din_valid,
input [LOCAL_PRECISION*4-1:0] din_a,
output signed [LOCAL_PRECISION+1:0] dout_b
);
wire signed [LOCAL_PRECISION-1:0] a0;
wire signed [LOCAL_PRECISION-1:0] a1;
wire signed [LOCAL_PRECISION-1:0] a2;
wire signed [LOCAL_PRECISION-1:0] a3;
wire signed [LOCAL_PRECISION:0] b1,b2;
assign a0 = din_a[(0+1)*LOCAL_PRECISION-1-:LOCAL_PRECISION];
assign a1 = din_a[(1+1)*LOCAL_PRECISION-1-:LOCAL_PRECISION];
assign a2 = din_a[(2+1)*LOCAL_PRECISION-1-:LOCAL_PRECISION];
assign a3 = din_a[(3+1)*LOCAL_PRECISION-1-:LOCAL_PRECISION];
assign b1 = a0*a1;
assign b2 = a2*a3;
assign dout_b = b1+b2;
endmodule
其RTL结果:
分析:当使用独立的输入signed wire,且是纯组合逻辑时,乘法器输入不进行补位。
使用拼接的signed wire
module name#(
parameter LOCAL_PRECISION = 16
)(
input din_valid,
input [LOCAL_PRECISION*4-1:0] din_a,
output signed [LOCAL_PRECISION+1:0] dout_b
);
wire signed [LOCAL_PRECISION-1:0] a[3:0];
wire signed [LOCAL_PRECISION:0] b1,b2;
genvar p;
generate
for(p=0;p<4;p=p+1) begin
assign a[p] = din_a[(p+1)*LOCAL_PRECISION-1-:LOCAL_PRECISION];
end
endgenerate
assign b1 = a[0]*a[1];
assign b2 = a[2]*a[3];
assign dout_b = b1+b2;
endmodule
其RTL仿真结果:
分析:当使用拼接的signed wire作为输入时,且是纯组合逻辑时,乘法器输入将会进行补位以扩展1个bit。
使用时序逻辑
使用独立的signed reg
module multiplier_test(
input clk,
input rst_n,
input mul_en,
input data_upgrade_valid,
input wire [8*4-1:0] a,
output reg signed [15:0] c1,
output reg signed [15:0] c2
);
reg signed [7:0] a_reg0;
reg signed [7:0] a_reg1;
reg signed [7:0] a_reg2;
reg signed [7:0] a_reg3;
reg data_ready_flag;
always@(posedge clk or negedge rst_n) begin
if( !rst_n ) begin
a_reg0 <= 8'b0;
a_reg1 <= 8'b0;
a_reg2 <= 8'b0;
a_reg3 <= 8'b0;
data_ready_flag <= 1'b0;
end
else begin
if(data_upgrade_valid) begin
a_reg0 <= a[7:0];
a_reg1 <= a[15:8];
a_reg2 <= a[23:16];
a_reg3 <= a[31:24];
data_ready_flag <= 1'b1;
end
else begin
data_ready_flag <= 1'b0;
end
end
end
always@(posedge clk or negedge rst_n) begin
if( !rst_n ) begin
c1 <= 0;
c2 <= 0;
end
else begin
if(data_ready_flag && mul_en) begin
c1 <= a_reg1*a_reg0;
c2 <= a_reg3*a_reg2;
end
end
end
endmodule
其RTL仿真结果:
分析:当使用独立的signed reg作为输入时,且是时序逻辑时,乘法器输入不进行补位。
使用拼接的signed reg(memory变量)
module multiplier_test(
input clk,
input rst_n,
input mul_en,
input data_upgrade_valid,
input wire [8*4-1:0] a,
output reg signed [15:0] c1,
output reg signed [15:0] c2
);
reg signed [7:0] a_reg[3:0];
reg data_ready_flag;
always@(posedge clk or negedge rst_n) begin
if( !rst_n ) begin
a_reg[0] <= 8'b0;
a_reg[1] <= 8'b0;
a_reg[2] <= 8'b0;
a_reg[3] <= 8'b0;
data_ready_flag <= 1'b0;
end
else begin
if(data_upgrade_valid) begin
a_reg[0] <= a[7:0];
a_reg[1] <= a[15:8];
a_reg[2] <= a[23:16];
a_reg[3] <= a[31:24];
data_ready_flag <= 1'b1;
end
else begin
data_ready_flag <= 1'b0;
end
end
end
always@(posedge clk or negedge rst_n) begin
if( !rst_n ) begin
c1 <= 0;
c2 <= 0;
end
else begin
if(data_ready_flag && mul_en) begin
c1 <= a_reg[1]*a_reg[0];
c2 <= a_reg[3]*a_reg[2];
end
end
end
endmodule
其RTL仿真结果:
分析:当使用拼接的signed reg作为输入时,且是时序逻辑时,乘法器输入将会进行补位以扩展1个bit。