2004/09/27 【ソフトウエア編TOPに戻る】
前回の411.VHDLの色々な記述方法(RS-FF回路)では、入力信号が変化したタイミングで出力信号が変化するRS−FF回路をご紹介しました。これはこれで良いのですが、一般的には外部クロックに同期したタイミングで出力が変化する「同期型のフリップフロップ動作」というものが良く使われます。入力信号の変化で勝手に出力が変化するフリップフロップに比べて動作タイミングの管理ができ、複数のFFを組み合わせた複雑な機能を、計画通りに確実に動作させやすくなります。また、誤動作の原因となるような微小幅のパルスの発生を防止できるなど、信頼性の高い回路を構築するためには欠かせない技術となっています。今回は、前回ご紹介した非同期型RS−FF回路と比較しつつ、同期型RS−FF回路のご紹介をしてみることにしましょう。
■412−1.非同期型RS−FF回路のおさらい
前回ご紹介した非同期型RS−FF回路は、以下のようなものでした。

| S | R | 出力Qの状態 |
| 0 | 0 | 出力状態を保持し、変化なし |
| 0 |
1 |
0にリセット |
| 1 |
0 |
1にセット |
| 1 | 1 | 出力確定せず。この組み合わせは禁止入力 |
※出力Qバー(QB)は、出力Qとは常に反転した出力となります。ただし、S、Rともに1の禁止入力状態ではその限りではありません。
非同期型RS−FF回路では、入力信号が変化したタイミングで出力信号も変化します。
では、VHDLの記述を見てみましょう。幾つかの記述方法がありましたが、今回は動作レベルでcase文を使ったプログラムを見てみます。このプログラムは前回ご紹介したものと同じです。ここをクリックするとダウンロードできます。RS_FF3.VHD
| ------------------------------------------ -- RS_FF3 2004.08.13 -- RIKIYA -- DOUSA LEVEL case BUN ------------------------------------------ library ieee; use ieee.std_logic_1164.all; entity RS_FF3 is port( R,S : in std_logic; Q,QB : out std_logic); end RS_FF3; ------------------------------------------ architecture RTL of RS_FF3 is signal R_S : std_logic_vector(1 downto 0); begin R_S <= R & S; -- 2 BIT DATA NI SURU process(R_S) begin case R_S is when "01" => Q <= '1'; QB <= '0'; -- SET when "10" => Q <= '0'; QB <= '1'; -- RESET when "11" => Q <= '0'; QB <= '0'; -- KINSHI when others => null; -- NANI MO SHINAI end case; end process; end RTL; |
VHDLプログラムの解説は前回の411.VHDLの色々な記述方法(RS-FF回路)をご参照頂くとして、ここでは注目すべき点だけをお話します。
注目して頂きたいのは、process(R_S) です。
これは、R_S つまり R_S <= R & S; によって1ビット目にRの値、0ビット目にSの値を格納した2ビットのレジスタの値に変化があったことを検知して、続く begin 〜 end process; の間の処理を実行するということです。リセット入力であるRか、セット入力であるSのどちらかに変化があった場合にR_Sの値が変化するため、これは入力信号に変化があったタイミングでcase文が実行され、条件に合った出力信号が変化するということになります。
回りくどくなりましたが、結局は入力信号の変化のタイミングで出力信号が変化するという動作をさせています。
■412−2.同期型RS−FF回路
さて、次に同期型RS−FF回路を見てみましょう。
| CLK | S | R | 出力Qの状態 |
| − | 0 | 0 | 出力状態を保持し、変化なし |
| − | 0 |
1 |
出力状態を保持し、変化なし |
| − | 1 |
0 |
出力状態を保持し、変化なし |
| − | 1 | 1 | 出力状態を保持し、変化なし |
| ↑ | 0 | 0 | 出力状態を保持し、変化なし |
| ↑ | 0 |
1 |
0にリセット |
| ↑ | 1 |
0 |
1にセット |
| ↑ | 1 | 1 | 出力確定せず。この組み合わせは禁止入力 |
前出のRとSの入力の他に、CLKという入力端子が追加されています。これはクロック入力のことです。このクロック入力がどのように回路動作に影響するのでしょう。
上の動作表がクロック入力に同期した同期型RS-FF回路の動作です。RとSの入力信号に対する出力信号の変化は非同期式と変わりませんが、出力が変化するタイミングは、CLKクロック入力信号の立ち上がりタイミングの時に限られます。黄色いエリアでは、RやS入力が色々と変化していますが、CLK入力に変化がないために出力にも変化が現れない様子を示しています。それに対して、緑色のエリアでは、CLKクロック入力の立ち上がりタイミングの時のRとSの入力信号の状態によって、出力状態が変化することを示しています。 クロック入力の立ち上がりタイミングの時に出力が変化する。それが同期型動作です。
では、VHDLの記述を見てみましょう。前項でご紹介したプログラムと同じく、動作レベルでcase文を使ったプログラムで見てみましょう。青い太字の部分が、非同期型の時と違う部分です。 ここをクリックするとダウンロードできます。RS_FF4.VHD
| ------------------------------------------ -- RS_FF4 2004.08.13 -- RIKIYA -- CLK DOUKI ------------------------------------------ library ieee; use ieee.std_logic_1164.all; entity RS_FF4 is port( R,S,CLK : in std_logic; Q,QB : out std_logic); end RS_FF4; ------------------------------------------ architecture RTL of RS_FF4 is signal R_S : std_logic_vector(1 downto 0); begin R_S <= R & S; -- 2 BIT DATA NI SURU process(CLK) begin if ( CLK' event and CLK = '1' ) then case R_S is when "01" => Q <= '1'; QB <= '0'; -- SET when "10" => Q <= '0'; QB <= '1'; -- RESET when "11" => Q <= '0'; QB <= '0'; -- KINSHI when others => null; -- NANI MO SHINAI end case; end if; end process; end RTL; |
それでは、非同期型の場合とどこが違うのか見てみましょう。
port( R,S,CLK : in std_logic;
先ず、エンティティ文の中で、CLK入力端子を追加で宣言しています。これは当然ですね。
process(CLK)
そしてprocess文の中で、非同期型では process(R_S) だったのを、process(CLK) にしました。つまり、CLK入力に変化があった時だけ、次のbegin 〜 end process;の中の処理を行うようにしているのです。
if ( CLK' event and CLK = '1' ) then 〜 end if;
さて、このif文ですが、CLK信号の変化タイミング(イベント発生のタイミング)で、尚且つCLK信号の状態が1の時だけ処理を実行するということです。つまり、CLK信号の立ち上がりタイミングの時だけ、処理を実行するという意味になります。この記述は、今後良く利用することになりますので、是非覚えておきましょう。 if文の中味のcase文は、非同期型と一緒です。つまり、その処理を実行させるタイミングだけを、CLK信号の立ち上がりタイミングに合わせているということになります。
今までのVHDLプログラムで、なんとなくVHDLというものが見えてきましたか? 書いている本人がまだよく分かっていないので、ちょっと無理かも知れませんが...
でも、74シリーズなどの汎用TTLロジックIC程度であれば、こんな調子でその機能を再現させることは簡単です。前回、今回と眺めてきたRS-FF回路は何種類かあるフリップフロップの中でも最も基本的なものです。そして、フリップフロップは動的なロジック回路を構築する上で元も重要な要素です。この次には、RS-FF以外の基本的なフリップフロップをご紹介することにしましょう。