-- Do not edit.  Generated on Thu Mar 19 12:30:09 2020 by tgingold
-- With Cheby 1.4.dev0 and these options:
--  -i vtudiag_regs.cheby --gen-hdl vtudiag_regs.vhd


library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wishbone_pkg.all;

entity vtudiag_regs is
  port (
    rst_n_i              : in    std_logic;
    clk_i                : in    std_logic;
    wb_i                 : in    t_wishbone_slave_in;
    wb_o                 : out   t_wishbone_slave_out;

    -- Control register
    -- Select the window to measure the frequency.  A change to this value is taken into account at the end of the current window. 00: 500us; 01: 50ms; 10: 5s; 11: 20s
    control_window_o     : out   std_logic_vector(1 downto 0);

    -- This register is incremented at the end of the window, when the new frequency is made available.
    generation_i         : in    std_logic_vector(15 downto 0);

    -- Number of period of the input signal during the previous window period.
    freq_i               : in    std_logic_vector(31 downto 0);

    -- This register is incremented on each rising edge of the signal. Not valid if the input frequency is greater than the clock.
    counter_i            : in    std_logic_vector(31 downto 0)
  );
end vtudiag_regs;

architecture syn of vtudiag_regs is
  signal adr_int                        : std_logic_vector(3 downto 1);
  signal rd_req_int                     : std_logic;
  signal wr_req_int                     : std_logic;
  signal rd_ack_int                     : std_logic;
  signal wr_ack_int                     : std_logic;
  signal wb_en                          : std_logic;
  signal ack_int                        : std_logic;
  signal wb_rip                         : std_logic;
  signal wb_wip                         : std_logic;
  signal control_window_reg             : std_logic_vector(1 downto 0);
  signal control_wreq                   : std_logic;
  signal control_wack                   : std_logic;
  signal rd_ack_d0                      : std_logic;
  signal rd_dat_d0                      : std_logic_vector(15 downto 0);
  signal wr_req_d0                      : std_logic;
  signal wr_adr_d0                      : std_logic_vector(3 downto 1);
  signal wr_dat_d0                      : std_logic_vector(15 downto 0);
  signal wr_sel_d0                      : std_logic_vector(1 downto 0);
begin

  -- WB decode signals
  adr_int <= wb_i.adr(3 downto 1);
  wb_en <= wb_i.cyc and wb_i.stb;

  process (clk_i) begin
    if rising_edge(clk_i) then
      if rst_n_i = '0' then
        wb_rip <= '0';
      else
        wb_rip <= (wb_rip or (wb_en and not wb_i.we)) and not rd_ack_int;
      end if;
    end if;
  end process;
  rd_req_int <= (wb_en and not wb_i.we) and not wb_rip;

  process (clk_i) begin
    if rising_edge(clk_i) then
      if rst_n_i = '0' then
        wb_wip <= '0';
      else
        wb_wip <= (wb_wip or (wb_en and wb_i.we)) and not wr_ack_int;
      end if;
    end if;
  end process;
  wr_req_int <= (wb_en and wb_i.we) and not wb_wip;

  ack_int <= rd_ack_int or wr_ack_int;
  wb_o.ack <= ack_int;
  wb_o.stall <= not ack_int and wb_en;
  wb_o.rty <= '0';
  wb_o.err <= '0';

  -- pipelining for wr-in+rd-out
  process (clk_i) begin
    if rising_edge(clk_i) then
      if rst_n_i = '0' then
        rd_ack_int <= '0';
        wr_req_d0 <= '0';
      else
        rd_ack_int <= rd_ack_d0;
        wb_o.dat(15 downto 0) <= rd_dat_d0;
        wr_req_d0 <= wr_req_int;
        wr_adr_d0 <= adr_int;
        wr_dat_d0 <= wb_i.dat(15 downto 0);
        wr_sel_d0 <= wb_i.sel(1 downto 0);
      end if;
    end if;
  end process;

  -- Register control
  control_window_o <= control_window_reg;
  process (clk_i) begin
    if rising_edge(clk_i) then
      if rst_n_i = '0' then
        control_window_reg <= "00";
        control_wack <= '0';
      else
        if control_wreq = '1' then
          control_window_reg <= wr_dat_d0(1 downto 0);
        end if;
        control_wack <= control_wreq;
      end if;
    end if;
  end process;

  -- Register generation

  -- Register freq

  -- Register counter

  -- Process for write requests.
  process (wr_adr_d0, wr_req_d0, control_wack) begin
    control_wreq <= '0';
    case wr_adr_d0(3 downto 2) is
    when "00" => 
      case wr_adr_d0(1 downto 1) is
      when "0" => 
        -- Reg control
        control_wreq <= wr_req_d0;
        wr_ack_int <= control_wack;
      when "1" => 
        -- Reg generation
        wr_ack_int <= wr_req_d0;
      when others =>
        wr_ack_int <= wr_req_d0;
      end case;
    when "01" => 
      case wr_adr_d0(1 downto 1) is
      when "0" => 
        -- Reg freq
        wr_ack_int <= wr_req_d0;
      when "1" => 
        -- Reg freq
        wr_ack_int <= wr_req_d0;
      when others =>
        wr_ack_int <= wr_req_d0;
      end case;
    when "10" => 
      case wr_adr_d0(1 downto 1) is
      when "0" => 
        -- Reg counter
        wr_ack_int <= wr_req_d0;
      when "1" => 
        -- Reg counter
        wr_ack_int <= wr_req_d0;
      when others =>
        wr_ack_int <= wr_req_d0;
      end case;
    when others =>
      wr_ack_int <= wr_req_d0;
    end case;
  end process;

  -- Process for read requests.
  process (adr_int, rd_req_int, control_window_reg, generation_i, freq_i, counter_i) begin
    -- By default ack read requests
    rd_dat_d0 <= (others => 'X');
    case adr_int(3 downto 2) is
    when "00" => 
      case adr_int(1 downto 1) is
      when "0" => 
        -- Reg control
        rd_ack_d0 <= rd_req_int;
        rd_dat_d0(1 downto 0) <= control_window_reg;
        rd_dat_d0(15 downto 2) <= (others => '0');
      when "1" => 
        -- Reg generation
        rd_ack_d0 <= rd_req_int;
        rd_dat_d0 <= generation_i;
      when others =>
        rd_ack_d0 <= rd_req_int;
      end case;
    when "01" => 
      case adr_int(1 downto 1) is
      when "0" => 
        -- Reg freq
        rd_ack_d0 <= rd_req_int;
        rd_dat_d0 <= freq_i(31 downto 16);
      when "1" => 
        -- Reg freq
        rd_ack_d0 <= rd_req_int;
        rd_dat_d0 <= freq_i(15 downto 0);
      when others =>
        rd_ack_d0 <= rd_req_int;
      end case;
    when "10" => 
      case adr_int(1 downto 1) is
      when "0" => 
        -- Reg counter
        rd_ack_d0 <= rd_req_int;
        rd_dat_d0 <= counter_i(31 downto 16);
      when "1" => 
        -- Reg counter
        rd_ack_d0 <= rd_req_int;
        rd_dat_d0 <= counter_i(15 downto 0);
      when others =>
        rd_ack_d0 <= rd_req_int;
      end case;
    when others =>
      rd_ack_d0 <= rd_req_int;
    end case;
  end process;
end syn;
