硬件描述语言(HDL)
硬件描述語言(HDL)
- 1 HDL基本介紹
- 2 VHDL語言
- 庫和實體
- 數據對象和數據類型:
- 操作符:
- 結構體之進程:
- VHDL語法 :
- VHDL語法規則及注意事項:
 
- 3 Verilog語言
- 基本:
- 模塊和端口:
- 數據流建模:
- 行為級建模
- 基于事件的時序控制
- 主要語句
- 注意事項:
 
- 4 綜合和仿真
- 基本:
- 有限狀態機
- testbench
- 與其他軟件的混合開發
- 注意事項:
 
- 5 時序分析和時序控制
- FPGA中的時序問題
- 同步時序控制的基本策略
- 跨時鐘域(CDC)邏輯設計
- 跨時鐘域多路信號處理
- 注意事項:
 
- 6 模塊化設計和片上總線
- 層次化設計方法
- 片上總線( On Chip Bus, OCB )
 
1 HDL基本介紹
Hardware Description Language (HDL)。
DSP:并行,一般最多三條語句同時執行。——由硬件內部結構決定。考慮GPU的使用即為CPU難以完成多個ALU(運算器)的處理,而GPU可以有非常多的ALU(相當于CPU為工程師,而GPU為普通工人)。
CPLD與FPGA的最大區別(為什么一個是乘積項一個是查找表):CPLD的觸發器工藝做不上去,因此主要用于組合邏輯;而FPGA集成了大量的RAM(SRAM),因此適合做時序邏輯。
時鐘的最大頻率由邏輯的時延決定(可編程邏輯器件最后一個題考的就是D觸發器的最大時鐘頻率公式)。
FPGA重點在于實時處理能力:CPU進行一個簡單的處理操作可能就要花費100多個時鐘周期。
硬件直接執行的語言和硬件描述語言的區別:一個是執行“軟件”,一個是“軟件”描述“硬件”。硬件描述語言可稱為:“面向接口編程”。(記得本科的JAVA老師提過除了熟悉的面向過程、面向對象,還有面向接口、面向方法,而很多學校已經在本科講后面兩種了)
多時鐘適用于CPLD(如時鐘取反),不適用于FPGA(同步時鐘)。
語言:將外部事物映射到現有基本單元和處理規則體系下。
代碼要符合邏輯關聯,表述硬件信號邏輯。(而非湊時序)
2 VHDL語言
- VHDL :超高速集成電路硬件描述語言 Very-High-Speed Integrated Circuit Hardware Description Language。現有主要版本:VHDL-1993。
- 基本代碼結構:(1)實體entity(二級單元:結構體architecture)(2)程序包package(二級單元:包體package body)(3)配置聲明(4)上下文聲明。基本單元能夠獨立存在,二級單元必須先定義其基本單元才能定義。
- 結構體主體:1 進程 2 信號賦值 3 元件例化 4 生成語句 5 塊語句(不常用)
 
 
庫和實體
*程序包 package:聲明了可以被電路各部分使用的數據類型、子程序、運算和元件等對象。包 體 package body:給出了程序包中聲明的子程序和運算的具體實現。
 *常用庫:(1)std 庫: VHDL 標準庫的一部分。默認下列語句存在, 不要顯式重復聲明:Library std; Use std.standard.all;(2)ieee 庫,包含了一組可用于 RTL 綜合的標準邏輯類型和數據類型的程序包(3)work 庫,包含了當前設計工程中的所有設計單元編譯結果。默認存在, 引用時不需要顯式使庫可見。
- 實體entity:定義了電路的接口和名稱;結構體architecture:定義了電路的具體實現。
數據對象和數據類型:
*三種數據對象:常量、變量、信號。
- 變量是中間關聯關系,
- 變量(定義)賦值:分配給變量的值立刻成為當前值,不能設置傳輸延遲variable 變量名 : 數據類型 [:= 初始值];
 信號賦值:如果 一 個進程中多次為同一個信號賦值,只有最后一次的賦值會起作用。signal 信號名 : 數據類型 [:= 初始值];
- 有效的硬件初始值必須通過統一的復位邏輯來實現!
- 條件信號賦值:sum3<=a+b when sel ==‘1’ else a-b; 各賦值語句有優先級的差別,賦值條件可以重疊。
 選擇信號賦值:with sel select
 dout<=d0 when “00”, d1 when “01”, d2 when “10”, d3 when “11”, “00000000” when others; 選擇值必須互斥,不能出現重復或重疊。
- record記錄:元素組成的集合,類似C中的結構體。在VHDL和Verilog混合編程中的project不建議使用record。
- 字符類型可綜合。
- 16#E#E1:16進制的14e1=14*16=224。
操作符:
- 標準邏輯位std_logic:只有“0”、“1”、“Z”(高阻態)可綜合。
- 移位操作符可綜合。(移位器)乘法器和除法器可綜合,乘方原則上不可綜合。移位器使用要優于乘法器(*2/4/8)。求模取余也可綜合。
 *VHDL沒有按位與、按位或。
 
 
結構體之進程:
-  注意敏感信號參數表的填寫!!!若無,則必須包含wait語句(互斥)。 
-  一個實體可以有多個結構體,每個結構體描述了同一個電路硬件部件的不同實現。 
-  1進程PROCESS是一系列必須按時序執行的時序語句。2與軟件程序的區別:重復運行,連續循環。3同一個結構體內的多個進程之間是并行執行的關系。 
-  如果沒有敏感列表,進程中必須包含 wait 語句來暫停進程;如果有敏感列表, wait 語句 不能出現在進程中。 
 
-  聲明對進程是局部的,只能用于進程內。 
-  仿真器對于進程的執行:進程執行過程中所有信號值不變–如果進程過程中有對信號的賦值,將改變信號值的事件排入等待執行的隊列–進程結束執行時,執行排在隊列中的賦值事件。 
-  進程中的信號賦值:同一個進程中對同一個信號多次賦值,只有最后一次生效。在不同進程中,不能對同一個信號進行賦值。在進程中只能使用簡單賦值。 
 
-  流程控制語句:if 和 case 語句替代條件賦值和選擇賦值;loop 語句:循環控制。 
-  1初始值沒有硬件解釋,綜合器會忽略初值2進程執行期間,信號不能用于存儲計算的中間值,必須使用變量3賦值語句立即更新變量 
-  需要避免的鎖存latch,兩種情況:1如果目標信號在某些條件下沒有接收數值,則保留先前值:(1)缺少了對應于 if 語句的 else 部分(2)if 語句的某些分支沒有對信號進行賦值。2先前值來自反饋:組合邏輯會引入latch。時序邏輯是允許的。 
 
-  時序進程:進程僅在每個時鐘的上升沿(下降沿)啟動。 
-  時鐘門控:時鐘信號由其他控制信號開啟或關閉。如果沒有特殊需求,不要使用時鐘門控,容易出現毛刺。防毛刺可以通過一個寄存器的鎖存輸出。數據門控:門控控制寄存器的數據輸入。 
 
VHDL語法 :
- 結構體之元件例化:將預先設計好的實體定義為元件,并將其與當前設計實體中的端口連接。
- 結構體之生成語句(重復語句):用于創建重復硬件結構或者條件硬件結構–for generate :用于重復硬件結構–if generate :用于條件硬件結構。并發語句,能用于任何結構體。
- 函數和過程:函數(function)和過程(procedure)統稱為子程序(subprogram)。子程序中不允許使用wait 語句。函數中禁止信號聲明和元件例化。procedure一般可用process代替,盡量不推薦使用。測試testbench時建議用。
 
VHDL語法規則及注意事項:
 1.命名規則:不區分大小寫;不允許出現兩個連續的下劃線,***注釋由兩個連續虛線(‘–’)開始直至行尾;注意in、out是關鍵字。
 2.port的最后一句不加分號!!!(編譯出現多條錯誤時首先檢查該項)
 3.entity名要與 VHDL 程序的文件名一致。
 4.“:=”表示預編譯時賦值,“<=”表示真實賦值。(注意賦值區分,結果會不同)
 5.“when···else”等選擇語句一定要窮舉所有可能性!(否則出現鎖存latch)
 6.等于“=”,不等于“/=”。
 7.VHDL是一種強類型語言,不支持類型復用。
 8.向量測試:常用AAAA(A 1010),5555(5 0101)測試焊接數據線短路問題。
 9.信號類型:盡量只用std_logic、std_logic_vector。
 10.不要在設計中同時使用異步(RST在時序clock外)復位和異步置位。
 11.elsif而非elseif!!!要有end if!!!
 12.極力避免組合邏輯!!!latch!!!(以及選擇涵蓋所有分支)
3 Verilog語言
基本:
- 區分大小寫
- 單行注釋以“//”開始,多行注釋以“/*”開始,以 “*/”結束。
- Verilog 中關鍵字全部為小寫。
- 四種基本電平邏輯:0,1,未知x或X,高阻z或Z。
- 數據類型:1.線網net:表示硬件單元之間的物理連線,由其連接的器件輸出端連續驅動。一般使用wire聲明,還有wand,wor,tri等。如果沒有驅動元件,缺省值一般為 z。 2.寄存器:用來表示存儲單元。會保持數據原有的值,直到被改寫,不需要驅動源。默認值為 x。僅僅意味著一個保持數值的變量,不代表硬件寄存器。 3.wire 或 reg 可聲明為向量(位寬大于 1。格式:[high#: low#]或 [low#: high#],左邊的數總是代表向量的最高有效位。起始位可以是變量,位寬必須是常量。
- 整數、實數和時間等數據類型實際也屬于寄存器類型。
- reg 型變量為無符號數, integer 型變量為有符號數。
- 時間寄存器:時間變量通過使用關鍵字 time 來聲明。通過調用系統函數 $time 可以得到當前的仿真時間。單位受`timescale 定義的參考時間單位控制。`timescale 1ns/1ps:時延單位1 ns,時延精度1 ps。(電腦左上角撇號)。用于仿真,不可綜合。慣性延遲,小于一個周期保持原來參數。
- 字符串保存在 reg 類型的變量中,每個字符占用一個字節(8bit)。
 
 
模塊和端口:
- 模塊是設計中的基本功能塊,端口是模塊與外部交互的通道。
- 所有端口隱含地聲明為wire類型。不能將 input 和 inout 類型的端口聲明為 reg 類型,output 類型的端口可以聲明為 reg 類型,端口數據類型為 reg 時, reg 聲明不能省略。
 
 
數據流建模:
- 連續賦值語句:以關鍵字 assign 開始,用于對線網進行賦值。不可綜合!
- 指定延遲寫法示例:wire #10 out; 注意:在延遲期間(左側獲得新值之前),如果右側信號再次發生變化,在計算表達式新值時會取右側信號的當前值(慣性延遲)
行為級建模
- 結構化過程語句:行為級建模的兩種基本語句:initial 、 always。initial 語句從0時刻開始執行,只執行一次,多個initial塊之間是相互獨立的。理論上不可綜合,類似于VHDL的process。 always 語句結構是重復執行的。
- 過程賦值語句,存在兩種:–阻塞賦值語句(=),順序執行。–非阻塞賦值語句(<=),并行執行。仿真時的時序控制結果不同。
基于事件的時序控制
- –常規事件控制;命名事件控制;OR (或)事件控制;電平敏感時序控制。可以用來觸發聲明語句或塊語句的執行。
- 使用符號@來說明。語句執行條件:信號值發生變化、發生正向跳變posedge、發生負向跳變negedge。
- 由關鍵字 or 連接多個事件名或者信號名構成敏感列表。多個信號或事件中發生的任意一個變化都能夠觸發語句或語句塊的執行。關鍵字 or 也可以使用“,”來代替。組合邏輯塊語句的輸入變量很多時,可以用@*或@(*),表示對其后語句塊中的所有輸入變量的變化是敏感的。
- 在同一個always 塊中 不要既用非阻塞賦值又用阻塞賦值。時序電路建模時,使用非阻塞賦值。鎖存器電路建模時,使用非阻塞賦值。用 always 塊建立組合邏輯模型時,使用阻塞賦值。
主要語句
-  條件語句:if-else;case(結尾加end或endcase) 
-  循環語句四種類型:while for repeat forever。只能在 always 或 initial 塊中使用。 
-  塊語句:1順序塊:用關鍵字 begin 和 end 來表示。順序塊中的語句是一條接一條按順序執行。2并行塊:由關鍵字 fork 和 join 聲明。并行塊內的語句并發執行。語句執行的順序由各自語句中的延遲或事件控制決定。 
-  子程序:任務(task)和函數 (function)。可以在任務和函數中聲明局部變量,如寄存器、時間、整數、實數和事件,但不能聲明線網類型的變量;只能使用行為級語句,但不能包含 always 和initial 塊;可以在 always 塊、 initial 塊中調用任務和函數。 
 
-  函數不含有非阻塞賦值語句,綜合成純組合邏輯。 
-  編譯指令:`define,`undef(鍵盤左上角)。條件編譯:`ifdef `ifndef `elsif `else `endif。 
-  系統任務:display打印;strobe語句結束后才打印。 
注意事項:
 1.時間寄存器`timescale電腦左上角撇號!!!
 2.在同一個always 塊中 不要既用非阻塞賦值又用阻塞賦值。時序電路建模時,使用非阻塞賦值<=。
 3.if-else關注配對問題。
 4.FPGA跳到不可能狀態:(1)邏輯寫法的latch:信號不完備,輸出端引入到輸入端的反饋!(2)時序邏輯電路建模不小心寫成阻塞賦值=。
 5.狀態機建議選用case(綜合時無先后順序),不要用if(有先后順序)。
 6.for進行判斷中判斷語句不能用=或~=。(Verilog里要求)
4 綜合和仿真
基本:
- 綜合(Synthesis):將較高級抽象層次的設計描述自動轉化為較低層次描述的過程。
- 編程(Program)配置 (Configuration):將適配后生成的編程文件裝入 PLD 器件中的過程。
- 大小寫敏感性:1當僅僅用大小寫區分兩個不同的實例或信號時,綜合器可以正常識別。2當僅僅用大小寫區分兩個不同的模塊( module )時綜合器可能會報錯!
 
 
 
有限狀態機
- 分類:Mealy狀態機、Moore狀態機、帶有流水線的Mealy 狀態機。
- 使用 parameter verilog 或枚舉 enum VHDL 類型定義狀態。避免直接使用數值定義狀態。避免使用數值計算定義狀態跳轉。
 
 
 
testbench
- 在綜合后和布局布線后仿真中,全局復位 置位信號( Global Set/Reset, GSR )默認持續 100ns。
- 自動驗證技術和自檢查測試文件:常見的自動驗證方法,1數據文件比較:將仿真結果的期望值寫入一個文件,將仿真結果寫入另一個文件,在仿真結束后比較兩個文件進行驗證。2波形比較:某些仿真軟件支持輸出波形和期望波形的自動比較。 自檢查測試文件:將期望結果作為測試文件的一部分,在仿真過程中實時完成結果的比較。
與其他軟件的混合開發
- MyHDL python http://www.myhdl.org
- cocotb python https:// github.com/cocotb/cocotb
- Chisel scala https:// github.com/chipsalliance/chisel3
- SpinalHDL scala https:// github.com/spinalhdl/spinalhdl
注意事項:
 1.建議不要使用未指定寬度的整數,有可能產生不確定的問題(和綜合器有關)。
 2.不要使用異步方式置位或復位寄存器。
 3.對于時鐘使能,set/reset,盡量使用高電平有效。低電平有效會綜合成額外的非門。
 4.人為增加信號延遲:(1)時鐘鎖-動態移位寄存器:對高頻延遲控制多個時鐘周期,可采用移位寄存器。(大延遲)(2)調用FPGA原語(小延遲)
 5.RAM使用初始化條件:請使用$readmemb,不要用$readmemh。
 6.ROM只有讀接口,initial語句可綜合成ROM。
 7.注意:timing error如果出現,請不要下載到FPGA中。
5 時序分析和時序控制
FPGA中的時序問題
1同步時序問題:過于復雜的組合邏輯,或邏輯的不適當設計,導致建立時間、保持時間的條件不能滿足。對同步接口鎖存造成的接口效率下降。
 2跨時鐘域問題:由于跨時鐘域造成的亞穩態,使得同一個輸出在不同的接收寄存器上被解釋成不同的值造成的邏輯錯誤。同一組信號輸出由于亞穩態造成的時間延遲不同,在接收端引起的數據接收錯誤。
同步時序控制的基本策略
1 建立時間、保持時間的條件不滿足(無握手)
 (1)同源時鐘問題
 如果不加特殊約束設置,分頻時鐘不能利用FPGA全局時鐘樹,到達各個寄存器的延遲相差太大,影響時序性能。解決方法:為分頻時鐘增加額外的時序約束;使用PLL+全局時鐘buffer產生分頻時鐘,使分頻時鐘成為全局時鐘;不要直接使用分頻后時鐘(最好方法)
 (2)流水線技術
 將原本一個時鐘周期完成的較大的組合邏輯通過合理的切割后分由多個時鐘周期完成。使用條件:處理流程可以分為若干步驟;整個數據處理是單向的,沒有反饋或迭代運算。
 (3)組合邏輯優化:
- 查找表技術:在FPGA中,對于某些特定問題,直接建立輸入信號和輸出結果之間的查找表,避免使用復雜組合邏輯通過運算產生結果,是有效的時序優化技術。運算中含有復雜計算時;算法比較復雜,但輸入和輸出信號簡單時。
- 8b/10編碼器
- CRC編碼
2 對同步接口鎖存造成的接口效率下降(接口的讀和寫)
- 產生一個額外的時鐘周期,延遲可能產生數據問題。(使用提前控制信號以及變種!)
 (1)適當的組合邏輯
 (2)同步接口流水線
- 使用提前控制信號。
- 預讀技術的變種:FWFT FIFO,First-Word Fall-Through FIFO,預讀一個數,保證后續的讀信號可以實時輸出數據。
 
(3)同步接口寄存器隔離
- 在同步接口設計中,通過額外的緩存寄存器實現所有接口信號的寄存器化(FIFO讀接口,讓rd_en信號寄存器化)
跨時鐘域(CDC)邏輯設計
- 1 由于跨時鐘域造成的亞穩態,使得同一個輸出在不同的接收寄存器上被解釋成不同的值造成的邏輯錯誤。
- 2 同一組信號輸出由于亞穩態造成的時間延遲不同,在接收端引起的數據接收錯誤。
 兩種場景
場景1:允許在不同時鐘域之間缺失采樣邊沿,每個采樣值必須是準確的。異步FIFO的讀寫地址。
 場景2:跨時鐘域的每個信號必須被采樣,信號必須確認被正確接收后才能改變
- 解決方式:同步寄存器鏈。(“鎖兩級”)
 對某些高速應用,兩級觸發器鎖存并不足以保證足夠好的MTBF性能,需要三級或更多級的同步寄存器鏈。
- 跨時鐘域時的可靠傳輸條件:由慢時鐘域向快時鐘域傳輸時的安全條件,“三邊沿”條件。當通過兩級觸發器來進行跨時鐘域信號傳輸時,當CDC信號寬度為接收時鐘域時鐘周期的1.5倍以上時,可以保證信號被接收端至少正確接收一次。以上條件等效為:CDC信號應至少持續3個接收時鐘邊沿來保證被正確接收。
- 同步寄存器鏈使用條件:1必須是從慢時鐘域到快時鐘域的傳輸 2必須滿足三邊沿條件
跨時鐘域多路信號處理
- 簡單的二級寄存器鏈不能保證信號的正確傳輸:不同信號之間有著傳輸延遲,并不能保證所有信號同時被同一個時鐘采樣!
- 可能采取的策略:1多位信號合并:如果可能,將多個CDC位合并成1個CDC信號 2多周期路徑(MCP)方式:使用同步的load位安全傳遞多位信號 3異步FIFO方式(格雷碼計數器等,僅有一位發生變化)
注意事項:
 1.命名常見規則:_p/_n(高/低電平有效)
 2.晶振jitter一般10 ps,高精度可做到ps以下。ps以下可直接做高速串行收發器。在外部鎖相環鎖過的信號不能直接驅動高速信號收發器(相噪大)。
 3.同步接口鎖存:使用提前控制信號以及變種!
 4.跨時鐘域(CDC):同步寄存器鏈。(“鎖兩級”)
6 模塊化設計和片上總線
層次化設計方法
- 真實設計時以 Top down 方法為主,以 Bottom up 方法為輔。
- IP:IC 設計和 FPGA 設計中指完成某種功能的設計模塊。硬核:以版圖形式實現的設計模塊,通常用GDS II文件格式。軟核:在寄存器級或門級對電路功能用 HDL 進行描述,表現為 Verilog 或 VHDL 代碼的形式。固核:完成了綜合的功能塊,通常以網表的形式提交給客戶使用。
 
片上總線( On Chip Bus, OCB )
- 以總線方式實現 IP 核之間的數據通信。需要定義各個模塊之間初始化、仲裁、請求傳輸、響應、發送接收過程中的驅動、時序、策略等關系。
 標準片上總線: AMBA ( ARM )、 Wishbone ( Silicore )、 Avalon ( Altera )等
- I2C 是一種串行總線的外設接口,它采用同步方式串行接收或發送信息,兩個設備在同一個時鐘下工作。I2C 總線只用兩根線:串行數據 SDA Serial Data、串行時鐘SCL Serial Clock。I2C 總線器件沒有片選控制線,所以 I2C 總線數據傳輸的開始必須由主器件產生通信的開始條件( SCL 高電平時,SDA 產生負跳變);通信結束時,由主器件產生通信的結束條件( SCL 高電平時, SDA 產生正跳變)。
 
總結
以上是生活随笔為你收集整理的硬件描述语言(HDL)的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: Java 插入排序 希尔排序
- 下一篇: 静态路由配置命令和完整流程
