普段、仕事で設計を始めるとなると設計仕様書を作成して、これから設計を始める内容をメンバー(あるいは顧客)と確認して始めるのであるが、さっさとコーディングをしたいので、TestBenchから始めることにします。

UARTも通信装置なので、送信と受信があるわけで、まずは送信側のTestBenchから始めてみましょう。

送信側は検証する項目がほとんどなく、与えられた設定に基づき送信を行うものですので、比較的簡単です。たった1つの task で作られます。

ただ1箇所、工夫している点があるので、その点について説明しておきます。

task には時間の制御があり、task の開始から終了までの間に時間とともに扱われている変数の値が変化していきます。
もし、task の実行中に更に同じ task がコールされてしまった場合、実行中の task が扱っている変数の値は保証されなくなります。(2つ目の task のコールによって順序処理が壊されてしまいます。)

そこでの工夫は、task の中に 変数 in_use を宣言して、task 実行開始とともに in_use を 1'b1 にセット、task 終了時に in_use を 1'b0 にリセットするものとし、2つ目に task がコールされたとき、in_use の値が 1'b1 であった場合、その task について ##ERROR## メッセージを出力して強制的に終了させています。


 28       task transmit;
 29          reg     in_use;
 30          integer trns_bit_num;
 31          reg     parity;
 32          begin : transmit_task
 33             if (in_use) begin
 34                $display("%t ##ERROR## %m - task is in use", $time);
 35                disable transmit_task;
 36             end
 37             in_use = 1'b1;

 〜

 81             in_use = 1'b0;
 82          end
 83       endtask

UART送信側の Testbench module の全体は以下のコードとなります。

bit_period, data_length, stop_length, parity_mode は シミュレーションの途中でも変えることができるよう`define で宣言はせず、それぞれの 型 で宣言しています。

  1    `ifndef non_parity
  2     `define non_parity 2'b00
  3    `endif
  4
  5    `ifndef odd_parity
  6     `define odd_parity 2'b01
  7    `endif
  8
  9    `ifndef even_parity
 10     `define even_parity 2'b10
 11    `endif
 12
 13    module TB_UART_tx
 14       (/*AUTOARG*/
 15        // Outputs
 16        UART_tx
 17       );
 18
 19       output reg     UART_tx = 1'bz;
 20
 21       time           bit_period = 1000;
 22       integer        data_length = 8;
 23       integer        stop_length = 2;
 24       reg [1:0]      parity_mode = `odd_parity;
 25       reg [127:0]    data = 8'b1010_1010;
 26       reg           LSB_first = 0;
 27
 28       task transmit;
 29          reg     in_use;
 30          integer trns_bit_num;
 31          reg     parity;
 32          begin : transmit_task
 33             if (in_use) begin
 34                $display("%t ##ERROR## %m - task is in use", $time);
 35                disable transmit_task;
 36             end
 37             in_use = 1'b1;
 38             $write("%t ##INFO## %m - Transmitting UART data ", $time);
 39             for (trns_bit_num = data_length - 1; trns_bit_num >= 0; trns_bit_num = trns_bit_num - 1) begin
 40                $write("%b", data[i]);
 41             end
 42             $write("\n");
 43             parity = 1'b0;
 44             // Start-bit
 45             UART_tx = 1'b0;
 46             #(bit_period);
 47             // Data
 48             if (LSB_first === 1) begin
 49                for (trns_bit_num = 0; trns_bit_num < data_length; trns_bit_num = trns_bit_num + 1) begin
 50                   UART_tx = data[trns_bit_num];
 51                   parity = parity ^ UART_tx;
 52                   #(bit_period);
 53                end
 54             end
 55             else begin
 56                for (trns_bit_num = data_length - 1; trns_bit_num >= 0; trns_bit_num = trns_bit_num - 1) begin
 57                   UART_tx = data[trns_bit_num];
 58                   parity = parity ^ UART_tx;
 59                   #(bit_period);
 60                end
 61             end
 62             // Parity
 63             case (parity_mode)
 64               `odd_parity : begin
 65                  UART_tx = parity;
 66                  #(bit_period);
 67               end
 68               `even_parity : begin
 69                  UART_tx = ~parity;
 70                  #(bit_period);
 71               end
 72               default : begin
 73               end
 74             endcase // case (parity_mode)
 75             // Stop-bit
 76             for (trns_bit_num = 0; trns_bit_num < stop_length; trns_bit_num = trns_bit_num + 1) begin
 77                UART_tx = 1'b1;
 78                #(bit_period);
 79             end
 80             UART_tx = 1'bz;
 81             in_use = 1'b0;
 82          end
 83       endtask
 84
 85    endmodule // TB_UART_tx



海外発激安ガジェットショップ!送料無料!【DX.com】
TITLE

自己紹介

50才になる半導体エンジニアです。
大学で電子電気工学を学び、1990年にその分野のまま就職。ASICやマイコンの設計を長く続けてきましたが20年も同じ分野にいると業態も衰退したり変化するもので退職し、今は外資のIT系会社に再就職して設計請負業をやっております。
お問い合わせは
nakata.xianzhi@outlook.com







Linux と 小ネタ

デジタル回路設計

海外駐在後記