簡體   English   中英

我的 Verilog 行為代碼得到正確模擬,但在 FPGA 上沒有按預期工作

[英]My Verilog behavioral code getting simulated properly but not working as expected on FPGA

我使用狀態機概念為展位乘數(基數 2)編寫了一個行為程序。 我在使用modelsim的程序模擬過程中得到了正確的結果,但是當我將它移植到fpga(spartan 3)時,結果並不如預期。

我哪里錯了?

module booth_using_statemachine(Mul_A,Mul_B,Mul_Result,clk,reset);

input Mul_A,Mul_B,clk,reset;
output Mul_Result;
wire [7:0] Mul_A,Mul_B;
reg [7:0] Mul_Result;


reg [15:0] R_B;
reg [7:0] R_A;
reg prev;
reg [1:0] state;
reg [3:0] count;

parameter start=1 ,add=2 ,shift=3;
always @(state)
begin

case(state)
 
  start:
   begin
      R_A   <= Mul_A;
      R_B   <= {8'b00000000,Mul_B};
      prev  <= 1'b0;
      count <= 3'b000;
      Mul_Result <= R_B[7:0];
     end
     
   add:
   begin
    
     case({R_B[0],prev})
            
         2'b00:
           begin
             prev <= 1'b0;
            end
         
         2'b01:
           begin
             R_B[15:8] <= R_B[15:8] + R_A;
         prev      <= 1'b0;
            end
         
         2'b10:
         begin
              R_B[15:8] <= R_B[15:8] - R_A;
              prev      <= 1'b1;
             end
         
         2'b11:
            begin
              prev <=1'b1;
             end
        
        endcase
        
    end
  
  shift:
   begin
     R_B  <= {R_B[15],R_B[15:1]};
     count <= count + 1;
    end
    
endcase
    
     
end  
     

  always @(posedge clk or posedge reset)
  begin
 
   if(reset==1)
      state <= start;
    
    else
      begin
       
        case(state)
           
            start:
              state <= add;
            
            add:
              state <= shift;
              
            
            shift:
              begin
                
                 if(count>7)
                  state <= start;
            
            else
              state <=add;
           
                end
                            
    
        
     endcase
  end
  end   
 endmodule

您的組合always阻止中的敏感度列表不完整。 改變:

always @(state)

到:

always @*

這可能是合成鎖存器。

在你的組合always阻塞中使用阻塞賦值。 <=更改為=

好的綜合和 linting 工具應該會警告您這些構造。

如果某些內容在模擬中有效但在現實中無效,請遵循以下清單:

  • 您是否已初始化每個寄存器? (是的)
  • 您是否將 2 個寄存器用於每個時鍾后傳輸的一個工作變量(否)(用於狀態 2 信號/線,例如 state 和 state_next 並在每個時鍾 state_next 后傳輸到 state)

第二點的一個例子在這里,你需要下一級邏輯,當前狀態邏輯和輸出邏輯。

有關如何為 FPGA 正確編碼 FSM 的更多信息,請參見此處(轉到 HDL 編碼技術 -> 基本 HDL 編碼技術)

你在這里有各種各樣的問題。

  1. 您的第一個 always 塊的敏感度列表不完整。 您只查看state ,但還有許多其他信號需要在那里。 如果您的工具支持它,請always @*使用always @* ,它會自動生成敏感度列表。 更改此設置,您的代碼將開始模擬,就像在 FPGA 上運行一樣。

    這隱藏了代碼的其他問題,因為它會導致信號在錯誤的時間更新。 您已經設法讓您的代碼在模擬器中運行,但這是基於謊言。 謊言是R_AR_BprevcountMul_Result依賴於狀態的變化,但有更多的信號是該邏輯的輸入。

  2. 您已經陷入了 Verilog 關鍵字reg創建寄存器的陷阱。 它沒有。 我知道這很愚蠢,但事情就是這樣。 reg意思是它是一個可以從程序塊分配的變量。 不能將wire s 分配給程序塊內部。

    當您在時鍾程序塊(參見腳注)中分配某些內容時,會創建一個寄存器,例如您的state變量。 R_AR_Bprevcount似乎都跨周期保存值,因此需要是寄存器。 我會像這樣更改代碼:

首先,我會創建一組next_*變量。 這些將包含我們在每個寄存器下一個時鍾中想要的值。

reg [15:0] next_R_B;
reg [7:0]  next_R_A;
reg        next_prev;
reg [3:0]  next_count;

然后我會更改時鍾過程以使用這些:

always @(posedge clk or posedge reset) begin

 if(reset==1) begin
   state <= start;
   R_A   <= '0;
   R_B   <= '0;
   prev  <= '0;
   count <= '0;
 
 end else begin
   R_A   <= next_R_A;
   R_B   <= next_R_B;
   prev  <= next_prev;
   count <= next_count;

   case (state)
   .....

然后最后將第一個進程更改為分配給next_*變量:

always @* begin
  next_R_A   <= R_A;
  next_R_B   <= R_B;
  next_prev  <= prev;
  next_count <= count;

  case(state)
    
    start: begin
      next_R_A   <= Mul_A;
      next_R_B   <= {8'b00000000,Mul_B};
      next_prev  <= 1'b0;
      next_count <= 3'b000;
      Mul_Result <= R_B[7:0];
    end

    add: begin

      case({R_B[0],prev})
        2'b00: begin
          next_prev <= 1'b0;
        end
        
    .....

筆記:

  • 所有寄存器現在都有一個復位
  • 任何寄存器的next_值默認為其前一個值。
  • next_值永遠不會被讀取,除了時鍾進程
  • next_值永遠不會被寫入,除非在時鍾過程中。

我還懷疑您希望Mul_Result成為一條wire並讓它assign Mul_Result = R_B[7:0]; 而不是僅在開始狀態更新的另一個寄存器,但我不確定您要在那里做什么。


  • 寄存器通常是reg ,但reg不一定是寄存器。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM