先週の実験では、Verilog を用いて組合せ回路を設計した。今週は順序回路の設計を学ぶ。また、複雑な順序回路設計を体験する。
Dフリップフロップはクロック信号線が立ち上がった(0から1へ変化した)瞬間の入力D の値を記憶する記憶素子である。Dフリップフロップの回路図を図1に示す。
図1. Dフリップフロップの回路図
Verilog において Dフリップフロップを記述したいとき、この回路図をそのまま assign 文で記述してはいけない。Verilog においてフリップフロップは手続きブロックを用いて記述される。図2 に Dフロップフロップの記述例を示す。
図2. Dフリップフロップの Verilog記述
入力信号値が変化した瞬間に出力信号値が変化する組合せ回路においては always に続く @(〜)には * 印を記述した。一方、クロックが立ち上がった瞬間にのみ出力値が更新されるフリップフロップを記述するときは、@(〜)にはキーワード posedge とクロック信号名を記述する。
図2の回路をシミュレーション実験で動作検証する。図3 のような入力波形を作成する。ここで、クロック信号 CLK と入力 D の変化するタイミングがずれている。これはクロック信号と通常の入力を同時に変化させることが許されていないからである。(理由は論理回路設計についてもう少し知識を深めれば分かるだろう。ここではそういうものだと納得して欲しい。)
図3. Dフリップフロップ検証用の入力波形図
図4 に検証用モジュール記述例を示す。クロック信号について、通常の入力信号と同様に、図3の波形図を実現するような代入文を initial ブロックの中に書いても良い。しかし、それでは面倒なので、図4ではもう少し簡単な書き方をしている。クロック信号はこのように記述されるものなので、このまま覚えてしまっても良い。図4では通常の入力信号値を記述する initial ブロックとは別に always ブロックを設けている。always ブロックは initial ブロックと並列に実行される。また、initial ブロックとは異なり、ブロックの最後まで実行終了するとブロックの最初に戻り、再度実行される。つまり、この場合、まず CLK = 1 が実行され、5 ns 待ち、CLK = 0 とし、5 ns 待つ。ここで always ブロックが終わっているので、always ブロックの最初に戻る。、以降、CLK = 1 とし 5ns 待つ、CLK = 0 とし 5ns 待つという動作を initial ブロック内の $finish が実行されシミュレーションが終了するまで延々と繰り返す。なお、always ブロックの最後に遅延 (#5) を記述することは文法上許されていない。そこで、遅延に続いて、何も実行しない空文 (セミコロンだけの文) を挿入している。
... always begin // always ブロックの始まり CLK = 1; #5 CLK = 0; #5 ; // 空文 end // always ブロックの終わり initial begin // initial ブロックの始まり D = 0; #19 D = 1; #10 D = 0; #20 D = 1; #21 $finish; end // initial ブロックの終わり endmodule |
図4. Dフリップフロップの検証用モジュール記述例
先週の組合せ回路の場合と同様、手続きブロックの中には if, case などを用いた複雑な処理を書くことができる。図5は長さ4ビットのシフトレジスタの記述例である。リセット信号 RST が 1 のとき、シフトレジスタの値は全零にリセットされる。RST が 0 のとき、値がシフトする。ただし、値の更新はクロック入力 CLK が立ち上がった瞬間にのみ行われる。
図5. 4ビットシフトレジスタの Verilog記述
Xilinx FPGA においては、起動時に一度だけ初期値を与えたいとき、リセット信号などの初期化信号を記述せず、図6 のように初期値を与える方法もある。ただ、この記述法に対応していない環境も多いので注意されたい。図5が一般的な記述法である。
図6. 4ビットシフトレジスタの Verilog記述2
10進カウンタを作成し、動作検証せよ。
先週は basys 2 の 7セグメント LED を扱った。しかし、4 数字を独立して操作させることはできなかった。今週は 4数字を独立して操作させる。本体とUSB ケーブル、マニュアルを準備されたい。
basys 2 のマニュアル
(The original file can be obtained from the site of Digilent. Inc.)
多くのシステムにおいて、クロック信号は FPGA 内部では作られない。振動子を用いて FPGA 外部で作り、FPGA に与えるのが一般的である。basys 2 においては、50MHz のクロック信号が振動子において作られ、FPGA のクロック入力 B8 から与えられる。
なお、ISE は basys 2 のクロックの周波数が 50MHz であることを知らない。このことは様々な問題を招く。そこで、以下のような方法でクロック周波数を与える。この方法は PlanAhead 実行後に行うべき操作である。とりあえず、課題2 を途中までこなし、PlanAhead 実行後に読み返されたい。
Processes から、"User Constraints → Create Timing Constraints" を選ぶ。図7 のような画面になる。Unconstrained Clocks からクロック信号名を選択されたい。
図7. Create Timing Constraints
図8のようなダイアログが開くはずである。そこで、図8のようにクロックが 50MHz であると指定し、OK をクリックする。あとは、パネルのタブを "Design" とし、通常画面に戻ればよい。
図8. Clock Period
図9 のように T-FF の T入力に押しボタン、クロック入力に振動子、出力にLED を割り当てた回路を考え、その動作を予想せよ。また、実際に FPGA 上に構成し、実際の動作を確認せよ。
図9.
通常の LED 1個について、1秒間に1回点滅する回路を作成せよ。
押しボタンを押す毎に 7セグメントLEDの値が 0 → 1 → 2 → … → 9 → 0 → … と変化する回路を作成せよ。
7セグメントLED に「1234」と表示する回路を作成せよ。ただし、マニュアル 4〜5ページに 7セグメントLED の使用法が書いてあるのでよく読むこと。特に Figure 8 をよく読むこと。
押しボタンを押す毎に 7セグメントLEDの値が 0000 → 0001 → 0002 → … → 9999 → 0000 → … と変化する回路を作成せよ。
その他、思い付いた回路を作成せよ。
難波 一輝 (助教・北神・難波研究室)
工学部1号棟4階409号室、内線3255、043-290-3255、namba@ieee.org