0

vhdl で Mealy タイプの FSM を実装しています。私は現在二重プロセスを使用していますが、単一プロセスの方がきれいかもしれないと読んだばかりです。それをあなたの答えのパラメータと考えてください。

質問の短いバージョンは次のとおりです。別のコンポーネントの入力が変更された状態があり、その後、同じ状態で、そのコンポーネントの出力を使用できますか? それは安全でしょうか、それともラット レースでしょうか?コンポーネントの出力を使用して別の状態を作成する必要がありますか?

長いバージョン: 私はメモリ モジュールを持っています。これは fifo メモリであり、そのリセット信号をアクティブにすると、queue_pointer という名前の変数が最初の要素に移動します。メモリへの書き込み後、ポインタは増加し、範囲外になると、最初の要素にリセットされ、出力信号doneがアクティブになります。ちなみに、私はこのコンポーネントを FIMEM と呼んでいます。

私の FSM は最初に FIMEM 全体を書き、それから他の問題に移ります。最後の書き込みは次の状態から行われます。

            when SRAM_read =>
            READ_ACK                <= '1';
            FIMEM_enable            <= '1';
            FIMEM_write_readNEG  <= '0';

            if(FIMEM_done = '1') then --is that too fast? if so, we're gonna have to add another state
                FIMEM_reset <= '1'; --this is even faster, will need check
                data_pipe_to_FOMEM := DELAYS_FIMEM_TO_FOMEM;
                next_state <= processing_phase1;
            else 
                SRAM_address := SRAM_address + 1;
                next_state <= SRAM_wait_read;
            end if;

この状態で、イネーブルと書き込みがアクティブになっているということは、データが FIMEM に書き込まれることを意味します。それがメモリ上の最後のデータ空間であった場合、FIMEM_done がアクティブになり、if 内のコードのナイス チャンクが将来の処理を行います。しかし、十分な時間はありますか?そうでない場合、次の状態が SRAM_wait_read に移行し、FIMEM_done がアクティブになると、問題が発生します。FIMEM が完全に同期的であるという事実 (私のコードのこの部分が非同期プロセスにある間) は、さらに混乱を招きますか?

念のため、ここに私のメモリコードがあります:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity memory is
    generic (size: positive := 20);
    Port (  clk, 
                reset, 
                enable, 
                write_readNEG: in std_logic;
                done: out std_logic;
            data_in:  in STD_LOGIC_VECTOR(7 downto 0);  
            data_out:  out STD_LOGIC_VECTOR(7 downto 0) );
end memory;

architecture Behavioral of memory is

    subtype word is STD_LOGIC_VECTOR(7 downto 0);
    type    fifo_memory_t is array (0 to size-1) of word;
    signal fifo_memory : fifo_memory_t :=((others=> (others=>'0')));

    --Functionality instructions:
    --Resetting sets the queue pointer to the first element, and done to 0
    --Each cycle with enable active, a datum from the pointer position is
    --written/read according to write_readNEG, and the pointer is incremented.
    --If the operation was at the last element, the pointer returns to the first place
    --and done is set to 1. When done is 1, enable is ignored.

    Begin
    process(clk,reset)
            variable done_buf : std_logic;
            variable queue_pointer: natural range 0 to size-1;
    begin
        if(reset = '1') then
                queue_pointer := 0;
                done_buf := '0';
        elsif(rising_edge(clk)) then
                if(done_buf = '0' and enable = '1') then
                        case write_readNEG is
                                when '0' => 
                                        data_out <= fifo_memory(queue_pointer);
                                when '1' =>
                                        fifo_memory(queue_pointer) <= data_in;
                                when others     => null;
                        end case;
                        if(queue_pointer = size-1) then
                                done_buf := '1';
                                queue_pointer := 0;--check
                        else
                                queue_pointer := queue_pointer + 1;
                        end if;
                end if; --enable x not done if
        end if; --reset/rising edge end if
        done <= done_buf;
    end process;
End Behavioral;

最初のコメントに触発された詳細:

次に示すように、メモリは、イネーブルがアクティブになるのと同じサイクルでデータを読み取ることができ配置配線後のシミュレーション ます。

残念ながら、コードの一部は非同期プロセスにあります! 私は単一プロセスの記述に移行することを非常に強く考えていますが.

これまでに設計したすべての回路とは対照的に、シミュレーションでテストするのは非常に困難です。これは私の大学のプロジェクトで、vhdl プログラムを xilinx spartan 3 FPGA にダウンロードします。今回は、Matlab と FPGA の SRAM の間でデータを転送するユニットが与えられました (その機能はわかりません)。したがって、このユニットを使用して、SRAM とメモリ モジュールの間でデータを転送する必要があります。つまり、シミュレートするには、テストベンチ ファイルで特定のユニットをシミュレートする必要があります。そして、これは難しい..私はそれを試してみなければならないと思う.

4

1 に答える 1

2

まず第一に、シングル プロセスまたはデュアル プロセス タイプの FSM 表記を使用するかどうかは、好みの問題 (または会社のコーディング スタイル ルール) です。単一プロセス表記の方が書き込み/読み取り/管理が簡単だと思います。

イネーブル信号は、次の立ち上がりクロック エッジの後にのみメモリ コードに影響を与えます。したがって、実際のメモリ状態に関連する完了信号は、イネーブルの更新後 1 クロック サイクルで利用可能になります私は推測します(そして、投稿されたコードには表示されません)、 FSM のcurrent_state<=next_state部分は同期的です! したがって、ステート マシンは、done が更新されるまでに SRAM_wait_read 状態になります。

ところで:シミュレーターを使用してください!機能をチェックするのに役立ちます!


シミュレーション ビューを追加していただきありがとうございます。奇妙なことに、あなたの完了信号はネガで更新されます。クロックエッジ...私のシミュレーションでは、pos.で更新されます。縁; ちなみに、当然のことです! ここに画像の説明を入力

状況をより明確にするために、done <= done_buf;を移動することをお勧めします。「rising_edge-if」内の行(同期プロセスを使用する場合は、とにかくこれを行う必要があります!)。

于 2013-04-28T05:59:47.530 に答える