-- To inform CPU about state: 3 Bit stateinfo: -- 000: Resetting -- 001: Resetted -- 010: running -- 011: disabling -- 100: disabled library IEEE; use IEEE.std_logic_1164.all; use IEEE.STD_LOGIC_ARITH.all; use IEEE.STD_LOGIC_UNSIGNED.all; entity fsm is port ( clk : in std_logic; reset_n : in std_logic; en : in std_logic; -- from CPU via SCSN to ctrl FSM rst : in std_logic; -- from CPU via SCSN to ctrl FSM cnt_en : out std_logic; -- to Counter block cnt_srst : out std_logic; -- to Counter block memin_zero : out std_logic; -- to dpmem input we : out std_logic; -- to dpmem hold_cntval : out std_logic; -- to dpmem calculator stateinfo : out std_logic_vector (2 downto 0); -- to CPU via SCSN address : out std_logic_vector (9 downto 0) -- to Counter block and dpmem ); end fsm; architecture behv of fsm is constant wscntwidth : integer := 3; component acnt port ( clk : in std_logic; reset_n : in std_logic; acnt_clr : in std_logic; acnt_en : in std_logic; acnt_zero : out std_logic; address : out std_logic_vector (9 downto 0)); end component; component waitstate generic ( cntwidth : integer); port ( clk : in std_logic; reset_n : in std_logic; val : in std_logic_vector(cntwidth-1 downto 0); start : in std_logic; expired : out std_logic); end component; type st_t is (rst_start, rst_wait_srst, rst_write, rst_inca, rst_test, rst_done, en_start, en_wait_cntmux, en_latch_cnt, en_wait_calc, en_write, en_inca, dis_start, dis_wait_cntmux, dis_latch_cnt, dis_wait_calc, dis_write, dis_inca, dis_test, dis_clr_first, dis_done); signal cst, nst : st_t; attribute state_vector : string; attribute state_vector of behv : architecture is "cst"; -- internal signals to used components signal acnt_clr : std_logic; signal acnt_en : std_logic; signal acnt_zero : std_logic; signal ws_val : std_logic_vector(wscntwidth-1 downto 0); signal ws_start : std_logic; signal ws_exp : std_logic; -- internal signal to first register signal firstreg : std_logic; signal en_first : std_logic; signal set_first : std_logic; begin -- behv -- acnt_1 : acnt port map ( clk => clk, reset_n => reset_n, acnt_clr => acnt_clr, acnt_en => acnt_en, acnt_zero => acnt_zero, address => address); -- waitstate_1 : waitstate generic map ( cntwidth => wscntwidth) port map ( clk => clk, reset_n => reset_n, val => ws_val, start => ws_start, expired => ws_exp); -- register to track disabling process: During disabling all counter data is -- copied to memory, continuing where the addresscounter was during en_ until -- the addresscounter wraps _two_ times. First round: from n to end, soecond -- round from begin to end. firstreg_p: process (clk, reset_n) begin -- process firstreg_p if reset_n = '0' then -- asynchronous reset (active low) firstreg <= '0'; elsif clk'event and clk = '1' then -- rising clock edge if en_first='1' then firstreg <= set_first; end if; end if; end process firstreg_p; -- fsm sequencial fsmreg : process (clk, reset_n) begin -- process fsmreg if reset_n = '0' then -- asynchronous reset (active low) cst <= rst_start; elsif clk'event and clk = '1' then -- rising clock edge cst <= nst; end if; end process fsmreg; -- fsm Combinatoric fsm_comb : process(cst,en,rst,ws_exp,acnt_zero,firstreg) begin -- process fsm_comb case cst is when rst_start => nst <= rst_wait_srst; when rst_wait_srst => if ws_exp = '1' then nst <= rst_write; else nst <= rst_wait_srst; end if; when rst_write => nst <= rst_inca; when rst_inca => nst <= rst_test; when rst_test => if acnt_zero = '1' then nst <= rst_done; else nst <= rst_write; end if; when rst_done => if en = '1' then nst <= en_start; else nst <= rst_done; end if; when en_start => nst <= en_wait_cntmux; when en_wait_cntmux => if ws_exp = '1' then nst <= en_latch_cnt; else nst <= en_wait_cntmux; end if; when en_latch_cnt => nst <= en_wait_calc; when en_wait_calc => if ws_exp = '1' then nst <= en_write; else nst <= en_wait_calc; end if; when en_write => nst <= en_inca; when en_inca => if rst = '1' then nst <= rst_start; elsif en = '1' then nst <= en_wait_cntmux; else nst <= dis_start; end if; when dis_start => nst <= dis_wait_cntmux; when dis_wait_cntmux => if ws_exp = '1' then nst <= dis_latch_cnt; else nst <= dis_wait_cntmux; end if; when dis_latch_cnt => nst <= dis_wait_calc; when dis_wait_calc => if ws_exp = '1' then nst <= dis_write; else nst <= dis_wait_calc; end if; when dis_write => nst <= dis_inca; when dis_inca => nst <= dis_test; when dis_test => if acnt_zero = '1' and firstreg = '0' then nst <= dis_done; elsif acnt_zero = '1' and firstreg = '1' then nst <= dis_clr_first; else nst <= dis_wait_cntmux; end if; when dis_clr_first => nst <= dis_wait_cntmux; when dis_done => if rst = '1' then nst <= rst_start; elsif en = '1' then nst <= en_start; else nst <= dis_done; end if; when others => nst <= rst_start; end case; end process fsm_comb; -- fsm_decode -- signals to Memory/Calc Unit ----------------------- -- cnt_en Enable 576 Counter with cst select cnt_en <= '1' when en_start, '1' when en_wait_cntmux, '1' when en_latch_cnt, '1' when en_wait_calc, '1' when en_write, '1' when en_inca, '0' when others; -- cnt_srst Reset 576 Counter with cst select cnt_srst <= '1' when rst_start, '0' when others; -- memin_zero Put 48x'0' to datain of memory with cst select memin_zero <= '1' when rst_start, '1' when rst_wait_srst, '1' when rst_write, '1' when rst_inca, '1' when rst_test, '0' when others; -- we write to memory location zero or result of calc-unit with cst select we <= '1' when rst_write, '1' when en_write, '1' when dis_write, '0' when others; -- hold_cntval latch current addressed counter value from 576 Counter with cst select hold_cntval <= '1' when en_latch_cnt, '1' when dis_latch_cnt, '0' when others; -- signals to Addresscounter ----------------------- -- acnt_clr reset address counter with cst select acnt_clr <= '1' when rst_start, '1' when en_start, '0' when others; -- acnt_en enable addresscounter with cst select acnt_en <= '1' when rst_inca, '1' when en_inca, '1' when dis_inca, '0' when others; -- signals to Waitstate Logic ----------------------- with cst select -- ws_start start wait state counter ws_start <= '1' when rst_wait_srst, '1' when en_wait_cntmux, '1' when en_wait_calc, '1' when dis_wait_cntmux, '1' when dis_wait_calc, '0' when others; -- ws_val value to load in wait state counter with cst select ws_val <= "011" when rst_wait_srst, "011" when en_wait_cntmux, "011" when dis_wait_cntmux, "001" when en_wait_calc, "001" when dis_wait_calc, "000" when others; -- signals to Firstregister ----------------------- with cst select set_first <= '1' when dis_start, '0' when others; with cst select en_first <= '1' when dis_start, '1' when dis_clr_first, '0' when others; -- signals to CPU about FSM status ----------------------- with cst select stateinfo <= "000" when rst_start, "000" when rst_wait_srst, "000" when rst_write, "000" when rst_inca, "000" when rst_test, "001" when rst_done, "010" when en_start, "010" when en_wait_cntmux, "010" when en_latch_cnt, "010" when en_wait_calc, "010" when en_write, "010" when en_inca, "011" when dis_start, "011" when dis_wait_cntmux, "011" when dis_latch_cnt, "011" when dis_wait_calc, "011" when dis_write, "011" when dis_inca, "011" when dis_test, "011" when dis_clr_first, "100" when dis_done, "111" when others; end behv;