--
-- Busy Generator
--
-- Matt Warren 2015
--

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

library utils;
use utils.pkg_types.all;

library hsio;
use hsio.pkg_core_globals.all;


entity trig_busygen is
-- generic(
-- SIM_MODE : integer := 0
-- );
  port(
    trig_i        : in  std_logic;
    trig_sbusy_i   : in  std_logic;
    reg_busylen_i : in  std_logic_vector(15 downto 0);
    busy_o        : out std_logic;
    tick_i        : in  std_logic_vector (34 downto 0);
    s40           : in  std_logic;
    clk           : in  std_logic;
    rst           : in  std_logic
    );

-- Declarations

end trig_busygen;

--
architecture rtl of trig_busygen is

  signal countdiv8 : std_logic_vector(2 downto 0) := "000";


  signal bcount    : std_logic_vector(15 downto 0);
  signal bcount_en : std_logic;


  signal finelen    : std_logic_vector(11 downto 0);
  signal scale      : integer range 0 to 15;
  signal scale_tick : std_logic;


  signal busy0      : std_logic;
  signal tick_100ns : std_logic;



  type states is (Count, TrigSoftBusy, Idle);

  signal state, nstate : states;

begin

  finelen <= reg_busylen_i(11 downto 0);
  scale   <= conv_integer(reg_busylen_i(15 downto 12));

  prc_countdiv8 : process (clk)
  begin
    if rising_edge(clk) then

      --default
      tick_100ns <= '0';

      if (countdiv8 = "111") then
        tick_100ns <= '1';
        countdiv8  <= "000";
      else
        countdiv8 <= countdiv8 + '1';
      end if;
    end if;
  end process;


  busy_o <= busy0 when rising_edge(clk);

  with scale select scale_tick <=
    s40              when 0,            --  25 ns
    tick_100ns       when 1,            -- 100 ns     
    tick_i(T_1MHz)   when 2,            --   1 us
    tick_i(T_100kHz) when 3,            --  10 us
    tick_i(T_10kHz)  when 4,            -- 100 us
    tick_i(T_1kHz)   when 5,            --   1 ms
    tick_i(T_100Hz)  when 6,            --  10 ms
    tick_i(T_10Hz)   when 7,            -- 100 ms
    tick_i(T_1Hz)    when others;       --   1  s


  ----------------------------------------------------------------------

  prc_bcount : process (clk)
  begin
    if rising_edge(clk) then
      if (bcount_en = '0') then
        bcount <= (others => '0');

      elsif (scale_tick = '1') then
        bcount <= bcount + '1';
      end if;
    end if;
  end process;



  -- State Machine
  --------------------------------------------------------
  prc_sync_part : process (clk)
  begin
    if rising_edge(clk) then
      if (rst = '1') then
        state <= Idle;

      else
        state <= nstate;

      end if;
    end if;
  end process;


  prc_async_machine : process (bcount, finelen, state, trig_i, trig_sbusy_i)
  begin

    -- defaults
    busy0     <= '0';
    bcount_en <= '0';

    case state is
      ----------------------------------

      when Idle =>
        nstate <= Idle;
        if (trig_i = '1') then
          busy0  <= '1';
          if (trig_sbusy_i = '1') then
            nstate <= TrigSoftBusy;
          else
            nstate <= Count;
          end if;
        end if;


      when Count =>
        nstate    <= Count;
        busy0     <= '1';
        bcount_en <= '1';
        if (bcount = finelen) then
          nstate <= Idle;
        end if;

      when TrigSoftBusy =>
        nstate    <= TrigSoftBusy;
        busy0     <= '1';
        if (trig_sbusy_i = '0') then
          nstate <= Idle;
        end if;

    end case;
  end process;

  -------------------------------------------------------


end architecture rtl;