LUT乘法器又称为查表法乘法器,就是先把各种各样的结果储存在一个表中,然后乘法的结果以“查表”的方式取得。
查表乘法器之所以被称为快速乘法器,因为查表乘法器只要用些许时钟去查表就可以求得乘法的结果。反之,非查表乘法器需要许多时钟用于乘法的运算。
查找表乘法器是“以空间换时间”的乘法器,因此查找表很消耗空间。
Quarter Square乘法查表
公式:
reg[8:0]I1,I2;
case(i)
0:
begin
I1<={A[7],A}+{B[7],B}; //C=A+B
I2<={A[7],A}+{~B[7],(~B+1'b1)}; //C=A-B
//正数我们直接用二进制原码表示,负数用补码表示,按位取反末位加一
i<=i+1'b1;
end
1: //在该步骤中,我们将负值全部转换成正值(因为正值的平方与负值的平方相等)从而正负值可以公用一个查找表
begin
I1<=I1[8]?(~I1+1'b1):I1;
I2<=I2[8]?(~I2+1'b1):I2;
i<=i+1'b1;
end
笔者的QuartusII下载失败,很是无语。天亡我哉?非也非也。主要目的是从中学到时序和流水线操作等知识,后期将知识移植到我用Vivado开发ZYNQ上。
//lut_multiplier_module.v 功能:取得I1=A+B, I2=A-B,然后将I1和I2分别转换为正值,再将I1和I2送到各自的查找表,
//根据得出的查找结果Q1_Sig与Q2_Sig的结果执行相减
module lut_multiplier_module
(
input clk,
input rst_n,
input Start_Sig,
input [7:0]A,
input [7:0]B,
output Done_Sig,
output [15:0]Product,
//仿真输出
output [8:0]SQ_I1_Sig,
output [8:0]SQ_I2_Sig,
output [15:0]SQ_Q1_Sig,
output [15:0]SQ_Q2_Sig
);
wire[15:0]Q1_Sig;
wire[15:0]Q2_Sig;
reg[3:0]i;
reg[8:0]I1;
reg[8:0]I2;
reg[15:0]Data;
reg isDone;
always@(posedge clk or negedge rst_n)
if(!rst_n)
begin
i<=4'd0;
I1<=9'd0;
I2<=9'd0;
Data<=16'd0;
isData<=1'b0;
end
else if(Start_Sig)
case(i)
0:
begin
I1<={A[7],A}+{B[7],B};
I2<={A[7],A}+{~B[7],(~B+1'b1)};
i<=i+1'b1;
end
1:
begin //将I1I2都转换成正值
I1<=I1[8]?(~I1+1'b1):I1;
I2<=I2[8]?(~I2+1'b1):I2;
i<=i+1'b1;
end
2:
beign i<=i-1'b1;end
3://Q1_Sig-Q2_Sig
begin Data<=Q1_Sig+(~Q2_Sig+1'b1);i<=i+1'b1;end
4:
begin isDone<=1'b1;i<=i+1'b1;end
5:
begin isDone<=1'b0;i<=4'd0;end
endcase
//U1是给I1使用的查表
lut_module U1
(
.clk(clk),
.rst_n(rst_n),
.addr(I1[7:0]),
.Q(Q1_Sig)
);
//U2是给I2使用的查表
lut_module U2
(
.clk(clk),
.rst_n(rst_n),
.addr(I2[7:0]),
.Q(Q2_Sig)
);
assign Done_Sig=isDone;
assign Product=Data; //product由Data寄存器驱动
//仿真输出
assign SQ_I1_Sig=I1;
assign SQ_I2_Sig=I2;
assign SQ_Q1_Sig=Q1_Sig;
assign SQ_Q2_Sig=Q2_Sig;
endmodule
//lut_multiplier_module.vt
module lut_multiplier_module_simulation();
reg clk;
reg rst_n;
reg Start_Sig;
reg[7:0]A;
reg[7:0]B;
wire Done_Sig;
wire[15:0]Product;
wire[8:0]SQ_I1_Sig;
wire[8:0]SQ_I2_Sig;
wire[15:0]SQ_Q1_Sig;
wire[15:0]SQ_Q2_Sig;
lut_multiplier_module U1
(
.clk(clk),
.rst_n(rst_n),
.Start_Sig(Start_Sig),
.A(A),
.B(B),
.Done_Sig(Done_Sig),
.Product(Product),
.SQ_I1_Sig(SQ_I1_Sig),
.SQ_I2_Sig(SQ_I2_Sig),
.SQ_Q1_Sig(SQ_Q1_Sig),
.SQ_Q2_Sig(SQ_Q2_Sig)
);
initial
begin
rst_n=0;rst_n=1;#10;
clk=0;forever#10clk=~clk;
end
reg[3:0]i;
always@(posedge clk or negedge rst_n)
if(!rst_n)
begin
i<=4'd0;
Start_Sig<=1'b0;
A<=8'd0;
B<=8'd0;
end
else
case(i)
0://A=-127,B=127
if(Done_Sig)begin Start_Sig<=1'b0;i<=i+1'b1;end
else begin A<=8'b10000001;B<=8'd127;Start_Sig<=1'b1;end
1://A=2,B=-4
if(Done_Sig)begin Start_Sig<=1'b0;i<=i+1'b1;end
else begin Start_Sig<=1'b0; i<=i+1'b1; end
else begin A<=8'd2;B<=8'b11111100;Start_Sig<=1'b1;end
2:
if(Done_Sig)begin Start_Sig<=1'b0;i<=i+1'b1;end
else begin A<=8'd10;B<=8'd100;Start_Sig<=1'b1;end
3:
if(Done_Sig)begin Start_Sig<=1'b0;i<=i+1'b1;end
else begin A<=8'b10000001;B<=8'b10000001;Start_Sig<=1'b1;end
4:
i<=4'd4;
endcase
endmodule