あのFPGAボードで 7セグメントLED をドライブする①
1. はじめに
あのFPGAボード(WINGONEER ALTERA FPGA Cyclonell EP2C5T144)で、定番の7セグメントLED(とりあえず今回は1ケタ)をドライブする基本的な記事です。QuartusⅡ自体の操作に慣れるという意味でも、再現できるように、できるかぎり具体的な手順を追って書いていきます。
VHDLで記述した回路をブロック図(Block Diagram)として登録し、それらブロック図をグラフィカルにつなぎ合わせて、目的とする「機能」をもつ回路を設計するやり方を、自分への備忘録も兼ねて書きます。
2. 実装する機能について
・7セグメントLED がタクトスイッチを1回押すたびごとに、カウントアップする。
・そうして、0~9までの数を数えられる。(今回、とりあえず7セグLEDは1個だけの使用です)
・タクトスイッチを押したときのチャタリング防止機能をつける。
(チャタリングとは、スイッチを押すときに機械接点がバウンドして小刻みなON/OFFを繰り返す現象。入力状態が不安定になるので、防止対策をとるのが一般的)
3. 完成回路図
先に、QuartusⅡで簡単に設計した回路の完成図を図示します。最終的にはこんな感じで、VHDLのコードを書く、あるいは各種ブロック(シンボル)を組み合わせながら開発をして、目的とする「機能」を実装していきます。
なお、この全体回路図の中に含まれているブロックのそれぞれは単一の機能をもつモジュールのようなもので、これらを組み合わせて(組み合わせ論理回路)、うまい具合に目的の「機能」を実装します。この図では、外からの見た目はブロックのように見えるものの、中身はVHDLコードで記述されており、あくまでも人が開発する上で理解しやすいグラフィカルな表示になっているだけです(たしか...)。
この図から、2入力(CLK, SW)、8出力(7セグLED + 小数点LED1つ)の回路をこれから組み上げていくイメージをなんとなく先に持っておくと理解しやすいかと思います。
4. 実験回路の作製
FPGAボード、7セグメントLED、タクトスイッチの実体配線は図のような感じになりました。ジャンパワイヤでごちゃごちゃしてますが、ブレッドボード上での実験ということでいつも通りです。7セグLEDのピン配置については、こちらの記事を参考にさせていただきました。
スイッチ側のプルアップ抵抗は入れましたが、7セグLEDへの電流制限抵抗は今回自分は入れませんでした...( ゚Д゚)。Quartus上で設定するピンアサインと実体配線が一致するように注意します。Quartus上でのピンアサイン図を載せておきますので、それを参考に実験回路を作製してください。
5. VHDLコード全文とBlock Diagram (~.bdf)上での回路設計
BINCNT4.vhd
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity BINCNT4 is
port( DIN : in std_logic;
SEG7LED : out std_logic_vector(7 downto 0) );
end BINCNT4;
architecture RTL of BINCNT4 is
signal BIN4 : std_logic_vector(3 downto 0);
begin
--カウンタ
process(DIN)
begin
if(DIN'event and DIN = '1') then
if( BIN4 = "1001" ) then
BIN4 <= "0000";
else
BIN4 <= BIN4 + 1;
end if;
end if;
end process;
process(BIN4)
begin
case BIN4 is
when "0000" => SEG7LED <= "00000011"; --0
when "0001" => SEG7LED <= "10011111"; --1
when "0010" => SEG7LED <= "00100101"; --2
when "0011" => SEG7LED <= "00001101"; --3
when "0100" => SEG7LED <= "10011001"; --4
when "0101" => SEG7LED <= "01001001"; --5
when "0110" => SEG7LED <= "01000001"; --6
when "0111" => SEG7LED <= "00011011"; --7
when "1000" => SEG7LED <= "00000001"; --8
when "1001" => SEG7LED <= "00001001"; --9
when "1010" => SEG7LED <= "00010001"; --A
when "1011" => SEG7LED <= "11000001"; --b
when "1100" => SEG7LED <= "01101011"; --C
when "1101" => SEG7LED <= "10000101"; --d
when "1110" => SEG7LED <= "01100001"; --E
when others => SEG7LED <= "01110001"; --F
end case;
end process;
end RTL;
CHATTER.vhd
library ieee;
use ieee.std_logic_1164.all;
entity CHATTER is
port( SSW: out std_logic;
CLK, SW: in std_logic );
end CHATTER;
architecture RTL of CHATTER is
signal CHATT : std_logic_vector( 3 downto 0 );
signal CNT1MS: integer range 0 to 4999;
begin
process (CLK) begin
if ( CLK'event and CLK = '1') then
if(CNT1MS = 4999) then
CNT1MS <= 0;
CHATT <= CHATT (2 downto 0) & SW;
else
CNT1MS <= CNT1MS + 1;
end if;
end if;
end process;
SSW <= CHATT (3) or CHATT (2) or CHATT (1) or CHATT (0);
end RTL;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity BINCNT4 is
port( DIN : in std_logic;
SEG7LED : out std_logic_vector(7 downto 0) );
end BINCNT4;
architecture RTL of BINCNT4 is
signal BIN4 : std_logic_vector(3 downto 0);
begin
--カウンタ
process(DIN)
begin
if(DIN'event and DIN = '1') then
if( BIN4 = "1001" ) then
BIN4 <= "0000";
else
BIN4 <= BIN4 + 1;
end if;
end if;
end process;
process(BIN4)
begin
case BIN4 is
when "0000" => SEG7LED <= "00000011"; --0
when "0001" => SEG7LED <= "10011111"; --1
when "0010" => SEG7LED <= "00100101"; --2
when "0011" => SEG7LED <= "00001101"; --3
when "0100" => SEG7LED <= "10011001"; --4
when "0101" => SEG7LED <= "01001001"; --5
when "0110" => SEG7LED <= "01000001"; --6
when "0111" => SEG7LED <= "00011011"; --7
when "1000" => SEG7LED <= "00000001"; --8
when "1001" => SEG7LED <= "00001001"; --9
when "1010" => SEG7LED <= "00010001"; --A
when "1011" => SEG7LED <= "11000001"; --b
when "1100" => SEG7LED <= "01101011"; --C
when "1101" => SEG7LED <= "10000101"; --d
when "1110" => SEG7LED <= "01100001"; --E
when others => SEG7LED <= "01110001"; --F
end case;
end process;
end RTL;
library ieee;
use ieee.std_logic_1164.all;
entity CHATTER is
port( SSW: out std_logic;
CLK, SW: in std_logic );
end CHATTER;
architecture RTL of CHATTER is
signal CHATT : std_logic_vector( 3 downto 0 );
signal CNT1MS: integer range 0 to 4999;
begin
process (CLK) begin
if ( CLK'event and CLK = '1') then
if(CNT1MS = 4999) then
CNT1MS <= 0;
CHATT <= CHATT (2 downto 0) & SW;
else
CNT1MS <= CNT1MS + 1;
end if;
end if;
end process;
SSW <= CHATT (3) or CHATT (2) or CHATT (1) or CHATT (0);
end RTL;
・この2つのVHDLファイルが記述出来たら、それぞれをブロック図(シンボル)として登録してみます。VHDLファイルのタブで選んだ状態で、上部メニューバーの "File" -> "Create/Update" -> "Create Symbol Files for Current File" を選択すると、シンボル登録の完了です。
・シンボルとして登録が完了したら、Block Diagram上で図のようなアイコンを選択し、"Symbol"ウィンドウを開きます。すると、"Project"の中にいま生成したCHATTER
やBITCNT4
が回路図中に置くシンボルとして選択できるようになっています!!
・ここまででVHDLコードで記述したものをシンボルとしてブロック図のように組み合わせ、回路を設計することができるようになりました。下図のように、シンボルを置いたり各種配線をする(配線に名前を付けて配線すると確実です)などして設計が完了した回路図を、例えばtop.bdf
のファイル名で保存します。(※詳しい操作方法などはこちらのPDFを参考にしながらやりました)
・SEG7LED[7..0]
の出力バス(束)をNOTゲートで一度すべて反転させている理由は、使用した7セグLEDがカソードコモンである仕様に対応させるためです。(7セグLEDがアクティブLOWの想定でVHDLを書いていたのですが、後々確認したら7セグLEDがアクティブHIGHだったので...)
※設定上の注意点として...
・プロジェクト名を右クリックして表示されるメニューの "Settings.." -> "General"の"Top-level entity" で top.bdf
と設定する。
・"Settings.." -> "Files"の"File Name"欄にtop.bdf
, CHATTER.vhd
, BITCNT4.vhd
がすべて設定されているようにする。
6. 実験結果
タクトスイッチを1回押すごとに(しっかりとチャタリングが防止されたうえで)、7セグLEDに表示された数字が0~9のあいだでカウントアップされました!!
7. まとめ
あのFPGAボードと7セグメントLEDを1つ用いて、チャタリング防止しながらタクトスイッチを1回押すたびに0~9のあいだで確実に1カウントアップする基本的な回路の設計演習を行いました。次は同じハードウェアで桁数を増やしてとりあえずストップウォッチでしょうか...。
8. 参考図書
Author And Source
この問題について(あのFPGAボードで 7セグメントLED をドライブする①), 我々は、より多くの情報をここで見つけました https://qiita.com/uukxu/items/cfe87372be2117bc4e7c著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .