學(xué)習(xí)FPGA,筆者推崇的學(xué)習(xí)方法是先整體再局部。先對FPGA 有一個整體的認(rèn)識,包括知道有哪些知識點,這些知識點所處的位置和作用。然后在此基礎(chǔ)上再逐個突破。
FPGA知識大串講是一個系列文章,先概括性地將FPGA的知識點串聯(lián)起來,使讀者對FPGA有一個整體的認(rèn)識,為后續(xù)的各項學(xué)習(xí)打下堅實基礎(chǔ)。
本系列文章由6篇文章組成。第一篇文章闡述大部分同學(xué)的學(xué)習(xí)誤區(qū)。第二篇文章,介紹了FPGA所有的知識點,并將其串聯(lián)起來。剩下的4篇文章,是對所有知識的分別概述,其內(nèi)容包括:組合邏輯、D觸發(fā)器、時序邏輯和FPGA 時序。
首先我們看一下學(xué)習(xí)誤區(qū)。
第1節(jié) 誤區(qū)1:學(xué)習(xí)語法過多
大部分初學(xué)者最大的學(xué)習(xí)誤區(qū)就是花費(fèi)大量的時間用于VERILOG語法的語法,并作為學(xué)習(xí)的重點。
入門就看VERILOG,相信這是很多讀者入門FPGA的普遍做法,甚至,甚至部分同學(xué)花了幾個月時間用來學(xué)習(xí)語法。
但其實VERILOG 里面的語法百分之九十的是用來測試用的,設(shè)計僅僅用到其中10%的語法,而且設(shè)計語法非常之簡單,大部分代碼是由一個一個always、assign和例化等組成的
上圖是實現(xiàn)FPGA例化功能的代碼,將模塊test_edge放到本模塊中來,其作用類似于C語言的函數(shù)調(diào)用,其語法亦相似,將接口信號一個一個關(guān)聯(lián)起來即可。還未掌握例化語法的讀者,可以自行查找相關(guān)知識。
FPGA的設(shè)計,通過使用ALWAYS的格式來實現(xiàn)。ALWAYS格式有兩種,時序邏輯的ALWAYS和組合邏輯的ALWAYS,其結(jié)構(gòu)如下。
當(dāng)要實現(xiàn)不同功能時,在ALWAYS格式里,添加if else,以及加減乘除、邏輯運(yùn)算等即可,如下面的代碼
?
?
?
上面實現(xiàn)串口接收功能、一個典型的FPGA代碼。第1至38行是接口、信號的定義,其他則是主體的設(shè)計部分。由上面代碼可以看出FPGA的代碼有以下幾個特點。
? FPGA代碼由多個結(jié)構(gòu)簡單、相似的ALWAYS和ASSIGN組成的。本例中一共用到了8個ALWAYS語句和7個ASSIGN語句,除此之外沒有其他結(jié)構(gòu)。復(fù)雜點的FPGA代碼,亦僅是多了一個例化功能。
? 每個ALWAYS塊只用到簡單的語法,均是由if else,以及加減乘除、邏輯判斷等基本操作。沒有復(fù)雜的東西,相信具有C語言基礎(chǔ)的讀者,一般能讀懂,或者能猜到大概功能。
? 除了第一個簡單的ALWAYS之外,其他每個ALWAYS只設(shè)計一個信號。例如,第53至62行只設(shè)計cnt0,第92至98行只設(shè)計dout信號。這是至簡設(shè)計法的一大特色,這樣的設(shè)計才符合硬件設(shè)計的特點。這不是沒有根據(jù)的,規(guī)范的企業(yè)如華為海思、中興等,均是如此風(fēng)格的代碼。
由此可見,VERILOG語法是非常簡單的。雖然語法簡單,但如何通過簡單的if else以及加減乘除,就實現(xiàn)強(qiáng)大的FPGA功能,這又很不簡單,所以不同于學(xué)習(xí)C、C++等軟件語言,學(xué)習(xí)FPGA沒有必要花太多的精力于語法上,關(guān)鍵在于應(yīng)用。
第2節(jié) 誤區(qū)2:追求代碼精簡
鉆研VERILOG語法,追求使用最少的代碼實現(xiàn)功能,這又是一個大誤區(qū)。
放在C、C++、JAVA等語言上,追求精簡的代碼實現(xiàn),是一個正常的需求。但放在FPGA,則完全不是這回事。
衡量FPGA設(shè)計優(yōu)秀的標(biāo)準(zhǔn),不是看代碼量的多少,而是比較綜合出來的電路,它使用了多少資源,能夠支持的時鐘頻率高低等。
例如一個加法器,在200M的時鐘頻率下,可以直接使用“+”來實現(xiàn)。但假如要跑到300M或者更高頻率,業(yè)界會把該加法器拆分成多個邏輯門,并且在邏輯門之間增加寄存器(即流水線設(shè)計)。這樣設(shè)計,代碼會由原來的1行,變成上百行,并且難以讀懂。雖然代碼量增加了,但電路卻更優(yōu)秀了。
總而言之,不要追求VERILOG代碼的精簡,而是追求電路的優(yōu)秀設(shè)計,多學(xué)習(xí)流水線、資源換速度、速度換資源等設(shè)計方式,這才是好的FPGA學(xué)習(xí)方向。
第3節(jié) 誤區(qū)3:膚淺的實驗
通過開發(fā)板學(xué)習(xí)FPGA是一個較好的入門方法,例如MDY的ALTERA學(xué)習(xí)板MP801、XILINX學(xué)習(xí)板MP802,既有LED燈、數(shù)碼管、VGA等簡單接口,還有SDRAM、DDR、千兆網(wǎng)等高級接口,其擁有大量免費(fèi)的學(xué)習(xí)資源,包括工程、視頻、文檔等,是學(xué)習(xí)FPGA非常好的方法。
但部分讀者拿到學(xué)習(xí)工程后,每個工程都是新建工程、編譯工程、上板、看現(xiàn)象,僅此而已。實驗做了很多,設(shè)計能力卻提高得很慢。因為這里缺少關(guān)鍵的一步:自己去寫代碼。
讀懂功能要求后,要親自去寫一寫代碼,邊寫邊仿真,邊仿真邊修改。寫不出來的時候,對著仿真波形多思考思考。通過這種方法,訓(xùn)練代碼設(shè)計能力、仿真調(diào)試能力,掌握MODELSIM等工具的使用。
代碼完成設(shè)計后,上板驗證,這個時候現(xiàn)象大概率是不正確的,使用在線調(diào)試工具去定位問題找到問題。通過這種方法,訓(xùn)練定位問題能力、解決問題能力,掌握在線調(diào)試工具的使用。
最后,將自己設(shè)計的代碼,與開發(fā)板的官方代碼對比,吸收好的方面,改進(jìn)自己的設(shè)計能力。
按照上面步驟,當(dāng)您親自完成一個功能設(shè)計,獲得極大成就感和滿足感的同時,設(shè)計能力也切實得到了提高,這樣幾個設(shè)計循環(huán)上來,基本上就掌握FPGA設(shè)計了。
第4節(jié) 誤區(qū)5:軟件思維
VERILOG是硬件描述語言,它是對硬件的描述,而非軟件的設(shè)計。FPGA開發(fā)本質(zhì)上是硬件的開發(fā),與設(shè)計電路原理圖是相似的,因此要用硬件思維。而C、C++、JAVA等語言是軟件開發(fā),使用的是軟件思維。
有C語言基礎(chǔ)的同學(xué),很容易按照軟件思維來進(jìn)行FPGA設(shè)計,這是不正確的一種思想。那么,硬件思維和軟件思維本質(zhì)上有什么不同呢?
我們先看下軟件是如何設(shè)計的。
上面4行是軟件代碼,先讓a為1;然后讓b=a+1,即讓b為2;再讓a為2;最后c=a+2,即讓c為4。這有什么特色?
? 軟件代碼是一行一行順序執(zhí)行的;
? 軟件是一種過程設(shè)計,是讓信號怎么做、怎么變的設(shè)計。
? 軟件考慮的是此時此刻,該信號要怎么做。
而硬件設(shè)計思維,我們可以通過MP801開發(fā)板的電路設(shè)計為例進(jìn)行闡述。
假設(shè)我們要設(shè)計一款MP801開發(fā)板,這個開發(fā)板使用了多個元器件,例如有FPGA主芯片、AD、DA、數(shù)碼管、按鍵等。每個元器件都有它自己獨(dú)特的功能。
首先,每個元器件不一定有輸入,但一定會有輸出。例如,晶振輸出50M時鐘;當(dāng)按下按鍵時,電平輸出為0,未按下時輸出為1;數(shù)碼管的輸出,則是顏色的發(fā)光狀態(tài)等。
其次,每個元器件通常都有一個數(shù)據(jù)手冊,該手冊描述的是該元器件的輸出功能,即在什么樣情況下,會有怎么樣的輸出。以晶振為例,文檔一般會說明電源電壓為多少,然后輸出50M的時鐘信號。再以AD9280為例,文檔會說明輸入二進(jìn)制值為多少時,輸出什么樣的電平,例如值為8’h00時,輸出電壓為0V;值為8’hff時,輸出電壓為5V等。
再次,您可以發(fā)現(xiàn),每個數(shù)據(jù)手冊一定會說明清楚,在所有的情況下,輸出會有什么樣的變化。
最后,當(dāng)選中了元器件后,硬件工程師的工作,就是把它們正確地連起來。
當(dāng)電路板開發(fā)并生產(chǎn)完成后,一通電,全部元器件都同時在工作。不存在說某個元器件工作,另一個元器件不工作的情況(這里不工作是指不通電的情況,而不是不變化。事實上,不變化也是該元器件的一個輸出功能)。當(dāng)然,更不存在,此時元器件A工作,元器件B消失的情況,事實上,這些元器件是一直保持存在的。
上面就是硬件的設(shè)計過程,我們可以總結(jié)出硬件思維的特色。
? 硬件首先是描述一個“元器件”,它是什么,它有什么功能,即在什么情況下,有什么樣的輸出。軟件是讓它怎么做,過多久為1,過多久又為2等。這就是VERILOG這個硬件描述語言的特性,一個ALWAYS語句,就相當(dāng)于一個“元器件”,每個ALWAYS都是描述“元器件”(設(shè)計信號)的變化情況。
? 描述一個“元器件”是什么時,就要概括所有的情況,就如數(shù)據(jù)手冊般的清晰。對應(yīng)的是FPGA的ALWAYS語句,其設(shè)計的信號,一定是所有條件if else下的變化。特別注意的是,不同于軟件只考慮此時此刻值為多少,硬件和FPGA考慮的是“整個電路生命周期”下的各種情況處理方式。
? 當(dāng)您選完了“元器件”后,就是把元器件連接起來。對應(yīng)FPGA,則是通過相同“信號名”來接各個部分連接起來。
? 最后,一通電,全部“元器件”都同時工作了。對應(yīng)FPGA,就是VERILOG代碼會綜合成電路網(wǎng)表,最終會下載到FPGA,像電路般全部同時運(yùn)行。ALWAYS設(shè)計的各種信號是一直物理存在的。
認(rèn)真體會軟件思維和硬件思維的異同,有助于我們更好更規(guī)范地進(jìn)行FPGA開發(fā)。同時,正確地理解硬件思維,對于一些錯誤觀念和設(shè)計法,就有自己的判斷了。
例1:有部分讀者閱讀VERILOG代碼時,會想當(dāng)然地認(rèn)為begin 里面代碼都是串行執(zhí)行的,例如下面的代碼,會認(rèn)為按順序從第2至11行順序地串行執(zhí)行。
?
從嚴(yán)格的意義上,筆者認(rèn)為“順序串行執(zhí)行”這個概念是不正確的,F(xiàn)PGA本身就沒有“執(zhí)行”的概念。由前面講述可知,ALWAYS僅是像數(shù)據(jù)手冊那樣,描述“元器件”cnt的功能,即描述cnt在所有情況下的變化情況。所以,正確的理解,應(yīng)當(dāng)是像讀“數(shù)據(jù)手冊”那般,“閱讀”cnt的功能。
例2:大家可以看出下面代碼,是按軟件思維,還是按硬件思維設(shè)計的呢?
不用理解上面代碼實現(xiàn)了什么功能,從風(fēng)格上就可以看出其是用軟件思維來設(shè)計的??梢圆孪肫鋵懘a的過程,如先寫第13行代碼,讓byte_satee加1;然后寫第14至18行代碼,讓Pre_CMOS_iData變化,這怎么看起來,都像是軟件的一種過程思維。其次,將多個信號放在一個ALWAYS中描述,就像將多個不同元器件都寫在一個數(shù)據(jù)手冊上,必定是雜亂無章,講不清楚的。
比較規(guī)范的設(shè)計方法,推薦一個ALWAYS設(shè)計一個信號,如下面代碼,就是實現(xiàn)了相似的功能。一個信號一個信號地描述設(shè)計,長期堅持,必定能寫出越來越優(yōu)秀的代碼。
審核編輯:湯梓紅
評論
查看更多