引き続き、例題をシミュレーションしてみましょう。今回は、これ。
えーと、記述のお作法ってゆーか、VerilogHDL の記述って新旧いろいろあるらしい。これまでの記述も間違いじゃなくて、そんなふうにも書けます、ってところかな。どれが新しいのか、どれが一般的なのか、ちょっとよくわかんないんですけど、気づいたところは変更していこうかなと思ってます。
んなわけで、これまでと違う記述がでてきますが、いちいち説明しませんので、あしからず。
7 セグメント LED デコーダをシミュレーションする
問題は図 1 のようになっています。
逆らうわけじゃないですが、どうせやるなら、いつも使っている TC4511 を倣いたいと思います。なので、DP は考慮しません。出力は TC4511 の真理値表に従います。BI などの制御入力は、なしです。
問題の解説にもありますが、回路の記述には 2 とおりのやりかたがあります。ひとつは always による組み合わせ回路の記述、もうひとつは function による組み合わせ回路の記述、です。
always による組み合わせ回路の記述
まずは、理解しやすかった always による組み合わせ回路の記述。
- module DECODER_7SEGMENT (
- input wire [3:0] DATA_INPUT,
- output reg [6:0] DATA_OUTPUT
- );
- always @*
- begin
- case (DATA_INPUT)
- 4'd0: DATA_OUTPUT = 7'b1111110;
- 4'd1: DATA_OUTPUT = 7'b0110000;
- 4'd2: DATA_OUTPUT = 7'b1101101;
- 4'd3: DATA_OUTPUT = 7'b1111001;
- 4'd4: DATA_OUTPUT = 7'b0110011;
- 4'd5: DATA_OUTPUT = 7'b1011011;
- 4'd6: DATA_OUTPUT = 7'b0011111;
- 4'd7: DATA_OUTPUT = 7'b1110000;
- 4'd8: DATA_OUTPUT = 7'b1111111;
- 4'd9: DATA_OUTPUT = 7'b1110011;
- default: DATA_OUTPUT = 7'b0000000;
- endcase
- end
- endmodule
3 行目。always を使うばあい、出力信号は reg で変数宣言します。
6 行目。always は、カウンタのシミュレーションでも使いましたが、@ の信号が変化した時に実行されて、無限にループします。@* とは、入力のいずれかが変化したら、という意味。ここでは、入力 DATA_INPUT が変化したら begin~end を実行、always へ戻り、信号の変化を待つ、ということになります。
8~20 行。おなじみの case 文。たとえば DATA_INPUT が 0 だったら、0b1111110 を出力する。これは、セグメント a~f が点灯、g が消灯の意。10 以上のときは全消灯。
なお、ケースが一致したら case 文を抜けます。同じケースがあったら、上の記述が優先される。C 言語とちょっと違いますね。
ちなみに、出力を不定にしたければ、7’bx とします。ビット列が長くてみづらければ、7’b111_1110 とか、書いてもいいらしい。
function による組み合わせ回路の記述
function とは、関数のこと。論理式で簡単に記述できないデーコーダなどの回路は、関数にするってことね。
- module DECODER_7SEGMENT (
- input wire [3:0] DATA_INPUT,
- output wire [6:0] DATA_OUTPUT
- );
- function [6:0] DECDR (
- input [3:0] DECDR_INPUT
- );
- begin
- case (DECDR_INPUT)
- 4'd0: DECDR = 7'b1111110;
- 4'd1: DECDR = 7'b0110000;
- 4'd2: DECDR = 7'b1101101;
- 4'd3: DECDR = 7'b1111001;
- 4'd4: DECDR = 7'b0110011;
- 4'd5: DECDR = 7'b1011011;
- 4'd6: DECDR = 7'b0011111;
- 4'd7: DECDR = 7'b1110000;
- 4'd8: DECDR = 7'b1111111;
- 4'd9: DECDR = 7'b1110011;
- default: DECDR = 7'b0000000;
- endcase
- end
- endfunction
- assign DATA_OUTPUT = DECDR(DATA_INPUT);
- endmodule
6~8 行目が、function の記述。DECDR_INPUT は引数で、関数名そのものが戻り値になる、みたいな。function の中身は、always と同様の case 文です。
26 行目。assign で function を呼び出す。なので、出力信号は wire でネット宣言する (3 行目)。
テストベンチ
テストベンチファイルです。
- module DECODER_7SEGMENT_TEST;
- reg [3:0] DATA_INPUT;
- wire [6:0] DATA_OUTPUT;
- parameter STEP = 10;
- DECODER_7SEGMENT DEC0(DATA_INPUT, DATA_OUTPUT);
- initial begin
- DATA_INPUT = 4'd0;
- #STEP DATA_INPUT = 4'd1;
- #STEP DATA_INPUT = 4'd2;
- #STEP DATA_INPUT = 4'd3;
- #STEP DATA_INPUT = 4'd4;
- #STEP DATA_INPUT = 4'd5;
- #STEP DATA_INPUT = 4'd6;
- #STEP DATA_INPUT = 4'd7;
- #STEP DATA_INPUT = 4'd8;
- #STEP DATA_INPUT = 4'd9;
- #STEP DATA_INPUT = 4'd10;
- #STEP DATA_INPUT = 4'd11;
- #STEP DATA_INPUT = 4'd12;
- #STEP DATA_INPUT = 4'd13;
- #STEP DATA_INPUT = 4'd14;
- #STEP DATA_INPUT = 4'd15;
- #STEP $finish;
- end
- initial begin
- $monitor("input = %d, output = %b", DATA_INPUT, DATA_OUTPUT);
- $dumpfile("dec_7seg_test.vcd");
- $dumpvars(0, DECODER_7SEGMENT_TEST);
- end
- endmodule
6 行目。遅延時間をパラメータ宣言にしてみました。
その他、これまでと同様です (^_^;)
シミュレーション結果
図 2 が、シミュレーション波形です。
入力 0~15 に対して、表示に応じたセグメントデータが出力されています。
んー、それ以上でもそれ以下でもない (;´Д`)