FPGA や CPLD は用途や機能が決まっている ASSP とは異なり、自由に かつ必要な機能だけを盛り込めます。
真っ白なキャンバスに絵を描くように、空っぽな箱(実際は空っぽではありませんが)に設計者が論理回路を作りこんでいく(デザインする)イメージです。自由に設計できるだけに、RTL 設計者は FPGA や CPLD に対する正しい設計手法を整理・確立し、特性を理解していないと、「シミュレーションで動いたのに、実機で動かない」とか「デバイスを冷やしたら動いた」などと言う不安定は事態が起こり得ます。これらはほとんどの場合がタイミングの問題から来ています。つまり “信頼度の低い論理回路がインプリメントされている” ことに他なりません。
信頼性の高い論理回路を構築するには、FPGA や CPLD を RTL 設計していく上でポイントとなるデザイン・テクニックの基本を学ぶことが重要です。
今回は、その記述テクニックをご紹介する前に、デジタル論理回路設計における「同期設計と非同期設計の違い」について触れておきたいと思います。
はじめて FPGA / CPLD の RTL設計をするユーザー必見です。
FPGA/CPLD 設計は同期化設計に尽きる!
インテルの FPGA や CPLD に限ったことではなく、すべての FPGA / CPLD メーカーに共通して言えることです。
それを理解する上で まず、同期、非同期のメリットとデメリットを理解しましょう。
同期回路とは
『同一クロックの同一エッジに同期して動作する回路系』を言います。
従って、同一クロックであっても逆位相のエッジを使用する場合は、同一クロックと見なしません。
また、基本的には単一クロック同期が望ましいです。異なるクロック間での信号の授受は非同期回路となり、非同期入力に対する適切な処理が必要になります。
同期回路のメリット | 同期回路のデメリット |
|
|
同期設計のデザイン例を VHDL 記述、VerilogHDL 記述に示します。
VHDL | VerilogHDL |
library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; entity s_counter is port ( clk : in std_logic; enable : in std_logic; q : out std_logic ); end s_counter; architecture sync_pld of s_counter is begin process (clk) variable cnt : std_logic_vector(2 downto 0); begin if enable = '0' then cnt := cnt; elsif (rising_edge(clk)) then cnt := cnt + 1; end if; q <= cnt(2); end process; end sync_pld; |
module s_counter (clk, enable, q);
|
非同期回路とは
『同一クロックの同一エッジに同期して動作しない回路系』を言います。
従って、同一クロックであっても異なるクロック・エッジで動作する回路は非同期回路となります。
リップル・クロックは、その最たる例です。また、内部で分周した出力を再利用することも源振クロックに対し非同期クロックとなります。
非同期回路のメリット | 非同期回路のデメリット |
|
|
非同期設計のデザイン例を VHDL 記述、VerilogHDL 記述に示します。
VHDL | VerilogHDL |
library ieee;
end async_pld; |
module a_counter (clk, enable, q); cnt0 = ~cnt0; cnt0 = cnt0; |
逆位相クロックを使用したデザイン例を VHDL 記述、VerilogHDL 記述に示します。
VHDL | VerilogHDL |
library ieee; use ieee.std_logic_1164.all; entity rev_clk is port ( clk : in std_logic; data : in std_logic; q : out std_logic ); end rev_clk; architecture rev_clk_pld of rev_clk is signal int0, int1: std_logic; begin process (clk) begin if (rising_edge(clk)) then int0 <= data; else int0 <= int0; end if; end process; process (clk) begin if (falling_edge(clk)) then int1 <= int0; else int1 <= int1; end if; end process; q <= int1; end rev_clk_pld; |
module rev_clk (clk, data, q); input clk, data; output q; reg int, q; always @(posedge clk) int = data; always @(negedge clk) q = int; endmodule |
以上をふまえて
FPGA や CPLD を使ったシステムの高いデザイン品質を確保するための基本的な考え方は、単一クロックによる同期設計です。
FPGA/CPLD が大規模になるにつれて、高速性を維持しながらも柔軟性を確保するために各デバイス・ベンダーから様々なインターコネクトの方式が提案されています。
しかしながら、一つのデバイス全体を通じてあらゆるデバイス内のディレイが均一になるように配置することは現実として不可能です。
さらに、これらのディレイは、電圧変動、周囲温度、ロットのバラツキなどの外部要因によって度々変動します。
このような条件の下で非同期設計を行うとクロック信号とデータ信号との間で競争が発生します。時には、データがクロックを追い越してしまう『すっぽ抜け』の状態が発生します。
このようなことを防ぐためには、インテルが推奨する最悪条件を維持しながら同期設計をおこなう必要があります。
同期設計を行う限り、デバイス内でクロック・スキューが最小になるように調整されていますので、『すっぽ抜け』を心配する必要はありません。
そのため唯一注意することは、外部からの入力信号のセットアップ・タイムとホールド・タイムを確保するだけになるのです。
これらの点を意識して、より信頼性の高いデジタル論理回路設計を構築して欲しいと思います。
今回は FPGA / CPLD 設計の基本となる同期回路と非同期回路について説明しました。
おすすめ記事/資料はこちら
FPGA って何者?
Beryll の FPGA でクロック同期によるLチカ![#1/3]
[RTL 設計ビギナー必見] 非同期信号を入力した際のシステムへ与える影響
FPGA/CPLD の動作特性について