Vivado軟件初學使用與VerilogHDL語法初探


》日志日期:2020-8-20

。Verilog HDL是一種硬件描述語言,它是以文本形式來描述數字系統硬件的結構和行為的語言。 (Verilog HDL是一種描述語言,它和常見的編程語言C有根本的不同。C語言,讓計算機的CPU從上往下按順序執行每一條指令,執行完程序就結束了。

而Verilog HDL主要是描述了一個數字模塊的結構,或者行為。有點像商業合同,合同里面也會描述產品的結構,產品的功能等等。合同的每一個條款,並不需要嚴格的先后順序,只要把項目的方方面面都考慮完整,寫下來就OK了。我們用Verilog HDL描述數字模塊的功能,剩下的交給編譯器;編譯器會根據我們的要求設計重構FPGA內部硬件。)

@Vivado軟件的使用學習

       要想學會如何使用FPGA的內部資源,就要先學會如何使用對應的EDA軟件,通過軟件編寫代碼來實現FPGA的內部功能。這里用的時xilinx公司的Vivado2019.2,從網上查找且主要根據正點原子的FPGA教學資料進行學習,新建工程就不介紹了。

       創建完一個新工程后,首先添加一個源文件,過程如下。

 

添加好源文件,編寫完代碼並保存后,進行分析綜合,步驟如下。

 

 

現在介紹下Project summary界面的一些信息。

 

 

分析綜合結束后就要進行約束輸入。約束輸入有 時鍾約束管腳約束 。這里介紹下如何看自己編寫的代碼的硬件原理圖,但主要是找到IO Planning進行管腳約束,過程如下。

 

 

 

 

 

 

 

 

當設計實現時,生成比特流下載到板子上運行。生成比特流時比較慢需要等幾分鍾。

 

 

。當設計好后,還需要進行調試驗證,這時就需要用到xlinx的硬件調試解決方案。

。xlinx硬件調試解決方案:

       >Vivado集成了邏輯分析儀

  >添加ILA核和VIO核實現硬件調試

  >通過JTAG接口與PC相連

       (

       ILA:監控邏輯內部信號和端口信號。

       VIO:實時監控和驅動邏輯內部信號和端口信號。

  )

#如何使用ILA核

       要如何使用ILA核首先要添加ILA核,添加過程如下。

 

 

 

 

設置完成,后面還有一步,默認就行,點擊OK生成IP核文件,然后過程如下。

 

 

 

 

 

 

  當源文件中的信號參數改變后(例如位寬,名稱等),vivado軟件不會自動改變ILA核的配置信息,也就是說修改完源文件,ILA核的配置信息還是對應修改前的源文件,這會導致調試仿真時並不是真正的仿真波形。當我們修改源文件的信號參數時,也要修改配置ILA核的對應信號探針的參數。

》日志日期:2020-8-21

。硬件調試簡介:

       1.功能仿真:

       主要用來驗證電路的功能是否符合設計要求,不考慮門電路的延遲和線延遲。

       2.時序仿真:

       是指電路已經映射到特定的環境后,綜合考慮門電路的延遲和線延遲的影響,驗證電路能否在一定時序條件下滿足設計構想的過程,較好的反映芯片的實際工作情況。

#如何創建Sim仿真文件進行軟件仿真

 

 

 

 

 

 

 

#代碼固化

。固化原理:

       就是將運行代碼加到外設存儲設備,然后重新上電運行外部存儲設備中的程序。

。固化方式:

       1.Bin文件燒錄進Flash進行固化。

       2.Mcs文件燒錄進Flash進行固化。

。代碼固化過程如下。

 

 

 

 

 

 

 

 

 

 

  然后重新生成比特流文件,Bin文件會跟着比特流文件一起生成。然后下載到硬件就行,前提是配置了與外部存儲芯片相同的硬件信息。

@VerilogHDL的學習

#Verilog基礎

。四種邏輯狀態:

。標識符:

 

 

。VerilogHDL的數據類型:

       在 Verilog 語法中,主要有三大類數據類型,即寄存器類型線網類型和參數類型。從名稱中,我們可以看出,真正在數字電路中起作用的數據類型應該是寄存器類型和線網類型。

  。寄存器類型:

       寄存器類型表示一個抽象的數據存儲單元,它只能在 always 語句initial 語句中被賦值,並且它的值從一個賦值到另一個賦值過程中被保存下來。如果該過程語句描述的是時序邏輯,即 always 語句帶有時鍾信號,則該寄存器變量對應為寄存器;如果該過程語句描述的是組合邏輯,即 always 語句不帶有時鍾信號,則該寄存器變量對應為硬件連線;寄存器類型的缺省值是 x(未知狀態)

       寄存器數據類型有很多種,如 reg、integer、real 等,其中最常用的就是 reg 類型。例子如下。

  。線網類型:

       線網表示 Verilog 結構化元件間的物理連線。它的值由驅動元件的值決定,例如連續賦值或門的輸出。如果沒有驅動元件連接到線網,線網的缺省值為 z(高阻態)。線網類型同寄存器類型一樣也是有很多種,如 tri 和 wire 等,其中最常用的就是 wire 類型。例子如下。

 

  。參數類型:

       參數其實就是一個常量,常被用於定義狀態機的狀態、數據位寬和延遲大小等,由於它可以在編譯時修改參數的值,因此它又常被用於一些參數可調的模塊中,使用戶在實例化模塊時,可以根據需要配置參數。在定義參數時,我們可以一次定義多個參數,參數與參數之間需要用逗號隔開。這里我們需要注意的是參數的定義是局部的,只在當前模塊中有效。例子如下。

 

 

 

 

 

 

 

 

                   

 

 

。阻塞賦值與非阻塞賦值:

       >阻塞賦值:

  阻塞賦值,顧名思義即在一個 always 塊中,后面的語句會受到前語句的影響,具體來說就是在同一個always 中,一條阻塞賦值語句如果沒有執行結束,那么該語句后面的語句就不能被執行,即被“阻塞”。也就是說 always 塊內的語句是一種順序關系,這里和 C 語言很類似。符號“=”用於阻塞的賦值(如:b = a;),阻塞賦值“=”在 begin 和 end 之間的語句是順序執行,屬於串行語句。阻塞賦值的執行可以認為是只有一個步驟的操作,即計算右值的值並更新左值,此時不允許任何其他語句的干擾,所謂的阻塞的概念就是值在同一個 always 塊中,其后面的賦值語句從概念上來講是在前面一條語句賦值完成后才執行的。

       >非阻塞賦值:

       符號“<=”用於非阻塞賦值(如:b <= a;),非阻塞賦值是由時鍾節拍決定,在時鍾上升到來時,執行賦值語句右邊,然后將 begin-end 之間的所有賦值語句同時賦值到賦值語句的左邊,注意: begin—end 之間的所有語句,一起執行,且一個時鍾只執行一次,屬於並行執行語句

       所謂的非阻塞的概念是指,在計算非阻塞賦值的 RHS 以及 LHS 期間,允許其它的非阻塞賦值語句同時計算 RHS 和更新 LHS。

       (RHS:賦值等號右邊的表達式或變量可以寫作 RHS 表達式或 RHS 變量;

  LHS:賦值等號左邊的表達式或變量可以寫作 LHS 表達式或 LHS 變量;)

。什么時候使用阻塞賦值核非阻塞賦值?

       在描述組合邏輯電路的時候,使用阻塞賦值,比如 assign 賦值語句和不帶時鍾的 always 賦值語句,這種電路結構只與輸入電平的變化有關系。

       在描述時序邏輯的時候,使用非阻塞賦值,綜合成時序邏輯的電路結構,比如帶時鍾的 always 語句;這種電路結構往往與觸發沿有關系,只有在觸發沿時才可能發生賦值的變化。

。assign和always的區別:

       assign 語句使用時不能帶時鍾。

       always 語句可以帶時鍾,也可以不帶時鍾。

       (在 always 不帶時鍾時,邏輯功能和 assign 完全一致,都是只產生組合邏輯。比較簡單的組合邏輯推薦使用 assign 語句,比較復雜的組合邏輯推薦使用 always 語句。)

。always帶時鍾與不帶時鍾的區別:

       1.不帶時鍾:

  always 語句可以帶時鍾,也可以不帶時鍾。在 always 不帶時鍾時,邏輯功能和 assign 完全一致,雖然產生的信號定義還是 reg 類型,但是該語句產生的還是組合邏輯。

  2.帶時鍾:

  在 always 帶時鍾信號時,這個邏輯語句才能產生真正的寄存器。

。什么是latch?

       latch 是指鎖存器,是一種對脈沖電平敏感的存儲單元電路。鎖存器和寄存器都是基本存儲單元,鎖存器是電平觸發的存儲器,寄存器是邊沿觸發的存儲器。兩者的基本功能是一樣的,都可以存儲數據。鎖存器是組合邏輯產生的,而寄存器是在時序電路中使用,由時鍾觸發產生的。

  (latch 的主要危害是會產生毛刺(glitch),這種毛刺對下一級電路是很危險的。並且其隱蔽性很強,不易查出。因此,在設計中,應盡量避免 latch 的使用。

。代碼里出現latch的兩個原因:

       在組合邏輯中,if 或者 case 語句不完整的描述,比如 if 缺少 else 分支,case 缺少 default 分支,導致代碼在綜合過程中出現了 latch。解決辦法就是 if 必須帶 else 分支,case 必須帶default 分支。(只有不帶時鍾的 always 語句 if 或者 case 語句不完整才會產生 latch,帶時鍾的語句 if或者 case 語句不完整描述不會產生 latch。)

 

#狀態機

。為什么要用狀態機?

Verilog 是硬件描述語言,硬件電路是並行執行的,當需要按照流程或者步驟來完成某個功能時,代碼中通常會使用很多個 if 嵌套語句來實現,這樣就增加了代碼的復雜度,以及降低了代碼的可讀性,這個時候就可以使用狀態機來編寫代碼。狀態機相當於一個控制器,它將一項功能的完成分解為若干步,每一步對應於二進制的一個狀態,通過預先設計的順序在各狀態之間進行轉換,狀態轉換的過程就是實現邏輯功能的過程。

。什么是狀態機?

       狀態機是一種在有限個狀態之間按一定規律轉換的時序電路,可以認為是組合邏輯和時序邏輯的一種組合。狀態機通過控制各個狀態的跳轉來控制流程,使得整個代碼看上去更加清晰易懂,在控制復雜流程的時候,狀態機優勢明顯,因此基本上都會用到狀態機,如 SDRAM 控制器等。

。兩類狀態機:

       1.Mealy狀態機:組合邏輯的輸出不僅取決於當前狀態,還取決於輸入狀態。

 

   2.Moore狀態機:組合邏輯的輸出只取決於當前狀態。

 

 

。三段式狀態機:

       根據狀態機的實際寫法,狀態機還可以分為一段式、二段式和三段式狀態機。

  *一段式:整個狀態機寫到一個 always 模塊里面,在該模塊中既描述狀態轉移,又描述狀態的輸入和輸出。不推薦采用這種狀態機,因為從代碼風格方面來講,一般都會要求把組合邏輯和時序邏輯分開;從代碼維護和升級來說,組合邏輯和時序邏輯混合在一起不利於代碼維護和修改,也不利於約束。

  *二段式:用兩個 always 模塊來描述狀態機,其中一個 always 模塊采用同步時序描述狀態轉移;另一個模塊采用組合邏輯判斷狀態轉移條件,描述狀態轉移規律以及輸出。不同於一段式狀態機的是,它需要定義兩個狀態,現態和次態,然后通過現態和次態的轉換來實現時序邏輯。

  *三段式:在兩個 always 模塊描述方法基礎上,使用三個 always 模塊,一個 always 模塊采用同步時序描述狀態轉移,一個 always 采用組合邏輯判斷狀態轉移條件,描述狀態轉移規律,另一個 always 模塊描述狀態輸出(可以用組合電路輸出,也可以時序電路輸出)。

       實際應用中三段式狀態機使用最多,因為三段式狀態機將組合邏輯和時序分開,有利於綜合器分析優化以及程序的維護;並且三段式狀態機將狀態轉移與狀態輸出分開,使代碼看上去更加清晰易懂,提高了代碼的可讀性。

  三段式狀態機的基本格式是:

    *第一個 always 語句實現同步狀態跳轉;

    *第二個 always 語句采用組合邏輯判斷狀態轉移條件;

    *第三個 always 語句描述狀態輸出(可以用組合電路輸出,也可以時序電路輸出)。

 

   

這里就寫完了,剛入門的菜鳥一只,有很多不懂得地方,文章有不完善的地方還請大佬們指點指點,學習一下😊😊😊😊😊

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM