【VHDL】立ち上がり/立ち下がりエッジの記述方法

信号の立ち上がりや立ち下がりの記述方法です。回路の動作開始タイミングを決めたり、信号変化の回数を数えるカウンタを作ったり。様々な場面で必要になります。

エッジ検出記述方法

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity edge_detect is
    port   (
        srstn_i : in    std_logic;
        clk_i   : in    std_logic;

        sig_i   : in    std_logic;

        rise_o  : out   std_logic;
        fall_o  : out   std_logic
    );
end edge_detect;

architecture rtl of edge_detect is

signal sig_ff  :   std_logic;

begin

process (clk_i) begin
    if (rising_edge(clk_i)) then
        if (srstn_i = '0') then
            sig_ff <= '0';
        else
            sig_ff <= sig_i;
        end if;
    end if;
end process;

-- 組み合わせ回路での書き方
rise_o <= sig_i and (not sig_ff);
fall_o <= (not sig_i) and sig_ff;

---- when文での書き方
--rise_o  <= '1'  when ((sig_i = '1') and (sig_ff = '0')) else '0';
--fall_o  <= '1'  when ((sig_i = '0') and (sig_ff = '1')) else '0';

end rtl;

自分は初めは見た目に分かりやすいwhen文の方を使用していたのですが、現在は記述量の短い組み合わせ回路の記述方法を使用しています。少し考えれば同じことですしね。

シミュレーション波形

組み合わせ回路の方は波形を見るとわかりやすいです。具体的にみると、"sig_i and (not sig_ff)"を満たすときだけ、"rise_o"がアサートされます。立ち下がりエッジ"fall_o"はその逆です。
vhdl rise fall edge

使用例:エッジカウンタ

if文の中で先ほどの検出式や検出信号を使用すれば、信号の立ち上がりや立ち下がりをカウントすることができます。

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity edge_count is
    port    (
        srstn_i         : in    std_logic;
        clk_i           : in    std_logic;

        sig_i           : in    std_logic;

        rise_count_o    : out   std_logic_vector (15 downto 0);
        fall_count_o    : out   std_logic_vector (15 downto 0)
    );
end edge_count;

architecture rtl of edge_count is

signal sig_ff       :   std_logic;
signal sig_rise     :   std_logic;
signal rise_count   :   std_logic_vector (15 downto 0);
signal fall_count   :   std_logic_vector (15 downto 0);

begin

process (clk_i) begin
    if (rising_edge(clk_i)) then
        if (srstn_i = '0') then
            sig_ff <= '0';
        else
            sig_ff <= sig_i;
        end if;
    end if;
end process;

-- 立ち上がり検出を組み合わせ回路で記述
-- if文に検出信号を使用
sig_rise   <= sig_i and (not sig_ff);

process (clk_i) begin
    if (rising_edge(clk_i)) then
        if (srstn_i = '0') then
            rise_count  <= (others => '0');
        else
            if (sig_rise = '1') then
                rise_count  <= rise_count + 1;
            end if;
        end if;
    end if;
end process;

-- if文に直接立ち上がり条件を書いてもエッジ検出可能
process (clk_i) begin
    if (rising_edge(clk_i)) then
        if (srstn_i = '0') then
            fall_count   <= (others => '0');
        else
            if ((sig_i = '0') and (sig_ff = '1')) then
                fall_count   <= fall_count + 1;
            end if;
        end if;
    end if;
end process;

rise_count_o    <= rise_count;
fall_count_o    <= fall_count;

end rtl;

下図がシミュレーション結果です。
edge count rise fall

シェアする

  • このエントリーをはてなブックマークに追加

フォローする