2

私はwebPackISEv13を使用して次のコードでNexys3ボードをプログラムしていますが、ifelsifステートメントのステートメントを交換することでまったく異なる動作に気づきました。基本的に、ボード上で3つの押しボタンを使用しています。最初の押しボタンbtn(0)を押すと、8つのスイッチの状態がレジスタに格納されます。btn(1)を押すと、スイッチの状態が8つのLEDに表示され、LEDはこの状態を維持するはずです。btn(2)を押すと、すべてのLEDが強制的に点灯し、btn1または2のどちらも押されていない場合はこのままになります。ボタン1と2のifとelsifのアクションを入れ替えると、動作が変わります。スイッチの状態は、対応するボタンを押したときにのみ表示され、離すとすべてのLEDが点灯します。

「これを機能させるために必要なもの」を探すだけでなく、vhdlがC ++とは非常に異なる動作をする理由を説明した後です(この場合、順序は重要ではありません)。

以下はコードの抜粋です。動作「a」または動作「b」を取得するためにコメント/コメント解除する行を指定します。

動作'a':

  • btn(0)を押すと、8つのスイッチの状態がdata_regに正しくロードされます
  • btn(1)を押すと、LEDがすべてオンになります( "111 ... 11")
  • btn(2)を押すと、LEDにdata_regの内容が表示されます
  • ボタンが押されていない場合、LEDの状態は、最後にボタンを押したときに指示された状態になります。

動作'b':

  • btn(0)を押すと、8つのスイッチの状態がdata_regに正しくロードされます
  • btn(1)を押すと、LEDにdata_regの内容が表示されます
  • btn(2)を押すと、LEDがすべてオンになります( "111 ... 11")
  • ボタンが押されていない場合、すべてのLEDがオンになり、data_regの内容を確認する唯一の方法は、btn(1)を押したままにすることです。

`

プロセス(clk)

始める

if (clk'event and clk='1') then
   if (db_btn(0)='1') then          --load sw state into data_reg
      data_reg <= sw;
   end if;

次の場合に終了します。終了プロセス;

   process(btn,data_reg)
   begin
     if btn(1)='1' then 
        data_s2f <= "1111111111111111";   --behvr a; comment this line for behvr b
        -- data_s2f <= "00000000" & data_reg; -- uncomment for behvr b; comment for behvr a
     elsif btn(2)='1' then -- read     
       data_s2f <= "00000000" & data_reg; --behvr a; comment this line for behvr b
       --data_s2f <= "1111111111111111";  -- uncomment for behvr b; comment for behvr a
      end if;
   end process;
   -- output
   led <= data_s2f(7 downto 0);  --display data_s2f in LEDs

シミュレーションテストベンチ

これが私のシミュレーションテストベンチです。すべてのシグナルの結果を実行すると、UUU..UUになります。コメントをいただければ幸いです。

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;

ENTITY ifstmt_tb IS
END ifstmt_tb;

ARCHITECTURE behavior OF ifstmt_tb IS 

    -- Component Declaration for the Unit Under Test (UUT)

    COMPONENT ram_ctrl_test
    PORT(
         clk : IN  std_logic;
         reset : IN  std_logic;
        sw : IN  std_logic_vector(7 downto 0);
        btn : IN  std_logic_vector(2 downto 0);
        led : OUT  std_logic_vector(7 downto 0)
        );
    END COMPONENT;


   --Inputs
  signal clk : std_logic := '0';
  signal reset : std_logic := '0';
  signal sw : std_logic_vector(7 downto 0) := (others => '0');
  signal btn : std_logic_vector(2 downto 0) := (others => '0');

    --Outputs
   signal led : std_logic_vector(7 downto 0);

   -- Clock period definitions
   constant clk_period : time := 10 ns;

BEGIN

    -- Instantiate the Unit Under Test (UUT)
   uut: ram_ctrl_test PORT MAP (
          clk => clk,
          reset => reset,
          sw => sw,
          btn => btn,
          led => led
        );

   -- Clock process definitions
   clk_process :process
   begin
        clk <= '0';
        wait for clk_period/2;
        clk <= '1';
        wait for clk_period/2;
   end process;


   -- Stimulus process
   stim_proc: process
   begin        
      -- hold reset state for 100 ns.
        reset <= '1';
        sw <= "11001100";
        btn<= (others => '0');
      wait for 100 ns;  
        reset <= '0';
      wait for clk_period*10;
        -- load register
        btn<= (0=>'1', others => '0');
       wait for clk_period*2;   
        btn<= (others => '0');  
       wait for clk_period*10;  
        -- display with btn 1
        btn<= (1=>'1', others => '0');
       wait for clk_period*5;   
        btn<= (others => '0');  
       wait for clk_period*10;  
        -- display with btn 2
        btn<= (2=>'1', others => '0');
       wait for clk_period*5;   
        btn<= (others => '0');  
       wait for clk_period*10;  
        -- change pattern
        sw <= "11100111";
        wait for clk_period;
        -- load register
        btn<= (0=>'1', others => '0');
       wait for clk_period*2;   
        btn<= (others => '0');  
       wait for clk_period*10;  
        -- display with btn 2
        btn<= (2=>'1', others => '0');
       wait for clk_period*5;   
        btn<= (others => '0');  
       wait for clk_period*10;  
        -- display with btn 1
        btn<= (1=>'1', others => '0');
       wait for clk_period*5;   
        btn<= (others => '0');  

      -- insert stimulus here         

      wait;
   end process;  

END;
4

3 に答える 3

3

VHDLは、カスケードを使用してステートメントを順番に実行すると、さまざまな条件ステートメントの出力を駆動できるようになります。すべての条件は常に完全に計算されます(このポイントの伝搬遅延は無視してください)。ハードウェアは、条件に一致する最初のステートメントを「選択」します(elsifブランチが下位ステートメントの有効化を駆動する場合は後続のステートメントからの出力であるため、falseと評価された場合は次のステートメントが有効になります)。

あなたが見る行動は「奇妙」に見えると思いますが、実際には何を期待していますか。デフォルト値を指定しないと、ハードウェアに基づいて予期しない結果が発生します。あなたは白黒でプログラムする必要があります。今、あなたは灰色をプログラミングしています。VHDLは、プログラマーの意図でははるかに寛容ではありません。あなたは常に決定的かつ明示的でなければなりません。

考えられる答えの1つは、これはifステートメントをコーディングするための最良の方法ではないということです。より良い方法は、「確実な」ボタンが押されたことを示す「ティック」信号を作成することです。これは、押されたオプションを記録する別の順次ラッチプロセスを駆動します。表示される動作はハードウェアに依存するため、説明が難しいと思います。

ここで言及されていないもう1つのポイントは、スイッチデバウンサーを実装する必要があるということです。事実上、スイッチを押したままにして、予期しない方法で動作すると、スイッチが大きく切り替わる可能性があります(スイッチをオシロスコープに接続し、エッジモードにすると表示されます)。スイッチが押されている間(たとえば1ms)カウントし、その期間の後にのみスイッチをオンにする必要があります。オフにする場合も同じです。これは、あなたが持っているかもしれないどんな弾力性も緩衝するのに良いかもしれません。これはあなたがあなたの「確実な」ボタンが「カチカチ」を押すようにする方法です

于 2012-06-18T19:55:12.703 に答える
1

btn(2)のハードウェアが予想よりも多くの「1」をスローしているか、そうでない場合はより頻繁に高信号を取得しているようです。別のハードウェアボタンへのマッピングが役立つかどうかを確認してください。btn(2)がプルダウンではなくプルアップモードで設定されていることを確認してください。

コード部分については、構造体がネストされている場合に注意してください。したがって、btn(1)とbtn(2)の両方が高い場合の動作に違いが見られます。

于 2012-06-14T19:22:41.483 に答える
0

シミュレータで動作を確認することに加えて...

  • スイッチがFPGAの正しいピンにマッピングされていることを確認しますか?
  • スイッチは、押すと-が生成されるように配線されていますか?1-時々、スイッチはに浮き、押す1と生成0されます。
于 2012-06-14T09:38:06.413 に答える