-- Do not edit.  Generated by cheby 1.6.dev0 using these options:
--  --gen-hdl=sfp_ctrl_if_wb.vhd -i sfp_ctrl_if_wb.cheby
-- Generated on Mon Mar 11 08:30:59 2024 by harvey


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

package sfp_ctrl_if_wb_pkg is
  type t_sfp_if_regs_master_out is record
    gpo0_gpo0_word   : std_logic_vector(31 downto 0);
    gpo1_gpo1_word   : std_logic_vector(31 downto 0);
    gpo2_gpo2_word   : std_logic_vector(31 downto 0);
  end record t_sfp_if_regs_master_out;
  subtype t_sfp_if_regs_slave_in is t_sfp_if_regs_master_out;

  type t_sfp_if_regs_slave_out is record
    gpi0_gpi0_word   : std_logic_vector(31 downto 0);
    gpi1_gpi1_word   : std_logic_vector(31 downto 0);
    gpi2_gpi2_word   : std_logic_vector(31 downto 0);
  end record t_sfp_if_regs_slave_out;
  subtype t_sfp_if_regs_master_in is t_sfp_if_regs_slave_out;

end sfp_ctrl_if_wb_pkg;

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

entity sfp_ctrl_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(5 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
    sfp_if_regs_i        : in    t_sfp_if_regs_master_in;
    sfp_if_regs_o        : out   t_sfp_if_regs_master_out
  );
end sfp_ctrl_if_wb;

architecture syn of sfp_ctrl_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 gpo0_gpo0_word_reg             : std_logic_vector(31 downto 0);
  signal gpo0_wreq                      : std_logic;
  signal gpo0_wack                      : std_logic;
  signal gpo1_gpo1_word_reg             : std_logic_vector(31 downto 0);
  signal gpo1_wreq                      : std_logic;
  signal gpo1_wack                      : std_logic;
  signal gpo2_gpo2_word_reg             : std_logic_vector(31 downto 0);
  signal gpo2_wreq                      : std_logic;
  signal gpo2_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(5 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 <= "0000";
        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 gpo0
  sfp_if_regs_o.gpo0_gpo0_word <= gpo0_gpo0_word_reg;
  process (clk_i) begin
    if rising_edge(clk_i) then
      if rst_n_i = '0' then
        gpo0_gpo0_word_reg <= "00000000000000000000000000000000";
        gpo0_wack <= '0';
      else
        if gpo0_wreq = '1' then
          gpo0_gpo0_word_reg <= wr_dat_d0;
        end if;
        gpo0_wack <= gpo0_wreq;
      end if;
    end if;
  end process;

  -- Register gpi0

  -- Register gpo1
  sfp_if_regs_o.gpo1_gpo1_word <= gpo1_gpo1_word_reg;
  process (clk_i) begin
    if rising_edge(clk_i) then
      if rst_n_i = '0' then
        gpo1_gpo1_word_reg <= "00000000000000000000000000000000";
        gpo1_wack <= '0';
      else
        if gpo1_wreq = '1' then
          gpo1_gpo1_word_reg <= wr_dat_d0;
        end if;
        gpo1_wack <= gpo1_wreq;
      end if;
    end if;
  end process;

  -- Register gpi1

  -- Register gpo2
  sfp_if_regs_o.gpo2_gpo2_word <= gpo2_gpo2_word_reg;
  process (clk_i) begin
    if rising_edge(clk_i) then
      if rst_n_i = '0' then
        gpo2_gpo2_word_reg <= "00000000000000000000000000000000";
        gpo2_wack <= '0';
      else
        if gpo2_wreq = '1' then
          gpo2_gpo2_word_reg <= wr_dat_d0;
        end if;
        gpo2_wack <= gpo2_wreq;
      end if;
    end if;
  end process;

  -- Register gpi2

  -- Process for write requests.
  process (wr_adr_d0, wr_req_d0, gpo0_wack, gpo1_wack, gpo2_wack) begin
    gpo0_wreq <= '0';
    gpo1_wreq <= '0';
    gpo2_wreq <= '0';
    case wr_adr_d0(5 downto 2) is
    when "1000" =>
      -- Reg gpo0
      gpo0_wreq <= wr_req_d0;
      wr_ack_int <= gpo0_wack;
    when "1001" =>
      -- Reg gpi0
      wr_ack_int <= wr_req_d0;
    when "1010" =>
      -- Reg gpo1
      gpo1_wreq <= wr_req_d0;
      wr_ack_int <= gpo1_wack;
    when "1011" =>
      -- Reg gpi1
      wr_ack_int <= wr_req_d0;
    when "1100" =>
      -- Reg gpo2
      gpo2_wreq <= wr_req_d0;
      wr_ack_int <= gpo2_wack;
    when "1101" =>
      -- Reg gpi2
      wr_ack_int <= wr_req_d0;
    when others =>
      wr_ack_int <= wr_req_d0;
    end case;
  end process;

  -- Process for read requests.
  process (wb_adr_i, rd_req_int, gpo0_gpo0_word_reg,
           sfp_if_regs_i.gpi0_gpi0_word, gpo1_gpo1_word_reg,
           sfp_if_regs_i.gpi1_gpi1_word, gpo2_gpo2_word_reg,
           sfp_if_regs_i.gpi2_gpi2_word) begin
    -- By default ack read requests
    rd_dat_d0 <= (others => 'X');
    case wb_adr_i(5 downto 2) is
    when "1000" =>
      -- Reg gpo0
      rd_ack_d0 <= rd_req_int;
      rd_dat_d0 <= gpo0_gpo0_word_reg;
    when "1001" =>
      -- Reg gpi0
      rd_ack_d0 <= rd_req_int;
      rd_dat_d0 <= sfp_if_regs_i.gpi0_gpi0_word;
    when "1010" =>
      -- Reg gpo1
      rd_ack_d0 <= rd_req_int;
      rd_dat_d0 <= gpo1_gpo1_word_reg;
    when "1011" =>
      -- Reg gpi1
      rd_ack_d0 <= rd_req_int;
      rd_dat_d0 <= sfp_if_regs_i.gpi1_gpi1_word;
    when "1100" =>
      -- Reg gpo2
      rd_ack_d0 <= rd_req_int;
      rd_dat_d0 <= gpo2_gpo2_word_reg;
    when "1101" =>
      -- Reg gpi2
      rd_ack_d0 <= rd_req_int;
      rd_dat_d0 <= sfp_if_regs_i.gpi2_gpi2_word;
    when others =>
      rd_ack_d0 <= rd_req_int;
    end case;
  end process;
end syn;
