41
35

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Verilog wireとregの使い分け

Last updated at Posted at 2018-04-22

はじめに

FPGAの授業の補助資料として入門したての頃に詰まったポイント、早く知っていればよかったなというポイントをいくつかまとめて記事にします。
今回はVerilogを書き始めたときに詰まったwireとregの使い分けです。

wireとreg

Verilogのデータ型として主に用いるのはwire(ネット型)とreg(レジスタ型)です。

wireは配線に対応し組み合わせ回路の記述に使えますが、regは記述の仕方によって組み合わせ回路になったり順序回路であるFFやラッチになったりします。

文法的には

  • wire: assign文でのみ代入可能
  • reg: always文やfunction文などで代入可能

という違いがあります。

個人的ですが、使い分けとしては

  1. 順序回路を作りたいとき
    regを使いalways文で記述
  2. 単純な組み合わせ回路を作りたいとき
    wireを使いassign文で記述
  3. 複雑な組み合わせ回路のうち、入力が異なるだけでロジックが同じものを複数作りたい時
    wireを使い回路はfunction文で記述(もしくは4+module化)
  4. 複雑な組み合わせ回路のうち、再利用が考えられないもの
    regを使いalways文で記述

なお、3の場合で出力が複数ある場合は別のモジュールにして記述すると良いと思います。

以下いくつか回路記述例と合成後の実際の回路を示します。

1. 順序回路(フリップフロップやラッチ)を作りたいとき

フリップフロップの例

例えばクロックをCLK、入力をA、出力をQとして、クロック立ち上がり時にAが1の時、Qが反転するという順序回路は

module ex1(
    input wire CLK,
    input wire RST,
    input wire A,
    output reg Q
    );
    always @(posedge CLK) begin
        if(RST) Q <= 1'd0;
        else if(A)  Q <= !Q;
    end
endmodule

とかくと
image.png

のようにFFが生成されます。
always文でクロックに同期して出力の値が変わるようにイベント式に@(posedge CLK)などと記述するとFFが生成されます。

ラッチの例

ラッチを生成したい場合はイベント式に出力を変化させるのに必要な信号線をすべて列挙し@(A or Q or RST)などと書くと
image.png
のようにラッチが生成されます。

なお、always文で組み合わせ回路やラッチを作成する場合、出力に必要な信号線をすべて列挙する書き方をすると漏れがある可能性があるため@(*)という省略記法で記述することをおすすめします。

2. 単純な組み合わせ回路を作りたいとき

組み合わせ回路 assign文の例

入力A,Bの論理積を取ったものを出力Cとするとき

module ex2_1(
    input wire A,
    input wire B,
    output wire C
    );
    assign C = A & B;
endmodule

とかくと
image.png
のような回路が生成されます。

組み合わせ回路 assign文+三項演算子の例

また、好みですがwire+always+if-elseによる組み合わせ回路の代わりに三項演算子を使って条件分岐させて出力を決める組み合わせ回路もassignで記述できます。(同様の記述のalways版はこちらをご覧ください)
入力をA, B出力をC(2ビット)とし、Aが1なら0b11を、Aが0でBが1なら0b01を、そうでないなら0b00を出力するものは

module ex2_2(
input wire A,
input wire B,
output wire[1:0] C
);
assign C = A ? 2'b11 :
B ? 2'b01 :
2'b00;
endmodule

> ![image.png](https://qiita-image-store.s3.amazonaws.com/0/140084/370cfaff-c849-bd54-bcbf-9c31f1b75b93.png)
> という回路が生成されます。

## 3.複雑な組み合わせ回路のうち、入力が異なるだけでロジックが同じものを複数作りたい時  
複数の信号に対して同じ組み合わせ回路を使う場合はfunction文を使うかmodule化しておくとコードが短くなりメンテナンスがしやすいです。(コピペをするとあとでバグが見つかったときに修正漏れが生じて悪化します)

### 組み合わせ回路 function文の例
ここではR,G,B 8bit入力に対して組み合わせ回路で4値化し、4値化結果をくっつけて出力O(6bit)とします。

4値化の基準は以下のとおりです

|入力|出力|
|:--:|:-:|
|8'd0|2'b00|
|8'd1~8'd63|2'b01|
|8'd64~8'd127|2'b10|
|8'd128~8'd255|2'b11|

```verilog
module ex3(
    input [7:0] R,
    input [7:0] G,
    input [7:0] B,
    output [5:0] O
    );
    function [1:0] convert(input [7:0] p);
    begin
        if(p == 8'd0) convert = 2'b00;
        else if(p <= 8'd63) convert = 2'b01;
        else if(p <= 8'd127) convert = 2'b10;
        else convert = 2'b11;
    end
    endfunction
    wire [1:0] r_4 = convert(R);
    wire [1:0] g_4 = convert(G);
    wire [1:0] b_4 = convert(B);
    assign O = {r_4, g_4, b_4};
endmodule

生成さた回路を見てみると下図のように各色ごとに同じような回路が生成されていることがわかります。
bitmap.png

4. 複雑な組み合わせ回路のうち、再利用が考えられないもの

複雑な組み合わせ回路のうち1箇所でしか使わない、もしくは複数箇所で使われるがモジュール化する場合は好みですが、個人的にはalways+regで書く事が多いです。

組み合わせ回路 always文の例

2で示した回路と同様のものをalways文で記述してみます。

module ex4_1(
    input wire A,
    input wire B,
    output reg [1:0] C
    );
    always @(*) begin
        if (A) C <= 2'b11;
        else if(B) C <= 2'b01;
        else C <= 2'b00;
    end
endmodule

この方法で組み合わせ回路を記述する際は

  • イベント式に内部で使うものすべてを列挙するか*を使う
  • すべての条件でregに代入する(regの値を代入しない条件が生じる場合、値を保持する必要があると判定されてラッチが生成されます。)

の2点に注意してください。

生成された回路は以下のようになります。
image.png

2で示した回路より最適化されたものが生成されました。

組み合わせ回路 always文+module化したものを利用する例

3で示した回路の4値化部分をconvertモジュールにし、モジュールを利用する例を次に示します。

module convert(
    input [7:0] p,
    output reg [1:0]  o
);
    always @(*) begin
        if(p == 8'd0) o <= 2'b00;
        else if(p <= 8'd63) o <= 2'b01;
        else if(p <= 8'd127) o <= 2'b10;
        else o <= 2'b11;
    end
endmodule

module ex4_2(
    input [7:0] R,
    input [7:0] G,
    input [7:0] B,
    output [5:0] O
    );
   
    wire [1:0] r_4;
    wire [1:0] g_4;
    wire [1:0] b_4;
    convert r_c(R, r_4);
    convert g_c(G, g_4);
    convert b_c(B, b_4);
    assign O = {r_4, g_4, b_4};
endmodule

のように上位モジュールでconvertモジュールを複数記述してあげて利用することも出来ます。
この場合も3で示した回路と同じような回路が生成されます。
image.png
bitmap.png

41
35
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
41
35

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?