FIFO とは
FIFO ( First-In First Out )はメモリの 1 種で、直訳すると「先入れ先出し」です。
先に入れたもの(古いもの)を先に出す。それって当たり前のことなんじゃないの?
コンビニでもスーパーでも、賞味期限が近い(先に並べられた)商品を前に出して
取りやすくしているじゃないですか。これも FIFO の考えですよね!
FIFO の動作
そこで FIFO の動作を確認してみることにしました。
FIFO は Quartus II の Megafunction として登録されていますので、こちらを使用します。
Quartus II 14.0 では、Tools メニューから IP Catalog を選択すると、あらかじめ登録されている Megafunction を選択することができます。
( Quartus II 13.1 より前のバージョンでは、 Tools メニューから MegaWizard Plug-In Manager を選択します)
今回は最小構成にし、 4 bit × 4 word、シングル・クロックで動作する FIFO を作りました。(図 1)
入力信号の中で、write は 1 の時、 FIFO 内に新しくデータを書き込むことを可能にする信号。
read は 1 の時、 FIFO 内に書いてある一番古いデータを読み出して出力 q に反映させることを可能にする信号です。
動作を 図 2 で表します。
また出力信号は 4 word 埋まっている時は full = 1 になり、逆に何も入ってない場合は empty = 1 が出力されます。
疑問
この時、私は次の 3 つの状況について疑問が浮かびました。
1. read = 0 の時、どのような値が出力されるのだろう?
2. full = 1 の時に書き込んだら中のデータはどうなるの?
3. empty = 1 の状態で read = 1 , write = 1 の場合はどのような値が出力されるのだろう?
この 3 つを ModelSim でシミュレーションを実行して検証します!
疑問1 : read = 0 の時、どのような値が出力されるのだろう?
FIFO のデータを読み出さない時はどのような値が出力されるのでしょう。
不定でしょうか?
0000 でしょうか?
それとも、 1 つ前に読み出した値が出力されるのでしょうか?
検証:
4 word 分データを書き込み( write = 1 )、 2 word だけ読み出し( write = 0 かつ read = 1 )、
その後読み出しを止めた( read = 0 )際の出力 q の値を見ます。
結果:
図 3 のようになりました。
出力 q の値を見ると、 2 word 目に書き込んだ「 0010 」が 3 クロック目にもそのまま出力されています。
結果は
「読み出しを止める( read = 0 にする)前と同じ値が出力される」
でした。
read = 0 の時は、前の値がそのまま出力されることがわかりました。
疑問2 : full = 1 の時に書き込んだら中のデータはどうなるの?
すでに 4 word 書き込まれている( full = 1 )の時に、書き込みだけを行ったとき、中のデータはどうなるのでしょうか。
上書きされる?
一番古いデータが消えて、新しいデータが書き込まれる?
それとも、各ビットが OR される?
検証:
今回 4 word の FIFO を使っていますので、 1 つ多い 5 word を書き込んで( write = 1 )、書き終わった後に
読み出し( write = 0 かつ read = 1 )を 5 回行います。さて 5 word 目はどう出力されるのでしょう。
結果:
図 4 のようになりました。
5 word 目に書き込んだ「 0110 」は、出力 q を確認すると出力されていないことが分かります。
結果は
「書き込まれない」
でした。
FIFO は full = 0 になるまで中のデータは上書きされない、ということがわかりました。
疑問 3: empty = 1 の状態で read = 1, write = 1 の場合はどのような値が出力されるの?
FIFO 内にデータがない場合に書き込みと読み出し同時に行うと何が出力されるのでしょう?
不定?
0000?
それとも、前回と同じ値?
検証:
2 word 書き込んで( write = 1 )、 2 word 読み出し( read = 1 )、その後読み出しと書き込みを同時( write = 1 かつ read = 1 )に行ったときの出力を見ます。
結果:
図 5 に示します。
書き込んだデータの「1000」がすぐに出力されるのではなく、前の値「0101」が出ています。
よって結果は
「前回と同じ出力」
でした。
今回作成したシングルクロック FIFO では、 empty = 1 の時、書き込んだデータが 1 クロック送れて出力されることが分かりました。
シングルクロック FIFO では、書き込み時に 1 クロック、読み出し時に 1 クロック、データの出力に 1 クロックかかるため、
「読みだし」てから 1 クロック遅れてデータが出力されます。
最後に
FIFO は、やはりデータを貯めることができるのでメモリの 1 種だとわかりました。
「先入れ先出し」の概念ですが、中のデータを上書きしない、読み出しを止めると前回と同じ値を出力する特性がありました。
実際にはデータの入力順番を守る、上書きされない、などの用途から取得したデータを処理するときに、
処理が重くならないように 1 次保存バッファとして使われるそうです。
今回の検証から、その用途で使われる理由がよくわかりました。「ファイフォ」と不思議な響きの FIFO は実は順番を守る律儀なメモリでした。
今日のポイント
FIFO は読み出しの要求がくるまでデータを保持し、入力したデータの順番を守るメモリ。
中のデータが full の場合には、新しく入力されたデータは取り込まない。
中のデータが空の状態で読み書き同時に行った場合には、 「書き込み」「読み出し」「出力」の 3 クロック必要なため、
「読み出して」から 1 クロック遅れてデータが出力される。