library ieee; use ieee.std_LOGIC_1164.all; use IEEE.STD_LOGIC_ARITH.all; use IEEE.STD_LOGIC_unsigned.all; -- using undebounced PB1, PB2 -- for this application, do not need to debounce PB1, PB2 entity tbfsm is port ( signal PB1, PB2: in std_logic; signal CLK : in std_logic; signal output_rdy : in std_logic; signal LSB_a, LSB_b, LSB_c, LSB_d, LSB_e, LSB_f, LSB_g, LSB_dp, MSB_a, MSB_b, MSB_c, MSB_d, MSB_e, MSB_f, MSB_g, MSB_dp : out std_logic; signal input_rdy : in std_logic; signal multdin : in std_logic_vector(7 downto 0); signal flexsw0: in std_logic; signal flexsw1: in std_logic; signal flexsw2: in std_logic; signal flexsw3: in std_logic; signal flexsw4: in std_logic; signal flexsw5: in std_logic; signal flexsw6: in std_logic; signal flexsw7: in std_logic; signal cf_start, cf_load : out std_logic; signal reset : out std_logic; signal accout : out std_logic_vector(7 downto 0); signal state : out std_logic_vector(3 downto 0); signal multdout : out std_logic_vector(8 downto 0) ); end tbfsm; architecture a of tbfsm is signal istate : std_logic_vector(13 downto 0); -- main FSM CONSTANT FSM_A : std_logic_vector(3 downto 0) := "0000"; CONSTANT FSM_B : std_logic_vector(3 downto 0) := "0001"; CONSTANT FSM_C : std_logic_vector(3 downto 0) := "0011"; CONSTANT FSM_Y : std_logic_vector(3 downto 0) := "0010"; CONSTANT FSM_Z : std_logic_vector(3 downto 0) := "0110"; CONSTANT FSM_W : std_logic_vector(3 downto 0) := "0111"; CONSTANT FSM_WAIT : std_logic_vector(3 downto 0) := "1110"; CONSTANT FSM_STOP : std_logic_vector(3 downto 0) := "1100"; CONSTANT FSM_X : std_logic_vector(3 downto 0) := "1111"; signal pstate: std_logic_vector(3 downto 0); signal accstate : std_logic_vector(7 downto 0); signal cntr: std_logic_vector(5 downto 0); signal cntr_zero : std_logic; signal sclr, inc, en : std_logic; signal flexsw_sync : std_logic_vector(7 downto 0); signal PB1_sync, PB2_sync :std_logic; signal MSB : std_logic_vector(3 downto 0); signal LSB : std_logic_vector(3 downto 0); signal LSB_7SEG,MSB_7SEG: std_logic_vector(6 Downto 0); begin multdout(8) <= '0'; multdout (7) <= istate (11); multdout (6) <= istate (10); multdout (5) <= istate (8); multdout (4) <= istate (7); multdout (3) <= istate (5); multdout (2) <= istate (4); multdout (1) <= istate (3); multdout (0) <= istate (2); cntr_zero <= '1' when (cntr = "000000") else '0'; accout <= accstate; MSB <= accstate(7 downto 4); LSB <= accstate(3 downto 0); state <= pstate; sync: process begin wait until (clk'event) and (clk='1'); PB1_Sync <= NOT PB1; -- PB1_sync, PB2_sync now active high PB2_Sync <= NOT PB2; flexsw_sync(0) <= flexsw0; flexsw_sync(1) <= flexsw1; flexsw_sync(2) <= flexsw2; flexsw_sync(3) <= flexsw3; flexsw_sync(4) <= flexsw4; flexsw_sync(5) <= flexsw5; flexsw_sync(6) <= flexsw6; flexsw_sync(7) <= flexsw7; end process sync; ffstate:process begin wait until (clk'event) and (clk='1'); -- accum register if (output_rdy = '1' ) then accstate <= accstate xor multdin; end if; -- lsfr register if (en = '1') then istate <= istate (12 downto 0) & (istate(13)xor istate(12) xor istate(11) xor istate(1)); end if; if (inc = '1') then cntr <= cntr + 1; end if; if (sclr = '1') then istate <= "00000000000000"; istate(12) <= flexsw_sync(7); istate(10) <= flexsw_sync(6); istate(9) <= flexsw_sync(5); istate(7) <= flexsw_sync(4); istate(3) <= flexsw_sync(3); istate(0) <= '1'; cntr <= "000001"; end if; -- fsm Code CASE pstate IS -- power up state when FSM_A => sclr <= '1'; inc <= '0'; en <= '0'; accstate <= "00000000"; reset <= '1'; cf_load <= '0'; cf_start <= '0'; if (PB1_sync = '1') then pstate <= FSM_B; end if; when FSM_B => reset <= '0'; en <= '1'; inc <= '1'; sclr <= '0'; if (cntr_zero = '1') then cf_load <= '1'; pstate <= FSM_C; end if; when FSM_C => cf_load <= '0'; -- load in some coefficents en <= '1'; inc <= '1'; if (cntr_zero = '1') then cf_start <= '1'; -- provide X, and keep Start asserted pstate <= FSM_X; end if; -- cf_start kicks things off. Input ready must be -- input_rdy must be asserted for the next 3 clocks. -- each time want more data, assert input rdy, will be provided on -- next sucessive 4 clocks -- for fully pipelined, keep input ready asserted all the time -- during entire computation, cf_start must be keep asserted. If -- cf_start is brought low, then current computation is finished. -- get 32 inputs when FSM_Y => inc <= '0'; en <= '1'; if (cntr_zero = '1') then cf_start <= '0'; end if; pstate <= FSM_Z; when FSM_Z => en <= '1'; pstate <= FSM_W; when FSM_W => en <= '0'; pstate <= FSM_WAIT; if (cntr_zero = '1') then pstate <= FSM_STOP; elsif (input_rdy = '1') then en <= '1'; inc <= '1'; pstate <= FSM_X; end if; when FSM_X => en <= '1'; inc <= '0'; pstate <= FSM_Y; when FSM_WAIT => en <= '0'; if (input_rdy = '1') then en <= '1'; inc <= '1'; pstate <= FSM_X; end if; when FSM_STOP => en <= '0'; if (PB2_sync = '1') then pstate <= FSM_A; end if; cf_start <= '0'; when OTHERS => pstate <= FSM_A; end case; end process ffstate; MSB_dp <= '0'; MSB_a <= NOT MSB_7SEG(6); MSB_b <= NOT MSB_7SEG(5); MSB_c <= NOT MSB_7SEG(4); MSB_d <= NOT MSB_7SEG(3); MSB_e <= NOT MSB_7SEG(2); MSB_f <= NOT MSB_7SEG(1); MSB_g <= NOT MSB_7SEG(0); LSB_dp <= '0'; LSB_a <= NOT LSB_7SEG(6); LSB_b <= NOT LSB_7SEG(5); LSB_c <= NOT LSB_7SEG(4); LSB_d <= NOT LSB_7SEG(3); LSB_e <= NOT LSB_7SEG(2); LSB_f <= NOT LSB_7SEG(1); LSB_g <= NOT LSB_7SEG(0); LED_DISPLAY: process (MSB,LSB) -- BCD to 7 Segment Decoders for LED Displays begin CASE MSB IS WHEN "0000" => MSB_7SEG <= "1111110"; WHEN "0001" => MSB_7SEG <= "0110000"; WHEN "0010" => MSB_7SEG <= "1101101"; WHEN "0011" => MSB_7SEG <= "1111001"; WHEN "0100" => MSB_7SEG <= "0110011"; WHEN "0101" => MSB_7SEG <= "1011011"; WHEN "0110" => MSB_7SEG <= "1011111"; WHEN "0111" => MSB_7SEG <= "1110000"; WHEN "1000" => MSB_7SEG <= "1111111"; WHEN "1001" => MSB_7SEG <= "1111011"; WHEN "1010" => MSB_7SEG <= "1110111"; WHEN "1011" => MSB_7SEG <= "0011111"; WHEN "1100" => MSB_7SEG <= "1001110"; WHEN "1101" => MSB_7SEG <= "0111101"; WHEN "1110" => MSB_7SEG <= "1001111"; WHEN "1111" => MSB_7SEG <= "1000111"; WHEN OTHERS => MSB_7SEG <= "0000001"; END CASE; CASE LSB IS WHEN "0000" => LSB_7SEG <= "1111110"; WHEN "0001" => LSB_7SEG <= "0110000"; WHEN "0010" => LSB_7SEG <= "1101101"; WHEN "0011" => LSB_7SEG <= "1111001"; WHEN "0100" => LSB_7SEG <= "0110011"; WHEN "0101" => LSB_7SEG <= "1011011"; WHEN "0110" => LSB_7SEG <= "1011111"; WHEN "0111" => LSB_7SEG <= "1110000"; WHEN "1000" => LSB_7SEG <= "1111111"; WHEN "1001" => LSB_7SEG <= "1111011"; WHEN "1010" => LSB_7SEG <= "1110111"; WHEN "1011" => LSB_7SEG <= "0011111"; WHEN "1100" => LSB_7SEG <= "1001110"; WHEN "1101" => LSB_7SEG <= "0111101"; WHEN "1110" => LSB_7SEG <= "1001111"; WHEN "1111" => LSB_7SEG <= "1000111"; WHEN OTHERS => LSB_7SEG <= "0000001"; END CASE; end process LED_DISPLAY; end a;