2017-06-30 48 views
1

我正面臨一個奇怪的問題。該代碼適用於簡單的ALU。只有感興趣的代碼粘貼在這裏:Verilog合成後的奇怪模擬結果

always @(posedge clk or posedge rst) 
    begin 
     if (rst == 1) begin 
      mul_valid_shr = 3'b000; 
     end else begin 
      if (op_mul_i == 1) begin 
       mul_valid_shr = 3'b111; 
      end else begin 
       mul_valid_shr <= mul_valid_shr << 1; 
      end 
     end 
    end 

而且總是塊之外:

assign mul_valid = mul_valid_shr[2]; 

與我的測試平臺後合成功能仿真有以下結果:

enter image description here

重置已經很低,爲什麼這款模擬器第一次不能正常工作,但第二次和第三次都能正常工作?如果我在100ns標記前觸發op_mul_i,即使rst爲低電平,即使mul_result第一次停止工作。

任何猜測是值得歡迎的。

UPDATE:FULL代碼在這裏:https://www.edaplayground.com/x/28Hx

+0

我懷疑這不是你問題的原因,但絕對不要在同步變量塊中混淆阻塞和非阻塞賦值_to。通常情況下,您希望對任何隱含觸發器的變量使用非阻塞賦值。我很驚訝你的合成器允許你這樣做。因此,對mul_valid_shr的兩個阻塞賦值('mul_valid_shr = 3'b ...')應該是非阻塞的('mul_valid_shr <= 3'b ...')。 –

+0

我已經試過這個,並且使用了非阻塞的一切。它仍然有完全相同的結果。 – Qazi

+0

我不認爲這會有所幫助。但是不要混淆。 –

回答

0

如何op_mul_i產生? 它與clk同步嗎?我問,因爲在仿真的第二部分,當op_mul_i爲邏輯1時,我看到mul_valid被驅動爲邏輯1。如果它是同步的,我希望mul_valid在200ns邊沿旁邊的時鐘邊沿處爲邏輯1。由於這是後期綜合,我懷疑亞穩態導致這個問題。 在100ns時,op_mul_i在故障窗口內發生變化,並且時鐘沿不檢測op_mul_i爲邏輯1,因此您什麼都看不到。

將op_mul_i同步到clk,並使用同步信號來驅動mul_valid_shr。 另外,不要在順序塊中使用阻塞語句。

希望有所幫助。 VK

+0

感謝您的回答,op_mul_i與n *週期時間的時鐘同步生成。在op_mul_i變高之後的第三個週期,mul_valid應該變高。我已經停止混合阻塞和非阻塞語句。 – Qazi

0

您創建了一個異步觸發器,op_mul_i作爲異步信號。它在你的初始塊中被修改,並且這個修改不與clk同步。所以,它看起來像是一場比賽。硬件是正確的,忽略了一些步驟。

因此,仿真結果可能是正確的,由於仿真工件。我認爲正確的rtl方法是通過爲該信號提供另一個觸發器來使信號與時鐘同步。

除此之外,您可以嘗試在模擬此信號的初始塊中使用無阻塞賦值或#0延遲。

+0

謝謝你的回答。你是什​​麼意思「與op_mul_i異步翻牌」? op_mul_i是僅在n *週期觸發的輸入信號,即20,40,60等,這不會使這個同步,即隨時鐘變化嗎?在最初的tb塊中,我現在使用「#0」,但它對結果沒有影響。 – Qazi

1

Verilog具有非確定性和種族條件的概念。

  • IEEE標準1364-1995 § 5.4.2 非確定性
  • IEEE標準1364-2001 § 5.4.2 非確定性
  • :下面是各種版本的Verilog和SystemVerilog的解釋的概念發揮IEEE Std 1800-2012 § 4。8 非確定性非確定性的

一個來源是活動的事件可採取從隊列和處理以任何順序的事實。非確定性的另一個來源是行爲塊中沒有時間控制結構的語句不必作爲一個事件來執行。時間控制語句是#表達式和@表達式結構(參見9.7 [9.4 for IEEE1800])。在評估行爲陳述時,模擬器可以暫停執行並將部分完成的事件作爲事件隊列上的未決活動事件。這樣做的效果是允許交叉執行流程。請注意,交錯執行的順序不確定,並且不受用戶的控制。

  • IEEE標準1364-1995 § 5.5 競態條件
  • IEEE標準1364-2001 § 5.5 競態條件
  • IEEE Std 1800-2012 § 4.8 競態條件

由於表達式求值和淨更新事件的執行可以被混雜,競爭條件是可能的:

assign p = q; 
initial begin 
    q = 1; 
    #1 q = 0; 
    $display(p); 
end

模擬器是在顯示正確或者是1或0的0至q的分配使得能夠更新事件爲p。模擬器可以繼續並執行$ display任務或執行p的更新,然後執行$ display任務。

總之,這意味着一個總是塊上clk觸發之前可評估或op_mul_i後即使clkop_mul_i在相同的時間步長被改變被更新。這種非確定性和種族條件行爲是有意的;使語言成爲一種模仿與FPGA和芯片關鍵路徑相同的行爲的方式。

不管解決方案和最佳做法是在時鐘和輸入激勵之間有一個偏移量(時間或調度程序區域)。您可以使用一個時間偏移量,例如在? 1在第一個#延遲;就像我在評論中所建議的那樣。或分配輸入刺激與非阻塞任務(<=);在時鐘和任何依賴於時鐘的東西之後,它總會被更新。 (這就是爲什麼觸發器應該被分配非阻塞)。你採取的路線由你或你的團隊決定。

+0

感謝您的詳細解答。不幸的是,它並沒有解決完整的問題。正如我在評論中寫到的,復位問題仍然存在。如果我給出足夠長的主動復位(〜100ns),那麼所有功能都存在,但對於較小的復位,在100ns內發生的任何事情都將被忽略。設計運行在250 Mhz,建立/保持時間小於十分之一ns。你有什麼想法嗎? – Qazi

1

Xilinx仿真器模擬任何綜合後仿真的前100ns的FPGA全局復位,因此基本上必須在復位和時鐘保持邏輯至少100ns才能獲得明智的結果。這在第13頁上的UG900中有提到。