-- ================================================================================ --
-- NEORV32 CPU - ALU Conditional Operations Unit (RISC-V Zicond ISA Extension)      --
-- -------------------------------------------------------------------------------- --
-- The NEORV32 RISC-V Processor - https://github.com/stnolting/neorv32              --
-- Copyright (c) NEORV32 contributors.                                              --
-- Copyright (c) 2020 - 2026 Stephan Nolting. All rights reserved.                  --
-- Licensed under the BSD-3-Clause license, see LICENSE for details.                --
-- SPDX-License-Identifier: BSD-3-Clause                                            --
-- ================================================================================ --

library ieee;
use ieee.std_logic_1164.all;

library neorv32;
use neorv32.neorv32_package.all;

entity neorv32_cpu_alu_cond is
  port (
    -- global control --
    clk_i   : in  std_ulogic; -- global clock, rising edge
    ctrl_i  : in  ctrl_bus_t; -- main control bus
    -- data input --
    rs1_i   : in  std_ulogic_vector(31 downto 0); -- rf source 1
    rs2_i   : in  std_ulogic_vector(31 downto 0); -- rf source 2
    -- result and status --
    res_o   : out std_ulogic_vector(31 downto 0); -- operation result
    valid_o : out std_ulogic                      -- data output valid
  );
end entity;

architecture neorv32_cpu_alu_cond_rtl of neorv32_cpu_alu_cond is

  signal valid_cmd, condition : std_ulogic;

begin

  -- Valid Instruction? ---------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  valid_cmd <= '1' when (ctrl_i.alu_cp_alu = '1') and
    (ctrl_i.ir_opcode(5) = '1') and (ctrl_i.ir_funct3(2) = '1') and
    (ctrl_i.ir_funct3(0) = '1') and (ctrl_i.ir_funct12(11 downto 5) = "0000111") else '0';

  -- Conditional Output ---------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  cond_out: process(clk_i)
  begin
    if rising_edge(clk_i) then
      if (valid_cmd = '1') and (condition = '1') then -- unit triggered and move-condition is true
        res_o <= rs1_i;
      else
        res_o <= (others => '0');
      end if;
    end if;
  end process;

  -- condition check: equal zero / non equal zero --
  condition <= or_reduce_f(rs2_i) xor ctrl_i.ir_funct3(1);

  -- processing done --
  valid_o <= valid_cmd;

end architecture;
