advertisement

2013年9月20日

Verilog incrementer mult4 mult8 PRcalc8


1.      若一AND(gate) 之輸出延遲為1nsOR閘之輸出延遲為1nsINVERTER閘之輸出延遲為0ns,請計算下列加法器之輸出延遲。
(A)以全加器與半加器設計之4位元漣波加法器(ripple carry adder)
假設a,b為被加數與加數,cout為相加後的進位,sum為相加後的總和,cin為進位輸入。
1位元半加器之運算式為下列:
          sum=a ^ b 延遲2ns
                  a ^ b= (a & ~b) | (~a &b)
                  a,b同時輸入,故(a & ~b)(~a & b)同時運算完成同時延遲1ns
                  延遲1ns後待計算完&後在計算| 故在延遲1ns
                  ^總延遲為2ns,故sum得出結果後延遲2ns
          cout=a & b 由題目假設得知延遲1ns
                 
1位元全加器之運算式為下列:
          sum=cin^a^b 延遲2ns
                  因為cinab為時輸入並同時做XOR運算故延遲僅為2ns
     cout=(a&b)|(a|b)&cin 延遲 3ns
                  a,b同時輸入,故(a&b)(a|b)同時運算完成同時延遲1ns
                  (a&b)(a|b)運算完後(a|b)要先跟cin 做&,故在延遲1ns最後(a|b)&cin運算完後再跟(a&b)做|在延遲1ns,故總延遲為 3ns
                 
由於四位元漣波加法器需用到一個半加器和三個全加器,由圖中可以看到每個半加器與全加器的輸入ab皆為同時輸入,我先看低位元的半加器,其半加器之sum在延遲2ns時即得到結果,cout在延遲1ns時得到結果,而第二位元全加器之sum需等待第一位元(半加器)cout運算完在輸入至cinXOR運算,故在這邊延遲為1+2=3ns,而第二位元全加器的cout在延遲1ns時先做了 a&b a|b運算,此時前一個位元(半加器)cont也一同運算出來並輸入至第二位元的cin,故第二位元在延遲1ns把運算完的(a|b)cin做&運算完,在延遲1ns把運算完的(a|b)&cin(a&b)做|,故第二位元的cout延遲為3ns,第三位元之sum需等第二位元之cout運算完才能做XOR,故第三位元之sum延遲為3+2=5ns,而第三位元之cout在延遲1ns時先做了 a&b a|b運算,此時第二位元的cout還沒運算完,還差3-1=2ns,故延遲2ns 第二位元cout才輸入至第三位元cin,在延遲1ns把運算完的(a|b)cin做&運算完,在延遲1ns把運算完的(a|b)&cin(a&b)做|,故第三位元的cout延遲為5ns,第四位元之sum要等到第三位元之cout輸出至第四位元cin,故延遲5+2=7ns,而第四位元之cout在延遲1ns時先做了 a&b a|b運算,此時第三位元的cout還沒運算完,還差5-1=4ns,故延遲4ns 第三位元cout才輸入至第四位元cin,在延遲1ns把運算完的(a|b)cin做&運算完,在延遲1ns把運算完的(a|b)&cin(a&b)做|,故第四位元的cout延遲為7ns
結論由於整個4位元之coutsum皆為延遲7ns,故漣波加法器延遲7ns

(B)4位元進位前瞻(carry lookahead)加法器。
                  進位前瞻加法器會預先運算完每個位元的進位位元,在此我假設cin為進位輸入,c0為第一位元運算後的進位,c1為第二位元運算後的進位,c2為第三位元運算後的進位,而cout=c3為第四位元運算後的進位,sum0為第一位元相加之和,sum1為第二位元相加之和,sum2為第三位元相加之和,sum3為第四位元相加之和。

由公式來看:
pi=ai+bi  延遲1ns
gi=aibi  延遲1ns
ci=gi+pic(i-1)
p0=a0+b0
g0=a0B0
c0=g0+p00=g0
c1=g1+p1c0=g1+p1g0
c2=g2+p2c1=g2+p2(g1+p1g0)=g2+p2g1+p2p1g0
c3=g3+p3c2=g3+p3(g2+p2g1+p2p1g0)
=g3+p3g2+p3p2g1+p3p2p1g0

pi gi皆延遲1nsc1在延遲1nsp1g0g1運算完成,在延遲1ns p1g0and,在延遲1nsg1OR,故c1延遲3ns
pi gi皆延遲1nsc2在延遲1nsp1p2g0g1g2運算完成,在延遲1ns p1g0 p2andp2 g1and,在延遲1ns g2 p2g1 p2p1g0OR,故c2延遲3ns
pi gi皆延遲1nsc3在延遲1nsp1 p2 p3 g0 g1 g2 g3運算完成,在延遲1ns p1 g0 p2 p3andp2 g1 p3p3 g2and,在延遲1ns g3 p3g2 p3p2g1 p3p2p1g0OR,故c1延遲3ns


sum0=a0^b0由於同時輸入且由上得知XOR延遲2ns
sum1=a1^b1^co0由於同時輸入且由上得知XOR延遲2ns
sum2=a2^b2^co1由於同時輸入且由上得知XOR延遲2ns
sum3=a3^b3^co2由於同時輸入且由上得知XOR延遲2ns

最後由於a,b,cin為同時輸入,故延遲時間以最長為3ns

2.      將一數加1在演算法中會經常用到,若以一般加法器來實作會速度較慢面積也較大,因此可以單獨設計一加一器(incrementer),請以進位前瞻加法器之方法設計一4位元incrementer,模組為inc4(a[3:0], cout, inc[3:0]),其中a為輸入,cout為進位輸出,inc4位元結果。

--------------------------------incrementer.v-----------------------------------
module cla4(a,cout,inc);
        input   [3:0]   a;
        output  [3:0]   inc;
        output  cout;
        wire    [2:0]   co;

        assign #1 co[0]=a[0]&1'b1;
        assign #1 co[1]=(a[1]&1'b0)|((a[1]|1'b0)&(a[0]&1'b1));
        assign #1 co[2]=(a[2]&1'b0)|((a[2]|1'b0)&((a[1]&1'b0)|((a[1]|1'b0)&(a[0]&1'b1))));
        assign #1 cout=(a[3]&1'b0)|((a[3]|1'b0)&((a[2]&1'b0)|((a[2]|1'b0)&((a[1]&1'b0)|((a[1]|1'b0)&(a[0]&1'b1))))));
        assign #1 inc[0]=a[0]^1'b1;
        assign #1 inc[1]=a[1]^1'b0^co[0];
        assign #1 inc[2]=a[2]^1'b0^co[1];
        assign #1 inc[3]=a[3]^1'b0^co[2];
endmodule
------------------------------incrementer_prove.v-----------------------------
module cla4(a,cout,inc);
        input   [3:0]   a;
        output  [3:0]   inc;
        output  cout;
        wire    [2:0]   co;

        assign #1 co[0]=a[0]&1'b1;
        assign #1 co[1]=(a[1]&(a[0]&1'b1));
        assign #1 co[2]=(a[2]&(a[1]&(a[0]&1'b1)));
        assign #1 cout=(a[3]&(a[2]&(a[1]&(a[0]&1'b1))));
        assign #1 inc[0]=a[0]^1'b1;
        assign #1 inc[1]=a[1]^1'b0^co[0];
        assign #1 inc[2]=a[2]^1'b0^co[1];
        assign #1 inc[3]=a[3]^1'b0^co[2];
endmodule
------------------------------------GTKWAVE---------------------------------------


3.      假設4位元加法器,模組為cla4(a[3:0], b[3:0], cin, cout, sum[3:0]),請以此模組為底(base)再加其他必須之邏輯,設計
(A)4位元乘法器,模組為mult4(a[3:0], b[3:0], axb[7:0]),其中a,b為輸入,axb為輸出。
-------------------------------------mult4_1.v----------------------------------------
module cla4(a,b,cin,cout,sum);
        input   [3:0]   a,b;
        input   cin;
        output  [3:0]   sum;
        output  cout;
        wire    [2:0]   co;

        assign #1 co[0]=(a[0]&b[0])|((a[0]|b[0])&cin);
        assign #1 co[1]=(a[1]&b[1])|((a[1]|b[1])&((a[0]&b[0])|((a[0]|b[0])&cin)));
        assign #1 co[2]=(a[2]&b[2])|((a[2]|b[2])&((a[1]&b[1])|((a[1]|b[1])&((a[0]&b[0])|((a[0]|b[0])&cin)))));
        assign #1 cout=(a[3]&b[3])|((a[3]|b[3])&((a[2]&b[2])|((a[2]|b[2])&((a[1]&b[1])|((a[1]|b[1])&((a[0]&b[0])|((a[0]|b[0])&cin)))))));
        assign #1 sum[0]=a[0]^b[0]^cin;
        assign #1 sum[1]=a[1]^b[1]^co[0];
        assign #1 sum[2]=a[2]^b[2]^co[1];
        assign #1 sum[3]=a[3]^b[3]^co[2];
endmodule

module  mult4(a,b,axb);
        input   [3:0]   a,b;
        output  [7:0]   axb;
        wire    [3:0]   pp0,pp1,pp2,pp3;

        assign  #1      pp0=b[0]?a:0;
        assign  #1      pp1=b[1]?a:0;
        assign  #1      pp2=b[2]?a:0;
        assign  #1      pp3=b[3]?a:0;

        wire    [3:0]   s1,s2;
        wire    c1,c2;

        cla4    u1      ({1'b0,pp0[3:1]},pp1,1'b0,c1,s1);
        cla4    u2      ({c1,s1[3:1]},pp2,1'b0,c2,s2);
        cla4    u3      ({c2,s2[3:1]},pp3,1'b0,axb[7],axb[6:3]);

        assign  axb[2]=s2[0];
        assign  axb[1]=s1[0];
        assign  axb[0]=pp0[0];
endmodule
------------------------------------GTKWAVE---------------------------------------

(B)再以cla4, mult4模組為底,設計8位元乘法器mult8(a[7:0], b[7:0], axb[15:0]),其中a,b為輸入,axb為輸出。
------------------------------------mult8.v---------------------------------------
module cla4(a,b,cin,cout,sum);
        input   [3:0]   a,b;
        input   cin;
        output  [3:0]   sum;
        output  cout;
        wire    [2:0]   co;

        assign #1 co[0]=(a[0]&b[0])|((a[0]|b[0])&cin);
        assign #1 co[1]=(a[1]&b[1])|((a[1]|b[1])&((a[0]&b[0])|((a[0]|b[0])&cin)));
        assign #1 co[2]=(a[2]&b[2])|((a[2]|b[2])&((a[1]&b[1])|((a[1]|b[1])&((a[0]&b[0])|((a[0]|b[0])&cin)))));
        assign #1 cout=(a[3]&b[3])|((a[3]|b[3])&((a[2]&b[2])|((a[2]|b[2])&((a[1]&b[1])|((a[1]|b[1])&((a[0]&b[0])|((a[0]|b[0])&cin)))))));
        assign #1 sum[0]=a[0]^b[0]^cin;
        assign #1 sum[1]=a[1]^b[1]^co[0];
        assign #1 sum[2]=a[2]^b[2]^co[1];
        assign #1 sum[3]=a[3]^b[3]^co[2];
endmodule

module  mult4(a,b,axb);
        input   [3:0]   a,b;
        output  [7:0]   axb;
        wire    [3:0]   pp0,pp1,pp2,pp3;

        assign  #1      pp0=b[0]?a:0;
        assign  #1      pp1=b[1]?a:0;
        assign  #1      pp2=b[2]?a:0;
        assign  #1      pp3=b[3]?a:0;

        wire    [3:0]   s1,s2;
        wire    c1,c2;

        cla4    u1      ({1'b0,pp0[3:1]},pp1,1'b0,c1,s1);
        cla4    u2      ({c1,s1[3:1]},pp2,1'b0,c2,s2);
        cla4    u3      ({c2,s2[3:1]},pp3,1'b0,axb[7],axb[6:3]);

        assign  axb[2]=s2[0];
        assign  axb[1]=s1[0];
        assign  axb[0]=pp0[0];
endmodule

module  mult8(a,b,axb);
        input   [7:0]   a,b;
        output  [15:0]  axb;
        wire    [7:0]   sum0,sum1,sum2,sum3;
        wire    cout0,cout1,cout2,cout3;
        wire    [3:0]   result0,result1,result2,result3,result4;

        mult4   V1      (a[3:0],b[3:0],sum0);
        mult4   V2      (a[7:4],b[3:0],sum1);
        mult4   V3      (a[3:0],b[7:4],sum2);
        mult4   V4      (a[7:4],b[7:4],sum3);

        cla4    V5      (sum0[7:4],sum1[3:0],1'b0,cout0,result0);
        cla4    V6      (result0,sum2[3:0],1'b0,cout1,axb[7:4]);
        cla4    V7      (sum1[7:4],sum2[7:4],cout0,cout2,result2);
        cla4    V8      (result2,sum3[3:0],cout1,cout3,axb[11:8]);

        assign  result3=sum3[7:4];
        assign  #1      result4=cout2?(result3+4'h1):result3;
        assign  #1      axb[15:12]=cout3?(result4+4'h1):result4;

        assign  axb[3:0]=sum0[3:0];
endmodule
------------------------------------GTKWAVE---------------------------------------


4.      請設計一8位元回復式除法器,div8(a[7:0], b[7:0], q[7:0], r[7:0]),其中a為被除數,b為除數,q為商數,r為餘數。
------------------------------------PRcalc8.v---------------------------------------
module  PR_calc(a,b,q,PR);
        input   [15:0]  a;
        input   [7:0]   b;
        output  q;
        output  [15:0]  PR;

        assign  #1 q=((a<<1) >= (b<<8))?1:0;
        assign  #1 PR=q?(a<<1)-(b<<8):(a<<1);
endmodule
module  restoring_div4(a,b,q,r);
        input   [7:0]   a,b;
        output  [7:0]   q,r;
        wire    [15:0]  PR1,PR2,PR3,PR4,PR5,PR6,PR7,PR8;
        PR_calc U1(a,b,q[7],PR1);
        PR_calc U2(PR1,b,q[6],PR2);
        PR_calc U3(PR2,b,q[5],PR3);
        PR_calc U4(PR3,b,q[4],PR4);
        PR_calc U5(PR4,b,q[3],PR5);
        PR_calc U6(PR5,b,q[2],PR6);
        PR_calc U7(PR6,b,q[1],PR7);
        PR_calc U8(PR7,b,q[0],PR8);

        assign  r=PR8[15:8];
endmodule
------------------------------------GTKWAVE---------------------------------------


沒有留言:

張貼留言

文章有誤或有問題麻煩您留言告知! 謝謝您~~