HDLはとてもややこしい

 さて、それを踏まえて、HDLを書くときの難しさについて、僕が理解したことを話していきます。

 先ほど述べた通り、S/W言語では振る舞いを記述するのですが、H/W言語では構造を記述します。従って、記述されたものを読んでも、すぐには振る舞いは分かりません。記述された構造を理解し、その上で回路がどのような振る舞いをするのか、ということを考える必要があります。S/Wのコーディングよりも、考えなければいけないことが1つ多いのです。

 HDLのややこしい点は、「すべての状態変化が並列に起こること」です。

 HDLでは、大きく分けて組み合わせ回路および順序回路という2種類の回路を構成できます。

 組み合わせ回路では、入力信号の組み合わせによって、出力信号が一意に定まります。組み合わせ回路は、回路に電気が通っている限り常に評価されているので、入力が変化した瞬間に出力が変化します。

 順序回路では、クロックの立ち上がり(もしくは立ち下がり、これは自分で決めます)のタイミングに同期して出力が変化します。クロックタイミングの時に取り込んだ入力の値と内部レジスターの状態(値)によって、出力と次の内部状態が決定します。レジスターというのは値を保持する回路のことで、S/Wでいえば変数、論理回路でいえばFF(フリップフロップ)のことです。

 どちらの回路にもややこしさがあります。

組み合わせ回路のややこしさ

 組み合わせ回路のややこしさは、「タイミング」です。

 HDLで記述される回路は、当たり前ですがリアルワールドに存在するH/Wなので、実際の回路ならではの注意点があります。

 先ほど、組み合わせ回路は入力信号の組み合わせによって出力信号が一意に定まると書きましたが、実際の入力から出力までは、信号線の長さと通過するロジックセル(さまざまな論理素子として振る舞うことのできるセル)に応じた遅延が入ります。あるレジスター間で、この遅延時間が1クロックの時間の長さを超えてしまうと、正しく動作しない回路になります。合成(HDLを実際の回路データにすること)の際に、ツールに「この信号線からこの信号線までは、この遅延以下で動作するように配線せよ」という制約を与えたり、ツールが出してくれるタイミングエラーを見たりすることで、正しく動作させることができる…、はずなのですが、回路内の実システムでの動作は、シミュレーションと必ずしも一致するわけではないので、正しく動作しないことがあります。

 こうした誤動作が起こったとき、その原因となる信号線を特定するのは非常に困難です。従って、そもそもタイミングエラーが起こらないように、組み合わせ回路では複雑なロジックをなるべく避けます。