2012-07-26 55 views
5

如我所知,D觸發器在時鐘的每個正沿 處對其輸入值進行採樣。爲什麼我的D觸發器不等待時鐘的正邊緣?

因此,它會產生1個週期的延遲。對?

但是,爲什麼我的D觸發器不會產生1個週期的延遲?

  module flipflop(
      input clk, 
      input rstn, 
      input [7:0] i_data, 
      output reg [7:0] o_data 
     ); 

      always @(posedge clk) begin 
        if (~rstn) begin 
          o_data <= 0; 
        end 
        else begin 
          o_data <= i_data; 
        end 
      end 
     endmodule 

     module test; 
      reg clk; 
      reg [7:0] i_data; 
      reg rstn; 
      wire [7:0] o_data; 

      initial begin 
        clk = 0; 
        rstn = 1; 
        i_data = 0; 
        #20; 
        rstn = 0; 

        #30; 
        rstn = 1; 
        #20; 
        i_data = 8'hFA; 
        #20; 
        i_data = 8'hF0; 
        #20 
        i_data = 8'hF1; 
        #20 
        #10 $finish; 
      end 

      always #10 clk = !clk; 

      flipflop flipflop(
        .clk (clk), 
        .rstn(rstn), 
        .i_data(i_data), 
        .o_data(o_data) 
      ); 

      initial begin 
        $dumpfile("flipflop.vcd"); 
        $dumpvars(); 
      end 
     endmodule 

dff no delay

我的d觸發器的功能,如在這裏組合電路。

回答

5

該模擬器可能做這樣的事情:

 initial begin 
       clk = 0; 
       rstn = 1; 
       i_data = 0; 
       #10; 
       clk = !clk; 
       #10; 
       rstn = 0; 
       clk = !clk; 

       #10; 
       clk = !clk; 
       #10; 
       clk = !clk; 
       #10; 
       rstn = 1; 
       clk = !clk; 
       #10; 
       clk = !clk; 
       #10 
       i_data = 8'hFA; //Input updated 
       clk = !clk;  //Clock event 
           //o_data assigned here 
       #10; 
       clk = !clk; 
       #10; 
       i_data = 8'hF0; 
       clk = !clk; 
       #20 
       i_data = 8'hF1; 
       #20 
       #10 $finish; 
     end 

由於時鐘事件最後從每個時間段出現在您的測試平臺,它看起來像翻牌正在分配。你可能希望你的測試平臺不受時間限制,所以Marty建議使用@(posedge ...)來達到這個目的。你也可以簡單地在一開始就延遲一次任務:

 initial begin 
       clk = 0; 
       #1; 
       rstn = 1; 
       i_data = 0; 
       #20; 
       rstn = 0; 

       #30; 
       rstn = 1; 
       #20; 
       i_data = 8'hFA; 
       #20; 
       i_data = 8'hF0; 
       #20 
       i_data = 8'hF1; 
       #20 
       #10 $finish; 
     end 
+0

這是闡明問題的好方法。 – Marty 2012-07-26 21:39:15

5

你已經運行了反對Verilog模擬器事件調度的微妙之處!更改數據分配以使用非阻塞分配可能是最簡單的解決方法。

#20; 
i_data <= 8'hFA; 
#20; 
i_data <= 8'hF0; 
#20 
i_data <= 8'hF1; 
#20 

原始版本中發生的情況是,時鐘和輸入數據被安排在同一時間發生。由於模擬器一次只能做一件事,所以必須先決定它是否會改變時鐘或數據。它首先改變了數據,所以當時鍾邊緣出現時,輸入數據已經改變爲下一個值,因此看起來數據正在通過FF滑動。

無阻塞分配(<=)計劃在所有阻塞分配(=)完成後發生。因此,使數據分配非阻塞可確保它們在分塊分配的時鐘沿之後發生。

另一種方式來重寫東西的工作將是:

initial begin 
    @(posedge clk) i_data = 8'hFA; 
    @(posedge clk) i_data = 8'hF0; 
    @(posedge clk) i_data = 8'hF1; 
end 
+0

馬蒂,你能回顧一下你最後的建議嗎?它認爲它應該是@ @(posedge clk)i_data <= 8'hFA;'(非阻塞)。這樣,在時鐘更新後,我們有2 @(posedge clk)。兩者都使用非阻塞賦值,因此無論執行順序如何,結果都是相同的:觸發器將註冊一箇舊值,並且'i_data'將被更新爲新值。 但是,如果我們對'i_data'進行阻塞賦值並對'o_data'進行非阻塞,則輸出將取決於仿真調度。在Cadence的irun上測試我得到了錯誤的結果,與OP最初的問題相同。 – RaZ 2018-01-07 13:14:54

相關問題