補足 - シミュレーション言語としてのVerilog
[←] [↑] [→]
本章は論理合成向けのHDLの書き方に絞っているので、Verilogのシミュレーション言語としての側面は省いている。しかし、なぜalwaysとか<=とか変な記号を使うのかは、Verilogが元々シミュレーション言語として作られたことに起因しているので、ここで補足しておく。
◇
ハードウェアの動作をシミュレーションするだけならばHDLでなくソフトウェア言語でもできる。例えば、同じ回路を両方で書いてみると次のようになる。
/* C言語による記述 */ main() { int ra,rb,ra_tmp,rb_tmp;
while(1) { /* clk変化前 */ ra_tmp = ra; rb_tmp = rb;
/* clk変化後 */ ra = ra_tmp + 1; rb = ra_tmp; } } |
/* Verilog-HDLによる記述 */ module main(); reg clk; reg ra,rb;
initial begin clk = 0; forever #10 clk = ~clk; end
always @(posedge clk) ra <= ra + 1;
always @(posedge clk) rb <= ra;
endmodule (注)この記述は論理合成できない書き方です |
これを見ると、C言語の方は全体をwhile(1)の無限ループに入れて、clk変化の前後を明示的に書かなければならないのに対して、Verilogの方は代入文をただ並列に書けばよいことがわかる。つまりハードウェア記述言語(HDL)がソフトウェア言語と違うところは、
「ソフトウェア言語は、そもそも実行するプロセッサが1個しかないから、上から順に1行ずつ実行するモデルで対象を記述するように作られているのに対して、HDLは複数のFFが並行動作するモデルを記述するように作られている」
という点にある。そして並列動作するモデルを記述するために、Verilog言語は暗黙の時刻変数($time)とそれを使う構文(always,#,@)を備えている。
上記のVerilog-HDLによる記述を詳しく追ってみると、
(1) まずC言語と同じく上から順に実行する。
(2) ただし#と@がついた箇所は特別で
・#10は、現時刻の10time unit後まで実行を保留する
・@(posedge clk)は、変数clkが0→1に変化する時刻まで実行を保留する
(3) 保留したまま最後の行まで実行すると、時刻を進めてから先頭に戻って続きを実行する。すなわち10 time unit後に時刻を進めてinitial文の#10に続くclk=~clkを実行する。
(4) clkが0→1に変化したので次はalways文の@(posedge clk)に続くra<=ra+1等を実行する。このときノンブロック代入(<=)は、同一時刻の複数の代入文に対して右辺はすべて更新前の値を使うという意味である。
(5) 再び先頭に戻って、保留になっている文がないのでinitial文内のforeverに続く#10で再び保留になる。またalways文はforeverと同様に何度も繰り返して実行するという意味なので、再びalways文に続く@(posedge clk)で保留になる
以上がシミュレーションの動作だが、実際にはこの動作を意識している人はあまりいないだろう。
私自身は、FFとalways@()とが1対1に対応していると見なして、HDL記述は2次元の回路図を1次元のテキストにマッピングしたものというイメージでとらえている。
[←] [↑] [→]