-- Do not edit.  Generated by cheby 1.6.dev0 using these options:
--  --gen-hdl=hydra_supervisor_regs.vhd --header=commit --gen-c=../../sw/include/hydra_supervisor_regs.h -i hydra_supervisor_regs.cheby


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

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

    -- Cause of a reset
    -- CPU divergence
    reset_cause_cpu_i    : in    std_logic;
    -- Uncorrectable ECC error in IRAM
    reset_cause_iram_ecc_i : in    std_logic;
    -- Uncorrectable ECC error in DRAM
    reset_cause_dram_ecc_i : in    std_logic;
    -- Watchdog timeout
    reset_cause_watchdog_i : in    std_logic;
    -- Software recovery
    reset_cause_recovery_i : in    std_logic;

    -- state of cpus
    -- CPU under reset due to divergence (RO)
    cpu_reset_i          : in    std_logic_vector(2 downto 0);
    cpu_reset_o          : out   std_logic_vector(2 downto 0);
    -- Set to start recovery (will reset all the cpus)
    cpu_recovery_i       : in    std_logic;
    cpu_recovery_o       : out   std_logic;
    cpu_wr_o             : out   std_logic;

    -- Each cpu will read a different value from this registers
    force_divergence_i   : in    std_logic_vector(31 downto 0);
    force_divergence_rd_o : out   std_logic;

    -- Nbr of cycles before watchdog timeout.
    wd_period_i          : in    std_logic_vector(31 downto 0);
    wd_period_o          : out   std_logic_vector(31 downto 0);
    wd_period_wr_o       : out   std_logic;

    -- Current counter value (decremented)
    wd_count_i           : in    std_logic_vector(31 downto 0);

    -- Write 0xc0423bc9 to restart watchdog counter
    wd_key_o             : out   std_logic_vector(31 downto 0);
    wd_key_wr_o          : out   std_logic;

    -- Number of ECC correctable errors for iram
    iram_ecc_se_i        : in    std_logic_vector(31 downto 0);

    -- IRAM scrubber cycle number.
    iram_scrub_cycle_i   : in    std_logic_vector(15 downto 0);

    -- Number of ECC corrected errors by scrubber in iram
    iram_scrub_se_i      : in    std_logic_vector(31 downto 0);

    -- Number of ECC uncorrected errors by scrubber in iram in the current scrubber cycle.  Saturate.

    iram_scrub_de_curr_i : in    std_logic_vector(15 downto 0);

    -- Number of ECC uncorrected errors by scrubber in iram during the last scrubber cycle.  Saturate.

    iram_scrub_de_last_i : in    std_logic_vector(15 downto 0);

    -- Number of ECC correctable errors for dram
    dram_ecc_se_i        : in    std_logic_vector(31 downto 0);

    -- DRAM scrubber cycle number.
    dram_scrub_cycle_i   : in    std_logic_vector(15 downto 0);

    -- Number of ECC corrected errors by scrubber in dram
    dram_scrub_se_i      : in    std_logic_vector(31 downto 0);

    -- Number of ECC uncorrected errors by scrubber in dram in the current scrubber cycle.  Saturate.

    dram_scrub_de_curr_i : in    std_logic_vector(15 downto 0);

    -- Number of ECC uncorrected errors by scrubber in dram during the last scrubber cycle.  Saturate.

    dram_scrub_de_last_i : in    std_logic_vector(15 downto 0);

    -- Number of CPU errors on data bus
    cpu_data_err_i       : in    std_logic_vector(31 downto 0);

    -- Number of CPU errors on instruction bus
    cpu_iaddr_err_i      : in    std_logic_vector(31 downto 0);

    -- Change ECC bits on dram writes for testing
    dram_ecc_mask_o      : out   std_logic_vector(7 downto 0);

    -- Address of the last ecc error
    iram_ecc_addr_i      : in    std_logic_vector(31 downto 0);

    -- Force one error on the address (insn)
    -- Set to enable, auto cleared
    iram_err_addr_en_i   : in    std_logic;
    iram_err_addr_en_o   : out   std_logic;
    -- Address
    iram_err_addr_addr_i : in    std_logic_vector(13 downto 0);
    iram_err_addr_addr_o : out   std_logic_vector(13 downto 0);
    iram_err_addr_wr_o   : out   std_logic;

    -- configuration of scrubbers
    -- Write 1 to enable iram scrubber (cannot be disabled)
    scrub_cfg_iram_en_i  : in    std_logic;
    scrub_cfg_iram_en_o  : out   std_logic;
    -- Write 1 to enable dram scrubber (cannot be disabled)
    scrub_cfg_dram_en_i  : in    std_logic;
    scrub_cfg_dram_en_o  : out   std_logic;
    scrub_cfg_wr_o       : out   std_logic;

    -- Maximum number of cycles between a scrub
    iram_scrub_period_o  : out   std_logic_vector(15 downto 0);

    -- Maximum number of cycles between a scrub
    dram_scrub_period_o  : out   std_logic_vector(15 downto 0);

    -- Number of cpu faults
    cpu_fault_count_i    : in    std_logic_vector(31 downto 0);
    cpu_fault_count_o    : out   std_logic_vector(31 downto 0);
    cpu_fault_count_wr_o : out   std_logic
  );
end hydra_supervisor_regs;

architecture syn of hydra_supervisor_regs is
  signal adr_int                        : std_logic_vector(6 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 cpu_wreq                       : std_logic;
  signal wd_period_wreq                 : std_logic;
  signal wd_key_reg                     : std_logic_vector(31 downto 0);
  signal wd_key_wreq                    : std_logic;
  signal wd_key_wack                    : std_logic;
  signal dram_ecc_mask_reg              : std_logic_vector(7 downto 0);
  signal dram_ecc_mask_wreq             : std_logic;
  signal dram_ecc_mask_wack             : std_logic;
  signal iram_err_addr_wreq             : std_logic;
  signal scrub_cfg_wreq                 : std_logic;
  signal iram_scrub_period_reg          : std_logic_vector(15 downto 0);
  signal iram_scrub_period_wreq         : std_logic;
  signal iram_scrub_period_wack         : std_logic;
  signal dram_scrub_period_reg          : std_logic_vector(15 downto 0);
  signal dram_scrub_period_wreq         : std_logic;
  signal dram_scrub_period_wack         : std_logic;
  signal cpu_fault_count_wreq           : 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(6 downto 2);
  signal wr_dat_d0                      : std_logic_vector(31 downto 0);
begin

  -- WB decode signals
  adr_int <= wb_i.adr(6 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;
      end if;
    end if;
  end process;

  -- Register reset_cause

  -- Register cpu
  cpu_reset_o <= wr_dat_d0(2 downto 0);
  cpu_recovery_o <= wr_dat_d0(8);
  cpu_wr_o <= cpu_wreq;

  -- Register force_divergence

  -- Register wd_period
  wd_period_o <= wr_dat_d0;
  wd_period_wr_o <= wd_period_wreq;

  -- Register wd_count

  -- Register wd_key
  wd_key_o <= wd_key_reg;
  process (clk_i) begin
    if rising_edge(clk_i) then
      if rst_n_i = '0' then
        wd_key_reg <= "00000000000000000000000000000000";
        wd_key_wack <= '0';
      else
        if wd_key_wreq = '1' then
          wd_key_reg <= wr_dat_d0;
        end if;
        wd_key_wack <= wd_key_wreq;
      end if;
    end if;
  end process;
  wd_key_wr_o <= wd_key_wack;

  -- Register iram_ecc_se

  -- Register iram_scrub_cycle

  -- Register iram_scrub_se

  -- Register iram_scrub_de_curr

  -- Register iram_scrub_de_last

  -- Register dram_ecc_se

  -- Register dram_scrub_cycle

  -- Register dram_scrub_se

  -- Register dram_scrub_de_curr

  -- Register dram_scrub_de_last

  -- Register cpu_data_err

  -- Register cpu_iaddr_err

  -- Register dram_ecc_mask
  dram_ecc_mask_o <= dram_ecc_mask_reg;
  process (clk_i) begin
    if rising_edge(clk_i) then
      if rst_n_i = '0' then
        dram_ecc_mask_reg <= "00000000";
        dram_ecc_mask_wack <= '0';
      else
        if dram_ecc_mask_wreq = '1' then
          dram_ecc_mask_reg <= wr_dat_d0(7 downto 0);
        end if;
        dram_ecc_mask_wack <= dram_ecc_mask_wreq;
      end if;
    end if;
  end process;

  -- Register iram_ecc_addr

  -- Register iram_err_addr
  iram_err_addr_en_o <= wr_dat_d0(0);
  iram_err_addr_addr_o <= wr_dat_d0(15 downto 2);
  iram_err_addr_wr_o <= iram_err_addr_wreq;

  -- Register scrub_cfg
  scrub_cfg_iram_en_o <= wr_dat_d0(0);
  scrub_cfg_dram_en_o <= wr_dat_d0(1);
  scrub_cfg_wr_o <= scrub_cfg_wreq;

  -- Register iram_scrub_period
  iram_scrub_period_o <= iram_scrub_period_reg;
  process (clk_i) begin
    if rising_edge(clk_i) then
      if rst_n_i = '0' then
        iram_scrub_period_reg <= "0000011111111111";
        iram_scrub_period_wack <= '0';
      else
        if iram_scrub_period_wreq = '1' then
          iram_scrub_period_reg <= wr_dat_d0(15 downto 0);
        end if;
        iram_scrub_period_wack <= iram_scrub_period_wreq;
      end if;
    end if;
  end process;

  -- Register dram_scrub_period
  dram_scrub_period_o <= dram_scrub_period_reg;
  process (clk_i) begin
    if rising_edge(clk_i) then
      if rst_n_i = '0' then
        dram_scrub_period_reg <= "0000011111111111";
        dram_scrub_period_wack <= '0';
      else
        if dram_scrub_period_wreq = '1' then
          dram_scrub_period_reg <= wr_dat_d0(15 downto 0);
        end if;
        dram_scrub_period_wack <= dram_scrub_period_wreq;
      end if;
    end if;
  end process;

  -- Register cpu_fault_count
  cpu_fault_count_o <= wr_dat_d0;
  cpu_fault_count_wr_o <= cpu_fault_count_wreq;

  -- Process for write requests.
  process (wr_adr_d0, wr_req_d0, wd_key_wack, dram_ecc_mask_wack,
           iram_scrub_period_wack, dram_scrub_period_wack) begin
    cpu_wreq <= '0';
    wd_period_wreq <= '0';
    wd_key_wreq <= '0';
    dram_ecc_mask_wreq <= '0';
    iram_err_addr_wreq <= '0';
    scrub_cfg_wreq <= '0';
    iram_scrub_period_wreq <= '0';
    dram_scrub_period_wreq <= '0';
    cpu_fault_count_wreq <= '0';
    case wr_adr_d0(6 downto 2) is
    when "00000" =>
      -- Reg reset_cause
      wr_ack_int <= wr_req_d0;
    when "00001" =>
      -- Reg cpu
      cpu_wreq <= wr_req_d0;
      wr_ack_int <= wr_req_d0;
    when "00010" =>
      -- Reg force_divergence
      wr_ack_int <= wr_req_d0;
    when "00011" =>
      -- Reg wd_period
      wd_period_wreq <= wr_req_d0;
      wr_ack_int <= wr_req_d0;
    when "00100" =>
      -- Reg wd_count
      wr_ack_int <= wr_req_d0;
    when "00101" =>
      -- Reg wd_key
      wd_key_wreq <= wr_req_d0;
      wr_ack_int <= wd_key_wack;
    when "00110" =>
      -- Reg iram_ecc_se
      wr_ack_int <= wr_req_d0;
    when "00111" =>
      -- Reg iram_scrub_cycle
      wr_ack_int <= wr_req_d0;
    when "01000" =>
      -- Reg iram_scrub_se
      wr_ack_int <= wr_req_d0;
    when "01001" =>
      -- Reg iram_scrub_de_curr
      wr_ack_int <= wr_req_d0;
    when "01010" =>
      -- Reg iram_scrub_de_last
      wr_ack_int <= wr_req_d0;
    when "01011" =>
      -- Reg dram_ecc_se
      wr_ack_int <= wr_req_d0;
    when "01100" =>
      -- Reg dram_scrub_cycle
      wr_ack_int <= wr_req_d0;
    when "01101" =>
      -- Reg dram_scrub_se
      wr_ack_int <= wr_req_d0;
    when "01110" =>
      -- Reg dram_scrub_de_curr
      wr_ack_int <= wr_req_d0;
    when "01111" =>
      -- Reg dram_scrub_de_last
      wr_ack_int <= wr_req_d0;
    when "10000" =>
      -- Reg cpu_data_err
      wr_ack_int <= wr_req_d0;
    when "10001" =>
      -- Reg cpu_iaddr_err
      wr_ack_int <= wr_req_d0;
    when "10010" =>
      -- Reg dram_ecc_mask
      dram_ecc_mask_wreq <= wr_req_d0;
      wr_ack_int <= dram_ecc_mask_wack;
    when "10011" =>
      -- Reg iram_ecc_addr
      wr_ack_int <= wr_req_d0;
    when "10100" =>
      -- Reg iram_err_addr
      iram_err_addr_wreq <= wr_req_d0;
      wr_ack_int <= wr_req_d0;
    when "10101" =>
      -- Reg scrub_cfg
      scrub_cfg_wreq <= wr_req_d0;
      wr_ack_int <= wr_req_d0;
    when "10110" =>
      -- Reg iram_scrub_period
      iram_scrub_period_wreq <= wr_req_d0;
      wr_ack_int <= iram_scrub_period_wack;
    when "10111" =>
      -- Reg dram_scrub_period
      dram_scrub_period_wreq <= wr_req_d0;
      wr_ack_int <= dram_scrub_period_wack;
    when "11000" =>
      -- Reg cpu_fault_count
      cpu_fault_count_wreq <= wr_req_d0;
      wr_ack_int <= wr_req_d0;
    when others =>
      wr_ack_int <= wr_req_d0;
    end case;
  end process;

  -- Process for read requests.
  process (adr_int, rd_req_int, reset_cause_cpu_i, reset_cause_iram_ecc_i,
           reset_cause_dram_ecc_i, reset_cause_watchdog_i,
           reset_cause_recovery_i, cpu_reset_i, cpu_recovery_i,
           force_divergence_i, wd_period_i, wd_count_i, iram_ecc_se_i,
           iram_scrub_cycle_i, iram_scrub_se_i, iram_scrub_de_curr_i,
           iram_scrub_de_last_i, dram_ecc_se_i, dram_scrub_cycle_i,
           dram_scrub_se_i, dram_scrub_de_curr_i, dram_scrub_de_last_i,
           cpu_data_err_i, cpu_iaddr_err_i, dram_ecc_mask_reg, iram_ecc_addr_i,
           iram_err_addr_en_i, iram_err_addr_addr_i, scrub_cfg_iram_en_i,
           scrub_cfg_dram_en_i, iram_scrub_period_reg, dram_scrub_period_reg,
           cpu_fault_count_i) begin
    -- By default ack read requests
    rd_dat_d0 <= (others => 'X');
    force_divergence_rd_o <= '0';
    case adr_int(6 downto 2) is
    when "00000" =>
      -- Reg reset_cause
      rd_ack_d0 <= rd_req_int;
      rd_dat_d0(0) <= reset_cause_cpu_i;
      rd_dat_d0(1) <= reset_cause_iram_ecc_i;
      rd_dat_d0(2) <= reset_cause_dram_ecc_i;
      rd_dat_d0(3) <= reset_cause_watchdog_i;
      rd_dat_d0(4) <= reset_cause_recovery_i;
      rd_dat_d0(31 downto 5) <= (others => '0');
    when "00001" =>
      -- Reg cpu
      rd_ack_d0 <= rd_req_int;
      rd_dat_d0(2 downto 0) <= cpu_reset_i;
      rd_dat_d0(7 downto 3) <= (others => '0');
      rd_dat_d0(8) <= cpu_recovery_i;
      rd_dat_d0(31 downto 9) <= (others => '0');
    when "00010" =>
      -- Reg force_divergence
      force_divergence_rd_o <= rd_req_int;
      rd_ack_d0 <= rd_req_int;
      rd_dat_d0 <= force_divergence_i;
    when "00011" =>
      -- Reg wd_period
      rd_ack_d0 <= rd_req_int;
      rd_dat_d0 <= wd_period_i;
    when "00100" =>
      -- Reg wd_count
      rd_ack_d0 <= rd_req_int;
      rd_dat_d0 <= wd_count_i;
    when "00101" =>
      -- Reg wd_key
      rd_ack_d0 <= rd_req_int;
    when "00110" =>
      -- Reg iram_ecc_se
      rd_ack_d0 <= rd_req_int;
      rd_dat_d0 <= iram_ecc_se_i;
    when "00111" =>
      -- Reg iram_scrub_cycle
      rd_ack_d0 <= rd_req_int;
      rd_dat_d0(15 downto 0) <= iram_scrub_cycle_i;
      rd_dat_d0(31 downto 16) <= (others => '0');
    when "01000" =>
      -- Reg iram_scrub_se
      rd_ack_d0 <= rd_req_int;
      rd_dat_d0 <= iram_scrub_se_i;
    when "01001" =>
      -- Reg iram_scrub_de_curr
      rd_ack_d0 <= rd_req_int;
      rd_dat_d0(15 downto 0) <= iram_scrub_de_curr_i;
      rd_dat_d0(31 downto 16) <= (others => '0');
    when "01010" =>
      -- Reg iram_scrub_de_last
      rd_ack_d0 <= rd_req_int;
      rd_dat_d0(15 downto 0) <= iram_scrub_de_last_i;
      rd_dat_d0(31 downto 16) <= (others => '0');
    when "01011" =>
      -- Reg dram_ecc_se
      rd_ack_d0 <= rd_req_int;
      rd_dat_d0 <= dram_ecc_se_i;
    when "01100" =>
      -- Reg dram_scrub_cycle
      rd_ack_d0 <= rd_req_int;
      rd_dat_d0(15 downto 0) <= dram_scrub_cycle_i;
      rd_dat_d0(31 downto 16) <= (others => '0');
    when "01101" =>
      -- Reg dram_scrub_se
      rd_ack_d0 <= rd_req_int;
      rd_dat_d0 <= dram_scrub_se_i;
    when "01110" =>
      -- Reg dram_scrub_de_curr
      rd_ack_d0 <= rd_req_int;
      rd_dat_d0(15 downto 0) <= dram_scrub_de_curr_i;
      rd_dat_d0(31 downto 16) <= (others => '0');
    when "01111" =>
      -- Reg dram_scrub_de_last
      rd_ack_d0 <= rd_req_int;
      rd_dat_d0(15 downto 0) <= dram_scrub_de_last_i;
      rd_dat_d0(31 downto 16) <= (others => '0');
    when "10000" =>
      -- Reg cpu_data_err
      rd_ack_d0 <= rd_req_int;
      rd_dat_d0 <= cpu_data_err_i;
    when "10001" =>
      -- Reg cpu_iaddr_err
      rd_ack_d0 <= rd_req_int;
      rd_dat_d0 <= cpu_iaddr_err_i;
    when "10010" =>
      -- Reg dram_ecc_mask
      rd_ack_d0 <= rd_req_int;
      rd_dat_d0(7 downto 0) <= dram_ecc_mask_reg;
      rd_dat_d0(31 downto 8) <= (others => '0');
    when "10011" =>
      -- Reg iram_ecc_addr
      rd_ack_d0 <= rd_req_int;
      rd_dat_d0 <= iram_ecc_addr_i;
    when "10100" =>
      -- Reg iram_err_addr
      rd_ack_d0 <= rd_req_int;
      rd_dat_d0(0) <= iram_err_addr_en_i;
      rd_dat_d0(1) <= '0';
      rd_dat_d0(15 downto 2) <= iram_err_addr_addr_i;
      rd_dat_d0(31 downto 16) <= (others => '0');
    when "10101" =>
      -- Reg scrub_cfg
      rd_ack_d0 <= rd_req_int;
      rd_dat_d0(0) <= scrub_cfg_iram_en_i;
      rd_dat_d0(1) <= scrub_cfg_dram_en_i;
      rd_dat_d0(31 downto 2) <= (others => '0');
    when "10110" =>
      -- Reg iram_scrub_period
      rd_ack_d0 <= rd_req_int;
      rd_dat_d0(15 downto 0) <= iram_scrub_period_reg;
      rd_dat_d0(31 downto 16) <= (others => '0');
    when "10111" =>
      -- Reg dram_scrub_period
      rd_ack_d0 <= rd_req_int;
      rd_dat_d0(15 downto 0) <= dram_scrub_period_reg;
      rd_dat_d0(31 downto 16) <= (others => '0');
    when "11000" =>
      -- Reg cpu_fault_count
      rd_ack_d0 <= rd_req_int;
      rd_dat_d0 <= cpu_fault_count_i;
    when others =>
      rd_ack_d0 <= rd_req_int;
    end case;
  end process;
end syn;
