2013-06-03 38 views
1

我試圖將一個整數值傳遞給模塊,但IF語句不能與該參數一起使用。它會引發以下錯誤。我是Verilog,所以我不知道如何使這項工作。不能使用Verilog中的if語句的輸入

Error (10200): Verilog HDL Conditional Statement error at clock_divider.v(17): 
cannot match operand(s) in the condition to the corresponding edges in the enclosing 
event control of the always construct 

clock_divider.v模塊

module clock_divider (clockHandler, clk, rst_n, clk_o); 

parameter DIV_CONST = 10000000 ; // 1 second 
parameter DIV_CONST_faster = 10000000/5; 
input clockHandler; 
input clk; 
input rst_n; 

output reg clk_o; 

reg [31:0] div; 
reg en; 
integer div_helper = 0; 

always @ (posedge clk or negedge rst_n) 
begin 
    if(clockHandler == 0) 
    begin div_helper = DIV_CONST; 
    end 

    else 
    begin div_helper = DIV_CONST_faster; 
    end 

    if (!rst_n) 
    begin div <= 0; 
      en <= 0; 
    end 

    else 
    begin 
     if (div == div_helper) 
     begin div <= 0; 
       en <= 1; 
     end 

     else 
     begin div <= div + 1; 
       en <= 0; 
     end 
    end 
end 

always @ (posedge clk or negedge rst_n) 
begin 
if (!rst_n) 
begin 
    clk_o <= 1'b0; 
end 
else if (en) 
    clk_o <= ~clk_o; 
end 

endmodule 

main.v模塊

reg clockHandler = 1; 

// 7-seg display mux 
always @ (*) 
begin 
    case (SW[2:0]) 
     3'b000: hexdata <= 16'h0188; 
     3'b001: hexdata <= register_A ; 
     3'b010: hexdata <= program_counter ; 
     3'b011: hexdata <= instruction_register ; 
     3'b100: hexdata <= memory_data_register_out ; 
     3'b111: hexdata <= out; 
     default: hexdata <= 16'h0188; 
    endcase 

    if(SW[8] == 1) 
    begin 
     clockHandler = 1; 
    end 
    else 
    begin 
     clockHandler = 0; 
    end 
end 

HexDigit d0(HEX0,hexdata[3:0]); 
HexDigit d1(HEX1,hexdata[7:4]); 
HexDigit d2(HEX2,hexdata[11:8]); 
HexDigit d3(HEX3,hexdata[15:12]); 


clock_divider clk1Hzfrom50MHz (
       clockHandler, 
       CLOCK_50, 
       KEY[3], 
       clk_1Hz 
       ); 

回答

4

這是我的理解是在Verilog的第一個語句總是塊必須if(reset)項如果你正在使用異步重置。

所以翻牌結構應該永遠是這樣的:

always @ (posedge clk or negedge rst_n) begin 
    if(~rst_n) begin 
     ...reset statements... 
    end else begin 
     ...all other statements... 
    end 
end 

因此,對於你的情況,你應該移動if(clockHandler==0)else語句中,因爲它是不相關的復位執行。更好的辦法是把它移動到一個單獨的組合塊中,因爲在塊中混合阻塞和非阻塞語句通常不是一個好主意,除非你真的知道你在做什麼。我認爲你的情況很好。

+0

保存我的生活@Tim – Jel

0

要添加到Tim的答案 - 原始代碼(在第17行左右)是有效的Verilog。

就是它的意思是「只要有上clk上升沿或rst_n下降沿,檢查clockHandler做點什麼」(順便說一下,擺脫了開始/結束;他們是多餘的,冗長的)。當你想在真實的硬件中實現這個問題時,問題就出現了,所以錯誤消息大概來自合成器,這需要比有效的Verilog更多的東西。合成器懷疑它必須構建某種類型的同步元素,但它不能(或者不會精確地)處理在邊緣處被檢查的情況,這兩種情況都是clkrst_n。按照合成模板的規則,你不會得到這個問題。

+2

一個常見的錯誤是擴展一個if語句,可能只是包含'$ display'並忘記添加'begin ... end'。乍一看,所有代碼都看起來不錯,但是現在只有第一行被包含在條件中。我總是建議添加'begin .. end'語句,但不會增加太多額外的行,並且正確縮進。 – Morgan

0

這是一個編譯錯誤或綜合錯誤?我使用相同的代碼來查看它是否編譯正常,並且我得到錯誤。此外,建議在同步塊內使用「< =」而不是「=」

0

您正在使用相同的觸發器構造爲兩個不同的事情。線性代碼會導致狀態滑動。如果狀態依賴於時鐘或重置,我總是將所有內容放在一個構造中,否則需要額外的步驟來確保多個信號不會嘗試改變您的狀態。

在翻譯結構中,你也不需要開始/結束,Verilog知道如何爲你處理。我相信Verilog雖然可以,但我通常不這麼做。在塊中使用單個語句時,您也不必使用它。

所以,你的第一個模塊是這樣的(如果我錯過了一個塊地方只是讓我知道):

clock_divider。v模塊(編輯)

module clock_divider (clockHandler, clk, rst_n, clk_o); 

parameter DIV_CONST = 10000000 ; // 1 second 
parameter DIV_CONST_faster = 10000000/5; 
input clockHandler; 
input clk; 
input rst_n; 

output reg clk_o; 

reg [31:0] div; 
reg en; 
integer div_helper = 0; 

always @ (posedge clk or negedge rst_n) 
begin 
    if(!rst_n) 
    begin 
     div <= 0; 
     en <= 0; 
     clk_o <= 1'b0; 
    end 
    else if(en) 
    begin 
     clk_o <= ~ clk_o; 

     if(clockHandler == 0) 
     begin 
      div_helper = DIV_CONST; 
     end 
     else 
     begin 
      div_helper = DIV_CONST_faster; 
     end 
     else 
     begin 
      if (div == div_helper) 
      begin 
       div <= 0; 
       en <= 1; 
      end 
     end 
     else 
     begin 
      div <= div + 1; 
      en <= 0; 
     end 
    end 
end 
end module 

如果clk_o並不意味着在同一時間與其他業務發生地處理,那麼你可以單獨一切與一般的「別人」的語句。只要確保將第二個構造嵌套爲if語句以檢查您的狀態。

還記得像Tim提到的那樣,總是將@(posedge clk或negedge rst_n)添加到main.v模塊中。