entity sculpture is
Port ( clk : in STD_LOGIC;
res : in STD_LOGIC;
touch_sens : in STD_LOGIC_VECTOR (3 downto 0);
motion_sens : in STD_LOGIC;
state_out : out STD_LOGIC_VECTOR (1 downto 0);
count_out : out STD_LOGIC_VECTOR (6 downto 0);
panes : out STD_LOGIC_VECTOR (2 downto 0));
end sculpture;
architecture sculpture_a of sculpture is
component delay_counter is
Port ( clk : in STD_LOGIC;
res : in STD_LOGIC;
start_count : in STD_LOGIC;
count_done : out STD_LOGIC);
end component;
signal start_timer : std_logic;
signal end_timer : std_logic;
signal reset_cnt : std_logic;
signal state : std_logic_vector(1 downto 0);
signal next_state : std_logic_vector(1 downto 0);
signal inc_cnt : std_logic;
signal idle_cnt : std_logic_vector(6 downto 0);
signal idle_cnt_done : std_logic;
signal next_frame : std_logic_vector (2 downto 0);
signal frame : std_logic_vector (2 downto 0);
signal next_toggles : std_logic_vector (2 downto 0);
signal toggles : std_logic_vector (2 downto 0);
signal frame_cnt : std_logic_vector (3 downto 0);
signal touch : std_logic_vector (2 downto 0);
signal reset_frame_cnt : std_logic;
signal reset_frame : std_logic;
signal reset_toggle : std_logic;
signal frame_on : std_logic;
signal frame_done : std_logic;
type frame_rom is array(0 to 15) of std_logic_vector(2 downto 0);
constant RAND_ROM : frame_rom := ("111", "110", "101", "100", "011", "010", "001", "010", "100", "101", "110", "111", "000", "010", "101", "100");
constant ANIM_ROM : frame_rom := ("100", "011", "010", "011", "100", "100", "100", "011", "011", "011", "100", "110", "110", "100", "011", "010");
constant ANIM_COND : std_logic_vector(2 downto 0) := "111";
-- State 0 : RESET_S "00"
-- State 1 : BORED "01"
-- State 2 : PLAY "10"
-- State 3 : ANIMATE "11"
begin
delay: delay_counter port map (
clk => clk,
res => res,
start_count => start_timer,
count_done => end_timer
);
--State Register
process(clk, res)
begin
if (rising_edge(clk)) then
if (res = '1') then
state <= "00";
else
state <= next_state;
end if;
end if;
end process;
--Next State Logic
process(state,motion_sens,idle_cnt_done,end_timer,frame,toggles,touch_sens,frame_done,idle_cnt)
begin
case state is
when "00" =>
inc_cnt <= '0';
reset_frame_cnt <= '1';
reset_frame <= '1';
reset_cnt <= '1';
reset_toggle <= '1';
start_timer <= '1';
frame_on <= '0';
next_state <= "01";
when "01" =>
if(motion_sens = '1') then
inc_cnt <= '0';
reset_frame_cnt <= '0';
reset_frame <= '0';
reset_cnt <= '1';
reset_toggle <= '0';
start_timer <= '0';
frame_on <= '0';
next_state <= "10";
elsif(idle_cnt_done = '1') then
inc_cnt <= '0';
reset_toggle <= '0';
reset_frame <= '0';
start_timer <= '0';
frame_on <= '1';
reset_cnt <= '1';
next_state <= "01";
elsif(end_timer = '1') then
inc_cnt <= '1';
reset_toggle <= '0';
reset_frame <= '0';
reset_cnt <= '0';
start_timer <= '1';
frame_on <= '0';
next_state <= "01";
else
inc_cnt <= inc_cnt;
reset_toggle <= reset_toggle;
reset_frame <= reset_frame;
start_timer <= start_timer;
frame_on <= frame_on;
reset_cnt <= reset_cnt;
next_state <= next_state;
end if;
when "10" =>
if((frame xor toggles) = "111") then
inc_cnt <= '0';
reset_toggle <= '1';
reset_frame <= '0';
start_timer <= '0';
frame_on <= '0';
reset_cnt <= '1';
next_state <= "11";
elsif(touch_sens(0) = '1') then
inc_cnt <= '0';
reset_toggle <= '0';
reset_frame <= '0';
start_timer <= '0';
frame_on <= '0';
touch(0) <= '1';
reset_cnt <= '1';
next_state <= "10";
elsif(touch_sens(1) = '1') then
inc_cnt <= '0';
reset_toggle <= '0';
reset_frame <= '0';
start_timer <= '0';
frame_on <= '0';
touch(1) <= '1';
reset_cnt <= '1';
next_state <= "10";
elsif(touch_sens(2) = '1') then
inc_cnt <= '0';
reset_toggle <= '0';
reset_frame <= '0';
start_timer <= '0';
frame_on <= '0';
touch(2) <= '1';
reset_cnt <= '1';
next_state <= "10";
elsif(idle_cnt_done = '1') then
inc_cnt <= '0';
reset_toggle <= '0';
reset_frame <= '0';
start_timer <= '0';
frame_on <= '0';
reset_cnt <= '1';
next_state <= "01";
elsif(end_timer = '1') then
inc_cnt <= '1';
reset_toggle <= '0';
reset_frame <= '0';
reset_cnt <= '0';
frame_on <= '0';
start_timer <= '1';
next_state <= "10";
else
inc_cnt <= inc_cnt;
reset_toggle <= reset_toggle;
reset_frame <= reset_frame;
start_timer <= start_timer;
frame_on <= frame_on;
reset_cnt <= reset_cnt;
next_state <= next_state;
end if;
when "11" =>
if(frame_done = '1') then
inc_cnt <= '0';
reset_toggle <= '0';
reset_frame <= '0';
start_timer <= '0';
frame_on <= '0';
reset_cnt <= '0';
next_state <= "10";
elsif(idle_cnt = "0000001") then
inc_cnt <= '0';
reset_toggle <= '0';
reset_frame <= '0';
start_timer <= '0';
reset_cnt <= '1';
frame_on <= '1';
next_state <= "11";
elsif(end_timer = '1') then
inc_cnt <= '1';
reset_toggle <= '0';
reset_frame <= '0';
reset_cnt <= '0';
frame_on <= '0';
start_timer <= '1';
next_state <= "11";
else
inc_cnt <= inc_cnt;
reset_toggle <= reset_toggle;
reset_frame <= reset_frame;
start_timer <= start_timer;
frame_on <= frame_on;
reset_cnt <= reset_cnt;
next_state <= next_state;
end if;
when others =>
inc_cnt <= inc_cnt;
reset_toggle <= reset_toggle;
reset_frame <= reset_frame;
start_timer <= start_timer;
frame_on <= frame_on;
reset_cnt <= reset_cnt;
next_state <= next_state;
end case;
end process;
-- Array Register
process(clk, res, reset_frame_cnt, frame_on)
begin
if(rising_edge(clk)) then
if(res = '1') then
frame_cnt <= X"0";
elsif(reset_frame_cnt = '1') then
frame_cnt <= X"0";
elsif(frame_on = '1') then
frame_cnt <= frame_cnt + '1';
else
frame_cnt <= frame_cnt;
end if;
end if;
end process;
frame_done <= '1' when (frame_cnt = X"F") else '0';
-- Frame Register
process(clk, res, reset_frame, state)
begin
if(rising_edge(clk)) then
if(res = '1') then
next_frame <= "000";
elsif(reset_frame = '1') then
next_frame <= "000";
elsif(state = "01") then
next_frame <= RAND_ROM(conv_integer(frame_cnt));
elsif(state = "11") then
next_frame <= ANIM_ROM(conv_integer(frame_cnt));
else
next_frame <= next_frame;
end if;
end if;
end process;
-- Idle counter
process(clk, res, reset_cnt, inc_cnt)
begin
if(rising_edge(clk)) then
if (res = '1') then
idle_cnt <= "0000000";
elsif (reset_cnt = '1') then
idle_cnt <= "0000000";
elsif (inc_cnt = '1') then
idle_cnt <= idle_cnt + '1';
else
idle_cnt <= idle_cnt;
end if;
end if;
end process;
idle_cnt_done <= '1' when (idle_cnt = "1111111") else '0';
-- Toggles Register
process(clk, res, reset_toggle, touch)
begin
if(rising_edge(clk)) then
if(res = '1') then
next_toggles <= "000";
elsif(reset_toggle = '1') then
next_toggles <= "000";
elsif(touch(0) = '1') then
next_toggles <= NOT(toggles xor "001");
elsif(touch(1) = '1') then
next_toggles <= NOT(toggles xor "010");
elsif(touch(2) = '1') then
next_toggles <= NOT(toggles xor "100");
else
next_toggles <= next_toggles;
end if;
end if;
end process;
frame <= next_frame;
toggles <= next_toggles;
panes <= frame xor toggles;
state_out <= state;
count_out <= idle_cnt;
end sculpture_a;