精华内容
下载资源
问答
  • 上期介绍了半加器、全加器以及行波进位加法器(RCA),本文介绍超前进位加法器(Lookahead Carry Adder,简称LCA)。在介绍超前进位加法器前,我们先来分析下行波进位加法器的关键路径。一、行波进位加法器关键路径...

    fd8dd27ba640d2598722289345ba5ffa.png

    上期介绍了半加器、全加器以及行波进位加法器(RCA),本文介绍超前进位加法器(Lookahead Carry Adder,简称LCA)。在介绍超前进位加法器前,我们先来分析下行波进位加法器的关键路径。

    一、行波进位加法器关键路径分析

    N比特行波进位加法器可由N个全加器级联而成,电路的延迟包括门延迟和线延迟等,分析忽略线延迟。

    ca5b40ee4dfc8bc84e78944642f62702.png
    单比特全加器门电路图

    从输入a,b,cin到输出s和cout,有以下路径:

    • a->s:经过xor1,xor2两个门电路
    • b->s:经过xor1,xor2两个门电路
    • cin->s:经过xor2一个门店路
    • a->cout:经过xor1,and1,or1三个门电路
    • b->cout:经过xor1,and1,or1三个门电路
    • cin->cout:经过and2,or1两个门电路

    由这些路径可知,从a,b,cin输入数据准备好,到所有的s和cout完成,a或b到cout共有三个门电路延迟,是全加器的最长路径,且s不参与下一级全加器运算,cout将作为下一个cin输入继续计算下一级的s和cout。

    e8abca31ba4427a7627a3fb57efc78d0.png
    4比特行波进位加法器关键路径

    由N个全加器级联的行波进位加法器除了第一个进位c1有3个门延迟外,剩余N-1个全加器生成进位需要2个门电路延迟,所以N比特行波进位加法器最长路径共有“(3+(N-1)*2)=2N+1”个门电路延迟,如上图4比特行波进位加法器,红色描绘的路径即是最长路径,共有2*4+1=9个门电路延迟。

    二、超前进位加法器

    对于更宽的加法器N,行波进位加法器关键路径越长,限制了加法器的性能,对于高速处理器等将是个极大的瓶颈。所以,本文介绍的超前进位加法器优化改进行波进位器的关键路径。RCA的缺点在于第k位的进位Ck必须依赖于前一级的Ck-1,所以最高位的进位将必须等待之前所有级进位计算完毕后才能计算出结果。所以,超前进位加法器的思想是并行计算进位Ck。

    416a4b709be9782432112c6c8e20fc56.png

    观察上式s和c,将共有部分分别定义:

    58f3ca24b953aeb1e423e73ce759f4a3.png

    对于N比特LCA加法器,进位与和公式将重新书写如下:

    a5675283a98275eb50ee48f12e79c62a.png

    其中:

    bd023acc31a45445279f38e3fdaa263f.png

    其门电路图如下,其实是个半加器:

    88cc6fdb35e8b99ac23a90349ed2ae27.png

    以4比特LCA加法器为例,其进位链与和公式分别计算如下:

    2a472f44c574418b9a586da63c317a18.png

    9b4bf7e010c2cd19ecbc96cec6eed2d9.png

    根据上述式子,可以计算出Ci和Si,其结构图为:

    c22e4c769cfa1cf4ad4dafe845a81c88.png
    4比特超前进位加法器结构图

    根据超前进位加法器中进位链c和输出s的物理实现方式不同,大致可分成以下三类:

    • 递归超前进位加法器(Recursive Lookahead Carry Adder,简称RLCA)
    • 分类超前进位加法器(Block Lookahead Carry Adder,BCLA),也称(section-carry-based carry-lookahead adder)
    • 混合型超前进位加法器

    以上不同种类LCA之后细讲。对于位宽更大的LCA如16,32,64比特LCA等可以并行生成所有的PG和进位C,但这会造成电路极大的扇入和扇出;另外可以根据4比特LCA级联而成,如16比特LCA可由如下图级联而成(属RLCA):

    a3bfe8a4343b2203505e0a16e09e24b0.png
    4比特LCA级联而成的16比特LCA

    三、超前进位加法器关键路径分析

    为什么超前进位加法器在速度方面相比行波进位加法器更胜一筹?当然,从进位链的生成上也可以看出,我们从进位链C4来对比一下。

    78a2a070ea27bb20f39d8bdf594865d1.png
    LCA进位的c4门电路图

    2b7e23604c23a3de42b62746806b01de.png
    LCA输出S3门电路图

    从输入所有的a,b和c0,LCA的输出进位c4只需要3级门电路延迟,c0,c1,c2,c3同时生成,同时由于S3=P3 xor c3,所以4比特LCA关键路径为4级门延迟。虽然经过了很多门电路,但他们的计算是同时的,而4比特RCA计算出c4需要9个门电路延迟。同样是32比特加法器,理想的LCA(全部展开所有的进位逻辑)关键路径延迟理论上只需要4个门电路,而RCA的关键路径延迟为65个门电路。如果采用4比特级联LCA,形成32比特LCA,则需要(3+7*2+1)=18级门电路延迟,相比RCA,缩短了关键路径的长度。

    以上比较忽略多输入门延迟,真正的门电路延迟计算需根据不同的门电路库文件,且对AND/OR/NAND等门电路输入数目有限制,如通常的4输入。此处只可意会。

    总而言之,RCA的缺点在于关键路径长,限制了速度,性能不高;LCA关键路径短,速度快,进位链计算依赖少,但对于位宽较大的加法器,PG和进位生成逻辑大,存在较大扇入扇出,变化信号多,会有较多的glitch,且面积与复杂度比同等的RCA大。

    四、Verilog描述

    以下参数化LCA基于4比特LCA设计,width可参数化定义为4的倍数,如20,24,32等。

    14465398392e25868a6691cef9cfe472.png

    verilog源码公众号回复003获取。

    更多阅读,关注“纸上谈芯”,不定期更新,共同学习:

    90803c4bef6782c3f6b9a965a4c80355.png
    展开全文
  • 行波进位加法器八位超前进位加法器原理设计文件综合电路测试文件仿真波形八位行波进位加法器原理设计文件测试文件仿真波形总结八位超前进位加法器原理 有学弟问我,超前进位加法器中的p=add1 ^ add2和g=add1 &...

    超前进位加法器&行波进位加法器

    • 八位超前进位加法器
      • 原理
      • 设计文件
      • 综合电路
      • 测试文件
      • 仿真波形
    • 八位行波进位加法器
      • 原理
      • 设计文件
      • 测试文件
      • 仿真波形
    • 总结

    八位超前进位加法器

    原理

    有学弟问我,超前进位加法器中的p=add1 ^ add2g=add1 & add2是什么意思,所以这篇文章就稍微赘述一点吧~

    所谓超前进位,首先应该明白进位是什么。

    8+4=12,其中的1就是进位,其中的2才是结果。

    那么在二进制中,1+1=10,其中的1就是进位,0就是结果。

    明白了进位和结果,那么多位的数字是怎么计算呢?

    其实上面的计算应该是1+1+上一位的进位=10,所以两个数字的计算应该涉及三个内容——加数,被加数,上一位的进位。

    在一位二进制加法中,ab分别表示两个加数,cin表示上一位的进位,cout表示下一位的进位,sum表示结果,我们列出其真值表:

    add1add2cincoutsum

    以数字 1为真 ,数字0为假a表示1a'表示0,这样的形式。学过离散数学或者数字电路的同学应该多少会点吧,“·”代表“与”“+”代表“或”,所以上面的真值表,写成表达式,就是:

    经过部分化简:

    同理:

    找到两个等式的相同部分,都有a⊕b其中代表“异或”,在Verilog中用“^”表示,即a^b,所以令p = add1 ^ add2,现在知道干什么用的了嘛?

    没错,就是中间变量而已,同理g = add1 & add2也是中间变量,这样就可以把上面两个等式改写成:cout = g | (cin & p)sum = add1 ^ add2 ^ cin(其实就是变短了一点点而已)

    不过呢,适当的使用中间变量,可能会让你的代码精简许多~

    此外,我发现一个网站可以通过真值表生成表达式:http://www.32x8.com/index.html

    设计文件

    module add_8_1(
        input wire [7:0] add1,
        input wire [7:0] add2,
        input wire cin,
        output wire [7:0] sum,
        output wire cout
        );
        wire[7:0] g,p,c;//g和p的含义已经讲解了,c代表每一位计算的进位,c[0]表示原始的进位cin
        assign c[0]=cin;
        assign p=add1 ^ add2;
        assign g=add1 & add2;
        assign c[0] = g[0] | (p[0] & c[0]);
        assign c[1] = g[1] | (p[1] & (g[0] | (p[0] & c[0])));
        assign c[2] = g[2] | (p[2] & (g[1] | (p[1] & (g[0] | (p[0] & c[0])))));
        assign c[3] = g[3] | (p[3] & (g[2] | (p[2] & (g[1] | (p[1] & (g[0] | (p[0] & c[0])))))));
        assign c[4] = g[4] | (p[4] & (g[3] | (p[3] & (g[2] | (p[2] & (g[1] | (p[1] & (g[0] | (p[0] & c[0])))))))));
        assign c[5] = g[5] | (p[5] & (g[4] | (p[4] & (g[3] | (p[3] & (g[2] | (p[2] & (g[1] | (p[1] & (g[0] | (p[0] & c[0])))))))))));
        assign c[6] = g[6] | (p[6] & (g[5] | (p[5] & (g[4] | (p[4] & (g[3] | (p[3] & (g[2] | (p[2] & (g[1] | (p[1] & (g[0] | (p[0] & c[0])))))))))))));
        assign c[7] = g[7] | (p[7] & (g[6] | (p[6] & (g[5] | (p[5] & (g[4] | (p[4] & (g[3] | (p[3] & (g[2] | (p[2] & (g[1] | (p[1] & (g[0] | (p[0] & c[0])))))))))))))));
        assign sum=p^c[7:0];
        assign cout=c[7];
    endmodule
    

    上面的代码应该看起来很长,像老太太的裹脚布,但这也就是所谓的超前进位

    Verilog中“块”和assign语句都是并行执行的,上面有许多assign语句,所以从c[0]c[7],根据第一步的cin,就可以同步计算出每一位的进位(超前进位),以及最后的结果,这些是同时完成的,也就完成了超前进位加法器。

    综合电路

    dc17a3b8abdffc1b97b0c24bc03b427f.png

    点击RTL-ANALYSIS——Synthesis,可以查看综合电路图:

    19个元件,26IO口,56根线

    d8a3197c4fde9ebe92b3e7090498c436.png

    测试文件

    `timescale 1ns / 1ps
    module add_tb();
        reg [7:0] add1,add2;
        reg cin;
        reg clk;
        wire [7:0] sum;
        wire cout;
        initial begin
            add1 <= 8'd10;
            add2 <= 8'd3;
            cin <= 1'b0;     
            clk <= 1'b0;   
        end
        
        always # 10 clk = ~clk;
        always @ (negedge clk) begin
            {add1,add2} <= {add1,add2} + 1'b1;
        end
    
        add_8_1 try(.add1(add1),.add2(add2),.cin(cin),.sum(sum),.cout(cout));
        
    endmodule
    

    还有些同学,对测试文件的理解也还是不够深刻,这里稍提一嘴,测试文件就是给电路加激励信息,使电路运作。至于加提示信息之类的,各自加油就好啦~

    仿真波形

    0121ce3beae81c05908bec307a82a041.png

    0fcd854f6a33e0d0b559073c2fc08b8a.png

    右键某一信号,选择相应的进制数,以10+9为例,最终输出cout=0sum=19

    那么之后的10+11为什么没有进位使cout=1呢?

    把他们转换成二进制观察一下就明白啦~

    八位行波进位加法器

    当时不知道在哪听的这个名字,就一直用下了,其实这个应该叫做行波进位加法器——由N个全加器级联而成,所以被我叫成了级联进位emmm

    原理

    如上所说,行波进位加法器是由N个全加器级联而成,比如8位的加法器可以由8个一位全加器级联而成,也可以由2个四位全加器构成,区别就是所综合出的电路大小。

    设计文件

    方式一

    module add_8_2(
        input wire [7:0] add1,add2,
        input wire cin,
        output reg [7:0] sum,
        output reg cout
    );
        reg[7:0] G,P,C; 
    always @(add1 or add2 or cin)
    begin
        G[0] = add1[0] & add2[0]; 
        P[0] = add1[0] ^ add2[0]; 
        C[0] = cin; //最低位的进位输入,即cin
        sum[0] = G[0]^ P[0] ^ C[0];//第一位的计算结果
        G[1] = add1[1] & add2[1];
        P[1] = add1[1] ^ add2[1];
        C[1] = G[0] |(P[0] & C[0]);//c=add1add2+(add1+add2)cin=G|(P&cin)
        sum[1] = G[1] ^ P[1] ^ C[1];
        G[2] = add1[2] & add2[2];
        P[2] = add1[2] ^ add2[2];
        C[2] = G[1] |(P[1] & C[1]);
        sum[2] = G[2] ^ P[2] ^ C[2];
        G[3] = add1[3]& add2[3];
        P[3] = add1[3] ^ add2[3];
        C[3] = G[2] |(P[2] & C[2]);
        sum[3] = G[3] ^ P[3] ^ C[3];
        G[4] = add1[4] & add2[4];
        P[4] = add1[4] ^ add2[4];
        C[4] = G[3] |(P[3] & C[3]);
        sum[4] = G[4] ^ P[4] ^ C[4];
        G[5] = add1[5] & add2[5];
        P[5] = add1[5] ^ add2[5];
        C[5] = G[4] |(P[4] & C[4]);
        sum[5] = G[5] ^ P[5] ^ C[5];
        G[6] = add1[6] & add2[6];
        P[6] = add1[6] ^ add2[6];
        C[6] = G[5] |(P[5] & C[5]);
        sum[6] = G[6] ^ P[6] ^ C[6];
        G[7] = add1[7] & add2[7];
        P[7] = add1[7] ^ add2[7];
        C[7] = G[6] |(P[6] & C[6]);
        sum[7] = G[7] ^ P[7] ^ C[7];
        cout = G[7] |(P[7] & C[7]);
    end
    endmodule
    

    这是把上述原理复现了一边,上一步的进位输出,传入到下一位计算的进位输入。

    综合后的电路如下,48个元件,26IO口,65根线

    综合电路

    1c4b985b3a5059d63afde58b9d4a740c.png

    方式二

    上面的语句重复性太大,就用模块例化的方式来写

    module add_8_2(
        input wire [7:0] add1,add2,
        input wire cin,
        output wire [7:0] sum,
        output wire cout
    );
        wire [6:0] c;
        add_1_unit a1(add1[0],add2[0],cin,c[0],sum[0]);
        add_1_unit a2(add1[1],add2[1],c[0],c[1],sum[1]);
        add_1_unit a3(add1[2],add2[2],c[1],c[2],sum[2]);
        add_1_unit a4(add1[3],add2[3],c[2],c[3],sum[3]);
        add_1_unit a5(add1[4],add2[4],c[3],c[4],sum[4]);
        add_1_unit a6(add1[5],add2[5],c[4],c[5],sum[5]);
        add_1_unit a7(add1[6],add2[6],c[5],c[6],sum[6]);
        add_1_unit a8(add1[7],add2[7],c[6],cout,sum[7]);
    endmodule
    

    其中的add_1_unit模块如下:

    module add_1_unit(
        input wire add1,add2,cin,
        output wire cout,sum
        );
        assign cout = (add1 & add2) | (cin & (add1 ^ add2));
        assign sum = add1 ^ add2 ^ cin;    
    endmodule
    

    综合后的电路如下,全展开后有48个元件,26IO口,97根线

    综合电路

    9abebd1904a0ec22df7e2eedd58af1ee.png

    其中的每一个单元如下:

    6a554719df7e21f4a71d28dca645fe09.png

    全展开后如下:

    93dd7b7cf927ab415532bfc1cf3bc391.png

    两种写法

    数据总线的数量有区别:一个是65根线,一个是97根线。

    代码量有区别:一个40行左右,一个总共27行左右。

    优缺点不言而喻。

    测试文件

    都是八位加法器,与超前进位加法器也没区别

    还是放一下吧:

    `timescale 1ns / 1ps
    module add_tb();
        reg [7:0] add1,add2;
        reg cin;
        reg clk;
        wire [7:0] sum;
        wire cout;
        initial begin
            add1 <= 8'd10;
            add2 <= 8'd3;
            cin <= 1'b0;     
            clk <= 1'b0;   
        end
        
        always # 10 clk = ~clk;
        always @ (negedge clk) begin
            {add1,add2} <= {add1,add2} + 1'b1;
        end
    
        add_8_2 try(.add1(add1),.add2(add2),.cin(cin),.sum(sum),.cout(cout));
        
    endmodule
    

    仿真波形

    与超前进位一致,用二进制查看一下如下图:

    9106bb7156baeb6fd66228c45888076b.png

    总结

    行波进位加法器,由于后一位的进位依赖于前一位的进位,所以关键路径更长,限制速度,性能不高,

    超前进位加法器,由于进位计算是并行的,所以关键路径短,速度快,但是位宽越宽,也就代表会综合出更复杂的、面积更大的电路。

    展开全文
  • 文章目录八位超前进位加法器原理设计文件综合电路测试文件仿真波形八位行波进位加法器原理设计文件方式一综合电路方式二综合电路测试文件仿真波形总结 八位超前进位加法器 原理 有学弟问我,超前进位加法器中的p=...

    八位超前进位加法器

    原理

    有学弟问我,超前进位加法器中的p=add1 ^ add2g=add1 & add2是什么意思,所以这篇文章就稍微赘述一点吧~

    所谓超前进位,首先应该明白进位是什么。

    8+4=12,其中的1就是进位,其中的2才是结果。

    那么在二进制中,1+1=10,其中的1就是进位,0就是结果。

    明白了进位和结果,那么多位的数字是怎么计算呢?

    其实上面的计算应该是1+1+上一位的进位=10,所以两个数字的计算应该涉及三个内容——加数,被加数,上一位的进位。

    在一位二进制加法中,ab分别表示两个加数,cin表示上一位的进位,cout表示下一位的进位,sum表示结果,我们列出其真值表:

    add1 add2 cin cout sum
    0 0 0 0 0
    0 1 0 0 1
    1 0 0 0 1
    1 1 0 1 0
    0 0 1 0 1
    0 1 1 1 0
    1 0 1 1 0
    1 1 1 1 1

    以数字**1为真**,数字**0为假**,a表示1a'表示0,这样的形式。学过离散数学或者数字电路的同学应该多少会点吧,“·”代表“与”“+”代表“或”,所以上面的真值表,写成表达式,就是:
    cout=add1add2cin+add1add2cin+add1add2cin+add1add2cin cout = add1·add2·cin'+add1'·add2·cin+add1·add2'cin+add1·add2·cin
    经过部分化简:
    cout=add1add2+add1add2cin+add1add2cin=add1add2+cin(add1add2) cout=add1·add2+add1'add2·cin+add1·add2'·cin=add1·add2+cin·(add1⊕add2)
    同理:
    sum=add1add2cin sum =add1⊕add2⊕cin
    找到两个等式的相同部分,都有a⊕b其中代表“异或”,在Verilog中用“^”表示,即a^b,所以令p = add1 ^ add2,现在知道干什么用的了嘛?

    没错,就是中间变量而已,同理g = add1 & add2也是中间变量,这样就可以把上面两个等式改写成:cout = g | (cin & p)sum = add1 ^ add2 ^ cin(其实就是变短了一点点而已)

    不过呢,适当的使用中间变量,可能会让你的代码精简许多~

    此外,我发现一个网站可以通过真值表生成表达式:http://www.32x8.com/index.html

    设计文件

    module add_8_1(
        input wire [7:0] add1,
        input wire [7:0] add2,
        input wire cin,
        output wire [7:0] sum,
        output wire cout
        );
        wire[7:0] g,p,c;//g和p的含义已经讲解了,c代表每一位计算的进位,c[0]表示原始的进位cin
        assign c[0]=cin;
        assign p=add1 ^ add2;
        assign g=add1 & add2;
        assign c[0] = g[0] | (p[0] & c[0]);
        assign c[1] = g[1] | (p[1] & (g[0] | (p[0] & c[0])));
        assign c[2] = g[2] | (p[2] & (g[1] | (p[1] & (g[0] | (p[0] & c[0])))));
        assign c[3] = g[3] | (p[3] & (g[2] | (p[2] & (g[1] | (p[1] & (g[0] | (p[0] & c[0])))))));
        assign c[4] = g[4] | (p[4] & (g[3] | (p[3] & (g[2] | (p[2] & (g[1] | (p[1] & (g[0] | (p[0] & c[0])))))))));
        assign c[5] = g[5] | (p[5] & (g[4] | (p[4] & (g[3] | (p[3] & (g[2] | (p[2] & (g[1] | (p[1] & (g[0] | (p[0] & c[0])))))))))));
        assign c[6] = g[6] | (p[6] & (g[5] | (p[5] & (g[4] | (p[4] & (g[3] | (p[3] & (g[2] | (p[2] & (g[1] | (p[1] & (g[0] | (p[0] & c[0])))))))))))));
        assign c[7] = g[7] | (p[7] & (g[6] | (p[6] & (g[5] | (p[5] & (g[4] | (p[4] & (g[3] | (p[3] & (g[2] | (p[2] & (g[1] | (p[1] & (g[0] | (p[0] & c[0])))))))))))))));
        assign sum=p^c[7:0];
        assign cout=c[7];
    endmodule
    

    上面的代码应该看起来很长,像老太太的裹脚布,但这也就是所谓的超前进位

    Verilog中“块”和assign语句都是并行执行的,上面有许多assign语句,所以从c[0]c[7],根据第一步的cin,就可以同步计算出每一位的进位(超前进位),以及最后的结果,这些是同时完成的,也就完成了超前进位加法器。

    综合电路

    image-20201107203230210

    点击RTL-ANALYSIS——Synthesis,可以查看综合电路图:

    19个元件,26IO口,56根线

    image-20201107213633419

    测试文件

    `timescale 1ns / 1ps
    module add_tb();
        reg [7:0] add1,add2;
        reg cin;
        reg clk;
        wire [7:0] sum;
        wire cout;
        initial begin
            add1 <= 8'd10;
            add2 <= 8'd3;
            cin <= 1'b0;     
            clk <= 1'b0;   
        end
        
        always # 10 clk = ~clk;
        always @ (negedge clk) begin
            {add1,add2} <= {add1,add2} + 1'b1;
        end
    
        add_8_1 try(.add1(add1),.add2(add2),.cin(cin),.sum(sum),.cout(cout));
        
    endmodule
    

    还有些同学,对测试文件的理解也还是不够深刻,这里稍提一嘴,测试文件就是给电路加激励信息,使电路运作。至于加提示信息之类的,各自加油就好啦~

    仿真波形

    image-20201107204605260

    image-20201107204248110

    右键某一信号,选择相应的进制数,以10+9为例,最终输出cout=0sum=19

    那么之后的10+11为什么没有进位使cout=1呢?

    把他们转换成二进制观察一下就明白啦~

    八位行波进位加法器

    当时不知道在哪听的这个名字,就一直用下了,其实这个应该叫做行波进位加法器——由N个全加器级联而成,所以被我叫成了级联进位emmm

    原理

    如上所说,行波进位加法器是由N个全加器级联而成,比如8位的加法器可以由8个一位全加器级联而成,也可以由2个四位全加器构成,区别就是所综合出的电路大小。

    设计文件

    方式一

    module add_8_2(
        input wire [7:0] add1,add2,
        input wire cin,
        output reg [7:0] sum,
        output reg cout
    );
        reg[7:0] G,P,C; 
    always @(add1 or add2 or cin)
    begin
        G[0] = add1[0] & add2[0]; 
        P[0] = add1[0] ^ add2[0]; 
        C[0] = cin; //最低位的进位输入,即cin
        sum[0] = G[0]^ P[0] ^ C[0];//第一位的计算结果
        G[1] = add1[1] & add2[1];
        P[1] = add1[1] ^ add2[1];
        C[1] = G[0] |(P[0] & C[0]);//c=add1add2+(add1+add2)cin=G|(P&cin)
        sum[1] = G[1] ^ P[1] ^ C[1];
        G[2] = add1[2] & add2[2];
        P[2] = add1[2] ^ add2[2];
        C[2] = G[1] |(P[1] & C[1]);
        sum[2] = G[2] ^ P[2] ^ C[2];
        G[3] = add1[3]& add2[3];
        P[3] = add1[3] ^ add2[3];
        C[3] = G[2] |(P[2] & C[2]);
        sum[3] = G[3] ^ P[3] ^ C[3];
        G[4] = add1[4] & add2[4];
        P[4] = add1[4] ^ add2[4];
        C[4] = G[3] |(P[3] & C[3]);
        sum[4] = G[4] ^ P[4] ^ C[4];
        G[5] = add1[5] & add2[5];
        P[5] = add1[5] ^ add2[5];
        C[5] = G[4] |(P[4] & C[4]);
        sum[5] = G[5] ^ P[5] ^ C[5];
        G[6] = add1[6] & add2[6];
        P[6] = add1[6] ^ add2[6];
        C[6] = G[5] |(P[5] & C[5]);
        sum[6] = G[6] ^ P[6] ^ C[6];
        G[7] = add1[7] & add2[7];
        P[7] = add1[7] ^ add2[7];
        C[7] = G[6] |(P[6] & C[6]);
        sum[7] = G[7] ^ P[7] ^ C[7];
        cout = G[7] |(P[7] & C[7]);
    end
    endmodule
    

    这是把上述原理复现了一边,上一步的进位输出,传入到下一位计算的进位输入。

    综合后的电路如下,48个元件,26IO口,65根线

    综合电路

    image-20201107211917238

    方式二

    上面的语句重复性太大,就用模块例化的方式来写

    module add_8_2(
        input wire [7:0] add1,add2,
        input wire cin,
        output wire [7:0] sum,
        output wire cout
    );
        wire [6:0] c;
        add_1_unit a1(add1[0],add2[0],cin,c[0],sum[0]);
        add_1_unit a2(add1[1],add2[1],c[0],c[1],sum[1]);
        add_1_unit a3(add1[2],add2[2],c[1],c[2],sum[2]);
        add_1_unit a4(add1[3],add2[3],c[2],c[3],sum[3]);
        add_1_unit a5(add1[4],add2[4],c[3],c[4],sum[4]);
        add_1_unit a6(add1[5],add2[5],c[4],c[5],sum[5]);
        add_1_unit a7(add1[6],add2[6],c[5],c[6],sum[6]);
        add_1_unit a8(add1[7],add2[7],c[6],cout,sum[7]);
    endmodule
    

    其中的add_1_unit模块如下:

    module add_1_unit(
        input wire add1,add2,cin,
        output wire cout,sum
        );
        assign cout = (add1 & add2) | (cin & (add1 ^ add2));
        assign sum = add1 ^ add2 ^ cin;    
    endmodule
    

    综合后的电路如下,全展开后有48个元件,26IO口,97根线

    综合电路

    image-20201107211509863

    其中的每一个单元如下:

    image-20201107211540510

    全展开后如下:

    image-20201107212247756

    两种写法

    数据总线的数量有区别:一个是65根线,一个是97根线。

    代码量有区别:一个40行左右,一个总共27行左右。

    优缺点不言而喻。

    测试文件

    都是八位加法器,与超前进位加法器也没区别

    还是放一下吧:

    `timescale 1ns / 1ps
    module add_tb();
        reg [7:0] add1,add2;
        reg cin;
        reg clk;
        wire [7:0] sum;
        wire cout;
        initial begin
            add1 <= 8'd10;
            add2 <= 8'd3;
            cin <= 1'b0;     
            clk <= 1'b0;   
        end
        
        always # 10 clk = ~clk;
        always @ (negedge clk) begin
            {add1,add2} <= {add1,add2} + 1'b1;
        end
    
        add_8_2 try(.add1(add1),.add2(add2),.cin(cin),.sum(sum),.cout(cout));
        
    endmodule
    

    仿真波形

    与超前进位一致,用二进制查看一下如下图:

    image-20201107214523763

    总结

    行波进位加法器,由于后一位的进位依赖于前一位的进位,所以关键路径更长,限制速度,性能不高,

    超前进位加法器,由于进位计算是并行的,所以关键路径短,速度快,但是位宽越宽,也就代表会综合出更复杂的、面积更大的电路。

    展开全文
  • 1. 行波进位实现方式:

    1. 行波进位实现方式:

    module adder4_ripple
    (
        input   wire    [3:0] a, b,
        input   wire    Cin0,
        
        output  wire    [3:0] y,
        output  wire    Cout
    );
    
    wire  Cin1, Cin2, Cin3;
        
    full_adder1 a1(a[0], b[0], Cin0, y[0], Cin1);
    full_adder1 a2(a[1], b[1], Cin1, y[1], Cin2);
    full_adder1 a3(a[2], b[2], Cin2, y[2], Cin3);
    full_adder1 a4(a[3], b[3], Cin3, y[3], Cout);
    
    endmodule
    
    
    module full_adder1
    (
        input   wire   a, b,
        input   wire   Cin,
        
        output  wire   y, Cout
    );
    
    assign  y = a ^ b ^ Cin;
    assign  Cout = (a & b) + (a & Cin) + (b & Cin);
    
    endmodule
    module tb_adder4();
    reg [3:0] a,b;
    reg Cin0;
    
    wire [3:0] y;
    wire Cout;
    
    initial begin
        a = 4'd5;
        Cin0 = 1'b1;
        b = 4'd8;
        #50 a = 4'd1;
        #50 a = 4'd3;
        #50 b = 4'd7;
        #50 a = 4'd10;
    end
    
    adder4_ripple adder4_ripple_inst
    (
        .a    ( a    ), 
        .b    ( b    ),
        .Cin0 ( Cin0 ),
        
        .y    ( y    ),
        .Cout ( Cout )
    );
    endmodule

    仿真结果:

     

    2. 超前进位实现方式:

    module adder4_CLA
    (
        input   wire    [3:0]   a   , 
        input   wire    [3:0]   b   ,
        input   wire            Cin0,
        
        output  wire            Gm  ,
        output  wire            Pm  ,
        output  wire    [3:0]   y   ,
        output  wire            Cout
    );
    
    wire  [3:0] G,P;
    wire  [4:1] C;
        
    full_adder_1bit a1(a[0], b[0], Cin0, y[0], G[0], P[0]);
    full_adder_1bit a2(a[1], b[1], C[1], y[1], G[1], P[1]);
    full_adder_1bit a3(a[2], b[2], C[2], y[2], G[2], P[2]);
    full_adder_1bit a4(a[3], b[3], C[3], y[3], G[3], P[3]);
    
    CLA_4 CLA_4_inst(P,G,Cin0,C,Gm,Pm);
    
    assign Cout = C[4];
    endmodule
    
    
    module full_adder_1bit
    (
        input   wire   a, b,
        input   wire   Cin,
        
        output  wire   y, 
        //Cout = a*b + a*Cin + b*Cin = a*b + (a+b)*Cin = g + p*Cin
        output  wire   g, //生成信号
        output  wire   p  //传播信号
    );
    
    assign  y = a ^ b ^ Cin;
    assign  g = a & b;
    assign  p = a | b;
    endmodule
    
    
    module CLA_4
    (
        input   wire [3:0]   P   ,
        input   wire [3:0]   G   ,
        input   wire         C_in ,
                
        output  wire [4:1]   Ci  ,
        output  wire         Gm  ,
        output  wire         Pm
    );
    
    assign Ci[1]=G[0]|P[0]&C_in;
    assign Ci[2]=G[1]|P[1]&G[0]|P[1]&P[0]&C_in;
    assign Ci[3]=G[2]|P[2]&G[1]|P[2]&P[1]&G[0]|P[2]&P[1]&P[0]&C_in;
    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]&C_in;
    
    //Cout = a*b + a*Cin + b*Cin = a*b + (a+b)*Cin = g + p*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
    module tb_adder4_CLA();
    reg [3:0] a,b;
    reg Cin0;
    
    wire [3:0] y;
    wire Gm, Pm, Cout;
    
    initial begin
        a = 4'd5;
        Cin0 = 1'b1;
        b = 4'd8;
        #50 a = 4'd1;
        #50 a = 4'd3;
        #50 b = 4'd7;
        #50 a = 4'd10;
    end
    
    adder4_CLA  adder4_CLA_inst
    (
        .a    ( a    ), 
        .b    ( b    ),
        .Cin0 ( Cin0 ),
        
        .Gm   ( Gm   ),
        .Pm   ( Pm   ),
        .y    ( y    ),
        .Cout ( Cout )
    );
    endmodule

    仿真结果:

    展开全文
  • 加法器是算术运算的一种,在计算机和一些处理器中被运用于算术逻辑单元ALU中或者处理器的其他部分如计算地址,加减操作等类似操作。今天。我们来重温下数字电路中的加法器。一、半加器半加器用于计算2个单比特二进制...
  • Sklansky加法器是另一种并行高速的树形...一、进位选择加法器Sklansky加法器使用了进位选择加法器:进位选择加法器由2个行波进位加法器和1个选择器构成其中一个行波进位加法器假定进位进位为0另外一个行波进位加法...
  • 前期已介绍了行波进位加法器(Ripple Carry Adder, RCA)依赖于低位进位,所以具有超长的进位链和关键路径。对于RCA的改进中,进位选择加法器(Carry Select Adder)是比较特别的一种,鉴于有太多的加法器缩写是CSA...
  • 3-2 Verilog 4位行波进位加法器

    千次阅读 2016-04-23 13:02:52
    Verilog 学习过程 4位行波进位加法器
  • 一、进位旁边加法器进位旁路加法器(Carry Skip Adder,CSA),...此前介绍了行波进位加法器RCA,第k位的进位Ck必须等待之前的Ck-1的结果才能计算出来,如下图进位c16必须等到前一级全加器的c15输出才可以计算,所以...
  • 来自微信公众号 “数字芯片实验室”加减法是一类非常基础的运算,本文分析最简单的行波进位加/减法(Ripple CarryAdder/Subtractor)的硬件开销和性能问题。在文章的开始控制变量,仅使用工艺库中的基本逻辑门AND-...
  • 半加器、全加器和行波进位加法器原理与设计 HDLBits链接 半加器 定义: 半加器用于计算2个单比特二进制数a与b的和,输出结果sum(s)和进位carry(c)。在多比特数的计算中,进位c将作为下一相邻比特的加法运算中。...
  • 三、行波进位加法器 加法器是算术运算的一种,在计算机和一些处理器中被运用于算术逻辑单元ALU中或者处理器的其他部分如计算地址,加减操作等类似操作。今天。我们来重温下数字电路中的加法器。 一、半加器 ...
  • 行波进位(ripple carry)加法器,将单个一比特全加器相连接,输出加法和以及进位 首先先写好单比特全加器的模块 ...在行波进位加法器实现中,将N个全加器相连来实现N位数加法 module ripple_carry_adder
  • 32位超前进位加法器设计verilog 分成几个部分啊
  • 一、行波进位加法器关键路径分析 二、超前进位加法器 三、超前进位加法器关键路径分析 四、Verilog描述 上期介绍了半加器、全加器以及行波进位加法器(RCA),本文介绍超前进位加法器(Lookahead Carry Adder,...
  • 超前进位加法器:普通全加器(行波进位加法器)是单比特全加器的级联,高位需要低位的进位位,故位宽增大时,加法的组合逻辑不断增大,超前进位加法器解决了这一问题。 优点:不需要等待低位的进位。直接计算就可...
  • `timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: SMIE // Engineer: ChenYu // Create Date: 08:57:11 10/05/2014 // Design Name: A

空空如也

空空如也

1 2 3 4 5 6
收藏数 120
精华内容 48
关键字:

行波进位加法器verilog