用verilog编写16位加法器乘法器自动售货机.docx
《用verilog编写16位加法器乘法器自动售货机.docx》由会员分享,可在线阅读,更多相关《用verilog编写16位加法器乘法器自动售货机.docx(26页珍藏版)》请在冰点文库上搜索。
用verilog编写16位加法器乘法器自动售货机
Verilog课程实验报告
实验1十六位超前进位加法器
1.1系统设计要求
用超前进位加法器实现一个有符号位的16位加法器,并且考虑溢出的情况
2.1详细设计
根据超前进位加法器的原理Co=G|(P&Ci)S=P^Ci设计出4位加法器的子模块,然后通过4个4位加法器的相连来得到十六位的加法器。
原理如下图所示。
溢出用flag=0表示。
3.1程序
//-------------16位超前进位加法器-----------------
modulecla16(a,b,s,flag);//含有a,b,输出s,进位flag的模块
input[15:
0]a,b;//输入a,b
output[16:
0]s;//输出s
outputregflag;//进位
wirepp4,pp3,pp2,pp1;
wiregg4,gg3,gg2,gg1;
wire[15:
0]Cp;
wire[15:
0]p,g;
pgi0(a[15:
0],b[15:
0],p[15:
0],g[15:
0]);
addi1(p[3],p[2],p[1],p[0],g[3],g[2],g[1],g[0],pp1,gg1);
addi2(p[7],p[6],p[5],p[4],g[7],g[6],g[5],g[4],pp2,gg2);
addi3(p[11],p[10],p[9],p[8],g[11],g[10],g[9],g[8],pp3,gg3);
addi4(p[15],p[14],p[13],p[12],g[15],g[14],g[13],g[12],pp4,gg4);
addi5(pp4,pp3,pp2,pp1,gg4,gg3,gg2,gg1,pp5,gg5);
//调用四位加法器模块
add4l0(p[3],p[2],p[1],p[0],g[3],g[2],g[1],g[0],1'b0,Cp[3],Cp[2],Cp[1],Cp[0]);
add4l1(p[7],p[6],p[5],p[4],g[7],g[6],g[5],g[4],Cp[3],Cp[7],Cp[6],Cp[5],Cp[4]);
add4l2(p[11],p[10],p[9],p[8],g[11],g[10],g[9],g[8],Cp[7],Cp[11],Cp[10],Cp[9],Cp[8]);
add4l3(p[15],p[14],p[13],p[12],g[15],g[14],g[13],g[12],Cp[11],Cp[15],Cp[14],Cp[13],Cp[12]);
assigns[0]=p[0]^1'b0;//保留位
assigns[1]=p[1]^Cp[0];
assigns[2]=p[2]^Cp[1];
assigns[3]=p[3]^Cp[2];
assigns[4]=p[4]^Cp[3];
assigns[5]=p[5]^Cp[4];
assigns[6]=p[6]^Cp[5];
assigns[7]=p[7]^Cp[6];
assigns[8]=p[8]^Cp[7];
assigns[9]=p[9]^Cp[8];
assigns[10]=p[10]^Cp[9];
assigns[11]=p[11]^Cp[10];
assigns[12]=p[12]^Cp[11];
assigns[13]=p[13]^Cp[12];
assigns[14]=p[14]^Cp[13];
assigns[15]=p[15]^Cp[14];
assigns[16]=pp5|gg5;
//溢出判断模块
always@(a,b,s)
begin
if((a[15]==1&&b[15]==1&&s[15]==0)||(a[15]==0&&b[15]==0&&s[15]==1))
flag=1'b1;
else
flag=1'b0;
end
endmodule
//4位加法器模块
moduleadd4(p[3],p[2],p[1],p[0],g[3],g[2],g[1],g[0],Co,Cp[3],Cp[2],Cp[1],Cp[0]);
input[3:
0]p,g;
inputCo;
output[3:
0]Cp;
assignCp[0]=g[0]|p[0]&Co;
assignCp[1]=g[1]|p[1]&Cp[0];
assignCp[2]=g[2]|p[2]&Cp[1];
assignCp[3]=g[3]|p[3]&Cp[2];
endmodule
//模块间的进位
moduleadd(p[3],p[2],p[1],p[0],g[3],g[2],g[1],g[0],pp,gg);
input[3:
0]p,g;
outputpp,gg;
assignpp=p[3]&p[2]&p[1]&p[0];
assigngg=g[3]|(p[3]&(g[2]|p[2]&(g[1]|p[1]&g[0])));
endmodule
//进位信号的产生
modulepg(a,b,p,g);
input[15:
0]a,b;
output[15:
0]p,g;
assignp=a^b;
assigng=a&b;
endmodule
4.1测试程序
通过产生一个随机输入a和b,来验证c=a+b。
//16位加法器的测试文件
`timescale1ns/1ns
`include"./sixteenadder.v"
modulesixteenaddertest;
wire[15:
0]s;
reg[15:
0]a,b;
wireflag;
parametertimes=5;
//随机产生一个数,总共产生6次
initial
begin
a={$random}%65536;
b={$random}%65536;
repeat(times)
begin
#100
a={$random}%65536;
b={$random}%65536;
end
#100$stop;
end
cla16cal161(a,b,s,flag);
endmodule
5.1仿真波形
用mudelsim10.0仿真得到的波形如下所示:
如图a=13604,b=24193s=-27739.s为负数,产生溢出,溢出标位sto=1.当a=-10743,,b=22115.s=11372没有溢出,sto=0.通过这个实验验证了s=a+b,实现了带符号位的加法器。
实验二十六位加减法器
1.1系统设计要求
将加法器和减法器结合到一起,实现带符号位的16位加减法运算,并考虑溢出。
2.1详细设计
在16位加法器的基础上,加上一条判断语句,如果出现减的操作,被减数取反加一,这样就实现了减的运算,用add_sub来表示加减运算符,当add_sub=0时候实现的是减运算,add_sub=1的时候实现的是加运算。
3.1程序
//--------------------16位加减法器------------------------
modulecla16(a,b,s);//定义模块包括a,b,s
input[15:
0]a,b;//输入a,b
output[16:
0]s;//输出s
wirepp4,pp3,pp2,pp1;
wiregg4,gg3,gg2,gg1;
wire[15:
0]Cp;
wire[15:
0]p,g;
pgi0(a[15:
0],b[15:
0],p[15:
0],g[15:
0]);
addi1(p[3],p[2],p[1],p[0],g[3],g[2],g[1],g[0],pp1,gg1);
addi2(p[7],p[6],p[5],p[4],g[7],g[6],g[5],g[4],pp2,gg2);
addi3(p[11],p[10],p[9],p[8],g[11],g[10],g[9],g[8],pp3,gg3);
addi4(p[15],p[14],p[13],p[12],g[15],g[14],g[13],g[12],pp4,gg4);
addi5(pp4,pp3,pp2,pp1,gg4,gg3,gg2,gg1,pp5,gg5);
add4l0(p[3],p[2],p[1],p[0],g[3],g[2],g[1],g[0],1'b0,Cp[3],Cp[2],Cp[1],Cp[0]);
add4l1(p[7],p[6],p[5],p[4],g[7],g[6],g[5],g[4],Cp[3],Cp[7],Cp[6],Cp[5],Cp[4]);
add4l2(p[11],p[10],p[9],p[8],g[11],g[10],g[9],g[8],Cp[7],Cp[11],Cp[10],Cp[9],Cp[8]);
add4l3(p[15],p[14],p[13],p[12],g[15],g[14],g[13],g[12],Cp[11],Cp[15],Cp[14],Cp[13],Cp[12]);
assigns[0]=p[0]^1'b0;
assigns[1]=p[1]^Cp[0];
assigns[2]=p[2]^Cp[1];
assigns[3]=p[3]^Cp[2];
assigns[4]=p[4]^Cp[3];
assigns[5]=p[5]^Cp[4];
assigns[6]=p[6]^Cp[5];
assigns[7]=p[7]^Cp[6];
assigns[8]=p[8]^Cp[7];
assigns[9]=p[9]^Cp[8];
assigns[10]=p[10]^Cp[9];
assigns[11]=p[11]^Cp[10];
assigns[12]=p[12]^Cp[11];
assigns[13]=p[13]^Cp[12];
assigns[14]=p[14]^Cp[13];
assigns[15]=p[15]^Cp[14];
assigns[16]=pp5|gg5;
endmodule
moduleadd4(p[3],p[2],p[1],p[0],g[3],g[2],g[1],g[0],Co,Cp[3],Cp[2],Cp[1],Cp[0]);
input[3:
0]p,g;
inputCo;
output[3:
0]Cp;
assignCp[0]=g[0]|p[0]&Co;
assignCp[1]=g[1]|p[1]&Cp[0];
assignCp[2]=g[2]|p[2]&Cp[1];
assignCp[3]=g[3]|p[3]&Cp[2];
endmodule
moduleadd(p[3],p[2],p[1],p[0],g[3],g[2],g[1],g[0],pp,gg);
input[3:
0]p,g;
outputpp,gg;
assignpp=p[3]&p[2]&p[1]&p[0];
assigngg=g[3]|(p[3]&(g[2]|p[2]&(g[1]|p[1]&g[0])));
endmodule
modulepg(a,b,p,g);
input[15:
0]a,b;
output[15:
0]p,g;
assignp=a^b;
assigng=a&b;
endmodule
//定义加减法器的模块
moduleaddsub(a,b,s,flag,add_sub);
input[15:
0]a,b;
inputadd_sub;
output[15:
0]s;
outputregflag;
wire[15:
0]b1;
cla16cla1(a,b1,s);
/*always@(posedgeclk)
begin
if(~add_sub)
begin
b1=~b;
b1=b1+1;
end
elseb1=b;
end
*/
assignb1=(add_sub)?
b:
(~b+1'b1);//判断是否为减操作,为减操作的话是取反加一的运算
always@(a,b,s)//判断是否溢出
begin
if((a[15]==1&&b[15]==1&&add_sub==1&&s[15]==0)||(a[15]==0&&b[15]==0&&add_sub==1&&s[15]==1))
flag=1'b1;
else
flag=1'b0;
end
endmodule
4.1测试程序
`timescale1ns/1ns
`include"./adder_sub.v"
moduleadder_sub_test;
wire[15:
0]s;
reg[15:
0]a,b;
regadd_sub;
wireflag;
initial//初始化,输入测试的数据
begin
a=-16'h7851;
b=16'ha432;
add_sub=1;
#100
begin
a=-16'h1233;
b=16'h3211;
add_sub=0;
end
#100
begin
a=16'h0232;
b=16'ha161;
add_sub=1;
end
#100
begin
a=16'h5632;
b=16'h04a1;
add_sub=0;
end
#100
begin
a=-16'h1234;
b=16'h4525;
add_sub=0;
end
#1000$stop;
end
addsubaddsub1(a,b,s,flag,add_sub);
endmodule
5.1仿真结果
用modelsim10.0仿真,得到的结果如下所示:
当a=-30801b=-23502,add-sub=1,加操作,s溢出,产生溢出信号flag=1.
当a=-4659b=12817add_sub=0,减操作,输出s=-17476,无溢出,flag=0.
当a=562b=-24223add_sub=1,加操作,输出s=-23661,无溢出,flag=0.
通过以上的结果分析,此程序实现了带符号位的加减法的功能。
实验三十六位的乘法器
11系统设计要求
实现16*16位的无符号位的乘法器
2.1详细设计
乘法器的硬件电路原理如下
定义16个寄存器,用来存储一行乘操作产生的数据,最后的结果为所有16行相加。
3.1程序
//----------16位乘法器-------------
modulemux(clk,rst_n,en,a,b_in,rdy,mux_out);
inputclk;//定义时钟
inputrst_n;//复位信号
inputen;//使能
input[15:
0]a,b_in;//输入a,b-in
outputrdy;//输出rdy,当结果正确时候为高电平
output[31:
0]mux_out;//乘法输出值
regrdy;
//定义中间的17个寄存器
reg[15:
0]mux_reg0;
reg[16:
0]mux_reg1;
reg[17:
0]mux_reg2;
reg[18:
0]mux_reg3;
reg[19:
0]mux_reg4;
reg[20:
0]mux_reg5;
reg[21:
0]mux_reg6;
reg[22:
0]mux_reg7;
reg[23:
0]mux_reg8;
reg[24:
0]mux_reg9;
reg[25:
0]mux_reg10;
reg[26:
0]mux_reg11;
reg[27:
0]mux_reg12;
reg[28:
0]mux_reg13;
reg[29:
0]mux_reg14;
reg[30:
0]mux_reg15;
reg[31:
0]mux_reg16;
always@(rst_noraorb_inoren)//监视4个变量
begin
if(!
rst_n)//复位
begin
rdy<=1'b0;
mux_reg0=16'd0;
mux_reg1=17'd0;
mux_reg2=18'd0;
mux_reg3=19'd0;
mux_reg4=20'd0;
mux_reg5=21'd0;
mux_reg6=22'd0;
mux_reg7=23'd0;
mux_reg8=24'd0;
mux_reg9=25'd0;
mux_reg10=26'd0;
mux_reg11=27'd0;
mux_reg12=28'd0;
mux_reg13=29'd0;
mux_reg14=30'd0;
mux_reg15=31'd0;
mux_reg16=32'd0;
end//
elseif(en&&rst_n)//开始乘法的运算操作
begin
if(a[0])mux_reg0<=b_in;elsemux_reg0<=16'd0;
if(a[1])mux_reg1<={b_in,mux_reg16[0]};elsemux_reg1<=17'd0;
if(a[2])mux_reg2<={b_in,mux_reg16[1:
0]};elsemux_reg2<=18'd0;
if(a[3])mux_reg3<={b_in,mux_reg16[2:
0]};elsemux_reg3<=19'd0;
if(a[4])mux_reg4<={b_in,mux_reg16[3:
0]};elsemux_reg4<=20'd0;
if(a[5])mux_reg5<={b_in,mux_reg16[4:
0]};elsemux_reg5<=21'd0;
if(a[6])mux_reg6<={b_in,mux_reg16[5:
0]};elsemux_reg6<=22'd0;
if(a[7])mux_reg7<={b_in,mux_reg16[6:
0]};elsemux_reg7<=23'd0;
if(a[8])mux_reg8<={b_in,mux_reg16[7:
0]};elsemux_reg8<=24'd0;
if(a[9])mux_reg9<={b_in,mux_reg16[8:
0]};elsemux_reg9<=25'd0;
if(a[10])mux_reg10<={b_in,mux_reg16[9:
0]};elsemux_reg10<=26'd0;
if(a[11])mux_reg11<={b_in,mux_reg16[10:
0]};elsemux_reg11<=27'd0;
if(a[12])mux_reg12<={b_in,mux_reg16[11:
0]};elsemux_reg12<=28'd0;
if(a[13])mux_reg13<={b_in,mux_reg16[12:
0]};elsemux_reg13<=29'd0;
if(a[14])mux_reg14<={b_in,mux_reg16[13:
0]};elsemux_reg14<=30'd0;
if(a[15])mux_reg15<={b_in,mux_reg16[14:
0]};elsemux_reg15<=31'd0;
rdy<=1;
end
else
begin
rdy<=1'b0;
end
end
//输出结果为所有寄存器的和
assignmux_out=mux_reg0+mux_reg1+mux_reg2+mux_reg3+mux_reg4+mux_reg5+mux_reg6+mux_reg7+mux_reg8+mux_reg9+mux_reg10+mux_reg11+mux_reg12+mux_reg13+mux_reg14+mux_reg15;
endmodule
4.1测试程序
`timescale1ns/1ns;
`include"./mult.v";
modulemult_test;
reg[15:
0]a,b_in;
wirerdy;
wire[31:
0]mux_out;
regclk,rst_n,en;
initial
begin
clk=0;
forever#50clk=~clk;
end
initial
begin
rst_n=0;
en=0;
a=16'h1231;
b_in=16'ha231;
#100
begin
rst_n=1;
en=0;
a=16'h2137;
b_in=16'h0142;
end
#100
begin
rst_n=1;
en=1;
a=16'h0234;
b_in=16'h12a7;
end
#100
begin
rst_n=1;
en=1;
a=16'h0012;
b_in=16'ha261;
end
#100
begin
rst_n=0;
en=1;
a=16'h1112;
b_in=16'h0879;
end
#10000$stop;
end
muxmux1(.clk(clk),.rst_n(rst_n),.en(en),.a(a),.b_in(b_in),.rdy(rdy),.mux_out(mux_out));
endmodule
5.1仿真波形
通过modelsim10.0仿真产生的波形如下所示:
当rst_n=0处于复位状态输出mux_out=0,当rst=1并且使能端en=1时候,乘法器工作。
当a=564,b=4775,mux_out=2693100,sto=1,实现了乘的操作,验证了电路实现乘法功能。
实验四自动售货机设计
1.1系统设计要求
自动售货机投入的金钱有50元,10元,5元,1元四种货币。
可供选择的商品有7种类型。
投入金钱后选择要买的商品,当投入的钱足够时,显示money_enough。
并显示出要买的商品,并且找零,当投入的钱不够的时候,通过复位成初始态。
具体的要求如下图所示:
2.1详细设计
初始状态下,设投入的money,找零charge,money_enough都为0。
投入的四种货币总共有12种情况,用price_all表示。
设商品