Re/Coder

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

【VHDL】Mealy型状態遷移回路を用いた30円の自動販売機の設計

Mealy型状態遷移回路を用いた30円の自動販売機の設計

以下に,Mealy型状態遷移回路を用いた30円の自動販売機のVHDLソースコードを表示する.

-- Vending Machine of Mealy State

library IEEE;
use IEEE.std_logic_1164.all;

entity MealyState30 is
    port (
        CLK, RESET : in std_logic;
        A, B : in std_logic;
        X, Y : out std_logic;
        Z : out std_logic_vector(2 downto 0)
    );
end MealyState30;

architecture RTL of MealyState30 is
    -- type statement
    type type_state is (S0, S1, S2, S3, S4, S5, S6, S7);

    signal state : type_state;
begin
    process(CLK)
    begin
        if (CLK'event and CLK = '1') then
            if (RESET = '0') then
                state <= S0;
            else
                case state is
                    when S0 =>
                        if (A = '1') then
                            state <= S1;
                        elsif (B = '1') then
                            state <= S5;
                        end if;
                    when S1 =>
                        if (A = '1') then
                            state <= S2;
                        elsif (B = '1') then
                            state <= S6;
                        end if;
                    when S2 =>
                        if (A = '1') then
                            state <= S3;
                        elsif (B = '1') then
                            state <= S7;
                        end if;
                    when S3 | S4 | S5 | S6 | S7 =>
                        state <= S0;
                end case;
            end if;
        end if;
    end process;

    -- Output Signal of Mealy State
    X <= '1' when (state = S2 and A = '1') or
                  (state = S0 and B = '1') or
                  (state = S1 and B = '1') or
                  (state = S2 and B = '1') else
         '0';

    Y <= '1' when (state = S2 and A = '1') or
                  (state = S0 and B = '1') or
                  (state = S1 and B = '1') or
                  (state = S2 and B = '1') else
         '0';

    Z <= "010" when (state = S0 and B = '1') else
         "011" when (state = S1 and B = '1') else
         "100" when (state = S2 and B = '1') else
         "000";

end RTL;

今回の状態遷移回路を以下に示す. f:id:zigzackey:20160615170234p:plain

テストベンチ

以下に,テストベンチのVHDLソースコードを示す.

-- TestBench : Vending Machine of Mealy State

library IEEE, STD;
use IEEE.std_logic_1164.all;
-- file input
use STD.textio.all;
use IEEE.std_logic_textio.all;

entity TestBench_MealyState30 is
end TestBench_MealyState30;

architecture TestBench of TestBench_MealyState30 is
    -- component
    component MealyState30
        port (
            CLK, RESET : in std_logic;
            A, B : in std_logic;
            X, Y : out std_logic;
            Z : out std_logic_vector(2 downto 0)
        );
    end component;

    -- signal
    signal CLKt, RESETt : std_logic;
    signal At, Bt, Xt, Yt : std_logic;
    signal Zt : std_logic_vector(2 downto 0);
    -- constant
    constant CLK_PERIOD : time := 50 ns;
    constant RESET_TIME : time := 5 ns;

begin
    DUT : MealyState30 port map (CLKt, RESETt, At, Bt, Xt, Yt, Zt);
    process
    -- file input / output
    file FILEin : TEXT open READ_MODE is "MealyState30.dat";
    file FILEout : TEXT open WRITE_MODE is "MealyState30.out";
    -- variable
    variable LINEin, LINEout : LINE;
    variable CLOCKen, RESETin : std_logic;
    variable Ain, Bin, Xin, Yin : std_logic;
    variable Zin : std_logic_vector(2 downto 0);
    variable colon : string(1 to 2) := " :";
        begin
            readline(FILEin, LINEin);
            read(LINEin, CLOCKen);
            read(LINEin, RESETin);
            read(LINEin, Ain);
            read(LINEin, Bin);
            CLKt <= '0';
            if (CLOCKen = '1') then
                CLKt <= '1' after RESET_TIME,
                        '0' after RESET_TIME + CLK_PERIOD / 2;
            end if;
            RESETt <= RESETin;
            At <= Ain;
            Bt <= Bin;
            read(LINEin, Xin);
            read(LINEin, Yin);
            read(LINEin, Zin);
            wait for CLK_PERIOD;

            write(LINEout, NOW, right, 4);
            write(LINEout, colon, right, 2);
            write(LINEout, Ain, right, 2);
            write(LINEout, Bin, right, 2);
            write(LINEout, Xin, right, 2);
            write(LINEout, Yin, right, 2);
            write(LINEout, Zin, right, 4);

            if ((Xt /= Xin) or (Yt /= Yin) or (Zt /= Zin)) then
                write(LINEout, Xt, right, 3);
                write(LINEout, Yt, right, 2);
                write(LINEout, Zt, right, 4);
            end if;
            writeline(FILEout, LINEout);

            if (endfile(FILEin)) then
                wait;
            end if;
    end process;
end TestBench;

入力情報である「MealyState30.dat」を以下に示す.

0 0 0 0 0 0 000
1 0 0 0 0 0 000
1 1 0 0 0 0 000
1 1 1 0 0 0 000
1 1 1 0 1 0 000
1 1 1 0 0 1 000
1 1 0 0 0 0 000
1 1 0 1 0 1 010
1 1 0 0 0 0 000
1 1 1 0 0 0 000
1 1 1 0 1 0 000
1 1 0 1 0 1 100
1 1 0 0 0 0 000

出力結果である「MealyState30.out」を以下に示す.

50 ns : 0 0 0 0 000
100 ns : 0 0 0 0 000
150 ns : 0 0 0 0 000
200 ns : 1 0 0 0 000
250 ns : 1 0 1 0 000  1 1 000
300 ns : 1 0 0 1 000  0 0 000
350 ns : 0 0 0 0 000
400 ns : 0 1 0 1 010  0 0 000
450 ns : 0 0 0 0 000
500 ns : 1 0 0 0 000
550 ns : 1 0 1 0 000  1 1 000
600 ns : 0 1 0 1 100  0 0 000
650 ns : 0 0 0 0 000

【VHDL】デコーダ回路

3to8デコーダ回路

以下に,3to8デコーダ回路のVHDLソースコードを表示する.

-- Barrel Shifter used Decoder

library IEEE;
use IEEE.std_logic_1164.all;

entity Decoder3to8 is
    port (
        CBA : in std_logic_vector(2 downto 0);
        D : out std_logic_vector(7 downto 0)
    );
end Decoder3to8;

architecture RTL of Decoder3to8 is
    component BShifterNbit
        generic (N : integer);
        port (
            A : in std_logic_vector((2**N) - 1 downto 0);
            S : in std_logic_vector(N - 1 downto 0);
            Z : out std_logic_vector((2**N) - 1 downto 0)
        );
    end component;

    constant N : integer := 3;
    signal tA : std_logic_vector((2**N) - 1 downto 0);

    begin
        tA <= "00000001";

        SHIFTER : BShifterNbit generic map (N) port map (tA, CBA, D);
end RTL;

バレルシフタを使用して,デコーダ回路を作成しています.

バレル・シフト回路&パリティ回路&デコーダ回路のテストベンチ

以下に,3つの回路をテストするテストベンチを示す.

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;

entity TestBench_Parity is
end TestBench_Parity;

architecture TestBench of TestBench_Parity is
    component Decoder3to8
        port (
            CBA : in std_logic_vector(2 downto 0);
            D : out std_logic_vector(7 downto 0)
            );
    end component;

    component ParityNbit
        generic (N : integer);
        port (
            A : in std_logic_vector(N - 1 downto 0);
            P : out std_logic
        );
    end component;

    constant N : integer := 8;
    signal CBAin : std_logic_vector(2 downto 0);
    signal Dout : std_logic_vector(7 downto 0);
    signal Pout : std_logic;

    begin
        DUT0 : Decoder3to8 port map (CBAin, Dout);
        DUT1 : ParityNbit generic map (N) port map (Dout, Pout);

        generator : process
            begin
                CBAin <= "000";
                wait for 10 ns;

                for I in 1 to 100 loop
                    CBAin <= CBAin + 1;
                    wait for 10 ns;
                end loop;
        end process;
end TestBench;

テストベンチの真理値表

以下の真理値表に基づき,テストベンチを作成した. f:id:zigzackey:20160601142859p:plain

【VHDL】バレル・シフト回路とrange-based loop

バレル・シフト回路

以下に,バレル・シフト回路のVHDLソースコードを表示する.

-- Barrel Shifter

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
use IEEE.numeric_std.all;

entity BShifterNbit is
    generic (N : integer := 3);
    port (
        A : in std_logic_vector((2**N) - 1 downto 0);
        S : in std_logic_vector(N - 1 downto 0);
        Z : out std_logic_vector((2**N) - 1 downto 0)
    );
end BShifterNbit;

architecture RTL of BShifterNbit is
begin
    process(A, S)
    variable sc : integer;
    begin
        sc := to_integer(unsigned(S));
        --Debugsc := conv_integer(S);
        for I in A'range loop
        --Debug--for I in 0 to 7 Loop
            if (I + sc <= A'left) then
                Z(I + sc) <= A(I);
            else
                Z(I + sc - A'left - 1) <= A(I);
            end if;
        end loop;
    end process;
end RTL;

[引用]range-based loop

for i in a'range loop

 ...;

end loop;

aの配列またはバスの範囲がある限りiを増加させながらループを繰り返す。

processの中で利用する。

参考文献

  1. VHDL Tips

【VHDL】パリティ回路とセンシティビティリスト

パリティ回路

以下に,パリティ回路のVHDLソースコードを表示する.

-- Even Parity Circuit

library IEEE;
use IEEE.std_logic_1164.all;

entity ParityNbit is
    generic (N : integer := 4);
    port (
        A : in std_logic_vector(N - 1 downto 0);
        P : out std_logic
    );
end ParityNbit;

architecture RTL of ParityNbit is
    begin
        process(A)
        variable tmp : std_logic;
        begin
            -- even parity -> tmp := '0'
            -- odd parity -> tmp := '1'
            tmp := '0';
            for I in 0 to N - 1 loop
                tmp := tmp xor A(I);
            end loop;
            P <= tmp;
        end process;
end RTL;

今回のパリティ回路ではXORを使って,パリティビットを決定する.

手計算を行えば,理屈はわかると思うが, 偶数パリティの時,

tmp := '0';

奇数パリティの時,

tmp := '1';

とすればよい.

センシティビティリスト

センシティビティリストは,process文の機能で,

process(A)
begin
--<順次処理文>
end process;

という風に使用する.

この機能は,信号名をカンマで区切って並べたリストで,

ここに記述された信号に変化があると以下の式が活性化されて実行される.

参考文献

  1. process文