logo资料库

用verilog编写16位加法器乘法器自动售货机.pdf

第1页 / 共19页
第2页 / 共19页
第3页 / 共19页
第4页 / 共19页
第5页 / 共19页
第6页 / 共19页
第7页 / 共19页
第8页 / 共19页
资料共19页,剩余部分请下载后查看
Verilog 课程实验报告
实验 1 十六位超前进位加法器 1.1 系统设计要求 用超前进位加法器实现一个有符号位的 16 位加法器,并且考虑溢出的情况 2.1 详细设计 根据超前进位加法器的原理 Co = G | ( P & Ci ) S 然后通过 4 个 4 位加法器的相连来得到十六位的加法器。原理如下图所示。溢出用 表示。 = P ^ Ci设计出 4位加法器的子模块, flag=0 P 0 G 1 P 0 G 1 P 2 G 2 P 3 G 3 Ci,0 C o,0 C o,1 C o,2 C o,3 FA FA FA P 0 G 1 P 0 G 1 P 2 G 2 P3 G 3 C i,0 C o,0 C o,1 C o,2 FA FA FA oP 1 P 2 P 3 o,3 ultiplexer M Idea: If (P0 and P1 and P2 and P3 = 1) then C o3 = C 0 , else “ kill ” or “ generate ”. 3.1 程序 //-------------16 位超前进位加法器 ----------------- module cla16(a,b,s,flag); input [15:0] a,b;// 输入 a, b output [16:0] s; // 输出 s output reg flag; // 进位 // 含有 a, b,输出 s,进位 flag 的模块
// 保留位 (a[15:0],b[15:0],p[15:0],g[15:0]); (p[3],p[2],p[1],p[0],g[3],g[2],g[1],g[0],pp1,gg1); (p[7],p[6],p[5],p[4],g[7],g[6],g[5],g[4],pp2,gg2); (p[11],p[10],p[9],p[8],g[11],g[10],g[9],g[8],pp3,gg3); (p[15],p[14],p[13],p[12],g[15],g[14],g[13],g[12],pp4,gg4); (pp4,pp3,pp2,pp1,gg4,gg3,gg2,gg1,pp5,gg5); wire pp4,pp3,pp2,pp1; wire gg4,gg3,gg2,gg1; wire [15:0] Cp; wire [15:0] p,g; i0 pg add i1 add i2 add i3 add i4 add i5 // 调用四位加法器模块 add4 l0 (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]); add4 l1 (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]); add4 l2 (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]); add4 l3 (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]); assign s[0]=p[0]^1'b0; assign s[1]=p[1]^Cp[0]; assign s[2]=p[2]^Cp[1]; assign s[3]=p[3]^Cp[2]; assign s[4]=p[4]^Cp[3]; assign s[5]=p[5]^Cp[4]; assign s[6]=p[6]^Cp[5]; assign s[7]=p[7]^Cp[6]; assign s[8]=p[8]^Cp[7]; assign s[9]=p[9]^Cp[8]; assign s[10]=p[10]^Cp[9]; assign s[11]=p[11]^Cp[10]; assign s[12]=p[12]^Cp[11]; assign s[13]=p[13]^Cp[12]; assign s[14]=p[14]^Cp[13]; assign s[15]=p[15]^Cp[14]; assign s[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 位加法器模块 module add4(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;
input Co; output [3:0] Cp; assign Cp[0]=g[0]|p[0]&Co; assign Cp[1]=g[1]|p[1]&Cp[0]; assign Cp[2]=g[2]|p[2]&Cp[1]; assign Cp[3]=g[3]|p[3]&Cp[2]; endmodule // 模块间的进位 module add(p[3],p[2],p[1],p[0],g[3],g[2],g[1],g[0],pp,gg); input [3:0]p,g; output pp,gg; assign pp=p[3]&p[2]&p[1]&p[0]; assign gg=g[3]|(p[3]&(g[2]|p[2]&(g[1]|p[1]&g[0]))); endmodule // 进位信号的产生 module pg(a,b,p,g); input [15:0] a,b; output [15:0] p,g; assign p=a^b; assign g=a&b; endmodule 4.1 测试程序 通过产生一个随机输入 a 和 b,来验证 c=a+b。 //16 位加法器的测试文件 `timescale 1ns/1ns `include"./sixteenadder.v" module sixteenaddertest; wire [15:0] s; reg [15:0]a,b; wire flag; parameter times=5; // 随机产生一个数 ,总共产生 6 次 initial begin a={$random}%65536; b={$random}%65536; repeat(times) begin #100 a={$random}%65536; b={$random}%65536;
end #100 $stop; end cla16 cal161(a,b,s,flag); endmodule 5.1 仿真波形 用 mudelsim10.0 仿真得到的波形如下所示: 如 图 a=13604,b=24193 s=-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 程序 // 定义模块包括 a, b, s // 输出 s (a[15:0],b[15:0],p[15:0],g[15:0]); (p[3],p[2],p[1],p[0],g[3],g[2],g[1],g[0],pp1,gg1); (p[7],p[6],p[5],p[4],g[7],g[6],g[5],g[4],pp2,gg2); (p[11],p[10],p[9],p[8],g[11],g[10],g[9],g[8],pp3,gg3); (p[15],p[14],p[13],p[12],g[15],g[14],g[13],g[12],pp4,gg4); (pp4,pp3,pp2,pp1,gg4,gg3,gg2,gg1,pp5,gg5); //--------------------16 位加减法器 ------------------------ module cla16(a,b,s); input [15:0] a,b;// 输入 a, b output [16:0] s; wire pp4,pp3,pp2,pp1; wire gg4,gg3,gg2,gg1; wire [15:0] Cp; wire [15:0] p,g; i0 pg add i1 add i2 add i3 add i4 add i5 add4 l0 (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]); add4 l1 (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]); add4 l2 (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]); add4 l3 (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]); assign s[0]=p[0]^1'b0; assign s[1]=p[1]^Cp[0]; assign s[2]=p[2]^Cp[1]; assign s[3]=p[3]^Cp[2]; assign s[4]=p[4]^Cp[3]; assign s[5]=p[5]^Cp[4]; assign s[6]=p[6]^Cp[5]; assign s[7]=p[7]^Cp[6]; assign s[8]=p[8]^Cp[7];
assign s[9]=p[9]^Cp[8]; assign s[10]=p[10]^Cp[9]; assign s[11]=p[11]^Cp[10]; assign s[12]=p[12]^Cp[11]; assign s[13]=p[13]^Cp[12]; assign s[14]=p[14]^Cp[13]; assign s[15]=p[15]^Cp[14]; assign s[16]=pp5|gg5; endmodule module add4(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; input Co; output [3:0] Cp; assign Cp[0]=g[0]|p[0]&Co; assign Cp[1]=g[1]|p[1]&Cp[0]; assign Cp[2]=g[2]|p[2]&Cp[1]; assign Cp[3]=g[3]|p[3]&Cp[2]; endmodule module add(p[3],p[2],p[1],p[0],g[3],g[2],g[1],g[0],pp,gg); input [3:0]p,g; output pp,gg; assign pp=p[3]&p[2]&p[1]&p[0]; assign gg=g[3]|(p[3]&(g[2]|p[2]&(g[1]|p[1]&g[0]))); endmodule module pg(a,b,p,g); input [15:0] a,b; output [15:0] p,g; assign p=a^b; assign g=a&b; endmodule // 定义加减法器的模块 module addsub(a,b,s,flag,add_sub); input[15:0]a,b; input add_sub; output [15:0] s; output reg flag; wire [15:0]b1; cla16 cla1(a,b1,s); /* always@(posedge clk) begin if(~add_sub) begin b1=~b; b1=b1+1;
end else b1=b; end // 判断是否溢出 */ assign b1= (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[1 5]==1)) flag=1'b1; else flag=1'b0; end endmodule 4.1 测试程序 `timescale 1ns/1ns `include"./adder_sub.v" module adder_sub_test; wire [15:0] s; reg [15:0]a,b; reg add_sub; wire flag ; 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;
分享到:
收藏