0

信号機のコントローラーを設計しようとしていますが、そのためにはさまざまなタイマーが必要です。したがって、VHDL でこの汎用タイマーを設計しました。

library IEEE;
use IEEE.std_logic_1164.all, IEEE.numeric_std.all;

entity timer is
generic (n: NATURAL :=20);
    port (clk, reset : in std_logic;
            count : buffer std_logic);
end entity timer;


architecture behavioural of timer is
begin
    o0: process (clk, reset) IS
    variable cnt : unsigned (n-1 downto 0);
    begin
        if reset = '0' then
            cnt := (others => '0');
        elsif rising_edge(clk) then
            cnt := cnt + 1;
        end if;
        if cnt = n-1 then
            count <= '1';
        else
            count <= '0';
        end if;
    end process;
end architecture behavioural;

ただし、タイマーを実行すると 0 が出力され、変化しないため (アルテラ MAX II EMP240T100C5 の LED にカウントをマッピングしてこれをテストしました)、コントローラーの状態が進行しません。なぜこれが起こるのか分かりませんか?

4

1 に答える 1

1

は のビットn数ですcnt。これは次のとおりです。

    if cnt = n-1 then
        count <= '1';

次のようにする必要があります。

    if cnt = 2**n-1 then
        count <= '1';

countは 1 クロックで '1' のみです。まばたきして見逃しましたか?クロックレートを指定しませんでした。カウンターのデモを行う目的で、clk を 25 MHz に設定しました。

これは上記の補正を使用しており、短い波形表示に収まるようにn設定されています。3

n が 3 のタイマーに入る

上記の修正がなければ、count「パルス」は 19 クロック後に発生します。信号機のコントローラーが応答しなかった理由は別の問題です。

カウントをスティッキーにする

タイマーを19クロックの遅延として使用したいとコメントした後、ジムにカウントをラッチする方法を尋ねました。

n-1が のトリガー値であると仮定しcountます。

    elsif rising_edge(clk) and cnt /= n-1 then
        cnt := cnt + 1;
    end if;

これは基本的に、インバーターと同じn広いゲート出力を使用して、カウンターに提供して有効にします。ラッチされたトリガ値から だけ抜けます。countcntcntreset

また、この場合は 5 ビットの長さしか必要ないのに、宣言でビット値cntとして指定されるのはなぜですか?n

タイマーを一般化するために、トリガー カウントを個別に指定する予定はありますか? その場合、同期リセットが適切であると思われます。

最も簡単な全体的な解決策は次のとおりです-

cnt と整数型を作成します。

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity timer is
    generic (
        trigger_cnt:    natural := 19
    );
    port (
        clk:        in      std_logic;
        reset:      in      std_logic;
        count:      buffer  std_logic
    );
end entity timer;


architecture behavioural of timer is

begin
o0: process (clk, reset) IS
    variable cnt : natural range 0 to trigger_cnt;
    begin
        if reset = '0' then
            cnt := 0;
        elsif rising_edge(clk) and count = '0' then
            cnt := cnt + 1;
        end if;
        if cnt = trigger_cnt then
            count <= '1';
        else
            count <= '0';
        end if;
    end process;

end architecture;

library ieee;
use ieee.std_logic_1164.all;

entity tb_timer is
end entity;

architecture foo of tb_timer is
    signal clk:     std_logic := '0';
    signal reset:   std_logic;
    signal count:   std_logic;
begin 

DUT:  
    entity work.timer
    generic map (
        trigger_cnt =>  7
    )
    port map (
    clk => clk,
    reset => reset,
    count => count
    );

CLOCK:
    process

    begin
        wait for 20 ns;
        clk <= not clk;
        if Now > 360 ns then
            wait;
        end if;
    end process;

STIMULUS:
    process 
    begin
        reset <= '0';
        wait for 40 ns;
        reset <= '1';
        wait;
    end process;
end architecture;

これにはスティッキーがあることに注意してくださいcount

整数型トリガーカウントのタイマー

ジェネリックとしての代わりにn、値trigger_cnt(整数型と互換性があります) がジェネリックとして提示されます。

プロセスでは、適切なビット数の合成カウンターを取得するtrigger_cnt範囲を制限するために使用されます。cnt

cntカウンターはリセットされるまで停止するため、その範囲を超える整数型に基づく厄介なエラーはありません。

これは、VHDL 実装の整数範囲 (ここに示されている自然な範囲subtype NATURAL is INTEGER range 0 to INTEGER'HIGH;。INTEGER'HIGH は実装定義であり、少なくとも 2**31-1 (+2147483647、事前定義された整数型、IEEE Std 1076 を参照) )。

于 2014-04-01T03:34:51.150 に答える