1

私はmidiインターフェースを作っています。UART は正常に動作し、フラグと共に 8 ビット メッセージをコントロール ユニットに送信します。フラグがハイになると、ユニットはメッセージをレジスタに保存し、UART のフラグを再びローに設定するために clr_flag をハイにします。問題は、この clr_flag を 1 周期の長さにできないことです。この信号は、保存されているメッセージの種類を示すステート マシンも制御するため (たとえば、note_on -> key_note -> ベロシティ)、1 周期の長さである必要があります。

ここでの私の質問は、信号 (この場合はフラグ) が 1 つの clk 期間だけパルスをトリガーするにはどうすればよいかということです。私が今持っているものは、クロック期間中にほぼパルスになりますが、フラグがまだ0になっていないため、2回行います。私は多くの方法を試しましたが、今私はこれを持っています:

get_data:process(clk, flag)
  begin
  if reset = '1' then
    midi <= (others => '0');
    clr_flag <= '0';
    control_flag <= '0';

  elsif ((clk'event and clk='1') and flag = '1') then
      midi <= data_in;
      clr_flag <= '1'; 
      control_flag <= '1';     
  elsif((clk'event and clk='0') and control_flag = '1') then
    control_flag <= '0';
  elsif((clk'event and clk='1') and control_flag = '0') then
    clr_flag <= '0';
  end if;
end process;

このダブル パルスまたは 1 周期よりも長いパルスの問題 (この前に、clr_flag を 2 周期の clk パルスにする何かがありました) は、システムがフラグごとに 1 つではなく 2 つの状態を通過することです。

つまり、1 つの信号がハイになると (ローになるタイミングとは関係なく)、1 クロック周期の間にパルスが生成される必要があります。

ご協力いただきありがとうございます。

4

9 に答える 9

6

シングル サイクル パルスを作成する秘訣は、パルスを作成したら、開始に戻る前にトリガー入力が高い間待機する必要があることを認識することです。基本的に、非常に単純なステート マシンを作成していますが、2 つのステートしかない場合は、単純なブール値を使用してそれらを区別できます。

Morten は、クロック処理の標準パターンの 1 つを採用する必要があるという点で正しいです。私は同じようにうまく機能する別のものを選びました。

get_data:process(clk, reset)
   variable idle : boolean;
begin
   if reset = '1' then
      idle := true;
   elsif rising_edge(clk) then
      clr_flag <= '0';     -- default action
      if idle then
         if flag = '1' then
            clr_flag <= '1';  -- overrides default FOR THIS CYCLE ONLY
            idle <= false;
         end if;
      else
         if flag = '0' then
            idle := true;
         end if;
      end if;
  end if;
end process;
于 2013-11-24T19:29:57.890 に答える
2

フリップフロップ (レジスタ) を使用して 1 サイクル パルスの設計を行うには、いくつかの問題に対処する必要があります。

まず、VHDL 構造によるハードウェアでのフリップフロップの使用は、通常、次のような構造に従います。

process (clk, reset) is
begin
  -- Clock
  if rising_edge(clk) then
    -- ... Flip flops to update at rising edge
  end if;
  -- Reset
  if reset = '1' then
    -- Flip flops to update at reset, which need not be all
  end if;
end process;

したがって、get_dataプロセスはそれに応じて更新する必要があります。

  • 感度リストには、クロック ( clk) とreset
  • ifon イベントの入れ子構造は上記のようになります
  • の立ち上がりエッジのみをclk使用する必要があるため、チェックはありませんclk = '0'

clr_flagハイになったときに1 サイクルのパルスをオンにflagすることは、同期 '0' から '1' 検出器をオンにして、以下で呼び出される 1 サイクル遅延されたflagのバージョンを使用して、 をチェックすることで行うことができます。flagflag_ff(flag = ''1) and (flag_ff = '0')

結果のコードは次のようになります。

get_data : process (clk, reset) is
begin
  -- Clock
  if rising_edge(clk) then
    flag_ff  <= flag;  -- One cycle delayed version
    clr_flag <= '0';   -- Default value with no clear
    if (flag = '1') and (flag_ff = '0') then  -- Detected flag going from '0' to '1'
      midi     <= data_in;
      clr_flag <= '1';  -- Override default value making clr_flag asserted signle cycle
    end if;
  end if;
  -- Reset
  if reset = '1' then
    midi     <= (others => '0');
    clr_flag <= '0';
    -- No need to reset flag_ff, since that is updated during reset anyway
  end if;
end process;
于 2013-11-24T18:30:50.737 に答える
0

以下は、少なくとも1 クロック周期続く信号 (flag1) からちょうど1 クロック周期続く信号 (flag2) を作成する方法です。

ここに画像の説明を入力

于 2013-11-30T13:48:15.247 に答える