連載
» 2008年10月16日 00時00分 公開

完全マスター! 電子回路ドリル III(7):【問題7】 モジュールを接続してみよう!

Verilog HDLで組み合わせ回路を記述するには? 今回は“関数”を用いる方法と、“always文”を用いる方法の2パターンを詳しく解説。

[横田一弘 埼玉県立新座総合技術高等学校 教諭,@IT MONOist]

【問題6】の解答

 前回の宿題【問題6】は、“4けたの2進数を7セグメントLEDに表示するためのデコーダを作る”という問題でした。皆さん解けましたでしょうか?

 解けた方も解けなかった方も答え合わせをして、次項の解説までぜひ読んでみてください。毎週コツコツ問題を解いて、ハードウェア記述言語によるデジタル回路設計の基礎知識を身に付けましょう。

 それでは、解答を発表します! なお、今回は解答が2パターンあります(詳しくは解説編をご覧ください)。


問題6

答え.

答え1答え2 (左)パターン1/(右)パターン2


【問題6】の解説

 4けたの2進数を7セグメントLEDに表示するためのデコーダを作成するには、はじめにデコーダの真理値表を作成します(表1)。

 7セグメントLEDとその表示方法については、連載「完全マスター! 電子回路ドリル」の【問題12】の解説で紹介しました。ここでも出力が負論理なので、LEDが“0”で光ることに注意しなければなりません。

7セグメントLEDデコーダの真理値表 表1 7セグメントLEDデコーダの真理値表

 それでは表1を基にデコーダを作ってみましょう。

 Verilog HDLでデコーダ(組み合わせ回路)を記述するには、関数(function)を用いる方法と、always文を用いる方法があります。

関数(function)でデコーダを記述する

 Verilog HDLでは、組み合わせ回路をassign文と関数で記述します。関数による組み合わせ回路の記述では、if文やcase文が使えるので、複雑な回路の記述に便利です。

 解答:パターン1(dec7seg1.v)がその例で、関数は、

assign LED = dec(data);

のように使います。関数decは信号detaを入力し、それに応じた値、すなわち7セグメントLEDの表示内容を出力します。

 関数の本体は別に定義します。以下に、関数定義の記述スタイルを示します。

function [ MSB : LSB ] 関数名 ;

引数の宣言

関数内ローカル信号の宣言

endfuntion



 関数定義は予約語functionではじまります。

function [7:0] dec;

により、関数decは8ビットの値を出力することが定義されます。ここでビット幅を指定しないと、出力は1ビットになります。

 続いて予約語inputで、関数の入力を宣言します。

input [3:0] data;

により、4ビットの信号dataを入力することが決まります。

 続いて機能を定義します。case文を用いると、真理値表をシンプルに記述できます。

case (data)  ←dataの場合分け
4'd0: dec = 8'b11000000; ←0の場合、decは2進数の11000000
4'd1: dec = 8'b11111100;
4'd2: dec = 8'b10010010;
4'd3: dec = 8'b10011000;
(中略)
default: dec = 8'bxxxxxxxx;  ←上記以外の場合、decの値は不定値
endcase

 ここで、関数名decのように、関数からの出力は関数名を使って行います。

 最後に予約語endfunctionで関数定義を終わります。

always文でデコーダを記述する

 always文は順序回路を記述するためのものですが、「入力をレベル・センスとし、すべての入力を記述する」ことで組み合わせ回路の記述が可能です。

 解答:パターン2(dec7seg2.v)がその例です。このモジュールのalways文では、

always @(data)

のように、立ち上がりエッジ(posedge)、立ち下がりエッジ(negedge)の指定がありません。そこでVerilog HDLは、「入力の値から出力を設定する(レベル・センス)」と理解します。

 always文の本体のcase文は、

case (data)
4'd0: LED = 8'b11000000;
4'd1: LED = 8'b11111100;
4'd2: LED = 8'b10010010;
4'd3: LED = 8'b10011000;
(中略)
default: LED = 8'bxxxxxxxx;
endcase

となっており、関数の場合と変わりありません。ただし、always文では「すべての因果関係が記述されていないと組み合わせ回路になりません」。例えば、

default: LED = 8'bxxxxxxxx;

がないと、信号dataが0から9以外で出力が変化しないように、Verilog HDLは保持回路を作ります。

 また、always文で組み合わせ回路を作る場合であっても、文法上、always文の出力(結果)はreg宣言しなければなりません。従って、変数LEDはレジスタ型のデータとして扱います。

 以上でVerilog HDLによるデコーダ記述の説明を終わりますが、Verilog HDLで組み合わせ回路を記述する場合、関数とalways文のどちらがよいのでしょうか?

 関数では必ず組み合わせ回路を生成するので、比較的回路構成が分かりやすいといえます。一方、always文であれば慣れは必要ですが記述量は少なくて済みます。本連載では筆者の好みで、以後always文で記述することにします。

シミュレータの起動と波形表示

 前回も述べましたが、Verilog HDLの習得には“回路を動作させ、検証すること”が一番です(図1)。【問題5】の解説を参考にシミュレーション環境を用意し、テスト・ベンチ(dec7seg_test.v)で回路の動作を試してみてください。

7セグメントデコーダのシミュレーション結果 図1 7セグメントデコーダのシミュレーション結果

次回までの宿題 ― 【問題7】

問題7

以下のブロック図のように、【問題5】の10進カウンタと【問題6】の7セグメントLEDデコーダを接続した回路をVerilog HDLで作ってください

問題7

答え. 解答はこちら(←クリック)



Copyright © ITmedia, Inc. All Rights Reserved.