モーターを制御する可変周波数パルス列の作成に取り組んでおり、次のコードを使用して、入力インクリメント値でカウントアップするカウンターを使用してパルスを生成しています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:コードを (最終) 作業版に更新しました。