VHDL の宿題を書いていますが、理解できない奇妙な動作が発生します。
コンセプトは以下。乱数の生成に使用される LFSR が必要です。LFSR は、I_CLK または I_NEXT 入力によって駆動できます。LFSR が I_CLK によって駆動される場合、その出力で乱数を自動的に生成する必要がありますが、I_NEXT 入力によって駆動される場合、I_NEXT 値を手動で 0 から 1 に変更して数値を生成する必要があります。次の問題があります。コード。プロセスの 1 つをコメントアウトすると、LFSR は正常に機能しますが、すべてのプロセスが有効になっていると、まったく機能しません。問題を解決するのを手伝ってくれませんか? 設計ミスのはずですが、設計のどこが悪いのかわかりません。
entity LFSR_v2 is
Generic (
width : positive := 31;
tap_1 : positive := 30;
tap_2 : positive := 27
);
Port (
i_enable : in std_logic;
i_reset : in std_logic;
i_clk : in std_logic;
i_next : in std_logic;
i_free_run : in std_logic;
i_load : in std_logic;
i_direction : in std_logic;
o_number : out std_logic_vector (width -1 downto 0);
i_seed : in std_logic_vector (width -1 downto 0)
);
end LFSR_v2;
architecture Behavioral of LFSR_v2 is
signal internal_number : std_logic_vector(width -1 downto 0);
begin
-------------------------------------------------------------------------------------------
-- FREE RUNNING PROCESS
--
-- In Free Running mode the LFSR switches its state on every rising edge of the i_clk input.
-------------------------------------------------------------------------------------------
next_number_free_run : process(i_clk, i_reset)
--variable fileline : line;
--variable gen_num : integer;
begin
if rising_edge(i_clk) then
--------------------------------------
-- NORMAL MODE
-- enable = 1
-- reset = 0
--------------------------------------
if (i_enable = '1' and i_free_run = '1') then
-- Internal number to the output
o_number <= internal_number;
-----------------------------
-- RESET
-----------------------------
if(i_reset = '1') then
if(i_direction = '1') then
internal_number <= (OTHERS => '1');
else
internal_number <= (OTHERS => '0');
end if;
else
------------------------------
-- LOAD SEED
-- load = 1
------------------------------
if(i_load = '1') then
internal_number <= i_seed;
else
--------------------------------------
-- GENERATE NEXT NUMBER - FREE RUNNING
-- load = 0
-- free_run = 1
-------------------------------------
if(i_direction = '1') then
internal_number <= internal_number(width - 2 downto 0) & (internal_number(tap_1) xnor internal_number(tap_2));
else
internal_number <= internal_number(width - 2 downto 0) & (internal_number(tap_1) xor internal_number(tap_2));
end if;
----------------------------------------
-- FILE LOGGING
----------------------------------------
--gen_num := to_integer(internal_number);
--write(fileline, gen_num);
--writeline(MyFile, fileline);
end if;
end if;
end if;
end if;
end process next_number_free_run;
---------------------------------------------------------------------------------
-- MANUAL RUNNING PROCESS
--
-- In this mode the LFSR does not use the input clock to generate the next number.
-- Number can be generated by creating a 0 -> 1 signal change on the i_next input.
---------------------------------------------------------------------------------
next_number_man_run : process(i_next, i_reset)
--variable fileline : line;
--variable gen_num : integer;
begin
if rising_edge(i_next) then
--------------------------------------
-- NORMAL MODE
-- enable = 1
-- reset = 0
--------------------------------------
if (i_enable = '1' and i_free_run = '0') then
-- Internal number to the output
o_number <= internal_number;
-----------------------------
-- RESET
-----------------------------
if(i_reset = '1') then
if(i_direction = '1') then
internal_number <= (OTHERS => '1');
else
internal_number <= (OTHERS => '0');
end if;
else
------------------------------
-- LOAD SEED
-- load = 1
------------------------------
if(i_load = '1') then
internal_number <= i_seed;
else
--------------------------------------
-- GENERATE NEXT NUMBER - FREE RUNNING
-- load = 0
-- free_run = 1
-------------------------------------
if(i_direction = '1') then
internal_number <= internal_number(width - 2 downto 0) & (internal_number(tap_1) xnor internal_number(tap_2));
else
internal_number <= internal_number(width - 2 downto 0) & (internal_number(tap_1) xor internal_number(tap_2));
end if;
----------------------------------------
-- FILE LOGGING
----------------------------------------
--gen_num := to_integer(internal_number);
--write(fileline, gen_num);
--writeline(MyFile, fileline);
end if;
end if;
end if;
end if;
end process next_number_man_run;
end Behavioral;
コードのテスト ベンチ:
----------------------------
-- TEST SEED INIT
----------------------------
-- ENABLE OFF -> SEED SHOULD NOT BE INITIALIZED
s_enable <= '0';
s_reset <= '0';
s_free_run <= '0';
s_load <= '1';
s_next <= '0';
s_direction <= '0';
s_seed <= (OTHERS => '1');
wait for 20 ns;
-- ENABLE ON -> SEED SHOULD BE INITIALIZED
s_enable <= '1';
s_reset <= '0';
s_next <= '0';
s_free_run <= '0';
s_load <= '1';
s_direction <= '0';
s_seed <= (OTHERS => '1');
wait for 20 ns;
-- DRIVE MANUAL
s_next <= '1';
wait for clk_period /2;
s_next <= '0';
wait for clk_period /2;
s_next <= '1';
wait for clk_period /2;
s_next <= '0';
wait for clk_period /2;