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