【VHDL】7セグメントLEDディスプレイ×4に対応した10進数カウンタ
VHDLによる設計
チャタリング除去回路<ELIMINATOR.vhdl>
library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_unsigned.all; use IEEE.std_logic_arith.all; use IEEE.numeric_std.all; entity ELIMINATOR is port ( CLK : in std_logic; SW : in std_logic; SOUT : out std_logic := '1' ); end ELIMINATOR; architecture RTL of ELIMINATOR is signal F1 : std_logic := '0'; signal F2 : std_logic := '0'; signal TP : std_logic := '1'; begin process(CLK) begin if (rising_edge(CLK)) then F2 <= F1; F1 <= SW; end if; end process; TP <= F1 or not F2; process(CLK) begin if (falling_edge(CLK)) then SOUT <= TP; end if; end process; end RTL;
7セグメントデコーダ点灯回路<SSD_DECODER.vhdl>
表示させたい数字を入力し,どのセグメントを点灯させるかを出力する. 記憶の限りでは,カソードコモンダイナミックタイプだったと思う.
library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_unsigned.all; entity SSD_DECODER is port ( BIN : in std_logic_vector(3 downto 0); SSD : out std_logic_vector(7 downto 0) ); end SSD_DECODER; architecture RTL of SSD_DECODER is begin DECORD : process(BIN) begin case BIN is when X"0" => SSD <= X"03"; when X"1" => SSD <= X"9F"; when X"2" => SSD <= X"25"; when X"3" => SSD <= X"0D"; when X"4" => SSD <= X"99"; when X"5" => SSD <= X"49"; when X"6" => SSD <= X"41"; when X"7" => SSD <= X"1B"; when X"8" => SSD <= X"01"; when X"9" => SSD <= X"09"; when X"A" => SSD <= X"11"; when X"B" => SSD <= X"C1"; when X"C" => SSD <= X"63"; when X"D" => SSD <= X"85"; when X"E" => SSD <= X"61"; when X"F" => SSD <= X"71"; when others => SSD <= "XXXXXXXX"; end case; end process; end RTL;
マルチプレクサ回路<MULTIPLEXER.vhdl>
今回使用する7セグメントLEDは,ダイナミックタイプのため,複数行を表示させるとき,高速に出力するポートを切り替える必要がある.マルチプレクサ回路では,どのポートに出力するかを決定する.
library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_unsigned.all; entity MULTIPLEXER is port ( INA : in std_logic_vector(3 downto 0); INB : in std_logic_vector(3 downto 0); INC : in std_logic_vector(3 downto 0); IND : in std_logic_vector(3 downto 0); SEL : in std_logic_vector(3 downto 0); DOUT : out std_logic_vector(3 downto 0) ); end MULTIPLEXER; architecture RTL of MULTIPLEXER is begin MUX : process(INA, INB, INC, IND, SEL) begin case SEL is when "1110" => DOUT <= INA; when "1101" => DOUT <= INB; when "1011" => DOUT <= INC; when "0111" => DOUT <= IND; when others => DOUT <= "1110"; end case; end process; end RTL;
シフトレジスタ回路<Shift_reg.vhdl>
ダイナミックタイプの7セグメントLEDにおいて,シフトレジスタ回路では 出力したいポートが'1'である4bitの数値をマルチプレクサ回路のセレクトポートに出力している.
library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; use IEEE.std_logic_unsigned.all; entity SHIFT_REG is port ( CLK : in std_logic; RST : in std_logic; SR : out std_logic_vector(3 downto 0) ); end SHIFT_REG; architecture RTL of SHIFT_REG is signal srs : std_logic_vector(3 downto 0) := "1110"; begin SR <= srs; SHIFTER : process(CLK) begin if (CLK'event and CLK = '1') then if (RST = '0') then srs<="1110"; end if; srs(3) <= srs(2); srs(2) <= srs(1); srs(1) <= srs(0); srs(0) <= srs(3); end if; end process; end RTL;
カウンタ回路<Counter.vhdl>
カウンタ回路では,入力された周波数のカウントを行い, 秒数へと変換を行うための回路である.
library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_unsigned.all; use IEEE.std_logic_arith.all; entity Counter is generic (N : integer := 25000); port ( CLK : in std_logic; RST : in std_logic; CO : out std_logic ); end Counter; architecture RTL of Counter is signal CNT : integer:=0; begin CO <= '1' when (CNT=N) else '0'; COUNT : process(CLK) begin if (CLK'event and CLK = '1') then if (CNT = N) then CNT <= 0; else CNT <= CNT + 1; end if; end if; end process; end RTL;
メイン回路<Watch.vhdl>
メイン回路では,ボタンの入力や1/100秒カウントや1秒カウント,カウントの総数を管理している.
library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_unsigned.all; entity Watch is port ( CLK : in std_logic; RST : in std_logic; -- reset SAT : in std_logic; -- start STP : in std_logic; -- stop SEG : out std_logic_vector(7 downto 0); SEL : out std_logic_vector(3 downto 0) ); end Watch; architecture RTL of Watch is -- component component SSD_DECODER is port ( BIN : in std_logic_vector(3 downto 0); SSD : out std_logic_vector(7 downto 0) ); end component; component MULTIPLEXER is port ( INA : in std_logic_vector(3 downto 0); INB : in std_logic_vector(3 downto 0); INC : in std_logic_vector(3 downto 0); IND : in std_logic_vector(3 downto 0); SEL : in std_logic_vector(3 downto 0); DOUT : out std_logic_vector(3 downto 0) ); end component; component Counter is generic (N : integer); port ( CLK : in std_logic; RST : in std_logic; CO : out std_logic ); end component; component SHIFT_REG is port ( CLK : in std_logic; RST : in std_logic; SR : out std_logic_vector(3 downto 0) ); end component; component ELIMINATOR is port ( CLK : in std_logic; SW : in std_logic; SOUT : out std_logic := '1' ); end component; -- signal signal co25000 : std_logic; signal co1000 : std_logic; signal act : std_logic := '0'; -- active or not active signal segment : std_logic_vector(15 downto 0) := X"0000"; signal sr : std_logic_vector(3 downto 0); signal dout : std_logic_vector(3 downto 0); signal flag : boolean; signal ERST : std_logic; signal ESAT : std_logic; signal ESTP : std_logic; begin SW_CNT01 : Counter generic map (25000) port map (CLK, RST, co25000); SW_CNT1s : Counter generic map (1000) port map (co25000, RST, co1000); SW_SHIFT : SHIFT_REG port map (co25000, RST, sr); --SW_MUX : MULTIPLEXER port map (INA=>segment(15 downto 12), INB=>segment(11 downto 8), -- INC=>segment(7 downto 4), IND=>segment(3 downto 0), -- SEL=>sr, DOUT=>dout); SW_MUX : MULTIPLEXER port map (INA=>segment(3 downto 0), INB=>segment(7 downto 4), INC=>segment(11 downto 8), IND=>segment(15 downto 12), SEL=>sr, DOUT=>dout); SW_SSD : SSD_DECODER port map (dout, SEG); SW_SW1 : ELIMINATOR port map (co25000, RST, ERST); SW_SW2 : ELIMINATOR port map (co25000, SAT, ESAT); SW_SW3 : ELIMINATOR port map (co25000, STP, ESTP); SEL <= sr; --process(CLK) --begin -- if (RST = '0') then -- segment <= X"0000"; -- end if; --end process; process(co25000) begin --if (rising_edge(co1000)) then if (ERST = '0') then segment <= X"0000"; flag <= False; elsif (ESTP = '0') then flag <= False; elsif (ESAT = '0') then flag <= True; elsif (rising_edge(co1000) and flag = True) then --if (co1000 = '1') then if (segment = X"9999") then segment <= X"0000"; elsif ((segment and X"0FFF") = X"0999") then segment(15 downto 12) <= segment(15 downto 12) + '1'; segment(11 downto 0) <= X"000"; elsif ((segment and X"00FF") = X"0099") then segment(15 downto 8) <= segment(15 downto 8) + '1'; segment(7 downto 0) <= X"00"; elsif ((segment and X"000F") = X"0009") then segment(15 downto 4) <= segment(15 downto 4) + '1'; segment(3 downto 0) <= X"0"; else segment <= segment + X"0001"; --segment <= segment; end if; --end if; end if; end process; end RTL;
動作環境など
Quartus II 11.1 sp.1,USB-Blaster,MAXVを使用した. ピンアサインの設定を以下に示す. 一応,動作確認済みですが,何かの手違いにより, うまく動作しないかもしれません.