2017-07-29 6 views
2

私はソフトウェアエンジニア(JAVA/C++)で電気工学者ではないので、VHDLが完全に混乱していると想像することができます。シンセサイザーは舞台裏でやろうとしています。そして、それは私が非常に単純なアーキテクチャであると信じるものを合成することができないと私に伝えています。 (実際には、それは私が、私はいくつかの基本的な概念を誤解し、複数の場所で建築ミスを繰り返してい疑われているいくつかのエンティティのためにそれをやっている。)これは合成できないのはなぜですか?

は、なぜこれが... (ERROR合成しない - (controller.vhdを63):。それは はNOT(クロックエッジ)の条件で、その値を保持していないので、文は が完了VHDL-1242を合成可能なされていない:エラーコード2)

LIBRARY ieee; 
USE ieee.std_logic_1164.all; 

ENTITY controller IS 
    PORT (
     ack: out STD_LOGIC := '0'; 
     data_request: in STD_LOGIC 
    ); 
END controller; 

ARCHITECTURE logic OF controller IS 
BEGIN 
    PROCESS (data_request) 
    BEGIN 
     if (rising_edge(data_request)) then 
      -- other logic will be added here 
      ack <= '1'; 
     elsif (falling_edge(data_request)) then 
      -- other logic will be added here too 
      ack<='0'; 
     end if; 
    END PROCESS; 
END logic; 

を(はい、私は完全に承知していますプロセスの「論理」は ack < = data_requestに置き換えることができますが、私のVHDLソースは実際にはtよりはるかに複雑です彼の しかし、私はエラーをスローする最も単純なサブセットにそれを蒸留しました。プロセスを別の構造体/同時実行文に置き換えることはお勧めしません)。

基本的に、data_request行がハイに遷移すると、ack出力はハイになります。立ち下がりエッジでは、ドライブをローに変更する必要があります。 (そして、それぞれの場合でも、他のものも同様に変更したいので、同時のステートメントの代わりにプロセスが必要です。要求が完了したことをトップレベルのエンティティに通知するために変更してください)

"価値を保持していない"とは何ですか?それが "NOT(クロックエッジ)"と書かれているとき、それは何の「時計」ですか?

これを修正する方法(構造を変更することなく)と、シンセサイザに何を求めているのか、シンセサイザが目的を達成できない理由についての説明が大好きです。

+0

私はいくつかの理由を理解しているかもしれません。私は、感性プロセスにおける "X <= Y"割り当てのX出力は、感度イベントに時計として接続されたフリップフロップ私はフリップフロップがサポートしていない2つの異なるクロックソースでフリップフロップを駆動しようとしています。これは正しいです?どのようにして2つの異なるイベントに応じて2つの異なる方法で出力を変更するのですか? – user3059763

+1

あなたの合成ツールは、IEEE Std 1076.6-2004(抜粋)から派生した受け入れ可能なフォームを示す順次ロジックのHDLガイドラインを持っています。ここでの問題は、デュアルデータレートクロックとしてdata_requestの両端を使用しようとすることです.DDRはサポートされていれば、iOセルでのみ使用でき、特殊な呼び出しが必要です(2つのフリップフロップを使用します)。一般に、1プロセス当たり1つのクロックエッジのみがサポートされる。ハードウェア記述言語を考える。 – user1155120

答えて

0

ソフトウェアのコンパイラとは対照的に、ハードウェアの合成は、一般に単語単位で行われません。代わりに、有限状態機械のような一般的な構造を見つけるためにコード全体が分析されます。あなたのケースでは、ほとんどの合成ツールは、立ち上がりエッジのためだけのチェックで、あるプロセスなど

process (...) 
begin 
    if rising_edge(clk) then 
     -- code here 
    end if; 
end process; 

を認識します。同じif文を使用して立ち上がりエッジと立ち下がりエッジの両方をチェックするため、コードに問題が発生する可能性があります。

2つのif文を使用するのと同じくらい簡単にコードを作成できます。しかし、user1155120が指摘しているように、両エッジでのトリガはすべてのターゲット(FPGA)で機能しない可能性があります。シミュレーションにはこの制限はありません。

また、立ち上がりエッジで特定のコードをトリガする別のクロック信号を追加することもできます。このコードは、data_request信号をチェックします。

(これはあなたが持っている他のコードによって異なります)、エッジではなく、data_requestのレベルを確認できます。

if data_request = '1' then 
    -- rising edge code 
else 
    -- falling edge code 
end if; 
+0

この修正により、A = A + 1のような "立ち上がりコード"の問題が発生しないでしょうか?インクリメントが制御不能になるでしょうか? – user3059763

+0

実際にそのような記述がある場合は、レベルトリガーコードはあなたのためではありません。まだエッジトリガーされている他の2つの提案を試してください。 – Mattenii

1

VHDLは単なるプログラミング言語であり、実際には多くの構造が可能です。しかし、デバイス(FPGA?)のVHDLをプログラムしたいとします。つまり、特定のルールに従ってプログラムする必要があります。

エッジを検出できるようにするには、2つの時点、つまり前と後の値を観察する必要があります。したがって、あなたのコードに時間の概念を導入する必要があります。信号xはt-1で '0'であり、tで '1'であった。

時刻のような時間の概念は、ほとんどのプログラマブルデバイスでは分かっていません。あなたはプログラマーとしてそれを紹介しなければなりません。ほとんどのデジタル回路では、特定の周波数の発振器を使用します。これは主に「クロック」と呼ばれています。

デジタルロジックにはその他の問題があり、それは遅延です。電気は無限の速度でロジックを通過しません。したがって、さまざまな移動経路を介してレイテンシを考慮する必要があります。これにより、非同期ロジックを設計することが非常に困難になります。あるいは、同期ロジックと呼ばれるタイミングの問題を解決するために、特定の場所のメモリ要素に値を格納することもできます。これらの要素は通常はレジスタです。

私はこれを説明する理由は、あなたのためのあなたの設計に時計を導入する理由を動機付けることです特定の要件。変更を確認するには、以前の状態のdata_requestを覚えておく必要があります。

signal data_request_old : std_logic; 
begin 
    data_request_old <= data_request when rising_edge(clk); 
    if data_request = '1' and data_request_old = '0' then 
     -- rising edge 
    end if; 
    if data_request = '0' and data_request_old = '1' then 
     -- falling edge 
    end if; 

x_old <= x when rising_edge(clk)は、入力を1クロックサイクル遅延させるレジスタを推論します。

p.s.私はdata_requestがすでにclkに同期していると仮定しています。そうでなければ、まずそれを同期させる必要があります。

p.s.2ほとんどのFPGA合成ツールが受け入れる最小構成物としてwhen rising_edge(clk);を書いています。あなたがしなければ、あなたはプロセス全体を書く必要があります。

+0

いつdata_request_oldを更新しますか?あなたは非同期システムです。 –

+0

@kingsjester私はあなたの質問を理解していません。あなたはそれを言い換えていただけますか?私はどんなシステムにもない。 – JHBonarius

+0

コンポーネントは非同期なので、 'data_request_old'をいつ更新しますか?私はそれが 'data_request'の以前の値だと思いますが、非同期システムではクロックエッジでそれを更新することはできません。だから私はあなたが実装しようとしているものだけである 'data_request'の立ち下がりエッジまたは立ち上がりエッジを意味する' data_request'値が変更されたときに更新するとします。 –

1

あなたのシグナルは、ackが立ち上がりエッジと立ち下がりエッジのみに設定されているという問題があります。合成では、物理的な制約のもとで、実際の世界でコンポーネントを動作させようとします。つまり、イベントがない場合は管理する必要があります。あなたのケースで は、あなただけの、次の方法のように、あなたのifelseステートメントを追加する必要があります。

architecture logic of controller is 

signal ack_s : std_logic := '0'; 

begin 
    process(data_request) 
    begin 
     if (rising_edge(data_request)) then 
      -- other logic will be added here 
      ack_s <= '1'; 
     elsif (falling_edge(data_request)) then 
      -- other logic will be added here too 
      ack_s <= '0'; 
     else then 
      ack_s <= ack_s; 
     end if; 
    end process; 

    ack <= ack_s; -- You map the output on the internal signal 

end architecture logic; 

この方法であなたの信号は常に値にマップされます。あなたが回路図を描こうとすると、あなたはポイントを得るでしょう。 ackが出力である場合、ack <= ack;にアクセスできないので、signalも使用する必要があります。 現実世界の回路では常にデフォルトの動作が必要なので、ifブロックを実行するたびに常にelseステートメントを使用することをお勧めします。

関連する問題