转如何设计乘加电路.docx

上传人:b****8 文档编号:9710141 上传时间:2023-02-06 格式:DOCX 页数:13 大小:203.24KB
下载 相关 举报
转如何设计乘加电路.docx_第1页
第1页 / 共13页
转如何设计乘加电路.docx_第2页
第2页 / 共13页
转如何设计乘加电路.docx_第3页
第3页 / 共13页
转如何设计乘加电路.docx_第4页
第4页 / 共13页
转如何设计乘加电路.docx_第5页
第5页 / 共13页
点击查看更多>>
下载资源
资源描述

转如何设计乘加电路.docx

《转如何设计乘加电路.docx》由会员分享,可在线阅读,更多相关《转如何设计乘加电路.docx(13页珍藏版)》请在冰豆网上搜索。

转如何设计乘加电路.docx

转如何设计乘加电路

原文出处(真OO无双):

Abstract

z=a*b+c*d;一個很簡單的運算,該如何使用數位電路實現呢?

Introduction

使用環境:

QuartusII8.0

在(原創)如何設計2數相加的電路?

(SOC)(Verilog)中,我們討論過如何實現y=a+b;但在實務上,其實最常用的是y=a*b+c*d,由於Verilog與數位電路本身的限制,不適合真的去實現很複雜的數學,就算真的實現出來,電路也跑不快,又佔resource,所以我們常會重新修改演算法配合數位電路的特性,通常演算法修改到最後,都會只剩下簡單的乘法與加法運算,也就是y=a*b+c*d的型式。

Method1:

一般寫法

ALT_MULTADD.v/Verilog

1 /* 

2 (C)OOMusou2008

4 Filename   :

ALT_MULTADD.v

5 Compiler   :

QuartusII8.0

6 Description:

Demohowtowritey=a*b+c*d

7 Release    :

10/11/20081.0

8 */

10 moduleALT_MULTADD(

11  input        iCLK,

12  input        iRST_N,

13  input [7:

0] iA0,

14  input [7:

0] iB0,

15  input [7:

0] iA1,

16  input [7:

0] iB1,

17  output[16:

0]oRESULT

18 );

19 

20 reg[7:

0]a0;

21 reg[7:

0]a1;

22 reg[7:

0]b0;

23 reg[7:

0]b1;

24 reg[16:

0]result;

25 

26 assignoRESULT=result;

27 

28 always@(posedgeiCLK,negedgeiRST_N)begin

29  if(!

iRST_N)begin

30    a0    <= 0;

31    a1    <= 0;

32    b0    <= 0;

33    b1    <= 0;

34    result<= 0;

35  end

36  else begin

37    a0    <=iA0;

38    a1    <=iA1;

39    b0    <=iB0;

40    b1    <=iB1;

41    

42    result<=a0*b0+a1*b1;

43  end   

44 end

45 

46 endmodule

模擬結果

輸出結果會delay2個clock,為什麼會這樣呢?

這可由合成結果來解釋。

合成結果

輸出輸入都使用reg寄存,所以一共delay2個clock,中間是組合電路負責乘加運算。

Fmax為195.43MHz

 

Method2:

使用Pipeline

ALT_MULTADD_pipe.v/Verilog

1 /* 

2 (C)OOMusou2008

4 Filename   :

ALT_MULTADD_pipe.v

5 Compiler   :

QuartusII8.0

6 Description:

Demohowtowritey=a*b+c*dwithpipeline

7 Release    :

10/11/20081.0

8 */

10 moduleALT_MULTADD_pipe(

11  input        iCLK,

12  input        iRST_N,

13  input [7:

0] iA0,

14  input [7:

0] iB0,

15  input [7:

0] iA1,

16  input [7:

0] iB1,

17  output[16:

0]oRESULT

18 );

19 

20 reg[7:

0]a0;

21 reg[7:

0]a1;

22 reg[7:

0]b0;

23 reg[7:

0]b1;

24 

25 reg[16:

0]m0;

26 reg[16:

0]m1;

27 

28 reg[16:

0]result;

29 

30 assignoRESULT=result;

31 

32 always@(posedgeiCLK,negedgeiRST_N)begin

33  if(!

iRST_N)begin

34    a0<= 0;

35    a1<= 0;

36    b0<= 0;

37    b1<= 0;

38    m0<= 0;

39    m1<= 0;

40  end

41  else begin

42    a0<=iA0;

43    a1<=iA1;

44    b0<=iB0;

45    b1<=iB1;

46    

47    m0<=a0*b0;

48    m1<=a1*b1;

49    

50    result<=m0+m1;

51  end   

52 end

53 

54 endmodule

模擬結果

 

輸出結果會delay3個clock,為什麼會這樣呢?

這可由合成結果來解釋。

合成結果

由於使用了3級reg,所以delay了3個clock。

其實在code中,也已經描述了這個現象,42行

a0<=iA0;

a1<=iA1;

b0<=iB0;

b1<=iB1;

第1個clock,將input做寄存。

47行

m0<=a0*b0;

m1<=a1*b1;

第2個clock,計算a0*b0與a1*b1,由於這兩個毫不相干,所以可以同時計算。

50行 

result<=m0+m1;

第3個clock,將output做寄存。

所以在寫code時,其實腦筋想的正是RTLViewer合成出來的結果,這也是為什麼寫Verilog時,不能像寫C一樣,只要語法對就好,剩下就是Compiler幫你優化,由於目前Ccompiler優化能力都很強,所以就算你亂寫,優化出來的結果也差不多,但寫Verilog卻要時時想著你想描述的硬體,

Fmax為260MHz

加上pipeline後,Fmax大增,為什麼加上pipeline後,Fmax增加這麼多呢?

尤其若你原本是寫C的背景,看到Verilog多了幾個reg後,差異就這麼大,一定很難理解。

解釋pipeline的書很多,在有名的算盤書(ComputerOrganization&DesignTheHardware/SoftwareInterface)Ch.6講得很清楚,在這我用另外一種方法來解釋。

在同步設計中,電路的設計都是循序電路、組合電路交錯的組合,由上面兩個合成結果也能發現這種設計,為了要同步,所以必須很穩定的前一個clock在第1級reg,而下一個clock在第2級reg,因為Fmax是period的倒數,兩級reg中間的組合電路所需時間越長,period一定越大,倒數後的Fmax就越小。

在Method1中

result<=a0*b0+a1*b1;

要乘要加,這樣的組合電路一定要花較長的時間,所以period也越大,Fmax當然也變小。

在Method2中

m0<=a0*b0;

m1<=a1*b1;

   

result<=m0+m1;

將相乘跟相加分開來做,先將乘法運算的結果做寄存,然後再作加法運算,這樣每個組合電路的時間變少,所以period也變小,Fmax當然也變大了。

但pipeline也是有tradeoff!

!

多花了一級reg,所以delay時間會變長,也就是一開始會慢一個clock出來,但之後每個clock都有產出,換來的就是Fmax變大。

所以有人說,硬體加速基本上就是將演算法切得很細來加速,就是因為pipeline的關係。

看到這裡,你或許會說:

『y=a*b+c*d在C只要一行的東西,在Verilog我要寫這麼多行?

那真的去寫一個演算法還得了?

幸好Altera提供了Megafunction,讓我們可以很輕鬆的計算y=a*b+c*d。

Method3:

使用Megafunction:

ALT_MULTADD

ALT_MULTADD_mf.v/Verilog

1 /* 

2 (C)OOMusou2008

4 Filename   :

ALT_MULTADD_mf.v

5 Compiler   :

QuartusII8.0

6 Description:

Demohowtowritey=a*b+c*dbyMegafunction

7 Release    :

10/11/20081.0

8 */

10 moduleALT_MULTADD_mf(

11  input        iCLK,

12  input        iRST_N,

13  input [7:

0] iA0,

14  input [7:

0] iB0,

15  input [7:

0] iA1,

16  input [7:

0] iB1,

17  output[16:

0]oRESULT

18 );

19 

20 MACmac0(

21  .aclr0(!

iRST_N),

22  .clock0(iCLK),

23  .dataa_0(iA0),

24  .datab_0(iB0),

25  .dataa_1(iA1),

26  .datab_1(iB1),

27  .result(oRESULT)

28 );

29 

30 endmodule

這樣的code夠精簡了吧!

!

模擬結果

 

與Method2的結果一樣delay3個clock,可見Megafunction:

ALT_MULTADD預設已經加上了pipeline。

合成結果

 

很單純的只有一個MACblock。

Fmax一樣為260MHz

所以不用擔心Megafunction:

ALT_MULTADD沒自己寫code效率好。

如何使用Megafunction:

ALT_MULTADD?

Tool->MegaWizardPlug-InManager

之後就是wizard介面,跟著一步一步設定即可。

Megafunction:

ALT_MULTADD預設已經將input與output用reg做寄存,所以我們只需單純的用wire連進去即可。

完整程式下載

ALT_MULTADD.7z(一般寫法)

ALT_MULTADD_pipe.7z(使用pipeline)

ALT_MULTADD_mf.7z(使用Megafunction:

ALT_MULTADD)

Conclusion

本文所要傳達的重點有4:

1.寫Verilog不能像寫C一樣,只要語法對就好,剩下的優化就交給Ccompiler;寫Verilog時要時時想著你要描述的硬體,因為合成器會依照你的code去做合成,寫法的差異影響結果甚鉅。

2.解釋pipeline概念,這是ccoder學Verilog很難理解的地方。

3.Altera提供了不少好用Megafunction,不僅方便,而且執行效率甚至比我們自己寫的還好些,應該盡量使用Megafunction增加開發效率以及執行效率。

4.Megafunction:

ALT_MULTADD在實務上經常使用,在(原創)如何實現RealTime的SobelEdgeDetector?

(SOC)(Verilog)(ImageProcessing)(DE2-70)(TRDB-D5M)(TRDB-LTM),我就曾經使用ALT_MULTADD這個Megafunction實現SobelEdgeDetector演算法。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 考试认证 > 其它考试

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1