概要
FPGA入力信号の立ち上がり/立下りエッジを検出して1クロックサイクルのHighパルスを生成する回路のVHDLでの実装例です。
メタステーブルと微分回路について詳しく説明されているページが多数ありますので、そこの部分の説明は割愛させていただきます。
前提
- 入力信号にチャタリングは無いものとします。(基板内のICからFPGAへ渡す信号)
- 入力信号の幅はFPGAクロック周期より長いものとします
- 入力信号はFPGAクロックと非同期で変化するものとします
目標回路構成
非同期入力によりメタステーブル対策として、初段のbuf_ff(0)出力はそのまま次段buf_ff(1)に接続します。
2~3段目のFFを利用して微分回路を構成し、立ち上がり/立下りエッジを検出します。
エッジ検出信号(o_RISE_pとo_FALL_p)は組み合わせ回路出力のままモジュール外に出していますが、設計ルールとして FF出しを要求されるシーンでは、適宜FFを追加してください。
VHDLコード
RTL図をVHDLで書いた例です。
エッジ検出部分はANDとnotで書いても構いませんが、個人的には三項演算子で書いた方が'1'に有意があることを強調している気がしますので、三項演算子で書いています。
SYNCRO_DFF.vhd
--同期化D-FlipFlopとエッジ検出(チャタリング無し入力)
library ieee;
use ieee.std_logic_1164.all;
entity SYNCRO_DFF is
Port(
i_CLK :in std_logic;
i_RST_p :in std_logic;
i_PORT :in std_logic;
o_SYNCRO :out std_logic;
o_RISE_p :out std_logic;
o_FALL_p :out std_logic
);
end entity;
architecture RTL of SYNCRO_DFF is
signal buf_ff :std_logic_vector(0 to 2);
signal rise :std_logic;
signal fall :std_logic;
begin
--入力同期化バッファFF
process(i_CLK)begin
if(rising_edge(i_CLK))then
buf_ff(0) <= i_PORT;
buf_ff(1) <= buf_ff(0);
buf_ff(2) <= buf_ff(1);
end if;
end process;
--エッジ検出パルス:1サイクルHigh出力
rise <= '1' when ((buf_ff(1)='1')and(buf_ff(2)='0')) else '0';
fall <= '1' when ((buf_ff(1)='0')and(buf_ff(2)='1')) else '0';
--出力
o_SYNCRO <=buf_ff(2);
o_RISE_p <=rise;
o_FALL_p <=fall;
end architecture;
動作
入力信号の立ち上がり・下がりで1クロックサイクルのパルスが出力されています。
テストベンチ
Verilogですがテストベンチのコードです。
SYNCRO_DFF_tb.v
`timescale 1ns / 1ps
module SYNCRO_DFF_tb();
reg i_CLK =0;
reg i_RST_p=1;
reg i_PORT =0;
wire o_SYNCRO;
wire o_RISE_p;
wire o_FALL_p;
SYNCRO_DFF SYNCRO_DFF(
.i_CLK (i_CLK ),
.i_RST_p (i_RST_p ),
.i_PORT (i_PORT ),
.o_SYNCRO (o_SYNCRO ),
.o_RISE_p (o_RISE_p ),
.o_FALL_p (o_FALL_p )
);
//クロック50MHz
initial begin
i_CLK = 0;
forever #10 i_CLK = ~i_CLK;
end
//リセット
initial begin
i_RST_p=1;
#1360;
i_RST_p=0;
end
initial begin
#1023;
i_PORT=~i_PORT;
#503;
i_PORT=~i_PORT;
#600;
i_PORT=~i_PORT;
end
endmodule