-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
--
-- Copyright 2025 VLSI Solution Oy
-- SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
--
-- Licensed under the Solderpad Hardware License v 2.1 (the "License");
-- you may not use this file except in compliance with the License, or,
-- at your option, the Apache License version 2.0.
-- You may obtain a copy of the License at
--
--    https://solderpad.org/licenses/SHL-2.1/
--
-- Unless required by applicable law or agreed to in writing, any work
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
--                               RISCV core
--                                 V1.1
--
--
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

-- - - - - - - -
--  libraries
-- - - - - - - -
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.rv_pkg.all;

entity rv_cpu is
  generic ( BOOT_ADDR       : slv_31_00 := X"80000000";
            CPU_ID          : slv_31_00 := X"00000000";
            CACHE_ADDR_L    : slv_31_00 := X"80000000";
            CACHE_ADDR_H    : slv_31_00 := X"8FFFFFFF";
            --
            RISCV_M         : sl_t := '1'; -- RV mul / div extension
            RISCV_A         : sl_t := '1'; -- amo extension
            RISCV_E         : sl_t := '0'; -- RV rf embedded extension
            RISCV_S_U       : sl_t := '1'; -- supervisor/user privilege levels
            RISCV_Zba       : sl_t := '1'; -- address generation (shXadd)
            RISCV_ZB        : sl_t := '1'; -- ZB-extension + Zicond
--          RISCV_I         : sl_t := '1'; -- always enabled when no RISCV_E !
--          RISCV_Zicsr     : sl_t := '1'; -- always enabled !
--          RISCV_Zifencei  : sl_t := '1'; -- always enabled !
            --
            SUPPORT_MMU         : sl_t := '1';
            BYPASS_LOAD         : sl_t := '1'; -- support data load bypass
            BYPASS_MULT         : sl_t := '1'; -- support multiplier bypass
            EXTRA_DECODE_STAGE  : sl_t := '1'
            );
  port ( clk_i             : in  std_logic;
         xrst_i            : in  std_logic;    -- syncr reset
         --  interrupt request from irq ctrl
         irq_i             : in  std_logic;    -- external inter
         tmrirq_i          : in  std_logic;    -- riscv timer inter
         --
         imem_accept_i     : in  std_logic;
         imem_valid_i      : in  std_logic;
         imem_error_i      : in  std_logic;
         imem_rdata_i      : in  slv_31_00;
         imem_rd_o         : out std_logic;
         imem_pc_o         : out slv_31_00;
         imem_flush_o      : out std_logic;
         imem_invalidate_o : out std_logic;
         --  dcache/peripheral inputs
         dmem_cacheable_o  : out std_logic;
         dmem_resp_tag_i   : in  slv_10_00;
         dmem_req_tag_o    : out slv_10_00;
         --
         dmem_accept_i     : in  std_logic;
         dmem_ack_i        : in  std_logic;
         dmem_rdata_i      : in  slv_31_00;
         dmem_error_i      : in  std_logic;
         --  dcache/peripheral outputs
         dmem_rd_o         : out std_logic;
         dmem_wr_o         : out slv_03_00;
         dmem_addr_o       : out slv_31_00;
         dmem_wdata_o      : out slv_31_00;
         dmem_flush_o      : out std_logic;
         dmem_invalidate_o : out std_logic;
         dmem_wb_o         : out std_logic
         );
end entity rv_cpu;


architecture rtl of rv_cpu is

  component rv_fetch
    port ( clk_i                : in  std_logic;
           xrst_i               : in  std_logic;
           --
           imem_rdata_i         : in  slv_31_00;
           imem_accept_i        : in  std_logic;
           imem_valid_i         : in  std_logic;
           imem_error_i         : in  std_logic;
           imem_page_fault_i    : in  std_logic;
           imem_rd_o            : out std_logic;
           imem_flush_o         : out std_logic;
           imem_invalidate_o    : out std_logic;
           imem_pc_o            : out slv_31_00;
           imem_priv_o          : out slv_01_00;
           --
           fetch_accept_i       : in  std_logic;
           branch_request_i     : in  std_logic;
           branch_pc_i          : in  slv_31_00;
           branch_priv_i        : in  slv_01_00;
           fetch_invalidate_i   : in  std_logic;
           --
           fetch_valid_o        : out std_logic;
           fetch_instr_o        : out slv_31_00;
           fetch_pc_o           : out slv_31_00;
           fetch_fault_fetch_o  : out std_logic;
           fetch_fault_page_o   : out std_logic );
  end component;

  component rv_decode
    generic ( RISCV_M             : sl_t := '1'; -- mul / div extension
              RISCV_A             : sl_t := '0'; -- amo extension
              RISCV_Zba           : sl_t := '0'; -- address generation (shXadd)
              RISCV_ZB            : sl_t := '0'; -- ZB extension
              EXTRA_DECODE_STAGE  : sl_t := '0' );
    port ( clk_i                   : in  std_logic;
           xrst_i                  : in  std_logic;    -- syncr reset
           --
           fetch_in_valid_i        : in  std_logic;
           iword_i                 : in  slv_31_00;
           fetch_in_pc_i           : in  slv_31_00;
           fetch_in_fault_fetch_i  : in  std_logic;
           fetch_in_fault_page_i   : in  std_logic;
           fetch_out_accept_i      : in  std_logic;
           squash_decode_i         : in  std_logic;
           --
           fetch_out_valid_o       : out std_logic;
           iword_buf_o             : out slv_31_00;
           imem_pc_o               : out slv_31_00;
           fetch_out_fault_fetch_o : out std_logic;
           fetch_out_fault_page_o  : out std_logic;
           --
           alu_op_o                : out alu_op_t;
           lsu_op_p1_o             : out lsu_op_t;
           mul_op_p1_o             : out mul_op_t;
           div_op_p1_o             : out div_op_t;
           csr_op_o                : out csr_op_t;
           branch_op_o             : out branch_op_t;
           amo_op_o                : out amo_op_t;
           --
           pline_stall_i           : in  std_logic;
           pline_step_i            : in  std_logic;
           idec_group_o            : out i_group_t );
  end component;

  component rv_exec
    generic ( RISCV_M    : sl_t := '0';        -- RV mul / div extension
              RISCV_Zba  : sl_t := '0';        -- address generation (shXadd)
              RISCV_ZB   : sl_t := '0' );      -- ZB-extension + Zicond
    port ( clk_i           : in  std_logic;
           xrst_i          : in  std_logic;
           --
           pline_stall_i   : in  std_logic;
           rs1_dat_i       : in  slv_31_00;
           rs2_dat_i       : in  slv_31_00;
           -- alu
           alu_op_i        : in  alu_op_t;
           iword_p2_i      : in  slv_31_00;
           pc_e1_i         : in  slv_31_00;
           alu_wb_o        : out slv_31_00;
           -- multiplier
           mul_op_p1_i     : in  mul_op_t;
           mul_vld_i       : in  std_logic;
           mul_wb_o        : out slv_31_00;
           --  divider
           div_op_p1_i     : in  div_op_t;
           div_vld_i       : in  std_logic;
           div_wb_vld_o    : out std_logic;
           div_wb_o        : out slv_31_00;
           -- branch
           iword_p1_i      : in  slv_31_00;
           opc_vld_i       : in  std_logic;
           opc_pc_i        : in  slv_31_00;
           branch_op_i     : in  branch_op_t;
           branch_req_o    : out std_logic;
           branch_pc_o     : out slv_31_00 );
  end component;

  component rv_mmu
    generic ( CACHE_ADDR_L  : slv_31_00 := X"80000000";
              CACHE_ADDR_H  : slv_31_00 := X"8FFFFFFF";
              SUPPORT_MMU   : sl_t      := '1' );
    port ( clk_i                  : in  std_logic;
           xrst_i                 : in  std_logic; -- syncr reset
           --
           priv_d_i               : in  slv_01_00;
           sum_i                  : in  std_logic;
           mxr_i                  : in  std_logic;
           flush_i                : in  std_logic;
           satp_i                 : in  slv_31_00;
           ifence_p1_i            : in  std_logic; -- ifence instr
           imem_pc_o              : out slv_31_00;
           lr_cancel_i            : in  std_logic;
           amofunc_i              : in  slv_03_00;
           amo_pending_o          : out std_logic;
           --
           fetch_in_priv_i        : in  slv_01_00;
           fetch_in_rd_i          : in  std_logic;
           fetch_in_pc_i          : in  slv_31_00;
           fetch_in_flush_i       : in  std_logic;
           fetch_in_invalidate_i  : in  std_logic;
           fetch_in_accept_o      : out std_logic;
           fetch_in_valid_o       : out std_logic;
           fetch_in_error_o       : out std_logic;
           fetch_in_fault_o       : out std_logic;
           fetch_out_accept_i     : in  std_logic;
           fetch_out_valid_i      : in  std_logic;
           fetch_out_error_i      : in  std_logic;
           fetch_out_rd_o         : out std_logic;
           fetch_out_flush_o      : out std_logic;
           fetch_out_invalidate_o : out std_logic;
           --
           lsu_atomic_i           : in  std_logic;  -- atomic op
           lsu_in_rd_i            : in  std_logic;
           lsu_in_wr_i            : in  slv_03_00;
           lsu_in_addr_i          : in  slv_31_00;
           lsu_in_wdata_i         : in  slv_31_00;
           lsu_in_cacheable_i     : in  std_logic;
           lsu_in_invalidate_i    : in  std_logic;
           lsu_in_flush_i         : in  std_logic;
           lsu_in_wb_i            : in  std_logic;
           lsu_in_req_tag_i       : in  slv_10_00;
           lsu_in_accept_o        : out std_logic;
           lsu_in_ack_o           : out std_logic;
           lsu_in_error_o         : out std_logic;
           lsu_in_load_fault_o    : out std_logic;
           lsu_in_store_fault_o   : out std_logic;
           --
           dmem_cacheable_o       : out std_logic;
           dmem_resp_tag_i        : in  slv_10_00;
           dmem_req_tag_o         : out slv_10_00;
           --
           dmem_accept_i          : in  std_logic;
           dmem_ack_i             : in  std_logic;
           dmem_rdata_i           : in  slv_31_00;
           dmem_error_i           : in  std_logic;
           dmem_rd_o              : out std_logic;
           dmem_wr_o              : out slv_03_00;
           dmem_addr_o            : out slv_31_00;
           dmem_wdata_o           : out slv_31_00;
           dmem_flush_o           : out std_logic;
           dmem_invalidate_o      : out std_logic;
           dmem_wb_o              : out std_logic;
           --
           dmem_accept_o          : out std_logic;
           dmem_rdata_o           : out slv_31_00;
           --
           dmem_accept_d1_o       : out std_logic );
  end component;

  component rv_lsu
    generic ( CACHE_ADDR_L  : slv_31_00 := X"80000000";
              CACHE_ADDR_H  : slv_31_00 := X"8FFFFFFF" );
    port ( clk_i              : in  std_logic;
           xrst_i             : in  std_logic;
           --
           instr_valid_i      : in  std_logic;
           instr_i            : in  slv_31_00;
           lsu_op_p1_i        : in  lsu_op_t;
           amofunc_i          : in  slv_03_00;
           dmem_ldtype_o      : out dmem_ldtyp_t;
           stall_o            : out std_logic;
           --
           oprs1_dat_i        : in  slv_31_00;
           oprs2_dat_i        : in  slv_31_00;
           -- added for module load fix
           ifence_p1_i        : in  std_logic;  -- ifence instruction
           mem_d_accept_d1_i  : in  std_logic;
           mem_d_accept_i     : in  std_logic;
           mem_accept_i       : in  std_logic;
           mem_ack_i          : in  std_logic;
           mem_error_i        : in  std_logic;
           --
           dmem_atomic_o      : out std_logic;  -- lr / sc
           dmem_amofunc_o     : out slv_03_00;
           dmem_rd_o          : out std_logic;
           dmem_wr_o          : out slv_03_00;
           dmem_addr_o        : out slv_31_00;
           dmem_wdata_o       : out slv_31_00;
           mem_cacheable_o    : out std_logic;
           mem_req_tag_o      : out slv_10_00;
           mem_invalidate_o   : out std_logic;
           mem_flush_o        : out std_logic;
           mem_wb_o           : out std_logic );
  end component;

  component rv_csr
    generic ( RISCV_M    : sl_t := '1';  -- RV mul / div extension
              RISCV_A    : sl_t := '1';  -- lrsc / amo extension
              RISCV_E    : sl_t := '0';  -- RV rf embedded extension
              RISCV_S_U  : sl_t := '1';
              RISCV_ZB   : sl_t := '0';  -- ZB-extension + Zicond
              BOOT_ADDR  : slv_31_00;
              CPU_ID     : slv_31_00 );
    port ( clk_i                      : in  std_logic;
           xrst_i                     : in  std_logic;
           --
           extirq_i                   : in  std_logic;  -- external intrrupt
           tmrirq_i                   : in  std_logic;  -- riscv timer intrrupt
           irq_block_i                : in  std_logic;
           take_irq_o                 : out std_logic;
           ifence_p1_o                : out std_logic;
           ifence_p2_o                : out std_logic;
           --
           branch_req_o               : out std_logic;
           branch_pc_o                : out slv_31_00;
           branch_priv_o              : out slv_01_00;
           --
           mmu_priv_d_o               : out slv_01_00;
           mmu_sum_o                  : out std_logic;
           mmu_mxr_o                  : out std_logic;
           mmu_flush_o                : out std_logic;
           mmu_satp_o                 : out slv_31_00;
           --
           csr_op_i                   : in  csr_op_t;
           opcode_valid_i             : in  std_logic;
           iword_p1_i                 : in  slv_31_00;
           opcode_invalid_i           : in  std_logic;
           oprs1_idx_i                : in  slv_04_00;
           oprs1_dat_i                : in  slv_31_00;
           csr_wb_write_i             : in  std_logic;
           csr_wb_waddr_i             : in  slv_11_00;
           csr_wb_wdata_i             : in  slv_31_00;
           csr_wb_exception_i         : in  slv_05_00;
           csr_wb_exception_pc_i      : in  slv_31_00;
           csr_wb_exception_addr_i    : in  slv_31_00;
           --
           csr_result_e1_value_o      : out slv_31_00;
           csr_wr_e1_o                : out std_logic;
           csr_wdata_e1_o             : out slv_31_00;
           csr_result_e1_exception_o  : out slv_05_00 );
  end component;

  component rv_issue
    generic ( RISCV_M      : sl_t := '1';  -- RV mul / div extension
              RISCV_E      : sl_t := '0';  -- RV rf embedded extension
              BYPASS_LOAD  : sl_t := '1';
              BYPASS_MULT  : sl_t := '1' );
    port ( clk_i                      : in  std_logic;
           xrst_i                     : in  std_logic;
           --
           fetch_valid_i              : in  std_logic;
           fetch_instr_i              : in  slv_31_00;
           fetch_pc_i                 : in  slv_31_00;
           fetch_fault_fetch_i        : in  std_logic;
           fetch_fault_page_i         : in  std_logic;
           --
           idec_group_i               : in  i_group_t;
           iss_stall_o                : out std_logic;
           iss_step_o                 : out std_logic;
            --
           branch_exe_req_i           : in  std_logic;
           branch_exe_pc_i            : in  slv_31_00;
           branch_csr_req_i           : in  std_logic;
           branch_csr_pc_i            : in  slv_31_00;
           branch_csr_priv_i          : in  slv_01_00;
           --
           mem_ack_i                  : in  std_logic;
           mem_error_i                : in  std_logic;
           mem_ld_fault_i             : in  std_logic;
           mem_st_fault_i             : in  std_logic;
           dmem_rdata_i               : in  slv_31_00;
           dmem_ldtype_i              : in dmem_ldtyp_t;
           --
           csr_result_value_e1_i      : in  slv_31_00;
           csr_wr_e1_i                : in  std_logic;
           csr_wdata_e1_i             : in  slv_31_00;
           csr_result_exception_e1_i  : in  slv_05_00;
           lsu_stall_i                : in  std_logic;
           take_irq_i                 : in  std_logic;
           --
           rs1_dat_o                  : out slv_31_00;
           rs2_dat_o                  : out slv_31_00;
           rs1_idx_o                  : out slv_04_00;
           --
           exec_opc_vld_o             : out std_logic;
           --
           --  multiplier / divider / ALU
           muldiv_opc_vld_o           : out std_logic;
           div_wb_vld_i               : in  std_logic;
           mul_wb_i                   : in  slv_31_00;
           div_wb_i                   : in  slv_31_00;
           alu_wb_i                   : in  slv_31_00;
           --
           --
           amo_op_i                   : in  amo_op_t;
           amofunc_p2_i               : in  slv_03_00;
           amo_pending_i              : in  std_logic;
           --
           iword_p2_o                 : out slv_31_00;
           pc_e1_o                    : out slv_31_00;
           fetch_accept_o             : out std_logic;
           branch_request_o           : out std_logic;
           branch_pc_o                : out slv_31_00;
           branch_priv_o              : out slv_01_00;
           lsu_opcode_valid_o         : out std_logic;
           csr_opcode_valid_o         : out std_logic;
           --
           csr_opcode_invalid_o       : out std_logic;
           csr_wb_write_o             : out std_logic;
           csr_wb_waddr_o             : out slv_11_00;
           csr_wb_wdata_o             : out slv_31_00;
           csr_wb_exception_o         : out slv_05_00;
           csr_wb_exception_pc_o      : out slv_31_00;
           csr_wb_exception_addr_o    : out slv_31_00;
           irq_block_o                : out std_logic );
  end component;

  signal dmem_accept_d1_w         : std_logic;
  signal dmem_accept_w            : std_logic;
  signal dmem_rdata_w             : slv_31_00;

  signal fetch_accept_w           : std_logic;
  signal div_wb_w                 : slv_31_00;
  signal csr_opcode_valid_w       : std_logic;
  signal pc_e1_w                  : slv_31_00;
  signal csr_opcode_invalid_w     : std_logic;
  signal branch_request_w         : std_logic;
  signal fetch_dec_fault_page_w   : std_logic;
  signal branch_pc_w              : slv_31_00;
  signal lsu_stall_w              : std_logic;
  signal fetch_dec_fault_fetch_w  : std_logic;
  signal fetch_dec_valid_w        : std_logic;
  signal fetch_fault_fetch_w      : std_logic;
  signal fetch_fault_page_w       : std_logic;

  signal muldiv_valid_w           : std_logic;

  signal fetch_pc_w               : slv_31_00;

  signal branch_exe_req_w         : std_logic;
  signal branch_exe_pc_w          : slv_31_00;

  signal branch_priv_w            : slv_01_00;
  signal fetch_dec_pc_w           : slv_31_00;
  signal irq_block_w              : std_logic;
  signal rs1_idx_w                : slv_04_00;

  signal idec_group_w             : i_group_t;

  signal dmem_ldtype_w            : dmem_ldtyp_t;

  signal div_wb_valid_w           : std_logic;

  signal mmu_ifetch_accept_w      : std_logic;
  signal mmu_ifetch_valid_w       : std_logic;
  signal mmu_ifetch_error_w       : std_logic;
  signal mmu_ifetch_fault_w       : std_logic;
  signal mmu_ifetch_rd_w          : std_logic;
  signal mmu_ifetch_flush_w       : std_logic;
  signal mmu_ifetch_invalidate_w  : std_logic;
  signal mmu_ifetch_pc_w          : slv_31_00;
  signal mmu_ifetch_priv_w        : slv_01_00;

  signal mmu_load_fault_w         : std_logic;
  signal rs1_dat_w                : slv_31_00;
  signal rs2_dat_w                : slv_31_00;

  signal ifence_p1_w              : std_logic;
  signal ifence_p2_w              : std_logic;
  signal take_irq_w               : std_logic;
  signal fetch_valid_w            : std_logic;
  signal lsu_opcode_valid_w       : std_logic;
  signal instr_fetch_w            : slv_31_00;

  signal alu_op_p2_w              : alu_op_t;
  signal lsu_op_p1_w              : lsu_op_t;
  signal mul_op_p1_w              : mul_op_t;
  signal div_op_p1_w              : div_op_t;
  signal csr_op_p1_w              : csr_op_t;
  signal branch_op_w              : branch_op_t;
  signal amo_op_w                 : amo_op_t;

  signal iword_p1_w               : slv_31_00;
  signal exec_opc_vld_w           : std_logic;
  signal mul_wb_w                 : slv_31_00;

  signal mmu_lsu_atomic_w         : std_logic;
  signal mmu_lsu_rd_w             : std_logic;
  signal mmu_lsu_wr_w             : slv_03_00;
  signal mmu_lsu_addr_w           : slv_31_00;
  signal mmu_lsu_wdata_w          : slv_31_00;
  signal mmu_lsu_invalidate_w     : std_logic;
  signal mmu_lsu_cacheable_w      : std_logic;
  signal mmu_lsu_flush_w          : std_logic;
  signal mmu_lsu_accept_w         : std_logic;
  signal mmu_lsu_wb_w             : std_logic;
  signal mmu_lsu_error_w          : std_logic;
  signal mmu_lsu_req_tag_w        : slv_10_00;
  signal mmu_lsu_ack_w            : std_logic;

  signal mmu_priv_d_w             : slv_01_00;
  signal mmu_sum_w                : std_logic;
  signal mmu_mxr_w                : std_logic;
  signal mmu_flush_w              : std_logic;
  signal mmu_satp_w               : slv_31_00;

  signal csr_wb_write_w           : std_logic;
  signal csr_wb_waddr_w           : slv_11_00;
  signal csr_wb_wdata_w           : slv_31_00;

  signal csr_wr_e1_w              : std_logic;
  signal csr_wdata_e1_w           : slv_31_00;
  signal csr_value_e1_w           : slv_31_00;
  signal csr_excp_e1_w            : slv_05_00;

  signal csr_wb_exception_w       : slv_05_00;
  signal csr_wb_exception_pc_w    : slv_31_00;
  signal csr_wb_exception_addr_w  : slv_31_00;

  signal branch_csr_req_w         : std_logic;
  signal branch_csr_pc_w          : slv_31_00;
  signal branch_csr_priv_w        : slv_01_00;

  signal alu_wb_value_w           : slv_31_00;
  signal mmu_store_fault_w        : std_logic;

  signal iword_p2_w               : slv_31_00;

  signal pline_stall_w            : std_logic;
  signal pline_step_w             : std_logic;

  signal lr_cancel_w              : std_logic;
  signal amofunc_w                : slv_03_00;
  signal amo_pending_w            : std_logic;

begin

  u_fetch : rv_fetch
    port map ( clk_i               => clk_i,
               xrst_i              => xrst_i,
               --
               imem_rdata_i        => imem_rdata_i,
               --
               imem_accept_i       => mmu_ifetch_accept_w,
               imem_valid_i        => mmu_ifetch_valid_w,
               imem_error_i        => mmu_ifetch_error_w,
               imem_page_fault_i   => mmu_ifetch_fault_w,
               imem_rd_o           => mmu_ifetch_rd_w,
               imem_flush_o        => mmu_ifetch_flush_w,
               imem_invalidate_o   => mmu_ifetch_invalidate_w,
               imem_pc_o           => mmu_ifetch_pc_w,
               imem_priv_o         => mmu_ifetch_priv_w,
               --
               fetch_accept_i      => fetch_accept_w,
               branch_request_i    => branch_request_w,
               branch_pc_i         => branch_pc_w,
               branch_priv_i       => branch_priv_w,
               --
               fetch_invalidate_i  => ifence_p2_w,
               --
               fetch_valid_o       => fetch_dec_valid_w,
               fetch_instr_o       => instr_fetch_w,
               fetch_pc_o          => fetch_dec_pc_w,
               fetch_fault_fetch_o => fetch_dec_fault_fetch_w,
               fetch_fault_page_o  => fetch_dec_fault_page_w );


  u_decode : rv_decode
    generic map ( RISCV_M            => RISCV_M,        -- multiplier / divider
                  RISCV_A            => RISCV_A,        -- amo extension
                  RISCV_Zba          => RISCV_Zba,      -- address generation
                  RISCV_ZB           => RISCV_ZB,       -- ZB extension
                  EXTRA_DECODE_STAGE => EXTRA_DECODE_STAGE )
    port map ( clk_i                   => clk_i,
               xrst_i                  => xrst_i,
               --
               iword_i                 => instr_fetch_w,
               fetch_in_valid_i        => fetch_dec_valid_w,
               fetch_in_pc_i           => fetch_dec_pc_w,
               fetch_in_fault_fetch_i  => fetch_dec_fault_fetch_w,
               fetch_in_fault_page_i   => fetch_dec_fault_page_w,
               --
               fetch_out_accept_i      => fetch_accept_w,
               squash_decode_i         => branch_request_w,
               fetch_out_valid_o       => fetch_valid_w,
               fetch_out_fault_fetch_o => fetch_fault_fetch_w,
               fetch_out_fault_page_o  => fetch_fault_page_w,
               --  fetched instr to: exec, lsu, csr, mul, div, issue
               iword_buf_o             => iword_p1_w,
               imem_pc_o               => fetch_pc_w,
               --
               alu_op_o                => alu_op_p2_w,
               lsu_op_p1_o             => lsu_op_p1_w,
               mul_op_p1_o             => mul_op_p1_w,
               div_op_p1_o             => div_op_p1_w,
               csr_op_o                => csr_op_p1_w,
               branch_op_o             => branch_op_w,
               amo_op_o                => amo_op_w,
               -- instruction group (csr, mul, div, ...)
               pline_stall_i           => pline_stall_w,
               pline_step_i            => pline_step_w,
               idec_group_o            => idec_group_w );


  u_exec : rv_exec
    generic map ( RISCV_M    => RISCV_M,            -- RV mul / div extension
                  RISCV_Zba  => RISCV_Zba,          -- addr generation (shXadd)
                  RISCV_ZB   => RISCV_ZB )          -- ZB-extension + Zicond
    port map ( clk_i         => clk_i,
               xrst_i        => xrst_i,
               --
               pline_stall_i  => pline_stall_w,
               rs1_dat_i      => rs1_dat_w,
               rs2_dat_i      => rs2_dat_w,
               --
               alu_op_i       => alu_op_p2_w,
               iword_p2_i     => iword_p2_w,
               pc_e1_i        => pc_e1_w,
               alu_wb_o       => alu_wb_value_w,
               --
               mul_op_p1_i    => mul_op_p1_w,
               mul_vld_i      => muldiv_valid_w,
               mul_wb_o       => mul_wb_w,
               --
               div_op_p1_i    => div_op_p1_w,
               div_vld_i      => muldiv_valid_w,
               div_wb_vld_o   => div_wb_valid_w,
               div_wb_o       => div_wb_w,
               -- branch
               iword_p1_i     => iword_p1_w,
               opc_vld_i      => exec_opc_vld_w,
               opc_pc_i       => fetch_pc_w,
               branch_op_i    => branch_op_w,
               branch_req_o   => branch_exe_req_w,
               branch_pc_o    => branch_exe_pc_w );


  lr_cancel_w <= take_irq_w;


  u_mmu : rv_mmu
    generic map ( CACHE_ADDR_L  => CACHE_ADDR_L,
                  CACHE_ADDR_H  => CACHE_ADDR_H,
                  SUPPORT_MMU          => SUPPORT_MMU )
    port map ( clk_i                  => clk_i,
               xrst_i                 => xrst_i,
               --
               priv_d_i               => mmu_priv_d_w,
               sum_i                  => mmu_sum_w,
               mxr_i                  => mmu_mxr_w,
               flush_i                => mmu_flush_w,
               satp_i                 => mmu_satp_w,
               --
               ifence_p1_i            => ifence_p1_w,
               lr_cancel_i            => lr_cancel_w,
               amofunc_i              => amofunc_w,
               amo_pending_o          => amo_pending_w,
               --  imem if
               fetch_in_priv_i        => mmu_ifetch_priv_w,
               fetch_in_rd_i          => mmu_ifetch_rd_w,
               fetch_in_pc_i          => mmu_ifetch_pc_w,
               fetch_in_flush_i       => mmu_ifetch_flush_w,
               fetch_in_invalidate_i  => mmu_ifetch_invalidate_w,
               fetch_in_accept_o      => mmu_ifetch_accept_w,
               fetch_in_valid_o       => mmu_ifetch_valid_w,
               fetch_in_error_o       => mmu_ifetch_error_w,
               fetch_in_fault_o       => mmu_ifetch_fault_w,
               fetch_out_accept_i     => imem_accept_i,
               fetch_out_valid_i      => imem_valid_i,
               fetch_out_error_i      => imem_error_i,
               fetch_out_rd_o         => imem_rd_o,
               imem_pc_o              => imem_pc_o,
               fetch_out_flush_o      => imem_flush_o,
               fetch_out_invalidate_o => imem_invalidate_o,
               --
               lsu_atomic_i           => mmu_lsu_atomic_w,
               lsu_in_rd_i            => mmu_lsu_rd_w,
               lsu_in_wr_i            => mmu_lsu_wr_w,
               lsu_in_addr_i          => mmu_lsu_addr_w,
               lsu_in_wdata_i         => mmu_lsu_wdata_w,
               lsu_in_cacheable_i     => mmu_lsu_cacheable_w,
               lsu_in_invalidate_i    => mmu_lsu_invalidate_w,
               lsu_in_flush_i         => mmu_lsu_flush_w,
               lsu_in_wb_i            => mmu_lsu_wb_w,
               lsu_in_req_tag_i       => mmu_lsu_req_tag_w,
               lsu_in_accept_o        => mmu_lsu_accept_w,
               lsu_in_ack_o           => mmu_lsu_ack_w,
               lsu_in_error_o         => mmu_lsu_error_w,
               lsu_in_load_fault_o    => mmu_load_fault_w,
               lsu_in_store_fault_o   => mmu_store_fault_w,
               --
               dmem_cacheable_o       => dmem_cacheable_o,
               dmem_resp_tag_i        => dmem_resp_tag_i,
               dmem_req_tag_o         => dmem_req_tag_o,
               --
               dmem_accept_i          => dmem_accept_i,
               dmem_ack_i             => dmem_ack_i,
               dmem_rdata_i           => dmem_rdata_i,
               dmem_error_i           => dmem_error_i,
               dmem_rd_o              => dmem_rd_o,
               dmem_wr_o              => dmem_wr_o,
               dmem_addr_o            => dmem_addr_o,
               dmem_wdata_o           => dmem_wdata_o,
               dmem_flush_o           => dmem_flush_o,
               dmem_invalidate_o      => dmem_invalidate_o,
               dmem_wb_o              => dmem_wb_o,
               --
               dmem_accept_o          => dmem_accept_w,
               dmem_rdata_o           => dmem_rdata_w,
               --
               dmem_accept_d1_o       => dmem_accept_d1_w );


  u_lsu : rv_lsu
    generic map ( CACHE_ADDR_L => CACHE_ADDR_L,
                  CACHE_ADDR_H => CACHE_ADDR_H )
    port map ( clk_i               => clk_i,
               xrst_i              => xrst_i,
               --
               instr_valid_i       => lsu_opcode_valid_w,
               instr_i             => iword_p1_w,
               lsu_op_p1_i         => lsu_op_p1_w,
               amofunc_i           => amo_op_w.amofunc,
               dmem_ldtype_o       => dmem_ldtype_w,
               stall_o             => lsu_stall_w,
               --
               oprs1_dat_i         => rs1_dat_w,
               oprs2_dat_i         => rs2_dat_w,
               --
               ifence_p1_i         => ifence_p1_w,
               mem_d_accept_i      => dmem_accept_w,
               --
               mem_d_accept_d1_i   => dmem_accept_d1_w,
               mem_accept_i        => mmu_lsu_accept_w,
               mem_ack_i           => mmu_lsu_ack_w,
               mem_error_i         => mmu_lsu_error_w,
               --
               dmem_atomic_o       => mmu_lsu_atomic_w,      -- lr / sc
               dmem_amofunc_o      => amofunc_w,             -- amo
               dmem_rd_o           => mmu_lsu_rd_w,
               dmem_wr_o           => mmu_lsu_wr_w,
               dmem_addr_o         => mmu_lsu_addr_w,
               dmem_wdata_o        => mmu_lsu_wdata_w,
               mem_cacheable_o     => mmu_lsu_cacheable_w,
               mem_req_tag_o       => mmu_lsu_req_tag_w,
               mem_invalidate_o    => mmu_lsu_invalidate_w,
               mem_flush_o         => mmu_lsu_flush_w,
               mem_wb_o            => mmu_lsu_wb_w );


  u_csr : rv_csr
    generic map ( RISCV_M    => RISCV_M,    -- RV mul / div extension
                  RISCV_A    => RISCV_A,    -- lrsc / amo extension
                  RISCV_E    => RISCV_E,    -- RV rf embedded extension
                  RISCV_S_U  => RISCV_S_U,  -- supervisor/user privilege levels
                  RISCV_ZB   => RISCV_ZB,   -- ZB-extension + Zicond
                  BOOT_ADDR  => BOOT_ADDR,
                  CPU_ID     => CPU_ID )
    port map (clk_i                      => clk_i,
              xrst_i                     => xrst_i,
              --
              extirq_i                   => irq_i,         -- external inter
              tmrirq_i                   => tmrirq_i,      -- riscv timer inter
              irq_block_i                => irq_block_w,
              take_irq_o                 => take_irq_w,
              ifence_p1_o                => ifence_p1_w,
              ifence_p2_o                => ifence_p2_w,
              --
              branch_req_o               => branch_csr_req_w,
              branch_pc_o                => branch_csr_pc_w,
              branch_priv_o              => branch_csr_priv_w,
              --
              mmu_priv_d_o               => mmu_priv_d_w,
              mmu_sum_o                  => mmu_sum_w,
              mmu_mxr_o                  => mmu_mxr_w,
              mmu_flush_o                => mmu_flush_w,
              mmu_satp_o                 => mmu_satp_w,
              --
              --
              csr_op_i                   => csr_op_p1_w,
              opcode_valid_i             => csr_opcode_valid_w,
              iword_p1_i                 => iword_p1_w,
              opcode_invalid_i           => csr_opcode_invalid_w,
              oprs1_idx_i                => rs1_idx_w,
              oprs1_dat_i                => rs1_dat_w,
              --
              csr_wb_write_i             => csr_wb_write_w,
              csr_wb_waddr_i             => csr_wb_waddr_w,
              csr_wb_wdata_i             => csr_wb_wdata_w,
              --
              csr_result_e1_value_o      => csr_value_e1_w,
              csr_wr_e1_o                => csr_wr_e1_w,
              csr_wdata_e1_o             => csr_wdata_e1_w,
              csr_result_e1_exception_o  => csr_excp_e1_w,
              --
              csr_wb_exception_i         => csr_wb_exception_w,
              csr_wb_exception_pc_i      => csr_wb_exception_pc_w,
              csr_wb_exception_addr_i    => csr_wb_exception_addr_w );


  u_issue : rv_issue
    generic map ( RISCV_M      => RISCV_M,   -- RV mul / div extension
                  RISCV_E      => RISCV_E,   -- RV rf embedded extension
                  BYPASS_LOAD  => BYPASS_LOAD,
                  BYPASS_MULT  => BYPASS_MULT )
    port map ( clk_i                      => clk_i,
               xrst_i                     => xrst_i,
               --
               dmem_rdata_i               => dmem_rdata_w,
               iss_stall_o                => pline_stall_w,
               iss_step_o                 => pline_step_w,
               --
               idec_group_i               => idec_group_w,
               fetch_valid_i              => fetch_valid_w,
               fetch_instr_i              => iword_p1_w,
               fetch_pc_i                 => fetch_pc_w,
               fetch_fault_fetch_i        => fetch_fault_fetch_w,
               fetch_fault_page_i         => fetch_fault_page_w,
               fetch_accept_o             => fetch_accept_w,
               --
               mem_ld_fault_i             => mmu_load_fault_w,
               mem_st_fault_i             => mmu_store_fault_w,
               mem_ack_i                  => mmu_lsu_ack_w,
               mem_error_i                => mmu_lsu_error_w,
               --
               branch_exe_req_i           => branch_exe_req_w,
               branch_exe_pc_i            => branch_exe_pc_w,
               --
               lsu_stall_i                => lsu_stall_w,
               dmem_ldtype_i              => dmem_ldtype_w,
               --
               rs1_dat_o                  => rs1_dat_w,
               rs2_dat_o                  => rs2_dat_w,
               rs1_idx_o                  => rs1_idx_w,
               --
               exec_opc_vld_o             => exec_opc_vld_w,
               --  multiplier / divider / alu
               muldiv_opc_vld_o           => muldiv_valid_w,
               div_wb_vld_i               => div_wb_valid_w,
               mul_wb_i                   => mul_wb_w,
               div_wb_i                   => div_wb_w,
               alu_wb_i                   => alu_wb_value_w,
               --
               amo_op_i                   => amo_op_w,
               amofunc_p2_i               => amofunc_w,
               amo_pending_i              => amo_pending_w,
               --
               iword_p2_o                 => iword_p2_w,
               pc_e1_o                    => pc_e1_w,
               --
               branch_request_o           => branch_request_w,
               branch_pc_o                => branch_pc_w,
               branch_priv_o              => branch_priv_w,
               lsu_opcode_valid_o         => lsu_opcode_valid_w,
               --
               csr_opcode_valid_o         => csr_opcode_valid_w,
               csr_opcode_invalid_o       => csr_opcode_invalid_w,
               --
               branch_csr_req_i           => branch_csr_req_w,
               branch_csr_pc_i            => branch_csr_pc_w,
               branch_csr_priv_i          => branch_csr_priv_w,
               --
               take_irq_i                 => take_irq_w,
               irq_block_o                => irq_block_w,
               --
               --
               csr_result_value_e1_i      => csr_value_e1_w,
               csr_wr_e1_i                => csr_wr_e1_w,
               csr_wdata_e1_i             => csr_wdata_e1_w,
               csr_result_exception_e1_i  => csr_excp_e1_w,
               --
               csr_wb_write_o             => csr_wb_write_w,
               csr_wb_waddr_o             => csr_wb_waddr_w,
               csr_wb_wdata_o             => csr_wb_wdata_w,
               --
               csr_wb_exception_o         => csr_wb_exception_w,
               csr_wb_exception_pc_o      => csr_wb_exception_pc_w,
               csr_wb_exception_addr_o    => csr_wb_exception_addr_w);

end rtl;
