2

Verilog プロジェクト内でラッチが作成されないようにする方法がわかりません。各 case ステートメント内のすべての信号に何が発生するかを指定していないため、ラッチが作成されていることを理解しています。ただし、これを回避する方法があるかどうかはわかりません(現在使用している厳格な方法以外)。

現在、2 つのシフター レジスタregister Xregister R. これらの各シフター レジスタには、有限ステート マシンから制御される 5 ビット幅の制御バスがあります。これらのシフター レジスタの管理を容易にするために、ビット演算を使用して制御バス ビットを設定および設定解除したいと考えていました。

たとえば、 stateでは、 のビットdoneを設定解除する必要があります。これを行うには、次のビット単位の操作を実行できます。shiftRightregister R

rRegisterControlBus = rRegisterControlBus & ~register_ctrl_shiftRight;

これは完全に機能します。以下に、レジスタ制御バス用に定義したすべての信号とビット演算を示します。ただし、各状態内の両方のレジスターのすべてのレジスター制御バスを変更する必要はないため、最終的にはラッチが必要になります。たとえば、done以下の状態では、 のレジスタ制御バスを変更するだけで済みregister Rます。その結果、register X制御バスに対してラッチが作成されます。

現時点では、ステート マシンの各ステート内の両方のレジスタ制御バスのすべてのビットを設定するだけでこれを解決し、信号に対してビット単位の演算を実行するという考えを捨てました。

ただし、ビット単位の操作方法の方がクリーンだと思います。ラッチを処理せずにこの方法を使い続ける方法があるかどうかを知りたいです。これにより、コードの読み取りと変更がはるかに簡単になります。

いつものように、ご協力ありがとうございます。

// 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;

以前の解決策:

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
4

2 に答える 2

3

これは Verilog です。ビットを直接取得できます。パラメータをビットインデックスに変更するかもしれません:


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

endmodule

ラッチを回避し、各ロジック ブランチがすべての変数を確実に設定するように大量の verilog を記述する必要を回避するために、名前のわからない手法を使用しています。

アイデアは、プロシージャ内で割り当てる変数をalways、最初に合理的な「デフォルト」のセットに設定することです。次に、これらのデフォルトからの逸脱を特別なケースとして扱うことができ、コードのすべてのブランチですべての変数が設定されていることを確認することを心配する必要はありません。それらは「デフォルト」値を取得します。

于 2011-12-05T15:02:29.947 に答える