2012-04-05 19 views
2

Ich habe eine Frage zu dem, was mir seltsam Verhalten eines AGC/SPI-Controllers, an dem ich arbeite, scheint. Es wurde in Verilog erstellt und zielt auf ein Xilinx Spartan 3e FPGA ab. Der Controller ist ein FSM, der zum Starten von externen Eingängen abhängig ist. Der Status des FSM wird in state_reg gespeichert, das nicht explizit initialisiert wird, da ich dachte, dass ein nicht initialisiertes Register standardmäßig auf Null gesetzt wäre. Wenn ich den Controller implementierte, würde der FSM nicht laufen. Beim Überwachen des SPI-Busses habe ich keine Aktivität beobachtet. Um den FSM zu überwachen, route ich den state_reg an einen Ausgangsbus, der an eine LED-Bank ging. Das ist, was die Zeile zuweisen data_out = state_reg tut. Ich habe jedoch festgestellt, dass, als ich das tat der FSM ein AGC/SPI-Controller korrekt betrieben, wie auf dem SPI-Bus beobachtet. Es scheint, dass, was passiert ist, dass state_reg ist in einem unbestimmten Zustand, wenn es initialisiert und daher die FSM ist nie in einem Zustand, so dass es nicht ausgeführt wird. Aber durch Zuweisen state_reg zu einem Ausgang initialisiert es zu , wie ich es von Anfang an zu tun erwartet. Meine Frage ist also, soll ein nicht initialisiertes Register einen Wert von 0 annehmen? Wenn man einem Ausgang ein nicht initialisiertes Register zuweist, zwingt es dann dazu, Null anzunehmen, wie es schien? Oder geht hier etwas anderes vor, das ich nicht verstehe? Unten ist mein Code. Ich habe den relevanten Teil kommentiert, in dem * state_reg ** der Ausgangsleitung [7: 0] data_out zugewiesen ist. Ich weiß, dass dies eine lange Frage, aber ich "versuche wirklich zu verstehen, welche Art von Verhalten soll ich erwarten DankVerilog, FPGA, Verwendung eines vereinheitlichten Registers

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

Bei FPGA-Designs initialisieren Sie immer immer Ihre Register. –

+0

Erhalten Sie beim Initialisieren der Register dieselben ungeraden Ergebnisse? Ich bin immer noch neugierig, was dieses seltsame Verhalten verursachen könnte - normalerweise, wenn Sie nicht angeben, werden die Werkzeuge standardmäßig auf 0 gesetzt, denke ich. – Josh

Antwort

9

ich im Zusammenhang mit der FPGAs beantworten (ich die meisten Erfahrungen mit Xilinx FPGAs).. I mit Tim Antwort nicht einverstanden sind.

Wenn ein FPGA programmiert und initialisiert wird, viele internen Ressourcen in einen bekannten Zustand initialisiert werden. Dazu gehören alle Flip-Flops und Block-RAMs. Decke Reset-Logik in Ihrem Design Durch das Hinzufügen Sie kann machen es deutlich komplizierter als es sein muss, wenn Sie sonst auf interne Elemente initiieren könnten Anpassung an einen bekannten Zustand. Hohe Fanout-Reset-Netze können die Implementierung Ihres Designs für den Router erheblich erschweren, und die Zuordnung Ihres Designs zu Slices wird auch durch die Auswahl von Resets - insbesondere asynchronen - erschwert.

Meine Vorschläge:

  • Verwenden Initialisierungswerte für Ihre Register. Überprüfen Sie die Xilinx XST-Dokumentation für die Version, die Sie für die unterstützte Syntax verwenden. Entgegen weit verbreiteter Meinung werden Initialisierungswerte in den meisten Fällen berücksichtigt. Der Nebeneffekt davon ist, dass der Anfangszustand Ihres Chips mit dem Ausgangszustand Ihrer Simulation übereinstimmt.
  • Setzen Sie nur die erforderlichen Steuersignale zurück und lassen Sie Ihre Datenpfadregister in Ruhe, um ein effizienteres Mapping zu ermöglichen (z. B. eine Pipeline in ein Schieberegister).
+1

Sie machen einen guten Punkt, ich wusste nicht, dass der Standardwert auf FPGA weitgehend unterstützt wurde. Ich lasse meine ASIC-Erfahrung mein Urteilsvermögen trüben :) – Tim

+2

Als Referenz wird dies auch in einem Xilinx White Paper behandelt: http://www.xilinx.com/support/documentation/white_papers/wp272.pdf – sonicwave

0

Also meine Frage ist, ist ein nicht initialisierten Register sollte einen Wert von 0 bis nehmen?

Nein, nehmen sie x an. Für Synthesis müssen Sie zurücksetzen, da sie einen beliebigen Wert enthalten können. Ich habe keine FPGA Erfahrung, aber Nathan Farrington schlägt vor, dass sie auch zurückgesetzt werden/initialisiert werden.

Für FPGA folgendes tun sollte genug sein:

reg [4:0] state_reg = 'b0, 

zur Synthese würde ich tun dies in einem Reset-Klausel empfehlen.

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