サーチ…


備考

Dフリップフロップ(DFF)およびラッチはメモリ要素である。 DFFは、クロックの一方または他方のエッジで入力をサンプリングします(両方ではない)一方、ラッチはイネーブルの1つのレベルでトランスペアレントであり、他方では記憶されます。次の図は、その違いを示しています。

DFF対ラッチ動作

VHDLのDFFやラッチのモデリングは簡単ですが、考慮する必要がある重要な側面がいくつかあります。

  • DFFとラッチのVHDLモデルの違い。

  • 信号のエッジを記述する方法。

  • 同期または非同期のセットまたはリセットを記述する方法。

Dフリップフロップ(DFF)

すべての例で:

  • clkは時計です、
  • dは入力であり、
  • qは出力、
  • srstはアクティブハイの同期リセットで、
  • srstnはアクティブロー同期リセット、
  • arstはアクティブハイの非同期リセットであり、
  • arstnはアクティブローの非同期リセットで、
  • ssetはアクティブな高同期セットで、
  • ssetnはアクティブロー同期セットで、
  • asetはアクティブな高非同期セットであり、
  • asetnはアクティブローの非同期セットです

すべての信号は、タイプieee.std_logic_1164.std_ulogicです。使用されるシンタックスは、すべてのロジックシンセサイザで正しい合成結果につながるシンタックスです。代わりのシンタックスについては、 クロックエッジ検出の例を参照してください。

立ち上がりエッジクロック

process(clk)
begin
  if rising_edge(clk) then
    q <= d;
  end if;
end process;

立ち下がりエッジクロック

process(clk)
begin
  if falling_edge(clk) then
    q <= d;
  end if;
end process;

立ち上がりエッジクロック、同期アクティブハイリセット

process(clk)
begin
  if rising_edge(clk) then
    if srst = '1' then
      q <= '0';
    else
      q <= d;
    end if;
  end if;
end process;

立ち上がりエッジ・クロック、非同期アクティブ・ハイ・リセット

process(clk, arst)
begin
  if arst = '1' then
    q <= '0';
  elsif rising_edge(clk) then
    q <= d;
  end if;
end process;

立ち下がりエッジクロック、非同期アクティブローリセット、同期アクティブハイセット

process(clk, arstn)
begin
  if arstn = '0' then
    q <= '0';
  elsif falling_edge(clk) then
    if sset = '1' then
      q <= '1';
    else
      q <= d;
    end if;
  end if;
end process;

立ち上がりエッジクロック、非同期アクティブハイリセット、非同期アクティブローセット

注:setはリセットよりも優先度が高い

process(clk, arst, asetn)
begin
  if asetn = '0' then
    q <= '1';
  elsif arst = '1' then
    q <= '0';
  elsif rising_edge(clk) then
    q <= d;
  end if;
end process;

ラッチ

すべての例で:

  • enはイネーブル信号、
  • dは入力であり、
  • qは出力、
  • srstはアクティブハイの同期リセットで、
  • srstnはアクティブロー同期リセット、
  • arstはアクティブハイの非同期リセットであり、
  • arstnはアクティブローの非同期リセットで、
  • ssetはアクティブな高同期セットで、
  • ssetnはアクティブロー同期セットで、
  • asetはアクティブな高非同期セットであり、
  • asetnはアクティブローの非同期セットです

すべての信号は、タイプieee.std_logic_1164.std_ulogicです。使用されるシンタックスは、すべてのロジックシンセサイザで正しい合成結果につながるシンタックスです。代わりのシンタックスについては、 クロックエッジ検出の例を参照してください。

アクティブハイイネーブル

process(en, d)
begin
  if en = '1' then
    q <= d;
  end if;
end process;

アクティブローイネーブル

process(en, d)
begin
  if en = '0' then
    q <= d;
  end if;
end process;

アクティブハイイネーブル、同期アクティブハイリセット

process(en, d)
begin
  if en = '1' then
    if srst = '1' then
      q <= '0';
    else
      q <= d;
    end if;
  end if;
end process;

アクティブハイイネーブル、非同期アクティブハイリセット

process(en, d, arst)
begin
  if arst = '1' then
    q <= '0';
  elsif en = '1' then
    q <= d;
  end if;
end process;

アクティブローイネーブル、非同期アクティブローリセット、同期アクティブハイセット

process(en, d, arstn)
begin
  if arstn = '0' then
    q <= '0';
  elsif en = '0' then
    if sset = '1' then
      q <= '1';
    else
      q <= d;
    end if;
  end if;
end process;

アクティブハイイネーブル、非同期アクティブハイリセット、非同期アクティブローセット

注:setはリセットよりも優先度が高い

process(en, d, arst, asetn)
begin
  if asetn = '0' then
    q <= '1';
  elsif arst = '1' then
    q <= '0';
  elsif en = '1' then
    q <= d;
  end if;
end process;

クロックエッジ検出

短編小説

Whith VHDL 2008、クロックの種類がbitであれば、 booleanieee.std_logic_1164.std_ulogicまたはieee.std_logic_1164.std_logic 、クロックエッジ検出を立ち上がりエッジでコーディングすることができます

  • if rising_edge(clock) then
  • if clock'event and clock = '1' then -- type bit, std_ulogic or std_logic
  • if clock'event and clock then -- type boolean

立ち下がりエッジ

  • if falling_edge(clock) then
  • if clock'event and clock = '0' then -- type bit, std_ulogic or std_logic
  • if clock'event and not clock then -- type boolean

これは、シミュレーションと合成の両方に対して、期待どおりに動作します。

注: std_ulogicタイプの信号の立ち上がりエッジの定義は、 if clock'event and clock = '1' thenよりも少し複雑です。例えば、標準のrising_edge関数は、異なる定義を持っています。おそらく合成のための差異を作らなくても、それはシミュレーションのために作ることができる。

rising_edgeおよびfalling_edge標準関数の使用を強く推奨します。以前のバージョンのVHDLでは、これらの関数を使用するために、標準パッケージの使用を明示的に宣言する必要があるかもしれません(eg ieee.numeric_bit bit )。

注: rising_edgeおよびfalling_edge標準関数を使用して、非クロック信号のエッジを検出しないでください。いくつかのシンセサイザーは、信号がクロックであると結論づけることができます。ヒント:非クロック信号のエッジを検出するには、シフトレジスタの信号をサンプリングし、シフトレジスタのさまざまなステージでサンプリングされた値を比較することがよくあります。

長い話

Dフリップフロップ(DFF)のモデリングでは、クロック信号のエッジの検出を適切に記述することが不可欠です。エッジは定義上、特定の値から別の値への遷移です。例えば、我々は、型の信号の立ち上がりエッジに定義することができbit (2つの値をとり、標準VHDL列挙型'0''1'から遷移として) '0''1'boolean型のtruefalseからtrueへの遷移として定義することができます。

多くの場合、より複雑な型が使用されます。たとえば、 ieee.std_logic_1164.std_ulogic型は、 bitまたはbooleanように列挙型ですが、2ではなく9つの値があります。

意味
'U' 未初期化
'X' 強制不明
'0' 強制的に低レベル
'1' 強制的に高レベル
'Z' 高インピーダンス
'W' 弱い不明
'L' 弱い低レベル
'H' 弱い高レベル
'-' 気にしない

このような型の立ち上がりエッジを定義するのは、 bitまたはboolean場合よりbit複雑です。たとえば、 '0'から'1''1'移行であると判断できます。しかし、それが'0'または'L'から'1'または'H'への移行であると決定することもできます。

注:これは、標準のために使用するこの2番目の定義であるrising_edge(signal s: std_ulogic)で定義された関数ieee.std_logic_1164

エッジを検出するさまざまな方法を検討するときは、信号の種類を検討することが重要です。モデリングの目標を考慮に入れることも重要です:シミュレーションのみか論理合成か?これをいくつかの例で説明しましょう。

タイプ・ビットの立ち上がりエッジDFF

signal clock, d, q: bit;
...
P1: process(clock)
begin
  if clock = '1' then
    q <= d;
  end if;
end process P1;

技術的には、純粋なシミュレーションセマンティクスの観点から、プロセスP1は立ち上がりエッジトリガDFFをモデル化します。実際、 q <= d割り当ては、次の場合にのみ実行されます。

  • clock (これは感度のリストが表現するものです)に変更し、
  • clockの現在の値は'1'です。

clockはタイプ・ビットであり、タイプ・ビットは値'0''1'しか持たないので、これはビット・タイプの信号の立ち上がりエッジとして定義したものです。どんなシミュレーターでもこのモデルを処理できます。

注:ロジックシンセサイザーの場合、後で説明するように、状況は少し複雑です。

非同期アクティブ・ハイ・リセットおよびタイプ・ビットを備えた立ち上がりエッジDFF

私たちのDFFに非同期アクティブハイリセットを追加するために、次のようなものを試すことができます:

signal clock, reset, d, q: bit;
...
P2_BOGUS: process(clock, reset)
begin
  if reset = '1' then
    q <= '0';
  elsif clock = '1' then
    q <= d;
  end if;
end process P2_BOGUS;

しかし、 これは機能しません 。実行されるq <= d割当ての条件は、 clock立上りエッジ、 reset = '0'なければなりません。しかし、我々がモデル化したのは、

  • clockまたはresetまたは両方が変更され
  • reset = '0' および
  • clock = '1'

これは同じではありません: clock = '1' '0'間にreset'1'から'0'変化すると、 clock立ち上がりエッジではない間に割り当てが実行されます。

実際、信号属性の助けを借りずにVHDLでこれをモデル化する方法はありません。

P2_OK: process(clock, reset)
begin
  if reset = '1' then
    q <= '0';
  elsif clock = '1' and clock'event then
    q <= d;
  end if;
end process P2_OK;

clock'eventは、信号clock適用される信号属性eventです。 booleanとして評価され、現在の実行フェーズの直前の信号更新フェーズで信号clock変更された場合にのみtrueとなります。これにより、プロセスP2_OKはシミュレーション(および合成)で必要なものを完全にモデル化するようになりました。

合成セマンティクス

多くのロジックシンセサイザは、VHDLモデルのセマンティクスではなく、構文パターンに基づいて信号エッジ検出を識別します。言い換えれば、彼らはVHDLコードがどんな振る舞いをしているのかを考えません。それらがすべて認識するパターンの1つは次のとおりです。

if clock = '1' and clock'event then

したがって、プロセスP1の例でも、すべてのロジックシンセサイザでモデルを合成できるようにするには、それを使用する必要があります。

signal clock, d, q: bit;
...
P1_OK: process(clock)
begin
  if clock = '1' and clock'event then
    q <= d;
  end if;
end process P1_OK;

条件のand clock'event部分は感度リストと完全に冗長ですが、シンセサイザーにはそれが必要なため...

非同期アクティブ・ハイ・リセットとタイプstd_ulogic持つ立ち上がりエッジDFF

この場合、クロックの立ち上がりエッジやリセット条件の表現が複雑になることがあります。上記で提案した立ち上がりエッジの定義を保持し、リセットが'1'または'H'場合にアクティブであると考えると、モデルは次のようになります。

library ieee;
use ieee.std_logic_1164.all;
...
signal clock, reset, d, q: std_ulogic;
...
P4: process(clock, reset)
begin
  if reset = '1' or reset = 'H' then
    q <= '0';
  elsif clock'event and
        (clock'last_value = '0' or clock'last_value = 'L') and
        (clock = '1' or clock = 'H') then
    q <= d;
  end if;
end process P4;

注: 'last_valueは、最後の値が変更される前の信号の値を返す別の信号属性です。

ヘルパー関数

VHDL 2008標準では、特にstd_ulogicなどの複数値の列挙型の場合、信号エッジの検出を簡素化するためのいくつかのヘルパ関数が用意されています。 std.standardパッケージは、 bitおよびboolean型のrising_edgeおよびfalling_edge関数を定義し、 ieee.std_logic_1164パッケージはstd_ulogicおよびstd_logic型でそれらを定義します。

注:以前のバージョンのVHDLでは、これらの関数を使用するために、標準パッケージの使用を明示的に宣言する必要があるかもしれません(eg ieee.numeric_bit in bit)。

前の例を再訪し、ヘルパー関数を使用しましょう:

signal clock, d, q: bit;
...
P1_OK_NEW: process(clock)
begin
  if rising_edge(clock) then
    q <= d;
  end if;
end process P1_OK_NEW;
signal clock, d, q: bit;
...
P2_OK_NEW: process(clock, reset)
begin
  if reset = '1' then
    q <= '0';
  elsif rising_edge(clock) then
    q <= d;
  end if;
end process P2_OK_NEW;
library ieee;
use ieee.std_logic_1164.all;
...
signal clock, reset, d, q: std_ulogic;
...
P4_NEW: process(clock, reset)
begin
  if reset = '1' then
    q <= '0';
  elsif rising_edge(clock) then
    q <= d;
  end if;
end process P4_NEW;

注:この最後の例では、リセットに関するテストも簡素化しました。フローティングで高インピーダンスのリセットは非常にまれで、ほとんどの場合、この単純化されたバージョンはシミュレーションと合成に適しています。



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow