2012-04-05 99 views
2

我有一個問題,關於我在工作的AGC/SPI控制器的奇怪行爲。它在Verilog中完成,針對Xilinx Spartan 3e FPGA。控制器是依靠外部輸入啓動的FSM。 FSM的狀態存儲在state_reg中,未被明確初始化,因爲我認爲未初始化的寄存器將默認爲零。當我實施控制器時,FSM不會運行。監測SPI總線我沒有觀察到任何活動。爲了監控FSM,我將state_reg路由到一個輸出總線,該輸出總線連接到一個LED組。那是什麼行分配data_out = state_reg正在做。我發現,當我這樣做的時候,FSM的一個AGC/SPI控制器在SPI總線上正常工作。看起來發生了什麼是state_reg初始化時處於未確定狀態,因此FSM從不處於任何狀態,因此不會運行。但是,通過將state_reg分配給輸出,它將其初始化爲,正如我預料的那樣從一開始。所以我的問題是,未初始化的寄存器應該假設值爲0嗎?通過將一個未初始化的寄存器分配給輸出,是否強制它假設爲零?或者是我不明白的其他事情呢?以下是我的代碼。我已經評論了* state_reg **分配給輸出線[7:0] data_out的相關部分。我知道這是一個長期的問題,但我的「M真的想了解我應該期待什麼類型的行爲由於Verilog,FPGA,使用單位寄存器

module agc_control 
     (
      input wire [7:0] agc_data, 
      input wire clk, 
      input wire agc_start, 
      input wire AMP_DO, 
      output reg MOSI, 
      output reg SCK, 
      output reg CS_AMP, 
      output wire inhibit_ADC, 
      output wire [7:0] data_out 
     ); 

     //signals 
     reg [4:0] state_reg, 
     reg [2: 

0] ampclkreg; 
    reg ampclk; 
    reg [7:0] agc_data_reg; 
    reg agc_running; 
    reg [7:0] data_out_reg; 
    wire agc_done; 




    //ampclk generation 
    always @(posedge clk) 
     begin 
      ampclkreg = ampclkreg + 1; 
      if (ampclkreg == 3) 
       begin 
        ampclkreg = 0; 
        ampclk = ~ampclk; 
       end 
     end 

    always @(posedge clk) 
     begin 
      if(agc_start == 1) 
       begin 
        agc_running = 1'b1; 
        agc_data_reg = agc_data; 
       end 
      if(agc_done == 1) 
       begin 
        agc_running = 1'b0; 
       end 
     end 



    //FSM 
    always @(posedge ampclk) 
     begin 
      if (agc_running == 0) 
       begin 
        SCK = 0; 
        state_reg = 0; 
        CS_AMP = 1; 
       end 
      if (agc_running == 1) 
       begin 
        case (state_reg) 
         0: begin 
           CS_AMP = 1; 
           SCK = 0; 
           state_reg = 1; 
          end 
         1: begin 
           CS_AMP = 0; 
           MOSI = agc_data_reg[7]; 
           state_reg = 2; 
          end 
         2: begin 
           SCK = 1; 
           state_reg = 3; 
          end 
         3: begin 
           SCK = 0; 
           MOSI = agc_data_reg[6]; 
           state_reg = 4; 
          end 
         4: begin 
           SCK = 1; 
           state_reg = 5; 
          end 
         5: begin 
           SCK = 0; 
           MOSI = agc_data_reg[5]; 
           state_reg = 6; 
          end 
         6: begin 
           SCK = 1; 
           state_reg = 7; 
          end 
         7: begin 
           SCK = 0; 
           MOSI = agc_data_reg[4]; 
           state_reg = 8; 
          end 
         8: begin 
           SCK = 1; 
           state_reg = 9; 
          end 
         9: begin 
           SCK = 0; 
           MOSI = agc_data_reg[3]; 
           state_reg = 10; 
          end 
         10:begin 
           SCK = 1; 
           state_reg = 11; 
          end 
         11:begin 
           SCK = 0; 
           MOSI = agc_data_reg[2]; 
           state_reg = 12; 
          end 
         12:begin 
           SCK = 1; 
           state_reg = 13; 
          end 
         13:begin 
           SCK = 0; 
           MOSI = agc_data_reg[1]; 
           state_reg = 14; 
          end 
         14:begin 
           SCK = 1; 
           state_reg = 15; 
          end 
         15:begin 
           SCK = 0; 
           MOSI = agc_data_reg[0]; 
           state_reg = 16; 
          end 
         16:begin 
           SCK = 1; 
           state_reg = 17; 
          end 
         17:begin 
           CS_AMP = 1; 
           state_reg = 18; 
          end 
         18:begin 
           SCK = 0; 
           state_reg = 19; 
          end 
         19:begin 
           state_reg = 19; 
          end 
        default: state_reg = 19; 
       endcase 
      end 
     end 

    //retrieve previous vlaues 
    always @(posedge clk) 
    begin 
     case(state_reg) 
      2: begin 
        if (ampclkreg == 2)    
         data_out_reg[7] = AMP_DO; 
       end 
      4: begin 
        if (ampclkreg == 2) 
         data_out_reg[6] = AMP_DO; 
       end 
      6: begin 
        if (ampclkreg == 2) 
         data_out_reg[5] = AMP_DO; 
       end 
      8: begin 
        if (ampclkreg == 2) 
         data_out_reg[4] = AMP_DO; 
       end 
      10:begin 
        if (ampclkreg == 2) 
         data_out_reg[3] = AMP_DO; 
       end 
      12:begin 
        if (ampclkreg == 2) 
         data_out_reg[2] = AMP_DO; 
       end 
      14:begin 
        if (ampclkreg == 2) 
         data_out_reg[1] = AMP_DO; 
       end 
      16:begin 
        if (ampclkreg == 2) 
         data_out_reg[0] = AMP_DO; 
       end 

     endcase 
    end 


    //output wire [7:0] data_out--to top module to drive 7 LEDs and display state_reg 
    assign data_out = state_reg; 

    assign agc_done = (state_reg == 19); 
    assign inhibit_ADC = (agc_running == 1); 


    endmodule 
+0

對於FPGA設計,始終始終始終初始化您的寄存器。 – 2012-04-06 18:39:38

+0

初始化寄存器時是否會得到相同的奇怪結果?我仍然好奇什麼可能會導致這種奇怪的行爲 - 通常如果你沒有指定,工具將默認爲0我認爲。 – Josh 2012-04-06 19:42:38

回答

9

我在FPGA中的情況下回答(我與賽靈思FPGA最有經驗);我不同意Tim的答案。

當FPGA進行編程和初始化,許多內部資源被初始化到已知狀態。這包括所有觸發器和塊RAM。通過在整個設計中加入毯復位邏輯,你可能使它比它需要顯着更復雜,如果你可以指望內部元件初始化。轉向已知的狀態。高扇出重置網絡可以讓你的設計的實現對於路由器來說更加困難,並且將你的設計映射到切片中也會因你選擇的重置 - 特別是異步重置而變得複雜。

我的建議:你的寄存器

  • 使用初始化值。請仔細檢查您使用的版本的Xilinx XST文檔以獲取支持的語法。與廣泛持有的觀點相反,在大多數情況下,初始化值將得到遵守。這樣做的副作用是,芯片的初始狀態將與您的仿真的初始狀態相匹配。
  • 只復位必要的控制信號並保留數據路徑寄存器,以允許更高效的映射(例如,將流水線移入移位寄存器)。
+1

你說得很好,我沒有意識到默認值在FPGA上得到了廣泛的支持。我讓我的ASIC體驗雲我的判斷:) – Tim 2012-04-06 17:08:52

+2

作爲參考,這也包含在賽靈思白皮書:http://www.xilinx.com/support/documentation/white_papers/wp272.pdf – sonicwave 2012-04-07 09:58:22

0

所以我的問題是,未初始化寄存器應該爲0的 價值?

,他們假設x。對於綜合,您必須重置,因爲它們可能會保留任何值。我沒有FPGA經驗,但Nathan Farrington建議他們也重置/初始化。

對於FPGA執行以下操作應該是足夠了:

reg [4:0] state_reg = 'b0, 

合成我建議這樣做復位子句中。

always @(posedge clk or negedge reset) begin 
    if (!reset) begin 
    state_reg <= 'b0 ; 
    end 
    else begin 
    .. 
    end 
end