LoginSignup
10
8

More than 5 years have passed since last update.

Verilog HDLによる組合せ論理回路の設計(授業用)

Last updated at Posted at 2016-10-15

モジュールの骨格

実習1. Half Adderの設計1

halfadder1.v を実習ボードに実装し、動作を確かめること。
入出力の割り当ては表の通りにすること。

halfadder1.v
// Top-level entity: halfadder

`default_nettype none

module halfadder( // モジュール名とポートリストを定める
  input   wire  a,
  input   wire  b,
  output  wire  c,
  output  wire  s
  );

  // 回路の機能を記述する
  assign  c = a & b;    // bitwise AND
  assign  s = a ^ b;    // bitwise XOR

endmodule
ポート I/O デバイス
a SA1 (トグルスイッチ)
b SA0 (トグルスイッチ)
c DA1 (個別LED)
s DA0 (個別LED)

設計する回路のイメージ
halfaddr.png

解説

  • Verilog HDLではモジュール単位で回路設計を行う
  • モジュール名と、モジュールへの入出力信号となるポートリストを宣言する
  • ポートリストでは入出力の方向(input/output)、ビット幅、信号名を定める
  • モジュール内で利用する信号を定める
  • 信号はwire宣言もしくはreg宣言をする
    • wire 宣言 ネット型のデータを示す(配線と考えてよい)
    • reg 宣言 レジスタ型のデータを示す
// モジュールの骨格
module module_name( // モジュール名
  // ポートリスト
  input   wire        input_signal0,    // 1bitの入力信号
  input   wire  [3:0] input_signal1,    // 4bitの入力信号
  output  wire  [7:0] output_signal,    // 8bitの出力信号
  ); // (セミコロンを忘れずに)

  // モジュール内で利用する信号の定義
  wire  [3:0] internal_signal;

  // *********************
  // 回路の機能を記述 (略)
  // *********************

endmodule // (ここはセミコロン必要なし)

assign による信号の割り当て

実習2. Half Adderの設計2

halfadder2.v を実習ボードに実装し、動作を確かめること。
入出力の割り当ては実習1と同様にすること。

halfadder2.v
// Top-level entitiy: halfadder

`default_nettype none

module halfadder( 
  input   wire  a,
  input   wire  b,
  output  wire  c,
  output  wire  s);
  // モジュール内信号定義
  wire  [1:0] sum;

  assign sum = a + b;   // 算術和
  assign {c, s} = sum;  // ビット連結 
  // sumを使わず以下でも大丈夫
  // assign {c, s} = a + b;

endmodule

解説

  • wire 宣言した出力信号、内部信号へは assign 文で配線の割当をおこなう
  • 算術演算や論理演算などの式を記述できる link

case 文による組合せ論理回路の設計

実習3. Half Adderの設計3

halfadder3.v を実習ボードに実装し、動作を確かめること。
入出力の割り当ては実習1と同様にすること。

halfadder3.v
// Top-level entitiy: halfadder
`default_nettype none

module halfadder( 
  input   wire  a,
  input   wire  b,
  output  wire  c,
  output  wire  s
  );

  reg   [1:0] sum; // always文で代入される信号はreg宣言する

  // always文
  always @ (*) begin // inputのa, bが変化した時の振舞いを記述
    // case文
    case ({a, b})
      2'b00:  sum = 2'b00;
      2'b01:  sum = 2'b01;
      2'b10:  sum = 2'b01;
      2'b11:  sum = 2'b10;
    endcase
    // case文終わり
  end 
  // always文終わり

  assign {c, s} = sum;

endmodule

解説

  • case文はalways文の中で記述する
  • case文では()内の信号についてパターンマッチングを行い、一致するところのステートメントを実行する
    • パターンマッチは上から順に行われる
    • どのパターンにも一致しない場合をまとめて記述するときはdefaultをもちいる
  • always文内での信号の割り当てはブロッキング代入(=)もしくはノンブロッキング代入(<=)で行う
    • assign文ではないことに注意する
  • always文内で代入される信号(=, <=の左辺)は、reg宣言されたものである必要がある
  • 数値はビット幅と基数を指定して表示する link

実習4. エンコーダの設計

encoder.v を実習ボードに実装し、動作を確かめること。
入出力の割り当ては下記の通りにすること。

encoder.v
// Top-level entitiy: encoder
`default_nettype none

module encoder( 
  input   wire  [3:0] data,
  output  reg   [2:0] y
  );

  always @ (*) begin
    case (data)
      4'b0001:  y = 3'b000;
      4'b0010:  y = 3'b001;
      4'b0100:  y = 3'b010;
      4'b1000:  y = 3'b011;
      default:  y = 3'b100;
    endcase
  end
endmodule
ポート I/O デバイス
data[3] SA3 (トグルスイッチ)
data[2] SA2 (トグルスイッチ)
data[1] SA1 (トグルスイッチ)
data[0] SA0 (トグルスイッチ)
y[2] DA2 (個別LED)
y[1] DA1 (個別LED)
y[0] DA0 (個別LED)

設計する回路のイメージ
encoder.png

解説

  • case文で組合せ論理回路を設計する際は以下のような記述を推奨する
    • 出力に相当する信号をreg宣言する
    • always @ (*) begin ~ end内にcase文を記述する
    • case文ではパターンマッチングに漏れが無いようにする(defaultを活用するとよい)
    • ブロッキング代入=を使って出力への信号の割り当てを行う

実習5. マルチプレクサの設計1

mux.v をカメレオンボードに実装し、動作を確かめること。
入出力の割り当ては表のとおりにすること。

mux1.v
// Top-level entity: mux
`default_nettype none

module mux( 
  input   wire  [2:0] d0,
  input   wire  [2:0] d1,
  input   wire        sel,
  output  reg   [2:0] y
  );

  always @ (*) begin
    case (sel)
      1'b0:  y = d0;
      1'b1:  y = d1;
    endcase
  end
endmodule
ポート I/O デバイス
d1[2:0] SA5~SA3 (トグルスイッチ)
d0[2:0] SA2~SA0 (トグルスイッチ)
sel SA7 (トグルスイッチ)
y[2:0] DA2~DA0 (個別LED)

設計する回路のイメージ
mux.png

if 文による組合せ論理回路の設計

実習6. マルチプレクサの設計2

mux.v をカメレオンボードに実装し、動作を確かめること。
入出力の割り当ては実習5と同様にすること。

mux2.v
// Top-level entity: mux
`default_nettype none

module mux( 
  input   wire  [2:0] d0,
  input   wire  [2:0] d1,
  input   wire        sel,
  output  reg   [2:0] y
  );

  always @ (*) begin
    if (sel) begin // selが非0の場合が成立, 0の場合が不成立
      y = d1;      //   selが成立のとき、こちらが実行される
    end else begin
      y = d0;      //   selが不成立のとき、こちらが実行される
    end
  end
endmodule

解説

  • if 文はalways文の中で記述する
  • if文では条件部()内の信号について成立/不成立を判定する
    • 成立: 非0 (どれか1ビットでも0でない場合)
    • 不成立: 0 (全てのビットが0の場合)
  • if文で組合せ論理回路を設計する際は以下のような記述を推奨する
    • 出力に相当する信号をreg宣言する
    • always @ (*) begin ~ end内にif文を記述する
    • else節を省略しない(成立/不成立両方の場合の動作を記述する)
    • ブロッキング代入=を使って出力への信号の割り当てを行う

関連資料

10
8
0

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
10
8