2017-12-03 56 views
0

我正在調試一段Verilog代碼,特別是從FX2LP(Cypress CY7C68016A)USB控制器發送和接收字節。沒有進入許多細節,數據在每個週期中按字節發送和傳輸。對於我的測試,我使用了一個16字節的緩衝區,我首先填充然後傳回(回波測試)。順序模塊中的位移失敗,組合不成功。爲什麼?

我的代碼的顯著部分看起來像:

reg [127:0] dataBuf; // 16 byte buffer for USB data 

reg [7:0] cntByte; // counter for number of bytes 
reg [7:0] nextCntByte; 

reg shiftBufRx, shiftBufTx; // flags whether buffer should be shifted 
reg [7:0] currentByte; // current read byte 

// in transmit cycle, byte is read from USB_DATAOUT 
assign USB_DATAOUT = dataBuf[7:0]; 

always @(posedge FIFO_CLK) begin 
    // update state variables 
    CurrentState <= NextState; 
    cntByte <= nextCntByte; 

    if(shiftBufRx) begin // cycle was a receive 
     dataBuf <= { currentByte , dataBuf[127:8] }; 
    end 
    if(shiftBufTx) begin // cycle was a transmit 
     dataBuf <= { dataBuf[127-8:0] , 8'h00 }; 
    end 
end 

always @(*) begin 
    // avoid race conditions 
    NextState = CurrentState; 
    nextCntByte = cntByte; 
    nextDataBuf = dataBuf; 
    currentByte = 0; 
    shiftBufRx = 0; 
    shiftBufTx = 0; 

    case(CurrentState) 
     [...] 
     STATE_USBRX: begin 
      if(cntByte < 16) begin 
       nextCntByte = cntByte + 1; 
       currentByte = USB_DATAIN; // contains received byte in receive cycle 
       shiftBufRx = 1; // shift buffer after this cycle 
      end 
      [...] 
     end 
     STATE_USBTX: begin 
      if(cntByte < 15) begin 
       shiftBufTx = 1; // shift buffer after this cycle 
       nextCntByte = cntByte + 1; 
      end 
      [...] 
     end 
     [...] 
    endcase 
end 

此代碼工作完美地模擬(iVerilog)。但是當在Altera Cyclone上進行綜合和執行時,我會遇到非常奇怪的錯誤。例如,大多數情況下,每個字節讀取傳輸到FPGA的第一個字節。例如,發送11 22 33 44 55 66 ...將收到11 11 11 11 11 11 ...

現在,當我代替引入新的變量:

reg [127:0] nextDataBuf; 

和在順序always @(posedge FIFO_CLK)塊與更換部分:

if(shiftBufRx) begin 
    dataBuf <= nextDataBuf; 
end 
if(shiftBufTx) begin 
    dataBuf <= nextDataBuf; 
end 

,並在組合部分:

 STATE_USBRX: begin 
      if(cntByte < 16) begin 
       nextCntByte = cntByte + 1; 
       //currentByte = FIFO_DATAIN; 
       nextDataBuf = { dataBuf[127-8:0] , FIFO_DATAIN }; 
       shiftBufRx = 1; 
      end 
      [...] 
     end 
     STATE_USBTX: begin 
      if(cntByte < 15) begin 
       shiftBufTx = 1; 
       nextCntByte = cntByte + 1; 
       nextDataBuf = { 8'h00 , dataBuf[127:8] }; 
      end 
      [...] 
     end 

然後它工作!

這意味着:我所做的只是將寄存器從順序塊移到組合塊。

我的代碼和仿真(iVerilog)中看不到任何競態條件,兩個版本都是相同的。

可能是什麼原因?

+0

檢查Tx/Rx標誌之間的關係。如果兩者同時出現,可能會發生奇怪的唱歌。 – Serge

+0

您的數據結構不匹配。 '{dataBuf [127-8:0],8'h00}'!='{8'h00,dataBuf [127:8]}' – Greg

回答

0

首先你應該肯定發帖MVCE。這幾乎是一個MVCE,但它不包含測試平臺,省略號隱藏了可能相關的事情,例如從RX到TX的狀態轉換。

從來沒有,因爲它接近,我建立了一個小測試臺,並添加了一些最低限度的代碼讓它運行。在我的情況下,它確實不是工作「完美的模擬」。實際上,正如@greg指出的那樣,移位寄存器存在明確的錯誤。

在你以前的代碼中,你將左移出寄存器,但正在傳輸低字節。第一個循環是8'h11,隨後將是8'h00或保持不變,這取決於shiftBufTx是否爲真,並且這取決於未發佈的邏輯。有足夠的張貼,看看它不可能正常工作。

assign USB_DATAOUT = dataBuf[7:0]; 
    ... 
    if(shiftBufTx) begin // cycle was a transmit 
     dataBuf <= { dataBuf[127-8:0] , 8'h00 }; 
    end 

在代碼後,你正在轉變,這就是爲什麼它的工作原理:

nextDataBuf = { 8'h00 , dataBuf[127:8] }; 

這可能是SIM卡沒有類似的原因匹配的合成。代碼看起來相當合成。幾點建議:

  • 沒有理由對Tx和Rx
  • 作爲@serge獨立的旗幟指出,會發生什麼,如果他們發生衝突?這可能會模擬好,但不是工作在硬件。
  • 您可以使用一個標誌並將其設置在每個狀態的輸出中。
  • 如果你需要不止一個條件,你必須有一個保證,只有一個路徑可以修改其他每個非阻塞賦值給一個變種是活躍在任何時鐘邊沿:

    if(shiftBufRx) begin // cycle was a receive 
        dataBuf <= { currentByte , dataBuf[127:8] }; 
    end 
    **else** if(shiftBufTx) begin // cycle was a transmit 
        dataBuf <= **{ 8'h00 , dataBuf[127:8] }**; 
    end 
    

爲什麼它似乎在SIM卡中工作?除了小小的錯別字或者所謂相同的代碼轉換之外,sim對於同一個var的多次寫入是非常寬容的(後者會「贏」)。

但綜合工具必須將你的意圖轉化爲註冊表。根據邏輯的複雜程度,它可能無法知道兩個標誌不能同時爲真。有時它會將這樣的事情解釋爲dataBuf的兩個並行「寫入使能」條件,並創建兩個並行寄存器。第二個副本在被設置爲符合症狀的8'h11之後可能從未被移出。完成後應檢查實際輸出電路以檢測此類錯誤。不幸的是,並非所有這些都失敗了,甚至沒有給出明顯的警告在Xilinx Vivado中,您可以拉出原理圖。

相關問題