前回に、DE10-Lite評価ボードを使用して、LEDの点灯をシフトする機能を作成しました。前々回の内容は下記を参照してください。
今回は、DE10-Lite評価ボードを使用して、24時間をカウントする機能を
構築したいと思います。今回も使用する言語は、VHDLです。
24時間カウンタ機能の仕様は下記の通りです。
- DE10-Liteには、7セグメントが6個用意されています。その中の2個ずつを、秒、分、時に割り当てます。
- Resetボタンを押すと、00時00分00秒になります。
- 24時間になった場合、00時00分00秒になります。
それでは、機能を構築していきたいと思います。前回使用したプロジェクトをコピーして使用します。前回の内容は、下記のリンクを参考にしてください。PLLファイルの生成なども行っています。
クロックはPLLで生成した「10MHz」を使用します。VHDLファイルに動作内容を記述していきます。下記のように記述しました。
library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_unsigned.all; use IEEE.std_logic_arith.all; entity sec_counter_top is -- Output pin port( CLK : in std_logic; -- 50MHz Clock RST_N : in std_logic; LED_OUT : out std_logic_vector(9 downto 0); SEG7_0_OUT : out std_logic_vector(7 downto 0); SEG7_1_OUT : out std_logic_vector(7 downto 0); SEG7_2_OUT : out std_logic_vector(7 downto 0); SEG7_3_OUT : out std_logic_vector(7 downto 0); SEG7_4_OUT : out std_logic_vector(7 downto 0); SEG7_5_OUT : out std_logic_vector(7 downto 0) ); end sec_counter_top; architecture rtl of sec_counter_top is -- Internal process component pll is -- pll port( inclk0 : in std_logic; -- 50MHz Clock c0 : out std_logic -- 10MHz Clock ); end component; signal s_clk : std_logic; -- 10MHz Clock signal signal en_sec_1 : std_logic; signal en_min_1 : std_logic; signal en_hour_1 : std_logic; signal en_sec_10 : std_logic; signal en_min_10 : std_logic; signal en_hour_10 : std_logic; signal en_hour_flg : std_logic_vector(3 downto 0); signal cnt : std_logic_vector(23 downto 0); signal sec_1_cnt : std_logic_vector(3 downto 0); signal min_1_cnt : std_logic_vector(3 downto 0); signal hour_1_cnt : std_logic_vector(3 downto 0); signal min_10_cnt : std_logic_vector(3 downto 0); signal sec_10_cnt : std_logic_vector(3 downto 0); signal hour_10_cnt : std_logic_vector(3 downto 0); signal counter_led : std_logic_vector(9 downto 0); begin u0_pll : pll port map( inclk0 => CLK, --in std_logic(50MHz) c0 => s_clk --out std_logic(10MHz) ); -- 1 sec -- en_sec_1 <= '1' when (cnt = X"AD9") else '0'; -- 1 / 3600 sec en_sec_1 <= '1' when (cnt = X"989659") else '0'; -- 1 sec process(s_clk, RST_N) -- s_clkに変化があった時 begin if(RST_N = '0')then cnt <= (others=>'0'); elsif(s_clk'event and s_clk = '1')then -- s_clk 変化有り 且つ s_clk = 1の時 →クロックの立ち上がりエッジ if(en_sec_1 = '1')then cnt <= (others=>'0'); else cnt <= cnt + '1'; end if; end if; end process; process(s_clk, RST_N) begin if(RST_N = '0')then sec_1_cnt <= X"0"; elsif(s_clk'event and s_clk = '1')then -- s_clk 変化有り 且つ s_clk = 1の時 →クロックの立ち上がりエッジ if(en_sec_1 = '1')then sec_1_cnt <= sec_1_cnt + '1'; else if(sec_1_cnt = X"A")then sec_1_cnt <= X"0"; end if; end if; end if; end process; process(s_clk, RST_N) begin if(RST_N = '0')then SEG7_0_OUT <= "11000000"; elsif(s_clk'event and s_clk = '1')then -- s_clk 変化有り 且つ s_clk = 1の時 →クロックの立ち上がりエッジ case sec_1_cnt is when X"1" => SEG7_0_OUT <= "11111001"; when X"2" => SEG7_0_OUT <= "10100100"; when X"3" => SEG7_0_OUT <= "10110000"; when X"4" => SEG7_0_OUT <= "10011001"; when X"5" => SEG7_0_OUT <= "10010010"; when X"6" => SEG7_0_OUT <= "10000010"; when X"7" => SEG7_0_OUT <= "11011000"; when X"8" => SEG7_0_OUT <= "10000000"; when X"9" => SEG7_0_OUT <= "10011000"; when others => SEG7_0_OUT <= "11000000"; end case; end if; end process; -- 10 sec en_sec_10 <= '1' when (sec_1_cnt = X"A") else '0'; -- 10 sec process(s_clk, RST_N) begin if(RST_N = '0')then -- sec_10_cnt <= X"5"; sec_10_cnt <= X"0"; elsif(s_clk'event and s_clk = '1')then -- s_clk 変化有り 且つ s_clk = 1の時 →クロックの立ち上がりエッジ if(en_sec_10 = '1')then sec_10_cnt <= sec_10_cnt + '1'; else if(sec_10_cnt = X"6")then sec_10_cnt <= X"0"; end if; end if; end if; end process; process(s_clk, RST_N) begin if(RST_N = '0')then -- SEG7_1_OUT <= "10010010"; SEG7_1_OUT <= "11000000"; elsif(s_clk'event and s_clk = '1')then -- s_clk 変化有り 且つ s_clk = 1の時 →クロックの立ち上がりエッジ case sec_10_cnt is when X"1" => SEG7_1_OUT <= "11111001"; when X"2" => SEG7_1_OUT <= "10100100"; when X"3" => SEG7_1_OUT <= "10110000"; when X"4" => SEG7_1_OUT <= "10011001"; when X"5" => SEG7_1_OUT <= "10010010"; when others => SEG7_1_OUT <= "11000000"; end case; end if; end process; -- 1 min en_min_1 <= '1' when (sec_10_cnt = X"6") else '0'; -- 1 min process(s_clk, RST_N) begin if(RST_N = '0')then -- min_1_cnt <= X"9"; min_1_cnt <= X"0"; elsif(s_clk'event and s_clk = '1')then -- s_clk 変化有り 且つ s_clk = 1の時 →クロックの立ち上がりエッジ if(en_min_1 = '1')then min_1_cnt <= min_1_cnt + '1'; else if(min_1_cnt = X"A")then min_1_cnt <= X"0"; end if; end if; end if; end process; process(s_clk, RST_N) begin if(RST_N = '0')then -- SEG7_2_OUT <= "10011000"; SEG7_2_OUT <= "11000000"; elsif(s_clk'event and s_clk = '1')then -- s_clk 変化有り 且つ s_clk = 1の時 →クロックの立ち上がりエッジ case min_1_cnt is when X"1" => SEG7_2_OUT <= "11111001"; when X"2" => SEG7_2_OUT <= "10100100"; when X"3" => SEG7_2_OUT <= "10110000"; when X"4" => SEG7_2_OUT <= "10011001"; when X"5" => SEG7_2_OUT <= "10010010"; when X"6" => SEG7_2_OUT <= "10000010"; when X"7" => SEG7_2_OUT <= "11011000"; when X"8" => SEG7_2_OUT <= "10000000"; when X"9" => SEG7_2_OUT <= "10011000"; when others => SEG7_2_OUT <= "11000000"; end case; end if; end process; -- 10 min en_min_10 <= '1' when (min_1_cnt = X"A") else '0'; -- 10 min process(s_clk, RST_N) begin if(RST_N = '0')then -- min_10_cnt <= X"5"; min_10_cnt <= X"0"; elsif(s_clk'event and s_clk = '1')then -- s_clk 変化有り 且つ s_clk = 1の時 →クロックの立ち上がりエッジ if(en_min_10 = '1')then min_10_cnt <= min_10_cnt + '1'; else if(min_10_cnt = X"6")then min_10_cnt <= X"0"; end if; end if; end if; end process; process(s_clk, RST_N) begin if(RST_N = '0')then -- SEG7_3_OUT <= "10010010"; SEG7_3_OUT <= "11000000"; elsif(s_clk'event and s_clk = '1')then -- s_clk 変化有り 且つ s_clk = 1の時 →クロックの立ち上がりエッジ case min_10_cnt is when X"1" => SEG7_3_OUT <= "11111001"; when X"2" => SEG7_3_OUT <= "10100100"; when X"3" => SEG7_3_OUT <= "10110000"; when X"4" => SEG7_3_OUT <= "10011001"; when X"5" => SEG7_3_OUT <= "10010010"; when others => SEG7_3_OUT <= "11000000"; end case; end if; end process; -- 1 hour en_hour_1 <= '1' when (min_10_cnt = X"6") else '0'; -- 1 hour process(s_clk, RST_N) begin if(RST_N = '0')then -- hour_1_cnt <= X"9"; hour_1_cnt <= X"0"; en_hour_flg <= X"F"; elsif(s_clk'event and s_clk = '1')then -- s_clk 変化有り 且つ s_clk = 1の時 →クロックの立ち上がりエッジ if(en_hour_1 = '1')then hour_1_cnt <= hour_1_cnt + '1'; en_hour_flg <= X"E"; elsif(en_hour_flg = X"E")then if(hour_10_cnt = X"2")then if(hour_1_cnt = X"4")then en_hour_flg <= X"4"; end if; else if(hour_1_cnt = X"A")then en_hour_flg <= X"A"; end if; end if; else if(en_hour_flg = X"4")then hour_1_cnt <= X"0"; en_hour_flg <= X"F"; elsif(en_hour_flg = X"A")then hour_1_cnt <= X"0"; en_hour_flg <= X"F"; end if; end if; end if; end process; process(s_clk, RST_N) begin if(RST_N = '0')then -- SEG7_4_OUT <= "10011000"; SEG7_4_OUT <= "11000000"; elsif(s_clk'event and s_clk = '1')then -- s_clk 変化有り 且つ s_clk = 1の時 →クロックの立ち上がりエッジ case hour_1_cnt is when X"1" => SEG7_4_OUT <= "11111001"; when X"2" => SEG7_4_OUT <= "10100100"; when X"3" => SEG7_4_OUT <= "10110000"; when X"4" => SEG7_4_OUT <= "10011001"; when X"5" => SEG7_4_OUT <= "10010010"; when X"6" => SEG7_4_OUT <= "10000010"; when X"7" => SEG7_4_OUT <= "11011000"; when X"8" => SEG7_4_OUT <= "10000000"; when X"9" => SEG7_4_OUT <= "10011000"; when others => SEG7_4_OUT <= "11000000"; end case; end if; end process; -- 10 hour en_hour_10 <= '1' when (hour_1_cnt = en_hour_flg) else '0'; -- 10 hour process(s_clk, RST_N) begin if(RST_N = '0')then -- hour_10_cnt <= X"1"; hour_10_cnt <= X"0"; elsif(s_clk'event and s_clk = '1')then -- s_clk 変化有り 且つ s_clk = 1の時 →クロックの立ち上がりエッジ if(en_hour_10 = '1')then hour_10_cnt <= hour_10_cnt + '1'; else if(hour_10_cnt = X"3")then hour_10_cnt <= X"0"; end if; end if; end if; end process; process(s_clk, RST_N) begin if(RST_N = '0')then -- SEG7_5_OUT <= "11111001"; SEG7_5_OUT <= "11000000"; elsif(s_clk'event and s_clk = '1')then -- s_clk 変化有り 且つ s_clk = 1の時 →クロックの立ち上がりエッジ case hour_10_cnt is when X"1" => SEG7_5_OUT <= "11111001"; when X"2" => SEG7_5_OUT <= "10100100"; when others => SEG7_5_OUT <= "11000000"; end case; end if; end process; -- 1sec blink led process(s_clk, RST_N) begin if(RST_N = '0')then counter_led <= "0000000001"; elsif(s_clk'event and s_clk = '1')then -- s_clk 変化有り 且つ s_clk = 1の時 →クロックの立ち上がりエッジ if(en_sec_1 = '1')then counter_led(1) <= counter_led(0); counter_led(2) <= counter_led(1); counter_led(3) <= counter_led(2); counter_led(4) <= counter_led(3); counter_led(5) <= counter_led(4); counter_led(6) <= counter_led(5); counter_led(7) <= counter_led(6); counter_led(8) <= counter_led(7); counter_led(9) <= counter_led(8); counter_led(0) <= counter_led(9); end if; end if; end process; LED_OUT <= counter_led; end rtl;
次に、Tasksから「Compile Design」をダブルクリックして実行します。(「Analysis & Synthesis」のみ実行してもよいと思います。)
「Compile Design」が成功したら、ピンの設定をします。メニューから「Assignments」→「Pin Planner」を選択します。ピンの設定を行う画面が表示されるので、下記のようにピンを設定します。
その他に関しては、下記のサイトと同様です。
それでは、再度、Tasksから「Compile Design」をダブルクリックして実行します。「Compile Design」が成功したら、書き込みを行い、実行します。書き込み方法は下記のサイト参考にしてください。
書き込みを行い、実行すると7セグメントが動作していています。動作確認をするにあたって24時間DE10-Liteを見るのはつらいので、KEY0ボタンを押した時のリセット値や1秒間のカウンタの値を調整して動作確認をしました。
例えば、下記のようにすれば、時間の7セグメントを1秒間隔で動作することができます。
今回、24時間カウンタを作成しましたが、目視では確認できないですが、カウンタのズレが発生していると思います。例えば下記の部分がそうです。
24時間経過後に、00時間になりますが、時間の1の位が2クロック遅れて、0になります。秒の部分がズレてはいないので、全体的に遅れが生じることはないと思いますが、うーんって感じです。もう少し遅れが生じないような仕組みを考えたいところです。
また、7セグメントに信号を送る処理をprocess処理のcase文で行っていますが、ここもカウンタが更新されて1クロック遅れて更新されていると思いわれます。下記のように回路図でみるとレジスタから出力されています。そのため、1クロック遅れていると思います。
目視でみて問題ないような内容ではありますが、ここも見直したいと思います