2 Stimmen

Verhindern von Latches in Verilog-Case-Anweisungen

Ich habe Schwierigkeiten zu verstehen, wie ich verhindern kann, dass Latches in einem Verilog-Projekt erstellt werden. Ich verstehe, dass Latches erzeugt werden, weil ich nicht festlege, was mit allen Signalen innerhalb jeder Case-Anweisung geschieht. Ich weiß jedoch nicht, ob es eine Möglichkeit gibt, dies zu vermeiden (abgesehen von der drakonischen Methode, die ich im Moment angewendet habe).

Ich habe derzeit zwei Schieberegister, register X y register R . Jedes dieser Schieberegister verfügt über einen 5-Bit breiten Steuerbus, der von einer endlichen Zustandsmaschine gesteuert wird. Um die Verwaltung dieser Schieberegister zu vereinfachen, hoffte ich, bitweise Operationen zum Setzen und Löschen von Steuerbusbits verwenden zu können.

Zum Beispiel, im Staat done muss ich die Option shiftRight Bit für register R . Zu diesem Zweck kann ich die folgende bitweise Operation durchführen:

rRegisterControlBus = rRegisterControlBus & ~register_ctrl_shiftRight;

Das funktioniert perfekt. Unten sehen Sie alle Signale und bitweisen Operationen, die ich für den Registersteuerungsbus definiert habe. Da ich jedoch nicht alle Registersteuerungsbusse für beide Register in jedem Zustand ändern muss, erhalte ich Latches. Zum Beispiel, im Zustand done unten, muss ich nur den Registersteuerungsbus für register R . Infolgedessen wird eine Verriegelung erstellt für register X Steuerbus.

Im Moment habe ich dieses Problem gelöst, indem ich einfach alle Bits für beide Registersteuerungsbusse in jedem Zustand des Zustandsautomaten gesetzt habe und meine Idee, bitweise Operationen an den Signalen durchzuführen, verworfen habe.

Allerdings glaube ich, dass die Bitwise-Operation-Methode sauberer ist - ich würde gerne wissen, ob es irgendwie für mich, um diese Methode ohne Umgang mit Latches weiter zu verwenden. Es macht den Code viel einfacher zu lesen und zu ändern.

Wie immer danke ich für jede Hilfe.

// Register Control Bus Signals
// bit # - purpose
// 0 - reset (rst)
// 1 - load (ld)
// 2 - shift left (sl)
// 3 - shift right (sr)
// 4 - auxilary 1 (mux select)
parameter register_ctrl_reset = 5'b00001;
parameter register_ctrl_load = 5'b00010;
parameter register_ctrl_shiftLeft = 5'b00100;
parameter register_ctrl_shiftRight = 5'b01000;
parameter register_ctrl_auxilary = 5'b10000;
parameter register_ctrl_width = 5;
output reg [register_ctrl_width-1:0] xRegisterControlBus;
output reg [register_ctrl_width-1:0] rRegisterControlBus;

Vorherige Lösung:

always@(currentState, ryCompareOut)
begin
  case(currentState)
   shiftRight:
   begin
     rRegisterControlBus = rRegisterControlBus & ~register_ctrl_shiftLeft;
     xRegisterControlBus = xRegisterControlBus & ~register_ctrl_shiftLeft;
     rRegisterControlBus = rRegisterControlBus | register_ctrl_shiftRight;
   end

   done:
   begin
    rRegisterControlBus = rRegisterControlBus & ~register_ctrl_shiftRight; 
   end

  endcase
end

3voto

Marty Punkte 6234

Dies ist Verilog - Sie können direkt auf die Bits zugreifen. Vielleicht ändern Sie Ihre Parameter in Bit-Indizes:

module case_statements
    #( parameter REGISTER_CTRL_WIDTH = 5 )
    (
     input [3:0] currentState,
     output reg [REGISTER_CTRL_WIDTH-1:0] xRegisterControlBus,
     output reg [REGISTER_CTRL_WIDTH-1:0] rRegisterControlBus
     );

localparam REGISTER_CTRL_RESET = 0;
localparam REGISTER_CTRL_LOAD = 1;
localparam REGISTER_CTRL_SHIFTLEFT = 2;
localparam REGISTER_CTRL_SHIFTRIGHT = 3;
localparam REGISTER_CTRL_AUXILARY = 4;

localparam STATE_SHIFTLEFT = 0;  // or enum, maybe?
localparam STATE_SHIFTRIGHT = 1;
localparam STATE_DONE = 2;

always@(*)
  begin
      // Defaults:
      rRegisterControlBus = 5'd0; // or whatever
      xRegisterControlBus = 5'd0;

      // Special cases:
      case(currentState)
        STATE_SHIFTRIGHT:
          begin
              rRegisterControlBus[REGISTER_CTRL_SHIFTRIGHT] = 1'b1;
          end
        STATE_SHIFTLEFT:
          begin
              rRegisterControlBus[REGISTER_CTRL_SHIFTLEFT] = 1'b1;
          end
        STATE_DONE:
          begin
              rRegisterControlBus[REGISTER_CTRL_SHIFTRIGHT] = 1'b0;
              rRegisterControlBus[REGISTER_CTRL_SHIFTLEFT] = 1'b0;
          end
      endcase
  end

Um Latches zu vermeiden, und um zu vermeiden, dass ich jede Menge Verilog schreiben muss, um sicherzustellen, dass jeder logische Zweig alle Variablen setzt, verwende ich eine Technik, deren Namen ich nicht kenne!

Die Idee ist, dass Sie alle Variablen, denen Sie zuweisen, innerhalb einer always Verfahren zu Beginn auf eine Reihe vernünftiger "Standardwerte" festlegen. Dann können Sie alle Abweichungen von diesen Vorgaben als Sonderfälle behandeln und müssen sich nicht darum kümmern, dass alle Ihre Variablen in allen Zweigen Ihres Codes gesetzt sind - sie erhalten den "Standardwert".

0voto

Rich Maes Punkte 1144

Diese Art von Zeile ist für eine kombinatorische Aussage nicht geeignet.

rRegisterControlBus = rRegisterControlBus & ~register_ctrl_shiftLeft;

Die Eingabe wirkt sich in dieser Zeile kombinatorisch auf die Ausgabe aus. Das Werkzeug erkennt dies und meldet Ihnen, dass es ein Problem gibt. Um das Problem zu verdeutlichen und um zu zeigen, worüber sich das Tool Sorgen macht, stellen Sie sich vor, ich würde schreiben:

always (*)
begin  
my_sig = ~my_sig;
end

Kombinatorisch gesehen will das Signal immer invertieren, und zwar mit der Geschwindigkeit der logischen Fortpflanzung. Ich habe gerade einen Oszillator gebaut, weil er nie in einen Ruhezustand kommen wird. Die Tools wissen, dass dies wahrscheinlich nicht erwünscht ist, und lassen mich das wissen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X