diff options
author | Tristan Gingold <tgingold@free.fr> | 2016-04-02 07:40:37 +0200 |
---|---|---|
committer | Tristan Gingold <tgingold@free.fr> | 2016-04-02 07:40:37 +0200 |
commit | 66e31d6d8c4faab0aeadee87298f13a3b67adbfb (patch) | |
tree | af863500c6e1ddf22321538a6c51247fccd57704 /testsuite/gna/issue50/vector.d/fsm.vhd | |
parent | 122fa90fb7e5c15b58efa100da828c1e879b4e4e (diff) | |
download | ghdl-66e31d6d8c4faab0aeadee87298f13a3b67adbfb.tar.gz ghdl-66e31d6d8c4faab0aeadee87298f13a3b67adbfb.tar.bz2 ghdl-66e31d6d8c4faab0aeadee87298f13a3b67adbfb.zip |
Add testcase for issue50.
Diffstat (limited to 'testsuite/gna/issue50/vector.d/fsm.vhd')
-rw-r--r-- | testsuite/gna/issue50/vector.d/fsm.vhd | 396 |
1 files changed, 396 insertions, 0 deletions
diff --git a/testsuite/gna/issue50/vector.d/fsm.vhd b/testsuite/gna/issue50/vector.d/fsm.vhd new file mode 100644 index 000000000..2f4ef87ee --- /dev/null +++ b/testsuite/gna/issue50/vector.d/fsm.vhd @@ -0,0 +1,396 @@ +--test bench written by Alban Bourge @ TIMA +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use std.textio.all; +library work; +use work.pkg_tb.all; + +entity fsm is + port( + clock : in std_logic; + reset : in std_logic; + --prog interface + instr_next : in instruction; + step : out std_logic; + --uut interface + cp_ok : in std_logic; + stdin_rdy : in std_logic; + stdin_ack : in std_logic; + reset_fsm : out std_logic; + start : out std_logic; + cp_en : out std_logic; + cp_rest : out std_logic; + --ram interface + ram_1 : out ram_instruction; + ram_2 : out ram_instruction; + --assert_uut interface + context_uut : out context_t; + en_feed : out std_logic; + en_check : out std_logic; + vecs_found : in std_logic; + vec_read : in std_logic; + --tb interface + stopped : out std_logic + ); +end fsm; + +architecture rtl of fsm is + + -- read output + signal step_sig : std_logic; + -- FSM signals + signal instr_c : instruction := instr_rst; + signal instr_n : instruction := instr_rst; + -- TIMER signal + signal times_en : std_logic := '0'; + signal times_z : std_logic := '0'; + signal times : unsigned(ARG_WIDTH - 1 downto 0); + signal times_max : unsigned(ARG_WIDTH - 1 downto 0); + signal times_ok : std_logic := '0'; + -- COUNTER signal + signal count_en : std_logic := '0'; + signal count_z : std_logic := '0'; + signal count : unsigned(ARG_WIDTH - 1 downto 0); + signal count_max : unsigned(ARG_WIDTH - 1 downto 0); + signal count_ok : std_logic := '0'; + -- runtime counter + signal runtime_en : std_logic := '0'; + signal runtime : integer range 0 to 99999999; --100 million cycles + +begin + + -- FSM + state_reg : process (clock, reset) is + begin + if (reset = '1') then + instr_c <= instr_rst; + elsif rising_edge(clock) then + instr_c <= instr_n; + end if; + end process state_reg; + + comb_logic: process(instr_next, instr_c, stdin_rdy, count_ok, times_ok, cp_ok, stdin_ack, vecs_found, vec_read) + begin + --default definition for fsm control signals + instr_n <= instr_rst; + step_sig <= '0'; + --top + reset_fsm <= '0'; + start <= '0'; + cp_en <= '0'; + cp_rest <= '0'; + --counter & timer + times_en <= '0'; + times_max <= (others => '0'); + count_en <= '0'; + count_max <= (others => '0'); + --runtime counter + runtime_en <= '0'; + --ram + ram_1 <= ram_instr_z; + ram_2 <= ram_instr_z; + --assert_uut + en_feed <= '0'; + en_check <= '0'; + --tb interface + stopped <= '0'; + + case instr_c.state is + when Rst => + --signals + reset_fsm <= '1'; + ram_1.addr_z <= '1'; + ram_2.addr_z <= '1'; + step_sig <= '1'; --demand for next instruction + --transition + instr_n <= instr_next; + + when Sig_start => + --signals + start <= '1'; + step_sig <= '1'; --demand for next instruction + --transition + instr_n <= instr_next; + --if (instr_next.state = Ack_data) then + --en_feed <= '1'; + --end if; + + when Ack_data => + times_max <= instr_c.arg - 1; + --signals + en_feed <= '1'; + --transition + if (stdin_rdy = '1' and stdin_ack = '1') then + times_en <= '1'; + end if; + if (times_ok = '1') then + en_feed <= '0'; + step_sig <= '1'; + instr_n <= instr_next; + else + instr_n <= instr_c; + end if; + + when Running => + --signals + count_max <= instr_c.arg; + count_en <= '1'; + --en_check <= '1'; + --runtime counter + if(vecs_found = '0') then + runtime_en <= '1'; + end if; + --transition + if (count_ok = '1') then + step_sig <= '1'; + instr_n <= instr_next; + else + instr_n <= instr_c; + end if; + + when Waitfor => + --signals + count_max <= instr_c.arg; + en_check <= '1'; + if(vec_read = '1') then + count_en <= '1'; + end if; + --runtime counter + if(vecs_found = '0') then + runtime_en <= '1'; + end if; + --transition + if (count_ok = '1') then + step_sig <= '1'; + instr_n <= instr_next; + else + instr_n <= instr_c; + end if; + + when Cp_search => + --signals + cp_en <= '1'; + --transition + if (cp_ok = '1') then + case instr_c.context_uut is + when "01" => + ram_1.we <= '1'; + ram_1.addr_up <= '1'; + ram_1.sel <= '1'; + when "10" => + ram_2.we <= '1'; + ram_2.addr_up <= '1'; + ram_2.sel <= '1'; + when others => + end case; + instr_n <= (state => Cp_save, context_uut => instr_c.context_uut, arg => (others => '0')); --hard coded + else + instr_n <= instr_c; + end if; + + when Cp_save => + --signals + cp_en <= '1'; + case instr_c.context_uut is + when "01" => + ram_1.we <= '1'; + ram_1.addr_up <= '1'; + ram_1.sel <= '1'; + when "10" => + ram_2.we <= '1'; + ram_2.addr_up <= '1'; + ram_2.sel <= '1'; + when others => + end case; + --transition + if (cp_ok = '0') then + case instr_c.context_uut is + when "01" => + ram_1.we <= '0'; + ram_1.addr_up <= '0'; + when "10" => + ram_2.we <= '0'; + ram_2.addr_up <= '0'; + when others => + end case; + step_sig <= '1'; + instr_n <= instr_next; + else + instr_n <= instr_c; + end if; + + when Idle => + --signals + count_max <= instr_c.arg; + count_en <= '1'; + --transition + if (count_ok = '1') then + step_sig <= '1'; + instr_n <= instr_next; + else + instr_n <= instr_c; + end if; + + when Rst_uut => + --signals + reset_fsm <= '1'; + ram_1.addr_z <= '1'; + ram_2.addr_z <= '1'; + --transition + step_sig <= '1'; + instr_n <= instr_next; + + when Rest_ini0 => + --signals + start <= '1'; + cp_en <= '1'; + cp_rest <= '1'; + --this is for restoration : reading the first word of the right memory + case instr_c.context_uut is + when "01" => + ram_1.sel <= '1'; + when "10" => + ram_2.sel <= '1'; + when others => + end case; + --transition + instr_n <= (state => Rest_ini1, context_uut => instr_c.context_uut, arg => (others => '0')); --hard coded + + when Rest_ini1 => + --signals + cp_en <= '1'; + cp_rest <= '1'; + case instr_c.context_uut is + when "01" => + ram_1.addr_up <= '1'; + ram_1.sel <= '1'; + when "10" => + ram_2.addr_up <= '1'; + ram_2.sel <= '1'; + when others => + end case; + --transition + instr_n <= (state => Rest, context_uut => instr_c.context_uut, arg => (others => '0')); --hard coded + + when Rest => + --signals + cp_en <= '1'; + cp_rest <= '1'; + case instr_c.context_uut is + when "01" => + ram_1.addr_up <= '1'; + ram_1.sel <= '1'; + when "10" => + ram_2.addr_up <= '1'; + ram_2.sel <= '1'; + when others => + end case; + --transition + if (cp_ok = '0') then + step_sig <= '1'; + instr_n <= instr_next; + else + instr_n <= instr_c; + end if; + + when Stop => + --signals + stopped <= '1'; + reset_fsm <= '1'; + report "RUNTIME:" & integer'image(runtime); + assert (vecs_found = '0') + report "END_OF_SIM ---> Stop state reached, some output vectors were read." severity note; + --transition + instr_n <= (state => Stop, context_uut => "00", arg => (others => '0')); --hard coded + + when others => + end case; + end process comb_logic; + + --*ER reset combo logic + --if a step_sig signal is sent, it means a instr_next will be consumed + reseter : process(step_sig) + begin + if (step_sig = '0') then + times_z <= '0'; + count_z <= '0'; + else + times_z <= '1'; + count_z <= '1'; + end if; + end process reseter; + + --TIMER + timer : process(clock, reset) + begin + if (reset = '1') then + times <= (others => '0'); + times_ok <= '0'; + elsif rising_edge(clock) then + if (times_z = '1') then + times <= (others => '0'); + times_ok <= '0'; + else + if (times_en = '1') then + times <= times + 1; + if (times = times_max) then + times_ok <= '1'; + else + times_ok <= '0'; + end if; + end if; + end if; + end if; + end process timer; + + --COUNTER + counter : process(clock, reset) + begin + if (reset = '1') then + count <= (others => '0'); + count_ok <= '0'; + elsif rising_edge(clock) then + --count_ok driving if + if (count_z = '1') then + count_ok <= '0'; + count <= (others => '0'); + else + if (count = count_max) then + count_ok <= '1'; + else + count_ok <= '0'; + if (count_en = '1') then + count <= count + 1; + end if; + end if; + end if; + end if; + end process counter; + + --Runtime counter + runtime_counter : process(clock, reset) + begin + if (reset = '1') then + runtime <= 0; + elsif rising_edge(clock) then + if (runtime_en = '1') then + runtime <= runtime + 1; + if ((runtime mod 1000) = 0) then + report "Running since:" & integer'image(runtime) severity note; + end if; + end if; + end if; + end process runtime_counter; + + -- process only used for reporting current instruction + reporter : process(instr_c) + begin + --report "Instruction: " & state_t'image(instr_c.state) severity note; + report "Instruction: " & state_t'image(instr_c.state) & " (context " & integer'image(to_integer(unsigned(instr_c.context_uut))) & ")" severity note; + end process reporter; + + --Combinational + step <= step_sig; + context_uut <= instr_c.context_uut; +end rtl; |