Ⅰ FPGA現在學起來怎麼樣難不需要了解哪些基礎課程
FPGA學習重點
1. 看代碼,建模型
只有在腦海中建立了一個個邏運祥模輯模型,理解FPGA內部邏輯結構實現的基礎,才能明白為什麼寫Verilog和寫C整體思路是不一樣的,才能理解順序執行語言和並行執行語言的設計方法上的差異。在看到一段簡單程序的時候應該想到是什麼樣的功能電路。2. 用數學思維來簡化設計邏輯
學習FPGA不僅邏輯思維很重要,好的數學思維也能讓你的設計化繁為簡,所以啊,那些看見高數就頭疼的童鞋需要重視一下這門課哦。舉個簡單的例子,比如有兩個32bit的數據X[31:0]與Y[31:0]相乘。當然,無論Altera還是Xilinx都有現成的乘法器IP核可以調用,這也是最簡單的方法,但是兩個32bit的乘法器將耗費大量的資源。那麼有沒有節省資源,又不太復雜的方式來實現呢?我們可以稍做修改:將X[31:0]拆成兩部分X1[15:0]和X2[15:0],令X1[15:0]=X[31:16],X2[15:0]=X[15:0],則X1左移16位後與X2相加可以得到X;同樣將Y[31:0]拆成兩部分宴者Y1[15:0]和Y2[15:0],令 Y1[15:0]=Y[31:16],Y2[15:0]=Y[15:0],則Y1左移16位後與Y2相加可以得到Y,則X與Y的相乘可以轉化為X1和X2 分別與Y1和Y2相乘,這樣一個32bit*32bit的乘法運算轉換成了四個16bit*16bit的乘法運算和三個32bit的加法運算。轉換後的佔用資源將會減少很多,有興趣的童鞋,不妨綜合一下看看,看看兩者差多少。3. 時鍾與觸發器的關系
「時鍾是時序電路的控制者」這句話太經典了,可以說是FPGA設計的聖言。FPGA的設計主要是以時序電路為主,因為組合邏輯電路再怎麼復雜也變不出太多花樣,理解起來也不沒太多困難。但是時序電路就不同了,它的所有動作都是在時鍾一拍一拍的節奏下轉變觸發,可以說時鍾就是整個電路的控制者,控制不好,電路功能就會混亂。打個比方,時鍾就相當於人體的心臟,它每一次的跳動就是觸發一個 CLK,向身體的各個器官供血,維持著機體的正常運作,每一個器官體統正常工作少不了組織細胞的構成,那麼觸發器就可以比作基本單元組織細胞。
時序邏輯電路的時鍾是控制時序邏輯電路旁緩狀態轉換的「發動機」,沒有它時序邏輯電路就不能正常工作。因為時序邏輯電路主要是利用觸發器存儲電路的狀態,而觸發器狀態變換需要時鍾的上升或下降沿,由此可見時鍾在時序電路中的核心作用。最後簡單說一下體會吧,歸結起來就是多實踐、多思考、多問。實踐出真知,看100遍別人的方案不如自己去實踐一下。實踐的動力一方面來自興趣,一方面來自壓力。有需求會容易形成壓力,也就是說最好能在實際的項目開發中鍛煉,而不是為了學習而學習。為什麼你會覺得FPGA難學?
1. 不熟悉FPGA的內部結構
FPGA為什麼是可以編程的?恐怕很多初學者不知道,他們也不想知道。因為他們覺得這是無關緊要的。他們潛意識的認為可編程嘛,肯定就是像寫軟體一樣啦。軟體編程的思想根深蒂固,看到Verilog或者VHDL就像看到C語言或者其它軟體編程語言一樣。一條條的讀,一條條的分析。
拒絕去了解為什麼FPGA是可以編程的,不去了解FPGA的內部結構,要想學會FPGA 恐怕是天方夜譚。那麼FPGA為什麼是可以「編程」的呢?首先來了解一下什麼叫「程」。其實 「程」只不過是一堆具有一定含義的01編碼而已。編程,其實就是編寫這些01編碼。只不過我們現在有了很多開發工具運算或者是其它操作。所以軟體是一條一條的,通常都不是直接編寫這些01編碼,而是以高級語言的形式來編寫,最後由開發工具轉換為這種01編碼而已。對於軟體編程而言,處理器會有一個專門的解碼電路逐條把這些01編碼翻譯為各種控制信號,然後控制其內部的電路完成一個個的讀,因為軟體的操作是一步一步完成的。
而FPGA的可編程,本質也是依靠這些01編碼實現其功能的改變,但不同的是FPGA之所以可以完成不同的功能,不是依靠像軟體那樣將01編碼翻譯出來再去控制一個運算電路,FPGA裡面沒有這些東西。FPGA內部主要三塊:可編程的邏輯單元、可編程的連線和可編程的IO模塊。
可編程的邏輯單元
其基本結構某種存儲器(SRAM、 FLASH等)製成的4輸入或6輸入1輸出的「真值表」加上一個D觸發器構成。任何一個4輸入1輸出組合邏輯電路,都有一張對應的「真值表」,同樣的如果用這么一個存儲器製成的4輸入1輸出的「真值表」,只需要修改其「真值表」內部值就可以等效出任意4輸入1輸出的組合邏輯,這些「真值表」內部值就是那些01編碼。
如果要實現時序邏輯電路怎麼辦?任何的時序邏輯都可以轉換為組合邏輯+D觸發器來完成。但這畢竟只實現了4輸入1輸出的邏輯電路而已,通常邏輯電路的規模那是相當的大。可編程連線
那怎麼辦呢?這個時候就需要用到可編程連線了。在這些連線上有很多用存儲器控制的鏈接點,通過改寫對應存儲器的值就可以確定哪些線是連上的而哪些線是斷開的。這就可以把很多可編程邏輯單元組合起來形成大型的邏輯電路。
可編程的IO
任何晶元都必然有輸入引腳和輸出引腳。有可編程的IO可以任意的定義某個非專用引腳(FPGA中有專門的非用戶可使用的測試、下載用引腳)為輸入還是輸出,還可以對IO的電平標准進行設置。
總歸一句話,FPGA之所以可編程是因為可以通過特殊的01代碼製作成一張張 「真值表」,並將這些「真值表」組合起來以實現大規模的邏輯功能。不了解FPGA內部結構,就不能明白最終代碼如何變到FPGA裡面去的,也就無法深入的了解如何能夠充分運用FPGA。現在的FPGA,不單單是有前面講的那三塊,還有很多專用的硬體功能單元,如何利用好這些單元實現復雜的邏輯電路設計,是從菜鳥邁向高手的路上必須要克服的障礙。而這一切,還是必須先從了解FPGA內部邏輯及其工作原理做起。
2. 錯誤理解HDL語言,怎麼看都看不出硬體結構
HDL語言的英語全稱是:Hardware Deion Language,注意這個單詞Deion,而不是Design。老外為什麼要用Deion這個詞而不是Design呢?因為HDL確實不是用用來設計硬體的,而僅僅是用來描述硬體的。
描述這個詞精確地反映了HDL語言的本質,HDL語言不過是已知硬體電路的文本表現形式而已,只是將以後的電路用文本的形式描述出來而已。而在編寫語言之前,硬體電路應該已經被設計出來了。語言只不過是將這種設計轉化為文字表達形式而已。
硬體設計也是有不同的抽象層次,每一個層次都需要設計。最高的抽象層次為演算法級、然後依次是體系結構級、寄存器傳輸級、門級、物理版圖級。
使用HDL的好處在於我們已經設計好了一個寄存器傳輸級的電路,那麼用HDL描述以後轉化為文本的形式,剩下的向更低層次的轉換就可以讓EDA工具去做了,這就大大的降低了工作量。這就是可綜合的概念,也就是說在對這一抽象層次上硬體單元進行描述可以被EDA工具理解並轉化為底層的門級電路或其他結構的電路。在FPGA設計中,就是在將這以抽象層級的意見描述成HDL語言,就可以通過FPGA開發軟體轉化為上一點中所述的FPGA內部邏輯功能實現形式。HDL也可以描述更高的抽象層級如演算法級或者是體系結構級,但目前受限於EDA軟體的發展,EDA軟體還無法理解這么高的抽象層次,所以HDL描述這樣抽象層級是無法被轉化為較低的抽象層級的,這也就是所謂的不可綜合。
所以在閱讀或編寫HDL語言,尤其是可綜合的HDL,不應該看到的是語言本身,而是要看到語言背後所對應的硬體電路結構。3. FPGA本身不算什麼,一切皆在FPGA之外
FPGA是給誰用的?很多學校是為給學微電子專業或者集成電路設計專業的學生用的,其實這不過是很多學校受資金限制,買不起專業的集成電路設計工具而用FPGA工具替代而已。其實FPGA是給設計電子系統的工程師使用的。這些工程師通常是使用已有的晶元搭配在一起完成一個電子設備,如基站、機頂盒、視頻監控設備等。當現有晶元無法滿足系統的需求時,就需要用FPGA來快速的定義一個能用的晶元。前面說了,FPGA裡面無法就是一些「真值表」、觸發器、各種連線以及一些硬體資源,電子系統工程師使用FPGA進行設計時無非就是考慮如何將這些以後資源組合起來實現一定的邏輯功能而已,而不必像IC設計工程師那樣一直要關注到最後晶元是不是能夠被製造出來。
本質上和利用現有晶元組合成不同的電子系統沒有區別,只是需要關注更底層的資源而已。要想把FPGA用起來還是簡單的,因為無非就是那些資源,在理解了前面兩點再搞個實驗板,跑跑實驗,做點簡單的東西是可以的。而真正要把FPGA用好,那光懂點FPGA知識就遠遠不夠了。因為最終要讓FPGA裡面的資源如何組合,實現何種功能才能滿足系統的需要,那就需要懂得更多更廣泛的知識。4. 數字邏輯知識是根本
無論是FPGA的哪個方向,都離不開數字邏輯知識的支撐。FPGA說白了是一種實現數字邏輯的方式而已。如果連最基本的數字邏輯的知識都有問題,學習FPGA的願望只是空中樓閣而已。數字邏輯是任何電子電氣類專業的專業基礎知識,也是必須要學好的一門課。
如果不能將數字邏輯知識爛熟於心,養成良好的設計習慣,學FPGA到最後仍然是霧里看花水中望月,始終是一場空的。以上四條只是我目前總結菜鳥們在學習FPGA時所最容易跑偏的地方,FPGA的學習其實就像學習圍棋一樣,學會如何在棋盤上落子很容易,成為一位高手卻是難上加難。要真成為李昌鎬那樣的神一般的選手,除了靠刻苦專研,恐怕還確實得要一點天賦。薦讀
1. 入門首先要掌握HDL(HDL=verilog+VHDL)
第一句話是:還沒學數電的先學數電。然後你可以選擇verilog或者VHDL,有C語言基礎的,建議選擇VHDL。因為verilog太像C了,很容易混淆,最後你會發現,你花了大量時間去區分這兩種語言,而不是在學習如何使用它。當然,你思維能轉得過來,也可以選verilog,畢竟在國內verilog用得比較多。接下來,首先找本實例抄代碼。抄代碼的意義在於熟悉語法規則和編譯器(這里的編譯器是硅編譯器又叫綜合器,常用的編譯器有:Quartus、ISE、Vivado、Design Compiler 、Synopsys的VCS、iverilog、Lattice的Diamond、Microsemi/Actel的Libero、Synplify pro),然後再模仿著寫,最後不看書也能寫出來。編譯完代碼,就打開RTL圖,看一下綜合出來是什麼樣的電路。HDL是硬體描述語言,突出硬體這一特點,所以要用數電的思維去思考HDL,而不是用C語言或者其它高級語言,如果不能理解這句話的,可以看《什麼是硬體以及什麼是軟體》。在這一階段,推薦的教材是《Verilog傳奇》、《Verilog HDL高級數字設計》或者是《用於邏輯綜合的VHDL》。不看書也能寫出個三段式狀態機就可以進入下一階段了。此外,你手上必須准備Verilog或者VHDL的官方文檔,《verilog_IEEE官方標准手冊-2005_IEEE_P1364》、《IEEE Standard VHDL Language_2008》,以便遇到一些語法問題的時候能查一下。2. 獨立完成中小規模的數字電路設計
現在,你可以設計一些數字電路了,像交通燈、電子琴、DDS等等,推薦的教材是夏老《Verilog 數字系統設計教程》(第三版)。在這一階段,你要做到的是:給你一個指標要求或者時序圖,你能用HDL設計電路去實現它。這里你需要一塊開發板,可以選Altera的cyclone IV系列,或者Xilinx的Spantan 6。
還沒掌握HDL之前千萬不要買開發板,因為你買回來也沒用。這里你沒必要每次編譯通過就下載代碼,咱們用modelsim模擬(此外還有QuestaSim、NC verilog、Diamond的Active-HDL、VCS、Debussy/Verdi等模擬工具),如果模擬都不能通過那就不用下載了,肯定不行的。在這里先掌握簡單的testbench就可以了。推薦的教材是《WRITING TESTBENCHES Functional Verification of HDL Models》。3. 掌握設計方法和設計原則
你可能發現你綜合出來的電路盡管沒錯,但有很多警告。這個時候,你得學會同步設計原則、優化電路,是速度優先還是面積優先,時鍾樹應該怎樣設計,怎樣同步兩個異頻時鍾等等。
推薦的教材是《FPGA權威指南》、《IP核芯志-數字邏輯設計思想》、《Altera FPGA/CPLD設計》第二版的基礎篇和高級篇兩本。學會加快編譯速度(增量式編譯、LogicLock),靜態時序分析(timequest),嵌入式邏輯分析儀(signaltap)就算是通關了。如果有不懂的地方可以暫時跳過,因為這部分還需要足量的實踐,才能有較深刻的理解。4. 學會提高開發效率
因為Quartus和ISE的編輯器功能太弱,影響了開發效率。所以建議使用Sublime text編輯器中代碼片段的功能,以減少重復性勞動。Modelsim也是常用的模擬工具,學會TCL/TK以編寫適合自己的DO文件,使得模擬變得自動化,推薦的教材是《TCL/TK入門經典》。
你可能會手動備份代碼,但是專業人士都是用版本控制器的,所以,為了提高工作效率,必須掌握GIT。文件比較器Beyond Compare也是個比較常用的工具。此外,你也可以使用System Verilog來替代testbench,這樣效率會更高一些。如果你是做IC驗證的,就必須掌握System Verilog和驗證方法學(UVM)。推薦的教材是《Writing Testbenches using SystemVerilog》、《The UVM Primer》、《System Verilog1800-2012語法手冊》。掌握了TCL/TK之後,可以學習虛擬Jtag(ISE也有類似的工具)製作屬於自己的調試工具,此外,有時間的話,最好再學個python。腳本,意味著一勞永逸。5. 增強理論基礎
這個時候,你已經會使用FPGA了,但是還有很多事情做不了(比如,FIR濾波器、PID演算法、OFDM等),因為理論沒學好。我大概地分幾個方向供大家參考,後面跟的是要掌握的理論課。信號處理 —— 信號與系統、數字信號處理、數字圖像處理、現代數字信號處理、盲信號處理、自適應濾波器原理、雷達信號處理
介面應用 —— 如:UART、SPI、IIC、USB、CAN、PCIE、Rapid IO、DDR、TCP/IP、SPI4.2(10G乙太網介面)、SATA、光纖、DisplayPort
無線通信 —— 信號與系統、數字信號處理、通信原理、移動通信基礎、隨機過程、資訊理論與編碼
CPU設計 —— 計算機組成原理、單片機、計算機體系結構、編譯原理
儀器儀表 —— 模擬電子技術、高頻電子線路、電子測量技術、智能儀器原理及應用
控制系統 —— 自動控制原理、現代控制理論、過程式控制制工程、模糊控制器理論與應用
壓縮、編碼、加密 —— 數論、抽象代數、現代編碼技術、資訊理論與編碼、數據壓縮導論、應用密碼學、音頻信息處理技術、數字視頻編碼技術原理現在你發現,原來FPGA會涉及到那麼多知識,你可以選一個感興趣的方向,但是工作中很有可能用到其中幾個方向的知識,所以理論還是學得越多越好。如果你要更上一層,數學和英語是不可避免的。6. 學會使用MATLAB模擬
設計FPGA演算法的時候,多多少少都會用到MATLAB,比如CRC的系數矩陣、數字濾波器系數、各種表格和文本處理等。此外,MATLAB還能用於調試HDL(用MATLAB的計算結果跟用HDL算出來的一步步對照,可以知道哪裡出問題)。推薦的教材是《MATLAB寶典》和杜勇的《數字濾波器的MATLAB與FPGA實現》。7. 圖像處理
Photoshop
花一、兩周的時間學習PS,對圖像處理有個大概的了解,知道各種圖片格式、直方圖、色相、通道、濾鏡、拼接等基本概念,並能使用它。這部分是0基礎,目的讓大家對圖像處理有個感性的認識,而不是一上來就各種各樣的公式推導。推薦《Photoshop CS6完全自學教程》。基於MATLAB或OpenCV的圖像處理
有C/C++基礎的可以學習OpenCV,否則的話,建議學MATLAB。這個階段下,只要學會簡單的調用函數即可,暫時不用深究實現的細節。推薦《數字圖像處理matlab版》、《學習OpenCV》。圖像處理的基礎理論
這部分的理論是需要高數、復變、線性代數、信號與系統、數字信號處理等基礎,基礎不好的話,建議先補補基礎再來。看不懂的理論也可以暫時先放下,或許學到後面就自然而然地開竅了。推薦《數字圖像處理》。基於FPGA的圖像處理
把前面學到的理論運用到FPGA上面,如果這時你有前面第七個階段的水平,你將輕松地獨立完成圖像演算法設計(圖像處理是離不開介面的,上面第五個階段有講)。推薦《基於FPGA的嵌入式圖像處理系統設計》、《基於FPGA的數字圖像處理原理及應用》。進一步鑽研數學。要在演算法上更上一層,必然需要更多的數學,所以這里建議學習實分析、泛涵分析、小波分析等。
Ⅱ 用FPGA編寫12864顯示的程序,跪求。。。可以顯示就行,內容可以是字母。。謝謝
/*LCD12864顯示程序
此程序控制LCD12864液晶屏,IC為KS0108或兼容型號
圖形文件獲取方法:
在字模提取V21軟體中 ,導入一幅128*64黑白圖像.
* 參數設置:
* 參數設置->其它選項,選擇縱向取模,勾上位元組倒序,保留逗號,
* 取模方式為C51。
將生成的數組通過keilc等C編譯軟體,在編譯軟體中新建一工程,寫入源程序如下:
unsigned char code tab[]=
{
//圖像數據
}
編譯此工程將得到hex文件.在QII中使用lpm_rom宏功能模塊中調用此hex文件.
*
*******************************************************************************/
mole newlcd(clock,rst_n,rs,rw,en,data,lcd_cs);
// I/O口聲明
input clock; //系統時鍾
input rst_n; //復位信號
output[1:0] lcd_cs; //
output rs; //1:數據模式;0:指令模式
output rw; //1:讀操作;0:寫操作
output en; //使能信號,寫操作時在下降沿將數據送出;讀操作時保持高電平
output[7:0] data; //LCD數據匯流排
// I/O寄存器
reg rs;
reg en;
reg[1:0] lcd_cs;
reg[7:0] data;
//內部寄存器
reg[3:0] state; //狀態機
reg[3:0] next_state;
reg[20:0] div_cnt; //分頻計數器
reg[9:0] cnt; //寫操作計數器
reg cnt_rst; //寫操作計數器復位信號
wire[7:0] showdata; //要顯示的數據
reg[1:0] cs_r;
reg [2:0] page_addr;
reg [5:0] row_addr;
//內部網線
wire clk_div; //分頻時鍾
wire clk_divs;
wire page_done; //寫一行數據完成標志位
wire frame_done; //寫一屏數據完成標志位
wire left_done;
//狀態機參數
parameter idle =4'b0000,
setbase_1 =4'b0001,
setbase_2 =4'b0011,
setmode_1 =4'b0010,
setmode_2 =4'b0110,
SETpage_addr_1 =4'b0111,
SETpage_addr_2 =4'b0101,
SETrow_addr_1 =4'b1101,
SETrow_addr_2 =4'b1111,
write_right_1 =4'b1110,
write_right_2 =4'b1010,
write_nextpage_1 =4'b1011,
write_nextpage_2 =4'b1001,
wr_data_1 =4'b0100,
wr_data_2 =4'b1100;
// set_1 =4'b1000;
//******************************代碼開始*********************************
assign rw = 1'b0; //對LCD始終為寫操作
//時鍾分頻
always@(posedge clock or negedge rst_n)
begin
if(!rst_n)
div_cnt <= 0;
else
div_cnt <= div_cnt+1'b1;
end
assign clk_div = (div_cnt[15:0] == 20'h7fff);
//狀態機轉向
always@(posedge clock or negedge rst_n)
begin
if(! rst_n)
state <= idle;
else if(clk_div)
state <= next_state;
end
//************************狀態機邏輯*********************************
always@(state or page_done or left_done or frame_done or cnt or showdata or page_addr or row_addr or cs_r)
begin
rs <= 1'b0;
en <= 1'b0;
lcd_cs <= cs_r;
cnt_rst <= 1'b0;
data <= 8'h0;
case(state)
idle:
begin
next_state <= setbase_1;
cnt_rst <= 1'b1;
end
//**************************初始化LCD********************************
setbase_1: //基本指令操作
begin
lcd_cs <= 2'b11;
next_state <= setbase_2;
data <= 8'hc0;
en <= 1'b1;
end
setbase_2:
begin
lcd_cs <= 2'b11;
next_state <= setmode_1;
data <= 8'hc0;
end
//******************************************************************
setmode_1:
begin
lcd_cs <= 2'b11;
next_state <= setmode_2;
data <= 8'h3f;
en <=1'b1;
end
setmode_2:
begin
next_state <= SETpage_addr_1;
data <= 8'h3f;
end
//******************************************************************
SETpage_addr_1: //設置頁地址
begin
next_state <= SETpage_addr_2;
data <= ;
en <= 1'b1;
end
SETpage_addr_2:
begin
next_state <= SETrow_addr_1;
data <= ;
end
SETrow_addr_1: //設置列地址
begin
next_state <= SETrow_addr_2;
data <= ;
en <= 1'b1;
end
SETrow_addr_2:
begin
next_state <= wr_data_1;
data <= ;
end
//******************************************************************
/*
write_right_1: //寫完左半屏64個,換為右半屏顯示
begin
next_state <=write_right_2;
row_addr <= 0;
end
write_right_2:
begin
next_state <= SETpage_addr_1;
end
//******************************************************************
write_nextpage_1: //寫完全一行128個
begin
next_state <=write_nextpage_2;
row_addr <= 0;
end
write_nextpage_2:
begin
next_state <= SETpage_addr_1;
end
*/
//******************************************************************
wr_data_1: //寫數據到圖形顯示區
begin
next_state <= wr_data_2;
rs <= 1'b1;
en <= 1'b1;
data <= showdata;
end
wr_data_2:
begin
rs <= 1'b1;
data <= showdata;
if(left_done) //寫完左半屏數據64個
begin
if(page_done) //寫完一頁數據128個
begin
if(frame_done) //寫完一屏數據(8頁)
next_state <= idle;
else
// next_state <= write_nextpage_1;
next_state <= SETpage_addr_1;
end
else
// next_state <= write_right_1;
next_state <= SETpage_addr_1;
end
else
next_state <= wr_data_1;
end
default: next_state <= idle;
endcase
end
//********************************************************************
always@(posedge clock)
begin
if(clk_div)
begin
if(cnt_rst)
begin
cnt <= 0;
end
else if(state == wr_data_2)
begin
cnt <= cnt+1'b1;
end
end
end
//****************************************************
always@(posedge clock or negedge rst_n)
if(!rst_n)
begin
cs_r <= 2'b01;
page_addr <= 0;
end
else
if(clk_div && (state == wr_data_2))
if(page_done)//
begin
cs_r <= 2'b01;
page_addr <= page_addr + 1'b1;//一頁寫完時寫下一頁
end
else
if(left_done)
begin
cs_r <= 2'b10;
end
//*********************************************************************
//********************************************************************
assign left_done = (cnt[5:0] == 6'd63); //寫完左半屏數據64個
assign page_done = (cnt[6:0] == 7'd127); //寫完一頁數據128個
assign frame_done = (cnt[9:4] == 7'h3f); //寫完一屏數據
//***********************************************************************
//*******************************************************************
//調用ROM(圖片數據)
rom rom(.address(cnt+'d8),.clock(clock),.q(showdata));
endmole
開發板常式 自己看吧
我可以幫助你,你先設置我最佳答案後,我網路Hii教你。
Ⅲ 如何快速掌握FPGA
任何一個硬體工程師對FPGA都不會陌生,就好比C語言對於軟體工程師來說是必修課程一樣,只要是電子相關專業的學生,都要學習可編程邏輯這門課程。 FPGA的英文全稱是Field Programmable Gate Array,即現場可編程門陣列,它是在PAL、GAL、EPLD等可編程器件的基礎上進一步發展的產物。
從表象看,Programmable這個單詞確實能夠很好的描述FPGA的特點,但這也使得很多初學者走了不少彎路。一說到編程,大家不免聯想到 coding,因為軟體編程的思想對工程師來說已經是根深蒂固了。因此,很多初學者都會問一個相同的問題,兩種硬體編程語言VHDL和Verilog,應該學哪個?即使明確了要學習哪種設計語言,也會一頭扎進浩瀚的語嫌物空法中,走向歧途。有些初學者寫了大量的代碼,在Demo板上跑了n個試驗,可還是覺得不懂 FPGA,甚至搞不清楚它和單片機的區別。這是為什麼?其實,這都歸結一個原因,就是被「可編程」這3個字給迷惑了,也就是說,沒有弄清楚FPGA的本質是什麼。因此,對於FPGA的學習也就不著法門,事倍功半,浪費了不少時間,卻仍然達不到效果。
FPGA是作為專用集成電路(ASIC)領域中的一種半定製電路而出現的,既解決了定製電路的不足,又克服了原有可編程器件門電路數有限的缺點。因此,從底層來看,FPGA還是屬於集成電路的范疇。就當前的技術而言,使用FPGA開發項目還是全部基於數字電路設計的,所以,FPGA的「可編程」也就是實現不同的數字電路邏輯。這與所謂的軟體編程有著本質的區別!歸根結底,FPGA設計就是電路設計,因此,對於每個FPGA工程師來說,在做設計時必須在腦中有電路的模樣,這很重要!那麼,到底該如何有效地學習FPGA呢?其實,很簡單,只要從以下7點著手,循序漸進,日積月累,就完全能夠對FPGA設計游刃有餘。
1. 首先,必須了解FPGA的結構和性能。不同廠家,不同系列的FPGA晶元都有不同的結構和性能,但是萬變不離其中。剛開始,從掌握幾款典型的高端晶元開始,例如Altera公司的Stratix III和Xilinx公司的Virtex 5。之後,再去了解其它系列的晶元就很容易了。至於Lattice和Actel公司的晶元,當使用時再了解也不遲,因為學習主流的東西才會更加有效!許多有關FPGA的教科書都會以幾款常用的晶元為例,講述FPGA的基本結構和原理。初學者看了後,總覺得過於抽象,有點不知所雲的感覺。因此,為了深刻理解 FPGA,必須要有扎實的數字電路基礎!在數字電路里,最基本的就是邏輯和時序。工程師必須明白FPGA內部邏輯結構和數字電路基本電路結構的關系。例如,任何4個輸入信號的組合邏輯都可以通過FPGA提供的4輸入LUT來實現。如果使用Xilinx的晶元,移位寄存器既可以通過多個觸發器級聯實現,也可以通過LUT來實現。通常,初學者可以設計出正確的邏輯,但卻很容易忽略時序。在I/O口的設計中,與時序相關的缺陷對於產品是致命的,會影響產品的可靠性。因此,在掌握了結構後,還必須關注晶元的一些重要時序參數,例如I/O口時鍾的建立時間、保持時間和從觸發器到輸出的延遲時間,以及晶元內部工作時鍾的最高頻率等等。只有充分掌握了所使用晶元的結構和性能,才能設計出一個合理的系統,才能保證FPGA的設計可靠穩定。FPGA廠商提供的大量文檔是一個不錯的學習資料。
2. FPGA既然是「可編程」,自然離不開編程語言。其實,早期的工程師大多使用原理圖輸入方式進行邏輯設計,這是一種更接近於電路設計的設計方芹瞎式。這種設計方式對設計者要求較高,而且也不利於移植和維護,因此VHDL和Verilog才漸漸流行起來。這兩種語言,無所謂孰優孰劣,只不過Verilog發展的比VHDL好,螞慎而且和將來可能一統天下的SystemVerilog比較接軌。它們都是硬體描述語言。既然叫硬體描述語言,自然是和軟體世界裡的編程不一樣,所以,初學者不能把它當作軟體編程語言來學習,否則就會捨本逐末。如果僅僅只是從事FPGA邏輯設計和做簡單的功能模擬,只需學習最簡單的語法就夠了。那些用於寫驗證腳本的語法,完全不用學,基本用不上。語言僅僅只是一個工具,尤其在硬體設計里,代碼寫得漂不漂亮,並不重要,最關鍵的是設計思想。記住,FPGA工程師是在設計電路,而不是在「編程」!
3. 很多工程師會談到演算法的重要性,認為必須懂得很多演算法。沒錯,好的演算法對於設計來說猶如利器一般。可是,研究演算法和如何實現演算法是兩個不同的概念,研究演算法是在做數學題,實現演算法才是工程師的職責。這里並不是說FPGA工程師不用去研究演算法,而是強調職責所在。不同的演算法,我們對其原理的研究和理解的要求也是不同的。例如8B/10B編碼,只要你懂得在哪裡需要使用它就夠了,現成的IP Core可以直接調用。但是,諸如FEC編解碼這樣的演算法,則只有了解了基本原理後才可能懂得如何實現。對於演算法,FPGA工程師的重點就是在於「如何實現」!。另外,演算法之外,邏輯設計里常用的設計方法必須懂得,例如,乒乓操作、流水線設計和分時復用等等。還有常用的邏輯模塊,如非同步FIFO、狀態機,這些其實都是數字電路里最基礎的東西,但是對於初學者來說,在做FPGA設計時未必會正確的使用。
4. FPGA設計必須有一個好的設計流程來支撐。代碼寫完後,花大量時間做完善的功能模擬和驗證是很有必要的。可是一些工程師並不重視模擬和驗證,而是迫不及待的上板調試。碰到BUG後就在代碼上修修補補,運氣好的話,BUG表面上是解決了,可真正深層次的原因卻未必發現,給產品留下了隱患。一個好的設計流程要求大多數BUG在前期工作中必須解決掉,功能模擬和驗證則是一個很有效也很重要的步驟。除了模擬驗證,綜合和布線也必須重視,這要求我們必須仔細瀏覽編譯報告和時序報告,因為,許多時序問題都能通過報告反映出來。有時候,一些工程師碰到時序問題,僅僅做時鍾反相來調整數據和時鍾的相位關系,或者修改綜合和布線的參數,仍無法解決問題。尤其是在用了高速時鍾的設計里,大多數情況,我們只有修改代碼里的邏輯才能滿足設計的時序要求。這些也只有仔細分析了報告後,才能對症下葯。另外,對於大多數同步邏輯設計來說,時序模擬是沒有必要的,這一步完全可以省略。
5. 現階段,FPGA發展的三大方向就是SOC,高速I/O和DSP。在有限的時間里,選擇一個領域進行主攻是有必要的,只有明確了目標,才會更加投入。 SOC設計要求設計者對軟體編程、CPU原理甚至是操作系統比較了解才行,因為SOC就是一個軟硬體結合的系統。高速I/O設計則要求設計者掌握許多模擬電路的基本知識以及一些常用的通信協議,例如,SDH、GbE、PCI-E等等。FPGA在DSP領域的使用是近幾年興起的一個發展方向。FPGA由於其內在的並行特性,能以很高的效率實現DSP演算法中計算量較大的模塊,非常適合視頻和圖像處理等對DSP性能要求越來越高的新興應用,設計者需要掌握數字信號處理常用演算法。這3個方向完全不同,切勿囫圇吞棗,一切通吃!「術業有專功」,資深的高級工程師也很難在多個方向都取得成就。當然,若能在一個領域有較深的研究,同時,對另外兩個領域也有一定的了解,那就更好了。
6. 一個優秀的FPGA工程師,必須做到「一專多能」。所謂的「一專」當然是指在FPGA設計領域的專業深度,而「多能」則是要求工程師對其它專業領域也要有所了解和掌握。例如,對於設計一個SOC系統來說,C語言就必須學習,否則對於片上系統的架構就可能不合理。另外,對於設計高速I/O口的工程師來說,電路板原理設計和PCB設計則需要有所了解。只有掌握了預加重、均衡以及阻抗匹配等這些與模擬電路相關的概念,才可能在設計和調試中得心應手。
7. 最後一點,也是最難的一點,這也是邁向高級工程師的關鍵,就是FPGA的設計需要一個好的系統架構方案和合理的模塊化分。這有助於FPGA的調試和維護,也便於多人共同開發,尤其是在使用大規模FPGA時,這也就是常說的Top-Down設計方式。把一個龐大的、復雜的設計化分成若干個小模塊,而且層次要分明,不能扁平化,這需要設計者對設計必須有全面深刻的理解。一個雜亂無序的設計對於後期的維護是災難性的,尤其是對於接手者來說,若要修改某個邏輯,可以說是苦不堪言。從這一點看,初學者的問題都可以在這里找到答案。FPGA學什麼?就是學習系統級的電路設計。所以,FPGA工程師的發展方向就是系統工程師。
以上7點若能有深刻理解,則就能看清FPGA的本質了。市場的瞬息變化,要求電子產品必須對市場具有高敏感性,產品從方案設計到市場投放的時間越來越短,FPGA在其中功不可沒。另外,在面對Cost Down時,FPGA也起著不可或缺的作用。在當今時代,FPGA已經在通信、數據處理、網路、儀器、工業控制、軍事和航空航天等眾多領域得到了廣泛應用。隨著功耗和成本的進一步降低,FPGA還將進入更多的應用領域,相信FPGA工程師也必將會有一個更加廣闊的施展空間。
推薦一本書《基於VHDL的FPGA開發快速入門·技巧·實例》
加油吧!