1

以下は、単純な 3 ビット カウンターです。

reset(rst) が 0 の場合、カウンタ値は "000" です。それ以外の場合は、クロックの立ち上がりエッジごとに 1 ずつ増加します。

 LIBRARY ieee;
 USE ieee.std_logic_1164.all;
 use IEEE.std_logic_unsigned.all;
 use IEEE.numeric_std.all;
 ---------------------------------------------
 ENTITY counter IS
 PORT (clk : IN STD_LOGIC;
    rst : in std_logic;
       digit : out std_logic_vector (2 downto 0)
       );
 END counter;
 ---------------------------------------------
 ARCHITECTURE counter OF counter IS
 BEGIN

 count: PROCESS(clk,rst)
 VARIABLE temp : std_logic_vector(2 downto 0);
 BEGIN
 IF (clk'EVENT AND clk='1') THEN
     if (rst = '1') then
        temp := temp + "001";
     else
        temp := "000";
     END IF;
 END IF;
 digit <= temp;
 END PROCESS count;
 END counter;

以下は、私が得たシミュレーション結果です。

ここに画像の説明を入力

その結果、出力は正しいです。ただし、時間 rst = 1 と output='001' の間には 1 クロックの遅延があります。つまり、rst = '1' の場合、カウンターは瞬時にインクリメントしません。

私の理解によると、clkまたはrstの変更が発生するたびに、プロセスが実行されます。したがって、rst がローからハイに変化すると、イベントが発生します。プロセスは、clk の立ち上がりエッジが YES かどうかをチェックします。次に、rst = 1、YES かどうかを確認します。したがって、通常、カウンターはその clk 自体でインクリメントする必要があります。しかし、そうではありません。

質問:

  1. リセット = 1 と出力 = 001 の間に 1 クロック周期の遅延があるのはなぜですか?
  2. そして、私の理解の何が間違っていますか?
4

3 に答える 3

5

最も可能性の高い原因は、「rst」が同じ「clk」信号によってクロックされる、クロックされたプロセスによって生成されることです。

したがって、「rst」は「clk」の 1 デルタ サイクル後に発生します。「rst」が変更されると、プロセスが起動しますが、「clk'event」は前のデルタ サイクルにあったため、「if」ステートメントは実行されません。

次のクロック エッジでは、rst = 1 であるため、カウンターは期待どおりに動作します。

3つのマイナーポイント:

  • アクティブ LOW リセットであることを明確にするために、リセット信号に rst_n という名前を付ける価値があります。
  • rst は機密リストに含まれる必要はありません
  • ブール式を括弧で囲む必要はありません
于 2012-12-01T17:30:30.870 に答える
3

(免責事項:VHDLでプログラミングしてから長い時間が経過したため、これは一般的なロジック設計に対する回答にすぎません。)

とにかく、プロセスがトリガーされたときに加算の結果がすぐに準備できるとは期待できません。ポイントは、000 + 001 の最初のビットの計算でも、1 回の xor 演算に相当する伝播遅延の影響を受けるということです。2 番目のビットは、最初のビットのキャリー (両方のビットが 1 の場合) と 2 番目のビットの xor 演算から計算されます。等々。

「temp」変数を非同期的にプローブすると、次のようになります。

                        ^ ________________
result_bit_0    __________|
                        0123456789
                _____________
result_bit_1            ^    |____________
                        0123456789
                ____________ _____
result_bit_2            ^  |_|   |________
                        0123456789abcde
                        ________       
clock:          ________|      |______|

この図は、一般的な追加操作の波形をより詳細に示しています。
時間 0 で、追加のプロセスが開始されます。
わずかな遅延「2」の後、最初のビットが 1 に安定します。
時間「5」で 2 番目のビットが 0 に安定し、時間「9」で 3 番目のビットが 0 に安定します。出力はさまざまな状態を切り替えます。

最小クロック周期を決定するのは、安定するために必要な各一時変数の合計/最大遅延です。この場合、瞬間「e」は、カウンターのインクリメントの結果が利用可能であると判断した瞬間です。

それでも、result(ベクトルである) 観点からは、すべてが次のクロック サイクルで即座に発生します。

于 2012-12-01T16:29:32.240 に答える
1

「問題」は、「最初」を説明した方法にあります。あなたが行った方法では、「同期」リセットが発生します。つまり、リセットはクロックの立ち上がりエッジの後にのみ有効になります。

一般に、これはコーディング スタイル/設定の問題です。私は通常、非同期リセットを好みます (リセットのリリース時にメタ安定性を回避するためにトップレベルでリセット シンクロナイザーを使用する場合があります) が、同期リセット アプローチを採用しても問題はありません。

非同期リセットの場合、コードを次のように変更する必要があります。

PROCESS (clk, rst_n) BEGIN
   IF rst_n = '0' THEN
      ...
   ELSIF rising_edge(clk) THEN
    ...
   END IF;
END PROCESS;
于 2018-09-25T13:22:49.557 に答える