2013-06-05 62 views
2

我遇到了一個綜合性問題,如果我在if語句中有兩個變量,綜合將會失敗(帶有誤導性和無用的錯誤消息)。Verilog綜合失敗,如果包含兩個變量的語句

下面給出

case(state) 
//other states here 
GET_PAYLOAD_DATA: 
     begin 
       if (packet_size < payload_length) begin 
        packet_size <= packet_size + 1; 
        //Code to place byte into ram that only triggers with a toggle flag 
        next_state = GET_PAYLOAD_DATA; 
       end else begin 
        next_state = GET_CHKSUM2; 
       end 
end 

我合成過程中得到的賽靈思ISE錯誤代碼片段:

ERROR:Xst:2001 - Width mismatch detected on comparator next_state_cmp_lt0000/ALB. Operand  A and B do not have the same size. 

錯誤聲稱next_state是不正確的,但如果我拿出payload_length併爲其分配一個靜態值,它工作得很好。由於packet_size和payload_length都是整型,所以它們的大小相同,這不是問題。因此,我認爲它與循環不能在硬件中實現類似的問題,除非它是一個具有已定義結束的靜態循環。但是,如果語句應該工作,因爲它只是2個二進制值之間的比較器。

我在這裏試圖做的是當我的模塊接收到一個字節時,它將被添加到RAM中,直到達到整個有效負載的大小(我從早期的分組數據中獲得),然後改變到另一個狀態來處理校驗和。由於數據一次只能進入1個字節,因此我會多次調用該狀態,直到計數器達到極限,然後將下一個狀態設置爲其他值。

那麼我的問題是,我如何獲得調用我的狀態的同樣結果並重復,直到計數器達到有效負載的長度而不出現錯誤?

編輯:的 片段PACKET_SIZE和payload_length如何聲明,如在意見要求

integer payload_length, packet_size; 

initial begin 
    //other stuff 
    packet_size <= 0; 
end 

always @ (posedge clk) begin 
    //case statements with various states 
    GET_PAYLOAD_LEN: 
     begin 
      if (rx_toggle == 1) begin 
       packet_size <= packet_size + 1; 
       addr <= 3; 
       din <= rx_byte_buffer; 
       payload_length <= rx_byte_buffer; 
       next_state = GET_PAYLOAD_DATA; 
      end else begin 
       next_state = GET_PAYLOAD_LEN; 
      end 
     end 

rx_byte_buffer是我的模塊接收作爲寬度爲8位的輸入數據的寄存器,而packet_size增量在各您在上面看到的那臺機器的其他狀態。

我通過切換if語句的條件來解決錯誤,但仍然想明白爲什麼會改變任何東西。

+0

'state'和'next_state'的位範圍是多少? 'GET_PAYLOAD_DATA'和'GET_CHKSUM2'的值是什麼? – Greg

+0

狀態和next_state是4位(reg [3:0]狀態,next_state),並且GET_PAYLOAD_DATA和GET_CHKSUM2是分別被指定爲4'd5和4'd7的參數。 – fysloc

+0

假設你正在使用一個組合塊和一個單獨的塊來分配觸發器,那麼'packet_size <= packet_size + 1;'應該是'next_packet_size = packet_size + 1;'保持阻塞是一個好習慣('=' )和非阻塞('<=')賦值在總是單獨的塊中。清理它,讓我們知道這是否有幫助。 – Greg

回答

1

有些錯誤馬上就會出現在代碼中,雖然它們可能無法解決這個問題,但它們需要更正,因爲它會導致仿真和硬件測試的不同。

下一個狀態邏輯需要位於一個不會根據時鐘邊界而改變的總是不同的塊中。敏感性列表需要包含諸如「狀態」和/或「*」之類的內容。如果你希望下一個狀態的邏輯被註冊爲現在的狀態(你不這樣做),你應該使用一個非阻塞的任務,這在下面提供的cummings文件中有很詳細的描述。

http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA_rev1_2.pdf

代碼應該是這個樣子:

always @ (*) begin 
    //case statements with various states 
    GET_PAYLOAD_LEN: 
     begin 
      if (rx_toggle == 1) begin 
       packet_size_en = 1'b1; 
    //these will need to be changed in a similar manner 
       addr <= 3; 
       din <= rx_byte_buffer; 
       payload_length <= rx_byte_buffer; 
    ///////////////////////////////////////////////////// 
       next_state = GET_PAYLOAD_DATA; 
      end else begin 
       next_state = GET_PAYLOAD_LEN; 
      end 
     end 

[email protected](posedge clk) begin 
    if(pcket_size_en) 
     packet_size <= packet_size +1 ; 
end 

而且,我想嘗試的第一件事就是讓這些規定的長度,使它們類型REG的(我假設你不會需要一個有符號的數字,所以它在模擬上應該沒有什麼區別),除了生成塊之外,你應該儘量不要讓綜合玩弄整數。

+1

組合塊應該只使用阻塞分配。請參閱所引用論文的第11部分。一個好的做法是使用「next」作爲前綴(或後綴)給網絡名稱分配一個翻牌。例如'addr <= next_addr;' – Greg