p[i]=x[i]^y[i];
g[i]=y[i];
q[i+1]=(p[i])?
q[i]:
g[i];
sum[i]=p[i]^q[i];
end
cout=q[DSIZE];
end
endmodule
//二进制跳跃进位加法器
modulecarry_skip_adder(x_in,y_in,c_in,sum,c_out);
parameter DSIZE=12;
parameter S=4;
input c_in;
input[DSIZE-1:
0] x_in,y_in;
output[DSIZE-1:
0] sum;
reg[DSIZE-1:
0]sum;
output c_out;
reg c_out;
integeri,j;
reg[DSIZE:
0]q;
always@(x_inory_inorc_in)begin
q[0]=c_in;
begin
carry_skip_add_cell(x_in[S-1:
0],y_in[S-1:
0],
q[0],q[S:
1]);
for(j=0;j<=S-1;j=j+1)
sum[j]=x_in[j]^y_in[j]^q[j];
carry_skip_add_cell(x_in[2*S-1:
S],y_in[2*S-1:
S],
q[S],q[2*S:
S+1]);
for(j=0;j<=S-1;j=j+1)
sum[S+j]=x_in[S+j]^y_in[S+j]^q[S+j];
carry_skip_add_cell(x_in[3*S-1:
2*S],y_in[3*S-1:
2*S],
q[2*S],q[3*S:
2*S+1]);
for(j=0;j<=S-1;j=j+1)
sum[2*S+j]=x_in[2*S+j]^y_in[2*S+j]^q[2*S+j];
end
c_out=q[DSIZE];
end
//S比特分组进位链
taskcarry_skip_add_cell;
input[S-1:
0]x,y;
inputcin;
output[S:
1]cout;
reg q[S:
0],p[S-1:
0],g[S-1:
0],accumulator,generalized_p;
integeri;
begin
q[0]=cin;
for(i=0;i<=S-1;i=i+1)begin
p[i]=x[i]^y[i];
g[i]=y[i];
q[i+1]=(p[i])?
q[i]:
g[i];
end
accumulator=p[0];
for(i=1;i<=S-1;i=i+1)
accumulator=accumulator&p[i];
generalized_p=accumulator;
cout[S]=(generalized_p)?
c_in:
q[S];
for(i=1;i<=S-1;i=i+1)
cout[i]=q[i];
end
endtask
endmodule
6、进位旁路加法器、线性进位选择加法器等
7、减法器
Verilog模型如下:
二、乘法器
1、定点原码乘法器
乘数与被乘数分别载入两个寄存器R1与R2中。
此外,还有一个寄存器A,A的初始值为0。
运算时,控制逻辑每次读乘数的一位。
若R1的最低位为1,则被乘数与A寄存器相加,并将结果存于A寄存器。
然后,A、R1这两个寄存器整体右移一位,A的最高位变成0,且A0进入R1的最高位,而R1的最低位丢弃。
若R1的最低位是0,则只需进行移位,不进行加法。
产生的2n位乘积存于A与R1寄存器中。
32位定点原码一位乘法流程图如下:
Verilog参考代码:
modulemult(start,resten,x,y,z,);
input resten;
input start;
regbusy;
input [2:
0] x;
input [2:
0] y;
output[5:
0]z;
reg[5:
0] z;
reg [2:
0]reg_x;
reg [2:
0] reg_y;
reg [3:
0] A;
reg [2:
0] temp_x;
integer i;
always@(xoryorrestenorstart)
begin
if(!
resten) begin
A =4'b0;
reg_x=3'b0;
reg_y=3'b0;
temp_x=3'b0;
z =6'b0;
busy =0;
end
elseif(start)begin
reg_x=x;
reg_y=y;
busy =1;
A =4'b0;
end
elsebegin
if(busy)
for(i=0;i<3;i=i+1)begin
if(y[i])temp_x=x;
else temp_x=3'b000;
A = A+{1'b0,temp_x};
reg_y = {A[0],reg_y[2:
1]};
A = A>>1;
end
z={A,reg_y};busy=0;
end
end
endmodule
2、加法树乘法器
moduleadd_tree_mult(out,a,b,clk);
output[15:
0]out;
input[7:
0]a,b;
inputclk;
wire[15:
0]out;
wire[14:
0]out1,c1;
wire[12:
0]out2;
wire[10:
0]out3,c2;
wire[8:
0]out4;
reg[14:
0]temp0;
reg[13:
0]temp1;
reg[12:
0]temp2;
reg[11:
0]temp3;
reg[10:
0]temp4;
reg[9:
0]temp5;
reg[8:
0]temp6;
reg[7:
0]temp7;
function[7:
0]mux8_1;
input[7:
0]operand;
inputsel;
begin
mux8_1=(sel)?
(operand):
8'b00000000;
end
endfunction
always@(posedgeclk)
begin
temp7<=mux8_1(a,b[0]);
temp6<=((mux8_1(a,b[1]))<<1);
temp5<=((mux8_1(a,b[2]))<<2);
temp4<=((mux8_1(a,b[3]))<<3);
temp3<=((mux8_1(a,b[4]))<<4);
temp2<=((mux8_1(a,b[5]))<<5);
temp1<=((mux8_1(a,b[6]))<<6);
temp0<=((mux8_1(a,b[7]))<<7);
end
assign out1=temp0+temp1;
assign out2=temp2+temp3;
assign out3=temp4+temp5;
assign out4=temp6+temp7;
assign c1=out1+out2;
assign c2=out3+out4;
assign out=c1+c2;
endmodule
3、查找表乘法器
查找表乘法器是将乘积直接存放在存储器中,将操作数作为地址访问存储器,得到的输出数据就是乘法器的结果。
查找表乘法器的速度只局限于所使用存储器的存取速度。
modulelookup_mult(out,a,b,clk);
output[7:
0]out;
input[3:
0]a,b;
inputclk;
reg[7:
0]out;
reg[1:
0]firsta,firstb;
reg[1:
0]seconda,secondb;
wire[3:
0]outa,outb,outc,outd;
always@(posedgeclk)
begin
firsta=a[3:
2];seconda=a[1:
0];
firstb=b[3:
2];secondb=b[1:
0];
end
lookup m1(outa,firsta,firstb,clk),
m2(outb,firsta,secondb,clk),
m3(outc,seconda,firstb,clk),
m4(outd,seconda,secondb,clk);
always@(posedgeclk)
begin
out=(outa<<4)+(outb<<2)+(outc<<2)+outd;
end
endmodule
modulelookup(out,a,b,clk);
output[3:
0]out;
input[1:
0]a,b;
inputclk;
reg[3:
0]out;
reg[3:
0]address;
always@(posedgeclk)
begin
address={a,b};
case(address)
4'h0:
out=4'b0000;
4'h1:
out=4'b0000;
4'h2:
out=4'b0000;
4'h3:
out=4'b0000;
4'h4:
out=4'b0000;
4'h5:
out=4'b0001;
4'h6:
out=4'b0010;
4'h7:
out=4'b0011;
4'h8:
out=4'b0000;
4'h9:
out=4'b0010;
4'ha:
out=4'b0100;
4'hb:
out=4'b0110;
4'hc:
out=4'b0000;
4'hd:
out=4'b0011;
4'he:
out=4'b0110;
4'hf:
out=4'b1001;
default:
out='bx;
endcase
end
endmodule
4、布尔乘法器
Booth算法通过以移位代替某些运算来提高乘法的运算速度。
Booth算法是补码乘法的算法,基本公式为:
[X*Y]补=[X]补*[Yn-1Yn-2…..Y0]-[X]补*Yn。
公式说明如果乘数为正,则将乘数的尾数与被乘数相乘即可,如果乘数为负,那么在乘法运算之后,还要再减去被乘数才能得到最后的乘积。
公式变形为[X*Y]补=[X]补*[2^n(Yn-1-Yn)+2^n-1(Yn-2-Yn-1)+……+2^0(0-Y0)]。
从变形公式中可以看出,如果在乘数Y的末位Y0之后再增设一个附加位Y-1,其初始值为0,对乘数Y的值并无影响,则{(Yi-1,Yi)[X]补}就是每一次的部分积,该部分的位权就是2^i。
这种方法即为补码一位乘,即每次只处理一位乘数。
运算流程:
乘数与被乘数分别载入Q和M寄存器内,同时,还有一个1位寄存器,位于Q寄存器最低位Q0的右边,成为Q’。
乘法的结果出现在A和Q寄存器中。
A与Q’初始值为0。
控制逻辑也是每次扫描乘数的一位,但同时它也要检查右边的一位。
若两位相同,则A、Q和Q’寄存器的所有位向右移一位。
若两位不同,则根据两位是1-0还是0-1,决定被乘数加到A寄存器,还是有A寄存器减去被乘数,加减之后再右移一位。
也就是说,右移总是要进行的。
右移是{A,Q,Q’}的右移且是算术右移(算术移位:
算术左移时,右端(低位)补0,左端(高位)部分舍去;右移保证符号位不改变)。
设计流程图为:
示例:
Verilog示例代码:
modulebooth_mult(product,ready,word1,word2,start,clock,reset);
parameterL_word=4;
parameterL_brc=2;
parameterAll_Ones=4'b1111;
parameterAll_Zeros=4'b0000;
output[2*L_word-1:
0]product;
outputready;
input[L_word-1:
0]word1,word2;
inputstart,clock,reset;
wireload_words,shift,add,sub,ready;
wire[L_brc-1:
0]brc;
Datapath_Boothm1(product,m0,word1,word2,load_words,shift,add,sub,clock,reset);
Controller_Boothm2(load_words,shift,add,sub,read,m0,start,clock,reset);
endmodule
//控制模块
moduleController_Booth(load_words,shift,add,sub,ready,m0,start,clock,reset);
parameterL_word=4;
parameterL_state=4;
parameterL_brc=2;
outputload_words,shift,add,sub,ready;
inputstart,clock,reset;
inputm0;
reg[L_state-1:
0]state,nextstate;
parameterS_idle=0,S_1=1,S_2=2,S_3=3,S_4=4,S_5=5,S_6=6,S_7=7,S_8=8;
regload_words,shift,add,sub;
wireready=((state==S_idle)&&!
reset)||(state==S_8);
regm0_del;
wire[L_brc-1:
0]brc={m0,m0_del};
always@(posedgeclockorposedgereset)
if(reset)state<=S_idle;elsestate<=nextstate;
always@(posedgeclockorposedgereset)
if(reset)m0_del<=0;elseif(load_words)m0_del<=0;elsem0_del<=m0;
always@(stateorstartorbrc)begin
load_words=0;shift=0;add=0;sub=0;
case(state)
S_idle:
if(start)beginload_words<=1;nextstate<=S_1;end
elsenextstate<=S_idle;
S_1:
if((brc==0)||(brc==3))beginshift=1;nextstate<=S_3;end
elseif(brc==1)beginadd=1;nextstate<=S_2;end
elseif(brc==2)beginsub=1;nextstate<=S_2;end
S_3:
if((brc==0)||(brc==3))beginshift=1;nextstate<=S_5;end
elseif(brc==1)beginadd=1;nextstate<=S_4;end
elseif(brc==2)beginsub=1;nextstate<=S_4;end
S_5:
if((brc==0)||(brc==3))beginshift=1;nextstate<=S_7;end
elseif(brc==1)beginadd=1;nextstate<=S_6;end
elseif(brc==2)beginsub=1;nextstate<=S_6;end
S_7:
if((brc==0)||(brc==3))beginshift=1;nextstate<=S_8;end
elseif(brc==1)beginadd=1;nextstate<=S_8;end
elseif(brc==2)beginsub=1;nextstate<=S_8;end
S_2:
beginshift=1;nextstate=S_3;end
S_4:
beginshift=1;nextstate=S_5;end
S_6:
beginshift=1;nextstate=S_7;end
S_8:
if(start)beginload_words=1;nextstate=S_1;end
elsenextstate=S_8;
default:
nextstate=S_idle;
endcase
end
endmodule
//数据路径模块
moduleDatapath_Booth(product,m0,word1,word2,load_words,shift,add,sub,clock,reset);
parameterL_word=4;
output[2*L_word-1:
0]product;
outputm0;
input[L_word-1:
0]word1,word2;
inputload_words,shift,add,sub,clock,reset;
reg[2*L_word-1:
0]product,multiplicand;
reg[L_word-1:
0]mult;
wirem0=mult[0];
parameterAll_Ones=4'b1111;
parameterAll_Zeros=4'b0000;
always@(posedgeclockorposedgereset)begin
if(reset)beginmult<=0;multiplicand<=0;product<=0;end
elseif(load_words)begin
if(word1[L_word-1]==0)multiplicand<=w