0

モーターを制御する可変周波数パルス列の作成に取り組んでおり、次のコードを使用して、入力インクリメント値でカウントアップするカウンターを使用してパルスを生成していますinc_i。次に、カウンターの出力の MSB をdout_o[N-1]FPGA の出力ピンにパイプします。これにより、目的の周波数の 50% デューティ サイクルの方形波が得られるはずですが、信号がローからハイになり、二度とオフにならないことがわかります。私のコードに明らかに問題がありますか?

--****************************************************************************
-- Load required libraries
--****************************************************************************
library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;

--****************************************************************************
-- Define the inputs, outputs, and parameters
--****************************************************************************
entity var_count is

    generic(N: integer :=32);               -- for generic counter size
    port(
            inc_i       : in    std_logic_vector(N-1 downto 0);
            load_i      : in    std_logic;
            clk_i       : in    std_logic;
            clear_i     : in    std_logic;
            clk_en_i    : in    std_logic;
            count_en_i  : in    std_logic;
            msb_o       : out   std_logic
        );

end var_count;

--****************************************************************************
-- Define the behavior of the counter
--****************************************************************************
architecture behavior of var_count is

    -- Define our count variable. No need to initialize in VHDL.
    signal count : unsigned(N-1 downto 0) := to_unsigned(0, N);
    signal incr  : unsigned(N-1 downto 0) := to_unsigned(0, N);

begin   
    -- Define our clock process
    clk_proc : process(clk_i, clear_i, load_i)
    begin
        -- Asynchronous clear
        if clear_i = '1' then
            count <= to_unsigned(0, N);
        end if;

        -- Asynchronous load
        if load_i = '1' then
            incr <= unsigned(inc_i);
        end if;

        -- Define processes synch'd with clock.
        if rising_edge(clk_i) and clk_en_i = '1' then
            if count_en_i = '1' then            -- increment the counter
                count <= count + incr;
            end if;
        end if;     
    end process clk_proc;

    -- Output the MSB for the sake of generating a nice easy square wave.
    msb_o <= count(count'left);

end behavior;

方形波の周波数はpulse_freq = clock_freq * inc_i / 2^N、N ビット カウンターの式で与えられる必要があります。

msb_o(k)また、カウンター出力 ( ) の MSB をシングル ビット DQ フリップフロップに渡して取得msb_o(k-1)し、実行することで、単一のクロック サイクル パルスを生成しようとしています。

pulse = ~msb_o(k) * msb_o(k-1)

where~は logicalNOT*表し、 は logical を表しますAND。これにより、カウンターがロールオーバーしたときにのみ、1 クロック サイクルのパルスが得られるはずです。オシロスコープを使用して出力ピンを読み取ると、これも MSB 自体 (50% デューティ サイクルの方形波) も表示されません。私のコードにエラーが表示された場合はお知らせください。

ご協力ありがとうございました!

これをまとめるために使用したリファレンスは、ここここ、およびここにあります。

編集 1:ユーザーが行った提案で質問のコードを更新しました。カウンターの MSB を出力すると、ハイになり、二度とオフになりません。オーバーフロー時にカウンターをリセットする必要があります(上記で試しました)。これを行う方法について何か提案はありますか?

編集 2:inc_i増分値は必ずしも 1 ではないため2**N - 1、ロールオーバー計算の値に達していない可能性があることに気付きました。したがって、ロールオーバー条件を次のように変更しました。

if count > (2**N - unsigned(inc_i) - 1) then
    count <= to_unsigned(0, N);

パルスを取得しているように見えますが、正確に 50% のデューティ サイクルではなく (これには意味があると思います)、インクリメント値を変更しても期待どおりに変化しないようですinc_i。レートが変わらない理由は何ですか?

編集 3:アプリケーションで気にするのはカウンターの MSB だけであることに気付きました。これは、50% のデューティ サイクルの方形波またはロールオーバー時のパルスを生成するために使用するものだからです。これに照らしdout_oて、エンティティ宣言を次のように置き換えました。

`msb_o : out std_logic`

最後に、同時割り当てステートメントを次のように置き換えました。

msb_o <= '1' when count > (2**(N-1) - 1) else '0';

50% のデューティ サイクルではない、または必ずしも正しい周波数ではない、非常に奇妙なパルスをまだ受信しています。さらなる提案をいただければ幸いです。

編集 4:コードをさらに変更して更新しました。また、この無料の本を参考文献リストに追加します。

編集 5:コードを (最終) 作業版に更新しました。

4

2 に答える 2

3

条件の外部レベルはプロセス センシティビティ リストの信号をカバーしていないため、プロセスは合成ツールによってプロセスがフリップフロップとして認識されるための一般的なルールには従いません。合成ツールは、おそらくこれに関して 1 つ以上の警告を出しています。

合成可能なフリップフロップの一般的なルールに従うようにプロセスを書き直す 1 つの方法は、次のとおりです。

clk_proc : process (CLK)
begin
  if (CLK'event and CLK = '1') then
    if CLEAR = '1' then           -- clear the counter
      COUNT <= COUNT - COUNT;
    elsif CLK_EN = '1' then       -- increment the counter
      COUNT <= COUNT + INC;
    end if;
  end if;
end process clk_proc;

これにより、外側のレベルでクロック エッジのチェックが行われ、CLEAR が同期していると見なされます。

レジスタの VHDL コーディング スタイルの詳細については、 ザイリンクス XST ユーザー ガイドなどを参照してください。

単一のクロックサイクルパルスの説明は問題ないように見えるので、それが機能しない理由はおそらく上記に由来します。

これらの有用な VHDL コーディング ルールを適用するために、モジュールの大規模な書き直しが考慮される場合があります。

  • 入力ポートと出力ポートには _i と _o という名前が付けられています。これは、モジュールがインスタンス化されているコードを読みやすくするためです。
  • すべての FPGA テクノロジで機能するとは限らないため、デフォルト値のない信号
  • コードを読みやすくするため、定数識別子には大文字のみを使用します。
  • std_logic_unsigned は使用しないでください。これは Synopsys ライブラリであり、VHDL 標準ではないためです。
  • 読みやすくするために、エッジ検出にrising_edge()を使用します
  • (others => '0')の代わりにクリアに使用しCOUNT - COUNTます。これは、COUNT がすべて X の場合でもシミュレーションで機能するためです。

以下のコードの例:

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

entity var_count is
  port(
    inc_i    : in  std_logic_vector(31 downto 0);
    clk_i    : in  std_logic;
    clear_i  : in  std_logic;
    clk_en_i : in  std_logic;
    dout_o   : out std_logic_vector(31 downto 0));
end var_count;

architecture behavior of var_count is

  -- Define our count variable
  signal count : std_logic_vector(31 downto 0);

begin

  -- Define our clock process
  clk_proc : process (clk_i)
  begin
    if rising_edge(clk_i) then
      if clear_i = '1' then           -- clear the counter
        count <= (others => '0');
      elsif clk_en_i = '1' then       -- increment the counter
        count <= std_logic_vector(unsigned(count) + unsigned(inc_i));
      end if;
    end if;
  end process clk_proc;

  -- Concurrent assignment statement
  dout_o <= count;

end behavior;

シミュレーターをまだ使用していない場合、ModelSim はツールボックスを大幅に改善する可能性があります。Alera には無料の ModelSim-Altera Starter Edition があり、小規模な設計に使用できます。

于 2013-08-07T05:47:33.740 に答える
2
  • 信号を初期化しても意味がありません。この信号がレジスタになる場合は、ゼロ (またはその他の必要な値) にリセットし、デザインがリセット状態で開始することを確認してください。
  • CLEARクロックされたプロセスは、プロセスで読み取られる に敏感ではありませんでした。非同期CLEARが必要だと思います。
  • std_logic_vectors は、 を使用して直接追加することはできませんIEEE.numeric_std.all。これは、さまざまなツール間の互換性のために推奨されます。
  • COUNT-COUNTを使用してすべてをゼロに駆動できる場合、レジスタをリセットする意味はありません(others => '0')

以下のコードを参照してください。

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


entity VAR_COUNT is

port(
        INC     : in    std_logic_vector(31 downto 0);
        CLK     : in    std_logic;
        CLEAR   : in    std_logic;
        CLK_EN  : in    std_logic;
        DOUT    : out   std_logic_vector(31 downto 0)
    );

end VAR_COUNT;

architecture behavior of VAR_COUNT is

-- Initialising a signal has no effect in hardware
signal COUNT:std_logic_vector(31 downto 0) := x"00_00_00_00";

-- Define our clock process, your clocked process was not senstive to CLEAR
begin clk_proc:process(CLK,CLEAR)
    begin
        if CLEAR = '1' then         -- clear the counter
            COUNT <= (others=>'0'); --always use this to reset
        elsif CLK_EN = '1' then     -- increment the counter
            if (CLK'EVENT AND CLK = '1') then
                COUNT <= std_logic_vector(unsigned(COUNT) + unsigned(INC));
            end if;
        end if;     
    end process clk_proc;

-- concurrent assignment statement
DOUT <= COUNT;

end behavior;
于 2013-08-07T06:02:00.343 に答える