找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 1946|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

FPGA設(shè)計(jì)代碼整潔之道2

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:588548 發(fā)表于 2019-7-26 09:00 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
《極限編程實(shí)施》作者Ron  Jeffries 仔細(xì)研究了貝克的簡單代碼規(guī)則,并依其重要順序分別列為:
  能通過所有測試
  沒有重復(fù)代碼
  體現(xiàn)系統(tǒng)中的全部涉及理念
  包括盡量少的實(shí)體,比如類、方法、函數(shù)等
能通過所有測試這一點(diǎn),后文中在架構(gòu)設(shè)計(jì)方面詳細(xì)說明,這里我們還是借助一個(gè)小的例子說明“沒有重復(fù)代碼”的一些技巧。
曾經(jīng)有一次我將多份不同的程序代碼用A4紙打印出來,平攤到我的床上對(duì)照時(shí),還在上小學(xué)的女兒在旁邊說道:爸比,你每天就是看這幾只毛毛蟲爬來爬去嗎?always、if、else,begin,對(duì)了,還有end,大概就是這幾只。小孩子幼稚的話語引得我哈哈大笑,當(dāng)我回頭看向這些代碼時(shí),突然記起一位大師說過的話:大部分程序都是由極為相似的元素構(gòu)成。誠哉斯言!同時(shí),由于這種相似性,許多程序中出現(xiàn)了重復(fù)的代碼。我們來看一下下面這組代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
assign data0 = {1'b1,din0,1'b0};
assign data1 = {1'b1,din1,1'b0};
assign data2 = {1'b1,din2,1'b0};
always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        dout <= 0 ;
    end
    else if(sel0)begin
        dout <= data0[9-cnt2];
    end
    else if(sel1)begin
        dout <= data1[9-cnt2];
    end
    else begin
        dout <= data2[9-cnt2];
    end
end
這是一個(gè)串口發(fā)送程序的代碼,所實(shí)現(xiàn)的功能是發(fā)送0、1、2三個(gè)數(shù)據(jù)。很明顯,在第2到第4行中,相當(dāng)于程序中同樣的事情做了三遍。第10到第19行也是選了三次,這就屬于重復(fù)的代碼。隨著信號(hào)越來越多,就需要不斷的四個(gè)、五個(gè)……N個(gè)。程序越來越累贅。
同一段代碼的反復(fù)出現(xiàn),“唯一性”的邊界變得模糊,也容易出現(xiàn)混亂。或者說,作者的想法沒有得到最佳的實(shí)現(xiàn)。在本例中假設(shè)通過搜索引擎輸入“?”就會(huì)得到相似的?個(gè)結(jié)果。還記得前文中提到的“做簡單的事”嗎,這時(shí)我們應(yīng)該思考是代碼自身贅余還是對(duì)象功能是否太多。如果是前者,應(yīng)該從有效命名等去改善它;如果是后者,那就“把復(fù)雜的事情簡單化”,采取某種手段重構(gòu)它,使功能可以清晰的被說明以及被實(shí)現(xiàn)。
如上面的代碼,正確的思路和做法應(yīng)該是什么呢?我們來看下面這份代碼。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
always  @(*)begin
    if(sel0)
        din_sel = din0 ;
    else if(sel1)
        din_sel = din1 ;
    else
        din_sel = din2 ;
end
assign data = {1'b1,din_sel,1'b0};
always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        dout <= 0 ;
    end
    else begin
        dout <= data[9-cnt2];
    end
end
首先先把din0,1,2選出來,如果se10的情況下,那么din-se1等于din0;否則,在se11的情況下,那么din-se1等于din1;否則,din-se1等于din2;
接下來我們?cè)賮硌a(bǔ)充0和1;
接著選擇時(shí)序。dout的變化為XXXXXX,到此代碼完成。
通過比較不難看出,第二份代碼中,無論是補(bǔ)0補(bǔ)1,還是dout送出,都只做一次,一行代碼只做一件事且做好這件事,讓編程語言看起來像是專為解決這個(gè)問題而存在的。
還有一點(diǎn),在本節(jié)的兩個(gè)例子中,驗(yàn)證時(shí)前一份代碼要依次驗(yàn)證,送出的信號(hào)din0,din,din2……din N,這個(gè)過程中任何一點(diǎn)出現(xiàn)錯(cuò)誤都非常麻煩;而第二份代碼僅需要驗(yàn)證它們之間的邏輯關(guān)系正確即可。
需要注意的是,本節(jié)是以一個(gè)非常小的信號(hào)輸出代碼為例。越是大型的、復(fù)雜的代碼,這兩種方法之間的效率和質(zhì)量差距越大。下一節(jié)《信號(hào)命名和定義應(yīng)該明確》

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表