-1

VHDL、Quartus II、ModelSim は初めてです。現在、点滅する LED を作成するラボを行っています。工事期間が比較的長い場合のシミュレーションの扱い方。点滅する LED の周波数は 1 Hz で、私が使用している開発ボード (Terasic DE2-115) のクロックは 50 MHz です。コードでは、クロック パルスをカウントし、それに応じて LED をオンにしています。しかし、ModelSim でコードを検証したい場合、数秒もの時間を処理するのに苦労します。そこで、コードの周期を数クロック サイクルに変更して、波が期待どおりに動作することを確認するだけで解決しました。最終的なコンパイルでは、1 秒に相当するカウント値を変更するだけです。

しかし、もっと良い方法があるはずです。シミュレーション後に VHDL コードに手を加えたくありません。1 ミリ秒以上の時間を処理する場合、1 つは合成用、もう 1 つはシミュレーション用の 2 つの rtl を使用する必要がありますか?

VHDL コード

library ieee;
use ieee.std_logic_1164.all;
entity lab4 is
port(   CLOCK_50 : in std_logic; -- DE2-115 internal clock
KEY      : in std_logic_vector(0 downto 0);   -- Push-buttons, active 0
                                                -- KEY(0) as reset
LEDG     : out std_logic_vector(7 downto 0)); -- Green LEDs
end entity lab4;

architecture lab4_rtl of lab4 is
signal RESET_N : std_logic;
begin

-- Parallel VHDL
constant CLK_FRQ : integer := 50000000;

RESET_N <= KEY(0); -- Here we connect reset to a push-button

-- synch process with asynch reset, i.e. reset as soon as reset is active
p1 : process(CLOCK_50, RESET_N)
variable counter : integer := 0;
variable led_num : integer := 0;
begin

    -- reset part
    if RESET_N = '0' then --KEY is active 0
        counter := 0;      --reset counter 
        LEDG(0) <= '0';    --turn OFF leds

    -- synch part, updates depending on clock
    elsif rising_edge(CLOCK_50) then

        counter := counter + 1; 

        if counter < 50000000 then;
            LEDG(0) <= '1';
        elsif counter >= 50000000 AND counter < 100000000 then
            LEDG(0) <= '0';
        else
            counter := 0;
        end if;
    end if;

 end process p1;

end architecture lab4_rtl;
4

2 に答える 2

1

名前付き定数を宣言しましたが、それを無視しました...

constant CLK_FRQ : integer := 50000000;

まず、マジック ナンバーの代わりに CLK_FRQ および CLK_FRQ * 2 に関してカウンターを書き換えることができます。

次に、sim とシンセで CLK_FRQ に異なる値を設定できます。それを行うにはさまざまな方法がありますが、私の好みは機能です。

function Clock_Frequency return natural is
begin
  -- synthesis translate_off
  return 50;
  -- synthesis translate_on
  return 50000000;
end Clock_Frequency;

「魔法の」プラグマ translate_off (および _on) を使用します。これは、合成ツールによって異なる場合がありますが、ほとんどの場合に受け入れられます。ソースのビットを無視するこれらの直接合成: この場合、シミュレータでのみ見られる最初のリターン。

これで、この関数を呼び出して定数を初期化できます

constant CLK_FRQ : integer := Clock_Frequency;

ジョブ完了。

于 2014-10-25T20:24:51.830 に答える
1

クロック周波数は変更しません。これは、シミュレーターでシミュレートする必要があるイベントの数を変更しないためです (これも時間のかかる要因です)。LED出力を変えるまでのサイクル数を変えたほうがいいと思います。

シミュレーション環境にいる場合に TRUE を返す VHDL 関数を定義できます。

function SIMULATION return boolean is
    variable ret : boolean;
begin
    ret := false;
    --synthesis translate_off
    if Is_X('X') then ret := true; end if;
    --synthesis translate_on
    return  ret;
end function;

これに加えて、if-then-else 関数を定義してコードを簡素化できます。

function ite(cond : BOOLEAN; value1 : INTEGER; value2 : INTEGER) return INTEGER is
begin
    if cond then
        return value1;
    else
        return value2;
    end if;
end function;

そして、次のように 1 行でカウンターの最大値を選択できるようになりました。

constant COUNTER_MAX : INTEGER := ite(SIMULATION, 500, 50000);

上記のコードを確認すると、いくつかのエラーがあります。

  • LED は 1 Hz ではなく 0.5 Hz で点滅しています (
  • デューティ サイクルは 50.00000 % ではありません。これは、カウンタが 1 サイクル遅れてゼロに設定されているためです。
  • 追加のフリップフロップとして LED を合成する意図はないと思います。
于 2014-10-26T10:15:31.507 に答える