-- Do not edit.  Generated on Thu Jul 22 08:41:43 2021 by tgingold
-- With Cheby 1.5.dev0 and these options:
--  -i fmc_adc_sata_regs.cheby --gen-hdl=fmc_adc_sata_regs.vhd


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

entity sata_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;

    -- Status register
    -- Transceiver 0 is locked and aligned
    rdy0_i               : in    std_logic;
    -- Transceiver 1 is locked and aligned
    rdy1_i               : in    std_logic;
    -- Byte received from transceiver 0
    rx0_i                : in    std_logic;
    -- Byte received from transceiver 1
    rx1_i                : in    std_logic;

    -- Control register
    -- Reset transceiver 0
    rst0_o               : out   std_logic;
    -- Reset transceiver 1
    rst1_o               : out   std_logic;

    -- Last data byte received from rx 0
    rx_data_0_i          : in    std_logic_vector(31 downto 0);
    rx_data_0_rd_o       : out   std_logic;

    -- Last data byte received from rx 1
    rx_data_1_i          : in    std_logic_vector(31 downto 0);
    rx_data_1_rd_o       : out   std_logic;

    -- Byte to be send on tx 0
    tx_data_0_o          : out   std_logic_vector(31 downto 0);
    tx_data_0_wr_o       : out   std_logic;

    -- Byte to be send on tx 1
    tx_data_1_o          : out   std_logic_vector(31 downto 0);
    tx_data_1_wr_o       : out   std_logic
  );
end sata_regs;

architecture syn of sata_regs is
  signal adr_int                        : std_logic_vector(4 downto 2);
  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 rst0_reg                       : std_logic;
  signal rst1_reg                       : std_logic;
  signal control_wreq                   : std_logic;
  signal control_wack                   : std_logic;
  signal tx_data_0_reg                  : std_logic_vector(31 downto 0);
  signal tx_data_0_wreq                 : std_logic;
  signal tx_data_0_wack                 : std_logic;
  signal tx_data_1_reg                  : std_logic_vector(31 downto 0);
  signal tx_data_1_wreq                 : std_logic;
  signal tx_data_1_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);
  signal wr_sel_d0                      : std_logic_vector(3 downto 0);
begin

  -- WB decode signals
  adr_int <= wb_i.adr(4 downto 2);
  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 <= rd_dat_d0;
        wr_req_d0 <= wr_req_int;
        wr_adr_d0 <= adr_int;
        wr_dat_d0 <= wb_i.dat;
        wr_sel_d0 <= wb_i.sel;
      end if;
    end if;
  end process;

  -- Register status

  -- Register control
  rst0_o <= rst0_reg;
  rst1_o <= rst1_reg;
  process (clk_i) begin
    if rising_edge(clk_i) then
      if rst_n_i = '0' then
        rst0_reg <= '0';
        rst1_reg <= '0';
        control_wack <= '0';
      else
        if control_wreq = '1' then
          rst0_reg <= wr_dat_d0(0);
          rst1_reg <= wr_dat_d0(1);
        end if;
        control_wack <= control_wreq;
      end if;
    end if;
  end process;

  -- Register rx_data_0

  -- Register rx_data_1

  -- Register tx_data_0
  tx_data_0_o <= tx_data_0_reg;
  process (clk_i) begin
    if rising_edge(clk_i) then
      if rst_n_i = '0' then
        tx_data_0_reg <= "00000000000000000000000000000000";
        tx_data_0_wack <= '0';
      else
        if tx_data_0_wreq = '1' then
          tx_data_0_reg <= wr_dat_d0;
        end if;
        tx_data_0_wack <= tx_data_0_wreq;
      end if;
    end if;
  end process;
  tx_data_0_wr_o <= tx_data_0_wack;

  -- Register tx_data_1
  tx_data_1_o <= tx_data_1_reg;
  process (clk_i) begin
    if rising_edge(clk_i) then
      if rst_n_i = '0' then
        tx_data_1_reg <= "00000000000000000000000000000000";
        tx_data_1_wack <= '0';
      else
        if tx_data_1_wreq = '1' then
          tx_data_1_reg <= wr_dat_d0;
        end if;
        tx_data_1_wack <= tx_data_1_wreq;
      end if;
    end if;
  end process;
  tx_data_1_wr_o <= tx_data_1_wack;

  -- Process for write requests.
  process (wr_adr_d0, wr_req_d0, control_wack, tx_data_0_wack, tx_data_1_wack) begin
    control_wreq <= '0';
    tx_data_0_wreq <= '0';
    tx_data_1_wreq <= '0';
    case wr_adr_d0(4 downto 2) is
    when "000" =>
      -- Reg status
      wr_ack_int <= wr_req_d0;
    when "001" =>
      -- Reg control
      control_wreq <= wr_req_d0;
      wr_ack_int <= control_wack;
    when "010" =>
      -- Reg rx_data_0
      wr_ack_int <= wr_req_d0;
    when "011" =>
      -- Reg rx_data_1
      wr_ack_int <= wr_req_d0;
    when "100" =>
      -- Reg tx_data_0
      tx_data_0_wreq <= wr_req_d0;
      wr_ack_int <= tx_data_0_wack;
    when "101" =>
      -- Reg tx_data_1
      tx_data_1_wreq <= wr_req_d0;
      wr_ack_int <= tx_data_1_wack;
    when others =>
      wr_ack_int <= wr_req_d0;
    end case;
  end process;

  -- Process for read requests.
  process (adr_int, rd_req_int, rdy0_i, rdy1_i, rx0_i, rx1_i, rst0_reg, rst1_reg, rx_data_0_i, rx_data_1_i) begin
    -- By default ack read requests
    rd_dat_d0 <= (others => 'X');
    rx_data_0_rd_o <= '0';
    rx_data_1_rd_o <= '0';
    case adr_int(4 downto 2) is
    when "000" =>
      -- Reg status
      rd_ack_d0 <= rd_req_int;
      rd_dat_d0(0) <= rdy0_i;
      rd_dat_d0(1) <= rdy1_i;
      rd_dat_d0(15 downto 2) <= (others => '0');
      rd_dat_d0(16) <= rx0_i;
      rd_dat_d0(17) <= rx1_i;
      rd_dat_d0(31 downto 18) <= (others => '0');
    when "001" =>
      -- Reg control
      rd_ack_d0 <= rd_req_int;
      rd_dat_d0(0) <= rst0_reg;
      rd_dat_d0(1) <= rst1_reg;
      rd_dat_d0(31 downto 2) <= (others => '0');
    when "010" =>
      -- Reg rx_data_0
      rx_data_0_rd_o <= rd_req_int;
      rd_ack_d0 <= rd_req_int;
      rd_dat_d0 <= rx_data_0_i;
    when "011" =>
      -- Reg rx_data_1
      rx_data_1_rd_o <= rd_req_int;
      rd_ack_d0 <= rd_req_int;
      rd_dat_d0 <= rx_data_1_i;
    when "100" =>
      -- Reg tx_data_0
      rd_ack_d0 <= rd_req_int;
    when "101" =>
      -- Reg tx_data_1
      rd_ack_d0 <= rd_req_int;
    when others =>
      rd_ack_d0 <= rd_req_int;
    end case;
  end process;
end syn;
