2016-05-04 11 views
1

私はVHDLデザインに取り組んでいますが、コードはかなり醜いです。私の目標を達成するために言語の設計を回避しようとしているようですが、何かが間違っているように感じます。私はVHDLについてはかなり新しいですが、プロジェクトの小規模なチャンクには1ヶ月近く取り組んでいるので、一般的な考え方があります。しかし、この部分はもう少し複雑です。rising_edgeを非クロック信号の悪い習慣で使用していますか?代わりがありますか?

信号の立ち上がりエッジ(END_ADC)後に1クロック周期の長いパルス(LOAD_PULSE)を生成するプロセスが必要ですが、その信号の最新の立ち上がりエッジ(END_ADC)から4クロックが経過するまでは発生しません第2の信号(LVAL)の立ち下がりエッジ。

待機期間を達成するために、私はここでは、マイクロ秒の期間をカウントするタイマモジュールを構築しています:以下のように

entity uS_generator is 
    generic(
     Frequency  : integer := 66          -- Frequency in MHz 
    ); 
    Port ( 
     CLK  : in STD_LOGIC; 
     RESET : in STD_LOGIC; 
     T_CNT : out integer range Frequency downto 1 := 1; 
     uS_CNT : out integer range 65535 downto 0 := 0 
    ); 
end uS_generator; 

architecture behavior of uS_generator is 

    signal T_CNT_INT  : integer range Frequency downto 1 := 1;  -- Counter for 1 uS 
    signal uS_CNT_INT  : integer range 65535 downto 0 := 0; 

begin 

    COUNT: process(CLK, RESET) 
    begin 
     if RESET = '1' then 
      T_CNT_INT <= 1; 
      uS_CNT_INT <= 0; 
     elsif rising_edge(CLK) then 
      if T_CNT_INT = (Frequency - 1) then        -- Increment one clock early so last rising edge sees one uS elapsed. 
       uS_CNT_INT <= uS_CNT_INT + 1; 
       T_CNT_INT <= T_CNT_INT + 1; 
       if uS_CNT_INT = 65535 then 
        uS_CNT_INT <= 0; 
       end if; 
      elsif T_CNT_INT = Frequency then 
       T_CNT_INT <= 1; 
      else 
       T_CNT_INT <= T_CNT_INT + 1; 
      end if; 
     end if; 
    end process COUNT; 

    T_CNT <= T_CNT_INT; 
    uS_CNT <= uS_CNT_INT; 

end behavior; 

私はデザインのパルス発生部のために使用しているプロセスは以下のとおりです。

loadPulseProc: process(PIXEL_CLK, END_ADC, RESET) 
begin 

    if RESET = '1' then 
     PULSE_FLAG <= '0'; 
     LOAD_PULSE <= '0'; 
    elsif rising_edge(END_ADC) then 
     PULSE_FLAG <= '1'; 
    end if; 

    if rising_edge(PIXEL_CLK) then 
     if PULSE_FLAG = '1' and END_ADC = '1' and LVAL <= '0' and ADC_TMR_T >= 4 and LVAL_TMR_T >= 4 then 
      LOAD_PULSE <= '1', '0' after PIXEL_CLK_T; 
      PULSE_FLAG <= '0'; 
     end if; 
    end if; 

end process loadPulseProc; 

ADCTimerProc: process(END_ADC, RESET) 
begin 

    if RESET = '1' then 
     ADC_TMR_RST <= '1', '0' after PIXEL_CLK_T/10; 
    end if; 

    if rising_edge(END_ADC) then 
     ADC_TMR_RST <= '1', '0' after PIXEL_CLK_T/10; 
    end if; 

    if falling_edge(END_ADC) then 
     ADC_TMR_RST <= '1', '0' after PIXEL_CLK_T/10; 
    end if; 

end process ADCTimerProc; 

LVALTimerProc: process(LVAL, RESET) 
begin 

    if RESET = '1' then 
     LVAL_TMR_RST <= '1', '0' after PIXEL_CLK_T/10; 
    end if; 

    if rising_edge(LVAL) then 
     LVAL_TMR_RST <= '1', '0' after PIXEL_CLK_T/10; 
    end if; 

    if falling_edge(LVAL) then 
     LVAL_TMR_RST <= '1', '0' after PIXEL_CLK_T/10; 
    end if;   

end process LVALTimerProc; 

PIXEL_CLK_Tは、クロックの周期であり、15.152nsです。

このデザインでは、必要なときにシミュレーションが実行されることが示されていますが、raise_edge呼び出しの複数のrising_edgeを使用することによるエラーの回避が重要な場合にのみ、私がrising_edgeとfalling_edgeを使って読んだ限り、時計用にしか予約されていないようです。この動作を回避するにはどうすれば同じ出力を作成できますか?

ありがとうございます!

+0

コードは合成可能ではありません。ハードウェア記述言語のハードウェアは記述されていません。「PIXEL_CLK_T/10後」によって課される遅延は、信号割り当てにおいて1つ以上の波形要素に対して作用されず、また、複数の波形要素でもない。両方のエッジを使用して同じ信号を制御することはできません(ダブルデータレートレジスタはFPGAの特定のI/Oセルです)。現在廃止されているIEEE Std 1076.6-2004(RTL合成)またはお好みのベンダーの合成ドキュメントを参照してください。 – user1155120

+0

'rising_edge'(または'イベントと= 1 'の同等の形式)を使用すると、クロック信号が作成されます。これは適切な場合もありますが、しばしば悪い習慣です(信号を再クロッキングし、新しい値と古い値を比較する方が良いでしょう)。 –

答えて

5

はい、rising_edge()/falling_edge()はクロック信号にのみ使用してください。それはシミュレーションでは機能しますが、合成では問題や意図しないハードウェアが発生する可能性があります。

合成ツールは、関数の引数からクロックを推測し、そのような信号/ワイヤをFPGAの特別なトラックに配置します(デザイン用にFPGAをターゲットにしていると仮定します)。このツールは、特殊クロックバッファをさらに推測し、入力クロックピンがクロック対応ピンでない場合に警告します。

いくつかのクロックを導入すると、非同期設計につながり、クロスクロックフォルトに対して脆弱になる可能性があります。

信号の立ち上がりエッジまたは立ち下がりエッジの検出は、前のクロックサイクルの信号と現在の値を比較する次のようなエッジ検出回路によって行われます。

必要な信号:

signal mySignal_d : std_logic := '0'; 
signal mySignal_re : std_logic; 

必要なロジック:

mySignal_d <= mySignal when rising_edge(Clock); 
mySignal_re <= not mySignal_d and mySignal; 

この最初の行は、(あなたは、プロセスを使用することができる)、1ビットのDフリップフロップに変換します。第2ラインは、mySignalがローからハイに変化すると、1サイクルストローブ信号を発生する。私は*_dを使用して元の入力の遅延信号を示し、立ち上がりエッジの信号を*_reとしています。

生成された信号は、まだClockに同期しています。

+0

わかりました。したがって、テストベンチの作成など、シミュレーション専用のものを作成しようとしているときは問題ありません。たとえば、rising_edge()ステートメントまで待機して、出力の立上りエッジに基づいて適切なタイミングで入力したいストリームを作成します。 – Jemimacakes

+0

簡潔に:はい: – Paebbels

+0

出力のエッジを検出するのと同様の解決策がありますか?私は、 'PIXEL_CLK_T/10'の後のインスタンスを置き換えるために私のコードのセクションを1つ作成したいと考えていました。私はまた、すべての出力の立ち上がりと立ち下がりエッジで1クロックサイクルの長いパルスを生成する必要がありますが、私は 'オブジェクト 'から読み取ることができないので、あなたの素敵なソリューションを使用することはできません。私はちょうどこれのために別の質問をするべきですか? – Jemimacakes

関連する問題