6

VHDL で有限状態マシンを実装しているかどうか、すべての出力が可能なすべての状態にあることを述べる必要があるかどうか疑問に思っていますか? 一部の出力が 1 つの状態から別の状態に変化しないことがわかっていて、状態の順序も同じ順序になることがわかっていても?

たとえば、この (強制) 例では:

entity test is
    port (
        clk : in std_logic;
        a : in std_logic;
        b: out std_logic;
        c: out std_logic;
    );
end test;

architecture Behavioral of test is

type executionStage is (s1,s2,s3);
signal currentstate, nextstate: executionStage;

begin
    process (clk)
    begin
          if(rising_edge(clk)) then
                 currentstate <= nextstate;
          else 
                 currentstate <= currentstate;
          end if;
    end process;

    process(currentstate)
    begin
        case currentstate is
            when s1 =>
                if (a = '1') then
                    b <= '1';
                    c <= '0';
                else
                    b <= '1';
                    c <= '1';
                end if;

                nextstate <= s2;

            when s2 =>
                -- b doesnt change state from s1 to here, do I need to define what it is here?
                if (a = '1') then
                    b <= '1';
                    c <= '1';
                else
                    b <= '1';
                    c <= '0';
                end if;

                nextstate <= s3;

            when s3 =>
                if (a = '1') then
                    b <= '0';
                    c <= '0';
                else
                    b <= '1';
                    c <= '1';
                end if;

                nextstate <= s1;
        end case;
    end process;
end Behavioral;

私の理解では、これを行わないとラッチが作成されますか?

そのような例では大したことではありませんが、10 を超える出力と 10 を超えるステートを持つマシンを使用している場合、VHDL ファイルが信じられないほど乱雑に見え始めます。何度も同じこと。これを行うより良い方法はありますか?

編集:出力の「デフォルト」状態を定義できますか? IE は、すべてのプロセスの外側で b を 1 に設定し、それが 0 である case ステートメントでのみ定義します。それはうまくいくでしょうか?

4

6 に答える 6

7

サンプル コードの 3 つの問題:

ポート リストの最後のポートにはセミコロンを含めないでください。

port (
    clk : in std_logic;
    a : in std_logic;
    b: out std_logic;
    c: out std_logic -- no semicolon here!!!
    );

登録プロセスでは、「else」ステートメントを使用しないでください。これはおそらくツールによって受け入れられるでしょうが、仲間の VHDL 設計者を混乱させるでしょう。

process (clk)
begin
    if(rising_edge(clk)) then
        currentstate <= nextstate;
    end if;
end process;

組み合わせロジックでは、センシティビティ リストには、読み取ったすべてのシグナルが含まれている必要がありますprocess(a, currentstate)。この特定のケースでは (再び) うまくいく可能性がありますが、感度リストが正しくない場合、ラッチを推測したり、他の問題を引き起こしたりすることになります。

あなたの質問について:

  1. はい、組み合わせプロセスの各信号に (状態ごとに) 値を割り当てる必要があります。
  2. Tomi が言及しているように、プロセスの最初にデフォルト値を割り当てることで、これを簡単に行うことができます。
  3. ただし、ステート マシン全体を 1 つの同期プロセスで記述することもできます。このように、すべての状態のすべての信号に値を割り当てる必要はありません。
于 2011-05-15T12:58:47.243 に答える
7

はい、プロセスのいくつかの分岐で組み合わせを意図した信号のみを駆動する場合、ラッチを推測します。

caseただし、ステートメントの前に (ただし同じプロセス内で) シグナルに値を割り当てるだけで、シグナルの「デフォルト」状態を定義できます。例えば:

process(currentstate, a)
begin
    b <= '1';
    c <= '1';
    case currentstate is
        when s1 =>
            if (a = '1') then
                c <= '0';
            end if;

            nextstate <= s2;

        when s2 =>
            -- b doesnt change state from s1 to here, do I need to define what it is here?
            if (a /= '1') then
                c <= '0';
            end if;

            nextstate <= s3;

        when s3 =>
            if (a = '1') then
                b <= '0';
                c <= '0';
            end if;

            nextstate <= s1;
    end case;
end process;
于 2011-05-14T14:53:41.420 に答える
3

Philippe の応答へのメモ (直接コメントすることはできませんか?)。

私は、2 プロセス スタイルでステート マシンを記述することを好みます。推論されたフリップフロップが予想される場所と予想されない場所が非常に明確になります。また、ハードウェアの説明にもう少し沿っています。たとえば、ボード レベルのロジックを使用してステート マシンを構築することを想像してください。登録されたデバイスは状態 <= next_state プロセスと一致し、case ステートメントは状態レジスタの前の and/or 配列にマップされます。

そうは言っても、私は通常、小さな単純なタスクには 1 つのプロセス ステート マシンを使用し、より大きなタスクには 2 つのプロセス マシンに移行します。状態出力をさまざまな「タスク」グループに編成するために、3 番目のプロセスを使用することもありますが、頻繁ではありません。非常に大きなステート マシンは、アーキテクチャに作業が必要であると教えてくれる傾向があります。

于 2012-10-18T20:56:34.723 に答える
0
process (clk)
begin
  if(rising_edge(clk)) then
    currentstate <= nextstate;
  end if;
end process;

やあ

上記のプロセスには問題がありますが、機密リストによるものではありません。順次処理の clk のみを宣言しても問題ありません。シミュレーション ツールと合成ツールの両方に問題はありません。clk は、結局のところ、コード内で最も高速に変化/遷移する信号です。

ただし、(できれば) 非同期リセットを使用する必要があります。もちろん、最近のベンダーは、FPGA 設計ではリセットは必要ないとさえ言っています。それらは起動時に発生します。または、同期リセットを提案します。

それでも、非同期リセットはボードベースの環境では価値があります。

つまり、デザインにリセットを追加し、その動作を適切に修正します。

よろしくニコラオス・カヴァディアス

于 2011-06-23T10:45:31.033 に答える
0

次の VHDL コードは、レベル センシティブ ステート マシンです。この例のレベル センシティブ プロセスは、「out1」を「clk」と位相をずらし、「out2」を「clk」と同相にします。

entity main_code is
    Port ( clk : in  STD_LOGIC;
           in1 : in  STD_LOGIC;
           in2 : in  STD_LOGIC;
           out1 : out  STD_LOGIC;
           out2 : out  STD_LOGIC);
end main_code;

architecture Behavioral of main_code is

-- here are temp signals to associate or assign output (out1 and out2) values indirectly
signal out1_temp : std_logic := '0';  
signal out2_temp : std_logic := '0';

-- counter registers 
signal counter : integer range 0 to 255 := 0;
signal counter_8th_clk : integer range 0 to 255 := 0;
-- state machines definition
type state_machine_type is (s0,s1);
signal state : state_machine_type := s0;
begin
-- concurrent assignments
out1 <= out1_temp;
out2 <= out2_temp;

--half clock generator process
half_clock : process (clk) is
begin
if rising_edge(clk) then
--out1_temp <= not out1_temp;
end if;
end process half_clock;

-- max counter = ndiv -1; here ndiv=4; counter starts from zero;
one_fourth_clock : process (clk)
begin
if rising_edge(clk) then
counter <= counter + 1;
    if (counter >= 3) then 
        counter <= 0;
--      out2_temp <= not out2_temp;
    end if;
end if;
end process one_fourth_clock;


one_eighth_clock : process (clk)
begin
if rising_edge(clk) then
counter_8th_clk <= counter_8th_clk + 1;
    if (counter_8th_clk>=7) then
        counter_8th_clk <= 0;
--      out2_temp <= not out2_temp;
    end if;
end if;
end process one_eighth_clock;

-- state_process creates two half clock (speed) with out1 out of phase with clk
-- and out2 in-phase with clk
-- following process is sensitive to clk level not edge
state_process_level_sensitive : process (clk)
begin
case state  is

    when s0 =>
        out1_temp <= not out1_temp;
        state <= s1;
    when s1 =>
        out2_temp <= not out2_temp;
        state <= s0;
end case;
end process state_process_level_sensitive;



end Behavioral;

ここにテストベンチがあります

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 my_test_bench IS
END my_test_bench;

ARCHITECTURE behavior OF my_test_bench IS 

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

    COMPONENT main_code
    PORT(
         clk : IN  std_logic;
         in1 : IN  std_logic;
         in2 : IN  std_logic;
         out1 : OUT  std_logic;
         out2 : OUT  std_logic
        );
    END COMPONENT;


   --Inputs
   signal clk : std_logic := '0';
   signal in1 : std_logic := '0';
   signal in2 : std_logic := '0';

    --Outputs
   signal out1 : std_logic;
   signal out2 : std_logic;

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

BEGIN

    -- Instantiate the Unit Under Test (UUT)
   uut: main_code PORT MAP (
          clk => clk,
          in1 => in1,
          in2 => in2,
          out1 => out1,
          out2 => out2
        );

   -- 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.
--      wait for 100 ns;    
--
--      wait for clk_period*10;

      -- insert stimulus here 

      wait;
   end process;

END;
于 2019-12-14T05:20:43.180 に答える