library ieee;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.all;

entity cliff_classic is
port (
  ds : out STD_LOGIC;
  rd : out STD_LOGIC;
  clk : in STD_LOGIC;
  go : in STD_LOGIC;
  rst_n : in STD_LOGIC;
  ws : in STD_LOGIC
);
end cliff_classic;

architecture fizzim of cliff_classic is

-- state bits
subtype state_type is STD_LOGIC_VECTOR(3 downto 0);

constant IDLE: state_type:="0001";
constant IDLE_BIT: natural:=0;
constant DLY: state_type:="0010";
constant DLY_BIT: natural:=1;
constant DONE: state_type:="0100";
constant DONE_BIT: natural:=2;
constant READ: state_type:="1000";
constant READ_BIT: natural:=3;
constant XXX: state_type:="XXXX";

signal state,nextstate: state_type;
signal ds_fzm: STD_LOGIC;
signal rd_fzm: STD_LOGIC;

-- comb always block
begin
  COMB: process(state,clk,go,rst_n,ws) begin
    nextstate <= "0000";

    if (state(IDLE_BIT) = '1') then
      if (go='1') then
        nextstate(READ_BIT) <= '1';
      else
        nextstate(IDLE_BIT) <= '1';
      end if;
    end if;

    if (state(DLY_BIT) = '1') then
      if (ws='1') then
        nextstate(READ_BIT) <= '1';
      else
        nextstate(DONE_BIT) <= '1';
      end if;
    end if;

    if (state(DONE_BIT) = '1') then
      nextstate(IDLE_BIT) <= '1';
    end if;

    if (state(READ_BIT) = '1') then
      nextstate(DLY_BIT) <= '1';
    end if;

  end process;

  -- Port renames for vhdl
  ds <= ds_fzm;
  rd <= rd_fzm;

  -- sequential always block
  FF: process(clk,rst_n,nextstate) begin
    if (rst_n='0') then
      state <= IDLE;
    elsif (rising_edge(clk)) then
      state <= nextstate;
    end if;
  end process;

  -- datapath sequential always block
  DP: process(clk,rst_n,nextstate) begin
    if (rst_n='0') then
      ds_fzm <= '0';
      rd_fzm <= '0';
    elsif (rising_edge(clk)) then
      ds_fzm <= '0'; -- default
      rd_fzm <= '0'; -- default

      if (nextstate(IDLE_BIT) = '1') then
      end if;

      if (nextstate(DLY_BIT) = '1') then
        rd_fzm <= '1';
      end if;

      if (nextstate(DONE_BIT) = '1') then
        ds_fzm <= '1';
      end if;

      if (nextstate(READ_BIT) = '1') then
        rd_fzm <= '1';
      end if;

    end if;
  end process;
end fizzim;