-- Do not edit.  Generated by cheby 1.6.dev0 using these options:
--  --gen-hdl=si549_if_wb.vhd -i si549_if_wb.cheby
-- Generated on Tue Mar 05 09:30:54 2024 by harvey


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

package si549_if_wb_pkg is
  type t_si549_regs_master_out is record
    CR_I2C_ADDR      : std_logic_vector(7 downto 0);
    CR_ENABLE        : std_logic;
    CR_GAIN          : std_logic_vector(7 downto 0);
    CR_CLK_DIV       : std_logic_vector(7 downto 0);
    CR_BUSY          : std_logic;
    GAIN_GAIN_VALUE  : std_logic_vector(15 downto 0);
    GPSR_scl         : std_logic;
    GPSR_sda         : std_logic;
    GPSR_wr          : std_logic;
    GPCR_scl         : std_logic;
    GPCR_sda         : std_logic;
    DEBUG_DAC_VAL    : std_logic_vector(15 downto 0);
    DEBUG_wr         : std_logic;
  end record t_si549_regs_master_out;
  subtype t_si549_regs_slave_in is t_si549_regs_master_out;

  type t_si549_regs_slave_out is record
    CR_BUSY          : std_logic;
    GPSR_scl         : std_logic;
    GPSR_sda         : std_logic;
  end record t_si549_regs_slave_out;
  subtype t_si549_regs_master_in is t_si549_regs_slave_out;

end si549_if_wb_pkg;

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

entity si549_if_wb is
  port (
    rst_n_i              : in    std_logic;
    clk_i                : in    std_logic;
    wb_cyc_i             : in    std_logic;
    wb_stb_i             : in    std_logic;
    wb_adr_i             : in    std_logic_vector(4 downto 2);
    wb_sel_i             : in    std_logic_vector(3 downto 0);
    wb_we_i              : in    std_logic;
    wb_dat_i             : in    std_logic_vector(31 downto 0);
    wb_ack_o             : out   std_logic;
    wb_err_o             : out   std_logic;
    wb_rty_o             : out   std_logic;
    wb_stall_o           : out   std_logic;
    wb_dat_o             : out   std_logic_vector(31 downto 0);
    -- Wires and registers
    si549_regs_i         : in    t_si549_regs_master_in;
    si549_regs_o         : out   t_si549_regs_master_out
  );
end si549_if_wb;

architecture syn of si549_if_wb is
  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 CR_I2C_ADDR_reg                : std_logic_vector(7 downto 0);
  signal CR_ENABLE_reg                  : std_logic;
  signal CR_GAIN_reg                    : std_logic_vector(7 downto 0);
  signal CR_CLK_DIV_reg                 : std_logic_vector(7 downto 0);
  signal CR_wreq                        : std_logic;
  signal CR_wack                        : std_logic;
  signal GAIN_GAIN_VALUE_reg            : std_logic_vector(15 downto 0);
  signal GAIN_wreq                      : std_logic;
  signal GAIN_wack                      : std_logic;
  signal GPSR_wreq                      : std_logic;
  signal GPCR_scl_reg                   : std_logic;
  signal GPCR_sda_reg                   : std_logic;
  signal GPCR_wreq                      : std_logic;
  signal GPCR_wack                      : std_logic;
  signal DEBUG_DAC_VAL_reg              : std_logic_vector(15 downto 0);
  signal DEBUG_wreq                     : std_logic;
  signal DEBUG_wack                     : std_logic;
  signal rd_ack_d0                      : std_logic;
  signal rd_dat_d0                      : std_logic_vector(31 downto 0);
  signal wr_req_d0                      : std_logic;
  signal wr_adr_d0                      : std_logic_vector(4 downto 2);
  signal wr_dat_d0                      : std_logic_vector(31 downto 0);
begin

  -- WB decode signals
  wb_en <= wb_cyc_i and wb_stb_i;

  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_we_i)) and not rd_ack_int;
      end if;
    end if;
  end process;
  rd_req_int <= (wb_en and not wb_we_i) 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_we_i)) and not wr_ack_int;
      end if;
    end if;
  end process;
  wr_req_int <= (wb_en and wb_we_i) and not wb_wip;

  ack_int <= rd_ack_int or wr_ack_int;
  wb_ack_o <= ack_int;
  wb_stall_o <= not ack_int and wb_en;
  wb_rty_o <= '0';
  wb_err_o <= '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';
        wb_dat_o <= "00000000000000000000000000000000";
        wr_req_d0 <= '0';
        wr_adr_d0 <= "000";
        wr_dat_d0 <= "00000000000000000000000000000000";
      else
        rd_ack_int <= rd_ack_d0;
        wb_dat_o <= rd_dat_d0;
        wr_req_d0 <= wr_req_int;
        wr_adr_d0 <= wb_adr_i;
        wr_dat_d0 <= wb_dat_i;
      end if;
    end if;
  end process;

  -- Register CR
  si549_regs_o.CR_I2C_ADDR <= CR_I2C_ADDR_reg;
  si549_regs_o.CR_ENABLE <= CR_ENABLE_reg;
  si549_regs_o.CR_GAIN <= CR_GAIN_reg;
  si549_regs_o.CR_CLK_DIV <= CR_CLK_DIV_reg;
  si549_regs_o.CR_BUSY <= wr_dat_d0(25);
  process (clk_i) begin
    if rising_edge(clk_i) then
      if rst_n_i = '0' then
        CR_I2C_ADDR_reg <= "00000000";
        CR_ENABLE_reg <= '0';
        CR_GAIN_reg <= "00000000";
        CR_CLK_DIV_reg <= "00000000";
        CR_wack <= '0';
      else
        if CR_wreq = '1' then
          CR_I2C_ADDR_reg <= wr_dat_d0(7 downto 0);
          CR_ENABLE_reg <= wr_dat_d0(8);
          CR_GAIN_reg <= wr_dat_d0(16 downto 9);
          CR_CLK_DIV_reg <= wr_dat_d0(24 downto 17);
        end if;
        CR_wack <= CR_wreq;
      end if;
    end if;
  end process;

  -- Register GAIN
  si549_regs_o.GAIN_GAIN_VALUE <= GAIN_GAIN_VALUE_reg;
  process (clk_i) begin
    if rising_edge(clk_i) then
      if rst_n_i = '0' then
        GAIN_GAIN_VALUE_reg <= "0000000000000000";
        GAIN_wack <= '0';
      else
        if GAIN_wreq = '1' then
          GAIN_GAIN_VALUE_reg <= wr_dat_d0(15 downto 0);
        end if;
        GAIN_wack <= GAIN_wreq;
      end if;
    end if;
  end process;

  -- Register GPSR
  si549_regs_o.GPSR_scl <= wr_dat_d0(0);
  si549_regs_o.GPSR_sda <= wr_dat_d0(1);
  si549_regs_o.GPSR_wr <= GPSR_wreq;

  -- Register GPCR
  si549_regs_o.GPCR_scl <= GPCR_scl_reg;
  si549_regs_o.GPCR_sda <= GPCR_sda_reg;
  process (clk_i) begin
    if rising_edge(clk_i) then
      if rst_n_i = '0' then
        GPCR_scl_reg <= '0';
        GPCR_sda_reg <= '0';
        GPCR_wack <= '0';
      else
        if GPCR_wreq = '1' then
          GPCR_scl_reg <= wr_dat_d0(0);
          GPCR_sda_reg <= wr_dat_d0(1);
        else
          GPCR_scl_reg <= '0';
          GPCR_sda_reg <= '0';
        end if;
        GPCR_wack <= GPCR_wreq;
      end if;
    end if;
  end process;

  -- Register DEBUG
  si549_regs_o.DEBUG_DAC_VAL <= DEBUG_DAC_VAL_reg;
  process (clk_i) begin
    if rising_edge(clk_i) then
      if rst_n_i = '0' then
        DEBUG_DAC_VAL_reg <= "0000000000000000";
        DEBUG_wack <= '0';
      else
        if DEBUG_wreq = '1' then
          DEBUG_DAC_VAL_reg <= wr_dat_d0(15 downto 0);
        end if;
        DEBUG_wack <= DEBUG_wreq;
      end if;
    end if;
  end process;
  si549_regs_o.DEBUG_wr <= DEBUG_wack;

  -- Process for write requests.
  process (wr_adr_d0, wr_req_d0, CR_wack, GAIN_wack, GPCR_wack, DEBUG_wack) begin
    CR_wreq <= '0';
    GAIN_wreq <= '0';
    GPSR_wreq <= '0';
    GPCR_wreq <= '0';
    DEBUG_wreq <= '0';
    case wr_adr_d0(4 downto 2) is
    when "000" =>
      -- Reg CR
      CR_wreq <= wr_req_d0;
      wr_ack_int <= CR_wack;
    when "001" =>
      -- Reg GAIN
      GAIN_wreq <= wr_req_d0;
      wr_ack_int <= GAIN_wack;
    when "010" =>
      -- Reg GPSR
      GPSR_wreq <= wr_req_d0;
      wr_ack_int <= wr_req_d0;
    when "011" =>
      -- Reg GPCR
      GPCR_wreq <= wr_req_d0;
      wr_ack_int <= GPCR_wack;
    when "100" =>
      -- Reg DEBUG
      DEBUG_wreq <= wr_req_d0;
      wr_ack_int <= DEBUG_wack;
    when others =>
      wr_ack_int <= wr_req_d0;
    end case;
  end process;

  -- Process for read requests.
  process (wb_adr_i, rd_req_int, CR_I2C_ADDR_reg, CR_ENABLE_reg, CR_GAIN_reg,
           CR_CLK_DIV_reg, si549_regs_i.CR_BUSY, GAIN_GAIN_VALUE_reg,
           si549_regs_i.GPSR_scl, si549_regs_i.GPSR_sda, DEBUG_DAC_VAL_reg) begin
    -- By default ack read requests
    rd_dat_d0 <= (others => 'X');
    case wb_adr_i(4 downto 2) is
    when "000" =>
      -- Reg CR
      rd_ack_d0 <= rd_req_int;
      rd_dat_d0(7 downto 0) <= CR_I2C_ADDR_reg;
      rd_dat_d0(8) <= CR_ENABLE_reg;
      rd_dat_d0(16 downto 9) <= CR_GAIN_reg;
      rd_dat_d0(24 downto 17) <= CR_CLK_DIV_reg;
      rd_dat_d0(25) <= si549_regs_i.CR_BUSY;
      rd_dat_d0(31 downto 26) <= (others => '0');
    when "001" =>
      -- Reg GAIN
      rd_ack_d0 <= rd_req_int;
      rd_dat_d0(15 downto 0) <= GAIN_GAIN_VALUE_reg;
      rd_dat_d0(31 downto 16) <= (others => '0');
    when "010" =>
      -- Reg GPSR
      rd_ack_d0 <= rd_req_int;
      rd_dat_d0(0) <= si549_regs_i.GPSR_scl;
      rd_dat_d0(1) <= si549_regs_i.GPSR_sda;
      rd_dat_d0(31 downto 2) <= (others => '0');
    when "011" =>
      -- Reg GPCR
      rd_ack_d0 <= rd_req_int;
    when "100" =>
      -- Reg DEBUG
      rd_ack_d0 <= rd_req_int;
      rd_dat_d0(15 downto 0) <= DEBUG_DAC_VAL_reg;
      rd_dat_d0(31 downto 16) <= (others => '0');
    when others =>
      rd_ack_d0 <= rd_req_int;
    end case;
  end process;
end syn;
