明德揚有一條非常重要的看波形技巧,即「時鐘上公升沿前看條件」的技巧,意思就是在時鐘上公升沿前,看條件訊號,看到什麼值就是值。
這一條技巧,對於剛學習fpga的人來說,非常之實用。
但是,部分工程師在做**時,有時候會出現違反這一原則的奇怪現象。例如下面這個案例:
關於在**軟體中,為什麼計數器的判定會在不滿足加一條件的時候進行加一操作(如下圖所示)。計數器cnt_col的加1條件是din_vld,按照原則,第4個時鐘上公升沿的時候,din_vld應該為0,計數器不應該加1,但事實上是加1了,這是怎麼回事?我們舉另乙個例子來說明這個問題。
功能要求如下:復位後,din_vld 不定時等於1,當din_vld出現3個或超過3個週期的高電平脈衝時,將第三個週期時對應的din值賦給dout,其他時候dout保持不變。
根據功能要求,寫出**後用modelsim進行**,效果如下圖:
然後發現**的波形和我們預期的波形並不一致!!
計數器cnt在din_vld == 0 的時候就已經開始計數了。
檢視**,計數器cnt的加一條件是:add_cnt = din_vld == 1 && flag == 0 。
也就是說,訊號din_vld在時鐘上公升沿處由0變1的時候,**軟體把訊號din_vld的值取為1了。
那麼會出現這種情況的原因是什麼呢?
這裡是軟體**,是軟體模擬真實的電路情況。但是,軟體模擬是有缺陷的,無論軟體如何模擬,本質上它都是序列執行的**,是一條一條指令執行的。
在**檔案裡,有兩個initial語句,乙個是產生時鐘的,乙個是產生din_vld的,如下圖。
按照verilog的語法,這兩個initial是並行執行的。但事實上軟體執行是有先後的。很有可能先執行了din_vld變1的**,再執行了clk由0變1的**,這種情況下,在時鐘的上公升沿就會採到din_vld為1,因此就會出現案例中的錯誤。
這是與fpga實際的電路是不符合的,也就是說這個其實是**缺陷的問題,而不是設計問題。
雖然不是設計問題,但**仍然要繼續,我們需要避免這種情況。如何避免呢?
解決上述問題的方法:
我們可以在測試檔案中給訊號加上乙個1ns 的延時,這樣兩個initial語句就絕對不會同時執行。
用modelsim重新編譯一下再**,此時的波形就是功能要求的正確結果。如下圖:
問題完美解決!
2雙時鐘沿 FPGA跨時鐘域處理3大方法揭秘!
跨時鐘域處理是fpga設計中經常遇到的問題,而如何處理好跨時鐘域間的資料,可以說是每個fpga初學者的必修課。如果是還在校生,跨時鐘域處理也是面試中經常常被問到的乙個問題。這裡主要介紹三種跨時鐘域處理的方法,這三種方法可以說是fpga界最常用也最實用的方法,這三種方法包含了單bit和多bit資料的跨...