FPGA環境でJKフリップフロップの動作を確認(シミュレーション編)
エレキ素人が何か考える(その9):JKフリップフロップでの予告のどおり、ハードウェアに近い環境であるFPGAで、動作確認を行う。今回はシミュレーション編。
CLK付きJKフリップフロップ回路
開発環境
その1からずっと同じOdyssey MAX10 FPGA Eval Kitを対象として、Quartusを利用する。
コード
本体
library ieee;
use ieee.std_logic_1164.all;
entity JK is
port (CLK, J, K : in std_logic; -- ①
Q, Qbar : out std_logic); -- ②
end;
architecture RTL of JK is
signal out1 : std_logic := '0'; -- ③
signal out2 : std_logic := '0';
signal out3 : std_logic := '1';
signal out4 : std_logic := '0';
begin
process (CLK)
begin
if (rising_edge(CLK)) then -- ④
out1 <= J and out3;
out2 <= K and out4;
-- out3 <= not(out1 or out4); -- does not work -- ⑤
-- out4 <= not(out2 or out3); -- does not work
end if;
end process;
out3 <= not(out1 or out4); -- ⑥
out4 <= not(out2 or out3);
Q <= out4;
Qbar <= out3;
end RTL;
- ①:入力信号(CLK、J、K)
- ②:出力信号(Q、Qbar(Q#))
- ③:回路内信号(out1、out2、out3、out4)の定義および初期化(Q='0'、Q#='1'となるように値を選択)
- begin - end内は同時処理
- ④:CLK(クロック)立ち上がり時の回路内のAND部分の処理
- ⑥:回路内のNOR部分の処理
VHDLが理解できれば、ロジックどおりなので、詳細な説明は不要であろう。
シミュレーションコード
信号JおよびKを変化させてシミュレーションする。信号の組み合わせは、(0,0)、(0,1)、(1,0)、(1,1)の4通り、よって状態の変化は、4x3=12通り存在するので、それらをCLKの有無を加えて、シミュレーションするコードが下記となる(全体で10回の繰り返しあり)。
library ieee;
use ieee.std_logic_1164.all;
entity testsim is
end testsim;
architecture sim of testsim is
constant t : time := 1 us;
signal CLK, J, K : std_logic;
signal Q : std_logic := '0';
signal Qbar : std_logic := '1';
component JK
port (J, K, CLK : in std_logic;
Q, Qbar : out std_logic);
end component;
begin
u1: JK
port map (CLK => CLK, J => J, K => K, Q => Q, Qbar => Qbar);
process begin
for N in 1 to 10 loop
CLK <= '0'; J <= '0'; K <= '1'; wait for t; -- 0 (0,1)
CLK <= '1'; J <= '0'; K <= '1'; wait for t;
CLK <= '0'; J <= '1'; K <= '1'; wait for t; -- 1 (1,1)
CLK <= '1'; J <= '1'; K <= '1'; wait for t;
CLK <= '0'; J <= '1'; K <= '0'; wait for t; -- 2 (1,0)
CLK <= '1'; J <= '1'; K <= '0'; wait for t;
CLK <= '0'; J <= '0'; K <= '0'; wait for t; -- 3 (0,0)
CLK <= '1'; J <= '0'; K <= '0'; wait for t;
CLK <= '0'; J <= '0'; K <= '1'; wait for t; -- 4 (0,1)
CLK <= '1'; J <= '0'; K <= '1'; wait for t;
CLK <= '0'; J <= '0'; K <= '0'; wait for t; -- 5 (0,0)
CLK <= '1'; J <= '0'; K <= '0'; wait for t;
CLK <= '0'; J <= '1'; K <= '1'; wait for t; -- 6 (1,1)
CLK <= '1'; J <= '1'; K <= '1'; wait for t;
CLK <= '0'; J <= '0'; K <= '1'; wait for t; -- 7 (0,1)
CLK <= '1'; J <= '0'; K <= '1'; wait for t;
CLK <= '0'; J <= '1'; K <= '0'; wait for t; -- 8 (1,0)
CLK <= '1'; J <= '1'; K <= '0'; wait for t;
CLK <= '0'; J <= '1'; K <= '1'; wait for t; -- 9 (1,1)
CLK <= '1'; J <= '1'; K <= '1'; wait for t;
CLK <= '0'; J <= '0'; K <= '0'; wait for t; -- 10 (0,0)
CLK <= '1'; J <= '0'; K <= '0'; wait for t;
CLK <= '0'; J <= '1'; K <= '0'; wait for t; -- 11 (1,0)
CLK <= '1'; J <= '1'; K <= '0'; wait for t;
-- 12 (0,1)
end loop;
end process;
end sim;
シミュレーションによる検証
上記シミュレーションコード(testsim.vhd)を用いて、本体コード(JK.vhd)をテストした結果(1サイクル+α)が下記となる。
最初の数回分を一部拡大表示(上から、CLK、J、K、Q、Q#(Qbar))。さらに真理値表を再掲。
CLK立ち上がり時に、期待どおりの結果が得られていることがわかる。
また、上述した本体コードの⑥以下2行の代わりに、⑤以下2行を用いたときの結果は下記となり、QとQbarとが反転していないタイミング(同じ値となる)が存在する。
回路上の左のAND回路と右のNOR回路は、Process文内で順番に実施してはいけないということを意味するはず、、(FPGA内で同時処理が必要)。
(間違っていたら、どなたか、ご指摘ください。)
次は
上記本体コードをコンポーネントとして用い、FPGAボードで検証を行う。