Re/Coder

知識蓄積備忘録/State-of-the-Ars

【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を使用した. ピンアサインの設定を以下に示す. f:id:zigzackey:20161124132236p:plain 一応,動作確認済みですが,何かの手違いにより, うまく動作しないかもしれません.