「Hardware Description Language」に今来た私が試したこと（ChatGPT先生と共に）

# はじめに
この記事は、[Hardware Description Language Advent Calendar 2024](https://qiita.com/advent-calendar/2024/hdl) の２２日目の記事となります。

アドベントカレンダのリストを見ていて、今、Hardware Description Languageに来た初心者の記録です。

# ChatGPT先生に教えてもらう

ChatGPT先生に嘘を教えられている可能性は否定できないので、誤りがありましたら有識者の方のコメントをお願いいたします。
![スクリーンショット 2024-12-17 9.23.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/5266d4f5-3a4e-7007-ea28-9b52324e8136.png)
![スクリーンショット 2024-12-17 9.24.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/e6646428-fd01-0ff3-ae86-ebe99e05828c.png)

![スクリーンショット 2024-12-17 9.24.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/b468d6be-6673-e0bc-b415-e6d031808e21.png)
![スクリーンショット 2024-12-17 9.24.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/da05ee85-6f86-a35e-b04a-e59edae08487.png)
![スクリーンショット 2024-12-17 9.24.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/8d5715c1-4755-8e1b-3f80-276aec27f146.png)

なるほど。Verilogはどんな文法なんだろう
聞いてみよう。

![スクリーンショット 2024-12-17 9.28.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/9f96c3d3-19f5-5a1d-ac2b-2dbad29b26d1.png)
![スクリーンショット 2024-12-17 9.29.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/f94c3d89-fb3d-1504-1229-e978eed33d4e.png)
![スクリーンショット 2024-12-17 9.29.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/d0d691e1-11be-1ef4-fe7e-4d854b12aef2.png)

```verilog:kouzou.v
module モジュール名 (入力, 出力);
  // ポート（入力と出力）の宣言
  input 入力名;
  output 出力名;

  // 内部の回路や信号の宣言
  wire 信号名;

  // 回路の動作を記述
  assign 出力名 = 入力名;

endmodule
```

![スクリーンショット 2024-12-17 9.33.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/9243ec1c-ae40-10d0-5933-8563045416c3.png)

```verilog:and_gate.v
module AND_Gate (a, b, y);
  input a, b;      // 入力信号
  output y;        // 出力信号

  assign y = a & b; // AND演算
endmodule
```
![スクリーンショット 2024-12-17 9.38.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/adfa8da3-3dc2-8014-6289-3813c430b2c6.png)



![スクリーンショット 2024-12-17 9.39.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/ae6b8acf-7846-c398-4fae-8b8d03f86911.png)

```verilog:and_gate_tb.v
module Testbench;
  reg a, b;        // 入力信号のシミュレーション用変数
  wire y;          // 出力信号

  // AND_Gateモジュールをインスタンス化
  AND_Gate U1 (a, b, y);

  initial begin
    // シミュレーションでの入力値を設定
    a = 0; b = 0;
    #10; // 10単位時間待つ
    a = 0; b = 1;
    #10;
    a = 1; b = 0;
    #10;
    a = 1; b = 1;
    #10;

    $finish; // シミュレーション終了
  end
endmodule
```
![スクリーンショット 2024-12-17 9.44.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/f97c1b42-49d4-7798-be59-e19f0421c516.png)
![スクリーンショット 2024-12-17 10.03.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/5f2925c9-0a4a-3662-6d53-efa83eae6163.png)
![スクリーンショット 2024-12-17 10.03.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/d756b095-2242-7037-1cd2-164fbae94aa5.png)

なるほどテストベンチを作って確認するのね。
拡張子は何？


![スクリーンショット 2024-12-17 10.05.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/3d2d3a47-51ed-215f-5b8f-8c2480153d6a.png)
![スクリーンショット 2024-12-17 10.06.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/ff6c3b3f-a3a0-b4aa-d407-a702e2d44870.png)


```verilog:defines.vh
// ヘッダーファイル defines.vh
`define AND_GATE_DELAY 10
```

```verilog:and_gate.v
// ソースファイル and_gate.v
`include "defines.vh" // ヘッダーファイルを読み込む

module AND_Gate (a, b, y);
  input a, b;
  output y;

  assign #`AND_GATE_DELAY y = a & b; // 定義された遅延を使用
endmodule
```

なるほど。

入力と出力が同じ引数のような書き方なのは気になる

![スクリーンショット 2024-12-17 10.08.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/a6857fb1-97ee-dbf0-8ae4-276f61fc847f.png)
![スクリーンショット 2024-12-17 10.08.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/f789e1dc-877c-4eba-0076-609e400f39e8.png)

```verilog:inout.v
module モジュール名 (入力信号, 出力信号);
  input 入力信号;  // 入力ポート
  output 出力信号; // 出力ポート
endmodule
```
![スクリーンショット 2024-12-17 10.10.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/44362087-af9d-86c4-4e43-c887f6b63931.png)

```verilog:kouzou.v
module AND_Gate (a, b, y);
  input a, b;      // 入力ポート
  output y;        // 出力ポート

  assign y = a & b; // AND演算
endmodule
```

![スクリーンショット 2024-12-17 10.11.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/e3696844-60d4-23a2-bff5-342cef17c685.png)


```c:add.c
int add(int a, int b) {
    return a + b;
}
```
![スクリーンショット 2024-12-17 10.12.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/d4a0d15a-2205-0908-adea-49d3024e9e9c.png)
![スクリーンショット 2024-12-17 10.12.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/71be41c0-16b0-740b-9a54-b11e15175f06.png)

![スクリーンショット 2024-12-17 10.20.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/9002fcef-eef5-f2df-cbfe-d763e7cfc59d.png)

```verilog:and.v
module Top_Module;
  wire a, b, y;

  // ANDゲートのインスタンス
  AND_Gate U1 (a, b, y); // 外部信号a, b, yをAND_Gateのポートに接続
endmodule
```
![スクリーンショット 2024-12-17 10.22.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/59c1b68f-8dd5-3c04-6caa-fae0f45ba5fb.png)

信号線を書いているということね。でもその信号線が、入力なのか出力なのか、信号線の名前だけ見たのでは、分からんのでは？
![スクリーンショット 2024-12-17 10.23.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/58a54cc7-09f5-d45c-2230-ef569df73dc8.png)

褒められた！

![スクリーンショット 2024-12-17 10.24.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/8783a7a6-a557-fc54-0f87-8d540de29a14.png)

```verilog:non_ansi.v
module AND_Gate (a, b, y);
  input a, b;    // 入力ポートを内部で宣言
  output y;      // 出力ポートを内部で宣言

  assign y = a & b; // AND演算
endmodule
```
![スクリーンショット 2024-12-17 10.24.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/b575a47c-d5cc-08d2-5a61-1afb559f71ea.png)
![スクリーンショット 2024-12-17 10.25.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/125bccf8-e0b9-f79f-47bd-4f13fb0281db.png)

```verilog:ansi.v
module AND_Gate (input a, input b, output y);
  assign y = a & b; // AND演算
endmodule
```
![スクリーンショット 2024-12-17 10.31.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/8e16a80c-d997-fe87-2b2a-7de663d7de2b.png)
![スクリーンショット 2024-12-17 10.31.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/9c531e2d-2c6d-1f54-0afb-7d938c2b4879.png)
![スクリーンショット 2024-12-17 10.31.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/675639ac-4020-66b9-a0b9-d2678e5e72e7.png)

なるほど腑に落ちた。

あっとテストベンチの拡張子を聞いてなかった。
![スクリーンショット 2024-12-17 10.33.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/8bb7fc03-6c5c-9ee0-b5f2-0599da0f2d4b.png)
![スクリーンショット 2024-12-17 10.34.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/fe00b8cf-76a3-e85c-314b-a4981778e4ad.png)
![スクリーンショット 2024-12-17 10.34.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/d9816d35-6b7a-16e7-9506-2fcf31b7d8bc.png)

納得です。

何か試してみたい。練習問題を検索してみる。

itmediaさんの素晴らしい記事を発見。

https://monoist.itmedia.co.jp/mn/articles/0809/04/news122.html

ここの練習問題をChatGPT先生に聞いてみよう。
![スクリーンショット 2024-12-17 10.38.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/b192a238-066d-6d9a-a1fb-841f517957c8.png)

```verilog:logic_circuit.v
module logic_circuit (
    input A,
    input B,
    input C,
    output X
);

    wire or_out;
    wire not_out;

    // ORゲート
    assign or_out = A | B;

    // NOTゲート
    assign not_out = ~C;

    // ANDゲート
    assign X = or_out & not_out;

endmodule

```

https://monoist.itmedia.co.jp/mn/articles/0809/11/news145.html

ChatGPTの方はANSIでロジックを１つ１つ書いている。
一方、模範解答の方はnon ANSIでロジックをまとめて書いている。
という感じか。

テストベンチをChatGPT先生に作ってもらおう。

![スクリーンショット 2024-12-17 10.43.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/b666bf2c-42ad-526d-ddf2-67c92467bdc4.png)


```verilog:logic_circuit_tb.v
module logic_circuit_tb;

    // テストベンチ用信号
    reg A;
    reg B;
    reg C;
    wire X;

    // 被テストモジュールのインスタンス化
    logic_circuit uut (
        .A(A),
        .B(B),
        .C(C),
        .X(X)
    );

    // テストケース
    initial begin
        // 波形を出力
        $dumpfile("logic_circuit_tb.vcd");
        $dumpvars(0, logic_circuit_tb);

        // 初期状態
        A = 0; B = 0; C = 0;
        #10; // 10タイムユニット待機

        A = 0; B = 0; C = 1;
        #10;

        A = 0; B = 1; C = 0;
        #10;

        A = 0; B = 1; C = 1;
        #10;

        A = 1; B = 0; C = 0;
        #10;

        A = 1; B = 0; C = 1;
        #10;

        A = 1; B = 1; C = 0;
        #10;

        A = 1; B = 1; C = 1;
        #10;

        // シミュレーション終了
        $finish;
    end

endmodule
```
![スクリーンショット 2024-12-17 11.02.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/aa487c0f-3e64-672b-34a8-f2ff5874f8f9.png)

おお。網羅しているっぽい。

# いざ実行！

これ動かすのはどうしたら良いのか。
Google先生で見つけた以下のサイトでトライしてみる。

使い方の参考にさせてもらったブログ

https://uzusayuu.hatenadiary.jp/entry/2018/12/17/125833


先ほどのコードを左、テストベンチを右に、貼り付ける。

![スクリーンショット 2024-12-17 10.50.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/c6bea939-1366-c474-0fa0-2d11b94117d4.png)

左のペインで適当なSimulatorを選択する。
左上の青色のRunボタンを押すと・・


![スクリーンショット 2024-12-17 11.01.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/28b539ed-2e53-6fee-85e9-af221c1e2326.png)

やったぁ！波形が出たぞ。
あってるのかな・・

真理値表をChatGPT先生に作ってもらう
![スクリーンショット 2024-12-17 11.02.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/ca1f4b60-5034-86cc-d6e8-02e415397c53.png)
![スクリーンショット 2024-12-17 11.02.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1032713/a45f1087-94ea-3181-4f63-980cd3fdf206.png)

波形と対比して入力が０００のとき０で・・・
っと・・・。おお。全部正しい。


以上、「Hardware Description Language」に今来た私が試したこと（ChatGPT先生と共に）でした。
最後までご覧いただきましてありがとうございました！。