天天看點

FPGA之道(82)功能仿真之仿真原理

文章目錄

  • ​​前言​​
  • ​​功能仿真篇​​
  • ​​仿真原理​​
  • ​​串行模仿并行思路分析​​
  • ​​有限模仿無限思路分析​​
  • ​​組合邏輯仿真原理​​
  • ​​時序邏輯仿真原理​​
  • ​​HDL的仿真原理​​
  • ​​仿真時間與實體時間​​

前言

《​​FPGA之道​​》。

功能仿真篇

功能仿真是所有仿真類型中最重要的,也是占項目開發比重最大的仿真,對任何一個項目的開發來說幾乎都是必須的,是以在此單獨使用一個篇章對它進行介紹。是以,本篇所指的“仿真”若無特别說明,皆泛指功能仿真。

仿真原理

功能仿真是FPGA項目開發中重要的一環,它是確定我們編寫的HDL設計代碼在功能上準确無誤的重要方法。FPGA中的電路都是并發執行的,是以HDL語言的本質也是并行的,并且硬體電路是無時無刻不在工作的。可FPGA的功能仿真是基于PC機上的相關軟體仿真環境的,而PC機上軟體的執行思路都是串行的,并且PC機每秒的運算次數是有限的。那麼想以串行模仿并行,以有限模仿無限,是否可行?它的原理又是什麼?這就是我們本章節需要讨論的問題。

串行模仿并行思路分析

串行模仿并行主要分為兩種情況:

一、獨立的并行電路

若并行的電路之間是互相獨立的,那麼此時,同時開始做N件事和做完一件事再開始下一件事從結果上來看是完全一樣的。例如加法器1的輸入是A和B,輸出是C,加法器2的輸入是D、E,輸出是F,如下圖:

FPGA之道(82)功能仿真之仿真原理

此時無論是找兩個人分别同時計算兩個加法器的輸出結果還是隻找一個人按任意順序逐個計算兩個加法器的輸出結果,最終得到的答案都會是一樣的。是以這種情況下串行可以比較輕松的模拟并行。

二、有關聯的并行電路

若并行的電路之間不是互相獨立的,那麼此時,情況就不那麼簡單了。例如,加法器1的輸入是A和B,輸出是C,加法器2的輸入是C、D,輸出是E,如下圖:

FPGA之道(82)功能仿真之仿真原理

這個時候,由于模拟環境會保留電路上一次模拟後的結果,是以先計算加法器1還是加法器2,得到的結果是不同的,并且此時并行的模拟思路如果隻做一次的話,也無法給出正确的結果。是以這種情況下,串行要想正确的模拟并行,需要遵循正确的執行順序。

分析到這裡,我想大家應該對HDL中設定串行執行的子語句體的用意有新的看法了吧。而且,為了配合得出正确的仿真結果,我們在串行子語句體中最好能夠嚴格按照數字信号傳遞的方向書寫代碼。

有限模仿無限思路分析

硬體電路隻要一上電,就會持續不斷的工作,永不停歇,因為現實中的電信号時間上都是連續的。而軟體的計算都是離散的,即使令仿真的時間間隔趨近于無窮小,這樣雖然可以使仿真情況無限逼近真實情況,但是卻仍不能完全代替真實情況,并且從計算量上來看,也是無法完成的。是以以PC有限的計算能力仿真硬體無限的時間變化,不能簡單的利用高頻率的采樣來解決。

那麼,仍以一個加法器為例來分析,設加法器的輸入為A和B,輸出為C,如下圖:

FPGA之道(82)功能仿真之仿真原理

若一開始,令A等于5,B等于3,那麼C自然應該等于8。若這種情況持續了10秒鐘,那麼,在這10秒鐘之内,由于A和B的值都沒有改變,雖然加法器電路在一直工作,而且也經過了無數次的加法運算,可是由于每次計算出的C值都為8,是以輸出也一直沒有改變。如果在這之後,A的值變為7,那麼加法器的輸出C會迅速變為10,并且此後C的值會一直保持下去,直到A或B的下一次變化到來,C才有可能改變(因為若A變為8,B變為2,C仍應該為10)。寫到這裡,我想大家應該明白了,雖然硬體電路無時無刻不在進行運算,但是,隻有那些可能會改變輸出的運算才是最重要的,隻要能夠捕捉住這些關鍵時刻,就可以完全模拟出真實的情況。是以,利用這一思路,就可以在FPGA中用有限來模拟無限了。

分析到這裡,我想大家對HDL中的敏感量表應該有了新的認識吧。而且,為了配合得出正确的仿真結果,我們往往需要給出正确的敏感量表,雖然目前來說這對實際硬體電路的實作已經幾乎沒有影響了。

組合邏輯仿真原理

組合邏輯的仿真原理就是結合上面分析的兩種思路得來的,我們姑且稱這兩種思路為“化并行為串行”和“化無限為有限”。是以,隻要注意合理的語句順序安排和正确的敏感量表提取,就可以實作正确和高效的組合邏輯功能仿真。

時序邏輯仿真原理

時序邏輯中最重要的就是寄存器。我們以一個最基本的上升沿敏感的寄存器為例來讨論,它有三個最重要的端口,分别是兩個輸入端口CLK、D,一個輸出端口Q。它的功能可以描述為:無論輸入端口D的值怎麼變化,當且僅當CLK的上升沿到來的時刻,更新輸出端口Q的值為此時輸入端口D的值。此後端口Q的值将會保持下去,直到下一次CLK的上升沿到來才有可能更新(D的值也許和上次一樣,這樣更新了也看不出來)。

是以,雖然寄存器内部的電路是一直工作的,而且随着D值的變化,寄存器内部的部分電路的值也是不斷在變化的,可是由于在任意兩個連續的clk上升沿期間,Q值絕對不會變化,是以我們可以僅僅保留CLK的上升沿時刻作為關鍵時刻,來化無限為有限,進而得出正确的仿真結果。

分析到這裡,我想大家對HDL中的時序描述程式段中的敏感量表的意義也會有進一步的認識了吧。

上述分析隻解決了“化無限為有限”的問題,那麼如果時序邏輯中需要同時改變多個寄存器的值的時候,該怎麼得出正确的仿真結果呢?由于時序邏輯的指派在實體硬體上是有一定延遲的,是以,對多個寄存器在進行并行指派的時候,情況要比組合邏輯簡單的多,那是因為所有寄存器在指派的時侯,新值并不是立即生效,而是等所有的寄存器指派語句都執行後的某一個時刻才生效。根據這樣的道理,那麼“化并行為串行”就是很簡單的事情,因為連指派語句的書寫順序都是無所謂的了。不過,為了提高代碼的閱讀性,便于以後的分析和修改,我還是建議大家“盡量”按照數字信号的傳遞方向來書寫時序邏輯代碼。說“盡量”,是因為在有些情況下,嚴格按照數字信号的傳遞方向來書寫時序邏輯代碼是不可能的,例如循環移位寄存器。

HDL的仿真原理

初學HDL文法的時候,都會對HDL文法中的串行、并行、敏感量表等定義多多少少有些費解。甚至在從事FPGA開發的初期,由于編寫的邏輯功能過于簡單,發現即使不嚴格按照文法規定的要求來做也一樣能夠在FPGA中實作正确的邏輯功能。這是因為編譯器會對我們的HDL代碼進行分析、補充、修改和優化,進而用最接近的門級電路來實作HDL代碼所描述的功能。但是,還是請大家養成嚴格遵守文法要求的程式設計習慣!首先,編譯器并不是每次都能幫你把電路适配正确的。其次,仿真器不具有将HDL代碼轉換為電路的功能,它隻能嚴格按照文法來了解我們的HDL代碼。是以,HDL文法對于仿真器是很重要的,它是仿真器了解FPGA設計的“新華字典”,要想使自己的HDL代碼得到正确仿真,在最開始編寫HDL代碼的時候,就要養成嚴格遵守HDL文法的好習慣!

通過之前的讨論,我們可以斷定,隻要有合理的語句順序安排(對于時序邏輯這點甚至也是可以不需要的)和正确的敏感量表提取,我們就能完美的仿真VHDL中的process語句體,或者Verilog中的always程式塊。但是HDL文法中有還有很多其他的文法結構,它們該怎麼仿真呢?

先看【程式設計篇->程式設計文法->VHDL基本文法->VHDL基本程式架構】小節介紹的VHDL基本模闆,除去一些與功能無關的端口聲明、變量聲明等以外,具有功能描述的部分除了process就剩元件例化語句和獨立指派語句了。在介紹VHDL基本程式架構時,我們分析過,architecture中的獨立語句其實就相當于隻有一條代碼的純組合邏輯process。而元件例化語句所調用元件的功能,最終其實也是對應到該元件architecture中描述的process、元件例化或者獨立語句。是以,VHDL中所有的并行語句都可以很友善的直接或間接的轉換為process語句結構。那麼此時,隻要利用“化并行為串行”和“化無限為有限”的思想,VHDL語言即是可仿的。

對于【程式設計篇->程式設計文法->Verilog基本文法->Verilog基本程式架構】小節中介紹的Verilog基本模闆的分析也是一樣。Verilog中所有的功能性并行語句都可以直接或間接轉換為always程式塊,是以利用“化并行為串行”和“化無限為有限”的思想,Verilog語言也是可仿的。

仿真時間與實體時間

仿真時間就是指仿真器模拟了FPGA晶片在現實世界中多少時間的工作行為,而實體時間指的是仿真過程所消耗的現實世界的時間長度。兩者的概念是截然不同的,舉例如下:

如果FPGA晶片中實作的功能原理圖如下:

FPGA之道(82)功能仿真之仿真原理

其時鐘的頻率為10MHz,那麼在現實世界中,該FPGA晶片在一秒鐘之内可以依次、串行的完成1千萬次加法運算。

如果本次仿真僅需要仿真1億次加法,那麼整個仿真過程完成的仿真時間為(1億次/1千萬次) 1秒 = 10秒,即仿真器仿真了1億次加法,相當于模仿了FPGA晶片在現實世界中10秒鐘時間内的工作行為。

同樣是仿真1億次加法,如果你使用的計算機每完成一次加法的模拟需要10個指令周期(包括讀取新的加數、被加數,計算加法,輸出結果等等操作),而你使用的計算機每個指令周期為1納秒,那麼整個仿真過程消耗的實體時間為(1億次10指令周期每次1納秒)=1秒,即你隻需要坐在你的電腦前,等待1秒鐘,就可以看到FPGA晶片在現實世界中需要10秒鐘才能完成的所有行為。不過請注意,實體時間是與你所使用的計算機的性能息息相關的,如果你有一台高性能的電腦,可能等待的時間就變為0.1秒,如果你用的是一台老古董,等待的時間很可能變為3秒、4秒甚至更多。

仿真1億次加法,完成仿真時間10秒,而消耗實體時間1秒,初步看來仿真效率還蠻高的,不過請不要高興得太早,現實情況中往往不是這樣的,因為FPGA設計最大的特點就是其并行性。對于稍微複雜一點的FPGA設計,它每秒完成的運算恐怕就是1千萬次并行算子。如果一個并行算子的複雜度是加法的1萬倍,那麼仿真一個并行算子很可能就需要10萬個指令周期。此時仿真1億次該并行算子所消耗的實體時間為(1億次10萬指令周期每次*1納秒)=1萬秒≈3小時,即為了完成10秒鐘的仿真時間,你可能需要癡癡地在電腦前等上3個小時,這種情況下我還是建議你先去買包瓜子吧!