Verilogで順序回路を書く

(1)ここで学ぶ内容

もふねこ

ここでは、順序回路(クロックに同期して動く回路)の書き方を学ぶよ🐾
C言語などのソフト開発にはない「always文」が登場するから、しっかり理解していこう!

概要
  • バイナリカウンタの記述を例に、簡単な順序回路の記述について学ぶ
  • always 文や if 文の基本を理解する

目標

以下の項目を理解し説明できる

  • reg 宣言
  • always 文の記述
  • if 文による条件分岐
  • reg 信号への代入
  • 定数の表現

修了判定

信号名を指定して、8ビットのダウンカウンタを記述する
条件:減算演算子を用いる

(2)バイナリカウンタの動作

4ビット・バイナリカウンタ

graph LR subgraph 4ビット・バイナリカウンタ CNT[counter

► ck] end RES[res] --> CNT CK[ck] --> CNT CNT -->|4| Q[q
4bit] style CNT fill:#e8f5e9,stroke:#388e3c,stroke-width:2px;


q[3]q[2]q[1]q[0]
0 0 1 0
 ck      ┐  ┌┐  ┌┐  ┌┐  ┌┐  ┌┐  ┌┐
         └──┘└──┘└──┘└──┘└──┘└──┘└
                    
 res     ┌──┐       
         └──┘       
                    
 q       | 0   | 1   2  | 3  | 4  | 5
                    
 q[0]  ██┐     ┌────    ┌────┐    ┌
         └─────┘    ────┘    └────┘
                    
 q[1]  ██┌────┐        ┌
         └──────────┘    └────────┘
                    
 q[2]  ██          ┌────
         └────────────────────┘
                    
 q[3]  ██
         └─────────────────────────
                    

※赤色ブロック(██)はリセット前の不定(Undefined)状態を示します。
※赤い縦線は q=2 (0 0 1 0) の瞬間を示しています。

(3)バイナリカウンタの記述

4ビット・バイナリカウンタ

graph LR subgraph 4ビット・バイナリカウンタ CNT[counter

► ck] end RES[res] --> CNT CK[ck] --> CNT CNT -->|4| Q[q
4bit] style CNT fill:#e8f5e9,stroke:#388e3c,stroke-width:2px;

加算演算子による4ビットカウンタ(非同期リセット)

module counter( ck, res, q );
input           ck, res;
output  [3:0]   q;
reg     [3:0]   q;

always @( posedge ck or posedge res )
begin
        if ( res==1'b1 )
                q <= 4'h0;
        else
                q <= q + 4'h1;
end

endmodule

(4)ワンポイント・アドバイス

もふねこ

ここは超重要!『regとalways文はペア』『代入記号は <= (ノンブロッキング代入) を使う』🐾
これらはVerilogのルールの中でも特にバグを生みやすいポイントだから、しっかり覚えておいてね!

  • 順序回路の記述には always 文を使う。
  • 「regとalways文はペア」と覚えておこう。
    regへの代入は、always文の中で行う。
    wireへの代入は、always文の中では文法エラー。
  • regへの代入記号は "<=" を使おう。
    "=" も文法上使えるが、不具合の原因にもなる。(詳細はO2ユニット参照)
    ただし、シミュレーション記述(テストベンチ)の時は、逆に "=" の方がよい。

回路記述

reg Q;
always @( posedge CK ) begin
    Q <= D;
end

シミュレーション記述(テストベンチ)

initial begin
        reset = 0;
    #STEP reset = 1;
    #STEP reset = 0;
end

📝 (補足)修了判定について

元の教材の(1)で言及されていた「修了判定」の設問は、E2ユニット用の画像(img_04相当)としては用意されていませんでしたが、内容は以下の通りです。

設問

信号名を指定して、8ビットのダウンカウンタを記述する。
条件:減算演算子を用いる。

module down_counter( ck, res, q );

input           ck, res;
output  [7:0]   q;
reg     [7:0]   q;

always @( posedge ck or posedge res )
begin
        if ( res==1'b1 )
                q <= 8'h00;
        else
                q <= q - 8'h01;
end

endmodule
🌸
たいへん
よく
できました