Verilog HDLによる論理回路のモジュール設計(授業用)

# モジュールを組み合わせた回路の設計

規模の大きな回路をVerilog HDLで設計する場合、回路全体を対象にして設計するよりは、回路を機能ごとに分割し、より小規模な回路の組合せで全体の回路を構成するほうが設計し易く、回路の動作検証も容易となる。この様な設計手法を構造化設計と呼ぶ。

Verilog HDL で構造化設計を行うには下位モジュールのインスタンス化が必要となる。

## 実習1. Half Adderを組み合わせたFull Adderの設計

fulladder.v と halfadder.v で設計される回路を実習ボードに実装して、動作を確かめること。
ただし top-level entityは fulladderとする。
入出力の割り当ては表の通りにすること。

```Verilog:fulladder.v
`default_nettype none

module fulladder(
  input   wire  a,
  input   wire  b,
  input   wire  c_i,
  output  wire  c_o,
  output  wire  s
  );

  wire  s0;
  wire  c0;
  wire  c1;
  
  // halfadder モジュールをインスタンス化
  halfadder ha1( // インスタンス名 ha1
    .a(a),    // ha1 の入力ポート a に fulladder の入力ポート信号 a を割り当て
    .b(b),    // ha1 の入力ポート b に fulladder の入力ポート信号 b を割り当て
    .c(c0),   // ha1 の出力ポート c に fulladder の内部信号 c0 を割り当て
    .s(s0),   // ha1 の出力ポート s に fulladder の内部信号 s0 を割り当て
  );
  
  // halfadder モジュールをインスタンス化
  halfadder ha0( // インスタンス名 ha0
    .a(s0),   // ha0 の入力ポート a に fulladder の内部信号 s0 を割り当て
    .b(c_i),  // ha0 の入力ポート b に fulladder の入力ポート信号 c_i を割り当て
    .c(c1),   // ha0 の出力ポート c に fulladder の内部信号 c1 を割り当て
    .s(s)     // ha0 の出力ポート s に fulladder の出力ポート信号 s を割り当て
  );
  
  assign c_o = c1 | c0;
  
endmodule
```

``` Verilog:halfadder.v
`default_nettype none

module halfadder(
  input   wire  a,
  input   wire  b,
  output  wire  c,
  output  wire  s
  );
  
  assign {c, s} = a + b;
  
endmodule
```

|fulladder のポート|I/O デバイス|
|:---:|:-----:|
| a   | SA2　(トグルスイッチ) |
| b   | SA1 (トグルスイッチ) |
| c_i | SA0 (トグルスイッチ) |
| c_o | DA1 (個別LED) |
| s   | DA0 (個別LED) |

設計する回路のイメージ
![fulladder.png](https://qiita-image-store.s3.amazonaws.com/0/25656/fca5f58d-effe-413b-1823-9e43da728489.png)

### 解説
実習1では上位モジュール fulladder 内でインスタンス名の異なる2つの下位モジュール halfadder をインスタンス化している。

- モジュールのインスタンス化ではモジュール名、インスタンス名、ポートリストを定義する
- ポートリストでは、下位モジュールで定義したポート名とインスタンス化した側(上位モジュール側)の信号名のペアを記述する
- 下位モジュールへの接続では、入力ポートについては式やレジスタ型信号(reg型)を接続できるが、出力ポートにはネット型信号(wire 型)のみが接続できる

```
// モジュールのインスタンス化
// port1, port2 は下位モジュール module_nameで定義したポート名とする
// signal1, signal2 は上位モジュール側での信号名とする

// モジュール名 インスタンス名  ポートリスト
module_name    instance_name  (.port1(signal1), .port2(signal2));

```

構造化設計では、上位モジュールにおいて必要な下位モジュールをインスタンス化し、インスタンス化したモジュールのポート同士や、インスタンス化したモジュールのポートと上位モジュールのポートとを、wire宣言した信号線で接続し、モジュール同士を組み合わせることで回路を設計していくイメージを持つとよい。



## 実習2. FullAdder と2-4ラインデコーダを組み合わせた回路の設計

以下の top.v、two_four_decoder.v、および実習1のfulladder.v、halfadder.v で設計される回路を実習ボードに実装して、動作を確認すること。
ただし top-level entityは top とする。
入出力の割り当ては表の通りにすること。

```Verilog:top.v
`default_nettype none

module top(
  input   wire        a,
  input   wire        b,
  input   wire        c_i,
  output  wire [3:0]  y
  );

  wire  c;
  wire  s;
  
  fulladder fa(
    .a  (a),
    .b  (b),
    .c_i(c_i),
    .c_o(c),
    .s  (s)
  );
  
  two_four_decoder decoder(
    .data ({c, s}),
    .y    (y)
  );

endmodule
```

```Verilog:two_four_decoder.v
`default_nettype none

module two_four_decoder(
  input   wire [1:0]  data,
  output  reg  [3:0]  y
  );
  
  always @ (*) begin
    case (data)
      2'b00:  y = 4'b0001;
      2'b01:  y = 4'b0010;
      2'b10:  y = 4'b0100;
      2'b11:  y = 4'b1000;
    endcase
  end
  
endmodule

```

| top のポート| I/O デバイス |
|:---:|:-----:|
| a | SA2 (トグルスイッチ) |
| b | SA1 (トグルスイッチ)  |
| c_i | SA0 (トグルスイッチ)  |
| y[3:0] | DA3~DA0 (個別LED) |

設計する回路のイメージ
![fulladder_decoder.png](https://qiita-image-store.s3.amazonaws.com/0/25656/ed4cb0ed-d9a5-eef9-0f3d-7219c78e0b53.png)