设计一个16位二进制超前进位全加器模块
- 实验内容与原理说明
本实验设计一个16位二进制的超前进位全加器模块,用来实现16位二进制的加法,超前进位加法器的结构如下图。下图为一个四位超前进位加法器的结构图。信号经过pi和gi产生一级时延,经过计算C产生一级时延,则A,B输入一旦产生,首先经过两级时延算出第1轮进位值C’不过这个值是不正确的。C’再次送入加法器,进行第2轮2级时延的计算,算出第2轮进位值C,这一次是正确的进位值。这里的4个4位超前进位加法器仍是串行的,所以一次计算经过4级加法器,一级加法器有2级时延,因此1次计算一共经过8级时延,相比串行加法器里的16级时延,速度提高很多。
设计封装模块如下:
可以求得两个输出的表达式为:
对于i=0~3的代入,得到每一级的进位输出表达式如下:
- 实验模块程序代码和激励代码
(1)设计模块代码
//定义一位超前加法器
module bit1Advanced(ain,bin,cin,sum,gi,pi);
input ain;
input bin;
input cin;//定义进位信号
output sum;//输出信号
output gi;//每位的进位产生信号
output pi;//每位的进位传播信号
assign gi=ain&bin;//数据流的方式描述逻辑式
assign pi=ain|bin;//数据流的方式描述逻辑式
assign sum=ain^bin^cin;//数据流的方式描述逻辑式
endmodule
//定义四位超前加法器
module bit4Advanced(ain,bin,cin,sum,pm,gm,co);
input[3:0] ain;
input[3:0] bin;//定义两个四位的输入
input cin;//定义进位信号
output[3:0] sum;//定义输出信号
output gm;//定义进位产生信号
output pm;//定义进位传播信号
output co;//定义输出的进位信号
//定义三条wire类型,连接四个一位超前加法器之间的端口
wire[4:1] ci;
wire[3:0] pi;
wire[3:0] gi;
bit1Advanced u0(.ain(ain[0]),.bin(bin[0]),.cin(cin),.sum(sum[0]),.gi(gi[0]),.pi(pi[0]));
bit1Advanced u1(.ain(ain[1]),.bin(bin[1]),.cin(ci[1]),.sum(sum[1]),.gi(gi[1]),.pi(pi[1]));
bit1Advanced u2(.ain(ain[2]),.bin(bin[2]),.cin(ci[2]),.sum(sum[2]),.gi(gi[2]),.pi(pi[2]));
bit1Advanced u3(.ain(ain[3]),.bin(bin[3]),.cin(ci[3]),.sum(sum[3]),.gi(gi[3]),.pi(pi[3]));//对四个一位的超前加法器进行元件例化,并连接对应的端口
CLA_4 uut(.p(pi),.g(gi),.cin(cin),.ci(ci),.gm(gm),.pm(pm));//对CLA_4进行元件例化
assign co=ci[4];//赋值进位信号co
endmodule
module CLA_4(p,g,cin,ci,gm,pm);//定义CLA_4模块,也就是超前进位信号产生的模块
input[3:0] p;//定义输入的进位传播信号
input[3:0] g;//定义输入的进位产生信号
input cin;//定义模块的输入进位信号
output[4:1] ci;//定义模块的输出进位信号
output gm;//定义模块本身产生的进位产生信号
output pm;//定义模块本身产生的进位传播信号
assign ci[1]=g[0]|p[0]&cin;
assign ci[2]=g[1]|p[1]&g[0]|p[1]&p[0]&cin;
assign ci[3]=g[2]|p[2]&g[1]|p[2]&p[1]&g[0]|p[2]&p[1]&p[0]&cin;
assign ci[4]=g[3]|p[3]&g[2]|p[3]&p[2]&g[1]|p[3]&p[2]&p[1]&g[0]|p[3]&p[2]&p[1]&p[0]&cin;//根据对应的公式和对应的进位产生信号和进位传播信号赋值进位信号
assign gm=g[3]|p[3]&g[2]|p[3]&p[2]&g[1]|p[3]&p[2]&p[1]&g[0];
assign pm=p[3]&p[2]&p[1]&p[0];//根据对应的公式赋值模块本身的进位产生信号和进位传播信号
endmodule
//定义16位的超前进位加法器
module bit16Advanced(ain,bin,cin,sum,co,gm,pm);
input[15:0] ain;
input[15:0] bin;//定义两个加数
input cin;//定义输入的进位信号
output [15:0] sum;//定义输出的和信号
output co;//定义输出的进位信号
output gm;//定义进位产生信号
output pm;//定义进位传播信号
//定义三个wire类型的变量
wire[3:0] gi;
wire[3:0] pi;
wire[4:1] ci;
bit4Advanced U0(.ain(ain[3:0]),.bin(bin[3:0]),.cin(cin),.sum(sum[3:0]),.gm(gi[0]),.pm(pi[0]));
bit4Advanced U1(.ain(ain[7:4]),.bin(bin[7:4]),.cin(ci[1]),.sum(sum[7:4]),.gm(gi[1]),.pm(pi[1]));
bit4Advanced U2(.ain(ain[11:8]),.bin(bin[11:8]),.cin(ci[2]),.sum(sum[11:8]),.gm(gi[2]),.pm(pi[2]));
//根据实例化关系实例化三个模块,并且根据逻辑关系将其端口连接起来
bit4Advanced U3(.ain(ain[15:12]),.bin(bin[15:12]),.cin(ci[3]),.sum(sum[15:12]),.gm(gi[3]),.pm(pi[3]));
//将四位超前进位加法器产生的进位输出送到进位信号处理器中
//以产生新的进位信号
CLA_4 CLA_4(.p(pi),.g(gi),.cin(cin),.ci(ci),.gm(gm),.pm(pm));
assign co=ci[4];
endmodule
(2)激励模块代码
// Verilog Test Bench template for design : bit16Advanced
//
// Simulation tool : ModelSim (Verilog)
//
`timescale 1 ps/ 1 ps
module bit16Advanced_vlg_tst();
// constants
// general purpose registers
reg eachvec;
// test vector input registers
reg [15:0] ain;
reg [15:0] bin;
reg cin;
// wires
wire co;
wire gm;
wire pm;
wire [15:0] sum;
// assign statements (if any)
bit16Advanced i1 (
// port map - connection between master ports and signals/registers
.ain(ain),
.bin(bin),
.cin(cin),
.co(co),
.gm(gm),
.pm(pm),
.sum(sum)
);
initial
begin
ain=16'b0001_1111_1010_0101;
bin=16'b1010_1010_1110_0110;
cin=0;
//50ps后停止
50 $stop;
end
always #10 ain={$random}%17'h10000;
always #10 bin={$random}%17'h10000;
always #10 cin={$random}%2;
endmodule
3.波形图
4.门级电路图
设计一个16-bit 8421-BCD码全加器模块
1.实验内容与原理说明
本实验实现一个16位二进制的BCD码全加器模块,用来实现16位二进制的加法,由于两个1位十进制数相加时,和的取值范围是0—18,将该范围内各数值对应的二进制数和8421BCD码列表,以便寻找何时应对结果修正以及如何修正。
实验封装设计框图如下:
同时,我们知道当两个BCD码相加时,如果得到的结果为10以内,则显示的BCD码即为相加得到的结果,比如0001+0010=0011即3;但是当两个BCD码相加结果大于10,则应当加上6,即为显示的BCD码,即1001+0001 =9+1=1010=10,但应当显示0,于是将1010+0110=10000=0000,即显示为0。
下面详细地列出了真值表:
- 实验模块程序代码和激励代码
(1)设计模块代码
//定义一位BCD码的加法器
module BCD1bit(co,sum,a,b,cin);
input cin;//定义进位信号
input[3:0] a;
input[3:0] b;//定义两个BCD码的加数
output reg [3:0] sum;//定义输出和
output reg co;//定义输出的进位信号
reg[4:0] temp;//定义一个寄存器temp用来暂存计算结果
always@(a,b,cin) begin//每当a,b或者cin变化时
temp<=a+b+cin; //令temp为三者相加,也就是以二进制相加
end
always@(temp) begin//每当temp变化时
if(temp>4'd9) begin//判断temp是否大于10
sum<=temp-10;//如果大于10需要减去10,同时输出进位信号,这也就是十进制体现所在
co<=1;
end
else begin //如果不大于10
sum<=temp;
co<=0;//将进位信号清零,将temp送给输出sum
end
end
endmodule
//定义16位的BCD加法器
module BCD16bit(a,b,cin,sum,co);
//定义两个16位的输入信号
input[15:0] a;
input[15:0] b;
input cin;//定义输入进位信号
output[15:0] sum;//定义16位的加法之和
output co;//定义输出的进位信号
//定义三个wire类型的变量,作为端口之间的连接线
wire carry1,carry2,carry3;
BCD1bit U0(.co(carry1),.sum(sum[3:0]),.a(a[3:0]),.b(b[3:0]),.cin(cin));
BCD1bit U1(.co(carry2),.sum(sum[7:4]),.a(a[7:4]),.b(b[7:4]),.cin(carry1));
BCD1bit U2(.co(carry3),.sum(sum[11:8]),.a(a[11:8]),.b(b[11:8]),.cin(carry2));
BCD1bit U3(.co(co),.sum(sum[15:12]),.a(a[15:12]),.b(b[15:12]),.cin(carry3));//根据对应的连接线关系,将四个实例化之后的模块连接起来,形成16位的BCD加法器
endmodule
()激励模块代码
// Verilog Test Bench template for design : BCD16bit
//
// Simulation tool : ModelSim (Verilog)
//
`timescale 1 ps/ 1 ps
module BCD16bit_vlg_tst();
// constants
// general purpose registers
reg eachvec;
// test vector input registers
reg [3:0] a;
reg [3:0] b;
reg cin;
// wires
wire co;
wire [3:0] sum;
// assign statements (if any)
BCD16bit i1 (
// port map - connection between master ports and signals/registers
.a(a),
.b(b),
.cin(cin),
.co(co),
.sum(sum)
);
initial
begin
a<=16'h0001;
b<=16'h0001;
cin<=0;
150 $stop;
end
always #10 a[3:0]={$random}%10;
always #10 a[7:4]={$random}%10;
always #10 a[11:8]={$random}%10;
always #10 a[15:12]={$random}%10;
always #10 b[3:0]={$random}%10;
always #10 b[7:4]={$random}%10;
always #10 b[11:8]={$random}%10;
always #10 b[15:12]={$random}%10;
//每经过10ps,对每一位十进制数进行复赋值
always #10 cin={$random}%2;
endmodule
3.波形图
4.门级电路图
【结果分析及思考】
本次实验分别对16位二进制全加器模块,16位超前进位二进制全加器模块,16-bit 8421-BCD码全加器模块进行了设计与实现。其中在设计16位二进制全加器模块的过程中,分别使用了按照行为描述的方式以及按照数据流的方式建模,让我从实践的角度理解了建模方式的不同,掌握了包括门级电路,数据流以及行为描述这三种建模方法。
全加器是常用的组合逻辑模块中的一种,对全加器的分析和对组合逻辑电路的分析一样。组合逻辑电路的分析,就是找出给定电路输入和输出之间的逻辑关系,从而了解给定逻辑电路的逻辑功能。组合逻辑电路的分析方法通常采用代数法,我的设计过程按照老师所给出的步骤进行:先根据所需要的功能,列出真值表。然后根据真值表,写出相应的逻辑函数表达式。再根据真值表或逻辑函数表达式,画出相应的组合逻辑电路的逻辑图。之后用编写程序在QuartusⅡ上进行仿真并在Modelsim上测试,分析结果的正确性。
印象较深的是在数据流描述中,通过层次化设计方法实现的结构,这个加法器是使用了16个全加器进行连接和信号传递组成的,而一位全加器是由两个半加器以及一个或门所构成,这个全加器的组成和描述频繁使用了元件例化语句,就是为了能够完整的描述这16个全加器在结构上的关系以及和所对应输入输出之间的关系。
全加器是组合逻辑电路中最常见也最实用的一种,考虑低位进位的加法运算就是全加运算,实现全加运算的电路称为全加器。它主要实现加法的运算,其中分为并行全加器和串行全加器,所谓并行就是指向高位进位时是并行执行的,而串行就是从低位到高位按顺序执行,为了提高运算,必须设法减小或消除由于进位信号逐级传递所消耗的时间,为了提高运算速度,制成了超前进位加法器,这是对全加器的一种创新。这也正是超前进位二进制全加器的思想。
在16位的BCD码加法器的设计中,用4个数与4个数进行加和,通过BCD码输出结果。但是实验中需要注意很多细节,例如BCD码的最大范围就是1001也就是9,因此需要将二进制改为10进制,判断得到的结果是否需要进位,如果不需要进位的话,显示的结果就为真实结果,如果需要进位,则应当将得到的结果加上6,即对数字进行修正,以此实现显示信号的输出。
通过此次设计对全加器的设计和实现,积累和总结了不少的经验,锻炼了我的独立工作和实际动手能力,加深了对计算机中的全加器工作原理的认识,提高了对复杂的综合性实践环节具有分析问题、解决问题、概括总结的实际工作能力,对涉及全加器项目的开发、设计过程有初步认识。