Compare commits
16 Commits
c08d5e49c6
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b3e5f395a1 | ||
|
|
12b848a74c | ||
|
|
0f3384e157 | ||
|
|
513244f16f | ||
|
|
9ed2c9a8f4 | ||
|
|
da358566a4 | ||
|
|
10b5b08537 | ||
|
|
b76ce3629e | ||
|
|
86249ca0f0 | ||
|
|
bd5792ac5d | ||
|
|
13be3b023a | ||
|
|
099605414c | ||
|
|
23e0e58f8b | ||
|
|
306061a76d | ||
|
|
8874ed2e31 | ||
|
|
66b5eb6471 |
@@ -13,7 +13,7 @@ if {$PaR_INIT eq "TRUE"} {
|
|||||||
|
|
||||||
set init_verilog ${NETLIST_PATH}/${NETLIST_TOP_NAME}; # SYN netlist file
|
set init_verilog ${NETLIST_PATH}/${NETLIST_TOP_NAME}; # SYN netlist file
|
||||||
set init_mmmc_file ${PAR_MMMC_FILE}; # Techmological file for multi-mode multi-corner PaR
|
set init_mmmc_file ${PAR_MMMC_FILE}; # Techmological file for multi-mode multi-corner PaR
|
||||||
set init_io_file ${PAR_NETLIST_TOP_PORT_FILE}; # File with location of the TOP level ports on the floorplan
|
#set init_io_file ${PAR_NETLIST_TOP_PORT_FILE}; # File with location of the TOP level ports on the floorplan
|
||||||
|
|
||||||
init_design
|
init_design
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,10 +12,10 @@
|
|||||||
|
|
||||||
|
|
||||||
### ================= USER SETTINGS =================
|
### ================= USER SETTINGS =================
|
||||||
set NETLIST_TOP_NAME "PWM_syn_netlist.v"; # RTL top module name
|
set NETLIST_TOP_NAME "scr1_core_top_syn_netlist.v"; # RTL top module name
|
||||||
set NETLIST_PATH "../results/results_syn"; # RTL path to the source files
|
set NETLIST_PATH "../results/results_syn"; # RTL path to the source files
|
||||||
|
|
||||||
set PAR_SDC_TOP_NAME "PWM_syn.sdc"; # SDC top file name
|
set PAR_SDC_TOP_NAME "scr1_core_top_syn.sdc"; # SDC top file name
|
||||||
set PAR_SDC_PATH "../results/results_syn"; # SDC path to the sources
|
set PAR_SDC_PATH "../results/results_syn"; # SDC path to the sources
|
||||||
|
|
||||||
set PAR_MMMC_FILE "../scripts/scripts_aux/XFAB180_MMMC.tcl"; # Multi-mode multi-corner file
|
set PAR_MMMC_FILE "../scripts/scripts_aux/XFAB180_MMMC.tcl"; # Multi-mode multi-corner file
|
||||||
@@ -28,7 +28,7 @@ set PAR_INIT_LEF_FILESET "/Cadence/Libs/X_FAB/XKIT/xt018/cadence/v7_0/techLEF/v7
|
|||||||
set PAR_REPORTS_FOLDER "../reports/reports_PaR"; # Reports folder
|
set PAR_REPORTS_FOLDER "../reports/reports_PaR"; # Reports folder
|
||||||
set PAR_RESULTS_FOLDER "../results/results_PaR"; # Results folder
|
set PAR_RESULTS_FOLDER "../results/results_PaR"; # Results folder
|
||||||
|
|
||||||
set FLOORPLAN_DIMENSIONS {200 200}; # FP chip area
|
set FLOORPLAN_DIMENSIONS {500 500}; # FP chip area
|
||||||
set FLOORPLAN_MARGINS {50 50 50 50}; #FP chip margins
|
set FLOORPLAN_MARGINS {50 50 50 50}; #FP chip margins
|
||||||
### ================= END of USER SETTINGS =============
|
### ================= END of USER SETTINGS =============
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,10 @@
|
|||||||
### - cd to the main folder with the scripts, src, reports etc. (BE_ASIC_DESIGN_CADENCE_SCRIPTS folder) and then cd to the ./WORK_TMP_FOLDER
|
### - cd to the main folder with the scripts, src, reports etc. (BE_ASIC_DESIGN_CADENCE_SCRIPTS folder) and then cd to the ./WORK_TMP_FOLDER
|
||||||
### - run synthesis with RTL Compiler by typing in the same terminal "RTL_Compiler ../scripts/scripts_syn/RUN_SYN.tcl"
|
### - run synthesis with RTL Compiler by typing in the same terminal "RTL_Compiler ../scripts/scripts_syn/RUN_SYN.tcl"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### ================= USER SETTINGS =================
|
### ================= USER SETTINGS =================
|
||||||
set RTL_TOP_NAME "scr1_top_ahb"; # RTL top module name
|
set RTL_TOP_NAME "scr1_core_top"; # RTL top module name
|
||||||
set RTL_PATH "../src/rtl"; # RTL path to the source files
|
set RTL_PATH "../src/rtl"; # RTL path to the source files
|
||||||
|
|
||||||
set RTL_FILELIST_NAME "filelist.v"; # RTL path to the filelist for synthesis
|
set RTL_FILELIST_NAME "filelist.v"; # RTL path to the filelist for synthesis
|
||||||
@@ -24,6 +26,12 @@ set SYN_REPORTS_FOLDER "../reports/reports_syn"; # Reports folde
|
|||||||
set SYN_RESULTS_FOLDER "../results/results_syn"; # Results folder
|
set SYN_RESULTS_FOLDER "../results/results_syn"; # Results folder
|
||||||
### ================= END of USER SETTINGS ==========
|
### ================= END of USER SETTINGS ==========
|
||||||
|
|
||||||
|
### ============== PROC to run synthesis ============
|
||||||
|
### Set TRUE to enable technological mapping and results export; otherwise only elaboration is active
|
||||||
|
#set MAPPING "FALSE";
|
||||||
|
set MAPPING "TRUE";
|
||||||
|
### ========== end of PROC to run synthesis =========
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### ================= SYNTHESIS =================
|
### ================= SYNTHESIS =================
|
||||||
@@ -33,12 +41,16 @@ include ${SYN_CORNER}
|
|||||||
# Read in Verilog HDL filelist for synthesis
|
# Read in Verilog HDL filelist for synthesis
|
||||||
read_hdl -sv ${RTL_PATH}/${RTL_FILELIST_NAME}
|
read_hdl -sv ${RTL_PATH}/${RTL_FILELIST_NAME}
|
||||||
|
|
||||||
# Synthesize (elabirate, no mapping)
|
# Synthesize (elaborate, no mapping)
|
||||||
elaborate ${RTL_TOP_NAME}
|
elaborate ${RTL_TOP_NAME}
|
||||||
|
|
||||||
|
if {$MAPPING eq "TRUE"} {
|
||||||
# Rear SDC constraints
|
# Rear SDC constraints
|
||||||
read_sdc ${SYN_SDC_PATH}/${SYN_SDC_TOP_NAME}
|
read_sdc ${SYN_SDC_PATH}/${SYN_SDC_TOP_NAME}
|
||||||
|
|
||||||
|
# For testing correctness of SDC uncomment the command below
|
||||||
|
#exit
|
||||||
|
|
||||||
# Synthesize (technology mapped)
|
# Synthesize (technology mapped)
|
||||||
synthesize -to_mapped
|
synthesize -to_mapped
|
||||||
synthesize -incremental
|
synthesize -incremental
|
||||||
@@ -53,6 +65,7 @@ write_hdl -mapped > ${SYN_RESULTS_FOLDER}/${RTL_TOP_NAME}_syn_netlist.v
|
|||||||
|
|
||||||
# Export SDC file for the next PaR stages
|
# Export SDC file for the next PaR stages
|
||||||
write_sdc > ${SYN_RESULTS_FOLDER}/${RTL_TOP_NAME}_syn.sdc
|
write_sdc > ${SYN_RESULTS_FOLDER}/${RTL_TOP_NAME}_syn.sdc
|
||||||
|
}
|
||||||
|
|
||||||
# Open RTL Compiler GUI
|
# Open RTL Compiler GUI
|
||||||
gui_show
|
gui_show
|
||||||
|
|||||||
@@ -1,63 +1,63 @@
|
|||||||
#`include "../scr1_custom_define.svh"
|
// `include "../scr1_custom_define.svh"
|
||||||
#`include "../scr1_arch_custom.svh"
|
// `include "../scr1_arch_custom.svh"
|
||||||
|
|
||||||
# core
|
// includes
|
||||||
#/home/yenuchenko/riscv_school/scr1/scr1-master/src/core
|
// /home/yenuchenko/riscv_school/scr1/scr1-master/src/includes
|
||||||
`include "../core/scr1_clk_ctrl.sv"
|
`include "scr1/scr1_ahb.svh"
|
||||||
`include "../core/scr1_core_top.sv"
|
`include "scr1/scr1_arch_description.svh"
|
||||||
`include "../core/scr1_dm.sv"
|
`include "scr1/scr1_arch_types.svh"
|
||||||
`include "../core/scr1_dmi.sv"
|
`include "scr1/scr1_csr.svh"
|
||||||
`include "../core/scr1_scu.sv"
|
`include "scr1/scr1_dm.svh"
|
||||||
`include "../core/scr1_tapc.sv"
|
`include "scr1/scr1_hdu.svh"
|
||||||
`include "../core/scr1_tapc_shift_reg.sv"
|
`include "scr1/scr1_ipic.svh"
|
||||||
`include "../core/scr1_tapc_synchronizer.sv"
|
`include "scr1/scr1_memif.svh"
|
||||||
|
`include "scr1/scr1_riscv_isa_decoding.svh"
|
||||||
|
`include "scr1/scr1_scu.svh"
|
||||||
|
`include "scr1/scr1_search_ms1.svh"
|
||||||
|
`include "scr1/scr1_tapc.svh"
|
||||||
|
`include "scr1/scr1_tdu.svh"
|
||||||
|
|
||||||
# pipeline
|
// core
|
||||||
#/home/yenuchenko/riscv_school/scr1/scr1-master/src/core/pipeline
|
// /home/yenuchenko/riscv_school/scr1/scr1-master/src/core
|
||||||
`include "../core/pipeline/scr1_ipic.sv"
|
`include "scr1/scr1_clk_ctrl.sv"
|
||||||
`include "../core/pipeline/scr1_pipe_csr.sv"
|
`include "scr1/scr1_core_top.sv"
|
||||||
`include "../core/pipeline/scr1_pipe_exu.sv"
|
`include "scr1/scr1_dm.sv"
|
||||||
`include "../core/pipeline/scr1_pipe_hdu.sv"
|
`include "scr1/scr1_dmi.sv"
|
||||||
`include "../core/pipeline/scr1_pipe_ialu.sv"
|
`include "scr1/scr1_scu.sv"
|
||||||
`include "../core/pipeline/scr1_pipe_idu.sv"
|
`include "scr1/scr1_tapc.sv"
|
||||||
`include "../core/pipeline/scr1_pipe_ifu.sv"
|
`include "scr1/scr1_tapc_shift_reg.sv"
|
||||||
`include "../core/pipeline/scr1_pipe_lsu.sv"
|
`include "scr1/scr1_tapc_synchronizer.sv"
|
||||||
`include "../core/pipeline/scr1_pipe_mprf.sv"
|
|
||||||
`include "../core/pipeline/scr1_pipe_tdu.sv"
|
|
||||||
`include "../core/pipeline/scr1_pipe_top.sv"
|
|
||||||
`include "../core/pipeline/scr1_tracelog.sv"
|
|
||||||
|
|
||||||
# primitives
|
// pipeline
|
||||||
#/home/yenuchenko/riscv_school/scr1/scr1-master/src/core/primitives
|
// /home/yenuchenko/riscv_school/scr1/scr1-master/src/core
|
||||||
`include "../core/primitives/scr1_cg.sv"
|
`include "scr1/scr1_ipic.sv"
|
||||||
`include "../core/primitives/scr1_reset_cells.sv"
|
`include "scr1/scr1_pipe_csr.sv"
|
||||||
|
`include "scr1/scr1_pipe_exu.sv"
|
||||||
|
`include "scr1/scr1_pipe_hdu.sv"
|
||||||
|
`include "scr1/scr1_pipe_ialu.sv"
|
||||||
|
`include "scr1/scr1_pipe_idu.sv"
|
||||||
|
`include "scr1/scr1_pipe_ifu.sv"
|
||||||
|
`include "scr1/scr1_pipe_lsu.sv"
|
||||||
|
`include "scr1/scr1_pipe_mprf.sv"
|
||||||
|
`include "scr1/scr1_pipe_tdu.sv"
|
||||||
|
`include "scr1/scr1_pipe_top.sv"
|
||||||
|
`include "scr1/scr1_tracelog.sv"
|
||||||
|
|
||||||
# includes
|
// primitives
|
||||||
#/home/yenuchenko/riscv_school/scr1/scr1-master/src/includes
|
// /home/yenuchenko/riscv_school/scr1/scr1-master/src/core
|
||||||
`include "../includes/scr1_ahb.svh"
|
`include "scr1/scr1_cg.sv"
|
||||||
`include "../includes/scr1_arch_description.svh"
|
`include "scr1/scr1_reset_cells.sv"
|
||||||
`include "../includes/scr1_arch_types.svh"
|
|
||||||
`include "../includes/scr1_csr.svh"
|
|
||||||
`include "../includes/scr1_dm.svh"
|
|
||||||
`include "../includes/scr1_hdu.svh"
|
|
||||||
`include "../includes/scr1_ipic.svh"
|
|
||||||
`include "../includes/scr1_memif.svh"
|
|
||||||
`include "../includes/scr1_riscv_isa_decoding.svh"
|
|
||||||
`include "../includes/scr1_scu.svh"
|
|
||||||
`include "../includes/scr1_search_ms1.svh"
|
|
||||||
`include "../includes/scr1_tapc.svh"
|
|
||||||
`include "../includes/scr1_tdu.svh"
|
|
||||||
|
|
||||||
# top
|
// top
|
||||||
#/home/yenuchenko/riscv_school/scr1/scr1-master/src/top
|
// /home/yenuchenko/riscv_school/scr1/scr1-master/src/top
|
||||||
`include "../top/scr1_dmem_ahb.sv"
|
`include "scr1/scr1_dmem_ahb.sv"
|
||||||
`include "../top/scr1_dmem_router.sv"
|
`include "scr1/scr1_dmem_router.sv"
|
||||||
`include "../top/scr1_dp_memory.sv"
|
`include "scr1/scr1_dp_memory.sv"
|
||||||
`include "../top/scr1_imem_ahb.sv"
|
`include "scr1/scr1_imem_ahb.sv"
|
||||||
`include "../top/scr1_imem_router.sv"
|
`include "scr1/scr1_imem_router.sv"
|
||||||
`include "../top/scr1_mem_axi.sv"
|
`include "scr1/scr1_mem_axi.sv"
|
||||||
`include "../top/scr1_tcm.sv"
|
`include "scr1/scr1_tcm.sv"
|
||||||
`include "../top/scr1_timer.sv"
|
`include "scr1/scr1_timer.sv"
|
||||||
`include "../top/scr1_top_ahb.sv"
|
`include "scr1/scr1_top_ahb.sv"
|
||||||
`include "../top/scr1_top_axi.sv"
|
`include "scr1/scr1_top_axi.sv"
|
||||||
|
|
||||||
|
|||||||
215
src/rtl/scr1/scr1_arch_description.svh
Normal file
215
src/rtl/scr1/scr1_arch_description.svh
Normal file
@@ -0,0 +1,215 @@
|
|||||||
|
/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
|
||||||
|
/// @file <scr1_arch_description.svh>
|
||||||
|
/// @brief Architecture description file
|
||||||
|
///
|
||||||
|
|
||||||
|
`ifndef SCR1_ARCH_DESCRIPTION_SVH
|
||||||
|
`define SCR1_ARCH_DESCRIPTION_SVH
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// CORE FUNDAMENTAL PARAMETERS
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// SCR1 core identifiers
|
||||||
|
`define SCR1_MIMPID 32'h22011200
|
||||||
|
`define SCR1_MVENDORID 32'h00000000
|
||||||
|
|
||||||
|
// Width of main registers and buses
|
||||||
|
`define SCR1_XLEN 32
|
||||||
|
`define SCR1_IMEM_AWIDTH `SCR1_XLEN
|
||||||
|
`define SCR1_IMEM_DWIDTH `SCR1_XLEN
|
||||||
|
`define SCR1_DMEM_AWIDTH `SCR1_XLEN
|
||||||
|
`define SCR1_DMEM_DWIDTH `SCR1_XLEN
|
||||||
|
|
||||||
|
// TAP IDCODE
|
||||||
|
`define SCR1_TAP_IDCODE 'hDEB11001
|
||||||
|
|
||||||
|
|
||||||
|
`ifdef SCR1_ARCH_CUSTOM
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// INCLUDE SCR1_ARCH_CUSTOM.SVH
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// The external file scr1_arch_custom.svh is used for the open SCR1-SDK project,
|
||||||
|
// and can also be used for any custom projects.
|
||||||
|
|
||||||
|
// The file sets:
|
||||||
|
// - target platform (FPGA/ASIC), which affects the choice of logical constructs;
|
||||||
|
// - device build ID;
|
||||||
|
// - address constants;
|
||||||
|
// - could enables configuration parameters.
|
||||||
|
|
||||||
|
// Possible targets:
|
||||||
|
// `define SCR1_TRGT_FPGA_INTEL // target platform is Intel FPGAs
|
||||||
|
// `define SCR1_TRGT_FPGA_INTEL_MAX10 // target platform is Intel MAX 10 FPGAs (used in the SCR1-SDK project)
|
||||||
|
// `define SCR1_TRGT_FPGA_INTEL_ARRIAV // target platform is Intel Arria V FPGAs (used in the SCR1-SDK project)
|
||||||
|
// `define SCR1_TRGT_FPGA_XILINX // target platform is Xilinx FPGAs (used in the SCR1-SDK project)
|
||||||
|
// `define SCR1_TRGT_ASIC // target platform is ASIC
|
||||||
|
// `define SCR1_TRGT_SIMULATION // target is simulation (enable simulation code)
|
||||||
|
|
||||||
|
`include "scr1_arch_custom.svh"
|
||||||
|
|
||||||
|
`endif // SCR1_ARCH_CUSTOM
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// RECOMMENDED CORE ARCHITECTURE CONFIGURATIONS
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Uncomment one of these defines to set the recommended configuration:
|
||||||
|
|
||||||
|
//`define SCR1_CFG_RV32IMC_MAX
|
||||||
|
//`define SCR1_CFG_RV32IC_BASE
|
||||||
|
`define SCR1_CFG_RV32EC_MIN
|
||||||
|
|
||||||
|
// If all defines are commented, custom configuration will be used (see below)
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// READ-ONLY: settings for recommended configurations
|
||||||
|
`ifdef SCR1_CFG_RV32IMC_MAX
|
||||||
|
`define SCR1_RVI_EXT
|
||||||
|
`define SCR1_RVM_EXT
|
||||||
|
`define SCR1_RVC_EXT
|
||||||
|
parameter int unsigned SCR1_MTVEC_BASE_WR_BITS = 26;
|
||||||
|
`define SCR1_MTVEC_MODE_EN
|
||||||
|
`define SCR1_FAST_MUL
|
||||||
|
`define SCR1_MPRF_RST_EN
|
||||||
|
`define SCR1_MCOUNTEN_EN
|
||||||
|
`define SCR1_DBG_EN
|
||||||
|
`define SCR1_TDU_EN
|
||||||
|
parameter int unsigned SCR1_TDU_TRIG_NUM = 4;
|
||||||
|
`define SCR1_TDU_ICOUNT_EN
|
||||||
|
`define SCR1_IPIC_EN
|
||||||
|
`define SCR1_IPIC_SYNC_EN
|
||||||
|
`define SCR1_TCM_EN
|
||||||
|
`elsif SCR1_CFG_RV32IC_BASE
|
||||||
|
`define SCR1_RVI_EXT
|
||||||
|
`define SCR1_RVC_EXT
|
||||||
|
parameter int unsigned SCR1_MTVEC_BASE_WR_BITS = 16;
|
||||||
|
`define SCR1_MTVEC_MODE_EN
|
||||||
|
`define SCR1_NO_DEC_STAGE
|
||||||
|
`define SCR1_MPRF_RST_EN
|
||||||
|
`define SCR1_MCOUNTEN_EN
|
||||||
|
`define SCR1_DBG_EN
|
||||||
|
`define SCR1_TDU_EN
|
||||||
|
parameter int unsigned SCR1_TDU_TRIG_NUM = 2;
|
||||||
|
`define SCR1_TDU_ICOUNT_EN
|
||||||
|
`define SCR1_IPIC_EN
|
||||||
|
`define SCR1_IPIC_SYNC_EN
|
||||||
|
`define SCR1_TCM_EN
|
||||||
|
`elsif SCR1_CFG_RV32EC_MIN
|
||||||
|
`define SCR1_RVE_EXT
|
||||||
|
`define SCR1_RVC_EXT
|
||||||
|
parameter int unsigned SCR1_MTVEC_BASE_WR_BITS = 0;
|
||||||
|
`define SCR1_NO_DEC_STAGE
|
||||||
|
`define SCR1_NO_EXE_STAGE
|
||||||
|
`define SCR1_TCM_EN
|
||||||
|
|
||||||
|
`else // begin custom configuration section
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// CUSTOM CORE ARCHITECTURE CONFIGURATION
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// To fine-tune custom configuration, you can change the values in this section.
|
||||||
|
// Make sure that the defines of the recommended configurations are commented,
|
||||||
|
// otherwise this section will be inactive.
|
||||||
|
|
||||||
|
// RISC-V ISA options
|
||||||
|
//`define SCR1_RVE_EXT // enable RV32E base integer instruction set, otherwise RV32I will be used
|
||||||
|
`define SCR1_RVM_EXT // enable standard extension "M" for integer hardware multiplier and divider
|
||||||
|
`define SCR1_RVC_EXT // enable standard extension "C" for compressed instructions
|
||||||
|
parameter int unsigned SCR1_MTVEC_BASE_WR_BITS = 26; // number of writable high-order bits in MTVEC.base field
|
||||||
|
// legal values are 0 to 26
|
||||||
|
// read-only bits are hardwired to reset value
|
||||||
|
`define SCR1_MTVEC_MODE_EN // enable writable MTVEC.mode field to allow vectored irq mode, otherwise only direct mode is possible
|
||||||
|
|
||||||
|
`ifndef SCR1_RVE_EXT
|
||||||
|
`define SCR1_RVI_EXT // RV32E base integer instruction set if SCR1_RVE_EXT is not enabled
|
||||||
|
`endif // ~SCR1_RVE_EXT
|
||||||
|
|
||||||
|
// Core pipeline options (power-performance-area optimization)
|
||||||
|
`define SCR1_NO_DEC_STAGE // disable register between IFU and IDU
|
||||||
|
`define SCR1_NO_EXE_STAGE // disable register between IDU and EXU
|
||||||
|
`define SCR1_NEW_PC_REG // enable register in IFU for New_PC value
|
||||||
|
`define SCR1_FAST_MUL // enable fast one-cycle multiplication, otherwise multiplication takes 32 cycles
|
||||||
|
`define SCR1_CLKCTRL_EN // enable global clock gating
|
||||||
|
`define SCR1_MPRF_RST_EN // enable reset for MPRF
|
||||||
|
`define SCR1_MCOUNTEN_EN // enable custom MCOUNTEN CSR for counter control
|
||||||
|
|
||||||
|
// Uncore options
|
||||||
|
`define SCR1_DBG_EN // enable Debug Subsystem (TAPC, DM, SCU, HDU)
|
||||||
|
`define SCR1_TDU_EN // enable Trigger Debug Unit (hardware breakpoints)
|
||||||
|
parameter int unsigned SCR1_TDU_TRIG_NUM = 2; // number of hardware triggers
|
||||||
|
`define SCR1_TDU_ICOUNT_EN // enable hardware triggers on instruction counter
|
||||||
|
`define SCR1_IPIC_EN // enable Integrated Programmable Interrupt Controller
|
||||||
|
`define SCR1_IPIC_SYNC_EN // enable IPIC synchronizer
|
||||||
|
`define SCR1_TCM_EN // enable Tightly-Coupled Memory
|
||||||
|
|
||||||
|
`endif // end custom configuration section
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// CORE INTEGRATION OPTIONS
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Bypasses on AXI/AHB bridge I/O
|
||||||
|
`define SCR1_IMEM_AHB_IN_BP // bypass instruction memory AHB bridge input register
|
||||||
|
`define SCR1_IMEM_AHB_OUT_BP // bypass instruction memory AHB bridge output register
|
||||||
|
`define SCR1_DMEM_AHB_IN_BP // bypass data memory AHB bridge input register
|
||||||
|
`define SCR1_DMEM_AHB_OUT_BP // bypass data memory AHB bridge output register
|
||||||
|
`define SCR1_IMEM_AXI_REQ_BP // bypass instruction memory AXI bridge request register
|
||||||
|
`define SCR1_IMEM_AXI_RESP_BP // bypass instruction memory AXI bridge response register
|
||||||
|
`define SCR1_DMEM_AXI_REQ_BP // bypass data memory AXI bridge request register
|
||||||
|
`define SCR1_DMEM_AXI_RESP_BP // bypass data memory AXI bridge response register
|
||||||
|
|
||||||
|
`ifndef SCR1_ARCH_CUSTOM
|
||||||
|
// Default address constants (if scr1_arch_custom.svh is not used)
|
||||||
|
parameter bit [`SCR1_XLEN-1:0] SCR1_ARCH_RST_VECTOR = 'h200; // Reset vector value (start address after reset)
|
||||||
|
parameter bit [`SCR1_XLEN-1:0] SCR1_ARCH_MTVEC_BASE = 'h1C0; // MTVEC.base field reset value, or constant value for MTVEC.base bits that are hardwired
|
||||||
|
|
||||||
|
parameter bit [`SCR1_DMEM_AWIDTH-1:0] SCR1_TCM_ADDR_MASK = 'hFFFF0000; // TCM mask and size; size in bytes is two's complement of the mask value
|
||||||
|
parameter bit [`SCR1_DMEM_AWIDTH-1:0] SCR1_TCM_ADDR_PATTERN = 'h00480000; // TCM address match pattern
|
||||||
|
|
||||||
|
parameter bit [`SCR1_DMEM_AWIDTH-1:0] SCR1_TIMER_ADDR_MASK = 'hFFFFFFE0; // Timer mask
|
||||||
|
parameter bit [`SCR1_DMEM_AWIDTH-1:0] SCR1_TIMER_ADDR_PATTERN = 'h00490000; // Timer address match pattern
|
||||||
|
|
||||||
|
// Device build ID
|
||||||
|
`define SCR1_ARCH_BUILD_ID `SCR1_MIMPID
|
||||||
|
|
||||||
|
`endif // SCR1_ARCH_CUSTOM
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// TARGET-SPECIFIC OPTIONS
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// RAM-based MPRF can be used for Intel FPGAs only
|
||||||
|
`ifdef SCR1_TRGT_FPGA_INTEL
|
||||||
|
`define SCR1_MPRF_RAM // implements MPRF with dedicated RAM blocks
|
||||||
|
`endif
|
||||||
|
|
||||||
|
// EXU_STAGE_BYPASS and MPRF_RST_EN must be disabled for RAM-based MPRF
|
||||||
|
`ifdef SCR1_MPRF_RAM
|
||||||
|
`undef SCR1_NO_EXE_STAGE
|
||||||
|
`undef SCR1_MPRF_RST_EN
|
||||||
|
`endif
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// SIMULATION OPTIONS
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//`define SCR1_TRGT_SIMULATION // enable simulation code (automatically defined by root makefile)
|
||||||
|
//`define SCR1_TRACE_LOG_EN // enable tracelog
|
||||||
|
//`define SCR1_XPROP_EN // enable X-propagation
|
||||||
|
|
||||||
|
// Addresses used in testbench
|
||||||
|
localparam [`SCR1_XLEN-1:0] SCR1_SIM_EXIT_ADDR = 32'h0000_00F8;
|
||||||
|
localparam [`SCR1_XLEN-1:0] SCR1_SIM_PRINT_ADDR = 32'hF000_0000;
|
||||||
|
localparam [`SCR1_XLEN-1:0] SCR1_SIM_EXT_IRQ_ADDR = 32'hF000_0100;
|
||||||
|
localparam [`SCR1_XLEN-1:0] SCR1_SIM_SOFT_IRQ_ADDR = 32'hF000_0200;
|
||||||
|
|
||||||
|
`endif // SCR1_ARCH_DESCRIPTION_SVH
|
||||||
78
src/sdc/scr1_core_top.sdc
Normal file
78
src/sdc/scr1_core_top.sdc
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
### Stage: "Synthesis and PaR"
|
||||||
|
### File description: "Constraints for the design"
|
||||||
|
|
||||||
|
|
||||||
|
# SET LIB UNITS
|
||||||
|
set_units -time 1.0ns;
|
||||||
|
set_units -capacitance 1.0pF;
|
||||||
|
|
||||||
|
set_max_capacitance 0.5 [all_outputs]
|
||||||
|
|
||||||
|
### ====================== CLOCKS ===========================
|
||||||
|
# Clock period: 10 ns (100 MHz)
|
||||||
|
set CLK_PERIOD 100
|
||||||
|
|
||||||
|
|
||||||
|
# Clock uncertainty: 200 ps for all clocks
|
||||||
|
set CLK_UNCERT 0.2;
|
||||||
|
|
||||||
|
|
||||||
|
# Clock transition: 1 ns R/F
|
||||||
|
set MINRISE 0
|
||||||
|
set MAXRISE 1.0
|
||||||
|
set MINFALL 0
|
||||||
|
set MAXFALL 1.0
|
||||||
|
|
||||||
|
|
||||||
|
# Clock setup
|
||||||
|
create_clock -name "clk" -period $CLK_PERIOD -waveform "0 [expr $CLK_PERIOD/2.0]" [get_ports "clk"]
|
||||||
|
|
||||||
|
set_clock_uncertainty $CLK_UNCERT [get_clocks "clk"]
|
||||||
|
|
||||||
|
set_clock_transition -rise -min $MINRISE [get_clocks "clk"]
|
||||||
|
set_clock_transition -rise -max $MAXRISE [get_clocks "clk"]
|
||||||
|
set_clock_transition -fall -min $MINFALL [get_clocks "clk"]
|
||||||
|
set_clock_transition -fall -max $MAXFALL [get_clocks "clk"]
|
||||||
|
|
||||||
|
### ====================== DELAYS ===========================
|
||||||
|
# IO delays: 2.5 ns
|
||||||
|
set INPUT_DELAY_CLK [expr $CLK_PERIOD/4.0]
|
||||||
|
set OUTPUT_DELAY_CLK [expr $CLK_PERIOD/4.0]
|
||||||
|
|
||||||
|
|
||||||
|
# IO delays setup
|
||||||
|
set_input_delay -clock "clk" -max $INPUT_DELAY_CLK [all_inputs]
|
||||||
|
set_input_delay -clock "clk" -min $INPUT_DELAY_CLK [all_inputs]
|
||||||
|
|
||||||
|
set_output_delay -clock "clk" -max $OUTPUT_DELAY_CLK [all_outputs]
|
||||||
|
set_output_delay -clock "clk" -min $OUTPUT_DELAY_CLK [all_outputs]
|
||||||
|
|
||||||
|
|
||||||
|
# Ideal networks
|
||||||
|
set_ideal_network [get_ports "pwrup_rst_n"]
|
||||||
|
set_ideal_network [get_ports "rst_n"]
|
||||||
|
set_ideal_network [get_ports "cpu_rst_n"]
|
||||||
|
set_ideal_network [get_ports "test_rst_n"]
|
||||||
|
|
||||||
|
|
||||||
|
# False paths
|
||||||
|
set_false_path -from [get_ports "pwrup_rst_n"]
|
||||||
|
set_false_path -from [get_ports "rst_n"]
|
||||||
|
set_false_path -from [get_ports "cpu_rst_n"]
|
||||||
|
set_false_path -from [get_ports "test_rst_n"]
|
||||||
|
|
||||||
|
|
||||||
|
set_case_analysis 0 [get_ports "test_mode"]
|
||||||
|
|
||||||
|
# |--------------|
|
||||||
|
#->| |->
|
||||||
|
#->| clk |->
|
||||||
|
# | |
|
||||||
|
# ----------------
|
||||||
|
# | rtc |
|
||||||
|
# ----------------
|
||||||
|
#->| |->tdo
|
||||||
|
#->| tck |->tdo_en
|
||||||
|
# | |
|
||||||
|
# |--------------|
|
||||||
|
|
||||||
@@ -1,106 +0,0 @@
|
|||||||
### Stage: "Synthesis and PaR"
|
|
||||||
### File description: "Constraints for the design"
|
|
||||||
|
|
||||||
|
|
||||||
# SET LIB UNITS
|
|
||||||
set_units -time 1.0ns;
|
|
||||||
set_units -capacitance 1.0pF;
|
|
||||||
|
|
||||||
set_max_capacitance 0.5 [all_outputs]
|
|
||||||
|
|
||||||
### ====================== CLOCKS ===========================
|
|
||||||
#clock uncertainty: 200ps for all clocks
|
|
||||||
set CLK_UNCERT 0.2;
|
|
||||||
#transition: 1ns R/F
|
|
||||||
|
|
||||||
# CLOCK PERIOD
|
|
||||||
set CLK_PERIOD 11.13
|
|
||||||
set TCK_PERIOD 100
|
|
||||||
set RTC_CLK_PERIOD 10000
|
|
||||||
|
|
||||||
# IO DELAYS
|
|
||||||
set INPUT_DELAY_CLK [expr $CLK_PERIOD/4.0]
|
|
||||||
set OUTPUT_DELAY_CLK [expr $CLK_PERIOD/4.0]
|
|
||||||
|
|
||||||
set INPUT_DELAY_TCK [expr $TCK_PERIOD/4.0]
|
|
||||||
set OUTPUT_DELAY_TCK [expr $TCK_PERIOD/4.0]
|
|
||||||
|
|
||||||
#clk->100MHz
|
|
||||||
create_clock -name "clk" -period $CLK_PERIOD -waveform "0 [expr $CLK_PERIOD/2.0]" [get_ports "clk"]
|
|
||||||
#tck->10MHz
|
|
||||||
create_clock -name "tck" -period $TCK_PERIOD -waveform "0 [expr $TCK_PERIOD/2.0]" [get_ports "tck"]
|
|
||||||
#rtc_clk->100kHz
|
|
||||||
create_clock -name "rtc_clk" -period $RTC_CLK_PERIOD -waveform "0 [expr $RTC_CLK_PERIOD/2.0]" [get_ports "rtc_clk"]
|
|
||||||
|
|
||||||
set_clock_groups -asynchronous -group {"clk"} -group {"tck"} -group {"rtc_clk"}
|
|
||||||
|
|
||||||
set MINRISE 0
|
|
||||||
set MAXRISE 1.0
|
|
||||||
set MINFALL 0
|
|
||||||
set MAXFALL 1.0
|
|
||||||
|
|
||||||
set_clock_uncertainty $CLK_UNCERT [get_clocks "clk"]
|
|
||||||
set_clock_transition -rise -min $MINRISE [get_clocks "clk"]
|
|
||||||
set_clock_transition -rise -max $MAXRISE [get_clocks "clk"]
|
|
||||||
set_clock_transition -fall -min $MINFALL [get_clocks "clk"]
|
|
||||||
set_clock_transition -fall -max $MAXFALL [get_clocks "clk"]
|
|
||||||
|
|
||||||
set_clock_uncertainty $CLK_UNCERT [get_clocks "tck"]
|
|
||||||
set_clock_transition -rise -min $MINRISE [get_clocks "tck"]
|
|
||||||
set_clock_transition -rise -max $MAXRISE [get_clocks "tck"]
|
|
||||||
set_clock_transition -fall -min $MINFALL [get_clocks "tck"]
|
|
||||||
set_clock_transition -fall -max $MAXFALL [get_clocks "tck"]
|
|
||||||
|
|
||||||
set_clock_uncertainty $CLK_UNCERT [get_clocks "rtc_clk"]
|
|
||||||
set_clock_transition -rise -min $MINRISE [get_clocks "rtc_clk"]
|
|
||||||
set_clock_transition -rise -max $MAXRISE [get_clocks "rtc_clk"]
|
|
||||||
set_clock_transition -fall -min $MINFALL [get_clocks "rtc_clk"]
|
|
||||||
set_clock_transition -fall -max $MAXFALL [get_clocks "rtc_clk"]
|
|
||||||
|
|
||||||
|
|
||||||
set_ideal_network [get_ports "pwrup_rst_n"]
|
|
||||||
set_ideal_network [get_ports "rst_n"]
|
|
||||||
set_ideal_network [get_ports "cpu_rst_n"]
|
|
||||||
set_ideal_network [get_ports "test_rst_n"]
|
|
||||||
set_ideal_network [get_ports "trst_n"]
|
|
||||||
|
|
||||||
set_false_path -from [get_ports "pwrup_rst_n"]
|
|
||||||
set_false_path -from [get_ports "rst_n"]
|
|
||||||
set_false_path -from [get_ports "cpu_rst_n"]
|
|
||||||
set_false_path -from [get_ports "test_rst_n"]
|
|
||||||
set_false_path -from [get_ports "trst_n"]
|
|
||||||
|
|
||||||
#IO delays:
|
|
||||||
|
|
||||||
set_input_delay -clock "clk" -max $INPUT_DELAY_CLK [remove_from_collection [all_inputs] {trst_n tdi tms}]
|
|
||||||
set_input_delay -clock "clk" -min $INPUT_DELAY_CLK [remove_from_collection [all_inputs] {trst_n tdi tms}]
|
|
||||||
|
|
||||||
set_input_delay -clock "tck" -max $INPUT_DELAY_TCK [get_ports {trst_n tdi tms}]
|
|
||||||
set_input_delay -clock "tck" -min $INPUT_DELAY_TCK [get_ports {trst_n tdi tms}]
|
|
||||||
|
|
||||||
|
|
||||||
set_output_delay -clock "clk" -max $OUTPUT_DELAY_CLK [remove_from_collection [all_outputs] {tdo tdo_en}]
|
|
||||||
set_output_delay -clock "clk" -min $OUTPUT_DELAY_CLK [remove_from_collection [all_outputs] {tdo tdo_en}]
|
|
||||||
|
|
||||||
set_output_delay -clock "tck" -max $OUTPUT_DELAY_TCK [get_ports {tdo tdo_en}]
|
|
||||||
set_output_delay -clock "tck" -min $OUTPUT_DELAY_TCK [get_ports {tdo tdo_en}]
|
|
||||||
|
|
||||||
|
|
||||||
set_case_analysis 0 [get_ports "test_mode"]
|
|
||||||
|
|
||||||
# |--------------|
|
|
||||||
#->| |->
|
|
||||||
#->| clk |->
|
|
||||||
# | |
|
|
||||||
# ----------------
|
|
||||||
# | rtc |
|
|
||||||
# ----------------
|
|
||||||
#->| |->tdo
|
|
||||||
#->| tck |->tdo_en
|
|
||||||
# | |
|
|
||||||
# |--------------|
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
605
src_ref/core/pipeline/scr1_ipic.sv
Normal file
605
src_ref/core/pipeline/scr1_ipic.sv
Normal file
@@ -0,0 +1,605 @@
|
|||||||
|
/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
|
||||||
|
/// @file <scr1_ipic.sv>
|
||||||
|
/// @brief Integrated Programmable Interrupt Controller (IPIC)
|
||||||
|
///
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Functionality:
|
||||||
|
// - Synchronizes IRQ lines (optional)
|
||||||
|
// - Detects level and edge (with optional lines inversion) of IRQ lines
|
||||||
|
// - Setups interrupts handling (mode, inversion, enable)
|
||||||
|
// - Provides information about pending interrupts and interrupts currently in
|
||||||
|
// service
|
||||||
|
// - Generates interrupt request to CSR
|
||||||
|
//
|
||||||
|
// Structure:
|
||||||
|
// - IRQ lines handling (synchronization, level and edge detection) logic
|
||||||
|
// - IPIC registers:
|
||||||
|
// - CISV
|
||||||
|
// - CICSR
|
||||||
|
// - EOI
|
||||||
|
// - SOI
|
||||||
|
// - IDX
|
||||||
|
// - IPR
|
||||||
|
// - ISVR
|
||||||
|
// - IER
|
||||||
|
// - IMR
|
||||||
|
// - IINVR
|
||||||
|
// - ICSR
|
||||||
|
// - Priority interrupt generation logic
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
`include "scr1_arch_description.svh"
|
||||||
|
|
||||||
|
`ifdef SCR1_IPIC_EN
|
||||||
|
|
||||||
|
`include "scr1_ipic.svh"
|
||||||
|
|
||||||
|
module scr1_ipic
|
||||||
|
(
|
||||||
|
// Common
|
||||||
|
input logic rst_n, // IPIC reset
|
||||||
|
input logic clk, // IPIC clock
|
||||||
|
|
||||||
|
// External Interrupt lines
|
||||||
|
input logic [SCR1_IRQ_LINES_NUM-1:0] soc2ipic_irq_lines_i, // External IRQ lines
|
||||||
|
|
||||||
|
// CSR <-> IPIC interface
|
||||||
|
input logic csr2ipic_r_req_i, // IPIC read request
|
||||||
|
input logic csr2ipic_w_req_i, // IPIC write request
|
||||||
|
input logic [2:0] csr2ipic_addr_i, // IPIC address
|
||||||
|
input logic [`SCR1_XLEN-1:0] csr2ipic_wdata_i, // IPIC write data
|
||||||
|
output logic [`SCR1_XLEN-1:0] ipic2csr_rdata_o, // IPIC read data
|
||||||
|
output logic ipic2csr_irq_m_req_o // IRQ request from IPIC
|
||||||
|
);
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Local types declaration
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
typedef struct {
|
||||||
|
logic vd;
|
||||||
|
logic idx;
|
||||||
|
} type_scr1_search_one_2_s;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
logic vd;
|
||||||
|
logic [SCR1_IRQ_IDX_WIDTH-1:0] idx;
|
||||||
|
} type_scr1_search_one_16_s;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic ip;
|
||||||
|
logic ie;
|
||||||
|
logic im;
|
||||||
|
logic inv;
|
||||||
|
logic isv;
|
||||||
|
logic [SCR1_IRQ_LINES_WIDTH-1:0] line;
|
||||||
|
} type_scr1_icsr_m_s;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic ip;
|
||||||
|
logic ie;
|
||||||
|
} type_scr1_cicsr_s;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Local functions declaration
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function automatic type_scr1_search_one_2_s scr1_search_one_2(
|
||||||
|
input logic [1:0] din
|
||||||
|
);
|
||||||
|
type_scr1_search_one_2_s tmp;
|
||||||
|
begin
|
||||||
|
tmp.vd = |din;
|
||||||
|
tmp.idx = ~din[0];
|
||||||
|
return tmp;
|
||||||
|
end
|
||||||
|
endfunction : scr1_search_one_2
|
||||||
|
|
||||||
|
function automatic type_scr1_search_one_16_s scr1_search_one_16(
|
||||||
|
input logic [15:0] din
|
||||||
|
);
|
||||||
|
begin
|
||||||
|
logic [7:0] stage1_vd;
|
||||||
|
logic [3:0] stage2_vd;
|
||||||
|
logic [1:0] stage3_vd;
|
||||||
|
|
||||||
|
logic stage1_idx [7:0];
|
||||||
|
logic [1:0] stage2_idx [3:0];
|
||||||
|
logic [2:0] stage3_idx [1:0];
|
||||||
|
type_scr1_search_one_16_s result;
|
||||||
|
|
||||||
|
// Stage 1
|
||||||
|
for (int unsigned i=0; i<8; ++i) begin
|
||||||
|
type_scr1_search_one_2_s tmp;
|
||||||
|
tmp = scr1_search_one_2(din[(i+1)*2-1-:2]);
|
||||||
|
stage1_vd[i] = tmp.vd;
|
||||||
|
stage1_idx[i] = tmp.idx;
|
||||||
|
end
|
||||||
|
|
||||||
|
// Stage 2
|
||||||
|
for (int unsigned i=0; i<4; ++i) begin
|
||||||
|
type_scr1_search_one_2_s tmp;
|
||||||
|
tmp = scr1_search_one_2(stage1_vd[(i+1)*2-1-:2]);
|
||||||
|
stage2_vd[i] = tmp.vd;
|
||||||
|
stage2_idx[i] = (~tmp.idx) ? {tmp.idx, stage1_idx[2*i]} : {tmp.idx, stage1_idx[2*i+1]};
|
||||||
|
end
|
||||||
|
|
||||||
|
// Stage 3
|
||||||
|
for (int unsigned i=0; i<2; ++i) begin
|
||||||
|
type_scr1_search_one_2_s tmp;
|
||||||
|
tmp = scr1_search_one_2(stage2_vd[(i+1)*2-1-:2]);
|
||||||
|
stage3_vd[i] = tmp.vd;
|
||||||
|
stage3_idx[i] = (~tmp.idx) ? {tmp.idx, stage2_idx[2*i]} : {tmp.idx, stage2_idx[2*i+1]};
|
||||||
|
end
|
||||||
|
|
||||||
|
// Stage 4
|
||||||
|
result.vd = |stage3_vd;
|
||||||
|
result.idx = (stage3_vd[0]) ? {1'b0, stage3_idx[0]} : {1'b1, stage3_idx[1]};
|
||||||
|
|
||||||
|
return result;
|
||||||
|
end
|
||||||
|
endfunction : scr1_search_one_16
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Local signals declaration
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// IRQ lines handling signals
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
logic [SCR1_IRQ_VECT_NUM-1:0] irq_lines; // Internal IRQ lines
|
||||||
|
`ifdef SCR1_IPIC_SYNC_EN
|
||||||
|
logic [SCR1_IRQ_VECT_NUM-1:0] irq_lines_sync;
|
||||||
|
`endif // SCR1_IPIC_SYNC_EN
|
||||||
|
logic [SCR1_IRQ_VECT_NUM-1:0] irq_lines_dly; // Internal IRQ lines delayed for 1 cycle
|
||||||
|
logic [SCR1_IRQ_VECT_NUM-1:0] irq_edge_detected; // IRQ lines edge detected flags
|
||||||
|
logic [SCR1_IRQ_VECT_NUM-1:0] irq_lvl; // IRQ lines level
|
||||||
|
|
||||||
|
// IPIC registers
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// CISV register
|
||||||
|
logic ipic_cisv_upd; // Current Interrupt Vecotr in Service register update
|
||||||
|
logic [SCR1_IRQ_VECT_WIDTH-1:0] ipic_cisv_ff; // Current Interrupt Vector in Service register
|
||||||
|
logic [SCR1_IRQ_VECT_WIDTH-1:0] ipic_cisv_next; // Current Interrupt Vector in Service register next value
|
||||||
|
|
||||||
|
// CICS register (CICSR)
|
||||||
|
logic cicsr_wr_req; // Write request to Current Interrupt Control Status register
|
||||||
|
type_scr1_cicsr_s ipic_cicsr; // Current Interrupt Control Status register
|
||||||
|
|
||||||
|
// EOI register
|
||||||
|
logic eoi_wr_req; // Write request to End of Interrupt register
|
||||||
|
logic ipic_eoi_req; // Request to end the interrupt that is currently in service
|
||||||
|
|
||||||
|
// SOI register
|
||||||
|
logic soi_wr_req; // Write request to Start of Interrupt register
|
||||||
|
logic ipic_soi_req; // Request to start the interrupt
|
||||||
|
|
||||||
|
// IDX register (IDXR)
|
||||||
|
logic idxr_wr_req; // Write request to Index register
|
||||||
|
logic [SCR1_IRQ_IDX_WIDTH-1:0] ipic_idxr_ff; // Index register
|
||||||
|
|
||||||
|
// IP register (IPR)
|
||||||
|
logic ipic_ipr_upd; // Interrupt pending register update
|
||||||
|
logic [SCR1_IRQ_VECT_NUM-1:0] ipic_ipr_ff; // Interrupt pending register
|
||||||
|
logic [SCR1_IRQ_VECT_NUM-1:0] ipic_ipr_next; // Interrupt pending register next value
|
||||||
|
logic [SCR1_IRQ_VECT_NUM-1:0] ipic_ipr_clr_cond; // Interrupt pending clear condition
|
||||||
|
logic [SCR1_IRQ_VECT_NUM-1:0] ipic_ipr_clr_req; // Interrupt pending clear request
|
||||||
|
logic [SCR1_IRQ_VECT_NUM-1:0] ipic_ipr_clr; // Interrupt pending clear operation
|
||||||
|
|
||||||
|
// ISV register (ISVR)
|
||||||
|
logic ipic_isvr_upd; // Interrupt Serviced register update
|
||||||
|
logic [SCR1_IRQ_VECT_NUM-1:0] ipic_isvr_ff; // Interrupt Serviced register
|
||||||
|
logic [SCR1_IRQ_VECT_NUM-1:0] ipic_isvr_next; // Interrupt Serviced register next value
|
||||||
|
|
||||||
|
// IE register (IER)
|
||||||
|
logic ipic_ier_upd; // Interrupt enable register update
|
||||||
|
logic [SCR1_IRQ_VECT_NUM-1:0] ipic_ier_ff; // Interrupt enable register
|
||||||
|
logic [SCR1_IRQ_VECT_NUM-1:0] ipic_ier_next; // Interrupt enable register next value
|
||||||
|
|
||||||
|
// IM register (IMR)
|
||||||
|
logic [SCR1_IRQ_VECT_NUM-1:0] ipic_imr_ff; // Interrupt mode register
|
||||||
|
logic [SCR1_IRQ_VECT_NUM-1:0] ipic_imr_next; // Interrupt mode register next value
|
||||||
|
|
||||||
|
// IINV register (IINVR)
|
||||||
|
logic [SCR1_IRQ_VECT_NUM-1:0] ipic_iinvr_ff; // Interrupt Inversion register
|
||||||
|
logic [SCR1_IRQ_VECT_NUM-1:0] ipic_iinvr_next; // Interrupt Inversion register next value
|
||||||
|
|
||||||
|
// ICS register (ICSR)
|
||||||
|
logic icsr_wr_req; // Write request to Interrupt Control Status register
|
||||||
|
type_scr1_icsr_m_s ipic_icsr; // Interrupt Control Status register
|
||||||
|
|
||||||
|
// Priority interrupt generation signals
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Serviced interrupt signals
|
||||||
|
logic irq_serv_vd; // There is an interrupt in service
|
||||||
|
logic [SCR1_IRQ_IDX_WIDTH-1:0] irq_serv_idx; // Index of an interrupt that is currently in service
|
||||||
|
|
||||||
|
// Requested interrupt signals
|
||||||
|
logic irq_req_vd; // There is a requested interrupt
|
||||||
|
logic [SCR1_IRQ_IDX_WIDTH-1:0] irq_req_idx; // Index of a requested interrupt
|
||||||
|
|
||||||
|
// Interrupt requested on "end of the previous interrupt" signals
|
||||||
|
logic irq_eoi_req_vd; // There is a requested interrupt when the previous one has ended
|
||||||
|
logic [SCR1_IRQ_IDX_WIDTH-1:0] irq_eoi_req_idx; // Index of an interrupt requested when the previous one has ended
|
||||||
|
|
||||||
|
logic [SCR1_IRQ_VECT_NUM-1:0] irq_req_v; // Vector of interrupts that are pending and enabled
|
||||||
|
|
||||||
|
logic irq_start_vd; // Request to start an interrupt is valid
|
||||||
|
logic irq_hi_prior_pnd; // There is a pending IRQ with a priority higher than of the interrupt that is currently in service
|
||||||
|
|
||||||
|
type_scr1_search_one_16_s irr_priority; // Structure for vd and idx of the requested interrupt
|
||||||
|
type_scr1_search_one_16_s isvr_priority_eoi; // Structure for vd and idx of the interrupt requested when the previous interrupt has ended
|
||||||
|
logic [SCR1_IRQ_VECT_NUM-1:0] ipic_isvr_eoi; // Interrupt Serviced register when the previous interrupt has ended
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// IRQ lines handling
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
`ifdef SCR1_IPIC_SYNC_EN
|
||||||
|
// IRQ lines synchronization
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
always_ff @(posedge clk, negedge rst_n) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
irq_lines_sync <= '0;
|
||||||
|
irq_lines <= '0;
|
||||||
|
end else begin
|
||||||
|
irq_lines_sync <= soc2ipic_irq_lines_i;
|
||||||
|
irq_lines <= irq_lines_sync;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
`else // SCR1_IPIC_SYNC_EN
|
||||||
|
assign irq_lines = soc2ipic_irq_lines_i;
|
||||||
|
`endif // SCR1_IPIC_SYNC_EN
|
||||||
|
|
||||||
|
// IRQ lines level detection
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign irq_lvl = irq_lines ^ ipic_iinvr_next;
|
||||||
|
|
||||||
|
// IRQ lines edge detection
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
always_ff @(negedge rst_n, posedge clk) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
irq_lines_dly <= '0;
|
||||||
|
end else begin
|
||||||
|
irq_lines_dly <= irq_lines;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign irq_edge_detected = (irq_lines_dly ^ irq_lines) & irq_lvl;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// IPIC registers read/write interface
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Read Logic
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Read data multiplexer
|
||||||
|
always_comb begin
|
||||||
|
ipic2csr_rdata_o = '0;
|
||||||
|
|
||||||
|
if (csr2ipic_r_req_i) begin
|
||||||
|
case (csr2ipic_addr_i)
|
||||||
|
SCR1_IPIC_CISV : begin
|
||||||
|
ipic2csr_rdata_o[SCR1_IRQ_VECT_WIDTH-1:0] = irq_serv_vd
|
||||||
|
? ipic_cisv_ff
|
||||||
|
: SCR1_IRQ_VOID_VECT_NUM;
|
||||||
|
end
|
||||||
|
SCR1_IPIC_CICSR : begin
|
||||||
|
ipic2csr_rdata_o[SCR1_IPIC_ICSR_IP] = ipic_cicsr.ip;
|
||||||
|
ipic2csr_rdata_o[SCR1_IPIC_ICSR_IE] = ipic_cicsr.ie;
|
||||||
|
end
|
||||||
|
SCR1_IPIC_IPR : begin
|
||||||
|
ipic2csr_rdata_o = `SCR1_XLEN'(ipic_ipr_ff);
|
||||||
|
end
|
||||||
|
SCR1_IPIC_ISVR : begin
|
||||||
|
ipic2csr_rdata_o = `SCR1_XLEN'(ipic_isvr_ff);
|
||||||
|
end
|
||||||
|
SCR1_IPIC_EOI,
|
||||||
|
SCR1_IPIC_SOI : begin
|
||||||
|
ipic2csr_rdata_o = '0;
|
||||||
|
end
|
||||||
|
SCR1_IPIC_IDX : begin
|
||||||
|
ipic2csr_rdata_o = `SCR1_XLEN'(ipic_idxr_ff);
|
||||||
|
end
|
||||||
|
SCR1_IPIC_ICSR : begin
|
||||||
|
ipic2csr_rdata_o[SCR1_IPIC_ICSR_IP] = ipic_icsr.ip;
|
||||||
|
ipic2csr_rdata_o[SCR1_IPIC_ICSR_IE] = ipic_icsr.ie;
|
||||||
|
ipic2csr_rdata_o[SCR1_IPIC_ICSR_IM] = ipic_icsr.im;
|
||||||
|
ipic2csr_rdata_o[SCR1_IPIC_ICSR_INV] = ipic_icsr.inv;
|
||||||
|
ipic2csr_rdata_o[SCR1_IPIC_ICSR_PRV_MSB:
|
||||||
|
SCR1_IPIC_ICSR_PRV_LSB] = SCR1_IPIC_PRV_M;
|
||||||
|
ipic2csr_rdata_o[SCR1_IPIC_ICSR_IS] = ipic_icsr.isv;
|
||||||
|
ipic2csr_rdata_o[SCR1_IPIC_ICSR_LN_MSB-1:
|
||||||
|
SCR1_IPIC_ICSR_LN_LSB] = ipic_icsr.line;
|
||||||
|
end
|
||||||
|
default : begin
|
||||||
|
ipic2csr_rdata_o = 'x;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// Write logic
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Register selection
|
||||||
|
always_comb begin
|
||||||
|
cicsr_wr_req = 1'b0;
|
||||||
|
eoi_wr_req = 1'b0;
|
||||||
|
soi_wr_req = 1'b0;
|
||||||
|
idxr_wr_req = 1'b0;
|
||||||
|
icsr_wr_req = 1'b0;
|
||||||
|
if (csr2ipic_w_req_i) begin
|
||||||
|
case (csr2ipic_addr_i)
|
||||||
|
SCR1_IPIC_CISV : begin end // Quiet Read-Only
|
||||||
|
SCR1_IPIC_CICSR: cicsr_wr_req = 1'b1;
|
||||||
|
SCR1_IPIC_IPR : begin end
|
||||||
|
SCR1_IPIC_ISVR : begin end // Quiet Read-Only
|
||||||
|
SCR1_IPIC_EOI : eoi_wr_req = 1'b1;
|
||||||
|
SCR1_IPIC_SOI : soi_wr_req = 1'b1;
|
||||||
|
SCR1_IPIC_IDX : idxr_wr_req = 1'b1;
|
||||||
|
SCR1_IPIC_ICSR : icsr_wr_req = 1'b1;
|
||||||
|
default : begin // Illegal IPIC register address
|
||||||
|
cicsr_wr_req = 'x;
|
||||||
|
eoi_wr_req = 'x;
|
||||||
|
soi_wr_req = 'x;
|
||||||
|
idxr_wr_req = 'x;
|
||||||
|
icsr_wr_req = 'x;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// IPIC registers
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Registers:
|
||||||
|
// - Current Interrupt Vector in Service (CISV) register
|
||||||
|
// - Current Interrupt Control Status (CICSR) register
|
||||||
|
// - End of Interrupt (EOI) register
|
||||||
|
// - Start of Interrupt (SOI) register
|
||||||
|
// - Index (IDX) register
|
||||||
|
// - Interrupt Pending Register (IPR)
|
||||||
|
// - Interrupt Serviced Register (ISVR)
|
||||||
|
// - Interrupt Enable Register (IER)
|
||||||
|
// - Interrupt Mode Register (IMR)
|
||||||
|
// - Interrupt Inversion Register (IINVR)
|
||||||
|
// - Interrupt Control Status Register (ICSR)
|
||||||
|
//
|
||||||
|
|
||||||
|
// CISV register
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Contains number of the interrupt vector currently in service. When no
|
||||||
|
// interrupts are in service, contains number of the void interrupt vector (0x10).
|
||||||
|
// The register cannot contain all 0's
|
||||||
|
|
||||||
|
assign ipic_cisv_upd = irq_start_vd | ipic_eoi_req;
|
||||||
|
|
||||||
|
always_ff @(negedge rst_n, posedge clk) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
ipic_cisv_ff <= SCR1_IRQ_VOID_VECT_NUM;
|
||||||
|
end else if (ipic_cisv_upd) begin
|
||||||
|
ipic_cisv_ff <= ipic_cisv_next;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign ipic_cisv_next = irq_start_vd ? {1'b0, irq_req_idx}
|
||||||
|
: ipic_eoi_req ? irq_eoi_req_vd ? {1'b0, irq_eoi_req_idx}
|
||||||
|
: SCR1_IRQ_VOID_VECT_NUM
|
||||||
|
: 1'b0;
|
||||||
|
|
||||||
|
assign irq_serv_idx = ipic_cisv_ff[SCR1_IRQ_VECT_WIDTH-2:0];
|
||||||
|
assign irq_serv_vd = ~ipic_cisv_ff[SCR1_IRQ_VECT_WIDTH-1];
|
||||||
|
|
||||||
|
// CICSR register
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Shows whether the interrupt currently in service is pending and enabled
|
||||||
|
|
||||||
|
assign ipic_cicsr.ip = ipic_ipr_ff[irq_serv_idx] & irq_serv_vd;
|
||||||
|
assign ipic_cicsr.ie = ipic_ier_ff[irq_serv_idx] & irq_serv_vd;
|
||||||
|
|
||||||
|
// EOI register
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Writing any value to EOI register ends the interrupt which is currently in service
|
||||||
|
|
||||||
|
assign ipic_eoi_req = eoi_wr_req & irq_serv_vd;
|
||||||
|
|
||||||
|
// SOI register
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Writing any value to SOI activates start of interrupt if one of the following
|
||||||
|
// conditions is true:
|
||||||
|
// - There is at least one pending interrupt with IE and ISR is zero
|
||||||
|
// - There is at least one pending interrupt with IE and higher priority than the
|
||||||
|
// interrupts currently in service
|
||||||
|
|
||||||
|
assign ipic_soi_req = soi_wr_req & irq_req_vd;
|
||||||
|
|
||||||
|
// IDX register
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Defines the number of interrupt vector which is accessed through the IPIC_ICSR
|
||||||
|
// register
|
||||||
|
|
||||||
|
always_ff @(negedge rst_n, posedge clk) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
ipic_idxr_ff <= '0;
|
||||||
|
end else if (idxr_wr_req) begin
|
||||||
|
ipic_idxr_ff <= csr2ipic_wdata_i[SCR1_IRQ_IDX_WIDTH-1:0];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// IPR
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// For every IRQ line shows whether there is a pending interrupt
|
||||||
|
|
||||||
|
assign ipic_ipr_upd = (ipic_ipr_next != ipic_ipr_ff);
|
||||||
|
|
||||||
|
always_ff @(negedge rst_n, posedge clk) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
ipic_ipr_ff <= '0;
|
||||||
|
end else if (ipic_ipr_upd) begin
|
||||||
|
ipic_ipr_ff <= ipic_ipr_next;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
ipic_ipr_clr_req = '0;
|
||||||
|
if (csr2ipic_w_req_i) begin
|
||||||
|
case (csr2ipic_addr_i)
|
||||||
|
SCR1_IPIC_CICSR: ipic_ipr_clr_req[irq_serv_idx] = csr2ipic_wdata_i[SCR1_IPIC_ICSR_IP]
|
||||||
|
& irq_serv_vd;
|
||||||
|
SCR1_IPIC_IPR : ipic_ipr_clr_req = csr2ipic_wdata_i[SCR1_IRQ_VECT_NUM-1:0];
|
||||||
|
SCR1_IPIC_SOI : ipic_ipr_clr_req[irq_req_idx] = irq_req_vd;
|
||||||
|
SCR1_IPIC_ICSR : ipic_ipr_clr_req[ipic_idxr_ff] = csr2ipic_wdata_i[SCR1_IPIC_ICSR_IP];
|
||||||
|
default : begin end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign ipic_ipr_clr_cond = ~irq_lvl | ipic_imr_next;
|
||||||
|
assign ipic_ipr_clr = ipic_ipr_clr_req & ipic_ipr_clr_cond;
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
ipic_ipr_next = '0;
|
||||||
|
for (int unsigned i=0; i<SCR1_IRQ_VECT_NUM; ++i) begin
|
||||||
|
ipic_ipr_next[i] = ipic_ipr_clr[i] ? 1'b0
|
||||||
|
: ~ipic_imr_ff[i] ? irq_lvl[i]
|
||||||
|
: ipic_ipr_ff[i] | irq_edge_detected[i];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// ISVR
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// For every IRQ line shows whether the interrupt is in service or not
|
||||||
|
|
||||||
|
assign ipic_isvr_upd = irq_start_vd | ipic_eoi_req;
|
||||||
|
|
||||||
|
always_ff @(negedge rst_n, posedge clk) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
ipic_isvr_ff <= '0;
|
||||||
|
end else if (ipic_isvr_upd) begin
|
||||||
|
ipic_isvr_ff <= ipic_isvr_next;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
ipic_isvr_eoi = ipic_isvr_ff;
|
||||||
|
if (irq_serv_vd) begin
|
||||||
|
ipic_isvr_eoi[irq_serv_idx] = 1'b0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
ipic_isvr_next = ipic_isvr_ff;
|
||||||
|
if (irq_start_vd) begin
|
||||||
|
ipic_isvr_next[irq_req_idx] = 1'b1;
|
||||||
|
end else if (ipic_eoi_req) begin
|
||||||
|
ipic_isvr_next = ipic_isvr_eoi;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// IER
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Enables/disables interrupt for every IRQ line
|
||||||
|
|
||||||
|
assign ipic_ier_upd = cicsr_wr_req | icsr_wr_req;
|
||||||
|
|
||||||
|
always_ff @(negedge rst_n, posedge clk) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
ipic_ier_ff <= '0;
|
||||||
|
end else if (ipic_ier_upd) begin
|
||||||
|
ipic_ier_ff <= ipic_ier_next;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
ipic_ier_next = ipic_ier_ff;
|
||||||
|
if (cicsr_wr_req) begin
|
||||||
|
ipic_ier_next[irq_serv_idx] = irq_serv_vd
|
||||||
|
? csr2ipic_wdata_i[SCR1_IPIC_ICSR_IE]
|
||||||
|
: ipic_ier_ff[irq_serv_idx];
|
||||||
|
end else if (icsr_wr_req) begin
|
||||||
|
ipic_ier_next[ipic_idxr_ff] = csr2ipic_wdata_i[SCR1_IPIC_ICSR_IE];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// IMR
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// For every IRQ line sets either Level (0) or Edge (1) detection
|
||||||
|
|
||||||
|
always_ff @(negedge rst_n, posedge clk) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
ipic_imr_ff <= '0;
|
||||||
|
end else if (icsr_wr_req) begin
|
||||||
|
ipic_imr_ff <= ipic_imr_next;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
ipic_imr_next = ipic_imr_ff;
|
||||||
|
if (icsr_wr_req) begin
|
||||||
|
ipic_imr_next[ipic_idxr_ff] = csr2ipic_wdata_i[SCR1_IPIC_ICSR_IM];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// IINVR
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// For every IRQ line defines whether it should be inverted or not
|
||||||
|
|
||||||
|
always_ff @(negedge rst_n, posedge clk) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
ipic_iinvr_ff <= '0;
|
||||||
|
end else if (icsr_wr_req) begin
|
||||||
|
ipic_iinvr_ff <= ipic_iinvr_next;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
ipic_iinvr_next = ipic_iinvr_ff;
|
||||||
|
if (icsr_wr_req) begin
|
||||||
|
ipic_iinvr_next[ipic_idxr_ff] = csr2ipic_wdata_i[SCR1_IPIC_ICSR_INV];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// ICSR
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Holds control and status information about the interrupt defined by Index Register
|
||||||
|
|
||||||
|
assign ipic_icsr.ip = ipic_ipr_ff [ipic_idxr_ff];
|
||||||
|
assign ipic_icsr.ie = ipic_ier_ff [ipic_idxr_ff];
|
||||||
|
assign ipic_icsr.im = ipic_imr_ff [ipic_idxr_ff];
|
||||||
|
assign ipic_icsr.inv = ipic_iinvr_ff[ipic_idxr_ff];
|
||||||
|
assign ipic_icsr.isv = ipic_isvr_ff [ipic_idxr_ff];
|
||||||
|
assign ipic_icsr.line = SCR1_IRQ_LINES_WIDTH'(ipic_idxr_ff);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Priority IRQ generation logic
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign irq_req_v = ipic_ipr_ff & ipic_ier_ff;
|
||||||
|
|
||||||
|
assign irr_priority = scr1_search_one_16(irq_req_v);
|
||||||
|
assign irq_req_vd = irr_priority.vd;
|
||||||
|
assign irq_req_idx = irr_priority.idx;
|
||||||
|
|
||||||
|
assign isvr_priority_eoi = scr1_search_one_16(ipic_isvr_eoi);
|
||||||
|
assign irq_eoi_req_vd = isvr_priority_eoi.vd;
|
||||||
|
assign irq_eoi_req_idx = isvr_priority_eoi.idx;
|
||||||
|
|
||||||
|
assign irq_hi_prior_pnd = irq_req_idx < irq_serv_idx;
|
||||||
|
|
||||||
|
assign ipic2csr_irq_m_req_o = irq_req_vd & (~irq_serv_vd | irq_hi_prior_pnd);
|
||||||
|
|
||||||
|
assign irq_start_vd = ipic2csr_irq_m_req_o & ipic_soi_req;
|
||||||
|
|
||||||
|
endmodule : scr1_ipic
|
||||||
|
|
||||||
|
`endif // SCR1_IPIC_EN
|
||||||
1169
src_ref/core/pipeline/scr1_pipe_csr.sv
Normal file
1169
src_ref/core/pipeline/scr1_pipe_csr.sv
Normal file
File diff suppressed because it is too large
Load Diff
1086
src_ref/core/pipeline/scr1_pipe_exu.sv
Normal file
1086
src_ref/core/pipeline/scr1_pipe_exu.sv
Normal file
File diff suppressed because it is too large
Load Diff
904
src_ref/core/pipeline/scr1_pipe_hdu.sv
Normal file
904
src_ref/core/pipeline/scr1_pipe_hdu.sv
Normal file
@@ -0,0 +1,904 @@
|
|||||||
|
/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
|
||||||
|
/// @file <scr1_pipe_hdu.sv>
|
||||||
|
/// @brief HART Debug Unit (HDU)
|
||||||
|
///
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Functionality:
|
||||||
|
// - Controls HART state (RUN, Debug RUN, Debug HALTED)
|
||||||
|
// - Setups Debug Mode execution
|
||||||
|
// - Provides status information about Debug Mode execution
|
||||||
|
// - Provides Program Buffer functionality (a few instructions execution while
|
||||||
|
// in Debug Mode)
|
||||||
|
// - Provides access to Debug CSRs
|
||||||
|
//
|
||||||
|
// Structure:
|
||||||
|
// - Debug state FSM
|
||||||
|
// - HART Control logic
|
||||||
|
// - HART Status logic
|
||||||
|
// - Program Buffer
|
||||||
|
// - Debug CSRs
|
||||||
|
// - HDU <-> DM interface
|
||||||
|
// - HDU <-> EXU interface
|
||||||
|
// - HDU <-> IFU interface
|
||||||
|
// - HDU <-> CSR interface
|
||||||
|
// - HDU <-> TDU interface
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
`include "scr1_arch_description.svh"
|
||||||
|
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
`include "scr1_arch_types.svh"
|
||||||
|
`include "scr1_riscv_isa_decoding.svh"
|
||||||
|
`include "scr1_hdu.svh"
|
||||||
|
|
||||||
|
module scr1_pipe_hdu #(parameter HART_PBUF_INSTR_REGOUT_EN = 1'b1) (
|
||||||
|
// Common signals
|
||||||
|
input logic rst_n, // HDU reset
|
||||||
|
input logic clk, // HDU clock
|
||||||
|
input logic clk_en, // HDU clock enable
|
||||||
|
`ifdef SCR1_CLKCTRL_EN
|
||||||
|
input logic clk_pipe_en, // Pipeline clock enable
|
||||||
|
`endif // SCR1_CLKCTRL_EN
|
||||||
|
input logic pipe2hdu_rdc_qlfy_i, // Pipeline RDC qualifier
|
||||||
|
|
||||||
|
// HDU <-> CSR i/f
|
||||||
|
input logic csr2hdu_req_i, // CSR i/f request
|
||||||
|
input type_scr1_csr_cmd_sel_e csr2hdu_cmd_i, // CSR i/f command
|
||||||
|
input logic [SCR1_HDU_DEBUGCSR_ADDR_WIDTH-1:0] csr2hdu_addr_i, // CSR i/f address
|
||||||
|
input logic [`SCR1_XLEN-1:0] csr2hdu_wdata_i, // CSR i/f write data
|
||||||
|
output type_scr1_csr_resp_e hdu2csr_resp_o, // CSR i/f response
|
||||||
|
output logic [`SCR1_XLEN-1:0] hdu2csr_rdata_o, // CSR i/f read data
|
||||||
|
|
||||||
|
// HDU <-> DM i/f
|
||||||
|
// HART Run Control i/f
|
||||||
|
input logic dm2hdu_cmd_req_i, // DM-HART Command request
|
||||||
|
input type_scr1_hdu_dbgstates_e dm2hdu_cmd_i, // DM-HART Command
|
||||||
|
output logic hdu2dm_cmd_resp_o, // DM-HART Command response
|
||||||
|
output logic hdu2dm_cmd_rcode_o, // DM-HART Command return code: 0 - Ok; 1 - Error
|
||||||
|
output logic hdu2dm_hart_event_o, // DM-HART Event: 1 if HART debug state changed
|
||||||
|
output type_scr1_hdu_hartstatus_s hdu2dm_hart_status_o, // DM-HART Status
|
||||||
|
|
||||||
|
// Program Buffer i/f
|
||||||
|
output logic [SCR1_HDU_PBUF_ADDR_WIDTH-1:0] hdu2dm_pbuf_addr_o, // Program Buffer address - so far request only for 1 instruction
|
||||||
|
input logic [SCR1_HDU_CORE_INSTR_WIDTH-1:0] dm2hdu_pbuf_instr_i, // Program Buffer instruction
|
||||||
|
|
||||||
|
// HART Abstract Data regs i/f
|
||||||
|
output logic hdu2dm_dreg_req_o, // Abstract Data Register request
|
||||||
|
output logic hdu2dm_dreg_wr_o, // Abstract Data Register write
|
||||||
|
output logic [`SCR1_XLEN-1:0] hdu2dm_dreg_wdata_o, // Abstract Data Register write data
|
||||||
|
input logic dm2hdu_dreg_resp_i, // Abstract Data Register response
|
||||||
|
input logic dm2hdu_dreg_fail_i, // Abstract Data Register fail
|
||||||
|
input logic [`SCR1_XLEN-1:0] dm2hdu_dreg_rdata_i, // Abstract Data Register read data
|
||||||
|
|
||||||
|
`ifdef SCR1_TDU_EN
|
||||||
|
// HDU <-> TDU interface
|
||||||
|
output logic hdu2tdu_hwbrk_dsbl_o, // Disables BRKM
|
||||||
|
input logic tdu2hdu_dmode_req_i, // Trigger Module requests transition to debug mode
|
||||||
|
input logic exu2hdu_ibrkpt_hw_i, // Hardware breakpoint on current instruction
|
||||||
|
`endif // SCR1_TDU_EN
|
||||||
|
|
||||||
|
// HART Run Status
|
||||||
|
input logic pipe2hdu_exu_busy_i, // EXU busy
|
||||||
|
input logic pipe2hdu_instret_i, // Instruction retired (with or without exception)
|
||||||
|
input logic pipe2hdu_init_pc_i, // Reset exit
|
||||||
|
|
||||||
|
// HART Halt Status
|
||||||
|
input logic pipe2hdu_exu_exc_req_i, // Exception request
|
||||||
|
input logic pipe2hdu_brkpt_i, // Software Breakpoint (EBREAK)
|
||||||
|
|
||||||
|
// HDU <-> EXU i/f
|
||||||
|
// HART Run Control
|
||||||
|
output logic hdu2exu_pbuf_fetch_o, // Fetch instruction from Program Buffer
|
||||||
|
output logic hdu2exu_no_commit_o, // Forbid instruction commitment
|
||||||
|
output logic hdu2exu_irq_dsbl_o, // Disable IRQ
|
||||||
|
output logic hdu2exu_pc_advmt_dsbl_o, // Forbid PC advancement
|
||||||
|
output logic hdu2exu_dmode_sstep_en_o, // Enable single-step
|
||||||
|
|
||||||
|
// HART state
|
||||||
|
output logic hdu2exu_dbg_halted_o, // Debug halted state
|
||||||
|
output logic hdu2exu_dbg_run2halt_o, // Transition to debug halted state
|
||||||
|
output logic hdu2exu_dbg_halt2run_o, // Transition to run state
|
||||||
|
output logic hdu2exu_dbg_run_start_o, // First cycle of run state
|
||||||
|
|
||||||
|
// PC interface
|
||||||
|
input logic [`SCR1_XLEN-1:0] pipe2hdu_pc_curr_i, // Current PC
|
||||||
|
output logic [`SCR1_XLEN-1:0] hdu2exu_dbg_new_pc_o, // New PC for resume
|
||||||
|
|
||||||
|
// HDU <-> IFU i/f
|
||||||
|
// Program Buffer Instruction interface
|
||||||
|
input logic ifu2hdu_pbuf_instr_rdy_i, // Program Buffer Instruction i/f ready
|
||||||
|
output logic hdu2ifu_pbuf_instr_vd_o, // Program Buffer Instruction valid
|
||||||
|
output logic hdu2ifu_pbuf_instr_err_o, // Program Buffer Instruction i/f error
|
||||||
|
output logic [SCR1_HDU_CORE_INSTR_WIDTH-1:0] hdu2ifu_pbuf_instr_o // Program Buffer Instruction itself
|
||||||
|
);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Local Parameters
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
localparam int unsigned SCR1_HDU_TIMEOUT = 64; // must be power of 2
|
||||||
|
localparam int unsigned SCR1_HDU_TIMEOUT_WIDTH = $clog2(SCR1_HDU_TIMEOUT);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Local Signals
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Debug FSM
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// FSM control signals
|
||||||
|
logic dm_dhalt_req;
|
||||||
|
logic dm_run_req;
|
||||||
|
|
||||||
|
logic dm_cmd_run;
|
||||||
|
logic dm_cmd_dhalted;
|
||||||
|
logic dm_cmd_drun;
|
||||||
|
|
||||||
|
// Debug state FSM signals
|
||||||
|
type_scr1_hdu_dbgstates_e dbg_state;
|
||||||
|
type_scr1_hdu_dbgstates_e dbg_state_next;
|
||||||
|
logic dbg_state_dhalted;
|
||||||
|
logic dbg_state_drun;
|
||||||
|
logic dbg_state_run;
|
||||||
|
logic dbg_state_reset;
|
||||||
|
|
||||||
|
// FSM transition, update and event registers
|
||||||
|
logic dfsm_trans;
|
||||||
|
logic dfsm_trans_next;
|
||||||
|
logic dfsm_update;
|
||||||
|
logic dfsm_update_next;
|
||||||
|
logic dfsm_event;
|
||||||
|
logic dfsm_event_next;
|
||||||
|
|
||||||
|
// HART Control signals
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
logic hart_resume_req;
|
||||||
|
logic hart_halt_req;
|
||||||
|
logic hart_cmd_req;
|
||||||
|
|
||||||
|
// HART Run Control register
|
||||||
|
logic hart_runctrl_upd;
|
||||||
|
logic hart_runctrl_clr;
|
||||||
|
type_scr1_hdu_runctrl_s hart_runctrl;
|
||||||
|
|
||||||
|
// HART halt request timeout counter signals
|
||||||
|
logic [SCR1_HDU_TIMEOUT_WIDTH-1:0] halt_req_timeout_cnt;
|
||||||
|
logic [SCR1_HDU_TIMEOUT_WIDTH-1:0] halt_req_timeout_cnt_next;
|
||||||
|
logic halt_req_timeout_cnt_en;
|
||||||
|
logic halt_req_timeout_flag;
|
||||||
|
|
||||||
|
// HART Status signals
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type_scr1_hdu_haltstatus_s hart_haltstatus;
|
||||||
|
type_scr1_hdu_haltcause_e hart_haltcause;
|
||||||
|
|
||||||
|
logic hart_halt_pnd;
|
||||||
|
logic hart_halt_ack;
|
||||||
|
|
||||||
|
// Debug mode cause decoder signals
|
||||||
|
logic dmode_cause_sstep;
|
||||||
|
logic dmode_cause_except;
|
||||||
|
logic dmode_cause_ebreak;
|
||||||
|
logic dmode_cause_any;
|
||||||
|
`ifdef SCR1_TDU_EN
|
||||||
|
logic dmode_cause_tmreq;
|
||||||
|
`endif // SCR1_TDU_EN
|
||||||
|
|
||||||
|
// Program Buffer FSM
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// PBUF FSM control signals
|
||||||
|
logic ifu_handshake_done;
|
||||||
|
logic pbuf_exc_inj_req;
|
||||||
|
logic pbuf_exc_inj_end;
|
||||||
|
logic pbuf_start_fetch;
|
||||||
|
|
||||||
|
// PBUF FSM signals
|
||||||
|
type_scr1_hdu_pbufstates_e pbuf_fsm_curr;
|
||||||
|
type_scr1_hdu_pbufstates_e pbuf_fsm_next;
|
||||||
|
logic pbuf_fsm_idle;
|
||||||
|
logic pbuf_fsm_fetch;
|
||||||
|
logic pbuf_fsm_excinj;
|
||||||
|
|
||||||
|
// PBUF address signals
|
||||||
|
logic [SCR1_HDU_PBUF_ADDR_WIDTH-1:0] pbuf_addr_ff;
|
||||||
|
logic [SCR1_HDU_PBUF_ADDR_WIDTH-1:0] pbuf_addr_next;
|
||||||
|
logic pbuf_addr_end;
|
||||||
|
logic pbuf_addr_next_vd;
|
||||||
|
|
||||||
|
logic pbuf_instr_wait_latching;
|
||||||
|
|
||||||
|
// Debugs CSRs
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// CSRs write/read interface signals
|
||||||
|
logic csr_upd_on_halt;
|
||||||
|
logic csr_wr;
|
||||||
|
logic [`SCR1_XLEN-1:0] csr_wr_data;
|
||||||
|
logic [`SCR1_XLEN-1:0] csr_rd_data;
|
||||||
|
|
||||||
|
// Debug Control and Status register (DCSR)
|
||||||
|
logic csr_dcsr_sel;
|
||||||
|
logic csr_dcsr_wr;
|
||||||
|
type_scr1_hdu_dcsr_s csr_dcsr_in;
|
||||||
|
type_scr1_hdu_dcsr_s csr_dcsr_out;
|
||||||
|
logic csr_dcsr_ebreakm;
|
||||||
|
logic csr_dcsr_stepie;
|
||||||
|
logic csr_dcsr_step;
|
||||||
|
logic [SCR1_HDU_DCSR_CAUSE_BIT_L-
|
||||||
|
SCR1_HDU_DCSR_CAUSE_BIT_R:0] csr_dcsr_cause;
|
||||||
|
|
||||||
|
// Debug Program Counter register (DPC)
|
||||||
|
logic csr_dpc_sel;
|
||||||
|
logic csr_dpc_wr;
|
||||||
|
logic [`SCR1_XLEN-1:0] csr_dpc_ff;
|
||||||
|
logic [`SCR1_XLEN-1:0] csr_dpc_next;
|
||||||
|
logic [`SCR1_XLEN-1:0] csr_dpc_out;
|
||||||
|
|
||||||
|
// Debug Scratch register 0 (DSCRATCH0)
|
||||||
|
logic csr_addr_dscratch0;
|
||||||
|
logic csr_dscratch0_sel;
|
||||||
|
logic csr_dscratch0_wr;
|
||||||
|
logic [`SCR1_XLEN-1:0] csr_dscratch0_out;
|
||||||
|
type_scr1_csr_resp_e csr_dscratch0_resp;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Debug state FSM logic
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Debug state FSM logic consists of the following functional units:
|
||||||
|
// - FSM control logic
|
||||||
|
// - Debug state FSM
|
||||||
|
// - FSM transition, update and event registers
|
||||||
|
//
|
||||||
|
|
||||||
|
// FSM control logic
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign dm_cmd_dhalted = (dm2hdu_cmd_i == SCR1_HDU_DBGSTATE_DHALTED);
|
||||||
|
assign dm_cmd_run = (dm2hdu_cmd_i == SCR1_HDU_DBGSTATE_RUN);
|
||||||
|
assign dm_cmd_drun = (dm2hdu_cmd_i == SCR1_HDU_DBGSTATE_DRUN);
|
||||||
|
|
||||||
|
assign dm_dhalt_req = dm2hdu_cmd_req_i & dm_cmd_dhalted;
|
||||||
|
assign dm_run_req = dm2hdu_cmd_req_i & (dm_cmd_run | dm_cmd_drun);
|
||||||
|
|
||||||
|
// Debug state FSM
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
always_ff @(negedge rst_n, posedge clk) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
dbg_state <= SCR1_HDU_DBGSTATE_RESET;
|
||||||
|
end else begin
|
||||||
|
dbg_state <= dbg_state_next;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
if (~pipe2hdu_rdc_qlfy_i) begin
|
||||||
|
dbg_state_next = SCR1_HDU_DBGSTATE_RESET;
|
||||||
|
end else begin
|
||||||
|
case (dbg_state)
|
||||||
|
SCR1_HDU_DBGSTATE_RESET: begin
|
||||||
|
dbg_state_next = ~pipe2hdu_init_pc_i ? SCR1_HDU_DBGSTATE_RESET
|
||||||
|
: dm_dhalt_req ? SCR1_HDU_DBGSTATE_DHALTED
|
||||||
|
: SCR1_HDU_DBGSTATE_RUN;
|
||||||
|
end
|
||||||
|
SCR1_HDU_DBGSTATE_RUN: begin
|
||||||
|
dbg_state_next = dfsm_update ? SCR1_HDU_DBGSTATE_DHALTED
|
||||||
|
: SCR1_HDU_DBGSTATE_RUN;
|
||||||
|
end
|
||||||
|
SCR1_HDU_DBGSTATE_DHALTED: begin
|
||||||
|
dbg_state_next = ~dfsm_update ? SCR1_HDU_DBGSTATE_DHALTED
|
||||||
|
: dm_cmd_drun ? SCR1_HDU_DBGSTATE_DRUN
|
||||||
|
: SCR1_HDU_DBGSTATE_RUN;
|
||||||
|
end
|
||||||
|
SCR1_HDU_DBGSTATE_DRUN: begin
|
||||||
|
dbg_state_next = dfsm_update ? SCR1_HDU_DBGSTATE_DHALTED
|
||||||
|
: SCR1_HDU_DBGSTATE_DRUN;
|
||||||
|
end
|
||||||
|
default: begin
|
||||||
|
`ifdef SCR1_XPROP_EN
|
||||||
|
dbg_state_next = SCR1_HDU_DBGSTATE_XXX;
|
||||||
|
`else // SCR1_XPROP_EN
|
||||||
|
dbg_state_next = dbg_state;
|
||||||
|
`endif // SCR1_XPROP_EN
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign dbg_state_dhalted = (dbg_state == SCR1_HDU_DBGSTATE_DHALTED);
|
||||||
|
assign dbg_state_drun = (dbg_state == SCR1_HDU_DBGSTATE_DRUN);
|
||||||
|
assign dbg_state_run = (dbg_state == SCR1_HDU_DBGSTATE_RUN);
|
||||||
|
assign dbg_state_reset = (dbg_state == SCR1_HDU_DBGSTATE_RESET);
|
||||||
|
|
||||||
|
// FSM transition, update and event registers
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
always_ff @(negedge rst_n, posedge clk) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
dfsm_trans <= 1'b0;
|
||||||
|
dfsm_update <= 1'b0;
|
||||||
|
dfsm_event <= 1'b0;
|
||||||
|
end else begin
|
||||||
|
dfsm_trans <= dfsm_trans_next;
|
||||||
|
dfsm_update <= dfsm_update_next;
|
||||||
|
dfsm_event <= dfsm_event_next;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
dfsm_trans_next = 1'b0;
|
||||||
|
dfsm_update_next = 1'b0;
|
||||||
|
dfsm_event_next = 1'b0;
|
||||||
|
|
||||||
|
if (~pipe2hdu_rdc_qlfy_i) begin
|
||||||
|
dfsm_trans_next = 1'b0;
|
||||||
|
dfsm_update_next = 1'b0;
|
||||||
|
dfsm_event_next = 1'b1;
|
||||||
|
end else begin
|
||||||
|
case (dbg_state)
|
||||||
|
SCR1_HDU_DBGSTATE_RESET: begin
|
||||||
|
dfsm_trans_next = 1'b0;
|
||||||
|
dfsm_update_next = 1'b0;
|
||||||
|
dfsm_event_next = pipe2hdu_init_pc_i & ~dm2hdu_cmd_req_i;
|
||||||
|
end
|
||||||
|
|
||||||
|
SCR1_HDU_DBGSTATE_RUN,
|
||||||
|
SCR1_HDU_DBGSTATE_DRUN: begin
|
||||||
|
dfsm_trans_next = ~dfsm_update ? hart_halt_pnd : dfsm_trans;
|
||||||
|
dfsm_update_next = ~dfsm_update & hart_halt_ack;
|
||||||
|
dfsm_event_next = dfsm_update;
|
||||||
|
end
|
||||||
|
|
||||||
|
SCR1_HDU_DBGSTATE_DHALTED: begin
|
||||||
|
dfsm_trans_next = ~dfsm_update ? ~dfsm_trans & dm_run_req
|
||||||
|
: dfsm_trans;
|
||||||
|
dfsm_update_next = ~dfsm_update & dfsm_trans;
|
||||||
|
dfsm_event_next = dfsm_update;
|
||||||
|
end
|
||||||
|
|
||||||
|
default : begin
|
||||||
|
dfsm_trans_next = 'X;
|
||||||
|
dfsm_update_next = 'X;
|
||||||
|
dfsm_event_next = 'X;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// HART Control logic
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// HART Control logic consists of the following functional units:
|
||||||
|
// - Control signals
|
||||||
|
// - HART Run Control register
|
||||||
|
// - HART Halt Request Time-Out counter
|
||||||
|
//
|
||||||
|
|
||||||
|
// Control logic
|
||||||
|
always_comb begin
|
||||||
|
hart_cmd_req = 1'b0;
|
||||||
|
|
||||||
|
if (~pipe2hdu_rdc_qlfy_i) begin
|
||||||
|
hart_cmd_req = 1'b0;
|
||||||
|
end else begin
|
||||||
|
case (dbg_state)
|
||||||
|
SCR1_HDU_DBGSTATE_RESET : hart_cmd_req = dm2hdu_cmd_req_i;
|
||||||
|
SCR1_HDU_DBGSTATE_DHALTED: hart_cmd_req = (dfsm_update | dfsm_trans);
|
||||||
|
SCR1_HDU_DBGSTATE_RUN,
|
||||||
|
SCR1_HDU_DBGSTATE_DRUN : hart_cmd_req = ~dfsm_update & dfsm_trans;
|
||||||
|
default : hart_cmd_req = 'X;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign hart_halt_req = dm_cmd_dhalted & hart_cmd_req;
|
||||||
|
assign hart_resume_req = (dm_cmd_run | dm_cmd_drun) & hart_cmd_req;
|
||||||
|
|
||||||
|
// HART Run Control register
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign hart_runctrl_clr = (dbg_state_run | dbg_state_drun)
|
||||||
|
& (dbg_state_next == SCR1_HDU_DBGSTATE_DHALTED);
|
||||||
|
assign hart_runctrl_upd = dbg_state_dhalted & dfsm_trans_next;
|
||||||
|
|
||||||
|
always_ff @(negedge rst_n, posedge clk) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
hart_runctrl.irq_dsbl <= 1'b0;
|
||||||
|
hart_runctrl.fetch_src <= SCR1_HDU_FETCH_SRC_NORMAL;
|
||||||
|
hart_runctrl.pc_advmt_dsbl <= 1'b0;
|
||||||
|
hart_runctrl.hwbrkpt_dsbl <= 1'b0;
|
||||||
|
hart_runctrl.redirect <= '0;
|
||||||
|
end else if(clk_en) begin
|
||||||
|
if (hart_runctrl_clr) begin
|
||||||
|
hart_runctrl <= '0;
|
||||||
|
end else begin
|
||||||
|
if (hart_runctrl_upd) begin
|
||||||
|
if (~dm_cmd_drun) begin
|
||||||
|
// Case : resume to RUN state
|
||||||
|
hart_runctrl.irq_dsbl <= csr_dcsr_step ? ~csr_dcsr_stepie : 1'b0;
|
||||||
|
hart_runctrl.fetch_src <= SCR1_HDU_FETCH_SRC_NORMAL;
|
||||||
|
hart_runctrl.pc_advmt_dsbl <= 1'b0;
|
||||||
|
hart_runctrl.hwbrkpt_dsbl <= 1'b0;
|
||||||
|
hart_runctrl.redirect.sstep <= csr_dcsr_step;
|
||||||
|
hart_runctrl.redirect.ebreak <= csr_dcsr_ebreakm;
|
||||||
|
end else begin
|
||||||
|
// Case : resume to DRUN state
|
||||||
|
hart_runctrl.irq_dsbl <= 1'b1;
|
||||||
|
hart_runctrl.fetch_src <= SCR1_HDU_FETCH_SRC_PBUF;
|
||||||
|
hart_runctrl.pc_advmt_dsbl <= 1'b1;
|
||||||
|
hart_runctrl.hwbrkpt_dsbl <= 1'b1;
|
||||||
|
hart_runctrl.redirect.sstep <= 1'b0;
|
||||||
|
hart_runctrl.redirect.ebreak <= 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// HART Halt Request Time-Out counter
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// HART goes into halt state only if the halt request is present for timeout period
|
||||||
|
// of time
|
||||||
|
|
||||||
|
assign halt_req_timeout_cnt_en = hdu2exu_dbg_halt2run_o
|
||||||
|
| (hart_halt_req & ~hdu2exu_dbg_run2halt_o);
|
||||||
|
|
||||||
|
always_ff @(posedge clk, negedge rst_n) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
halt_req_timeout_cnt <= '1;
|
||||||
|
end else if (halt_req_timeout_cnt_en) begin
|
||||||
|
halt_req_timeout_cnt <= halt_req_timeout_cnt_next;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign halt_req_timeout_cnt_next = hdu2exu_dbg_halt2run_o ? '1
|
||||||
|
: (hart_halt_req & ~hdu2exu_dbg_run2halt_o) ? halt_req_timeout_cnt - 1'b1
|
||||||
|
: halt_req_timeout_cnt;
|
||||||
|
|
||||||
|
assign halt_req_timeout_flag = ~|halt_req_timeout_cnt;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// HART Status logic
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// HART Status logic consists of the following functional units:
|
||||||
|
// - Debug mode cause decoder
|
||||||
|
// - Hart halt status cause encoder
|
||||||
|
// - Hart halt status register
|
||||||
|
//
|
||||||
|
|
||||||
|
// Debug mode cause decoder
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign dmode_cause_sstep = hart_runctrl.redirect.sstep & pipe2hdu_instret_i;
|
||||||
|
assign dmode_cause_except = dbg_state_drun & pipe2hdu_exu_exc_req_i
|
||||||
|
& ~pipe2hdu_brkpt_i
|
||||||
|
`ifdef SCR1_TDU_EN
|
||||||
|
& ~exu2hdu_ibrkpt_hw_i
|
||||||
|
`endif // SCR1_TDU_EN
|
||||||
|
;
|
||||||
|
assign dmode_cause_ebreak = hart_runctrl.redirect.ebreak & pipe2hdu_brkpt_i;
|
||||||
|
`ifdef SCR1_TDU_EN
|
||||||
|
assign dmode_cause_tmreq = tdu2hdu_dmode_req_i & exu2hdu_ibrkpt_hw_i;
|
||||||
|
`endif // SCR1_TDU_EN
|
||||||
|
|
||||||
|
assign dmode_cause_any = dmode_cause_sstep | dmode_cause_ebreak | dmode_cause_except
|
||||||
|
| hart_halt_req
|
||||||
|
`ifdef SCR1_TDU_EN
|
||||||
|
| dmode_cause_tmreq
|
||||||
|
`endif // SCR1_TDU_EN
|
||||||
|
;
|
||||||
|
|
||||||
|
// HART halt cause encoder
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
case (1'b1)
|
||||||
|
`ifdef SCR1_TDU_EN
|
||||||
|
dmode_cause_tmreq : hart_haltcause = SCR1_HDU_HALTCAUSE_TMREQ;
|
||||||
|
`endif // SCR1_TDU_EN
|
||||||
|
dmode_cause_ebreak : hart_haltcause = SCR1_HDU_HALTCAUSE_EBREAK;
|
||||||
|
hart_halt_req : hart_haltcause = SCR1_HDU_HALTCAUSE_DMREQ;
|
||||||
|
dmode_cause_sstep : hart_haltcause = SCR1_HDU_HALTCAUSE_SSTEP;
|
||||||
|
default : hart_haltcause = SCR1_HDU_HALTCAUSE_NONE;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
// HART halt status register
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
always_ff @(posedge clk, negedge rst_n) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
hart_haltstatus <= '0;
|
||||||
|
end else if (hart_halt_ack) begin
|
||||||
|
hart_haltstatus.except <= dmode_cause_except;
|
||||||
|
hart_haltstatus.cause <= hart_haltcause;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign hart_halt_pnd = (dfsm_trans | dm_dhalt_req) & ~hart_halt_ack;
|
||||||
|
assign hart_halt_ack = ~hdu2exu_dbg_halted_o
|
||||||
|
& (halt_req_timeout_flag | (~pipe2hdu_exu_busy_i & dmode_cause_any));
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Program Buffer (PBUF) logic
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Program Buffer allows to execute small programs in debug mode
|
||||||
|
//
|
||||||
|
|
||||||
|
// To terminate Program Buffer execution exception should be raised. There are 2
|
||||||
|
// cases:
|
||||||
|
// - One of PBUF instructions raise an exception
|
||||||
|
// - No PBUF instruction raise an exception before the last PBUF instruction has
|
||||||
|
// been issued. In this case FSM goes into EXCINJECT state and an "Instruction
|
||||||
|
// fetch access fault" exception is injected
|
||||||
|
|
||||||
|
// PBUF FSM
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign ifu_handshake_done = hdu2ifu_pbuf_instr_vd_o & ifu2hdu_pbuf_instr_rdy_i;
|
||||||
|
assign pbuf_addr_end = (pbuf_addr_ff == (SCR1_HDU_PBUF_ADDR_SPAN-1));
|
||||||
|
|
||||||
|
assign pbuf_start_fetch = dbg_state_dhalted & (dbg_state_next == SCR1_HDU_DBGSTATE_DRUN);
|
||||||
|
assign pbuf_exc_inj_req = ifu_handshake_done & pbuf_addr_end;
|
||||||
|
assign pbuf_exc_inj_end = pipe2hdu_exu_exc_req_i | ifu_handshake_done;
|
||||||
|
|
||||||
|
always_ff @(negedge rst_n, posedge clk) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
pbuf_fsm_curr <= SCR1_HDU_PBUFSTATE_IDLE;
|
||||||
|
end else if(clk_en) begin
|
||||||
|
pbuf_fsm_curr <= pbuf_fsm_next;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
case (pbuf_fsm_curr)
|
||||||
|
SCR1_HDU_PBUFSTATE_IDLE: begin
|
||||||
|
pbuf_fsm_next = pbuf_start_fetch ? SCR1_HDU_PBUFSTATE_FETCH
|
||||||
|
: SCR1_HDU_PBUFSTATE_IDLE;
|
||||||
|
end
|
||||||
|
SCR1_HDU_PBUFSTATE_FETCH: begin
|
||||||
|
pbuf_fsm_next = pipe2hdu_exu_exc_req_i ? SCR1_HDU_PBUFSTATE_WAIT4END
|
||||||
|
: pbuf_exc_inj_req ? SCR1_HDU_PBUFSTATE_EXCINJECT
|
||||||
|
: SCR1_HDU_PBUFSTATE_FETCH;
|
||||||
|
end
|
||||||
|
SCR1_HDU_PBUFSTATE_EXCINJECT: begin
|
||||||
|
pbuf_fsm_next = pbuf_exc_inj_end ? SCR1_HDU_PBUFSTATE_WAIT4END
|
||||||
|
: SCR1_HDU_PBUFSTATE_EXCINJECT;
|
||||||
|
end
|
||||||
|
SCR1_HDU_PBUFSTATE_WAIT4END: begin
|
||||||
|
pbuf_fsm_next = hdu2exu_dbg_halted_o ? SCR1_HDU_PBUFSTATE_IDLE
|
||||||
|
: SCR1_HDU_PBUFSTATE_WAIT4END;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
assign pbuf_fsm_idle = (pbuf_fsm_curr == SCR1_HDU_PBUFSTATE_IDLE);
|
||||||
|
assign pbuf_fsm_fetch = (pbuf_fsm_curr == SCR1_HDU_PBUFSTATE_FETCH);
|
||||||
|
assign pbuf_fsm_excinj = (pbuf_fsm_curr == SCR1_HDU_PBUFSTATE_EXCINJECT);
|
||||||
|
|
||||||
|
// Program Buffer address register
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign pbuf_addr_next_vd = pbuf_fsm_fetch & ifu_handshake_done
|
||||||
|
& ~pipe2hdu_exu_exc_req_i & ~pbuf_addr_end;
|
||||||
|
|
||||||
|
always_ff @(negedge rst_n, posedge clk) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
pbuf_addr_ff <= '0;
|
||||||
|
end else if(clk_en) begin
|
||||||
|
pbuf_addr_ff <= pbuf_addr_next;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign pbuf_addr_next = pbuf_fsm_idle ? '0
|
||||||
|
: pbuf_addr_next_vd ? pbuf_addr_ff + 1'b1
|
||||||
|
: pbuf_addr_ff;
|
||||||
|
|
||||||
|
// Pass instruction from debug program buffer to cpu pipeline with two options:
|
||||||
|
// - through register, better for frequency
|
||||||
|
// - through wires, better for area
|
||||||
|
generate if (HART_PBUF_INSTR_REGOUT_EN) begin
|
||||||
|
always_ff @(posedge clk, negedge rst_n) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
pbuf_instr_wait_latching <= 1'b0;
|
||||||
|
end else begin
|
||||||
|
pbuf_instr_wait_latching <= ifu_handshake_done;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end else begin
|
||||||
|
assign pbuf_instr_wait_latching = 1'b0;
|
||||||
|
end endgenerate
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Debug CSRs
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign csr_upd_on_halt = (dbg_state_reset | dbg_state_run)
|
||||||
|
& (dbg_state_next == SCR1_HDU_DBGSTATE_DHALTED);
|
||||||
|
|
||||||
|
// CSRs select logic
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
always_comb begin : csr_if_regsel
|
||||||
|
csr_dcsr_sel = 1'b0;
|
||||||
|
csr_dpc_sel = 1'b0;
|
||||||
|
csr_dscratch0_sel = 1'b0;
|
||||||
|
//csr_dscratch1_sel = 1'b0;
|
||||||
|
|
||||||
|
if (csr2hdu_req_i) begin
|
||||||
|
case (csr2hdu_addr_i)
|
||||||
|
SCR1_HDU_DBGCSR_OFFS_DCSR : csr_dcsr_sel = 1'b1;
|
||||||
|
SCR1_HDU_DBGCSR_OFFS_DPC : csr_dpc_sel = 1'b1;
|
||||||
|
SCR1_HDU_DBGCSR_OFFS_DSCRATCH0: csr_dscratch0_sel = 1'b1;
|
||||||
|
default : begin
|
||||||
|
csr_dcsr_sel = 1'bX;
|
||||||
|
csr_dpc_sel = 1'bX;
|
||||||
|
csr_dscratch0_sel = 1'bX;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end : csr_if_regsel
|
||||||
|
|
||||||
|
// CSRs read interface
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign csr_rd_data = csr_dcsr_out | csr_dpc_out | csr_dscratch0_out;
|
||||||
|
|
||||||
|
// CSRs write interface
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign csr_wr = csr2hdu_req_i;
|
||||||
|
|
||||||
|
always_comb begin : csr_if_write
|
||||||
|
csr_wr_data = '0;
|
||||||
|
|
||||||
|
if (csr2hdu_req_i) begin
|
||||||
|
case (csr2hdu_cmd_i)
|
||||||
|
SCR1_CSR_CMD_WRITE : csr_wr_data = csr2hdu_wdata_i;
|
||||||
|
SCR1_CSR_CMD_SET : csr_wr_data = csr_rd_data | csr2hdu_wdata_i;
|
||||||
|
SCR1_CSR_CMD_CLEAR : csr_wr_data = csr_rd_data & (~csr2hdu_wdata_i);
|
||||||
|
default : csr_wr_data = 'X;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end : csr_if_write
|
||||||
|
|
||||||
|
// Debug Control and Status register
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Setups the HART behaviour in Debug Mode and holds Debug status information
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
csr_dcsr_in = csr_wr_data;
|
||||||
|
csr_dcsr_wr = csr_wr & csr_dcsr_sel;
|
||||||
|
|
||||||
|
csr_dcsr_out = '0;
|
||||||
|
if (csr_dcsr_sel) begin
|
||||||
|
csr_dcsr_out.xdebugver = SCR1_HDU_DEBUGCSR_DCSR_XDEBUGVER;
|
||||||
|
csr_dcsr_out.ebreakm = csr_dcsr_ebreakm;
|
||||||
|
csr_dcsr_out.stepie = csr_dcsr_stepie;
|
||||||
|
csr_dcsr_out.step = csr_dcsr_step;
|
||||||
|
csr_dcsr_out.prv = 2'b11;
|
||||||
|
csr_dcsr_out.cause = csr_dcsr_cause;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_ff @(negedge rst_n, posedge clk) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
csr_dcsr_ebreakm <= 1'b0;
|
||||||
|
csr_dcsr_stepie <= 1'b0;
|
||||||
|
csr_dcsr_step <= 1'b0;
|
||||||
|
end else if(clk_en) begin
|
||||||
|
if (csr_dcsr_wr) begin
|
||||||
|
csr_dcsr_ebreakm <= csr_dcsr_in.ebreakm;
|
||||||
|
csr_dcsr_stepie <= csr_dcsr_in.stepie;
|
||||||
|
csr_dcsr_step <= csr_dcsr_in.step;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_ff @(negedge rst_n, posedge clk) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
csr_dcsr_cause <= 1'b0;
|
||||||
|
end else if(clk_en) begin
|
||||||
|
if(csr_upd_on_halt) begin
|
||||||
|
csr_dcsr_cause <= hart_haltstatus.cause;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// Debug PC register
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Saves the virtual address of the next instruction to be executed when Debug
|
||||||
|
// Mode is entered. Could be changed by debugger
|
||||||
|
|
||||||
|
assign csr_dpc_wr = csr_wr & csr_dpc_sel;
|
||||||
|
|
||||||
|
always_ff @(posedge clk, negedge rst_n) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
csr_dpc_ff <= '0;
|
||||||
|
end else if(clk_en) begin
|
||||||
|
csr_dpc_ff <= csr_dpc_next;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign csr_dpc_next = csr_upd_on_halt ? pipe2hdu_pc_curr_i
|
||||||
|
: csr_dpc_wr ? csr_wr_data
|
||||||
|
: csr_dpc_ff;
|
||||||
|
assign csr_dpc_out = csr_dpc_sel ? csr_dpc_ff : '0;
|
||||||
|
|
||||||
|
// Debug Scratch 0 register
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign csr_dscratch0_resp = (~dm2hdu_dreg_resp_i | dm2hdu_dreg_fail_i)
|
||||||
|
? SCR1_CSR_RESP_ER
|
||||||
|
: SCR1_CSR_RESP_OK;
|
||||||
|
assign csr_dscratch0_out = csr_dscratch0_sel ? dm2hdu_dreg_rdata_i : '0;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// HDU <-> DM interface
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign hdu2dm_hart_event_o = dfsm_event;
|
||||||
|
|
||||||
|
// HART status
|
||||||
|
always_comb begin
|
||||||
|
hdu2dm_hart_status_o = '0;
|
||||||
|
hdu2dm_hart_status_o.dbg_state = dbg_state;
|
||||||
|
hdu2dm_hart_status_o.except = dbg_state_dhalted & hart_haltstatus.except;
|
||||||
|
hdu2dm_hart_status_o.ebreak = dbg_state_dhalted & (hart_haltstatus.cause == SCR1_HDU_HALTCAUSE_EBREAK);
|
||||||
|
end
|
||||||
|
|
||||||
|
assign hdu2dm_cmd_rcode_o = dbg_state_reset
|
||||||
|
? ~pipe2hdu_rdc_qlfy_i | ~pipe2hdu_init_pc_i | ~dm2hdu_cmd_req_i
|
||||||
|
: ~pipe2hdu_rdc_qlfy_i | ~dfsm_update;
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
hdu2dm_cmd_resp_o = 1'b0;
|
||||||
|
|
||||||
|
case (dbg_state)
|
||||||
|
SCR1_HDU_DBGSTATE_RESET: begin
|
||||||
|
hdu2dm_cmd_resp_o = pipe2hdu_rdc_qlfy_i & pipe2hdu_init_pc_i & dm2hdu_cmd_req_i;
|
||||||
|
end
|
||||||
|
|
||||||
|
SCR1_HDU_DBGSTATE_RUN: begin
|
||||||
|
hdu2dm_cmd_resp_o = pipe2hdu_rdc_qlfy_i & dfsm_update & dm2hdu_cmd_req_i;
|
||||||
|
end
|
||||||
|
|
||||||
|
SCR1_HDU_DBGSTATE_DHALTED: begin
|
||||||
|
hdu2dm_cmd_resp_o = pipe2hdu_rdc_qlfy_i ? dfsm_update : dm2hdu_cmd_req_i;
|
||||||
|
end
|
||||||
|
|
||||||
|
SCR1_HDU_DBGSTATE_DRUN: begin
|
||||||
|
hdu2dm_cmd_resp_o = (~pipe2hdu_rdc_qlfy_i | dfsm_update) & dm2hdu_cmd_req_i;
|
||||||
|
end
|
||||||
|
|
||||||
|
default: begin
|
||||||
|
hdu2dm_cmd_resp_o = 'X;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
assign hdu2dm_pbuf_addr_o = pbuf_addr_ff;
|
||||||
|
assign hdu2dm_dreg_req_o = csr_dscratch0_sel;
|
||||||
|
assign hdu2dm_dreg_wr_o = csr_wr & csr_dscratch0_sel;
|
||||||
|
assign hdu2dm_dreg_wdata_o = csr_wr_data;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// HDU <-> EXU interface
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign hdu2exu_dbg_halted_o = (dbg_state_next == SCR1_HDU_DBGSTATE_DHALTED)
|
||||||
|
| (~pipe2hdu_rdc_qlfy_i & ~dbg_state_run);
|
||||||
|
assign hdu2exu_dbg_run_start_o = dbg_state_dhalted & pipe2hdu_rdc_qlfy_i & dfsm_update;
|
||||||
|
assign hdu2exu_dbg_halt2run_o = hdu2exu_dbg_halted_o & hart_resume_req
|
||||||
|
`ifdef SCR1_CLKCTRL_EN
|
||||||
|
& clk_pipe_en
|
||||||
|
`endif // SCR1_CLKCTRL_EN
|
||||||
|
;
|
||||||
|
assign hdu2exu_dbg_run2halt_o = hart_halt_ack;
|
||||||
|
|
||||||
|
assign hdu2exu_pbuf_fetch_o = hart_runctrl.fetch_src;
|
||||||
|
assign hdu2exu_irq_dsbl_o = hart_runctrl.irq_dsbl;
|
||||||
|
assign hdu2exu_pc_advmt_dsbl_o = hart_runctrl.pc_advmt_dsbl;
|
||||||
|
// No change in arch. state if dmode caused by breakpoint
|
||||||
|
assign hdu2exu_no_commit_o = dmode_cause_ebreak
|
||||||
|
`ifdef SCR1_TDU_EN
|
||||||
|
| dmode_cause_tmreq
|
||||||
|
`endif // SCR1_TDU_EN
|
||||||
|
;
|
||||||
|
assign hdu2exu_dmode_sstep_en_o = hart_runctrl.redirect.sstep;
|
||||||
|
assign hdu2exu_dbg_new_pc_o = csr_dpc_ff;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// HDU <-> IFU interface
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign hdu2ifu_pbuf_instr_vd_o = (pbuf_fsm_fetch | pbuf_fsm_excinj)
|
||||||
|
& ~pbuf_instr_wait_latching;
|
||||||
|
assign hdu2ifu_pbuf_instr_err_o = pbuf_fsm_excinj;
|
||||||
|
|
||||||
|
generate if (HART_PBUF_INSTR_REGOUT_EN) begin
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
hdu2ifu_pbuf_instr_o <= dm2hdu_pbuf_instr_i;
|
||||||
|
end
|
||||||
|
end else begin
|
||||||
|
assign hdu2ifu_pbuf_instr_o = dm2hdu_pbuf_instr_i;
|
||||||
|
end endgenerate
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// HDU <-> CSR interface
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign csr_addr_dscratch0 = (csr2hdu_addr_i == SCR1_HDU_DBGCSR_OFFS_DSCRATCH0);
|
||||||
|
|
||||||
|
assign hdu2csr_resp_o = ~dbg_state_drun ? SCR1_CSR_RESP_ER
|
||||||
|
: csr_addr_dscratch0 ? csr_dscratch0_resp
|
||||||
|
: csr2hdu_req_i ? SCR1_CSR_RESP_OK
|
||||||
|
: SCR1_CSR_RESP_ER;
|
||||||
|
assign hdu2csr_rdata_o = csr_rd_data;
|
||||||
|
|
||||||
|
`ifdef SCR1_TDU_EN
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// HDU <-> TDU interface
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign hdu2tdu_hwbrk_dsbl_o = hart_runctrl.hwbrkpt_dsbl;
|
||||||
|
`endif // SCR1_TDU_EN
|
||||||
|
|
||||||
|
`ifdef SCR1_TRGT_SIMULATION
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Assertion
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
SVA_HDU_XCHECK_COMMON :
|
||||||
|
assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
!$isunknown( {rst_n,clk,clk_en,csr2hdu_req_i,pipe2hdu_rdc_qlfy_i} )
|
||||||
|
)
|
||||||
|
else $error("HDU Error: common signals are in X state");
|
||||||
|
|
||||||
|
SVA_HDU_XCHECK_CSR_INTF :
|
||||||
|
assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
csr2hdu_req_i |-> !$isunknown( {csr2hdu_cmd_i,csr2hdu_addr_i,csr2hdu_wdata_i} )
|
||||||
|
)
|
||||||
|
else $error("HDU Error: CSR i/f is in X state");
|
||||||
|
|
||||||
|
SVA_HDU_XCHECK_DM_INTF :
|
||||||
|
assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
!$isunknown( {dm2hdu_cmd_req_i,dm2hdu_cmd_i,dm2hdu_dreg_resp_i,
|
||||||
|
dm2hdu_dreg_fail_i} )
|
||||||
|
)
|
||||||
|
else $error("HDU Error: DM i/f is in X state");
|
||||||
|
|
||||||
|
SVA_HDU_XCHECK_TDU_INTF :
|
||||||
|
assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
!$isunknown( {tdu2hdu_dmode_req_i,exu2hdu_ibrkpt_hw_i} )
|
||||||
|
)
|
||||||
|
else $error("HDU Error: TDU i/f is in X state");
|
||||||
|
|
||||||
|
SVA_HDU_XCHECK_HART_INTF :
|
||||||
|
assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
!$isunknown( {pipe2hdu_exu_busy_i,pipe2hdu_instret_i,pipe2hdu_init_pc_i,pipe2hdu_exu_exc_req_i,pipe2hdu_brkpt_i,
|
||||||
|
pipe2hdu_pc_curr_i,ifu2hdu_pbuf_instr_rdy_i} )
|
||||||
|
)
|
||||||
|
else $error("HDU Error: HART i/f is in X state");
|
||||||
|
|
||||||
|
`endif // SCR1_TRGT_SIMULATION
|
||||||
|
|
||||||
|
endmodule : scr1_pipe_hdu
|
||||||
|
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
720
src_ref/core/pipeline/scr1_pipe_ialu.sv
Normal file
720
src_ref/core/pipeline/scr1_pipe_ialu.sv
Normal file
@@ -0,0 +1,720 @@
|
|||||||
|
/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
|
||||||
|
/// @file <scr1_pipe_ialu.sv>
|
||||||
|
/// @brief Integer Arithmetic Logic Unit (IALU)
|
||||||
|
///
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Functionality:
|
||||||
|
// - Performs addition/subtraction and arithmetic and branch comparisons
|
||||||
|
// - Performs logical operations (AND(I), OR(I), XOR(I))
|
||||||
|
// - Performs address calculation for branch, jump, DMEM load and store and AUIPC
|
||||||
|
// instructions
|
||||||
|
// - Performs shift operations
|
||||||
|
// - Performs MUL/DIV operations
|
||||||
|
//
|
||||||
|
// Structure:
|
||||||
|
// - Main adder
|
||||||
|
// - Address adder
|
||||||
|
// - Shift logic
|
||||||
|
// - MUL/DIV logic
|
||||||
|
// - Output result multiplexer
|
||||||
|
//
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
`include "scr1_arch_description.svh"
|
||||||
|
`include "scr1_riscv_isa_decoding.svh"
|
||||||
|
`include "scr1_search_ms1.svh"
|
||||||
|
|
||||||
|
|
||||||
|
module scr1_pipe_ialu (
|
||||||
|
`ifdef SCR1_RVM_EXT
|
||||||
|
// Common
|
||||||
|
input logic clk, // IALU clock
|
||||||
|
input logic rst_n, // IALU reset
|
||||||
|
input logic exu2ialu_rvm_cmd_vd_i, // MUL/DIV command valid
|
||||||
|
output logic ialu2exu_rvm_res_rdy_o, // MUL/DIV result ready
|
||||||
|
`endif // SCR1_RVM_EXT
|
||||||
|
|
||||||
|
// Main adder
|
||||||
|
input logic [`SCR1_XLEN-1:0] exu2ialu_main_op1_i, // main ALU 1st operand
|
||||||
|
input logic [`SCR1_XLEN-1:0] exu2ialu_main_op2_i, // main ALU 2nd operand
|
||||||
|
input type_scr1_ialu_cmd_sel_e exu2ialu_cmd_i, // IALU command
|
||||||
|
output logic [`SCR1_XLEN-1:0] ialu2exu_main_res_o, // main ALU result
|
||||||
|
output logic ialu2exu_cmp_res_o, // IALU comparison result
|
||||||
|
|
||||||
|
// Address adder
|
||||||
|
input logic [`SCR1_XLEN-1:0] exu2ialu_addr_op1_i, // Address adder 1st operand
|
||||||
|
input logic [`SCR1_XLEN-1:0] exu2ialu_addr_op2_i, // Address adder 2nd operand
|
||||||
|
output logic [`SCR1_XLEN-1:0] ialu2exu_addr_res_o // Address adder result
|
||||||
|
);
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Local parameters declaration
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
`ifdef SCR1_RVM_EXT
|
||||||
|
`ifdef SCR1_FAST_MUL
|
||||||
|
localparam SCR1_MUL_WIDTH = `SCR1_XLEN;
|
||||||
|
localparam SCR1_MUL_RES_WIDTH = 2 * `SCR1_XLEN;
|
||||||
|
localparam SCR1_MDU_SUM_WIDTH = `SCR1_XLEN + 1;
|
||||||
|
`else
|
||||||
|
localparam SCR1_MUL_STG_NUM = 32;
|
||||||
|
localparam SCR1_MUL_WIDTH = 32 / SCR1_MUL_STG_NUM;
|
||||||
|
localparam SCR1_MUL_CNT_INIT = 32'b1 << (`SCR1_XLEN/SCR1_MUL_WIDTH - 2);
|
||||||
|
localparam SCR1_MDU_SUM_WIDTH = `SCR1_XLEN + SCR1_MUL_WIDTH;
|
||||||
|
`endif // ~SCR1_FAST_MUL
|
||||||
|
localparam SCR1_DIV_WIDTH = 1;
|
||||||
|
localparam SCR1_DIV_CNT_INIT = 32'b1 << (`SCR1_XLEN/SCR1_DIV_WIDTH - 2);
|
||||||
|
`endif // SCR1_RVM_EXT
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Local types declaration
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic z; // Zero
|
||||||
|
logic s; // Sign
|
||||||
|
logic o; // Overflow
|
||||||
|
logic c; // Carry
|
||||||
|
} type_scr1_ialu_flags_s;
|
||||||
|
|
||||||
|
`ifdef SCR1_RVM_EXT
|
||||||
|
typedef enum logic [1:0] {
|
||||||
|
SCR1_IALU_MDU_FSM_IDLE,
|
||||||
|
SCR1_IALU_MDU_FSM_ITER,
|
||||||
|
SCR1_IALU_MDU_FSM_CORR
|
||||||
|
} type_scr1_ialu_fsm_state;
|
||||||
|
|
||||||
|
typedef enum logic [1:0] {
|
||||||
|
SCR1_IALU_MDU_NONE,
|
||||||
|
SCR1_IALU_MDU_MUL,
|
||||||
|
SCR1_IALU_MDU_DIV
|
||||||
|
} type_scr1_ialu_mdu_cmd;
|
||||||
|
`endif // SCR1_RVM_EXT
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Local signals declaration
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Main adder signals
|
||||||
|
logic [`SCR1_XLEN:0] main_sum_res; // Main adder result
|
||||||
|
type_scr1_ialu_flags_s main_sum_flags; // Main adder flags
|
||||||
|
logic main_sum_pos_ovflw; // Main adder positive overflow
|
||||||
|
logic main_sum_neg_ovflw; // Main adder negative overflow
|
||||||
|
logic main_ops_diff_sgn; // Main adder operands have different signs
|
||||||
|
logic main_ops_non_zero; // Both main adder operands are NOT 0
|
||||||
|
|
||||||
|
// Shifter signals
|
||||||
|
logic ialu_cmd_shft; // IALU command is shift
|
||||||
|
logic signed [`SCR1_XLEN-1:0] shft_op1; // SHIFT operand 1
|
||||||
|
logic [4:0] shft_op2; // SHIFT operand 2
|
||||||
|
logic [1:0] shft_cmd; // SHIFT command: 00 - logical left, 10 - logical right, 11 - arithmetical right
|
||||||
|
logic [`SCR1_XLEN-1:0] shft_res; // SHIFT result
|
||||||
|
|
||||||
|
// MUL/DIV signals
|
||||||
|
`ifdef SCR1_RVM_EXT
|
||||||
|
// MUL/DIV FSM control signals
|
||||||
|
logic mdu_cmd_is_iter; // MDU Command is iterative
|
||||||
|
logic mdu_iter_req; // Request iterative stage
|
||||||
|
logic mdu_iter_rdy; // Iteration is ready
|
||||||
|
logic mdu_corr_req; // DIV/REM(U) correction request
|
||||||
|
logic div_corr_req; // Correction request for DIV operation
|
||||||
|
logic rem_corr_req; // Correction request for REM(U) operations
|
||||||
|
|
||||||
|
// MUL/DIV FSM signals
|
||||||
|
type_scr1_ialu_fsm_state mdu_fsm_ff; // Current FSM state
|
||||||
|
type_scr1_ialu_fsm_state mdu_fsm_next; // Next FSM state
|
||||||
|
logic mdu_fsm_idle; // MDU FSM is in IDLE state
|
||||||
|
`ifdef SCR1_TRGT_SIMULATION
|
||||||
|
logic mdu_fsm_iter; // MDU FSM is in ITER state
|
||||||
|
`endif // SCR1_TRGT_SIMULATION
|
||||||
|
logic mdu_fsm_corr; // MDU FSM is in CORR state
|
||||||
|
|
||||||
|
// MDU command signals
|
||||||
|
type_scr1_ialu_mdu_cmd mdu_cmd; // MDU command: 00 - NONE, 01 - MUL, 10 - DIV
|
||||||
|
logic mdu_cmd_mul; // MDU command is MUL(HSU)
|
||||||
|
logic mdu_cmd_div; // MDU command is DIV(U)/REM(U)
|
||||||
|
logic [1:0] mul_cmd; // MUL command: 00 - MUL, 01 - MULH, 10 - MULHSU, 11 - MULHU
|
||||||
|
logic mul_cmd_hi; // High part of MUL result is requested
|
||||||
|
logic [1:0] div_cmd; // DIV command: 00 - DIV, 01 - DIVU, 10 - REM, 11 - REMU
|
||||||
|
logic div_cmd_div; // DIV command is DIV
|
||||||
|
logic div_cmd_rem; // DIV command is REM(U)
|
||||||
|
|
||||||
|
// Multiplier signals
|
||||||
|
logic mul_op1_is_sgn; // First MUL operand is signed
|
||||||
|
logic mul_op2_is_sgn; // Second MUL operand is signed
|
||||||
|
logic mul_op1_sgn; // First MUL operand is negative
|
||||||
|
logic mul_op2_sgn; // Second MUL operand is negative
|
||||||
|
logic signed [`SCR1_XLEN:0] mul_op1; // MUL operand 1
|
||||||
|
logic signed [SCR1_MUL_WIDTH:0] mul_op2; // MUL operand 1
|
||||||
|
`ifdef SCR1_FAST_MUL
|
||||||
|
logic signed [SCR1_MUL_RES_WIDTH-1:0] mul_res; // MUL result
|
||||||
|
`else // ~SCR1_FAST_MUL
|
||||||
|
logic signed [SCR1_MDU_SUM_WIDTH:0] mul_part_prod;
|
||||||
|
logic [`SCR1_XLEN-1:0] mul_res_hi;
|
||||||
|
logic [`SCR1_XLEN-1:0] mul_res_lo;
|
||||||
|
`endif // ~SCR1_FAST_MUL
|
||||||
|
|
||||||
|
// Divisor signals
|
||||||
|
logic div_ops_are_sgn;
|
||||||
|
logic div_op1_is_neg;
|
||||||
|
logic div_op2_is_neg;
|
||||||
|
logic div_res_rem_c;
|
||||||
|
logic [`SCR1_XLEN-1:0] div_res_rem;
|
||||||
|
logic [`SCR1_XLEN-1:0] div_res_quo;
|
||||||
|
logic div_quo_bit;
|
||||||
|
logic div_dvdnd_lo_upd;
|
||||||
|
logic [`SCR1_XLEN-1:0] div_dvdnd_lo_ff;
|
||||||
|
logic [`SCR1_XLEN-1:0] div_dvdnd_lo_next;
|
||||||
|
|
||||||
|
// MDU adder signals
|
||||||
|
logic mdu_sum_sub; // MDU adder operation: 0 - add, 1 - sub
|
||||||
|
logic signed [SCR1_MDU_SUM_WIDTH-1:0] mdu_sum_op1; // MDU adder operand 1
|
||||||
|
logic signed [SCR1_MDU_SUM_WIDTH-1:0] mdu_sum_op2; // MDU adder operand 2
|
||||||
|
logic signed [SCR1_MDU_SUM_WIDTH-1:0] mdu_sum_res; // MDU adder result
|
||||||
|
|
||||||
|
// MDU iteration counter signals
|
||||||
|
logic mdu_iter_cnt_en;
|
||||||
|
logic [`SCR1_XLEN-1:0] mdu_iter_cnt;
|
||||||
|
logic [`SCR1_XLEN-1:0] mdu_iter_cnt_next;
|
||||||
|
|
||||||
|
// Intermediate results registers
|
||||||
|
logic mdu_res_upd;
|
||||||
|
logic mdu_res_c_ff;
|
||||||
|
logic mdu_res_c_next;
|
||||||
|
logic [`SCR1_XLEN-1:0] mdu_res_hi_ff;
|
||||||
|
logic [`SCR1_XLEN-1:0] mdu_res_hi_next;
|
||||||
|
logic [`SCR1_XLEN-1:0] mdu_res_lo_ff;
|
||||||
|
logic [`SCR1_XLEN-1:0] mdu_res_lo_next;
|
||||||
|
`endif // SCR1_RVM_EXT
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Main adder
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Main adder is used for the following types of operations:
|
||||||
|
// - Addition/subtraction (ADD/ADDI/SUB)
|
||||||
|
// - Branch comparisons (BEQ/BNE/BLT(U)/BGE(U))
|
||||||
|
// - Arithmetic comparisons (SLT(U)/SLTI(U))
|
||||||
|
//
|
||||||
|
|
||||||
|
// Carry out (MSB of main_sum_res) is evaluated correctly because the result
|
||||||
|
// width equals to the maximum width of both the right-hand and left-hand side variables
|
||||||
|
always_comb begin
|
||||||
|
main_sum_res = (exu2ialu_cmd_i != SCR1_IALU_CMD_ADD)
|
||||||
|
? ({1'b0, exu2ialu_main_op1_i} - {1'b0, exu2ialu_main_op2_i}) // Subtraction and comparison
|
||||||
|
: ({1'b0, exu2ialu_main_op1_i} + {1'b0, exu2ialu_main_op2_i}); // Addition
|
||||||
|
|
||||||
|
main_sum_pos_ovflw = ~exu2ialu_main_op1_i[`SCR1_XLEN-1]
|
||||||
|
& exu2ialu_main_op2_i[`SCR1_XLEN-1]
|
||||||
|
& main_sum_res[`SCR1_XLEN-1];
|
||||||
|
main_sum_neg_ovflw = exu2ialu_main_op1_i[`SCR1_XLEN-1]
|
||||||
|
& ~exu2ialu_main_op2_i[`SCR1_XLEN-1]
|
||||||
|
& ~main_sum_res[`SCR1_XLEN-1];
|
||||||
|
|
||||||
|
// FLAGS1 - flags for comparison (result of subtraction)
|
||||||
|
main_sum_flags.c = main_sum_res[`SCR1_XLEN];
|
||||||
|
main_sum_flags.z = ~|main_sum_res[`SCR1_XLEN-1:0];
|
||||||
|
main_sum_flags.s = main_sum_res[`SCR1_XLEN-1];
|
||||||
|
main_sum_flags.o = main_sum_pos_ovflw | main_sum_neg_ovflw;
|
||||||
|
end
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Address adder
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Additional adder is used for the following types of operations:
|
||||||
|
// - PC-based address calculation (AUIPC)
|
||||||
|
// - IMEM branch address calculation (BEQ/BNE/BLT(U)/BGE(U))
|
||||||
|
// - IMEM jump address calculation (JAL/JALR)
|
||||||
|
// - DMEM load address calculation (LB(U)/LH(U)/LW)
|
||||||
|
// - DMEM store address calculation (SB/SH/SW)
|
||||||
|
//
|
||||||
|
|
||||||
|
assign ialu2exu_addr_res_o = exu2ialu_addr_op1_i + exu2ialu_addr_op2_i;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Shift logic
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Shift logic supports the following types of shift operations:
|
||||||
|
// - Logical left shift (SLLI/SLL)
|
||||||
|
// - Logical right shift (SRLI/SRL)
|
||||||
|
// - Arithmetic right shift (SRAI/SRA)
|
||||||
|
//
|
||||||
|
|
||||||
|
assign ialu_cmd_shft = (exu2ialu_cmd_i == SCR1_IALU_CMD_SLL)
|
||||||
|
| (exu2ialu_cmd_i == SCR1_IALU_CMD_SRL)
|
||||||
|
| (exu2ialu_cmd_i == SCR1_IALU_CMD_SRA);
|
||||||
|
assign shft_cmd = ialu_cmd_shft
|
||||||
|
? {(exu2ialu_cmd_i != SCR1_IALU_CMD_SLL),
|
||||||
|
(exu2ialu_cmd_i == SCR1_IALU_CMD_SRA)}
|
||||||
|
: 2'b00;
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
shft_op1 = exu2ialu_main_op1_i;
|
||||||
|
shft_op2 = exu2ialu_main_op2_i[4:0];
|
||||||
|
case (shft_cmd)
|
||||||
|
2'b10 : shft_res = shft_op1 >> shft_op2;
|
||||||
|
2'b11 : shft_res = shft_op1 >>> shft_op2;
|
||||||
|
default : shft_res = shft_op1 << shft_op2;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
`ifdef SCR1_RVM_EXT
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// MUL/DIV logic
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// MUL/DIV instructions use the following functional units:
|
||||||
|
// - MUL/DIV FSM control logic, including iteration number counter
|
||||||
|
// - MUL/DIV FSM
|
||||||
|
// - MUL logic
|
||||||
|
// - DIV logic
|
||||||
|
// - MDU adder to produce an intermediate result
|
||||||
|
// - 2 registers to save the intermediate result (shared between MUL and DIV
|
||||||
|
// operations)
|
||||||
|
//
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// MUL/DIV FSM Control logic
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign mdu_cmd_div = (exu2ialu_cmd_i == SCR1_IALU_CMD_DIV)
|
||||||
|
| (exu2ialu_cmd_i == SCR1_IALU_CMD_DIVU)
|
||||||
|
| (exu2ialu_cmd_i == SCR1_IALU_CMD_REM)
|
||||||
|
| (exu2ialu_cmd_i == SCR1_IALU_CMD_REMU);
|
||||||
|
assign mdu_cmd_mul = (exu2ialu_cmd_i == SCR1_IALU_CMD_MUL)
|
||||||
|
| (exu2ialu_cmd_i == SCR1_IALU_CMD_MULH)
|
||||||
|
| (exu2ialu_cmd_i == SCR1_IALU_CMD_MULHU)
|
||||||
|
| (exu2ialu_cmd_i == SCR1_IALU_CMD_MULHSU);
|
||||||
|
|
||||||
|
assign mdu_cmd = mdu_cmd_div ? SCR1_IALU_MDU_DIV
|
||||||
|
: mdu_cmd_mul ? SCR1_IALU_MDU_MUL
|
||||||
|
: SCR1_IALU_MDU_NONE;
|
||||||
|
|
||||||
|
assign main_ops_non_zero = |exu2ialu_main_op1_i & |exu2ialu_main_op2_i;
|
||||||
|
assign main_ops_diff_sgn = exu2ialu_main_op1_i[`SCR1_XLEN-1]
|
||||||
|
^ exu2ialu_main_op2_i[`SCR1_XLEN-1];
|
||||||
|
|
||||||
|
`ifdef SCR1_FAST_MUL
|
||||||
|
assign mdu_cmd_is_iter = mdu_cmd_div;
|
||||||
|
`else // ~SCR1_FAST_MUL
|
||||||
|
assign mdu_cmd_is_iter = mdu_cmd_mul | mdu_cmd_div;
|
||||||
|
`endif // ~SCR1_FAST_MUL
|
||||||
|
|
||||||
|
assign mdu_iter_req = mdu_cmd_is_iter ? (main_ops_non_zero & mdu_fsm_idle) : 1'b0;
|
||||||
|
assign mdu_iter_rdy = mdu_iter_cnt[0];
|
||||||
|
|
||||||
|
assign div_cmd_div = (div_cmd == 2'b00);
|
||||||
|
assign div_cmd_rem = div_cmd[1];
|
||||||
|
|
||||||
|
// Correction request signals
|
||||||
|
assign div_corr_req = div_cmd_div & main_ops_diff_sgn;
|
||||||
|
assign rem_corr_req = div_cmd_rem & |div_res_rem & (div_op1_is_neg ^ div_res_rem_c);
|
||||||
|
assign mdu_corr_req = mdu_cmd_div & (div_corr_req | rem_corr_req);
|
||||||
|
|
||||||
|
// MDU iteration counter
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign mdu_iter_cnt_en = exu2ialu_rvm_cmd_vd_i & ~ialu2exu_rvm_res_rdy_o;
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if (mdu_iter_cnt_en) begin
|
||||||
|
mdu_iter_cnt <= mdu_iter_cnt_next;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign mdu_iter_cnt_next = ~mdu_fsm_idle ? mdu_iter_cnt >> 1
|
||||||
|
: mdu_cmd_div ? SCR1_DIV_CNT_INIT
|
||||||
|
`ifndef SCR1_FAST_MUL
|
||||||
|
: mdu_cmd_mul ? SCR1_MUL_CNT_INIT
|
||||||
|
`endif // ~SCR1_FAST_MUL
|
||||||
|
: mdu_iter_cnt;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// MUL/DIV FSM
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
always_ff @(posedge clk, negedge rst_n) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
mdu_fsm_ff <= SCR1_IALU_MDU_FSM_IDLE;
|
||||||
|
end else begin
|
||||||
|
mdu_fsm_ff <= mdu_fsm_next;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
mdu_fsm_next = SCR1_IALU_MDU_FSM_IDLE;
|
||||||
|
|
||||||
|
if (exu2ialu_rvm_cmd_vd_i) begin
|
||||||
|
case (mdu_fsm_ff)
|
||||||
|
SCR1_IALU_MDU_FSM_IDLE : begin
|
||||||
|
mdu_fsm_next = mdu_iter_req ? SCR1_IALU_MDU_FSM_ITER
|
||||||
|
: SCR1_IALU_MDU_FSM_IDLE;
|
||||||
|
end
|
||||||
|
SCR1_IALU_MDU_FSM_ITER : begin
|
||||||
|
mdu_fsm_next = ~mdu_iter_rdy ? SCR1_IALU_MDU_FSM_ITER
|
||||||
|
: mdu_corr_req ? SCR1_IALU_MDU_FSM_CORR
|
||||||
|
: SCR1_IALU_MDU_FSM_IDLE;
|
||||||
|
end
|
||||||
|
SCR1_IALU_MDU_FSM_CORR : begin
|
||||||
|
mdu_fsm_next = SCR1_IALU_MDU_FSM_IDLE;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign mdu_fsm_idle = (mdu_fsm_ff == SCR1_IALU_MDU_FSM_IDLE);
|
||||||
|
`ifdef SCR1_TRGT_SIMULATION
|
||||||
|
assign mdu_fsm_iter = (mdu_fsm_ff == SCR1_IALU_MDU_FSM_ITER);
|
||||||
|
`endif // SCR1_TRGT_SIMULATION
|
||||||
|
assign mdu_fsm_corr = (mdu_fsm_ff == SCR1_IALU_MDU_FSM_CORR);
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Multiplier logic
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Multiplication has 2 options: fast (1 cycle) and Radix-2 (32 cycles) multiplication.
|
||||||
|
//
|
||||||
|
// 1. Fast multiplication uses the straightforward approach when 2 operands are
|
||||||
|
// multiplied in one cycle
|
||||||
|
//
|
||||||
|
// 2. Radix-2 multiplication uses 2 registers (high and low part of multiplication)
|
||||||
|
//
|
||||||
|
// Radix-2 algorithm:
|
||||||
|
// 1. Initialize registers
|
||||||
|
// 2. Create a partial product by multiplying multiplicand by the LSB of multiplier
|
||||||
|
// 3. Add the partial product to the previous (intermediate) value of multiplication
|
||||||
|
// result (stored into high and low parts of multiplication result register)
|
||||||
|
// 4. Shift the low part of multiplication result register right
|
||||||
|
// 4. Store the addition result into the high part of multiplication result register
|
||||||
|
// 6. If iteration is not ready, go to step 2. Otherwise multiplication is done
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
assign mul_cmd = {((exu2ialu_cmd_i == SCR1_IALU_CMD_MULHU) | (exu2ialu_cmd_i == SCR1_IALU_CMD_MULHSU)),
|
||||||
|
((exu2ialu_cmd_i == SCR1_IALU_CMD_MULHU) | (exu2ialu_cmd_i == SCR1_IALU_CMD_MULH))};
|
||||||
|
|
||||||
|
assign mul_cmd_hi = |mul_cmd;
|
||||||
|
assign mul_op1_is_sgn = ~&mul_cmd;
|
||||||
|
assign mul_op2_is_sgn = ~mul_cmd[1];
|
||||||
|
assign mul_op1_sgn = mul_op1_is_sgn & exu2ialu_main_op1_i[`SCR1_XLEN-1];
|
||||||
|
assign mul_op2_sgn = mul_op2_is_sgn & exu2ialu_main_op2_i[`SCR1_XLEN-1];
|
||||||
|
|
||||||
|
`ifdef SCR1_FAST_MUL
|
||||||
|
assign mul_op1 = mdu_cmd_mul ? $signed({mul_op1_sgn, exu2ialu_main_op1_i}) : '0;
|
||||||
|
assign mul_op2 = mdu_cmd_mul ? $signed({mul_op2_sgn, exu2ialu_main_op2_i}) : '0;
|
||||||
|
assign mul_res = mdu_cmd_mul ? mul_op1 * mul_op2 : $signed('0);
|
||||||
|
`else // ~SCR1_FAST_MUL
|
||||||
|
assign mul_op1 = mdu_cmd_mul ? $signed({mul_op1_sgn, exu2ialu_main_op1_i}) : '0;
|
||||||
|
assign mul_op2 = ~mdu_cmd_mul ? '0
|
||||||
|
: mdu_fsm_idle ? $signed({1'b0, exu2ialu_main_op2_i[SCR1_MUL_WIDTH-1:0]})
|
||||||
|
: $signed({(mdu_iter_cnt[0] & mul_op2_is_sgn & mdu_res_lo_ff[SCR1_MUL_WIDTH-1]),
|
||||||
|
mdu_res_lo_ff[SCR1_MUL_WIDTH-1:0]});
|
||||||
|
|
||||||
|
assign mul_part_prod = mdu_cmd_mul ? mul_op1 * mul_op2 : $signed('0);
|
||||||
|
assign {mul_res_hi, mul_res_lo} = ~mdu_cmd_mul ? '0
|
||||||
|
: mdu_fsm_idle ? ({mdu_sum_res, exu2ialu_main_op2_i[`SCR1_XLEN-1:SCR1_MUL_WIDTH]})
|
||||||
|
: ({mdu_sum_res, mdu_res_lo_ff[`SCR1_XLEN-1:SCR1_MUL_WIDTH]});
|
||||||
|
`endif // ~SCR1_FAST_MUL
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Divider logic
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Division uses a non-restoring algorithm. 3 registers are used:
|
||||||
|
// - Remainder register
|
||||||
|
// - Quotient register
|
||||||
|
// - Dividend low part register (for corner case quotient bit calculation)
|
||||||
|
//
|
||||||
|
// Algorithm:
|
||||||
|
// 1. Initialize registers
|
||||||
|
// 2. Shift remainder and dividend low part registers left
|
||||||
|
// 3. Compare remainder register with the divisor (taking previous quotient bit
|
||||||
|
// and operands signs into account) and calculate quotient bit based on the
|
||||||
|
// comparison results
|
||||||
|
// 4. Shift quotient register left, append quotient bit to the quotient register
|
||||||
|
// 5. If iteration is not ready, go to step 2. Otherwise go to step 6
|
||||||
|
// 6. Do correction if necessary, otherwise division is done
|
||||||
|
//
|
||||||
|
// Quotient bit calculation has a corner case:
|
||||||
|
// When dividend is negative result carry bit check takes into account only
|
||||||
|
// the case of remainder register been greater than divisor. To handle
|
||||||
|
// equality case we should check if both the comparison result and the
|
||||||
|
// lower part of dividend are zero
|
||||||
|
//
|
||||||
|
|
||||||
|
assign div_cmd = {((exu2ialu_cmd_i == SCR1_IALU_CMD_REM) | (exu2ialu_cmd_i == SCR1_IALU_CMD_REMU)),
|
||||||
|
((exu2ialu_cmd_i == SCR1_IALU_CMD_REMU) | (exu2ialu_cmd_i == SCR1_IALU_CMD_DIVU))};
|
||||||
|
|
||||||
|
assign div_ops_are_sgn = ~div_cmd[0];
|
||||||
|
assign div_op1_is_neg = div_ops_are_sgn & exu2ialu_main_op1_i[`SCR1_XLEN-1];
|
||||||
|
assign div_op2_is_neg = div_ops_are_sgn & exu2ialu_main_op2_i[`SCR1_XLEN-1];
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
div_res_rem_c = '0;
|
||||||
|
div_res_rem = '0;
|
||||||
|
div_res_quo = '0;
|
||||||
|
div_quo_bit = 1'b0;
|
||||||
|
if (mdu_cmd_div & ~mdu_fsm_corr) begin
|
||||||
|
div_res_rem_c = mdu_sum_res[SCR1_MDU_SUM_WIDTH-1];
|
||||||
|
div_res_rem = mdu_sum_res[SCR1_MDU_SUM_WIDTH-2:0];
|
||||||
|
div_quo_bit = ~(div_op1_is_neg ^ div_res_rem_c)
|
||||||
|
| (div_op1_is_neg & ({mdu_sum_res, div_dvdnd_lo_next} == '0));
|
||||||
|
div_res_quo = mdu_fsm_idle
|
||||||
|
? {'0, div_quo_bit}
|
||||||
|
: {mdu_res_lo_ff[`SCR1_XLEN-2:0], div_quo_bit};
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// Dividend low part register
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign div_dvdnd_lo_upd = exu2ialu_rvm_cmd_vd_i & ~ialu2exu_rvm_res_rdy_o;
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if (div_dvdnd_lo_upd) begin
|
||||||
|
div_dvdnd_lo_ff <= div_dvdnd_lo_next;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign div_dvdnd_lo_next = (~mdu_cmd_div | mdu_fsm_corr) ? '0
|
||||||
|
: mdu_fsm_idle ? exu2ialu_main_op1_i << 1
|
||||||
|
: div_dvdnd_lo_ff << 1;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// MDU adder
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
mdu_sum_sub = 1'b0;
|
||||||
|
mdu_sum_op1 = '0;
|
||||||
|
mdu_sum_op2 = '0;
|
||||||
|
case (mdu_cmd)
|
||||||
|
SCR1_IALU_MDU_DIV : begin
|
||||||
|
logic sgn;
|
||||||
|
logic inv;
|
||||||
|
|
||||||
|
sgn = mdu_fsm_corr ? div_op1_is_neg ^ mdu_res_c_ff
|
||||||
|
: mdu_fsm_idle ? 1'b0
|
||||||
|
: ~mdu_res_lo_ff[0];
|
||||||
|
inv = div_ops_are_sgn & main_ops_diff_sgn;
|
||||||
|
mdu_sum_sub = ~inv ^ sgn;
|
||||||
|
mdu_sum_op1 = mdu_fsm_corr ? $signed({1'b0, mdu_res_hi_ff})
|
||||||
|
: mdu_fsm_idle ? $signed({div_op1_is_neg, exu2ialu_main_op1_i[`SCR1_XLEN-1]})
|
||||||
|
: $signed({mdu_res_hi_ff, div_dvdnd_lo_ff[`SCR1_XLEN-1]});
|
||||||
|
mdu_sum_op2 = $signed({div_op2_is_neg, exu2ialu_main_op2_i});
|
||||||
|
end
|
||||||
|
`ifndef SCR1_FAST_MUL
|
||||||
|
SCR1_IALU_MDU_MUL : begin
|
||||||
|
mdu_sum_op1 = mdu_fsm_idle
|
||||||
|
? '0
|
||||||
|
: $signed({(mul_op1_is_sgn & mdu_res_hi_ff[`SCR1_XLEN-1]), mdu_res_hi_ff});
|
||||||
|
mdu_sum_op2 = mul_part_prod;
|
||||||
|
end
|
||||||
|
`endif // SCR1_FAST_MUL
|
||||||
|
default : begin end
|
||||||
|
endcase
|
||||||
|
mdu_sum_res = mdu_sum_sub
|
||||||
|
? (mdu_sum_op1 - mdu_sum_op2)
|
||||||
|
: (mdu_sum_op1 + mdu_sum_op2);
|
||||||
|
end
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// MUL/DIV intermediate results registers
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign mdu_res_upd = exu2ialu_rvm_cmd_vd_i & ~ialu2exu_rvm_res_rdy_o;
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if (mdu_res_upd) begin
|
||||||
|
mdu_res_c_ff <= mdu_res_c_next;
|
||||||
|
mdu_res_hi_ff <= mdu_res_hi_next;
|
||||||
|
mdu_res_lo_ff <= mdu_res_lo_next;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign mdu_res_c_next = mdu_cmd_div ? div_res_rem_c : mdu_res_c_ff;
|
||||||
|
assign mdu_res_hi_next = mdu_cmd_div ? div_res_rem
|
||||||
|
`ifndef SCR1_FAST_MUL
|
||||||
|
: mdu_cmd_mul ? mul_res_hi
|
||||||
|
`endif // SCR1_FAST_MUL
|
||||||
|
: mdu_res_hi_ff;
|
||||||
|
assign mdu_res_lo_next = mdu_cmd_div ? div_res_quo
|
||||||
|
`ifndef SCR1_FAST_MUL
|
||||||
|
: mdu_cmd_mul ? mul_res_lo
|
||||||
|
`endif // SCR1_FAST_MUL
|
||||||
|
: mdu_res_lo_ff;
|
||||||
|
`endif // SCR1_RVM_EXT
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Operation result forming
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
ialu2exu_main_res_o = '0;
|
||||||
|
ialu2exu_cmp_res_o = 1'b0;
|
||||||
|
`ifdef SCR1_RVM_EXT
|
||||||
|
ialu2exu_rvm_res_rdy_o = 1'b1;
|
||||||
|
`endif // SCR1_RVM_EXT
|
||||||
|
|
||||||
|
case (exu2ialu_cmd_i)
|
||||||
|
SCR1_IALU_CMD_AND : begin
|
||||||
|
ialu2exu_main_res_o = exu2ialu_main_op1_i & exu2ialu_main_op2_i;
|
||||||
|
end
|
||||||
|
SCR1_IALU_CMD_OR : begin
|
||||||
|
ialu2exu_main_res_o = exu2ialu_main_op1_i | exu2ialu_main_op2_i;
|
||||||
|
end
|
||||||
|
SCR1_IALU_CMD_XOR : begin
|
||||||
|
ialu2exu_main_res_o = exu2ialu_main_op1_i ^ exu2ialu_main_op2_i;
|
||||||
|
end
|
||||||
|
SCR1_IALU_CMD_ADD : begin
|
||||||
|
ialu2exu_main_res_o = main_sum_res[`SCR1_XLEN-1:0];
|
||||||
|
end
|
||||||
|
SCR1_IALU_CMD_SUB : begin
|
||||||
|
ialu2exu_main_res_o = main_sum_res[`SCR1_XLEN-1:0];
|
||||||
|
end
|
||||||
|
SCR1_IALU_CMD_SUB_LT : begin
|
||||||
|
ialu2exu_main_res_o = `SCR1_XLEN'(main_sum_flags.s ^ main_sum_flags.o);
|
||||||
|
ialu2exu_cmp_res_o = main_sum_flags.s ^ main_sum_flags.o;
|
||||||
|
end
|
||||||
|
SCR1_IALU_CMD_SUB_LTU : begin
|
||||||
|
ialu2exu_main_res_o = `SCR1_XLEN'(main_sum_flags.c);
|
||||||
|
ialu2exu_cmp_res_o = main_sum_flags.c;
|
||||||
|
end
|
||||||
|
SCR1_IALU_CMD_SUB_EQ : begin
|
||||||
|
ialu2exu_main_res_o = `SCR1_XLEN'(main_sum_flags.z);
|
||||||
|
ialu2exu_cmp_res_o = main_sum_flags.z;
|
||||||
|
end
|
||||||
|
SCR1_IALU_CMD_SUB_NE : begin
|
||||||
|
ialu2exu_main_res_o = `SCR1_XLEN'(~main_sum_flags.z);
|
||||||
|
ialu2exu_cmp_res_o = ~main_sum_flags.z;
|
||||||
|
end
|
||||||
|
SCR1_IALU_CMD_SUB_GE : begin
|
||||||
|
ialu2exu_main_res_o = `SCR1_XLEN'(~(main_sum_flags.s ^ main_sum_flags.o));
|
||||||
|
ialu2exu_cmp_res_o = ~(main_sum_flags.s ^ main_sum_flags.o);
|
||||||
|
end
|
||||||
|
SCR1_IALU_CMD_SUB_GEU : begin
|
||||||
|
ialu2exu_main_res_o = `SCR1_XLEN'(~main_sum_flags.c);
|
||||||
|
ialu2exu_cmp_res_o = ~main_sum_flags.c;
|
||||||
|
end
|
||||||
|
SCR1_IALU_CMD_SLL,
|
||||||
|
SCR1_IALU_CMD_SRL,
|
||||||
|
SCR1_IALU_CMD_SRA: begin
|
||||||
|
ialu2exu_main_res_o = shft_res;
|
||||||
|
end
|
||||||
|
`ifdef SCR1_RVM_EXT
|
||||||
|
SCR1_IALU_CMD_MUL,
|
||||||
|
SCR1_IALU_CMD_MULHU,
|
||||||
|
SCR1_IALU_CMD_MULHSU,
|
||||||
|
SCR1_IALU_CMD_MULH : begin
|
||||||
|
`ifdef SCR1_FAST_MUL
|
||||||
|
ialu2exu_main_res_o = mul_cmd_hi
|
||||||
|
? mul_res[SCR1_MUL_RES_WIDTH-1:`SCR1_XLEN]
|
||||||
|
: mul_res[`SCR1_XLEN-1:0];
|
||||||
|
`else // ~SCR1_FAST_MUL
|
||||||
|
case (mdu_fsm_ff)
|
||||||
|
SCR1_IALU_MDU_FSM_IDLE : begin
|
||||||
|
ialu2exu_main_res_o = '0;
|
||||||
|
ialu2exu_rvm_res_rdy_o = ~mdu_iter_req;
|
||||||
|
end
|
||||||
|
SCR1_IALU_MDU_FSM_ITER : begin
|
||||||
|
ialu2exu_main_res_o = mul_cmd_hi ? mul_res_hi : mul_res_lo;
|
||||||
|
ialu2exu_rvm_res_rdy_o = mdu_iter_rdy;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
`endif // ~SCR1_FAST_MUL
|
||||||
|
end
|
||||||
|
SCR1_IALU_CMD_DIV,
|
||||||
|
SCR1_IALU_CMD_DIVU,
|
||||||
|
SCR1_IALU_CMD_REM,
|
||||||
|
SCR1_IALU_CMD_REMU : begin
|
||||||
|
case (mdu_fsm_ff)
|
||||||
|
SCR1_IALU_MDU_FSM_IDLE : begin
|
||||||
|
ialu2exu_main_res_o = (|exu2ialu_main_op2_i | div_cmd_rem)
|
||||||
|
? exu2ialu_main_op1_i
|
||||||
|
: '1;
|
||||||
|
ialu2exu_rvm_res_rdy_o = ~mdu_iter_req;
|
||||||
|
end
|
||||||
|
SCR1_IALU_MDU_FSM_ITER : begin
|
||||||
|
ialu2exu_main_res_o = div_cmd_rem ? div_res_rem : div_res_quo;
|
||||||
|
ialu2exu_rvm_res_rdy_o = mdu_iter_rdy & ~mdu_corr_req;
|
||||||
|
end
|
||||||
|
SCR1_IALU_MDU_FSM_CORR : begin
|
||||||
|
ialu2exu_main_res_o = div_cmd_rem
|
||||||
|
? mdu_sum_res[`SCR1_XLEN-1:0]
|
||||||
|
: -mdu_res_lo_ff[`SCR1_XLEN-1:0];
|
||||||
|
ialu2exu_rvm_res_rdy_o = 1'b1;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
`endif // SCR1_RVM_EXT
|
||||||
|
default : begin end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
`ifdef SCR1_TRGT_SIMULATION
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Assertion
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
`ifdef SCR1_RVM_EXT
|
||||||
|
|
||||||
|
// X checks
|
||||||
|
|
||||||
|
SCR1_SVA_IALU_XCHECK : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
!$isunknown({exu2ialu_rvm_cmd_vd_i, mdu_fsm_ff})
|
||||||
|
) else $error("IALU Error: unknown values");
|
||||||
|
|
||||||
|
SCR1_SVA_IALU_XCHECK_QUEUE : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
exu2ialu_rvm_cmd_vd_i |->
|
||||||
|
!$isunknown({exu2ialu_main_op1_i, exu2ialu_main_op2_i, exu2ialu_cmd_i})
|
||||||
|
) else $error("IALU Error: unknown values in queue");
|
||||||
|
|
||||||
|
// Behavior checks
|
||||||
|
|
||||||
|
SCR1_SVA_IALU_ILL_STATE : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
$onehot0({~exu2ialu_rvm_cmd_vd_i, mdu_fsm_iter, mdu_fsm_corr})
|
||||||
|
) else $error("IALU Error: illegal state");
|
||||||
|
|
||||||
|
SCR1_SVA_IALU_JUMP_FROM_IDLE : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
(mdu_fsm_idle & (~exu2ialu_rvm_cmd_vd_i | ~mdu_iter_req)) |=> mdu_fsm_idle
|
||||||
|
) else $error("EXU Error: illegal jump from IDLE state");
|
||||||
|
|
||||||
|
SCR1_SVA_IALU_IDLE_TO_ITER : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
(mdu_fsm_idle & exu2ialu_rvm_cmd_vd_i & mdu_iter_req) |=> mdu_fsm_iter
|
||||||
|
) else $error("EXU Error: illegal change state form IDLE to ITER");
|
||||||
|
|
||||||
|
SCR1_SVA_IALU_JUMP_FROM_ITER : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
(mdu_fsm_iter & ~mdu_iter_rdy) |=> mdu_fsm_iter
|
||||||
|
) else $error("EXU Error: illegal jump from ITER state");
|
||||||
|
|
||||||
|
SCR1_SVA_IALU_ITER_TO_IDLE : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
(mdu_fsm_iter & mdu_iter_rdy & ~mdu_corr_req) |=> mdu_fsm_idle
|
||||||
|
) else $error("EXU Error: illegal state change ITER to IDLE");
|
||||||
|
|
||||||
|
SCR1_SVA_IALU_ITER_TO_CORR : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
(mdu_fsm_iter & mdu_iter_rdy & mdu_corr_req) |=> mdu_fsm_corr
|
||||||
|
) else $error("EXU Error: illegal state change ITER to CORR");
|
||||||
|
|
||||||
|
SCR1_SVA_IALU_CORR_TO_IDLE : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
mdu_fsm_corr |=> mdu_fsm_idle
|
||||||
|
) else $error("EXU Error: illegal state stay in CORR");
|
||||||
|
|
||||||
|
`endif // SCR1_RVM_EXT
|
||||||
|
|
||||||
|
`endif // SCR1_TRGT_SIMULATION
|
||||||
|
|
||||||
|
endmodule : scr1_pipe_ialu
|
||||||
940
src_ref/core/pipeline/scr1_pipe_idu.sv
Normal file
940
src_ref/core/pipeline/scr1_pipe_idu.sv
Normal file
@@ -0,0 +1,940 @@
|
|||||||
|
/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
|
||||||
|
/// @file <scr1_pipe_idu.sv>
|
||||||
|
/// @brief Instruction Decoder Unit (IDU)
|
||||||
|
///
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Functionality:
|
||||||
|
// - Decodes the instruction and creates the appropriate control signals for EXU
|
||||||
|
//
|
||||||
|
// Structure:
|
||||||
|
// - Instruction decoder
|
||||||
|
// - IDU <-> IFU i/f
|
||||||
|
// - IDU <-> EXU i/f
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
`include "scr1_memif.svh"
|
||||||
|
`include "scr1_arch_types.svh"
|
||||||
|
`include "scr1_riscv_isa_decoding.svh"
|
||||||
|
`include "scr1_arch_description.svh"
|
||||||
|
|
||||||
|
module scr1_pipe_idu
|
||||||
|
(
|
||||||
|
`ifdef SCR1_TRGT_SIMULATION
|
||||||
|
input logic rst_n, // IDU reset
|
||||||
|
input logic clk, // IDU clock
|
||||||
|
`endif // SCR1_TRGT_SIMULATION
|
||||||
|
|
||||||
|
// IFU <-> IDU interface
|
||||||
|
output logic idu2ifu_rdy_o, // IDU ready for new data
|
||||||
|
input logic [`SCR1_IMEM_DWIDTH-1:0] ifu2idu_instr_i, // IFU instruction
|
||||||
|
input logic ifu2idu_imem_err_i, // Instruction access fault exception
|
||||||
|
input logic ifu2idu_err_rvi_hi_i, // 1 - imem fault when trying to fetch second half of an unaligned RVI instruction
|
||||||
|
input logic ifu2idu_vd_i, // IFU request
|
||||||
|
|
||||||
|
// IDU <-> EXU interface
|
||||||
|
output logic idu2exu_req_o, // IDU request
|
||||||
|
output type_scr1_exu_cmd_s idu2exu_cmd_o, // IDU command
|
||||||
|
output logic idu2exu_use_rs1_o, // Instruction uses rs1
|
||||||
|
output logic idu2exu_use_rs2_o, // Instruction uses rs2
|
||||||
|
`ifndef SCR1_NO_EXE_STAGE
|
||||||
|
output logic idu2exu_use_rd_o, // Instruction uses rd
|
||||||
|
output logic idu2exu_use_imm_o, // Instruction uses immediate
|
||||||
|
`endif // SCR1_NO_EXE_STAGE
|
||||||
|
input logic exu2idu_rdy_i // EXU ready for new data
|
||||||
|
);
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Local parameters declaration
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
localparam [SCR1_GPR_FIELD_WIDTH-1:0] SCR1_MPRF_ZERO_ADDR = 5'd0;
|
||||||
|
localparam [SCR1_GPR_FIELD_WIDTH-1:0] SCR1_MPRF_RA_ADDR = 5'd1;
|
||||||
|
localparam [SCR1_GPR_FIELD_WIDTH-1:0] SCR1_MPRF_SP_ADDR = 5'd2;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Local signals declaration
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
logic [`SCR1_IMEM_DWIDTH-1:0] instr;
|
||||||
|
type_scr1_instr_type_e instr_type;
|
||||||
|
type_scr1_rvi_opcode_e rvi_opcode;
|
||||||
|
logic rvi_illegal;
|
||||||
|
logic [2:0] funct3;
|
||||||
|
logic [6:0] funct7;
|
||||||
|
logic [11:0] funct12;
|
||||||
|
logic [4:0] shamt;
|
||||||
|
`ifdef SCR1_RVC_EXT
|
||||||
|
logic rvc_illegal;
|
||||||
|
`endif // SCR1_RVC_EXT
|
||||||
|
`ifdef SCR1_RVE_EXT
|
||||||
|
logic rve_illegal;
|
||||||
|
`endif // SCR1_RVE_EXT
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Instruction decoding
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign idu2ifu_rdy_o = exu2idu_rdy_i;
|
||||||
|
assign idu2exu_req_o = ifu2idu_vd_i;
|
||||||
|
assign instr = ifu2idu_instr_i;
|
||||||
|
|
||||||
|
// RVI / RVC
|
||||||
|
assign instr_type = type_scr1_instr_type_e'(instr[1:0]);
|
||||||
|
|
||||||
|
// RVI / RVC fields
|
||||||
|
assign rvi_opcode = type_scr1_rvi_opcode_e'(instr[6:2]); // RVI
|
||||||
|
assign funct3 = (instr_type == SCR1_INSTR_RVI) ? instr[14:12] : instr[15:13]; // RVI / RVC
|
||||||
|
assign funct7 = instr[31:25]; // RVI
|
||||||
|
assign funct12 = instr[31:20]; // RVI (SYSTEM)
|
||||||
|
assign shamt = instr[24:20]; // RVI
|
||||||
|
|
||||||
|
// RV32I(MC) decode
|
||||||
|
always_comb begin
|
||||||
|
// Defaults
|
||||||
|
idu2exu_cmd_o.instr_rvc = 1'b0;
|
||||||
|
idu2exu_cmd_o.ialu_op = SCR1_IALU_OP_REG_REG;
|
||||||
|
idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_NONE;
|
||||||
|
idu2exu_cmd_o.sum2_op = SCR1_SUM2_OP_PC_IMM;
|
||||||
|
idu2exu_cmd_o.lsu_cmd = SCR1_LSU_CMD_NONE;
|
||||||
|
idu2exu_cmd_o.csr_op = SCR1_CSR_OP_REG;
|
||||||
|
idu2exu_cmd_o.csr_cmd = SCR1_CSR_CMD_NONE;
|
||||||
|
idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_NONE;
|
||||||
|
idu2exu_cmd_o.jump_req = 1'b0;
|
||||||
|
idu2exu_cmd_o.branch_req = 1'b0;
|
||||||
|
idu2exu_cmd_o.mret_req = 1'b0;
|
||||||
|
idu2exu_cmd_o.fencei_req = 1'b0;
|
||||||
|
idu2exu_cmd_o.wfi_req = 1'b0;
|
||||||
|
idu2exu_cmd_o.rs1_addr = '0;
|
||||||
|
idu2exu_cmd_o.rs2_addr = '0;
|
||||||
|
idu2exu_cmd_o.rd_addr = '0;
|
||||||
|
idu2exu_cmd_o.imm = '0;
|
||||||
|
idu2exu_cmd_o.exc_req = 1'b0;
|
||||||
|
idu2exu_cmd_o.exc_code = SCR1_EXC_CODE_INSTR_MISALIGN;
|
||||||
|
|
||||||
|
// Clock gating
|
||||||
|
idu2exu_use_rs1_o = 1'b0;
|
||||||
|
idu2exu_use_rs2_o = 1'b0;
|
||||||
|
`ifndef SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_use_rd_o = 1'b0;
|
||||||
|
idu2exu_use_imm_o = 1'b0;
|
||||||
|
`endif // SCR1_NO_EXE_STAGE
|
||||||
|
|
||||||
|
rvi_illegal = 1'b0;
|
||||||
|
`ifdef SCR1_RVE_EXT
|
||||||
|
rve_illegal = 1'b0;
|
||||||
|
`endif // SCR1_RVE_EXT
|
||||||
|
`ifdef SCR1_RVC_EXT
|
||||||
|
rvc_illegal = 1'b0;
|
||||||
|
`endif // SCR1_RVC_EXT
|
||||||
|
|
||||||
|
// Check for IMEM access fault
|
||||||
|
if (ifu2idu_imem_err_i) begin
|
||||||
|
idu2exu_cmd_o.exc_req = 1'b1;
|
||||||
|
idu2exu_cmd_o.exc_code = SCR1_EXC_CODE_INSTR_ACCESS_FAULT;
|
||||||
|
idu2exu_cmd_o.instr_rvc = ifu2idu_err_rvi_hi_i;
|
||||||
|
end else begin // no imem fault
|
||||||
|
case (instr_type)
|
||||||
|
SCR1_INSTR_RVI : begin
|
||||||
|
idu2exu_cmd_o.rs1_addr = instr[19:15];
|
||||||
|
idu2exu_cmd_o.rs2_addr = instr[24:20];
|
||||||
|
idu2exu_cmd_o.rd_addr = instr[11:7];
|
||||||
|
case (rvi_opcode)
|
||||||
|
SCR1_OPCODE_AUIPC : begin
|
||||||
|
`ifndef SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_use_rd_o = 1'b1;
|
||||||
|
idu2exu_use_imm_o = 1'b1;
|
||||||
|
`endif // SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_cmd_o.sum2_op = SCR1_SUM2_OP_PC_IMM;
|
||||||
|
idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_SUM2;
|
||||||
|
idu2exu_cmd_o.imm = {instr[31:12], 12'b0};
|
||||||
|
`ifdef SCR1_RVE_EXT
|
||||||
|
if (instr[11]) rve_illegal = 1'b1;
|
||||||
|
`endif // SCR1_RVE_EXT
|
||||||
|
end // SCR1_OPCODE_AUIPC
|
||||||
|
|
||||||
|
SCR1_OPCODE_LUI : begin
|
||||||
|
`ifndef SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_use_rd_o = 1'b1;
|
||||||
|
idu2exu_use_imm_o = 1'b1;
|
||||||
|
`endif // SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_IMM;
|
||||||
|
idu2exu_cmd_o.imm = {instr[31:12], 12'b0};
|
||||||
|
`ifdef SCR1_RVE_EXT
|
||||||
|
if (instr[11]) rve_illegal = 1'b1;
|
||||||
|
`endif // SCR1_RVE_EXT
|
||||||
|
end // SCR1_OPCODE_LUI
|
||||||
|
|
||||||
|
SCR1_OPCODE_JAL : begin
|
||||||
|
`ifndef SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_use_rd_o = 1'b1;
|
||||||
|
idu2exu_use_imm_o = 1'b1;
|
||||||
|
`endif // SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_cmd_o.sum2_op = SCR1_SUM2_OP_PC_IMM;
|
||||||
|
idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_INC_PC;
|
||||||
|
idu2exu_cmd_o.jump_req = 1'b1;
|
||||||
|
idu2exu_cmd_o.imm = {{12{instr[31]}}, instr[19:12], instr[20], instr[30:21], 1'b0};
|
||||||
|
`ifdef SCR1_RVE_EXT
|
||||||
|
if (instr[11]) rve_illegal = 1'b1;
|
||||||
|
`endif // SCR1_RVE_EXT
|
||||||
|
end // SCR1_OPCODE_JAL
|
||||||
|
|
||||||
|
SCR1_OPCODE_LOAD : begin
|
||||||
|
idu2exu_use_rs1_o = 1'b1;
|
||||||
|
`ifndef SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_use_rd_o = 1'b1;
|
||||||
|
idu2exu_use_imm_o = 1'b1;
|
||||||
|
`endif // SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_cmd_o.sum2_op = SCR1_SUM2_OP_REG_IMM;
|
||||||
|
idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_LSU;
|
||||||
|
idu2exu_cmd_o.imm = {{21{instr[31]}}, instr[30:20]};
|
||||||
|
case (funct3)
|
||||||
|
3'b000 : idu2exu_cmd_o.lsu_cmd = SCR1_LSU_CMD_LB;
|
||||||
|
3'b001 : idu2exu_cmd_o.lsu_cmd = SCR1_LSU_CMD_LH;
|
||||||
|
3'b010 : idu2exu_cmd_o.lsu_cmd = SCR1_LSU_CMD_LW;
|
||||||
|
3'b100 : idu2exu_cmd_o.lsu_cmd = SCR1_LSU_CMD_LBU;
|
||||||
|
3'b101 : idu2exu_cmd_o.lsu_cmd = SCR1_LSU_CMD_LHU;
|
||||||
|
default : rvi_illegal = 1'b1;
|
||||||
|
endcase // funct3
|
||||||
|
`ifdef SCR1_RVE_EXT
|
||||||
|
if (instr[11] | instr[19]) rve_illegal = 1'b1;
|
||||||
|
`endif // SCR1_RVE_EXT
|
||||||
|
end // SCR1_OPCODE_LOAD
|
||||||
|
|
||||||
|
SCR1_OPCODE_STORE : begin
|
||||||
|
idu2exu_use_rs1_o = 1'b1;
|
||||||
|
idu2exu_use_rs2_o = 1'b1;
|
||||||
|
`ifndef SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_use_imm_o = 1'b1;
|
||||||
|
`endif // SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_cmd_o.sum2_op = SCR1_SUM2_OP_REG_IMM;
|
||||||
|
idu2exu_cmd_o.imm = {{21{instr[31]}}, instr[30:25], instr[11:7]};
|
||||||
|
case (funct3)
|
||||||
|
3'b000 : idu2exu_cmd_o.lsu_cmd = SCR1_LSU_CMD_SB;
|
||||||
|
3'b001 : idu2exu_cmd_o.lsu_cmd = SCR1_LSU_CMD_SH;
|
||||||
|
3'b010 : idu2exu_cmd_o.lsu_cmd = SCR1_LSU_CMD_SW;
|
||||||
|
default : rvi_illegal = 1'b1;
|
||||||
|
endcase // funct3
|
||||||
|
`ifdef SCR1_RVE_EXT
|
||||||
|
if (instr[19] | instr[24]) rve_illegal = 1'b1;
|
||||||
|
`endif // SCR1_RVE_EXT
|
||||||
|
end // SCR1_OPCODE_STORE
|
||||||
|
|
||||||
|
SCR1_OPCODE_OP : begin
|
||||||
|
idu2exu_use_rs1_o = 1'b1;
|
||||||
|
idu2exu_use_rs2_o = 1'b1;
|
||||||
|
`ifndef SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_use_rd_o = 1'b1;
|
||||||
|
`endif // SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_cmd_o.ialu_op = SCR1_IALU_OP_REG_REG;
|
||||||
|
idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_IALU;
|
||||||
|
case (funct7)
|
||||||
|
7'b0000000 : begin
|
||||||
|
case (funct3)
|
||||||
|
3'b000 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_ADD;
|
||||||
|
3'b001 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SLL;
|
||||||
|
3'b010 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SUB_LT;
|
||||||
|
3'b011 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SUB_LTU;
|
||||||
|
3'b100 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_XOR;
|
||||||
|
3'b101 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SRL;
|
||||||
|
3'b110 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_OR;
|
||||||
|
3'b111 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_AND;
|
||||||
|
endcase // funct3
|
||||||
|
end // 7'b0000000
|
||||||
|
|
||||||
|
7'b0100000 : begin
|
||||||
|
case (funct3)
|
||||||
|
3'b000 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SUB;
|
||||||
|
3'b101 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SRA;
|
||||||
|
default : rvi_illegal = 1'b1;
|
||||||
|
endcase // funct3
|
||||||
|
end // 7'b0100000
|
||||||
|
`ifdef SCR1_RVM_EXT
|
||||||
|
7'b0000001 : begin
|
||||||
|
case (funct3)
|
||||||
|
3'b000 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_MUL;
|
||||||
|
3'b001 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_MULH;
|
||||||
|
3'b010 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_MULHSU;
|
||||||
|
3'b011 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_MULHU;
|
||||||
|
3'b100 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_DIV;
|
||||||
|
3'b101 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_DIVU;
|
||||||
|
3'b110 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_REM;
|
||||||
|
3'b111 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_REMU;
|
||||||
|
endcase // funct3
|
||||||
|
end // 7'b0000001
|
||||||
|
`endif // SCR1_RVM_EXT
|
||||||
|
default : rvi_illegal = 1'b1;
|
||||||
|
endcase // funct7
|
||||||
|
`ifdef SCR1_RVE_EXT
|
||||||
|
if (instr[11] | instr[19] | instr[24]) rve_illegal = 1'b1;
|
||||||
|
`endif // SCR1_RVE_EXT
|
||||||
|
end // SCR1_OPCODE_OP
|
||||||
|
|
||||||
|
SCR1_OPCODE_OP_IMM : begin
|
||||||
|
idu2exu_use_rs1_o = 1'b1;
|
||||||
|
`ifndef SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_use_rd_o = 1'b1;
|
||||||
|
idu2exu_use_imm_o = 1'b1;
|
||||||
|
`endif // SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_cmd_o.imm = {{21{instr[31]}}, instr[30:20]};
|
||||||
|
idu2exu_cmd_o.ialu_op = SCR1_IALU_OP_REG_IMM;
|
||||||
|
idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_IALU;
|
||||||
|
case (funct3)
|
||||||
|
3'b000 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_ADD; // ADDI
|
||||||
|
3'b010 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SUB_LT; // SLTI
|
||||||
|
3'b011 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SUB_LTU; // SLTIU
|
||||||
|
3'b100 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_XOR; // XORI
|
||||||
|
3'b110 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_OR; // ORI
|
||||||
|
3'b111 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_AND; // ANDI
|
||||||
|
3'b001 : begin
|
||||||
|
case (funct7)
|
||||||
|
7'b0000000 : begin
|
||||||
|
// SLLI
|
||||||
|
idu2exu_cmd_o.imm = `SCR1_XLEN'(shamt); // zero-extend
|
||||||
|
idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SLL;
|
||||||
|
end
|
||||||
|
default : rvi_illegal = 1'b1;
|
||||||
|
endcase // funct7
|
||||||
|
end
|
||||||
|
3'b101 : begin
|
||||||
|
case (funct7)
|
||||||
|
7'b0000000 : begin
|
||||||
|
// SRLI
|
||||||
|
idu2exu_cmd_o.imm = `SCR1_XLEN'(shamt); // zero-extend
|
||||||
|
idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SRL;
|
||||||
|
end
|
||||||
|
7'b0100000 : begin
|
||||||
|
// SRAI
|
||||||
|
idu2exu_cmd_o.imm = `SCR1_XLEN'(shamt); // zero-extend
|
||||||
|
idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SRA;
|
||||||
|
end
|
||||||
|
default : rvi_illegal = 1'b1;
|
||||||
|
endcase // funct7
|
||||||
|
end
|
||||||
|
endcase // funct3
|
||||||
|
`ifdef SCR1_RVE_EXT
|
||||||
|
if (instr[11] | instr[19]) rve_illegal = 1'b1;
|
||||||
|
`endif // SCR1_RVE_EXT
|
||||||
|
end // SCR1_OPCODE_OP_IMM
|
||||||
|
|
||||||
|
SCR1_OPCODE_MISC_MEM : begin
|
||||||
|
case (funct3)
|
||||||
|
3'b000 : begin
|
||||||
|
if (~|{instr[31:28], instr[19:15], instr[11:7]}) begin
|
||||||
|
// FENCE = NOP
|
||||||
|
end
|
||||||
|
else rvi_illegal = 1'b1;
|
||||||
|
end
|
||||||
|
3'b001 : begin
|
||||||
|
if (~|{instr[31:15], instr[11:7]}) begin
|
||||||
|
// FENCE.I
|
||||||
|
idu2exu_cmd_o.fencei_req = 1'b1;
|
||||||
|
end
|
||||||
|
else rvi_illegal = 1'b1;
|
||||||
|
end
|
||||||
|
default : rvi_illegal = 1'b1;
|
||||||
|
endcase // funct3
|
||||||
|
end // SCR1_OPCODE_MISC_MEM
|
||||||
|
|
||||||
|
SCR1_OPCODE_BRANCH : begin
|
||||||
|
idu2exu_use_rs1_o = 1'b1;
|
||||||
|
idu2exu_use_rs2_o = 1'b1;
|
||||||
|
`ifndef SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_use_imm_o = 1'b1;
|
||||||
|
`endif // SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_cmd_o.imm = {{20{instr[31]}}, instr[7], instr[30:25], instr[11:8], 1'b0};
|
||||||
|
idu2exu_cmd_o.branch_req = 1'b1;
|
||||||
|
idu2exu_cmd_o.sum2_op = SCR1_SUM2_OP_PC_IMM;
|
||||||
|
idu2exu_cmd_o.ialu_op = SCR1_IALU_OP_REG_REG;
|
||||||
|
case (funct3)
|
||||||
|
3'b000 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SUB_EQ;
|
||||||
|
3'b001 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SUB_NE;
|
||||||
|
3'b100 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SUB_LT;
|
||||||
|
3'b101 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SUB_GE;
|
||||||
|
3'b110 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SUB_LTU;
|
||||||
|
3'b111 : idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SUB_GEU;
|
||||||
|
default : rvi_illegal = 1'b1;
|
||||||
|
endcase // funct3
|
||||||
|
`ifdef SCR1_RVE_EXT
|
||||||
|
if (instr[19] | instr[24]) rve_illegal = 1'b1;
|
||||||
|
`endif // SCR1_RVE_EXT
|
||||||
|
end // SCR1_OPCODE_BRANCH
|
||||||
|
|
||||||
|
SCR1_OPCODE_JALR : begin
|
||||||
|
idu2exu_use_rs1_o = 1'b1;
|
||||||
|
`ifndef SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_use_rd_o = 1'b1;
|
||||||
|
idu2exu_use_imm_o = 1'b1;
|
||||||
|
`endif // SCR1_NO_EXE_STAGE
|
||||||
|
case (funct3)
|
||||||
|
3'b000 : begin
|
||||||
|
// JALR
|
||||||
|
idu2exu_cmd_o.sum2_op = SCR1_SUM2_OP_REG_IMM;
|
||||||
|
idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_INC_PC;
|
||||||
|
idu2exu_cmd_o.jump_req = 1'b1;
|
||||||
|
idu2exu_cmd_o.imm = {{21{instr[31]}}, instr[30:20]};
|
||||||
|
end
|
||||||
|
default : rvi_illegal = 1'b1;
|
||||||
|
endcase
|
||||||
|
`ifdef SCR1_RVE_EXT
|
||||||
|
if (instr[11] | instr[19]) rve_illegal = 1'b1;
|
||||||
|
`endif // SCR1_RVE_EXT
|
||||||
|
end // SCR1_OPCODE_JALR
|
||||||
|
|
||||||
|
SCR1_OPCODE_SYSTEM : begin
|
||||||
|
`ifndef SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_use_rd_o = 1'b1;
|
||||||
|
idu2exu_use_imm_o = 1'b1;
|
||||||
|
`endif // SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_cmd_o.imm = `SCR1_XLEN'({funct3, instr[31:20]}); // {funct3, CSR address}
|
||||||
|
case (funct3)
|
||||||
|
3'b000 : begin
|
||||||
|
`ifndef SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_use_rd_o = 1'b0;
|
||||||
|
idu2exu_use_imm_o = 1'b0;
|
||||||
|
`endif // SCR1_NO_EXE_STAGE
|
||||||
|
case ({instr[19:15], instr[11:7]})
|
||||||
|
10'd0 : begin
|
||||||
|
case (funct12)
|
||||||
|
12'h000 : begin
|
||||||
|
// ECALL
|
||||||
|
idu2exu_cmd_o.exc_req = 1'b1;
|
||||||
|
idu2exu_cmd_o.exc_code = SCR1_EXC_CODE_ECALL_M;
|
||||||
|
end
|
||||||
|
12'h001 : begin
|
||||||
|
// EBREAK
|
||||||
|
idu2exu_cmd_o.exc_req = 1'b1;
|
||||||
|
idu2exu_cmd_o.exc_code = SCR1_EXC_CODE_BREAKPOINT;
|
||||||
|
end
|
||||||
|
12'h302 : begin
|
||||||
|
// MRET
|
||||||
|
idu2exu_cmd_o.mret_req = 1'b1;
|
||||||
|
end
|
||||||
|
12'h105 : begin
|
||||||
|
// WFI
|
||||||
|
idu2exu_cmd_o.wfi_req = 1'b1;
|
||||||
|
end
|
||||||
|
default : rvi_illegal = 1'b1;
|
||||||
|
endcase // funct12
|
||||||
|
end
|
||||||
|
default : rvi_illegal = 1'b1;
|
||||||
|
endcase // {instr[19:15], instr[11:7]}
|
||||||
|
end
|
||||||
|
3'b001 : begin
|
||||||
|
// CSRRW
|
||||||
|
idu2exu_use_rs1_o = 1'b1;
|
||||||
|
idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_CSR;
|
||||||
|
idu2exu_cmd_o.csr_cmd = SCR1_CSR_CMD_WRITE;
|
||||||
|
idu2exu_cmd_o.csr_op = SCR1_CSR_OP_REG;
|
||||||
|
`ifdef SCR1_RVE_EXT
|
||||||
|
if (instr[11] | instr[19]) rve_illegal = 1'b1;
|
||||||
|
`endif // SCR1_RVE_EXT
|
||||||
|
end
|
||||||
|
3'b010 : begin
|
||||||
|
// CSRRS
|
||||||
|
idu2exu_use_rs1_o = 1'b1;
|
||||||
|
idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_CSR;
|
||||||
|
idu2exu_cmd_o.csr_cmd = SCR1_CSR_CMD_SET;
|
||||||
|
idu2exu_cmd_o.csr_op = SCR1_CSR_OP_REG;
|
||||||
|
`ifdef SCR1_RVE_EXT
|
||||||
|
if (instr[11] | instr[19]) rve_illegal = 1'b1;
|
||||||
|
`endif // SCR1_RVE_EXT
|
||||||
|
end
|
||||||
|
3'b011 : begin
|
||||||
|
// CSRRC
|
||||||
|
idu2exu_use_rs1_o = 1'b1;
|
||||||
|
idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_CSR;
|
||||||
|
idu2exu_cmd_o.csr_cmd = SCR1_CSR_CMD_CLEAR;
|
||||||
|
idu2exu_cmd_o.csr_op = SCR1_CSR_OP_REG;
|
||||||
|
`ifdef SCR1_RVE_EXT
|
||||||
|
if (instr[11] | instr[19]) rve_illegal = 1'b1;
|
||||||
|
`endif // SCR1_RVE_EXT
|
||||||
|
end
|
||||||
|
3'b101 : begin
|
||||||
|
// CSRRWI
|
||||||
|
idu2exu_use_rs1_o = 1'b1; // zimm
|
||||||
|
idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_CSR;
|
||||||
|
idu2exu_cmd_o.csr_cmd = SCR1_CSR_CMD_WRITE;
|
||||||
|
idu2exu_cmd_o.csr_op = SCR1_CSR_OP_IMM;
|
||||||
|
`ifdef SCR1_RVE_EXT
|
||||||
|
if (instr[11]) rve_illegal = 1'b1;
|
||||||
|
`endif // SCR1_RVE_EXT
|
||||||
|
end
|
||||||
|
3'b110 : begin
|
||||||
|
// CSRRSI
|
||||||
|
idu2exu_use_rs1_o = 1'b1; // zimm
|
||||||
|
idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_CSR;
|
||||||
|
idu2exu_cmd_o.csr_cmd = SCR1_CSR_CMD_SET;
|
||||||
|
idu2exu_cmd_o.csr_op = SCR1_CSR_OP_IMM;
|
||||||
|
`ifdef SCR1_RVE_EXT
|
||||||
|
if (instr[11]) rve_illegal = 1'b1;
|
||||||
|
`endif // SCR1_RVE_EXT
|
||||||
|
end
|
||||||
|
3'b111 : begin
|
||||||
|
// CSRRCI
|
||||||
|
idu2exu_use_rs1_o = 1'b1; // zimm
|
||||||
|
idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_CSR;
|
||||||
|
idu2exu_cmd_o.csr_cmd = SCR1_CSR_CMD_CLEAR;
|
||||||
|
idu2exu_cmd_o.csr_op = SCR1_CSR_OP_IMM;
|
||||||
|
`ifdef SCR1_RVE_EXT
|
||||||
|
if (instr[11]) rve_illegal = 1'b1;
|
||||||
|
`endif // SCR1_RVE_EXT
|
||||||
|
end
|
||||||
|
default : rvi_illegal = 1'b1;
|
||||||
|
endcase // funct3
|
||||||
|
end // SCR1_OPCODE_SYSTEM
|
||||||
|
|
||||||
|
default : begin
|
||||||
|
rvi_illegal = 1'b1;
|
||||||
|
end
|
||||||
|
endcase // rvi_opcode
|
||||||
|
end // SCR1_INSTR_RVI
|
||||||
|
|
||||||
|
`ifdef SCR1_RVC_EXT
|
||||||
|
|
||||||
|
// Quadrant 0
|
||||||
|
SCR1_INSTR_RVC0 : begin
|
||||||
|
idu2exu_cmd_o.instr_rvc = 1'b1;
|
||||||
|
idu2exu_use_rs1_o = 1'b1;
|
||||||
|
`ifndef SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_use_imm_o = 1'b1;
|
||||||
|
`endif // SCR1_NO_EXE_STAGE
|
||||||
|
case (funct3)
|
||||||
|
3'b000 : begin
|
||||||
|
if (~|instr[12:5]) rvc_illegal = 1'b1;
|
||||||
|
// C.ADDI4SPN
|
||||||
|
`ifndef SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_use_rd_o = 1'b1;
|
||||||
|
`endif // SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_ADD;
|
||||||
|
idu2exu_cmd_o.ialu_op = SCR1_IALU_OP_REG_IMM;
|
||||||
|
idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_IALU;
|
||||||
|
idu2exu_cmd_o.rs1_addr = SCR1_MPRF_SP_ADDR;
|
||||||
|
idu2exu_cmd_o.rd_addr = {2'b01, instr[4:2]};
|
||||||
|
idu2exu_cmd_o.imm = {22'd0, instr[10:7], instr[12:11], instr[5], instr[6], 2'b00};
|
||||||
|
end
|
||||||
|
3'b010 : begin
|
||||||
|
// C.LW
|
||||||
|
`ifndef SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_use_rd_o = 1'b1;
|
||||||
|
`endif // SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_cmd_o.sum2_op = SCR1_SUM2_OP_REG_IMM;
|
||||||
|
idu2exu_cmd_o.lsu_cmd = SCR1_LSU_CMD_LW;
|
||||||
|
idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_LSU;
|
||||||
|
idu2exu_cmd_o.rs1_addr = {2'b01, instr[9:7]};
|
||||||
|
idu2exu_cmd_o.rd_addr = {2'b01, instr[4:2]};
|
||||||
|
idu2exu_cmd_o.imm = {25'd0, instr[5], instr[12:10], instr[6], 2'b00};
|
||||||
|
end
|
||||||
|
3'b110 : begin
|
||||||
|
// C.SW
|
||||||
|
idu2exu_use_rs2_o = 1'b1;
|
||||||
|
idu2exu_cmd_o.sum2_op = SCR1_SUM2_OP_REG_IMM;
|
||||||
|
idu2exu_cmd_o.lsu_cmd = SCR1_LSU_CMD_SW;
|
||||||
|
idu2exu_cmd_o.rs1_addr = {2'b01, instr[9:7]};
|
||||||
|
idu2exu_cmd_o.rs2_addr = {2'b01, instr[4:2]};
|
||||||
|
idu2exu_cmd_o.imm = {25'd0, instr[5], instr[12:10], instr[6], 2'b00};
|
||||||
|
end
|
||||||
|
default : begin
|
||||||
|
rvc_illegal = 1'b1;
|
||||||
|
end
|
||||||
|
endcase // funct3
|
||||||
|
end // Quadrant 0
|
||||||
|
|
||||||
|
// Quadrant 1
|
||||||
|
SCR1_INSTR_RVC1 : begin
|
||||||
|
idu2exu_cmd_o.instr_rvc = 1'b1;
|
||||||
|
`ifndef SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_use_rd_o = 1'b1;
|
||||||
|
idu2exu_use_imm_o = 1'b1;
|
||||||
|
`endif // SCR1_NO_EXE_STAGE
|
||||||
|
case (funct3)
|
||||||
|
3'b000 : begin
|
||||||
|
// C.ADDI / C.NOP
|
||||||
|
idu2exu_use_rs1_o = 1'b1;
|
||||||
|
idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_ADD;
|
||||||
|
idu2exu_cmd_o.ialu_op = SCR1_IALU_OP_REG_IMM;
|
||||||
|
idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_IALU;
|
||||||
|
idu2exu_cmd_o.rs1_addr = instr[11:7];
|
||||||
|
idu2exu_cmd_o.rd_addr = instr[11:7];
|
||||||
|
idu2exu_cmd_o.imm = {{27{instr[12]}}, instr[6:2]};
|
||||||
|
`ifdef SCR1_RVE_EXT
|
||||||
|
if (instr[11]) rve_illegal = 1'b1;
|
||||||
|
`endif // SCR1_RVE_EXT
|
||||||
|
end
|
||||||
|
3'b001 : begin
|
||||||
|
// C.JAL
|
||||||
|
idu2exu_cmd_o.sum2_op = SCR1_SUM2_OP_PC_IMM;
|
||||||
|
idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_INC_PC;
|
||||||
|
idu2exu_cmd_o.jump_req = 1'b1;
|
||||||
|
idu2exu_cmd_o.rd_addr = SCR1_MPRF_RA_ADDR;
|
||||||
|
idu2exu_cmd_o.imm = {{21{instr[12]}}, instr[8], instr[10:9], instr[6], instr[7], instr[2], instr[11], instr[5:3], 1'b0};
|
||||||
|
end
|
||||||
|
3'b010 : begin
|
||||||
|
// C.LI
|
||||||
|
idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_IMM;
|
||||||
|
idu2exu_cmd_o.rd_addr = instr[11:7];
|
||||||
|
idu2exu_cmd_o.imm = {{27{instr[12]}}, instr[6:2]};
|
||||||
|
`ifdef SCR1_RVE_EXT
|
||||||
|
if (instr[11]) rve_illegal = 1'b1;
|
||||||
|
`endif // SCR1_RVE_EXT
|
||||||
|
end
|
||||||
|
3'b011 : begin
|
||||||
|
if (~|{instr[12], instr[6:2]}) rvc_illegal = 1'b1;
|
||||||
|
if (instr[11:7] == SCR1_MPRF_SP_ADDR) begin
|
||||||
|
// C.ADDI16SP
|
||||||
|
idu2exu_use_rs1_o = 1'b1;
|
||||||
|
idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_ADD;
|
||||||
|
idu2exu_cmd_o.ialu_op = SCR1_IALU_OP_REG_IMM;
|
||||||
|
idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_IALU;
|
||||||
|
idu2exu_cmd_o.rs1_addr = SCR1_MPRF_SP_ADDR;
|
||||||
|
idu2exu_cmd_o.rd_addr = SCR1_MPRF_SP_ADDR;
|
||||||
|
idu2exu_cmd_o.imm = {{23{instr[12]}}, instr[4:3], instr[5], instr[2], instr[6], 4'd0};
|
||||||
|
end else begin
|
||||||
|
// C.LUI
|
||||||
|
idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_IMM;
|
||||||
|
idu2exu_cmd_o.rd_addr = instr[11:7];
|
||||||
|
idu2exu_cmd_o.imm = {{15{instr[12]}}, instr[6:2], 12'd0};
|
||||||
|
`ifdef SCR1_RVE_EXT
|
||||||
|
if (instr[11]) rve_illegal = 1'b1;
|
||||||
|
`endif // SCR1_RVE_EXT
|
||||||
|
end
|
||||||
|
end
|
||||||
|
3'b100 : begin
|
||||||
|
idu2exu_cmd_o.rs1_addr = {2'b01, instr[9:7]};
|
||||||
|
idu2exu_cmd_o.rd_addr = {2'b01, instr[9:7]};
|
||||||
|
idu2exu_cmd_o.rs2_addr = {2'b01, instr[4:2]};
|
||||||
|
idu2exu_use_rs1_o = 1'b1;
|
||||||
|
`ifndef SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_use_rd_o = 1'b1;
|
||||||
|
`endif // SCR1_NO_EXE_STAGE
|
||||||
|
case (instr[11:10])
|
||||||
|
2'b00 : begin
|
||||||
|
if (instr[12]) rvc_illegal = 1'b1;
|
||||||
|
// C.SRLI
|
||||||
|
`ifndef SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_use_imm_o = 1'b1;
|
||||||
|
`endif // SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_cmd_o.imm = {27'd0, instr[6:2]};
|
||||||
|
idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SRL;
|
||||||
|
idu2exu_cmd_o.ialu_op = SCR1_IALU_OP_REG_IMM;
|
||||||
|
idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_IALU;
|
||||||
|
end
|
||||||
|
2'b01 : begin
|
||||||
|
if (instr[12]) rvc_illegal = 1'b1;
|
||||||
|
// C.SRAI
|
||||||
|
`ifndef SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_use_imm_o = 1'b1;
|
||||||
|
`endif // SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_cmd_o.imm = {27'd0, instr[6:2]};
|
||||||
|
idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SRA;
|
||||||
|
idu2exu_cmd_o.ialu_op = SCR1_IALU_OP_REG_IMM;
|
||||||
|
idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_IALU;
|
||||||
|
end
|
||||||
|
2'b10 : begin
|
||||||
|
// C.ANDI
|
||||||
|
`ifndef SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_use_imm_o = 1'b1;
|
||||||
|
`endif // SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_AND;
|
||||||
|
idu2exu_cmd_o.ialu_op = SCR1_IALU_OP_REG_IMM;
|
||||||
|
idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_IALU;
|
||||||
|
idu2exu_cmd_o.imm = {{27{instr[12]}}, instr[6:2]};
|
||||||
|
end
|
||||||
|
2'b11 : begin
|
||||||
|
idu2exu_use_rs2_o = 1'b1;
|
||||||
|
case ({instr[12], instr[6:5]})
|
||||||
|
3'b000 : begin
|
||||||
|
// C.SUB
|
||||||
|
idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SUB;
|
||||||
|
idu2exu_cmd_o.ialu_op = SCR1_IALU_OP_REG_REG;
|
||||||
|
idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_IALU;
|
||||||
|
end
|
||||||
|
3'b001 : begin
|
||||||
|
// C.XOR
|
||||||
|
idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_XOR;
|
||||||
|
idu2exu_cmd_o.ialu_op = SCR1_IALU_OP_REG_REG;
|
||||||
|
idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_IALU;
|
||||||
|
end
|
||||||
|
3'b010 : begin
|
||||||
|
// C.OR
|
||||||
|
idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_OR;
|
||||||
|
idu2exu_cmd_o.ialu_op = SCR1_IALU_OP_REG_REG;
|
||||||
|
idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_IALU;
|
||||||
|
end
|
||||||
|
3'b011 : begin
|
||||||
|
// C.AND
|
||||||
|
idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_AND;
|
||||||
|
idu2exu_cmd_o.ialu_op = SCR1_IALU_OP_REG_REG;
|
||||||
|
idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_IALU;
|
||||||
|
end
|
||||||
|
default : begin
|
||||||
|
rvc_illegal = 1'b1;
|
||||||
|
end
|
||||||
|
endcase // {instr[12], instr[6:5]}
|
||||||
|
end
|
||||||
|
endcase // instr[11:10]
|
||||||
|
end // funct3 == 3'b100
|
||||||
|
3'b101 : begin
|
||||||
|
// C.J
|
||||||
|
`ifndef SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_use_imm_o = 1'b1;
|
||||||
|
`endif // SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_cmd_o.sum2_op = SCR1_SUM2_OP_PC_IMM;
|
||||||
|
idu2exu_cmd_o.jump_req = 1'b1;
|
||||||
|
idu2exu_cmd_o.imm = {{21{instr[12]}}, instr[8], instr[10:9], instr[6], instr[7], instr[2], instr[11], instr[5:3], 1'b0};
|
||||||
|
end
|
||||||
|
3'b110 : begin
|
||||||
|
// C.BEQZ
|
||||||
|
idu2exu_use_rs1_o = 1'b1;
|
||||||
|
idu2exu_use_rs2_o = 1'b1;
|
||||||
|
`ifndef SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_use_imm_o = 1'b1;
|
||||||
|
`endif // SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SUB_EQ;
|
||||||
|
idu2exu_cmd_o.ialu_op = SCR1_IALU_OP_REG_REG;
|
||||||
|
idu2exu_cmd_o.sum2_op = SCR1_SUM2_OP_PC_IMM;
|
||||||
|
idu2exu_cmd_o.branch_req = 1'b1;
|
||||||
|
idu2exu_cmd_o.rs1_addr = {2'b01, instr[9:7]};
|
||||||
|
idu2exu_cmd_o.rs2_addr = SCR1_MPRF_ZERO_ADDR;
|
||||||
|
idu2exu_cmd_o.imm = {{24{instr[12]}}, instr[6:5], instr[2], instr[11:10], instr[4:3], 1'b0};
|
||||||
|
end
|
||||||
|
3'b111 : begin
|
||||||
|
// C.BNEZ
|
||||||
|
idu2exu_use_rs1_o = 1'b1;
|
||||||
|
idu2exu_use_rs2_o = 1'b1;
|
||||||
|
`ifndef SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_use_imm_o = 1'b1;
|
||||||
|
`endif // SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SUB_NE;
|
||||||
|
idu2exu_cmd_o.ialu_op = SCR1_IALU_OP_REG_REG;
|
||||||
|
idu2exu_cmd_o.sum2_op = SCR1_SUM2_OP_PC_IMM;
|
||||||
|
idu2exu_cmd_o.branch_req = 1'b1;
|
||||||
|
idu2exu_cmd_o.rs1_addr = {2'b01, instr[9:7]};
|
||||||
|
idu2exu_cmd_o.rs2_addr = SCR1_MPRF_ZERO_ADDR;
|
||||||
|
idu2exu_cmd_o.imm = {{24{instr[12]}}, instr[6:5], instr[2], instr[11:10], instr[4:3], 1'b0};
|
||||||
|
end
|
||||||
|
endcase // funct3
|
||||||
|
end // Quadrant 1
|
||||||
|
|
||||||
|
// Quadrant 2
|
||||||
|
SCR1_INSTR_RVC2 : begin
|
||||||
|
idu2exu_cmd_o.instr_rvc = 1'b1;
|
||||||
|
idu2exu_use_rs1_o = 1'b1;
|
||||||
|
case (funct3)
|
||||||
|
3'b000 : begin
|
||||||
|
if (instr[12]) rvc_illegal = 1'b1;
|
||||||
|
// C.SLLI
|
||||||
|
`ifndef SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_use_rd_o = 1'b1;
|
||||||
|
idu2exu_use_imm_o = 1'b1;
|
||||||
|
`endif // SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_cmd_o.rs1_addr = instr[11:7];
|
||||||
|
idu2exu_cmd_o.rd_addr = instr[11:7];
|
||||||
|
idu2exu_cmd_o.imm = {27'd0, instr[6:2]};
|
||||||
|
idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_SLL;
|
||||||
|
idu2exu_cmd_o.ialu_op = SCR1_IALU_OP_REG_IMM;
|
||||||
|
idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_IALU;
|
||||||
|
`ifdef SCR1_RVE_EXT
|
||||||
|
if (instr[11]) rve_illegal = 1'b1;
|
||||||
|
`endif // SCR1_RVE_EXT
|
||||||
|
end
|
||||||
|
3'b010 : begin
|
||||||
|
if (~|instr[11:7]) rvc_illegal = 1'b1;
|
||||||
|
// C.LWSP
|
||||||
|
`ifndef SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_use_rd_o = 1'b1;
|
||||||
|
idu2exu_use_imm_o = 1'b1;
|
||||||
|
`endif // SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_cmd_o.sum2_op = SCR1_SUM2_OP_REG_IMM;
|
||||||
|
idu2exu_cmd_o.lsu_cmd = SCR1_LSU_CMD_LW;
|
||||||
|
idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_LSU;
|
||||||
|
idu2exu_cmd_o.rs1_addr = SCR1_MPRF_SP_ADDR;
|
||||||
|
idu2exu_cmd_o.rd_addr = instr[11:7];
|
||||||
|
idu2exu_cmd_o.imm = {24'd0, instr[3:2], instr[12], instr[6:4], 2'b00};
|
||||||
|
`ifdef SCR1_RVE_EXT
|
||||||
|
if (instr[11]) rve_illegal = 1'b1;
|
||||||
|
`endif // SCR1_RVE_EXT
|
||||||
|
end
|
||||||
|
3'b100 : begin
|
||||||
|
if (~instr[12]) begin
|
||||||
|
if (|instr[6:2]) begin
|
||||||
|
// C.MV
|
||||||
|
idu2exu_use_rs2_o = 1'b1;
|
||||||
|
`ifndef SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_use_rd_o = 1'b1;
|
||||||
|
`endif // SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_ADD;
|
||||||
|
idu2exu_cmd_o.ialu_op = SCR1_IALU_OP_REG_REG;
|
||||||
|
idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_IALU;
|
||||||
|
idu2exu_cmd_o.rs1_addr = SCR1_MPRF_ZERO_ADDR;
|
||||||
|
idu2exu_cmd_o.rs2_addr = instr[6:2];
|
||||||
|
idu2exu_cmd_o.rd_addr = instr[11:7];
|
||||||
|
`ifdef SCR1_RVE_EXT
|
||||||
|
if (instr[11]|instr[6]) rve_illegal = 1'b1;
|
||||||
|
`endif // SCR1_RVE_EXT
|
||||||
|
end else begin
|
||||||
|
if (~|instr[11:7]) rvc_illegal = 1'b1;
|
||||||
|
// C.JR
|
||||||
|
`ifndef SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_use_imm_o = 1'b1;
|
||||||
|
`endif // SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_cmd_o.sum2_op = SCR1_SUM2_OP_REG_IMM;
|
||||||
|
idu2exu_cmd_o.jump_req = 1'b1;
|
||||||
|
idu2exu_cmd_o.rs1_addr = instr[11:7];
|
||||||
|
idu2exu_cmd_o.imm = 0;
|
||||||
|
`ifdef SCR1_RVE_EXT
|
||||||
|
if (instr[11]) rve_illegal = 1'b1;
|
||||||
|
`endif // SCR1_RVE_EXT
|
||||||
|
end
|
||||||
|
end else begin // instr[12] == 1
|
||||||
|
if (~|instr[11:2]) begin
|
||||||
|
// C.EBREAK
|
||||||
|
idu2exu_cmd_o.exc_req = 1'b1;
|
||||||
|
idu2exu_cmd_o.exc_code = SCR1_EXC_CODE_BREAKPOINT;
|
||||||
|
end else if (~|instr[6:2]) begin
|
||||||
|
// C.JALR
|
||||||
|
idu2exu_use_rs1_o = 1'b1;
|
||||||
|
`ifndef SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_use_rd_o = 1'b1;
|
||||||
|
idu2exu_use_imm_o = 1'b1;
|
||||||
|
`endif // SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_cmd_o.sum2_op = SCR1_SUM2_OP_REG_IMM;
|
||||||
|
idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_INC_PC;
|
||||||
|
idu2exu_cmd_o.jump_req = 1'b1;
|
||||||
|
idu2exu_cmd_o.rs1_addr = instr[11:7];
|
||||||
|
idu2exu_cmd_o.rd_addr = SCR1_MPRF_RA_ADDR;
|
||||||
|
idu2exu_cmd_o.imm = 0;
|
||||||
|
`ifdef SCR1_RVE_EXT
|
||||||
|
if (instr[11]) rve_illegal = 1'b1;
|
||||||
|
`endif // SCR1_RVE_EXT
|
||||||
|
end else begin
|
||||||
|
// C.ADD
|
||||||
|
idu2exu_use_rs1_o = 1'b1;
|
||||||
|
idu2exu_use_rs2_o = 1'b1;
|
||||||
|
`ifndef SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_use_rd_o = 1'b1;
|
||||||
|
`endif // SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_ADD;
|
||||||
|
idu2exu_cmd_o.ialu_op = SCR1_IALU_OP_REG_REG;
|
||||||
|
idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_IALU;
|
||||||
|
idu2exu_cmd_o.rs1_addr = instr[11:7];
|
||||||
|
idu2exu_cmd_o.rs2_addr = instr[6:2];
|
||||||
|
idu2exu_cmd_o.rd_addr = instr[11:7];
|
||||||
|
`ifdef SCR1_RVE_EXT
|
||||||
|
if (instr[11]|instr[6]) rve_illegal = 1'b1;
|
||||||
|
`endif // SCR1_RVE_EXT
|
||||||
|
end
|
||||||
|
end // instr[12] == 1
|
||||||
|
end
|
||||||
|
3'b110 : begin
|
||||||
|
// C.SWSP
|
||||||
|
idu2exu_use_rs1_o = 1'b1;
|
||||||
|
idu2exu_use_rs2_o = 1'b1;
|
||||||
|
`ifndef SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_use_imm_o = 1'b1;
|
||||||
|
`endif // SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_cmd_o.sum2_op = SCR1_SUM2_OP_REG_IMM;
|
||||||
|
idu2exu_cmd_o.lsu_cmd = SCR1_LSU_CMD_SW;
|
||||||
|
idu2exu_cmd_o.rs1_addr = SCR1_MPRF_SP_ADDR;
|
||||||
|
idu2exu_cmd_o.rs2_addr = instr[6:2];
|
||||||
|
idu2exu_cmd_o.imm = {24'd0, instr[8:7], instr[12:9], 2'b00};
|
||||||
|
`ifdef SCR1_RVE_EXT
|
||||||
|
if (instr[6]) rve_illegal = 1'b1;
|
||||||
|
`endif // SCR1_RVE_EXT
|
||||||
|
end
|
||||||
|
default : begin
|
||||||
|
rvc_illegal = 1'b1;
|
||||||
|
end
|
||||||
|
endcase // funct3
|
||||||
|
end // Quadrant 2
|
||||||
|
|
||||||
|
default : begin
|
||||||
|
`ifdef SCR1_XPROP_EN
|
||||||
|
rvi_illegal = 1'b1;
|
||||||
|
`endif // SCR1_XPROP_EN
|
||||||
|
end
|
||||||
|
`else // SCR1_RVC_EXT
|
||||||
|
default : begin
|
||||||
|
idu2exu_cmd_o.instr_rvc = 1'b1;
|
||||||
|
rvi_illegal = 1'b1;
|
||||||
|
end
|
||||||
|
`endif // SCR1_RVC_EXT
|
||||||
|
endcase // instr_type
|
||||||
|
end // no imem fault
|
||||||
|
|
||||||
|
// At this point the instruction is fully decoded
|
||||||
|
// given that no imem fault has happened
|
||||||
|
|
||||||
|
// Check illegal instruction
|
||||||
|
if (
|
||||||
|
rvi_illegal
|
||||||
|
`ifdef SCR1_RVC_EXT
|
||||||
|
| rvc_illegal
|
||||||
|
`endif
|
||||||
|
`ifdef SCR1_RVE_EXT
|
||||||
|
| rve_illegal
|
||||||
|
`endif
|
||||||
|
) begin
|
||||||
|
idu2exu_cmd_o.ialu_cmd = SCR1_IALU_CMD_NONE;
|
||||||
|
idu2exu_cmd_o.lsu_cmd = SCR1_LSU_CMD_NONE;
|
||||||
|
idu2exu_cmd_o.csr_cmd = SCR1_CSR_CMD_NONE;
|
||||||
|
idu2exu_cmd_o.rd_wb_sel = SCR1_RD_WB_NONE;
|
||||||
|
idu2exu_cmd_o.jump_req = 1'b0;
|
||||||
|
idu2exu_cmd_o.branch_req = 1'b0;
|
||||||
|
idu2exu_cmd_o.mret_req = 1'b0;
|
||||||
|
idu2exu_cmd_o.fencei_req = 1'b0;
|
||||||
|
idu2exu_cmd_o.wfi_req = 1'b0;
|
||||||
|
|
||||||
|
idu2exu_use_rs1_o = 1'b0;
|
||||||
|
idu2exu_use_rs2_o = 1'b0;
|
||||||
|
`ifndef SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_use_rd_o = 1'b0;
|
||||||
|
`endif // SCR1_NO_EXE_STAGE
|
||||||
|
|
||||||
|
`ifndef SCR1_MTVAL_ILLEGAL_INSTR_EN
|
||||||
|
idu2exu_use_imm_o = 1'b0;
|
||||||
|
`else // SCR1_MTVAL_ILLEGAL_INSTR_EN
|
||||||
|
`ifndef SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_use_imm_o = 1'b1;
|
||||||
|
`endif // SCR1_NO_EXE_STAGE
|
||||||
|
idu2exu_cmd_o.imm = instr;
|
||||||
|
`endif // SCR1_MTVAL_ILLEGAL_INSTR_EN
|
||||||
|
|
||||||
|
idu2exu_cmd_o.exc_req = 1'b1;
|
||||||
|
idu2exu_cmd_o.exc_code = SCR1_EXC_CODE_ILLEGAL_INSTR;
|
||||||
|
end
|
||||||
|
|
||||||
|
end // RV32I(MC) decode
|
||||||
|
|
||||||
|
`ifdef SCR1_TRGT_SIMULATION
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Assertion
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// X checks
|
||||||
|
|
||||||
|
SCR1_SVA_IDU_XCHECK : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
!$isunknown({ifu2idu_vd_i, exu2idu_rdy_i})
|
||||||
|
) else $error("IDU Error: unknown values");
|
||||||
|
|
||||||
|
// Behavior checks
|
||||||
|
|
||||||
|
SCR1_SVA_IDU_IALU_CMD_RANGE : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
(ifu2idu_vd_i & ~ifu2idu_imem_err_i) |->
|
||||||
|
((idu2exu_cmd_o.ialu_cmd >= SCR1_IALU_CMD_NONE) &
|
||||||
|
(idu2exu_cmd_o.ialu_cmd <=
|
||||||
|
`ifdef SCR1_RVM_EXT
|
||||||
|
SCR1_IALU_CMD_REMU
|
||||||
|
`else
|
||||||
|
SCR1_IALU_CMD_SRA
|
||||||
|
`endif // SCR1_RVM_EXT
|
||||||
|
))
|
||||||
|
) else $error("IDU Error: IALU_CMD out of range");
|
||||||
|
|
||||||
|
`endif // SCR1_TRGT_SIMULATION
|
||||||
|
|
||||||
|
endmodule : scr1_pipe_idu
|
||||||
826
src_ref/core/pipeline/scr1_pipe_ifu.sv
Normal file
826
src_ref/core/pipeline/scr1_pipe_ifu.sv
Normal file
@@ -0,0 +1,826 @@
|
|||||||
|
/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
|
||||||
|
/// @file <scr1_pipe_ifu.sv>
|
||||||
|
/// @brief Instruction Fetch Unit (IFU)
|
||||||
|
///
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Functionality:
|
||||||
|
// - Controls instruction fetching process:
|
||||||
|
// - Fetches instructions either from IMEM or from Program Buffer, supporting
|
||||||
|
// pending IMEM instructions handling
|
||||||
|
// - Handles new PC misalignment and constructs the correct instruction (supports
|
||||||
|
// RVI and RVC instructions)
|
||||||
|
// - Either stores instructions in the instruction queue or bypasses to the
|
||||||
|
// IDU if the corresponding option is used
|
||||||
|
// - Flushes instruction queue if requested
|
||||||
|
//
|
||||||
|
// Structure:
|
||||||
|
// - Instruction queue
|
||||||
|
// - IFU FSM
|
||||||
|
// - IFU <-> IMEM i/f
|
||||||
|
// - IFU <-> IDU i/f
|
||||||
|
// - IFU <-> HDU i/f
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
`include "scr1_memif.svh"
|
||||||
|
`include "scr1_arch_description.svh"
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
`include "scr1_hdu.svh"
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
|
||||||
|
module scr1_pipe_ifu
|
||||||
|
(
|
||||||
|
// Control signals
|
||||||
|
input logic rst_n, // IFU reset
|
||||||
|
input logic clk, // IFU clock
|
||||||
|
input logic pipe2ifu_stop_fetch_i, // Stop instruction fetch
|
||||||
|
|
||||||
|
// IFU <-> IMEM interface
|
||||||
|
input logic imem2ifu_req_ack_i, // Instruction memory request acknowledgement
|
||||||
|
output logic ifu2imem_req_o, // Instruction memory request
|
||||||
|
output type_scr1_mem_cmd_e ifu2imem_cmd_o, // Instruction memory command (READ/WRITE)
|
||||||
|
output logic [`SCR1_IMEM_AWIDTH-1:0] ifu2imem_addr_o, // Instruction memory address
|
||||||
|
input logic [`SCR1_IMEM_DWIDTH-1:0] imem2ifu_rdata_i, // Instruction memory read data
|
||||||
|
input type_scr1_mem_resp_e imem2ifu_resp_i, // Instruction memory response
|
||||||
|
|
||||||
|
// IFU <-> EXU New PC interface
|
||||||
|
input logic exu2ifu_pc_new_req_i, // New PC request (jumps, branches, traps etc)
|
||||||
|
input logic [`SCR1_XLEN-1:0] exu2ifu_pc_new_i, // New PC
|
||||||
|
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
// IFU <-> HDU Program Buffer interface
|
||||||
|
input logic hdu2ifu_pbuf_fetch_i, // Fetch instructions provided by Program Buffer
|
||||||
|
output logic ifu2hdu_pbuf_rdy_o, // Program Buffer Instruction i/f ready
|
||||||
|
input logic hdu2ifu_pbuf_vd_i, // Program Buffer Instruction valid
|
||||||
|
input logic hdu2ifu_pbuf_err_i, // Program Buffer Instruction i/f error
|
||||||
|
input logic [SCR1_HDU_CORE_INSTR_WIDTH-1:0] hdu2ifu_pbuf_instr_i, // Program Buffer Instruction itself
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
|
||||||
|
`ifdef SCR1_CLKCTRL_EN
|
||||||
|
output logic ifu2pipe_imem_txns_pnd_o, // There are pending imem transactions
|
||||||
|
`endif // SCR1_CLKCTRL_EN
|
||||||
|
|
||||||
|
// IFU <-> IDU interface
|
||||||
|
input logic idu2ifu_rdy_i, // IDU ready for new data
|
||||||
|
output logic [`SCR1_IMEM_DWIDTH-1:0] ifu2idu_instr_o, // IFU instruction
|
||||||
|
output logic ifu2idu_imem_err_o, // Instruction access fault exception
|
||||||
|
output logic ifu2idu_err_rvi_hi_o, // 1 - imem fault when trying to fetch second half of an unaligned RVI instruction
|
||||||
|
output logic ifu2idu_vd_o // IFU request
|
||||||
|
);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Local parameters declaration
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
localparam SCR1_IFU_Q_SIZE_WORD = 2;
|
||||||
|
localparam SCR1_IFU_Q_SIZE_HALF = SCR1_IFU_Q_SIZE_WORD * 2;
|
||||||
|
localparam SCR1_TXN_CNT_W = 3;
|
||||||
|
|
||||||
|
localparam SCR1_IFU_QUEUE_ADR_W = $clog2(SCR1_IFU_Q_SIZE_HALF);
|
||||||
|
localparam SCR1_IFU_QUEUE_PTR_W = SCR1_IFU_QUEUE_ADR_W + 1;
|
||||||
|
|
||||||
|
localparam SCR1_IFU_Q_FREE_H_W = $clog2(SCR1_IFU_Q_SIZE_HALF + 1);
|
||||||
|
localparam SCR1_IFU_Q_FREE_W_W = $clog2(SCR1_IFU_Q_SIZE_WORD + 1);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Local types declaration
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
typedef enum logic {
|
||||||
|
SCR1_IFU_FSM_IDLE,
|
||||||
|
SCR1_IFU_FSM_FETCH
|
||||||
|
} type_scr1_ifu_fsm_e;
|
||||||
|
|
||||||
|
typedef enum logic[1:0] {
|
||||||
|
SCR1_IFU_QUEUE_WR_NONE, // No write to queue
|
||||||
|
SCR1_IFU_QUEUE_WR_FULL, // Write 32 rdata bits to queue
|
||||||
|
SCR1_IFU_QUEUE_WR_HI // Write 16 upper rdata bits to queue
|
||||||
|
} type_scr1_ifu_queue_wr_e;
|
||||||
|
|
||||||
|
typedef enum logic[1:0] {
|
||||||
|
SCR1_IFU_QUEUE_RD_NONE, // No queue read
|
||||||
|
SCR1_IFU_QUEUE_RD_HWORD, // Read halfword
|
||||||
|
SCR1_IFU_QUEUE_RD_WORD // Read word
|
||||||
|
} type_scr1_ifu_queue_rd_e;
|
||||||
|
|
||||||
|
`ifdef SCR1_NO_DEC_STAGE
|
||||||
|
typedef enum logic[1:0] {
|
||||||
|
SCR1_BYPASS_NONE, // No bypass
|
||||||
|
SCR1_BYPASS_RVC, // Bypass RVC
|
||||||
|
SCR1_BYPASS_RVI_RDATA_QUEUE, // Bypass RVI, rdata+queue
|
||||||
|
SCR1_BYPASS_RVI_RDATA // Bypass RVI, rdata only
|
||||||
|
} type_scr1_bypass_e;
|
||||||
|
`endif // SCR1_NO_DEC_STAGE
|
||||||
|
|
||||||
|
typedef enum logic [2:0] {
|
||||||
|
// SCR1_IFU_INSTR_<UPPER_16_BITS>_<LOWER_16_BITS>
|
||||||
|
SCR1_IFU_INSTR_NONE, // No valid instruction
|
||||||
|
SCR1_IFU_INSTR_RVI_HI_RVI_LO, // Full RV32I instruction
|
||||||
|
SCR1_IFU_INSTR_RVC_RVC,
|
||||||
|
SCR1_IFU_INSTR_RVI_LO_RVC,
|
||||||
|
SCR1_IFU_INSTR_RVC_RVI_HI,
|
||||||
|
SCR1_IFU_INSTR_RVI_LO_RVI_HI,
|
||||||
|
SCR1_IFU_INSTR_RVC_NV, // Instruction after unaligned new_pc
|
||||||
|
SCR1_IFU_INSTR_RVI_LO_NV // Instruction after unaligned new_pc
|
||||||
|
} type_scr1_ifu_instr_e;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Local signals declaration
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Instruction queue signals
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// New PC unaligned flag register
|
||||||
|
logic new_pc_unaligned_ff;
|
||||||
|
logic new_pc_unaligned_next;
|
||||||
|
logic new_pc_unaligned_upd;
|
||||||
|
|
||||||
|
// IMEM instruction type decoder
|
||||||
|
logic instr_hi_is_rvi;
|
||||||
|
logic instr_lo_is_rvi;
|
||||||
|
type_scr1_ifu_instr_e instr_type;
|
||||||
|
|
||||||
|
// Register to store if the previous IMEM instruction had low part of RVI instruction
|
||||||
|
// in its high part
|
||||||
|
logic instr_hi_rvi_lo_ff;
|
||||||
|
logic instr_hi_rvi_lo_next;
|
||||||
|
|
||||||
|
// Queue read/write size decoders
|
||||||
|
type_scr1_ifu_queue_rd_e q_rd_size;
|
||||||
|
logic q_rd_vd;
|
||||||
|
logic q_rd_none;
|
||||||
|
logic q_rd_hword;
|
||||||
|
type_scr1_ifu_queue_wr_e q_wr_size;
|
||||||
|
logic q_wr_none;
|
||||||
|
logic q_wr_full;
|
||||||
|
|
||||||
|
// Write/read pointer registers
|
||||||
|
logic [SCR1_IFU_QUEUE_PTR_W-1:0] q_rptr;
|
||||||
|
logic [SCR1_IFU_QUEUE_PTR_W-1:0] q_rptr_next;
|
||||||
|
logic q_rptr_upd;
|
||||||
|
logic [SCR1_IFU_QUEUE_PTR_W-1:0] q_wptr;
|
||||||
|
logic [SCR1_IFU_QUEUE_PTR_W-1:0] q_wptr_next;
|
||||||
|
logic q_wptr_upd;
|
||||||
|
|
||||||
|
// Instruction queue control signals
|
||||||
|
logic q_wr_en;
|
||||||
|
logic q_flush_req;
|
||||||
|
|
||||||
|
// Queue data registers
|
||||||
|
logic [`SCR1_IMEM_DWIDTH/2-1:0] q_data [SCR1_IFU_Q_SIZE_HALF];
|
||||||
|
logic [`SCR1_IMEM_DWIDTH/2-1:0] q_data_head;
|
||||||
|
logic [`SCR1_IMEM_DWIDTH/2-1:0] q_data_next;
|
||||||
|
|
||||||
|
// Queue error flags registers
|
||||||
|
logic q_err [SCR1_IFU_Q_SIZE_HALF];
|
||||||
|
logic q_err_head;
|
||||||
|
logic q_err_next;
|
||||||
|
|
||||||
|
// Instruction queue status signals
|
||||||
|
logic q_is_empty;
|
||||||
|
logic q_has_free_slots;
|
||||||
|
logic q_has_1_ocpd_hw;
|
||||||
|
logic q_head_is_rvc;
|
||||||
|
logic q_head_is_rvi;
|
||||||
|
logic [SCR1_IFU_Q_FREE_H_W-1:0] q_ocpd_h;
|
||||||
|
logic [SCR1_IFU_Q_FREE_H_W-1:0] q_free_h_next;
|
||||||
|
logic [SCR1_IFU_Q_FREE_W_W-1:0] q_free_w_next;
|
||||||
|
|
||||||
|
// IFU FSM signals
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// IFU FSM control signals
|
||||||
|
logic ifu_fetch_req;
|
||||||
|
logic ifu_stop_req;
|
||||||
|
|
||||||
|
type_scr1_ifu_fsm_e ifu_fsm_curr;
|
||||||
|
type_scr1_ifu_fsm_e ifu_fsm_next;
|
||||||
|
logic ifu_fsm_fetch;
|
||||||
|
|
||||||
|
// IMEM signals
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// IMEM response signals
|
||||||
|
logic imem_resp_ok;
|
||||||
|
logic imem_resp_er;
|
||||||
|
logic imem_resp_er_discard_pnd;
|
||||||
|
logic imem_resp_discard_req;
|
||||||
|
logic imem_resp_received;
|
||||||
|
logic imem_resp_vd;
|
||||||
|
logic imem_handshake_done;
|
||||||
|
|
||||||
|
logic [15:0] imem_rdata_lo;
|
||||||
|
logic [31:16] imem_rdata_hi;
|
||||||
|
|
||||||
|
// IMEM address signals
|
||||||
|
logic imem_addr_upd;
|
||||||
|
logic [`SCR1_XLEN-1:2] imem_addr_ff;
|
||||||
|
logic [`SCR1_XLEN-1:2] imem_addr_next;
|
||||||
|
|
||||||
|
// IMEM pending transactions counter
|
||||||
|
logic imem_pnd_txns_cnt_upd;
|
||||||
|
logic [SCR1_TXN_CNT_W-1:0] imem_pnd_txns_cnt;
|
||||||
|
logic [SCR1_TXN_CNT_W-1:0] imem_pnd_txns_cnt_next;
|
||||||
|
logic [SCR1_TXN_CNT_W-1:0] imem_vd_pnd_txns_cnt;
|
||||||
|
logic imem_pnd_txns_q_full;
|
||||||
|
|
||||||
|
// IMEM responses discard counter
|
||||||
|
logic imem_resp_discard_cnt_upd;
|
||||||
|
logic [SCR1_TXN_CNT_W-1:0] imem_resp_discard_cnt;
|
||||||
|
logic [SCR1_TXN_CNT_W-1:0] imem_resp_discard_cnt_next;
|
||||||
|
|
||||||
|
`ifdef SCR1_NEW_PC_REG
|
||||||
|
logic new_pc_req_ff;
|
||||||
|
`endif // SCR1_NEW_PC_REG
|
||||||
|
|
||||||
|
// Instruction bypass signals
|
||||||
|
`ifdef SCR1_NO_DEC_STAGE
|
||||||
|
type_scr1_bypass_e instr_bypass_type;
|
||||||
|
logic instr_bypass_vd;
|
||||||
|
`endif // SCR1_NO_DEC_STAGE
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Instruction queue
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Instruction queue consists of the following functional units:
|
||||||
|
// - New PC unaligned flag register
|
||||||
|
// - Instruction type decoder, including register to store if the previous
|
||||||
|
// IMEM instruction had low part of RVI instruction in its high part
|
||||||
|
// - Read/write size decoders
|
||||||
|
// - Read/write pointer registers
|
||||||
|
// - Data and error flag registers
|
||||||
|
// - Status logic
|
||||||
|
//
|
||||||
|
|
||||||
|
// New PC unaligned flag register
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign new_pc_unaligned_upd = exu2ifu_pc_new_req_i | imem_resp_vd;
|
||||||
|
|
||||||
|
always_ff @(posedge clk, negedge rst_n) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
new_pc_unaligned_ff <= 1'b0;
|
||||||
|
end else if (new_pc_unaligned_upd) begin
|
||||||
|
new_pc_unaligned_ff <= new_pc_unaligned_next;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign new_pc_unaligned_next = exu2ifu_pc_new_req_i ? exu2ifu_pc_new_i[1]
|
||||||
|
: ~imem_resp_vd ? new_pc_unaligned_ff
|
||||||
|
: 1'b0;
|
||||||
|
|
||||||
|
// Instruction type decoder
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign instr_hi_is_rvi = &imem2ifu_rdata_i[17:16];
|
||||||
|
assign instr_lo_is_rvi = &imem2ifu_rdata_i[1:0];
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
instr_type = SCR1_IFU_INSTR_NONE;
|
||||||
|
|
||||||
|
if (imem_resp_ok & ~imem_resp_discard_req) begin
|
||||||
|
if (new_pc_unaligned_ff) begin
|
||||||
|
instr_type = instr_hi_is_rvi ? SCR1_IFU_INSTR_RVI_LO_NV
|
||||||
|
: SCR1_IFU_INSTR_RVC_NV;
|
||||||
|
end else begin // ~new_pc_unaligned_ff
|
||||||
|
if (instr_hi_rvi_lo_ff) begin
|
||||||
|
instr_type = instr_hi_is_rvi ? SCR1_IFU_INSTR_RVI_LO_RVI_HI
|
||||||
|
: SCR1_IFU_INSTR_RVC_RVI_HI;
|
||||||
|
end else begin // SCR1_OTHER
|
||||||
|
case ({instr_hi_is_rvi, instr_lo_is_rvi})
|
||||||
|
2'b00 : instr_type = SCR1_IFU_INSTR_RVC_RVC;
|
||||||
|
2'b10 : instr_type = SCR1_IFU_INSTR_RVI_LO_RVC;
|
||||||
|
default : instr_type = SCR1_IFU_INSTR_RVI_HI_RVI_LO;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// Register to store if the previous IMEM instruction had low part of RVI
|
||||||
|
// instruction in its high part
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
always_ff @(posedge clk, negedge rst_n) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
instr_hi_rvi_lo_ff <= 1'b0;
|
||||||
|
end else begin
|
||||||
|
if (exu2ifu_pc_new_req_i) begin
|
||||||
|
instr_hi_rvi_lo_ff <= 1'b0;
|
||||||
|
end else if (imem_resp_vd) begin
|
||||||
|
instr_hi_rvi_lo_ff <= instr_hi_rvi_lo_next;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign instr_hi_rvi_lo_next = (instr_type == SCR1_IFU_INSTR_RVI_LO_NV)
|
||||||
|
| (instr_type == SCR1_IFU_INSTR_RVI_LO_RVI_HI)
|
||||||
|
| (instr_type == SCR1_IFU_INSTR_RVI_LO_RVC);
|
||||||
|
|
||||||
|
// Queue write/read size decoders
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Queue read size decoder
|
||||||
|
assign q_rd_vd = ~q_is_empty & ifu2idu_vd_o & idu2ifu_rdy_i;
|
||||||
|
assign q_rd_hword = q_head_is_rvc | q_err_head
|
||||||
|
`ifdef SCR1_NO_DEC_STAGE
|
||||||
|
| (q_head_is_rvi & instr_bypass_vd)
|
||||||
|
`endif // SCR1_NO_DEC_STAGE
|
||||||
|
;
|
||||||
|
assign q_rd_size = ~q_rd_vd ? SCR1_IFU_QUEUE_RD_NONE
|
||||||
|
: q_rd_hword ? SCR1_IFU_QUEUE_RD_HWORD
|
||||||
|
: SCR1_IFU_QUEUE_RD_WORD;
|
||||||
|
assign q_rd_none = (q_rd_size == SCR1_IFU_QUEUE_RD_NONE);
|
||||||
|
|
||||||
|
// Queue write size decoder
|
||||||
|
always_comb begin
|
||||||
|
q_wr_size = SCR1_IFU_QUEUE_WR_NONE;
|
||||||
|
if (~imem_resp_discard_req) begin
|
||||||
|
if (imem_resp_ok) begin
|
||||||
|
`ifdef SCR1_NO_DEC_STAGE
|
||||||
|
case (instr_type)
|
||||||
|
SCR1_IFU_INSTR_NONE : q_wr_size = SCR1_IFU_QUEUE_WR_NONE;
|
||||||
|
SCR1_IFU_INSTR_RVI_LO_NV : q_wr_size = SCR1_IFU_QUEUE_WR_HI;
|
||||||
|
SCR1_IFU_INSTR_RVC_NV : q_wr_size = (instr_bypass_vd & idu2ifu_rdy_i)
|
||||||
|
? SCR1_IFU_QUEUE_WR_NONE
|
||||||
|
: SCR1_IFU_QUEUE_WR_HI;
|
||||||
|
SCR1_IFU_INSTR_RVI_HI_RVI_LO: q_wr_size = (instr_bypass_vd & idu2ifu_rdy_i)
|
||||||
|
? SCR1_IFU_QUEUE_WR_NONE
|
||||||
|
: SCR1_IFU_QUEUE_WR_FULL;
|
||||||
|
SCR1_IFU_INSTR_RVC_RVC,
|
||||||
|
SCR1_IFU_INSTR_RVI_LO_RVC,
|
||||||
|
SCR1_IFU_INSTR_RVC_RVI_HI,
|
||||||
|
SCR1_IFU_INSTR_RVI_LO_RVI_HI: q_wr_size = (instr_bypass_vd & idu2ifu_rdy_i)
|
||||||
|
? SCR1_IFU_QUEUE_WR_HI
|
||||||
|
: SCR1_IFU_QUEUE_WR_FULL;
|
||||||
|
endcase // instr_type
|
||||||
|
`else // SCR1_NO_DEC_STAGE
|
||||||
|
case (instr_type)
|
||||||
|
SCR1_IFU_INSTR_NONE : q_wr_size = SCR1_IFU_QUEUE_WR_NONE;
|
||||||
|
SCR1_IFU_INSTR_RVC_NV,
|
||||||
|
SCR1_IFU_INSTR_RVI_LO_NV : q_wr_size = SCR1_IFU_QUEUE_WR_HI;
|
||||||
|
default : q_wr_size = SCR1_IFU_QUEUE_WR_FULL;
|
||||||
|
endcase // instr_type
|
||||||
|
`endif // SCR1_NO_DEC_STAGE
|
||||||
|
end else if (imem_resp_er) begin
|
||||||
|
q_wr_size = SCR1_IFU_QUEUE_WR_FULL;
|
||||||
|
end // imem_resp_er
|
||||||
|
end // ~imem_resp_discard_req
|
||||||
|
end
|
||||||
|
|
||||||
|
assign q_wr_none = (q_wr_size == SCR1_IFU_QUEUE_WR_NONE);
|
||||||
|
assign q_wr_full = (q_wr_size == SCR1_IFU_QUEUE_WR_FULL);
|
||||||
|
|
||||||
|
// Write/read pointer registers
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign q_flush_req = exu2ifu_pc_new_req_i | pipe2ifu_stop_fetch_i;
|
||||||
|
|
||||||
|
// Queue write pointer register
|
||||||
|
assign q_wptr_upd = q_flush_req | ~q_wr_none;
|
||||||
|
|
||||||
|
always_ff @(posedge clk, negedge rst_n) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
q_wptr <= '0;
|
||||||
|
end else if (q_wptr_upd) begin
|
||||||
|
q_wptr <= q_wptr_next;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign q_wptr_next = q_flush_req ? '0
|
||||||
|
: ~q_wr_none ? q_wptr + (q_wr_full ? SCR1_IFU_QUEUE_PTR_W'('b010) : SCR1_IFU_QUEUE_PTR_W'('b001))
|
||||||
|
: q_wptr;
|
||||||
|
|
||||||
|
// Queue read pointer register
|
||||||
|
assign q_rptr_upd = q_flush_req | ~q_rd_none;
|
||||||
|
|
||||||
|
always_ff @(posedge clk, negedge rst_n) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
q_rptr <= '0;
|
||||||
|
end else if (q_rptr_upd) begin
|
||||||
|
q_rptr <= q_rptr_next;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign q_rptr_next = q_flush_req ? '0
|
||||||
|
: ~q_rd_none ? q_rptr + (q_rd_hword ? SCR1_IFU_QUEUE_PTR_W'('b001) : SCR1_IFU_QUEUE_PTR_W'('b010))
|
||||||
|
: q_rptr;
|
||||||
|
|
||||||
|
// Queue data and error flag registers
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign imem_rdata_hi = imem2ifu_rdata_i[31:16];
|
||||||
|
assign imem_rdata_lo = imem2ifu_rdata_i[15:0];
|
||||||
|
|
||||||
|
assign q_wr_en = imem_resp_vd & ~q_flush_req;
|
||||||
|
|
||||||
|
always_ff @(posedge clk, negedge rst_n) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
q_data <= '{SCR1_IFU_Q_SIZE_HALF{'0}};
|
||||||
|
q_err <= '{SCR1_IFU_Q_SIZE_HALF{1'b0}};
|
||||||
|
end else if (q_wr_en) begin
|
||||||
|
case (q_wr_size)
|
||||||
|
SCR1_IFU_QUEUE_WR_HI : begin
|
||||||
|
q_data[SCR1_IFU_QUEUE_ADR_W'(q_wptr)] <= imem_rdata_hi;
|
||||||
|
q_err [SCR1_IFU_QUEUE_ADR_W'(q_wptr)] <= imem_resp_er;
|
||||||
|
end
|
||||||
|
SCR1_IFU_QUEUE_WR_FULL : begin
|
||||||
|
q_data[SCR1_IFU_QUEUE_ADR_W'(q_wptr)] <= imem_rdata_lo;
|
||||||
|
q_err [SCR1_IFU_QUEUE_ADR_W'(q_wptr)] <= imem_resp_er;
|
||||||
|
q_data[SCR1_IFU_QUEUE_ADR_W'(q_wptr + 1'b1)] <= imem_rdata_hi;
|
||||||
|
q_err [SCR1_IFU_QUEUE_ADR_W'(q_wptr + 1'b1)] <= imem_resp_er;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign q_data_head = q_data [SCR1_IFU_QUEUE_ADR_W'(q_rptr)];
|
||||||
|
assign q_data_next = q_data [SCR1_IFU_QUEUE_ADR_W'(q_rptr + 1'b1)];
|
||||||
|
assign q_err_head = q_err [SCR1_IFU_QUEUE_ADR_W'(q_rptr)];
|
||||||
|
assign q_err_next = q_err [SCR1_IFU_QUEUE_ADR_W'(q_rptr + 1'b1)];
|
||||||
|
|
||||||
|
// Queue status logic
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign q_ocpd_h = SCR1_IFU_Q_FREE_H_W'(q_wptr - q_rptr);
|
||||||
|
assign q_free_h_next = SCR1_IFU_Q_FREE_H_W'(SCR1_IFU_Q_SIZE_HALF - (q_wptr - q_rptr_next));
|
||||||
|
assign q_free_w_next = SCR1_IFU_Q_FREE_W_W'(q_free_h_next >> 1'b1);
|
||||||
|
|
||||||
|
assign q_is_empty = (q_rptr == q_wptr);
|
||||||
|
assign q_has_free_slots = (SCR1_TXN_CNT_W'(q_free_w_next) > imem_vd_pnd_txns_cnt);
|
||||||
|
assign q_has_1_ocpd_hw = (q_ocpd_h == SCR1_IFU_Q_FREE_H_W'(1));
|
||||||
|
|
||||||
|
assign q_head_is_rvi = &(q_data_head[1:0]);
|
||||||
|
assign q_head_is_rvc = ~q_head_is_rvi;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// IFU FSM
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// IFU FSM control signals
|
||||||
|
assign ifu_fetch_req = exu2ifu_pc_new_req_i & ~pipe2ifu_stop_fetch_i;
|
||||||
|
assign ifu_stop_req = pipe2ifu_stop_fetch_i
|
||||||
|
| (imem_resp_er_discard_pnd & ~exu2ifu_pc_new_req_i);
|
||||||
|
|
||||||
|
always_ff @(posedge clk, negedge rst_n) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
ifu_fsm_curr <= SCR1_IFU_FSM_IDLE;
|
||||||
|
end else begin
|
||||||
|
ifu_fsm_curr <= ifu_fsm_next;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
case (ifu_fsm_curr)
|
||||||
|
SCR1_IFU_FSM_IDLE : begin
|
||||||
|
ifu_fsm_next = ifu_fetch_req ? SCR1_IFU_FSM_FETCH
|
||||||
|
: SCR1_IFU_FSM_IDLE;
|
||||||
|
end
|
||||||
|
SCR1_IFU_FSM_FETCH : begin
|
||||||
|
ifu_fsm_next = ifu_stop_req ? SCR1_IFU_FSM_IDLE
|
||||||
|
: SCR1_IFU_FSM_FETCH;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
assign ifu_fsm_fetch = (ifu_fsm_curr == SCR1_IFU_FSM_FETCH);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// IFU <-> IMEM interface
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// IFU <-> IMEM interface consists of the following functional units:
|
||||||
|
// - IMEM response logic
|
||||||
|
// - IMEM address register
|
||||||
|
// - Pending IMEM transactions counter
|
||||||
|
// - IMEM discard responses counter
|
||||||
|
// - IFU <-> IMEM interface output signals
|
||||||
|
//
|
||||||
|
|
||||||
|
// IMEM response logic
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign imem_resp_er = (imem2ifu_resp_i == SCR1_MEM_RESP_RDY_ER);
|
||||||
|
assign imem_resp_ok = (imem2ifu_resp_i == SCR1_MEM_RESP_RDY_OK);
|
||||||
|
assign imem_resp_received = imem_resp_ok | imem_resp_er;
|
||||||
|
assign imem_resp_vd = imem_resp_received & ~imem_resp_discard_req;
|
||||||
|
assign imem_resp_er_discard_pnd = imem_resp_er & ~imem_resp_discard_req;
|
||||||
|
|
||||||
|
assign imem_handshake_done = ifu2imem_req_o & imem2ifu_req_ack_i;
|
||||||
|
|
||||||
|
// IMEM address register
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign imem_addr_upd = imem_handshake_done | exu2ifu_pc_new_req_i;
|
||||||
|
|
||||||
|
always_ff @(posedge clk, negedge rst_n) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
imem_addr_ff <= '0;
|
||||||
|
end else if (imem_addr_upd) begin
|
||||||
|
imem_addr_ff <= imem_addr_next;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
`ifndef SCR1_NEW_PC_REG
|
||||||
|
assign imem_addr_next = exu2ifu_pc_new_req_i ? exu2ifu_pc_new_i[`SCR1_XLEN-1:2] + imem_handshake_done
|
||||||
|
: &imem_addr_ff[5:2] ? imem_addr_ff + imem_handshake_done
|
||||||
|
: {imem_addr_ff[`SCR1_XLEN-1:6], imem_addr_ff[5:2] + imem_handshake_done};
|
||||||
|
`else // SCR1_NEW_PC_REG
|
||||||
|
assign imem_addr_next = exu2ifu_pc_new_req_i ? exu2ifu_pc_new_i[`SCR1_XLEN-1:2]
|
||||||
|
: &imem_addr_ff[5:2] ? imem_addr_ff + imem_handshake_done
|
||||||
|
: {imem_addr_ff[`SCR1_XLEN-1:6], imem_addr_ff[5:2] + imem_handshake_done};
|
||||||
|
`endif // SCR1_NEW_PC_REG
|
||||||
|
|
||||||
|
// Pending IMEM transactions counter
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Pending IMEM transactions occur if IFU request has been acknowledged, but
|
||||||
|
// response comes in the next cycle or later
|
||||||
|
|
||||||
|
assign imem_pnd_txns_cnt_upd = imem_handshake_done ^ imem_resp_received;
|
||||||
|
|
||||||
|
always_ff @(posedge clk, negedge rst_n) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
imem_pnd_txns_cnt <= '0;
|
||||||
|
end else if (imem_pnd_txns_cnt_upd) begin
|
||||||
|
imem_pnd_txns_cnt <= imem_pnd_txns_cnt_next;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign imem_pnd_txns_cnt_next = imem_pnd_txns_cnt + (imem_handshake_done - imem_resp_received);
|
||||||
|
assign imem_pnd_txns_q_full = &imem_pnd_txns_cnt;
|
||||||
|
|
||||||
|
// IMEM discard responses counter
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// IMEM instructions should be discarded in the following 2 cases:
|
||||||
|
// 1. New PC is requested by jump, branch, mret or other instruction
|
||||||
|
// 2. IMEM response was erroneous and not discarded
|
||||||
|
//
|
||||||
|
// In both cases the number of instructions to be discarded equals to the number
|
||||||
|
// of pending instructions.
|
||||||
|
// In the 1st case we don't need all the instructions that haven't been fetched
|
||||||
|
// yet, since the PC has changed.
|
||||||
|
// In the 2nd case, since the IMEM responce was erroneous there is no guarantee
|
||||||
|
// that subsequent IMEM instructions would be valid.
|
||||||
|
|
||||||
|
assign imem_resp_discard_cnt_upd = exu2ifu_pc_new_req_i | imem_resp_er
|
||||||
|
| (imem_resp_ok & imem_resp_discard_req);
|
||||||
|
|
||||||
|
always_ff @(posedge clk, negedge rst_n) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
imem_resp_discard_cnt <= '0;
|
||||||
|
end else if (imem_resp_discard_cnt_upd) begin
|
||||||
|
imem_resp_discard_cnt <= imem_resp_discard_cnt_next;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
`ifndef SCR1_NEW_PC_REG
|
||||||
|
assign imem_resp_discard_cnt_next = exu2ifu_pc_new_req_i ? imem_pnd_txns_cnt_next - imem_handshake_done
|
||||||
|
: imem_resp_er_discard_pnd ? imem_pnd_txns_cnt_next
|
||||||
|
: imem_resp_discard_cnt - 1'b1;
|
||||||
|
`else // SCR1_NEW_PC_REG
|
||||||
|
assign imem_resp_discard_cnt_next = exu2ifu_pc_new_req_i | imem_resp_er_discard_pnd
|
||||||
|
? imem_pnd_txns_cnt_next
|
||||||
|
: imem_resp_discard_cnt - 1'b1;
|
||||||
|
`endif // SCR1_NEW_PC_REG
|
||||||
|
|
||||||
|
assign imem_vd_pnd_txns_cnt = imem_pnd_txns_cnt - imem_resp_discard_cnt;
|
||||||
|
assign imem_resp_discard_req = |imem_resp_discard_cnt;
|
||||||
|
|
||||||
|
// IFU <-> IMEM interface output signals
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
`ifndef SCR1_NEW_PC_REG
|
||||||
|
assign ifu2imem_req_o = (exu2ifu_pc_new_req_i & ~imem_pnd_txns_q_full & ~pipe2ifu_stop_fetch_i)
|
||||||
|
| (ifu_fsm_fetch & ~imem_pnd_txns_q_full & q_has_free_slots);
|
||||||
|
assign ifu2imem_addr_o = exu2ifu_pc_new_req_i
|
||||||
|
? {exu2ifu_pc_new_i[`SCR1_XLEN-1:2], 2'b00}
|
||||||
|
: {imem_addr_ff, 2'b00};
|
||||||
|
`else // SCR1_NEW_PC_REG
|
||||||
|
assign ifu2imem_req_o = ifu_fsm_fetch & ~imem_pnd_txns_q_full & q_has_free_slots;
|
||||||
|
assign ifu2imem_addr_o = {imem_addr_ff, 2'b00};
|
||||||
|
`endif // SCR1_NEW_PC_REG
|
||||||
|
|
||||||
|
assign ifu2imem_cmd_o = SCR1_MEM_CMD_RD;
|
||||||
|
|
||||||
|
`ifdef SCR1_CLKCTRL_EN
|
||||||
|
assign ifu2pipe_imem_txns_pnd_o = |imem_pnd_txns_cnt;
|
||||||
|
`endif // SCR1_CLKCTRL_EN
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// IFU <-> IDU interface
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// IFU <-> IDU interface consists of the following functional units:
|
||||||
|
// - Instruction bypass type decoder
|
||||||
|
// - IFU <-> IDU status signals
|
||||||
|
// - Output instruction multiplexer
|
||||||
|
//
|
||||||
|
|
||||||
|
`ifdef SCR1_NO_DEC_STAGE
|
||||||
|
|
||||||
|
// Instruction bypass type decoder
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign instr_bypass_vd = (instr_bypass_type != SCR1_BYPASS_NONE);
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
instr_bypass_type = SCR1_BYPASS_NONE;
|
||||||
|
|
||||||
|
if (imem_resp_vd) begin
|
||||||
|
if (q_is_empty) begin
|
||||||
|
case (instr_type)
|
||||||
|
SCR1_IFU_INSTR_RVC_NV,
|
||||||
|
SCR1_IFU_INSTR_RVC_RVC,
|
||||||
|
SCR1_IFU_INSTR_RVI_LO_RVC : begin
|
||||||
|
instr_bypass_type = SCR1_BYPASS_RVC;
|
||||||
|
end
|
||||||
|
SCR1_IFU_INSTR_RVI_HI_RVI_LO : begin
|
||||||
|
instr_bypass_type = SCR1_BYPASS_RVI_RDATA;
|
||||||
|
end
|
||||||
|
default : begin end
|
||||||
|
endcase // instr_type
|
||||||
|
end else if (q_has_1_ocpd_hw & q_head_is_rvi) begin
|
||||||
|
if (instr_hi_rvi_lo_ff) begin
|
||||||
|
instr_bypass_type = SCR1_BYPASS_RVI_RDATA_QUEUE;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end // imem_resp_vd
|
||||||
|
end
|
||||||
|
|
||||||
|
// IFU <-> IDU interface status signals
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
ifu2idu_vd_o = 1'b0;
|
||||||
|
ifu2idu_imem_err_o = 1'b0;
|
||||||
|
ifu2idu_err_rvi_hi_o = 1'b0;
|
||||||
|
|
||||||
|
if (ifu_fsm_fetch | ~q_is_empty) begin
|
||||||
|
if (instr_bypass_vd) begin
|
||||||
|
ifu2idu_vd_o = 1'b1;
|
||||||
|
ifu2idu_imem_err_o = (instr_bypass_type == SCR1_BYPASS_RVI_RDATA_QUEUE)
|
||||||
|
? (imem_resp_er | q_err_head)
|
||||||
|
: imem_resp_er;
|
||||||
|
ifu2idu_err_rvi_hi_o = (instr_bypass_type == SCR1_BYPASS_RVI_RDATA_QUEUE) & imem_resp_er;
|
||||||
|
end else if (~q_is_empty) begin
|
||||||
|
if (q_has_1_ocpd_hw) begin
|
||||||
|
ifu2idu_vd_o = q_head_is_rvc | q_err_head;
|
||||||
|
ifu2idu_imem_err_o = q_err_head;
|
||||||
|
ifu2idu_err_rvi_hi_o = ~q_err_head & q_head_is_rvi & q_err_next;
|
||||||
|
end else begin
|
||||||
|
ifu2idu_vd_o = 1'b1;
|
||||||
|
ifu2idu_imem_err_o = q_err_head ? 1'b1 : (q_head_is_rvi & q_err_next);
|
||||||
|
end
|
||||||
|
end // ~q_is_empty
|
||||||
|
end
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
if (hdu2ifu_pbuf_fetch_i) begin
|
||||||
|
ifu2idu_vd_o = hdu2ifu_pbuf_vd_i;
|
||||||
|
ifu2idu_imem_err_o = hdu2ifu_pbuf_err_i;
|
||||||
|
end
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
end
|
||||||
|
|
||||||
|
// Output instruction multiplexer
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
case (instr_bypass_type)
|
||||||
|
SCR1_BYPASS_RVC : begin
|
||||||
|
ifu2idu_instr_o = `SCR1_IMEM_DWIDTH'(new_pc_unaligned_ff ? imem_rdata_hi
|
||||||
|
: imem_rdata_lo);
|
||||||
|
end
|
||||||
|
SCR1_BYPASS_RVI_RDATA : begin
|
||||||
|
ifu2idu_instr_o = imem2ifu_rdata_i;
|
||||||
|
end
|
||||||
|
SCR1_BYPASS_RVI_RDATA_QUEUE: begin
|
||||||
|
ifu2idu_instr_o = {imem_rdata_lo, q_data_head};
|
||||||
|
end
|
||||||
|
default : begin
|
||||||
|
ifu2idu_instr_o = `SCR1_IMEM_DWIDTH'(q_head_is_rvc ? q_data_head
|
||||||
|
: {q_data_next, q_data_head});
|
||||||
|
end
|
||||||
|
endcase // instr_bypass_type
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
if (hdu2ifu_pbuf_fetch_i) begin
|
||||||
|
ifu2idu_instr_o = `SCR1_IMEM_DWIDTH'({'0, hdu2ifu_pbuf_instr_i});
|
||||||
|
end
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
end
|
||||||
|
|
||||||
|
`else // SCR1_NO_DEC_STAGE
|
||||||
|
|
||||||
|
// IFU <-> IDU interface status signals
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
ifu2idu_vd_o = 1'b0;
|
||||||
|
ifu2idu_imem_err_o = 1'b0;
|
||||||
|
ifu2idu_err_rvi_hi_o = 1'b0;
|
||||||
|
if (~q_is_empty) begin
|
||||||
|
if (q_has_1_ocpd_hw) begin
|
||||||
|
ifu2idu_vd_o = q_head_is_rvc | q_err_head;
|
||||||
|
ifu2idu_imem_err_o = q_err_head;
|
||||||
|
end else begin
|
||||||
|
ifu2idu_vd_o = 1'b1;
|
||||||
|
ifu2idu_imem_err_o = q_err_head ? 1'b1 : (q_head_is_rvi & q_err_next);
|
||||||
|
ifu2idu_err_rvi_hi_o = ~q_err_head & q_head_is_rvi & q_err_next;
|
||||||
|
end
|
||||||
|
end // ~q_is_empty
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
if (hdu2ifu_pbuf_fetch_i) begin
|
||||||
|
ifu2idu_vd_o = hdu2ifu_pbuf_vd_i;
|
||||||
|
ifu2idu_imem_err_o = hdu2ifu_pbuf_err_i;
|
||||||
|
end
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
end
|
||||||
|
|
||||||
|
// Output instruction multiplexer
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
ifu2idu_instr_o = q_head_is_rvc ? `SCR1_IMEM_DWIDTH'(q_data_head)
|
||||||
|
: {q_data_next, q_data_head};
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
if (hdu2ifu_pbuf_fetch_i) begin
|
||||||
|
ifu2idu_instr_o = `SCR1_IMEM_DWIDTH'({'0, hdu2ifu_pbuf_instr_i});
|
||||||
|
end
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
end
|
||||||
|
|
||||||
|
`endif // SCR1_NO_DEC_STAGE
|
||||||
|
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
assign ifu2hdu_pbuf_rdy_o = idu2ifu_rdy_i;
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
|
||||||
|
`ifdef SCR1_TRGT_SIMULATION
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Assertions
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// X checks
|
||||||
|
|
||||||
|
SCR1_SVA_IFU_XCHECK : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
!$isunknown({imem2ifu_req_ack_i, idu2ifu_rdy_i, exu2ifu_pc_new_req_i})
|
||||||
|
) else $error("IFU Error: unknown values");
|
||||||
|
|
||||||
|
SCR1_SVA_IFU_XCHECK_REQ : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
ifu2imem_req_o |-> !$isunknown({ifu2imem_addr_o, ifu2imem_cmd_o})
|
||||||
|
) else $error("IFU Error: unknown {ifu2imem_addr_o, ifu2imem_cmd_o}");
|
||||||
|
|
||||||
|
// Behavior checks
|
||||||
|
|
||||||
|
SCR1_SVA_IFU_DRC_UNDERFLOW : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
~imem_resp_discard_req |=> ~(imem_resp_discard_cnt == SCR1_TXN_CNT_W'('1))
|
||||||
|
) else $error("IFU Error: imem_resp_discard_cnt underflow");
|
||||||
|
|
||||||
|
SCR1_SVA_IFU_DRC_RANGE : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
(imem_resp_discard_cnt >= 0) & (imem_resp_discard_cnt <= imem_pnd_txns_cnt)
|
||||||
|
) else $error("IFU Error: imem_resp_discard_cnt out of range");
|
||||||
|
|
||||||
|
SCR1_SVA_IFU_QUEUE_OVF : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
(q_ocpd_h >= SCR1_IFU_Q_FREE_H_W'(SCR1_IFU_Q_SIZE_HALF-1)) |->
|
||||||
|
((q_ocpd_h == SCR1_IFU_Q_FREE_H_W'(SCR1_IFU_Q_SIZE_HALF-1)) ? (q_wr_size != SCR1_IFU_QUEUE_WR_FULL)
|
||||||
|
: (q_wr_size == SCR1_IFU_QUEUE_WR_NONE))
|
||||||
|
) else $error("IFU Error: queue overflow");
|
||||||
|
|
||||||
|
SCR1_SVA_IFU_IMEM_ERR_BEH : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
(imem_resp_er & ~imem_resp_discard_req & ~exu2ifu_pc_new_req_i) |=>
|
||||||
|
(ifu_fsm_curr == SCR1_IFU_FSM_IDLE) & (imem_resp_discard_cnt == imem_pnd_txns_cnt)
|
||||||
|
) else $error("IFU Error: incorrect behavior after memory error");
|
||||||
|
|
||||||
|
SCR1_SVA_IFU_NEW_PC_REQ_BEH : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
exu2ifu_pc_new_req_i |=> q_is_empty
|
||||||
|
) else $error("IFU Error: incorrect behavior after exu2ifu_pc_new_req_i");
|
||||||
|
|
||||||
|
SCR1_SVA_IFU_IMEM_ADDR_ALIGNED : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
ifu2imem_req_o |-> ~|ifu2imem_addr_o[1:0]
|
||||||
|
) else $error("IFU Error: unaligned IMEM access");
|
||||||
|
|
||||||
|
SCR1_SVA_IFU_STOP_FETCH : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
pipe2ifu_stop_fetch_i |=> (ifu_fsm_curr == SCR1_IFU_FSM_IDLE)
|
||||||
|
) else $error("IFU Error: fetch not stopped");
|
||||||
|
|
||||||
|
SCR1_SVA_IFU_IMEM_FAULT_RVI_HI : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
ifu2idu_err_rvi_hi_o |-> ifu2idu_imem_err_o
|
||||||
|
) else $error("IFU Error: ifu2idu_imem_err_o == 0");
|
||||||
|
|
||||||
|
`endif // SCR1_TRGT_SIMULATION
|
||||||
|
|
||||||
|
endmodule : scr1_pipe_ifu
|
||||||
351
src_ref/core/pipeline/scr1_pipe_lsu.sv
Normal file
351
src_ref/core/pipeline/scr1_pipe_lsu.sv
Normal file
@@ -0,0 +1,351 @@
|
|||||||
|
/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
|
||||||
|
/// @file <scr1_pipe_lsu.sv>
|
||||||
|
/// @brief Load/Store Unit (LSU)
|
||||||
|
///
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Functionality:
|
||||||
|
// - Performs load and store operations in Data Memory
|
||||||
|
// - Generates DMEM address misalign and access fault exceptions
|
||||||
|
// - Passes DMEM operations information to TDU and generates LSU breakpoint exception
|
||||||
|
//
|
||||||
|
// Structure:
|
||||||
|
// - FSM
|
||||||
|
// - Exceptions logic
|
||||||
|
// - LSU <-> EXU interface
|
||||||
|
// - LSU <-> DMEM interface
|
||||||
|
// - LSU <-> TDU interface
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
`include "scr1_arch_description.svh"
|
||||||
|
`include "scr1_arch_types.svh"
|
||||||
|
`include "scr1_memif.svh"
|
||||||
|
`include "scr1_riscv_isa_decoding.svh"
|
||||||
|
`ifdef SCR1_TDU_EN
|
||||||
|
`include "scr1_tdu.svh"
|
||||||
|
`endif // SCR1_TDU_EN
|
||||||
|
|
||||||
|
module scr1_pipe_lsu (
|
||||||
|
// Common
|
||||||
|
input logic rst_n, // LSU reset
|
||||||
|
input logic clk, // LSU clock
|
||||||
|
|
||||||
|
// LSU <-> EXU interface
|
||||||
|
input logic exu2lsu_req_i, // Request to LSU
|
||||||
|
input type_scr1_lsu_cmd_sel_e exu2lsu_cmd_i, // LSU command
|
||||||
|
input logic [`SCR1_XLEN-1:0] exu2lsu_addr_i, // Address of DMEM
|
||||||
|
input logic [`SCR1_XLEN-1:0] exu2lsu_sdata_i, // Data for store
|
||||||
|
output logic lsu2exu_rdy_o, // LSU received DMEM response
|
||||||
|
output logic [`SCR1_XLEN-1:0] lsu2exu_ldata_o, // Load data
|
||||||
|
output logic lsu2exu_exc_o, // Exception from LSU
|
||||||
|
output type_scr1_exc_code_e lsu2exu_exc_code_o, // Exception code
|
||||||
|
|
||||||
|
`ifdef SCR1_TDU_EN
|
||||||
|
// LSU <-> TDU interface
|
||||||
|
output type_scr1_brkm_lsu_mon_s lsu2tdu_dmon_o, // Data address stream monitoring
|
||||||
|
input logic tdu2lsu_ibrkpt_exc_req_i, // Instruction BP exception request
|
||||||
|
input logic tdu2lsu_dbrkpt_exc_req_i, // Data BP exception request
|
||||||
|
`endif // SCR1_TDU_EN
|
||||||
|
|
||||||
|
// LSU <-> DMEM interface
|
||||||
|
output logic lsu2dmem_req_o, // Data memory request
|
||||||
|
output type_scr1_mem_cmd_e lsu2dmem_cmd_o, // Data memory command (READ/WRITE)
|
||||||
|
output type_scr1_mem_width_e lsu2dmem_width_o, // Data memory data width
|
||||||
|
output logic [`SCR1_DMEM_AWIDTH-1:0] lsu2dmem_addr_o, // Data memory address
|
||||||
|
output logic [`SCR1_DMEM_DWIDTH-1:0] lsu2dmem_wdata_o, // Data memory write data
|
||||||
|
input logic dmem2lsu_req_ack_i, // Data memory request acknowledge
|
||||||
|
input logic [`SCR1_DMEM_DWIDTH-1:0] dmem2lsu_rdata_i, // Data memory read data
|
||||||
|
input type_scr1_mem_resp_e dmem2lsu_resp_i // Data memory response
|
||||||
|
);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Local types declaration
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
typedef enum logic {
|
||||||
|
SCR1_LSU_FSM_IDLE,
|
||||||
|
SCR1_LSU_FSM_BUSY
|
||||||
|
} type_scr1_lsu_fsm_e;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Local signals declaration
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// LSU FSM signals
|
||||||
|
type_scr1_lsu_fsm_e lsu_fsm_curr; // LSU FSM current state
|
||||||
|
type_scr1_lsu_fsm_e lsu_fsm_next; // LSU FSM next state
|
||||||
|
logic lsu_fsm_idle; // LSU FSM is in IDLE state
|
||||||
|
|
||||||
|
// LSU Command register signals
|
||||||
|
logic lsu_cmd_upd; // LSU Command register update
|
||||||
|
type_scr1_lsu_cmd_sel_e lsu_cmd_ff; // LSU Command register value
|
||||||
|
logic lsu_cmd_ff_load; // Registered LSU Command is load
|
||||||
|
logic lsu_cmd_ff_store; // Registered LSU Command is store
|
||||||
|
|
||||||
|
// DMEM command and width flags
|
||||||
|
logic dmem_cmd_load; // DMEM command is load
|
||||||
|
logic dmem_cmd_store; // DMEM Command is store
|
||||||
|
logic dmem_wdth_word; // DMEM data width is WORD
|
||||||
|
logic dmem_wdth_hword; // DMEM data width is HALFWORD
|
||||||
|
logic dmem_wdth_byte; // DMEM data width is BYTE
|
||||||
|
|
||||||
|
// DMEM response and request control signals
|
||||||
|
logic dmem_resp_ok; // DMEM response is OK
|
||||||
|
logic dmem_resp_er; // DMEM response is erroneous
|
||||||
|
logic dmem_resp_received; // DMEM response is received
|
||||||
|
logic dmem_req_vd; // DMEM request is valid (req_ack received)
|
||||||
|
|
||||||
|
// Exceptions signals
|
||||||
|
logic lsu_exc_req; // LSU exception request
|
||||||
|
logic dmem_addr_mslgn; // DMEM address is misaligned
|
||||||
|
logic dmem_addr_mslgn_l; // DMEM load address is misaligned
|
||||||
|
logic dmem_addr_mslgn_s; // DMEM store address is misaligned
|
||||||
|
`ifdef SCR1_TDU_EN
|
||||||
|
logic lsu_exc_hwbrk; // LSU hardware breakpoint exception
|
||||||
|
`endif // SCR1_TDU_EN
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Control logic
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// DMEM response and request control signals
|
||||||
|
assign dmem_resp_ok = (dmem2lsu_resp_i == SCR1_MEM_RESP_RDY_OK);
|
||||||
|
assign dmem_resp_er = (dmem2lsu_resp_i == SCR1_MEM_RESP_RDY_ER);
|
||||||
|
assign dmem_resp_received = dmem_resp_ok | dmem_resp_er;
|
||||||
|
assign dmem_req_vd = exu2lsu_req_i & dmem2lsu_req_ack_i & ~lsu_exc_req;
|
||||||
|
|
||||||
|
// LSU load and store command flags
|
||||||
|
assign dmem_cmd_load = (exu2lsu_cmd_i == SCR1_LSU_CMD_LB )
|
||||||
|
| (exu2lsu_cmd_i == SCR1_LSU_CMD_LBU)
|
||||||
|
| (exu2lsu_cmd_i == SCR1_LSU_CMD_LH )
|
||||||
|
| (exu2lsu_cmd_i == SCR1_LSU_CMD_LHU)
|
||||||
|
| (exu2lsu_cmd_i == SCR1_LSU_CMD_LW );
|
||||||
|
assign dmem_cmd_store = (exu2lsu_cmd_i == SCR1_LSU_CMD_SB )
|
||||||
|
| (exu2lsu_cmd_i == SCR1_LSU_CMD_SH )
|
||||||
|
| (exu2lsu_cmd_i == SCR1_LSU_CMD_SW );
|
||||||
|
|
||||||
|
// LSU data width flags
|
||||||
|
assign dmem_wdth_word = (exu2lsu_cmd_i == SCR1_LSU_CMD_LW )
|
||||||
|
| (exu2lsu_cmd_i == SCR1_LSU_CMD_SW );
|
||||||
|
assign dmem_wdth_hword = (exu2lsu_cmd_i == SCR1_LSU_CMD_LH )
|
||||||
|
| (exu2lsu_cmd_i == SCR1_LSU_CMD_LHU)
|
||||||
|
| (exu2lsu_cmd_i == SCR1_LSU_CMD_SH );
|
||||||
|
assign dmem_wdth_byte = (exu2lsu_cmd_i == SCR1_LSU_CMD_LB )
|
||||||
|
| (exu2lsu_cmd_i == SCR1_LSU_CMD_LBU)
|
||||||
|
| (exu2lsu_cmd_i == SCR1_LSU_CMD_SB );
|
||||||
|
|
||||||
|
// LSU command register
|
||||||
|
assign lsu_cmd_upd = lsu_fsm_idle & dmem_req_vd;
|
||||||
|
|
||||||
|
always_ff @(posedge clk, negedge rst_n) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
lsu_cmd_ff <= SCR1_LSU_CMD_NONE;
|
||||||
|
end else if (lsu_cmd_upd) begin
|
||||||
|
lsu_cmd_ff <= exu2lsu_cmd_i;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// LSU registered load and store command flags
|
||||||
|
assign lsu_cmd_ff_load = (lsu_cmd_ff == SCR1_LSU_CMD_LB )
|
||||||
|
| (lsu_cmd_ff == SCR1_LSU_CMD_LBU)
|
||||||
|
| (lsu_cmd_ff == SCR1_LSU_CMD_LH )
|
||||||
|
| (lsu_cmd_ff == SCR1_LSU_CMD_LHU)
|
||||||
|
| (lsu_cmd_ff == SCR1_LSU_CMD_LW );
|
||||||
|
assign lsu_cmd_ff_store = (lsu_cmd_ff == SCR1_LSU_CMD_SB )
|
||||||
|
| (lsu_cmd_ff == SCR1_LSU_CMD_SH )
|
||||||
|
| (lsu_cmd_ff == SCR1_LSU_CMD_SW );
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// LSU FSM
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// LSU FSM is used to control the LSU <-> DMEM interface
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
// Updating LSU FSM state
|
||||||
|
always_ff @(posedge clk, negedge rst_n) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
lsu_fsm_curr <= SCR1_LSU_FSM_IDLE;
|
||||||
|
end else begin
|
||||||
|
lsu_fsm_curr <= lsu_fsm_next;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// LSU FSM next state logic
|
||||||
|
always_comb begin
|
||||||
|
case (lsu_fsm_curr)
|
||||||
|
SCR1_LSU_FSM_IDLE: begin
|
||||||
|
lsu_fsm_next = dmem_req_vd ? SCR1_LSU_FSM_BUSY
|
||||||
|
: SCR1_LSU_FSM_IDLE;
|
||||||
|
end
|
||||||
|
SCR1_LSU_FSM_BUSY: begin
|
||||||
|
lsu_fsm_next = dmem_resp_received ? SCR1_LSU_FSM_IDLE
|
||||||
|
: SCR1_LSU_FSM_BUSY;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
assign lsu_fsm_idle = (lsu_fsm_curr == SCR1_LSU_FSM_IDLE);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Exceptions logic
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// The following types of exceptions are supported:
|
||||||
|
// - Load address misalign
|
||||||
|
// - Load access fault
|
||||||
|
// - Store address misalign
|
||||||
|
// - Store access fault
|
||||||
|
// - LSU breakpoint exception
|
||||||
|
//
|
||||||
|
|
||||||
|
// DMEM addr misalign logic
|
||||||
|
assign dmem_addr_mslgn = exu2lsu_req_i & ( (dmem_wdth_hword & exu2lsu_addr_i[0])
|
||||||
|
| (dmem_wdth_word & |exu2lsu_addr_i[1:0]));
|
||||||
|
assign dmem_addr_mslgn_l = dmem_addr_mslgn & dmem_cmd_load;
|
||||||
|
assign dmem_addr_mslgn_s = dmem_addr_mslgn & dmem_cmd_store;
|
||||||
|
|
||||||
|
// Exception code logic
|
||||||
|
always_comb begin
|
||||||
|
case (1'b1)
|
||||||
|
dmem_resp_er : lsu2exu_exc_code_o = lsu_cmd_ff_load ? SCR1_EXC_CODE_LD_ACCESS_FAULT
|
||||||
|
: lsu_cmd_ff_store ? SCR1_EXC_CODE_ST_ACCESS_FAULT
|
||||||
|
: SCR1_EXC_CODE_INSTR_MISALIGN;
|
||||||
|
`ifdef SCR1_TDU_EN
|
||||||
|
lsu_exc_hwbrk : lsu2exu_exc_code_o = SCR1_EXC_CODE_BREAKPOINT;
|
||||||
|
`endif // SCR1_TDU_EN
|
||||||
|
dmem_addr_mslgn_l: lsu2exu_exc_code_o = SCR1_EXC_CODE_LD_ADDR_MISALIGN;
|
||||||
|
dmem_addr_mslgn_s: lsu2exu_exc_code_o = SCR1_EXC_CODE_ST_ADDR_MISALIGN;
|
||||||
|
default : lsu2exu_exc_code_o = SCR1_EXC_CODE_INSTR_MISALIGN;
|
||||||
|
endcase // 1'b1
|
||||||
|
end
|
||||||
|
|
||||||
|
assign lsu_exc_req = dmem_addr_mslgn_l | dmem_addr_mslgn_s
|
||||||
|
`ifdef SCR1_TDU_EN
|
||||||
|
| lsu_exc_hwbrk
|
||||||
|
`endif // SCR1_TDU_EN
|
||||||
|
;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// LSU <-> EXU interface
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign lsu2exu_rdy_o = dmem_resp_received;
|
||||||
|
assign lsu2exu_exc_o = dmem_resp_er | lsu_exc_req;
|
||||||
|
|
||||||
|
// Sign- or zero-extending data received from DMEM
|
||||||
|
always_comb begin
|
||||||
|
case (lsu_cmd_ff)
|
||||||
|
SCR1_LSU_CMD_LH : lsu2exu_ldata_o = {{16{dmem2lsu_rdata_i[15]}}, dmem2lsu_rdata_i[15:0]};
|
||||||
|
SCR1_LSU_CMD_LHU: lsu2exu_ldata_o = { 16'b0, dmem2lsu_rdata_i[15:0]};
|
||||||
|
SCR1_LSU_CMD_LB : lsu2exu_ldata_o = {{24{dmem2lsu_rdata_i[7]}}, dmem2lsu_rdata_i[7:0]};
|
||||||
|
SCR1_LSU_CMD_LBU: lsu2exu_ldata_o = { 24'b0, dmem2lsu_rdata_i[7:0]};
|
||||||
|
default : lsu2exu_ldata_o = dmem2lsu_rdata_i;
|
||||||
|
endcase // lsu_cmd_ff
|
||||||
|
end
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// LSU <-> DMEM interface
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign lsu2dmem_req_o = exu2lsu_req_i & ~lsu_exc_req & lsu_fsm_idle;
|
||||||
|
assign lsu2dmem_addr_o = exu2lsu_addr_i;
|
||||||
|
assign lsu2dmem_wdata_o = exu2lsu_sdata_i;
|
||||||
|
assign lsu2dmem_cmd_o = dmem_cmd_store ? SCR1_MEM_CMD_WR : SCR1_MEM_CMD_RD;
|
||||||
|
assign lsu2dmem_width_o = dmem_wdth_byte ? SCR1_MEM_WIDTH_BYTE
|
||||||
|
: dmem_wdth_hword ? SCR1_MEM_WIDTH_HWORD
|
||||||
|
: SCR1_MEM_WIDTH_WORD;
|
||||||
|
|
||||||
|
`ifdef SCR1_TDU_EN
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// LSU <-> TDU interface
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign lsu2tdu_dmon_o.vd = exu2lsu_req_i & lsu_fsm_idle & ~tdu2lsu_ibrkpt_exc_req_i;
|
||||||
|
assign lsu2tdu_dmon_o.addr = exu2lsu_addr_i;
|
||||||
|
assign lsu2tdu_dmon_o.load = dmem_cmd_load;
|
||||||
|
assign lsu2tdu_dmon_o.store = dmem_cmd_store;
|
||||||
|
|
||||||
|
assign lsu_exc_hwbrk = (exu2lsu_req_i & tdu2lsu_ibrkpt_exc_req_i)
|
||||||
|
| tdu2lsu_dbrkpt_exc_req_i;
|
||||||
|
|
||||||
|
`endif // SCR1_TDU_EN
|
||||||
|
|
||||||
|
`ifdef SCR1_TRGT_SIMULATION
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Assertions
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// X checks
|
||||||
|
|
||||||
|
SCR1_SVA_LSU_XCHECK_CTRL : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
!$isunknown({exu2lsu_req_i, lsu_fsm_curr
|
||||||
|
`ifdef SCR1_TDU_EN
|
||||||
|
, tdu2lsu_ibrkpt_exc_req_i, tdu2lsu_dbrkpt_exc_req_i
|
||||||
|
`endif // SCR1_TDU_EN
|
||||||
|
})
|
||||||
|
) else $error("LSU Error: unknown control value");
|
||||||
|
|
||||||
|
SCR1_SVA_LSU_XCHECK_CMD : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
exu2lsu_req_i |-> !$isunknown({exu2lsu_cmd_i, exu2lsu_addr_i})
|
||||||
|
) else $error("LSU Error: undefined CMD or address");
|
||||||
|
|
||||||
|
SCR1_SVA_LSU_XCHECK_SDATA : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
(exu2lsu_req_i & (lsu2dmem_cmd_o == SCR1_MEM_CMD_WR)) |-> !$isunknown({exu2lsu_sdata_i})
|
||||||
|
) else $error("LSU Error: undefined store data");
|
||||||
|
|
||||||
|
SCR1_SVA_LSU_XCHECK_EXC : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
lsu2exu_exc_o |-> !$isunknown(lsu2exu_exc_code_o)
|
||||||
|
) else $error("LSU Error: exception code undefined");
|
||||||
|
|
||||||
|
SCR1_SVA_LSU_IMEM_CTRL : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
lsu2dmem_req_o |-> !$isunknown({lsu2dmem_cmd_o, lsu2dmem_width_o, lsu2dmem_addr_o})
|
||||||
|
) else $error("LSU Error: undefined dmem control");
|
||||||
|
|
||||||
|
SCR1_SVA_LSU_IMEM_ACK : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
lsu2dmem_req_o |-> !$isunknown(dmem2lsu_req_ack_i)
|
||||||
|
) else $error("LSU Error: undefined dmem ack");
|
||||||
|
|
||||||
|
SCR1_SVA_LSU_IMEM_WDATA : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
lsu2dmem_req_o & (lsu2dmem_cmd_o == SCR1_MEM_CMD_WR)
|
||||||
|
|-> !$isunknown(lsu2dmem_wdata_o[8:0])
|
||||||
|
) else $error("LSU Error: undefined dmem wdata");
|
||||||
|
|
||||||
|
// Behavior checks
|
||||||
|
|
||||||
|
SCR1_SVA_LSU_EXC_ONEHOT : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
$onehot0({dmem_resp_er, dmem_addr_mslgn_l, dmem_addr_mslgn_s})
|
||||||
|
) else $error("LSU Error: more than one exception at a time");
|
||||||
|
|
||||||
|
SCR1_SVA_LSU_UNEXPECTED_DMEM_RESP : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
lsu_fsm_idle |-> ~dmem_resp_received
|
||||||
|
) else $error("LSU Error: not expecting memory response");
|
||||||
|
|
||||||
|
SCR1_SVA_LSU_REQ_EXC : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
lsu2exu_exc_o |-> exu2lsu_req_i
|
||||||
|
) else $error("LSU Error: impossible exception");
|
||||||
|
|
||||||
|
`ifdef SCR1_TDU_EN
|
||||||
|
|
||||||
|
SCR1_COV_LSU_MISALIGN_BRKPT : cover property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
(dmem_addr_mslgn_l | dmem_addr_mslgn_s) & lsu_exc_hwbrk
|
||||||
|
);
|
||||||
|
`endif // SCR1_TDU_EN
|
||||||
|
|
||||||
|
`endif // SCR1_TRGT_SIMULATION
|
||||||
|
|
||||||
|
endmodule : scr1_pipe_lsu
|
||||||
167
src_ref/core/pipeline/scr1_pipe_mprf.sv
Normal file
167
src_ref/core/pipeline/scr1_pipe_mprf.sv
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
|
||||||
|
/// @file <scr1_pipe_mprf.sv>
|
||||||
|
/// @brief Multi Port Register File (MPRF)
|
||||||
|
///
|
||||||
|
|
||||||
|
`include "scr1_arch_description.svh"
|
||||||
|
`include "scr1_arch_types.svh"
|
||||||
|
|
||||||
|
module scr1_pipe_mprf (
|
||||||
|
// Common
|
||||||
|
`ifdef SCR1_MPRF_RST_EN
|
||||||
|
input logic rst_n, // MPRF reset
|
||||||
|
`endif // SCR1_MPRF_RST_EN
|
||||||
|
input logic clk, // MPRF clock
|
||||||
|
|
||||||
|
// EXU <-> MPRF interface
|
||||||
|
input logic [`SCR1_MPRF_AWIDTH-1:0] exu2mprf_rs1_addr_i, // MPRF rs1 read address
|
||||||
|
output logic [`SCR1_XLEN-1:0] mprf2exu_rs1_data_o, // MPRF rs1 read data
|
||||||
|
input logic [`SCR1_MPRF_AWIDTH-1:0] exu2mprf_rs2_addr_i, // MPRF rs2 read address
|
||||||
|
output logic [`SCR1_XLEN-1:0] mprf2exu_rs2_data_o, // MPRF rs2 read data
|
||||||
|
input logic exu2mprf_w_req_i, // MPRF write request
|
||||||
|
input logic [`SCR1_MPRF_AWIDTH-1:0] exu2mprf_rd_addr_i, // MPRF rd write address
|
||||||
|
input logic [`SCR1_XLEN-1:0] exu2mprf_rd_data_i // MPRF rd write data
|
||||||
|
);
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Local types declaration
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
logic wr_req_vd;
|
||||||
|
|
||||||
|
logic rs1_addr_vd;
|
||||||
|
logic rs2_addr_vd;
|
||||||
|
|
||||||
|
`ifdef SCR1_MPRF_RAM
|
||||||
|
logic rs1_addr_vd_ff;
|
||||||
|
logic rs2_addr_vd_ff;
|
||||||
|
|
||||||
|
logic rs1_new_data_req;
|
||||||
|
logic rs2_new_data_req;
|
||||||
|
logic rs1_new_data_req_ff;
|
||||||
|
logic rs2_new_data_req_ff;
|
||||||
|
logic read_new_data_req;
|
||||||
|
|
||||||
|
logic [`SCR1_XLEN-1:0] rd_data_ff;
|
||||||
|
|
||||||
|
logic [`SCR1_XLEN-1:0] rs1_data_ff;
|
||||||
|
logic [`SCR1_XLEN-1:0] rs2_data_ff;
|
||||||
|
|
||||||
|
// when using RAM, 2 memories are needed because 3 simultaneous independent
|
||||||
|
// write/read operations can occur
|
||||||
|
`ifdef SCR1_TRGT_FPGA_INTEL_MAX10
|
||||||
|
(* ramstyle = "M9K" *) logic [`SCR1_XLEN-1:0] mprf_int [1:`SCR1_MPRF_SIZE-1];
|
||||||
|
(* ramstyle = "M9K" *) logic [`SCR1_XLEN-1:0] mprf_int2 [1:`SCR1_MPRF_SIZE-1];
|
||||||
|
`elsif SCR1_TRGT_FPGA_INTEL_ARRIAV
|
||||||
|
(* ramstyle = "M10K" *) logic [`SCR1_XLEN-1:0] mprf_int [1:`SCR1_MPRF_SIZE-1];
|
||||||
|
(* ramstyle = "M10K" *) logic [`SCR1_XLEN-1:0] mprf_int2 [1:`SCR1_MPRF_SIZE-1];
|
||||||
|
`else
|
||||||
|
logic [`SCR1_XLEN-1:0] mprf_int [1:`SCR1_MPRF_SIZE-1];
|
||||||
|
logic [`SCR1_XLEN-1:0] mprf_int2 [1:`SCR1_MPRF_SIZE-1];
|
||||||
|
`endif
|
||||||
|
`else // distributed logic implementation
|
||||||
|
type_scr1_mprf_v [1:`SCR1_MPRF_SIZE-1] mprf_int;
|
||||||
|
`endif
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// MPRF control logic
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// control signals common for distributed logic and RAM implementations
|
||||||
|
assign rs1_addr_vd = |exu2mprf_rs1_addr_i;
|
||||||
|
assign rs2_addr_vd = |exu2mprf_rs2_addr_i;
|
||||||
|
|
||||||
|
assign wr_req_vd = exu2mprf_w_req_i & |exu2mprf_rd_addr_i;
|
||||||
|
|
||||||
|
// RAM implementation specific control signals
|
||||||
|
`ifdef SCR1_MPRF_RAM
|
||||||
|
assign rs1_new_data_req = wr_req_vd & ( exu2mprf_rs1_addr_i == exu2mprf_rd_addr_i );
|
||||||
|
assign rs2_new_data_req = wr_req_vd & ( exu2mprf_rs2_addr_i == exu2mprf_rd_addr_i );
|
||||||
|
assign read_new_data_req = rs1_new_data_req | rs2_new_data_req;
|
||||||
|
|
||||||
|
always_ff @( posedge clk ) begin
|
||||||
|
rs1_addr_vd_ff <= rs1_addr_vd;
|
||||||
|
rs2_addr_vd_ff <= rs2_addr_vd;
|
||||||
|
rs1_new_data_req_ff <= rs1_new_data_req;
|
||||||
|
rs2_new_data_req_ff <= rs2_new_data_req;
|
||||||
|
end
|
||||||
|
`endif // SCR1_MPRF_RAM
|
||||||
|
|
||||||
|
`ifdef SCR1_MPRF_RAM
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// RAM implementation
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// RAM is implemented with 2 simple dual-port memories with sync read operation;
|
||||||
|
// logic for "write-first" RDW behavior is implemented externally to the embedded
|
||||||
|
// memory blocks
|
||||||
|
|
||||||
|
// bypass new wr_data to the read output if write/read collision occurs
|
||||||
|
assign mprf2exu_rs1_data_o = ( rs1_new_data_req_ff ) ? rd_data_ff
|
||||||
|
: (( rs1_addr_vd_ff ) ? rs1_data_ff
|
||||||
|
: '0 );
|
||||||
|
|
||||||
|
assign mprf2exu_rs2_data_o = ( rs2_new_data_req_ff ) ? rd_data_ff
|
||||||
|
: (( rs2_addr_vd_ff ) ? rs2_data_ff
|
||||||
|
: '0 );
|
||||||
|
|
||||||
|
always_ff @( posedge clk ) begin
|
||||||
|
if ( read_new_data_req ) begin
|
||||||
|
rd_data_ff <= exu2mprf_rd_data_i;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// synchronous read operation
|
||||||
|
always_ff @( posedge clk ) begin
|
||||||
|
rs1_data_ff <= mprf_int[exu2mprf_rs1_addr_i];
|
||||||
|
rs2_data_ff <= mprf_int2[exu2mprf_rs2_addr_i];
|
||||||
|
end
|
||||||
|
|
||||||
|
// write operation
|
||||||
|
always_ff @( posedge clk ) begin
|
||||||
|
if ( wr_req_vd ) begin
|
||||||
|
mprf_int[exu2mprf_rd_addr_i] <= exu2mprf_rd_data_i;
|
||||||
|
mprf_int2[exu2mprf_rd_addr_i] <= exu2mprf_rd_data_i;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
`else // distributed logic implementation
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// distributed logic implementation
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// asynchronous read operation
|
||||||
|
assign mprf2exu_rs1_data_o = ( rs1_addr_vd ) ? mprf_int[exu2mprf_rs1_addr_i] : '0;
|
||||||
|
assign mprf2exu_rs2_data_o = ( rs2_addr_vd ) ? mprf_int[exu2mprf_rs2_addr_i] : '0;
|
||||||
|
|
||||||
|
// write operation
|
||||||
|
`ifdef SCR1_MPRF_RST_EN
|
||||||
|
always_ff @( posedge clk, negedge rst_n ) begin
|
||||||
|
if ( ~rst_n ) begin
|
||||||
|
mprf_int <= '{default: '0};
|
||||||
|
end else if ( wr_req_vd ) begin
|
||||||
|
mprf_int[exu2mprf_rd_addr_i] <= exu2mprf_rd_data_i;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
`else // ~SCR1_MPRF_RST_EN
|
||||||
|
always_ff @( posedge clk ) begin
|
||||||
|
if ( wr_req_vd ) begin
|
||||||
|
mprf_int[exu2mprf_rd_addr_i] <= exu2mprf_rd_data_i;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
`endif // ~SCR1_MPRF_RST_EN
|
||||||
|
`endif
|
||||||
|
|
||||||
|
`ifdef SCR1_TRGT_SIMULATION
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Assertion
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
`ifdef SCR1_MPRF_RST_EN
|
||||||
|
SCR1_SVA_MPRF_WRITEX : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
exu2mprf_w_req_i |-> !$isunknown({exu2mprf_rd_addr_i, (|exu2mprf_rd_addr_i ? exu2mprf_rd_data_i : `SCR1_XLEN'd0)})
|
||||||
|
) else $error("MPRF error: unknown values");
|
||||||
|
`endif // SCR1_MPRF_RST_EN
|
||||||
|
|
||||||
|
`endif // SCR1_TRGT_SIMULATION
|
||||||
|
|
||||||
|
endmodule : scr1_pipe_mprf
|
||||||
610
src_ref/core/pipeline/scr1_pipe_tdu.sv
Normal file
610
src_ref/core/pipeline/scr1_pipe_tdu.sv
Normal file
@@ -0,0 +1,610 @@
|
|||||||
|
/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
|
||||||
|
/// @file <scr1_pipe_tdu.sv>
|
||||||
|
/// @brief Trigger Debug Unit (TDU)
|
||||||
|
///
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Functionality:
|
||||||
|
// - Provides read/write interface for TDU CSRs
|
||||||
|
// - Provides triggers functionality:
|
||||||
|
// - Supports triggers either in both Debug and M modes or in Debug mode only
|
||||||
|
// - Supports virtual address matching (load, store, exec) triggers
|
||||||
|
// - Supports instruction count triggers
|
||||||
|
// - Supports the following actions on trigger firing:
|
||||||
|
// - Breakpoint exception raising
|
||||||
|
// - Debug Mode entering
|
||||||
|
// - Supports triggers chaining
|
||||||
|
//
|
||||||
|
// Structure:
|
||||||
|
// - CSR read/write i/f
|
||||||
|
// - TDU CSRs:
|
||||||
|
// - TSELECT
|
||||||
|
// - TDATA1/MCONTROL/ICOUNT
|
||||||
|
// - TDATA2
|
||||||
|
// - TINFO
|
||||||
|
// - TDU <-> EXU i/f
|
||||||
|
// - TDU <-> LSU i/f
|
||||||
|
// - TDU <-> HDU i/f
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
`include "scr1_arch_description.svh"
|
||||||
|
|
||||||
|
`ifdef SCR1_TDU_EN
|
||||||
|
`include "scr1_riscv_isa_decoding.svh"
|
||||||
|
`include "scr1_tdu.svh"
|
||||||
|
|
||||||
|
module scr1_pipe_tdu (
|
||||||
|
// Common signals
|
||||||
|
input logic rst_n, // TDU reset
|
||||||
|
input logic clk, // TDU clock
|
||||||
|
input logic clk_en, // TDU clock enable
|
||||||
|
input logic tdu_dsbl_i, // TDU Disable
|
||||||
|
|
||||||
|
// TDU <-> CSR interface
|
||||||
|
input logic csr2tdu_req_i, // CSR-TDU i/f request
|
||||||
|
input type_scr1_csr_cmd_sel_e csr2tdu_cmd_i, // CSR-TDU i/f command
|
||||||
|
input logic [SCR1_CSR_ADDR_TDU_OFFS_W-1:0] csr2tdu_addr_i, // CSR-TDU i/f address
|
||||||
|
input logic [SCR1_TDU_DATA_W-1:0] csr2tdu_wdata_i, // CSR-TDU i/f write data
|
||||||
|
output logic [SCR1_TDU_DATA_W-1:0] tdu2csr_rdata_o, // CSR-TDU i/f read data
|
||||||
|
output type_scr1_csr_resp_e tdu2csr_resp_o, // CSR-TDU i/f response
|
||||||
|
|
||||||
|
// TDU <-> EXU interface
|
||||||
|
input type_scr1_brkm_instr_mon_s exu2tdu_imon_i, // Instruction stream monitoring
|
||||||
|
output logic [SCR1_TDU_ALLTRIG_NUM-1 : 0] tdu2exu_ibrkpt_match_o, // Instruction BP match
|
||||||
|
output logic tdu2exu_ibrkpt_exc_req_o, // Instruction BP exception request
|
||||||
|
input logic [SCR1_TDU_ALLTRIG_NUM-1 : 0] exu2tdu_bp_retire_i, // Map of BPs being retired
|
||||||
|
|
||||||
|
// TDU <-> LSU interface
|
||||||
|
`ifndef SCR1_TDU_EN
|
||||||
|
output logic tdu2lsu_brk_en_o, // TDU-LSU Breakpoint enable
|
||||||
|
`endif // SCR1_TDU_EN
|
||||||
|
output logic tdu2lsu_ibrkpt_exc_req_o, // TDU-LSU Instruction BP exception request
|
||||||
|
input type_scr1_brkm_lsu_mon_s lsu2tdu_dmon_i, // TDU-LSU Data address stream monitoring
|
||||||
|
output logic [SCR1_TDU_MTRIG_NUM-1 : 0] tdu2lsu_dbrkpt_match_o, // TDU-LSU Data BP match
|
||||||
|
output logic tdu2lsu_dbrkpt_exc_req_o, // TDU-LSU Data BP exception request
|
||||||
|
|
||||||
|
// TDU <-> HDU interface
|
||||||
|
output logic tdu2hdu_dmode_req_o // Debug Mode redirection request
|
||||||
|
);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Local parameters declaration
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
localparam int unsigned MTRIG_NUM = SCR1_TDU_MTRIG_NUM;
|
||||||
|
localparam int unsigned ALLTRIG_NUM = SCR1_TDU_ALLTRIG_NUM;
|
||||||
|
localparam int unsigned ALLTRIG_W = $clog2(ALLTRIG_NUM+1);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Local signals declaration
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// TDU CSRs read/write i/f signals
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Write signals
|
||||||
|
logic csr_wr_req;
|
||||||
|
logic [SCR1_TDU_DATA_W-1:0] csr_wr_data;
|
||||||
|
|
||||||
|
// Register select
|
||||||
|
logic csr_addr_tselect;
|
||||||
|
logic [MTRIG_NUM-1:0] csr_addr_mcontrol;
|
||||||
|
logic [MTRIG_NUM-1:0] csr_addr_tdata2;
|
||||||
|
`ifdef SCR1_TDU_ICOUNT_EN
|
||||||
|
logic csr_addr_icount;
|
||||||
|
`endif // SCR1_TDU_ICOUNT_EN
|
||||||
|
|
||||||
|
// TDU CSRs
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// TSELECT register
|
||||||
|
logic csr_tselect_upd;
|
||||||
|
logic [ALLTRIG_W-1:0] csr_tselect_ff;
|
||||||
|
|
||||||
|
// MCONTROL register
|
||||||
|
logic [MTRIG_NUM-1:0] csr_mcontrol_wr_req;
|
||||||
|
logic [MTRIG_NUM-1:0] csr_mcontrol_clk_en;
|
||||||
|
logic [MTRIG_NUM-1:0] csr_mcontrol_upd;
|
||||||
|
|
||||||
|
logic [MTRIG_NUM-1:0] csr_mcontrol_dmode_ff;
|
||||||
|
logic [MTRIG_NUM-1:0] csr_mcontrol_dmode_next;
|
||||||
|
logic [MTRIG_NUM-1:0] csr_mcontrol_m_ff;
|
||||||
|
logic [MTRIG_NUM-1:0] csr_mcontrol_m_next;
|
||||||
|
logic [MTRIG_NUM-1:0] csr_mcontrol_exec_ff;
|
||||||
|
logic [MTRIG_NUM-1:0] csr_mcontrol_exec_next;
|
||||||
|
logic [MTRIG_NUM-1:0] csr_mcontrol_load_ff;
|
||||||
|
logic [MTRIG_NUM-1:0] csr_mcontrol_load_next;
|
||||||
|
logic [MTRIG_NUM-1:0] csr_mcontrol_store_ff;
|
||||||
|
logic [MTRIG_NUM-1:0] csr_mcontrol_store_next;
|
||||||
|
logic [MTRIG_NUM-1:0] csr_mcontrol_action_ff;
|
||||||
|
logic [MTRIG_NUM-1:0] csr_mcontrol_action_next;
|
||||||
|
logic [MTRIG_NUM-1:0] csr_mcontrol_hit_ff;
|
||||||
|
logic [MTRIG_NUM-1:0] csr_mcontrol_hit_next;
|
||||||
|
|
||||||
|
logic [MTRIG_NUM-1:0] csr_mcontrol_exec_hit;
|
||||||
|
logic [MTRIG_NUM-1:0] csr_mcontrol_ldst_hit;
|
||||||
|
|
||||||
|
// ICOUNT register
|
||||||
|
`ifdef SCR1_TDU_ICOUNT_EN
|
||||||
|
logic csr_icount_wr_req;
|
||||||
|
logic csr_icount_clk_en;
|
||||||
|
logic csr_icount_upd;
|
||||||
|
|
||||||
|
logic csr_icount_dmode_ff;
|
||||||
|
logic csr_icount_dmode_next;
|
||||||
|
logic csr_icount_m_ff;
|
||||||
|
logic csr_icount_m_next;
|
||||||
|
logic csr_icount_action_ff;
|
||||||
|
logic csr_icount_action_next;
|
||||||
|
logic csr_icount_hit_ff;
|
||||||
|
logic csr_icount_hit_next;
|
||||||
|
logic [SCR1_TDU_ICOUNT_COUNT_HI-SCR1_TDU_ICOUNT_COUNT_LO:0]
|
||||||
|
csr_icount_count_ff;
|
||||||
|
logic [SCR1_TDU_ICOUNT_COUNT_HI-SCR1_TDU_ICOUNT_COUNT_LO:0]
|
||||||
|
csr_icount_count_next;
|
||||||
|
logic csr_icount_skip_ff;
|
||||||
|
logic csr_icount_skip_next;
|
||||||
|
|
||||||
|
logic csr_icount_decr_en;
|
||||||
|
logic csr_icount_count_decr;
|
||||||
|
logic csr_icount_skip_dsbl;
|
||||||
|
logic csr_icount_hit;
|
||||||
|
`endif // SCR1_TDU_ICOUNT_EN
|
||||||
|
|
||||||
|
// TDATA2 register
|
||||||
|
logic [MTRIG_NUM-1:0] csr_tdata2_upd;
|
||||||
|
logic [MTRIG_NUM-1:0] [SCR1_TDU_DATA_W-1:0] csr_tdata2_ff;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// CSR read/write interface
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Read logic
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign tdu2csr_resp_o = csr2tdu_req_i ? SCR1_CSR_RESP_OK : SCR1_CSR_RESP_ER;
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
tdu2csr_rdata_o = '0;
|
||||||
|
if (csr2tdu_req_i) begin
|
||||||
|
case (csr2tdu_addr_i)
|
||||||
|
SCR1_CSR_ADDR_TDU_OFFS_TSELECT: begin
|
||||||
|
tdu2csr_rdata_o = {'0, csr_tselect_ff};
|
||||||
|
end
|
||||||
|
SCR1_CSR_ADDR_TDU_OFFS_TDATA2 : begin
|
||||||
|
for(int unsigned i = 0; i < MTRIG_NUM; ++i) begin
|
||||||
|
if(csr_tselect_ff == ALLTRIG_W'(i)) begin
|
||||||
|
tdu2csr_rdata_o = csr_tdata2_ff[i];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
SCR1_CSR_ADDR_TDU_OFFS_TDATA1 : begin
|
||||||
|
for(int unsigned i = 0; i < MTRIG_NUM; ++i) begin
|
||||||
|
if(csr_tselect_ff == ALLTRIG_W'(i)) begin
|
||||||
|
tdu2csr_rdata_o[SCR1_TDU_TDATA1_TYPE_HI:
|
||||||
|
SCR1_TDU_TDATA1_TYPE_LO] = SCR1_TDU_MCONTROL_TYPE_VAL;
|
||||||
|
tdu2csr_rdata_o[SCR1_TDU_TDATA1_DMODE] = csr_mcontrol_dmode_ff[i];
|
||||||
|
tdu2csr_rdata_o[SCR1_TDU_MCONTROL_MASKMAX_HI:
|
||||||
|
SCR1_TDU_MCONTROL_MASKMAX_LO] = SCR1_TDU_MCONTROL_MASKMAX_VAL;
|
||||||
|
tdu2csr_rdata_o[SCR1_TDU_MCONTROL_HIT] = csr_mcontrol_hit_ff[i];
|
||||||
|
tdu2csr_rdata_o[SCR1_TDU_MCONTROL_SELECT] = SCR1_TDU_MCONTROL_SELECT_VAL;
|
||||||
|
tdu2csr_rdata_o[SCR1_TDU_MCONTROL_TIMING] = SCR1_TDU_MCONTROL_TIMING_VAL;
|
||||||
|
tdu2csr_rdata_o[SCR1_TDU_MCONTROL_ACTION_HI:
|
||||||
|
SCR1_TDU_MCONTROL_ACTION_LO] = {5'b0, csr_mcontrol_action_ff[i]};
|
||||||
|
tdu2csr_rdata_o[SCR1_TDU_MCONTROL_CHAIN] = 1'b0;
|
||||||
|
tdu2csr_rdata_o[SCR1_TDU_MCONTROL_MATCH_HI:
|
||||||
|
SCR1_TDU_MCONTROL_MATCH_LO] = 4'b0;
|
||||||
|
tdu2csr_rdata_o[SCR1_TDU_MCONTROL_M] = csr_mcontrol_m_ff[i];
|
||||||
|
tdu2csr_rdata_o[SCR1_TDU_MCONTROL_RESERVEDA] = SCR1_TDU_MCONTROL_RESERVEDA_VAL;
|
||||||
|
tdu2csr_rdata_o[SCR1_TDU_MCONTROL_S] = 1'b0;
|
||||||
|
tdu2csr_rdata_o[SCR1_TDU_MCONTROL_U] = 1'b0;
|
||||||
|
tdu2csr_rdata_o[SCR1_TDU_MCONTROL_EXECUTE] = csr_mcontrol_exec_ff [i];
|
||||||
|
tdu2csr_rdata_o[SCR1_TDU_MCONTROL_STORE] = csr_mcontrol_store_ff[i];
|
||||||
|
tdu2csr_rdata_o[SCR1_TDU_MCONTROL_LOAD] = csr_mcontrol_load_ff [i];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
`ifdef SCR1_TDU_ICOUNT_EN
|
||||||
|
if(csr_tselect_ff == ALLTRIG_W'(SCR1_TDU_ALLTRIG_NUM - 1'b1)) begin
|
||||||
|
tdu2csr_rdata_o[SCR1_TDU_TDATA1_TYPE_HI:
|
||||||
|
SCR1_TDU_TDATA1_TYPE_LO] = SCR1_TDU_ICOUNT_TYPE_VAL;
|
||||||
|
tdu2csr_rdata_o[SCR1_TDU_TDATA1_DMODE] = csr_icount_dmode_ff;
|
||||||
|
tdu2csr_rdata_o[SCR1_TDU_ICOUNT_HIT] = csr_icount_hit_ff;
|
||||||
|
tdu2csr_rdata_o[SCR1_TDU_ICOUNT_COUNT_HI:
|
||||||
|
SCR1_TDU_ICOUNT_COUNT_LO] = csr_icount_count_ff;
|
||||||
|
tdu2csr_rdata_o[SCR1_TDU_ICOUNT_U] = 1'b0;
|
||||||
|
tdu2csr_rdata_o[SCR1_TDU_ICOUNT_S] = 1'b0;
|
||||||
|
tdu2csr_rdata_o[SCR1_TDU_ICOUNT_M] = csr_icount_m_ff;
|
||||||
|
tdu2csr_rdata_o[SCR1_TDU_ICOUNT_ACTION_HI:
|
||||||
|
SCR1_TDU_ICOUNT_ACTION_LO] = {5'b0, csr_icount_action_ff};
|
||||||
|
end
|
||||||
|
`endif // SCR1_TDU_ICOUNT_EN
|
||||||
|
end
|
||||||
|
SCR1_CSR_ADDR_TDU_OFFS_TINFO : begin
|
||||||
|
for(int unsigned i = 0; i < MTRIG_NUM; ++i) begin
|
||||||
|
if(csr_tselect_ff == ALLTRIG_W'(i)) begin
|
||||||
|
tdu2csr_rdata_o[SCR1_TDU_MCONTROL_TYPE_VAL] = 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
`ifdef SCR1_TDU_ICOUNT_EN
|
||||||
|
if(csr_tselect_ff == ALLTRIG_W'(SCR1_TDU_ALLTRIG_NUM - 1'b1)) begin
|
||||||
|
tdu2csr_rdata_o[SCR1_TDU_ICOUNT_TYPE_VAL] = 1'b1;
|
||||||
|
end
|
||||||
|
`endif // SCR1_TDU_ICOUNT_EN
|
||||||
|
end
|
||||||
|
default : begin
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// Write logic
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
csr_wr_req = 1'b0;
|
||||||
|
csr_wr_data = '0;
|
||||||
|
|
||||||
|
case (csr2tdu_cmd_i)
|
||||||
|
SCR1_CSR_CMD_WRITE: begin
|
||||||
|
csr_wr_req = 1'b1;
|
||||||
|
csr_wr_data = csr2tdu_wdata_i;
|
||||||
|
end
|
||||||
|
SCR1_CSR_CMD_SET : begin
|
||||||
|
csr_wr_req = |csr2tdu_wdata_i;
|
||||||
|
csr_wr_data = tdu2csr_rdata_o | csr2tdu_wdata_i;
|
||||||
|
end
|
||||||
|
SCR1_CSR_CMD_CLEAR: begin
|
||||||
|
csr_wr_req = |csr2tdu_wdata_i;
|
||||||
|
csr_wr_data = tdu2csr_rdata_o & ~csr2tdu_wdata_i;
|
||||||
|
end
|
||||||
|
default : begin
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
// Register selection
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
csr_addr_tselect = 1'b0;
|
||||||
|
csr_addr_tdata2 = '0;
|
||||||
|
csr_addr_mcontrol = '0;
|
||||||
|
`ifdef SCR1_TDU_ICOUNT_EN
|
||||||
|
csr_addr_icount = '0;
|
||||||
|
`endif // SCR1_TDU_ICOUNT_EN
|
||||||
|
|
||||||
|
if (csr2tdu_req_i) begin
|
||||||
|
case (csr2tdu_addr_i)
|
||||||
|
SCR1_CSR_ADDR_TDU_OFFS_TSELECT: begin
|
||||||
|
csr_addr_tselect = 1'b1;
|
||||||
|
end
|
||||||
|
SCR1_CSR_ADDR_TDU_OFFS_TDATA1 : begin
|
||||||
|
for(int unsigned i = 0; i < MTRIG_NUM; ++i) begin
|
||||||
|
if(csr_tselect_ff == ALLTRIG_W'(i)) begin
|
||||||
|
csr_addr_mcontrol[i] = 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
`ifdef SCR1_TDU_ICOUNT_EN
|
||||||
|
if(csr_tselect_ff == ALLTRIG_W'(SCR1_TDU_ALLTRIG_NUM - 1'b1)) begin
|
||||||
|
csr_addr_icount = 1'b1;
|
||||||
|
end
|
||||||
|
`endif // SCR1_TDU_ICOUNT_EN
|
||||||
|
end
|
||||||
|
SCR1_CSR_ADDR_TDU_OFFS_TDATA2 : begin
|
||||||
|
for(int unsigned i = 0; i < MTRIG_NUM; ++i) begin
|
||||||
|
if(csr_tselect_ff == ALLTRIG_W'(i) ) begin
|
||||||
|
csr_addr_tdata2[i] = 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
default : begin
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// TDU CSRs
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// TDU CSRs consist of the following registers:
|
||||||
|
// - TSELECT
|
||||||
|
// - TDATA1/MCONTROL/ICOUNT (depending on the type field value)
|
||||||
|
// - TDATA2
|
||||||
|
//
|
||||||
|
|
||||||
|
// TSELECT register
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Determines which trigger is accessible through the other trigger registers
|
||||||
|
|
||||||
|
assign csr_tselect_upd = clk_en & csr_addr_tselect & csr_wr_req
|
||||||
|
& (csr_wr_data[ALLTRIG_W-1:0] < ALLTRIG_W'(ALLTRIG_NUM));
|
||||||
|
|
||||||
|
always_ff @(negedge rst_n, posedge clk) begin
|
||||||
|
if(~rst_n) begin
|
||||||
|
csr_tselect_ff <= '0;
|
||||||
|
end else if(csr_tselect_upd) begin
|
||||||
|
csr_tselect_ff <= csr_wr_data[ALLTRIG_W-1:0];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
`ifdef SCR1_TDU_ICOUNT_EN
|
||||||
|
// ICOUNT register
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Provides a trigger that fires when the certain number of instructions has retired
|
||||||
|
// Is intended to be used as a single step trigger (in this case count must be 1)
|
||||||
|
|
||||||
|
assign csr_icount_wr_req = csr_addr_icount & csr_wr_req;
|
||||||
|
assign csr_icount_clk_en = clk_en & (csr_icount_wr_req | csr_icount_m_ff);
|
||||||
|
assign csr_icount_upd = ~csr_icount_dmode_ff
|
||||||
|
? csr_icount_wr_req
|
||||||
|
: tdu_dsbl_i & csr_icount_wr_req;
|
||||||
|
|
||||||
|
always_ff @(negedge rst_n, posedge clk) begin
|
||||||
|
if(~rst_n) begin
|
||||||
|
csr_icount_dmode_ff <= 1'b0;
|
||||||
|
csr_icount_m_ff <= 1'b0;
|
||||||
|
csr_icount_action_ff <= 1'b0;
|
||||||
|
csr_icount_hit_ff <= 1'b0;
|
||||||
|
csr_icount_count_ff <= '0;
|
||||||
|
csr_icount_skip_ff <= 1'b0;
|
||||||
|
end else if (csr_icount_clk_en) begin
|
||||||
|
csr_icount_dmode_ff <= csr_icount_dmode_next;
|
||||||
|
csr_icount_m_ff <= csr_icount_m_next;
|
||||||
|
csr_icount_action_ff <= csr_icount_action_next;
|
||||||
|
csr_icount_hit_ff <= csr_icount_hit_next;
|
||||||
|
csr_icount_count_ff <= csr_icount_count_next;
|
||||||
|
csr_icount_skip_ff <= csr_icount_skip_next;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign csr_icount_decr_en = (~tdu_dsbl_i & csr_icount_m_ff)
|
||||||
|
? exu2tdu_imon_i.vd & (csr_icount_count_ff != 14'b0)
|
||||||
|
: 1'b0;
|
||||||
|
assign csr_icount_count_decr = exu2tdu_imon_i.req & csr_icount_decr_en & ~csr_icount_skip_ff;
|
||||||
|
assign csr_icount_skip_dsbl = exu2tdu_imon_i.req & csr_icount_decr_en & csr_icount_skip_ff;
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
if (csr_icount_upd) begin
|
||||||
|
csr_icount_dmode_next = csr_wr_data[SCR1_TDU_TDATA1_DMODE];
|
||||||
|
csr_icount_m_next = csr_wr_data[SCR1_TDU_ICOUNT_M];
|
||||||
|
csr_icount_action_next = (csr_wr_data[SCR1_TDU_ICOUNT_ACTION_HI
|
||||||
|
:SCR1_TDU_ICOUNT_ACTION_LO] == 'b1);
|
||||||
|
csr_icount_hit_next = csr_wr_data[SCR1_TDU_ICOUNT_HIT];
|
||||||
|
csr_icount_count_next = csr_wr_data[SCR1_TDU_ICOUNT_COUNT_HI:SCR1_TDU_ICOUNT_COUNT_LO];
|
||||||
|
end else begin
|
||||||
|
csr_icount_dmode_next = csr_icount_dmode_ff;
|
||||||
|
csr_icount_m_next = csr_icount_m_ff;
|
||||||
|
csr_icount_action_next = csr_icount_action_ff;
|
||||||
|
csr_icount_hit_next = exu2tdu_bp_retire_i[ALLTRIG_NUM - 1'b1]
|
||||||
|
? 1'b1
|
||||||
|
: csr_icount_hit_ff;
|
||||||
|
csr_icount_count_next = csr_icount_count_decr
|
||||||
|
? csr_icount_count_ff - 1'b1
|
||||||
|
: csr_icount_count_ff;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign csr_icount_skip_next = csr_icount_wr_req ? csr_wr_data[SCR1_TDU_ICOUNT_M]
|
||||||
|
: csr_icount_skip_dsbl ? 1'b0
|
||||||
|
: csr_icount_skip_ff;
|
||||||
|
`endif // SCR1_TDU_ICOUNT_EN
|
||||||
|
|
||||||
|
// MCONTROL registers
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Provides a trigger that fires on the virtual address (stored in TDATA2) match
|
||||||
|
// (load, store, exec options supported). Triggers chaining supported
|
||||||
|
|
||||||
|
genvar trig;
|
||||||
|
generate
|
||||||
|
for (trig = 0; $unsigned(trig) < MTRIG_NUM; ++trig) begin : gblock_mtrig
|
||||||
|
|
||||||
|
assign csr_mcontrol_wr_req[trig] = csr_addr_mcontrol[trig] & csr_wr_req;
|
||||||
|
assign csr_mcontrol_clk_en[trig] = clk_en
|
||||||
|
& (csr_mcontrol_wr_req[trig] | csr_mcontrol_m_ff[trig]);
|
||||||
|
assign csr_mcontrol_upd [trig] = ~csr_mcontrol_dmode_ff[trig]
|
||||||
|
? csr_mcontrol_wr_req[trig]
|
||||||
|
: tdu_dsbl_i & csr_mcontrol_wr_req[trig];
|
||||||
|
|
||||||
|
always_ff @(negedge rst_n, posedge clk) begin
|
||||||
|
if(~rst_n) begin
|
||||||
|
csr_mcontrol_dmode_ff [trig] <= 1'b0;
|
||||||
|
csr_mcontrol_m_ff [trig] <= 1'b0;
|
||||||
|
csr_mcontrol_exec_ff [trig] <= 1'b0;
|
||||||
|
csr_mcontrol_load_ff [trig] <= 1'b0;
|
||||||
|
csr_mcontrol_store_ff [trig] <= 1'b0;
|
||||||
|
csr_mcontrol_action_ff[trig] <= 1'b0;
|
||||||
|
csr_mcontrol_hit_ff [trig] <= 1'b0;
|
||||||
|
end else if(csr_mcontrol_clk_en[trig]) begin
|
||||||
|
csr_mcontrol_dmode_ff [trig] <= csr_mcontrol_dmode_next[trig];
|
||||||
|
csr_mcontrol_m_ff [trig] <= csr_mcontrol_m_next[trig];
|
||||||
|
csr_mcontrol_exec_ff [trig] <= csr_mcontrol_exec_next[trig];
|
||||||
|
csr_mcontrol_load_ff [trig] <= csr_mcontrol_load_next[trig];
|
||||||
|
csr_mcontrol_store_ff [trig] <= csr_mcontrol_store_next[trig];
|
||||||
|
csr_mcontrol_action_ff[trig] <= csr_mcontrol_action_next[trig];
|
||||||
|
csr_mcontrol_hit_ff [trig] <= csr_mcontrol_hit_next[trig];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
if (csr_mcontrol_upd[trig]) begin
|
||||||
|
csr_mcontrol_dmode_next [trig] = csr_wr_data[SCR1_TDU_TDATA1_DMODE];
|
||||||
|
csr_mcontrol_m_next [trig] = csr_wr_data[SCR1_TDU_MCONTROL_M];
|
||||||
|
csr_mcontrol_exec_next [trig] = csr_wr_data[SCR1_TDU_MCONTROL_EXECUTE];
|
||||||
|
csr_mcontrol_load_next [trig] = csr_wr_data[SCR1_TDU_MCONTROL_LOAD];
|
||||||
|
csr_mcontrol_store_next [trig] = csr_wr_data[SCR1_TDU_MCONTROL_STORE];
|
||||||
|
csr_mcontrol_action_next[trig] = (csr_wr_data[SCR1_TDU_MCONTROL_ACTION_HI
|
||||||
|
:SCR1_TDU_MCONTROL_ACTION_LO] == 'b1);
|
||||||
|
csr_mcontrol_hit_next [trig] = csr_wr_data[SCR1_TDU_MCONTROL_HIT];
|
||||||
|
end else begin
|
||||||
|
csr_mcontrol_dmode_next [trig] = csr_mcontrol_dmode_ff [trig];
|
||||||
|
csr_mcontrol_m_next [trig] = csr_mcontrol_m_ff [trig];
|
||||||
|
csr_mcontrol_exec_next [trig] = csr_mcontrol_exec_ff [trig];
|
||||||
|
csr_mcontrol_load_next [trig] = csr_mcontrol_load_ff [trig];
|
||||||
|
csr_mcontrol_store_next [trig] = csr_mcontrol_store_ff [trig];
|
||||||
|
csr_mcontrol_action_next[trig] = csr_mcontrol_action_ff[trig];
|
||||||
|
csr_mcontrol_hit_next [trig] = exu2tdu_bp_retire_i[trig]
|
||||||
|
? 1'b1
|
||||||
|
: csr_mcontrol_hit_ff[trig];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// TDATA2 register
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign csr_tdata2_upd[trig] = ~csr_mcontrol_dmode_ff[trig]
|
||||||
|
? clk_en & csr_addr_tdata2[trig] & csr_wr_req
|
||||||
|
: clk_en & csr_addr_tdata2[trig] & csr_wr_req & tdu_dsbl_i;
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if (csr_tdata2_upd[trig]) begin
|
||||||
|
csr_tdata2_ff[trig] <= csr_wr_data;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
endgenerate // gblock_mtrig
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// TDU <-> EXU interface
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign csr_icount_hit = ~tdu_dsbl_i & csr_icount_m_ff
|
||||||
|
? exu2tdu_imon_i.vd & (csr_icount_count_ff == 14'b1) & ~csr_icount_skip_ff
|
||||||
|
: 1'b0;
|
||||||
|
|
||||||
|
`ifndef SCR1_TDU_ICOUNT_EN
|
||||||
|
assign tdu2exu_ibrkpt_match_o = csr_mcontrol_exec_hit;
|
||||||
|
assign tdu2exu_ibrkpt_exc_req_o = |csr_mcontrol_exec_hit;
|
||||||
|
`else
|
||||||
|
assign tdu2exu_ibrkpt_match_o = {csr_icount_hit, csr_mcontrol_exec_hit};
|
||||||
|
assign tdu2exu_ibrkpt_exc_req_o = |csr_mcontrol_exec_hit | csr_icount_hit;
|
||||||
|
`endif // SCR1_TDU_ICOUNT_EN
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// TDU <-> LSU interface
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Breakpoint logic
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
generate
|
||||||
|
for (trig = 0; $unsigned(trig) < MTRIG_NUM; ++trig) begin : gblock_break_trig
|
||||||
|
assign csr_mcontrol_exec_hit[trig] = ~tdu_dsbl_i
|
||||||
|
& csr_mcontrol_m_ff[trig]
|
||||||
|
& csr_mcontrol_exec_ff[trig]
|
||||||
|
& exu2tdu_imon_i.vd
|
||||||
|
& exu2tdu_imon_i.addr == csr_tdata2_ff[trig];
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
`ifndef SCR1_TDU_ICOUNT_EN
|
||||||
|
assign tdu2lsu_ibrkpt_exc_req_o = |csr_mcontrol_exec_hit;
|
||||||
|
`else
|
||||||
|
assign tdu2lsu_ibrkpt_exc_req_o = |csr_mcontrol_exec_hit | csr_icount_hit;
|
||||||
|
`endif // SCR1_TDU_ICOUNT_EN
|
||||||
|
|
||||||
|
// Watchpoint logic
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
generate
|
||||||
|
for( trig = 0; $unsigned(trig) < MTRIG_NUM; ++trig ) begin : gblock_watch_trig
|
||||||
|
assign csr_mcontrol_ldst_hit[trig] = ~tdu_dsbl_i
|
||||||
|
& csr_mcontrol_m_ff[trig]
|
||||||
|
& lsu2tdu_dmon_i.vd
|
||||||
|
& ( (csr_mcontrol_load_ff [trig] & lsu2tdu_dmon_i.load)
|
||||||
|
| (csr_mcontrol_store_ff[trig] & lsu2tdu_dmon_i.store))
|
||||||
|
& lsu2tdu_dmon_i.addr == csr_tdata2_ff[trig];
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
assign tdu2lsu_dbrkpt_match_o = csr_mcontrol_ldst_hit;
|
||||||
|
assign tdu2lsu_dbrkpt_exc_req_o = |csr_mcontrol_ldst_hit;
|
||||||
|
|
||||||
|
`ifndef SCR1_TDU_EN
|
||||||
|
assign tdu2lsu_brk_en_o = |csr_mcontrol_m_ff | csr_icount_m_ff;
|
||||||
|
`endif // SCR1_TDU_EN
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// TDU <-> HDU interface
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
tdu2hdu_dmode_req_o = 1'b0;
|
||||||
|
|
||||||
|
for(int unsigned i = 0; i < MTRIG_NUM; ++i) begin
|
||||||
|
tdu2hdu_dmode_req_o |= (csr_mcontrol_action_ff[i] & exu2tdu_bp_retire_i[i]);
|
||||||
|
end
|
||||||
|
`ifdef SCR1_TDU_ICOUNT_EN
|
||||||
|
tdu2hdu_dmode_req_o |= (csr_icount_action_ff & exu2tdu_bp_retire_i[ALLTRIG_NUM-1]);
|
||||||
|
`endif // SCR1_TDU_ICOUNT_EN
|
||||||
|
end
|
||||||
|
|
||||||
|
`ifdef SCR1_TRGT_SIMULATION
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Assertion
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
SVA_TDU_X_CONTROL : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
!$isunknown({clk_en, tdu_dsbl_i, csr2tdu_req_i,
|
||||||
|
exu2tdu_imon_i.vd, lsu2tdu_dmon_i.vd, exu2tdu_bp_retire_i})
|
||||||
|
) else $error("TDU Error: control signals is X - %0b", {clk_en,
|
||||||
|
tdu_dsbl_i, csr2tdu_req_i, exu2tdu_imon_i.vd, lsu2tdu_dmon_i.vd, exu2tdu_bp_retire_i});
|
||||||
|
|
||||||
|
SVA_DM_X_CLK_EN : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
!$isunknown(clk_en)
|
||||||
|
) else $error("TDU Error: clk_en control signals is X");
|
||||||
|
|
||||||
|
SVA_DM_X_DSBL : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
!$isunknown(tdu_dsbl_i)
|
||||||
|
) else $error("TDU Error: tdu_dsbl_i control signals is X");
|
||||||
|
|
||||||
|
SVA_DM_X_CSR2TDU_REQ : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
!$isunknown(csr2tdu_req_i)
|
||||||
|
) else $error("TDU Error: csr2tdu_req_i control signals is X");
|
||||||
|
|
||||||
|
SVA_DM_X_I_MON_VD : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
!$isunknown(exu2tdu_imon_i.vd)
|
||||||
|
) else $error("TDU Error: exu2tdu_imon_i.vd control signals is X");
|
||||||
|
|
||||||
|
SVA_DM_X_D_MON_VD : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
!$isunknown(lsu2tdu_dmon_i.vd)
|
||||||
|
) else $error("TDU Error: lsu2tdu_dmon_i.vd control signals is X");
|
||||||
|
|
||||||
|
SVA_DM_X_BP_RETIRE : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
!$isunknown(exu2tdu_bp_retire_i)
|
||||||
|
) else $error("TDU Error: exu2tdu_bp_retire_i control signals is X");
|
||||||
|
|
||||||
|
SVA_TDU_X_CSR : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
csr2tdu_req_i |-> !$isunknown({csr2tdu_cmd_i,csr2tdu_addr_i})
|
||||||
|
) else $error("TDU Error: csr is X");
|
||||||
|
|
||||||
|
SVA_TDU_XW_CSR : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
(csr2tdu_req_i & csr_wr_req) |-> !$isunknown(csr2tdu_wdata_i)
|
||||||
|
) else $error("TDU Error: csr wdata is X ");
|
||||||
|
|
||||||
|
SVA_TDU_X_IMON : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
exu2tdu_imon_i.vd |-> !$isunknown({exu2tdu_imon_i.req,exu2tdu_imon_i.addr})
|
||||||
|
) else $error("TDU Error: imonitor is X");
|
||||||
|
|
||||||
|
SVA_TDU_X_DMON : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
lsu2tdu_dmon_i.vd |-> !$isunknown({lsu2tdu_dmon_i})
|
||||||
|
) else $error("TDU Error: dmonitor is X");
|
||||||
|
|
||||||
|
`endif // SCR1_TRGT_SIMULATION
|
||||||
|
|
||||||
|
endmodule : scr1_pipe_tdu
|
||||||
|
|
||||||
|
`endif // SCR1_TDU_EN
|
||||||
825
src_ref/core/pipeline/scr1_pipe_top.sv
Normal file
825
src_ref/core/pipeline/scr1_pipe_top.sv
Normal file
@@ -0,0 +1,825 @@
|
|||||||
|
/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
|
||||||
|
/// @file <scr1_pipe_top.sv>
|
||||||
|
/// @brief SCR1 pipeline top
|
||||||
|
///
|
||||||
|
|
||||||
|
`include "scr1_arch_description.svh"
|
||||||
|
`include "scr1_memif.svh"
|
||||||
|
`include "scr1_riscv_isa_decoding.svh"
|
||||||
|
`include "scr1_csr.svh"
|
||||||
|
|
||||||
|
`ifdef SCR1_IPIC_EN
|
||||||
|
`include "scr1_ipic.svh"
|
||||||
|
`endif // SCR1_IPIC_EN
|
||||||
|
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
`include "scr1_hdu.svh"
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
|
||||||
|
`ifdef SCR1_TDU_EN
|
||||||
|
`include "scr1_tdu.svh"
|
||||||
|
`endif // SCR1_TDU_EN
|
||||||
|
|
||||||
|
module scr1_pipe_top (
|
||||||
|
// Common
|
||||||
|
input logic pipe_rst_n, // Pipe reset
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
input logic pipe2hdu_rdc_qlfy_i, // Pipe RDC qualifier
|
||||||
|
input logic dbg_rst_n, // Debug reset
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
input logic clk, // Pipe clock
|
||||||
|
|
||||||
|
// Instruction Memory Interface
|
||||||
|
output logic pipe2imem_req_o, // IMEM request
|
||||||
|
output type_scr1_mem_cmd_e pipe2imem_cmd_o, // IMEM command
|
||||||
|
output logic [`SCR1_IMEM_AWIDTH-1:0] pipe2imem_addr_o, // IMEM address
|
||||||
|
input logic imem2pipe_req_ack_i, // IMEM request acknowledge
|
||||||
|
input logic [`SCR1_IMEM_DWIDTH-1:0] imem2pipe_rdata_i, // IMEM read data
|
||||||
|
input type_scr1_mem_resp_e imem2pipe_resp_i, // IMEM response
|
||||||
|
|
||||||
|
// Data Memory Interface
|
||||||
|
output logic pipe2dmem_req_o, // DMEM request
|
||||||
|
output type_scr1_mem_cmd_e pipe2dmem_cmd_o, // DMEM command
|
||||||
|
output type_scr1_mem_width_e pipe2dmem_width_o, // DMEM data width
|
||||||
|
output logic [`SCR1_DMEM_AWIDTH-1:0] pipe2dmem_addr_o, // DMEM address
|
||||||
|
output logic [`SCR1_DMEM_DWIDTH-1:0] pipe2dmem_wdata_o, // DMEM write data
|
||||||
|
input logic dmem2pipe_req_ack_i, // DMEM request acknowledge
|
||||||
|
input logic [`SCR1_DMEM_DWIDTH-1:0] dmem2pipe_rdata_i, // DMEM read data
|
||||||
|
input type_scr1_mem_resp_e dmem2pipe_resp_i, // DMEM response
|
||||||
|
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
// Debug interface:
|
||||||
|
input logic dbg_en, // 1 - debug operations enabled
|
||||||
|
// DM <-> Pipeline: HART Run Control i/f
|
||||||
|
input logic dm2pipe_active_i, // Debug Module active flag
|
||||||
|
|
||||||
|
input logic dm2pipe_cmd_req_i, // Request from Debug Module
|
||||||
|
input type_scr1_hdu_dbgstates_e dm2pipe_cmd_i, // Command from Debug Module
|
||||||
|
output logic pipe2dm_cmd_resp_o, // Response to Debug Module
|
||||||
|
output logic pipe2dm_cmd_rcode_o, // Debug Module return code: 0 - Ok; 1 - Error
|
||||||
|
output logic pipe2dm_hart_event_o, // HART event flag
|
||||||
|
output type_scr1_hdu_hartstatus_s pipe2dm_hart_status_o, // HART status
|
||||||
|
|
||||||
|
// DM <-> Pipeline: Program Buffer - HART instruction execution i/f
|
||||||
|
output logic [SCR1_HDU_PBUF_ADDR_WIDTH-1:0] pipe2dm_pbuf_addr_o, // Program Buffer address
|
||||||
|
input logic [SCR1_HDU_CORE_INSTR_WIDTH-1:0] dm2pipe_pbuf_instr_i, // Program Buffer instruction
|
||||||
|
|
||||||
|
// DM <-> Pipeline: HART Abstract Data regs i/f
|
||||||
|
output logic pipe2dm_dreg_req_o, // Abstract Data Register request
|
||||||
|
output logic pipe2dm_dreg_wr_o, // Abstract Data Register write
|
||||||
|
output logic [`SCR1_XLEN-1:0] pipe2dm_dreg_wdata_o, // Abstract Data Register write data
|
||||||
|
input logic dm2pipe_dreg_resp_i, // Abstract Data Register response
|
||||||
|
input logic dm2pipe_dreg_fail_i, // Abstract Data Register fail - possibly not needed?
|
||||||
|
input logic [`SCR1_XLEN-1:0] dm2pipe_dreg_rdata_i, // Abstract Data Register read data
|
||||||
|
|
||||||
|
// DM <-> Pipeling: PC i/f
|
||||||
|
output logic [`SCR1_XLEN-1:0] pipe2dm_pc_sample_o, // Current PC for sampling
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
|
||||||
|
// IRQ
|
||||||
|
`ifdef SCR1_IPIC_EN
|
||||||
|
input logic [SCR1_IRQ_LINES_NUM-1:0] soc2pipe_irq_lines_i, // External interrupt request lines
|
||||||
|
`else // SCR1_IPIC_EN
|
||||||
|
input logic soc2pipe_irq_ext_i, // External interrupt request
|
||||||
|
`endif // SCR1_IPIC_EN
|
||||||
|
input logic soc2pipe_irq_soft_i, // Software generated interrupt request
|
||||||
|
input logic soc2pipe_irq_mtimer_i, // Machine timer interrupt request
|
||||||
|
|
||||||
|
// Memory-mapped external timer
|
||||||
|
input logic [63:0] soc2pipe_mtimer_val_i, // Machine timer value
|
||||||
|
|
||||||
|
`ifdef SCR1_CLKCTRL_EN
|
||||||
|
// CLK_CTRL interface
|
||||||
|
output logic pipe2clkctl_sleep_req_o, // CLK disable request to CLK gating circuit
|
||||||
|
output logic pipe2clkctl_wake_req_o, // CLK enable request to CLK gating circuit
|
||||||
|
input logic clkctl2pipe_clk_alw_on_i, // Not gated CLK
|
||||||
|
input logic clkctl2pipe_clk_dbgc_i, // CLK for HDU (not gated for now)
|
||||||
|
input logic clkctl2pipe_clk_en_i, // CLK enabled flag
|
||||||
|
`endif // SCR1_CLKCTRL_EN
|
||||||
|
|
||||||
|
// Fuse
|
||||||
|
input logic [`SCR1_XLEN-1:0] soc2pipe_fuse_mhartid_i // Fuse MHARTID value
|
||||||
|
);
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Local signals declaration
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Pipeline control
|
||||||
|
logic [`SCR1_XLEN-1:0] curr_pc; // Current PC
|
||||||
|
logic [`SCR1_XLEN-1:0] next_pc; // Is written to MEPC on interrupt trap
|
||||||
|
logic new_pc_req; // New PC request (jumps, branches, traps etc)
|
||||||
|
logic [`SCR1_XLEN-1:0] new_pc; // New PC
|
||||||
|
|
||||||
|
logic stop_fetch; // Stop IFU
|
||||||
|
logic exu_exc_req; // Exception request
|
||||||
|
logic brkpt; // Breakpoint (sw) on current instruction
|
||||||
|
logic exu_init_pc; // Reset exit
|
||||||
|
logic wfi_run2halt; // Transition to WFI halted state
|
||||||
|
logic instret; // Instruction retirement (with or without exception)
|
||||||
|
`ifndef SCR1_CSR_REDUCED_CNT
|
||||||
|
logic instret_nexc; // Instruction retirement (without exception)
|
||||||
|
`endif // SCR1_CSR_REDUCED_CNT
|
||||||
|
`ifdef SCR1_IPIC_EN
|
||||||
|
logic ipic2csr_irq; // IRQ request from IPIC
|
||||||
|
`endif // SCR1_IPIC_EN
|
||||||
|
`ifdef SCR1_TDU_EN
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
logic brkpt_hw; // Hardware breakpoint on current instruction
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
`endif // SCR1_TDU_EN
|
||||||
|
`ifdef SCR1_CLKCTRL_EN
|
||||||
|
logic imem_txns_pending; // There are pending imem transactions
|
||||||
|
logic wfi_halted; // WFI halted state
|
||||||
|
`endif // SCR1_CLKCTRL_EN
|
||||||
|
|
||||||
|
// IFU <-> IDU
|
||||||
|
logic ifu2idu_vd; // IFU request
|
||||||
|
logic [`SCR1_IMEM_DWIDTH-1:0] ifu2idu_instr; // IFU instruction
|
||||||
|
logic ifu2idu_imem_err; // IFU instruction access fault
|
||||||
|
logic ifu2idu_err_rvi_hi; // 1 - imem fault when trying to fetch second half of an unaligned RVI instruction
|
||||||
|
logic idu2ifu_rdy; // IDU ready for new data
|
||||||
|
|
||||||
|
// IDU <-> EXU
|
||||||
|
logic idu2exu_req; // IDU request
|
||||||
|
type_scr1_exu_cmd_s idu2exu_cmd; // IDU command (see scr1_riscv_isa_decoding.svh)
|
||||||
|
logic idu2exu_use_rs1; // Instruction uses rs1
|
||||||
|
logic idu2exu_use_rs2; // Instruction uses rs2
|
||||||
|
`ifndef SCR1_NO_EXE_STAGE
|
||||||
|
logic idu2exu_use_rd; // Instruction uses rd
|
||||||
|
logic idu2exu_use_imm; // Instruction uses immediate
|
||||||
|
`endif // SCR1_NO_EXE_STAGE
|
||||||
|
logic exu2idu_rdy; // EXU ready for new data
|
||||||
|
|
||||||
|
// EXU <-> MPRF
|
||||||
|
logic [`SCR1_MPRF_AWIDTH-1:0] exu2mprf_rs1_addr; // MPRF rs1 read address
|
||||||
|
logic [`SCR1_XLEN-1:0] mprf2exu_rs1_data; // MPRF rs1 read data
|
||||||
|
logic [`SCR1_MPRF_AWIDTH-1:0] exu2mprf_rs2_addr; // MPRF rs2 read address
|
||||||
|
logic [`SCR1_XLEN-1:0] mprf2exu_rs2_data; // MPRF rs2 read data
|
||||||
|
logic exu2mprf_w_req; // MPRF write request
|
||||||
|
logic [`SCR1_MPRF_AWIDTH-1:0] exu2mprf_rd_addr; // MPRF rd write address
|
||||||
|
logic [`SCR1_XLEN-1:0] exu2mprf_rd_data; // MPRF rd write data
|
||||||
|
|
||||||
|
// EXU <-> CSR
|
||||||
|
logic [SCR1_CSR_ADDR_WIDTH-1:0] exu2csr_rw_addr; // CSR read/write address
|
||||||
|
logic exu2csr_r_req; // CSR read request
|
||||||
|
logic [`SCR1_XLEN-1:0] csr2exu_r_data; // CSR read data
|
||||||
|
logic exu2csr_w_req; // CSR write request
|
||||||
|
type_scr1_csr_cmd_sel_e exu2csr_w_cmd; // CSR write command
|
||||||
|
logic [`SCR1_XLEN-1:0] exu2csr_w_data; // CSR write data
|
||||||
|
logic csr2exu_rw_exc; // CSR read/write access exception
|
||||||
|
|
||||||
|
// EXU <-> CSR event interface
|
||||||
|
logic exu2csr_take_irq; // Take IRQ trap
|
||||||
|
logic exu2csr_take_exc; // Take exception trap
|
||||||
|
logic exu2csr_mret_update; // MRET update CSR
|
||||||
|
logic exu2csr_mret_instr; // MRET instruction
|
||||||
|
type_scr1_exc_code_e exu2csr_exc_code; // Exception code (see scr1_arch_types.svh)
|
||||||
|
logic [`SCR1_XLEN-1:0] exu2csr_trap_val; // Trap value
|
||||||
|
logic [`SCR1_XLEN-1:0] csr2exu_new_pc; // Exception/IRQ/MRET new PC
|
||||||
|
logic csr2exu_irq; // IRQ request
|
||||||
|
logic csr2exu_ip_ie; // Some IRQ pending and locally enabled
|
||||||
|
logic csr2exu_mstatus_mie_up; // MSTATUS or MIE update in the current cycle
|
||||||
|
|
||||||
|
`ifdef SCR1_IPIC_EN
|
||||||
|
// CSR <-> IPIC
|
||||||
|
logic csr2ipic_r_req; // IPIC read request
|
||||||
|
logic csr2ipic_w_req; // IPIC write request
|
||||||
|
logic [2:0] csr2ipic_addr; // IPIC address
|
||||||
|
logic [`SCR1_XLEN-1:0] csr2ipic_wdata; // IPIC write data
|
||||||
|
logic [`SCR1_XLEN-1:0] ipic2csr_rdata; // IPIC read data
|
||||||
|
`endif // SCR1_IPIC_EN
|
||||||
|
|
||||||
|
`ifdef SCR1_TDU_EN
|
||||||
|
// CSR <-> TDU
|
||||||
|
logic csr2tdu_req; // Request to TDU
|
||||||
|
type_scr1_csr_cmd_sel_e csr2tdu_cmd; // TDU command
|
||||||
|
logic [SCR1_CSR_ADDR_TDU_OFFS_W-1:0] csr2tdu_addr; // TDU address
|
||||||
|
logic [`SCR1_XLEN-1:0] csr2tdu_wdata; // TDU write data
|
||||||
|
logic [`SCR1_XLEN-1:0] tdu2csr_rdata; // TDU read data
|
||||||
|
type_scr1_csr_resp_e tdu2csr_resp; // TDU response
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
// Qualified TDU input signals from pipe_rst_n
|
||||||
|
// reset domain:
|
||||||
|
logic csr2tdu_req_qlfy; // Request to TDU
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
|
||||||
|
// EXU/LSU <-> TDU
|
||||||
|
type_scr1_brkm_instr_mon_s exu2tdu_i_mon; // Instruction monitor
|
||||||
|
type_scr1_brkm_lsu_mon_s lsu2tdu_d_mon; // Data monitor
|
||||||
|
logic [SCR1_TDU_ALLTRIG_NUM-1:0] tdu2exu_i_match; // Instruction breakpoint(s) match
|
||||||
|
logic [SCR1_TDU_MTRIG_NUM-1:0] tdu2lsu_d_match; // Data breakpoint(s) match
|
||||||
|
logic tdu2exu_i_x_req; // Instruction breakpoint exception
|
||||||
|
logic tdu2lsu_i_x_req; // Instruction breakpoint exception
|
||||||
|
logic tdu2lsu_d_x_req; // Data breakpoint exception
|
||||||
|
logic [SCR1_TDU_ALLTRIG_NUM-1:0] exu2tdu_bp_retire; // Instruction with breakpoint flag retire
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
// Qualified TDU input signals from pipe_rst_n
|
||||||
|
// reset domain:
|
||||||
|
type_scr1_brkm_instr_mon_s exu2tdu_i_mon_qlfy; // Instruction monitor
|
||||||
|
type_scr1_brkm_lsu_mon_s lsu2tdu_d_mon_qlfy; // Data monitor
|
||||||
|
logic [SCR1_TDU_ALLTRIG_NUM-1:0] exu2tdu_bp_retire_qlfy; // Instruction with breakpoint flag retire
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
`endif // SCR1_TDU_EN
|
||||||
|
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
// Debug signals:
|
||||||
|
logic fetch_pbuf; // Fetch instructions provided by Program Buffer (via HDU)
|
||||||
|
logic csr2hdu_req; // Request to HDU
|
||||||
|
type_scr1_csr_cmd_sel_e csr2hdu_cmd; // HDU command
|
||||||
|
logic [SCR1_HDU_DEBUGCSR_ADDR_WIDTH-1:0] csr2hdu_addr; // HDU address
|
||||||
|
logic [`SCR1_XLEN-1:0] csr2hdu_wdata; // HDU write data
|
||||||
|
logic [`SCR1_XLEN-1:0] hdu2csr_rdata; // HDU read data
|
||||||
|
type_scr1_csr_resp_e hdu2csr_resp; // HDU response
|
||||||
|
// Qualified HDU input signals from pipe_rst_n
|
||||||
|
// reset domain:
|
||||||
|
logic csr2hdu_req_qlfy; // Request to HDU
|
||||||
|
|
||||||
|
logic hwbrk_dsbl; // Disables TDU
|
||||||
|
logic hdu_hwbrk_dsbl; // Disables TDU
|
||||||
|
logic tdu2hdu_dmode_req; // TDU requests transition to debug mode
|
||||||
|
|
||||||
|
logic exu_no_commit; // Forbid instruction commitment
|
||||||
|
logic exu_irq_dsbl; // Disable IRQ
|
||||||
|
logic exu_pc_advmt_dsbl; // Forbid PC advancement
|
||||||
|
logic exu_dmode_sstep_en; // Enable single-step
|
||||||
|
|
||||||
|
logic dbg_halted; // Debug halted state
|
||||||
|
logic dbg_run2halt; // Transition to debug halted state
|
||||||
|
logic dbg_halt2run; // Transition to run state
|
||||||
|
logic dbg_run_start; // First cycle of run state
|
||||||
|
logic [`SCR1_XLEN-1:0] dbg_new_pc; // New PC as starting point for HART Resume
|
||||||
|
|
||||||
|
logic ifu2hdu_pbuf_rdy;
|
||||||
|
logic hdu2ifu_pbuf_vd;
|
||||||
|
logic hdu2ifu_pbuf_err;
|
||||||
|
logic [SCR1_HDU_CORE_INSTR_WIDTH-1:0] hdu2ifu_pbuf_instr;
|
||||||
|
|
||||||
|
// Qualified HDU input signals from pipe_rst_n reset domain:
|
||||||
|
logic ifu2hdu_pbuf_rdy_qlfy;
|
||||||
|
logic exu_busy_qlfy;
|
||||||
|
logic instret_qlfy;
|
||||||
|
logic exu_init_pc_qlfy;
|
||||||
|
logic exu_exc_req_qlfy;
|
||||||
|
logic brkpt_qlfy;
|
||||||
|
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
|
||||||
|
logic exu_busy;
|
||||||
|
|
||||||
|
|
||||||
|
`ifndef SCR1_CLKCTRL_EN
|
||||||
|
logic pipe2clkctl_wake_req_o;
|
||||||
|
`endif // SCR1_CLKCTRL_EN
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Pipeline logic
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
assign stop_fetch = wfi_run2halt
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
| fetch_pbuf
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
;
|
||||||
|
|
||||||
|
`ifdef SCR1_CLKCTRL_EN
|
||||||
|
assign pipe2clkctl_sleep_req_o = wfi_halted & ~imem_txns_pending;
|
||||||
|
assign pipe2clkctl_wake_req_o = csr2exu_ip_ie
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
| dm2pipe_active_i
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
;
|
||||||
|
`endif // SCR1_CLKCTRL_EN
|
||||||
|
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
assign pipe2dm_pc_sample_o = curr_pc;
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Instruction fetch unit
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
scr1_pipe_ifu i_pipe_ifu (
|
||||||
|
.rst_n (pipe_rst_n ),
|
||||||
|
.clk (clk ),
|
||||||
|
|
||||||
|
// Instruction memory interface
|
||||||
|
.imem2ifu_req_ack_i (imem2pipe_req_ack_i),
|
||||||
|
.ifu2imem_req_o (pipe2imem_req_o ),
|
||||||
|
.ifu2imem_cmd_o (pipe2imem_cmd_o ),
|
||||||
|
.ifu2imem_addr_o (pipe2imem_addr_o ),
|
||||||
|
.imem2ifu_rdata_i (imem2pipe_rdata_i ),
|
||||||
|
.imem2ifu_resp_i (imem2pipe_resp_i ),
|
||||||
|
|
||||||
|
// New PC interface
|
||||||
|
.exu2ifu_pc_new_req_i (new_pc_req ),
|
||||||
|
.exu2ifu_pc_new_i (new_pc ),
|
||||||
|
.pipe2ifu_stop_fetch_i (stop_fetch ),
|
||||||
|
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
// IFU <-> HDU Program Buffer interface
|
||||||
|
.hdu2ifu_pbuf_fetch_i (fetch_pbuf ),
|
||||||
|
.ifu2hdu_pbuf_rdy_o (ifu2hdu_pbuf_rdy ),
|
||||||
|
.hdu2ifu_pbuf_vd_i (hdu2ifu_pbuf_vd ),
|
||||||
|
.hdu2ifu_pbuf_err_i (hdu2ifu_pbuf_err ),
|
||||||
|
.hdu2ifu_pbuf_instr_i (hdu2ifu_pbuf_instr ),
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
`ifdef SCR1_CLKCTRL_EN
|
||||||
|
.ifu2pipe_imem_txns_pnd_o (imem_txns_pending ),
|
||||||
|
`endif // SCR1_CLKCTRL_EN
|
||||||
|
|
||||||
|
// IFU <-> IDU interface
|
||||||
|
.idu2ifu_rdy_i (idu2ifu_rdy ),
|
||||||
|
.ifu2idu_instr_o (ifu2idu_instr ),
|
||||||
|
.ifu2idu_imem_err_o (ifu2idu_imem_err ),
|
||||||
|
.ifu2idu_err_rvi_hi_o (ifu2idu_err_rvi_hi ),
|
||||||
|
.ifu2idu_vd_o (ifu2idu_vd )
|
||||||
|
);
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Instruction decode unit
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
scr1_pipe_idu i_pipe_idu (
|
||||||
|
`ifdef SCR1_TRGT_SIMULATION
|
||||||
|
.rst_n (pipe_rst_n ),
|
||||||
|
.clk (clk ),
|
||||||
|
`endif // SCR1_TRGT_SIMULATION
|
||||||
|
.idu2ifu_rdy_o (idu2ifu_rdy ),
|
||||||
|
.ifu2idu_instr_i (ifu2idu_instr ),
|
||||||
|
.ifu2idu_imem_err_i (ifu2idu_imem_err ),
|
||||||
|
.ifu2idu_err_rvi_hi_i (ifu2idu_err_rvi_hi),
|
||||||
|
.ifu2idu_vd_i (ifu2idu_vd ),
|
||||||
|
|
||||||
|
.idu2exu_req_o (idu2exu_req ),
|
||||||
|
.idu2exu_cmd_o (idu2exu_cmd ),
|
||||||
|
.idu2exu_use_rs1_o (idu2exu_use_rs1 ),
|
||||||
|
.idu2exu_use_rs2_o (idu2exu_use_rs2 ),
|
||||||
|
`ifndef SCR1_NO_EXE_STAGE
|
||||||
|
.idu2exu_use_rd_o (idu2exu_use_rd ),
|
||||||
|
.idu2exu_use_imm_o (idu2exu_use_imm ),
|
||||||
|
`endif // SCR1_NO_EXE_STAGE
|
||||||
|
.exu2idu_rdy_i (exu2idu_rdy )
|
||||||
|
);
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Execution unit
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
scr1_pipe_exu i_pipe_exu (
|
||||||
|
.rst_n (pipe_rst_n ),
|
||||||
|
.clk (clk ),
|
||||||
|
`ifdef SCR1_CLKCTRL_EN
|
||||||
|
.clk_alw_on (clkctl2pipe_clk_alw_on_i),
|
||||||
|
.clk_pipe_en (clkctl2pipe_clk_en_i),
|
||||||
|
`endif // SCR1_CLKCTRL_EN
|
||||||
|
|
||||||
|
// IDU <-> EXU interface
|
||||||
|
.idu2exu_req_i (idu2exu_req ),
|
||||||
|
.exu2idu_rdy_o (exu2idu_rdy ),
|
||||||
|
.idu2exu_cmd_i (idu2exu_cmd ),
|
||||||
|
.idu2exu_use_rs1_i (idu2exu_use_rs1 ),
|
||||||
|
.idu2exu_use_rs2_i (idu2exu_use_rs2 ),
|
||||||
|
`ifndef SCR1_NO_EXE_STAGE
|
||||||
|
.idu2exu_use_rd_i (idu2exu_use_rd ),
|
||||||
|
.idu2exu_use_imm_i (idu2exu_use_imm ),
|
||||||
|
`endif // SCR1_NO_EXE_STAGE
|
||||||
|
|
||||||
|
// EXU <-> MPRF interface
|
||||||
|
.exu2mprf_rs1_addr_o (exu2mprf_rs1_addr ),
|
||||||
|
.mprf2exu_rs1_data_i (mprf2exu_rs1_data ),
|
||||||
|
.exu2mprf_rs2_addr_o (exu2mprf_rs2_addr ),
|
||||||
|
.mprf2exu_rs2_data_i (mprf2exu_rs2_data ),
|
||||||
|
.exu2mprf_w_req_o (exu2mprf_w_req ),
|
||||||
|
.exu2mprf_rd_addr_o (exu2mprf_rd_addr ),
|
||||||
|
.exu2mprf_rd_data_o (exu2mprf_rd_data ),
|
||||||
|
|
||||||
|
// EXU <-> CSR read/write interface
|
||||||
|
.exu2csr_rw_addr_o (exu2csr_rw_addr ),
|
||||||
|
.exu2csr_r_req_o (exu2csr_r_req ),
|
||||||
|
.csr2exu_r_data_i (csr2exu_r_data ),
|
||||||
|
.exu2csr_w_req_o (exu2csr_w_req ),
|
||||||
|
.exu2csr_w_cmd_o (exu2csr_w_cmd ),
|
||||||
|
.exu2csr_w_data_o (exu2csr_w_data ),
|
||||||
|
.csr2exu_rw_exc_i (csr2exu_rw_exc ),
|
||||||
|
|
||||||
|
// EXU <-> CSR event interface
|
||||||
|
.exu2csr_take_irq_o (exu2csr_take_irq ),
|
||||||
|
.exu2csr_take_exc_o (exu2csr_take_exc ),
|
||||||
|
.exu2csr_mret_update_o (exu2csr_mret_update ),
|
||||||
|
.exu2csr_mret_instr_o (exu2csr_mret_instr ),
|
||||||
|
.exu2csr_exc_code_o (exu2csr_exc_code ),
|
||||||
|
.exu2csr_trap_val_o (exu2csr_trap_val ),
|
||||||
|
.csr2exu_new_pc_i (csr2exu_new_pc ),
|
||||||
|
.csr2exu_irq_i (csr2exu_irq ),
|
||||||
|
.csr2exu_ip_ie_i (csr2exu_ip_ie ),
|
||||||
|
.csr2exu_mstatus_mie_up_i (csr2exu_mstatus_mie_up ),
|
||||||
|
|
||||||
|
// EXU <-> DMEM interface
|
||||||
|
.exu2dmem_req_o (pipe2dmem_req_o ),
|
||||||
|
.exu2dmem_cmd_o (pipe2dmem_cmd_o ),
|
||||||
|
.exu2dmem_width_o (pipe2dmem_width_o ),
|
||||||
|
.exu2dmem_addr_o (pipe2dmem_addr_o ),
|
||||||
|
.exu2dmem_wdata_o (pipe2dmem_wdata_o ),
|
||||||
|
.dmem2exu_req_ack_i (dmem2pipe_req_ack_i ),
|
||||||
|
.dmem2exu_rdata_i (dmem2pipe_rdata_i ),
|
||||||
|
.dmem2exu_resp_i (dmem2pipe_resp_i ),
|
||||||
|
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
// EXU <-> HDU interface
|
||||||
|
.hdu2exu_no_commit_i (exu_no_commit ),
|
||||||
|
.hdu2exu_irq_dsbl_i (exu_irq_dsbl ),
|
||||||
|
.hdu2exu_pc_advmt_dsbl_i (exu_pc_advmt_dsbl ),
|
||||||
|
.hdu2exu_dmode_sstep_en_i (exu_dmode_sstep_en ),
|
||||||
|
.hdu2exu_pbuf_fetch_i (fetch_pbuf ),
|
||||||
|
.hdu2exu_dbg_halted_i (dbg_halted ),
|
||||||
|
.hdu2exu_dbg_run2halt_i (dbg_run2halt ),
|
||||||
|
.hdu2exu_dbg_halt2run_i (dbg_halt2run ),
|
||||||
|
.hdu2exu_dbg_run_start_i (dbg_run_start ),
|
||||||
|
.hdu2exu_dbg_new_pc_i (dbg_new_pc ),
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
|
||||||
|
`ifdef SCR1_TDU_EN
|
||||||
|
// EXU <-> TDU interface
|
||||||
|
.exu2tdu_imon_o (exu2tdu_i_mon ),
|
||||||
|
.tdu2exu_ibrkpt_match_i (tdu2exu_i_match ),
|
||||||
|
.tdu2exu_ibrkpt_exc_req_i (tdu2exu_i_x_req ),
|
||||||
|
.lsu2tdu_dmon_o (lsu2tdu_d_mon ),
|
||||||
|
.tdu2lsu_ibrkpt_exc_req_i (tdu2lsu_i_x_req ),
|
||||||
|
.tdu2lsu_dbrkpt_match_i (tdu2lsu_d_match ),
|
||||||
|
.tdu2lsu_dbrkpt_exc_req_i (tdu2lsu_d_x_req ),
|
||||||
|
.exu2tdu_ibrkpt_ret_o (exu2tdu_bp_retire ),
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
.exu2hdu_ibrkpt_hw_o (brkpt_hw ),
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
`endif // SCR1_TDU_EN
|
||||||
|
|
||||||
|
// EXU control
|
||||||
|
.exu2pipe_exc_req_o (exu_exc_req ),
|
||||||
|
.exu2pipe_brkpt_o (brkpt ),
|
||||||
|
.exu2pipe_init_pc_o (exu_init_pc ),
|
||||||
|
.exu2pipe_wfi_run2halt_o (wfi_run2halt ),
|
||||||
|
.exu2pipe_instret_o (instret ),
|
||||||
|
`ifndef SCR1_CSR_REDUCED_CNT
|
||||||
|
.exu2csr_instret_no_exc_o (instret_nexc ),
|
||||||
|
`endif // SCR1_CSR_REDUCED_CNT
|
||||||
|
.exu2pipe_exu_busy_o (exu_busy ),
|
||||||
|
|
||||||
|
// PC interface
|
||||||
|
`ifdef SCR1_CLKCTRL_EN
|
||||||
|
.exu2pipe_wfi_halted_o (wfi_halted ),
|
||||||
|
`endif // SCR1_CLKCTRL_EN
|
||||||
|
.exu2pipe_pc_curr_o (curr_pc ),
|
||||||
|
.exu2csr_pc_next_o (next_pc ),
|
||||||
|
.exu2ifu_pc_new_req_o (new_pc_req ),
|
||||||
|
.exu2ifu_pc_new_o (new_pc )
|
||||||
|
);
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Multi-port register file
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
scr1_pipe_mprf i_pipe_mprf (
|
||||||
|
`ifdef SCR1_MPRF_RST_EN
|
||||||
|
.rst_n (pipe_rst_n ),
|
||||||
|
`endif // SCR1_MPRF_RST_EN
|
||||||
|
.clk (clk ),
|
||||||
|
|
||||||
|
// EXU <-> MPRF interface
|
||||||
|
.exu2mprf_rs1_addr_i (exu2mprf_rs1_addr),
|
||||||
|
.mprf2exu_rs1_data_o (mprf2exu_rs1_data),
|
||||||
|
.exu2mprf_rs2_addr_i (exu2mprf_rs2_addr),
|
||||||
|
.mprf2exu_rs2_data_o (mprf2exu_rs2_data),
|
||||||
|
.exu2mprf_w_req_i (exu2mprf_w_req ),
|
||||||
|
.exu2mprf_rd_addr_i (exu2mprf_rd_addr ),
|
||||||
|
.exu2mprf_rd_data_i (exu2mprf_rd_data )
|
||||||
|
);
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Control and status registers
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
scr1_pipe_csr i_pipe_csr (
|
||||||
|
.rst_n (pipe_rst_n ),
|
||||||
|
.clk (clk ),
|
||||||
|
`ifndef SCR1_CSR_REDUCED_CNT
|
||||||
|
`ifdef SCR1_CLKCTRL_EN
|
||||||
|
.clk_alw_on (clkctl2pipe_clk_alw_on_i),
|
||||||
|
`endif // SCR1_CLKCTRL_EN
|
||||||
|
`endif // SCR1_CSR_REDUCED_CNT
|
||||||
|
|
||||||
|
// EXU <-> CSR read/write interface
|
||||||
|
.exu2csr_r_req_i (exu2csr_r_req ),
|
||||||
|
.exu2csr_rw_addr_i (exu2csr_rw_addr ),
|
||||||
|
.csr2exu_r_data_o (csr2exu_r_data ),
|
||||||
|
.exu2csr_w_req_i (exu2csr_w_req ),
|
||||||
|
.exu2csr_w_cmd_i (exu2csr_w_cmd ),
|
||||||
|
.exu2csr_w_data_i (exu2csr_w_data ),
|
||||||
|
.csr2exu_rw_exc_o (csr2exu_rw_exc ),
|
||||||
|
|
||||||
|
// EXU <-> CSR event interface
|
||||||
|
.exu2csr_take_irq_i (exu2csr_take_irq ),
|
||||||
|
.exu2csr_take_exc_i (exu2csr_take_exc ),
|
||||||
|
.exu2csr_mret_update_i (exu2csr_mret_update ),
|
||||||
|
.exu2csr_mret_instr_i (exu2csr_mret_instr ),
|
||||||
|
.exu2csr_exc_code_i (exu2csr_exc_code ),
|
||||||
|
.exu2csr_trap_val_i (exu2csr_trap_val ),
|
||||||
|
.csr2exu_new_pc_o (csr2exu_new_pc ),
|
||||||
|
.csr2exu_irq_o (csr2exu_irq ),
|
||||||
|
.csr2exu_ip_ie_o (csr2exu_ip_ie ),
|
||||||
|
.csr2exu_mstatus_mie_up_o (csr2exu_mstatus_mie_up ),
|
||||||
|
|
||||||
|
`ifdef SCR1_IPIC_EN
|
||||||
|
// CSR <-> IPIC interface
|
||||||
|
.csr2ipic_r_req_o (csr2ipic_r_req ),
|
||||||
|
.csr2ipic_w_req_o (csr2ipic_w_req ),
|
||||||
|
.csr2ipic_addr_o (csr2ipic_addr ),
|
||||||
|
.csr2ipic_wdata_o (csr2ipic_wdata ),
|
||||||
|
.ipic2csr_rdata_i (ipic2csr_rdata ),
|
||||||
|
`endif // SCR1_IPIC_EN
|
||||||
|
|
||||||
|
// CSR <-> PC interface
|
||||||
|
.exu2csr_pc_curr_i (curr_pc ),
|
||||||
|
.exu2csr_pc_next_i (next_pc ),
|
||||||
|
`ifndef SCR1_CSR_REDUCED_CNT
|
||||||
|
.exu2csr_instret_no_exc_i (instret_nexc ),
|
||||||
|
`endif // SCR1_CSR_REDUCED_CNT
|
||||||
|
|
||||||
|
// IRQ
|
||||||
|
`ifdef SCR1_IPIC_EN
|
||||||
|
.soc2csr_irq_ext_i (ipic2csr_irq ),
|
||||||
|
`else // SCR1_IPIC_EN
|
||||||
|
.soc2csr_irq_ext_i (soc2pipe_irq_ext_i ),
|
||||||
|
`endif // SCR1_IPIC_EN
|
||||||
|
.soc2csr_irq_soft_i (soc2pipe_irq_soft_i ),
|
||||||
|
.soc2csr_irq_mtimer_i (soc2pipe_irq_mtimer_i ),
|
||||||
|
|
||||||
|
// Memory-mapped external timer
|
||||||
|
.soc2csr_mtimer_val_i (soc2pipe_mtimer_val_i ),
|
||||||
|
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
// CSR <-> HDU interface
|
||||||
|
.csr2hdu_req_o (csr2hdu_req ),
|
||||||
|
.csr2hdu_cmd_o (csr2hdu_cmd ),
|
||||||
|
.csr2hdu_addr_o (csr2hdu_addr ),
|
||||||
|
.csr2hdu_wdata_o (csr2hdu_wdata ),
|
||||||
|
.hdu2csr_rdata_i (hdu2csr_rdata ),
|
||||||
|
.hdu2csr_resp_i (hdu2csr_resp ),
|
||||||
|
.hdu2csr_no_commit_i (exu_no_commit ),
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
|
||||||
|
`ifdef SCR1_TDU_EN
|
||||||
|
// CSR <-> TDU interface
|
||||||
|
.csr2tdu_req_o (csr2tdu_req ),
|
||||||
|
.csr2tdu_cmd_o (csr2tdu_cmd ),
|
||||||
|
.csr2tdu_addr_o (csr2tdu_addr ),
|
||||||
|
.csr2tdu_wdata_o (csr2tdu_wdata ),
|
||||||
|
.tdu2csr_rdata_i (tdu2csr_rdata ),
|
||||||
|
.tdu2csr_resp_i (tdu2csr_resp ),
|
||||||
|
`endif // SCR1_TDU_EN
|
||||||
|
.soc2csr_fuse_mhartid_i (soc2pipe_fuse_mhartid_i )
|
||||||
|
);
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Integrated programmable interrupt controller
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
`ifdef SCR1_IPIC_EN
|
||||||
|
scr1_ipic i_pipe_ipic (
|
||||||
|
.rst_n (pipe_rst_n ),
|
||||||
|
`ifdef SCR1_CLKCTRL_EN
|
||||||
|
.clk (clkctl2pipe_clk_alw_on_i),
|
||||||
|
`else // SCR1_CLKCTRL_EN
|
||||||
|
.clk (clk ),
|
||||||
|
`endif // SCR1_CLKCTRL_EN
|
||||||
|
.soc2ipic_irq_lines_i (soc2pipe_irq_lines_i ),
|
||||||
|
.csr2ipic_r_req_i (csr2ipic_r_req ),
|
||||||
|
.csr2ipic_w_req_i (csr2ipic_w_req ),
|
||||||
|
.csr2ipic_addr_i (csr2ipic_addr ),
|
||||||
|
.csr2ipic_wdata_i (csr2ipic_wdata ),
|
||||||
|
.ipic2csr_rdata_o (ipic2csr_rdata ),
|
||||||
|
.ipic2csr_irq_m_req_o (ipic2csr_irq )
|
||||||
|
);
|
||||||
|
`endif // SCR1_IPIC_EN
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Breakpoint module
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
`ifdef SCR1_TDU_EN
|
||||||
|
scr1_pipe_tdu i_pipe_tdu (
|
||||||
|
// Common signals
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
.rst_n (dbg_rst_n ),
|
||||||
|
`else
|
||||||
|
.rst_n (pipe_rst_n ),
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
.clk (clk ),
|
||||||
|
.clk_en (1'b1 ),
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
.tdu_dsbl_i (hwbrk_dsbl ),
|
||||||
|
`else // SCR1_DBG_EN
|
||||||
|
.tdu_dsbl_i (1'b0 ),
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
|
||||||
|
// TDU <-> CSR interface
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
.csr2tdu_req_i (csr2tdu_req_qlfy ),
|
||||||
|
.csr2tdu_cmd_i (csr2tdu_cmd ),
|
||||||
|
.csr2tdu_addr_i (csr2tdu_addr ),
|
||||||
|
.csr2tdu_wdata_i (csr2tdu_wdata ),
|
||||||
|
`else // SCR1_DBG_EN
|
||||||
|
.csr2tdu_req_i (csr2tdu_req ),
|
||||||
|
.csr2tdu_cmd_i (csr2tdu_cmd ),
|
||||||
|
.csr2tdu_addr_i (csr2tdu_addr ),
|
||||||
|
.csr2tdu_wdata_i (csr2tdu_wdata ),
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
.tdu2csr_rdata_o (tdu2csr_rdata ),
|
||||||
|
.tdu2csr_resp_o (tdu2csr_resp ),
|
||||||
|
|
||||||
|
// TDU <-> EXU interface
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
.exu2tdu_imon_i (exu2tdu_i_mon_qlfy ),
|
||||||
|
`else // SCR1_DBG_EN
|
||||||
|
.exu2tdu_imon_i (exu2tdu_i_mon ),
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
.tdu2exu_ibrkpt_match_o (tdu2exu_i_match ),
|
||||||
|
.tdu2exu_ibrkpt_exc_req_o (tdu2exu_i_x_req ),
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
.exu2tdu_bp_retire_i (exu2tdu_bp_retire_qlfy),
|
||||||
|
`else // SCR1_DBG_EN
|
||||||
|
.exu2tdu_bp_retire_i (exu2tdu_bp_retire ),
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
|
||||||
|
// TDU <-> LSU interface
|
||||||
|
.tdu2lsu_ibrkpt_exc_req_o (tdu2lsu_i_x_req ),
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
.lsu2tdu_dmon_i (lsu2tdu_d_mon_qlfy ),
|
||||||
|
`else // SCR1_DBG_EN
|
||||||
|
.lsu2tdu_dmon_i (lsu2tdu_d_mon ),
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
.tdu2lsu_dbrkpt_match_o (tdu2lsu_d_match ),
|
||||||
|
.tdu2lsu_dbrkpt_exc_req_o (tdu2lsu_d_x_req ),
|
||||||
|
// EPU I/F
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
.tdu2hdu_dmode_req_o (tdu2hdu_dmode_req )
|
||||||
|
`else // SCR1_DBG_EN
|
||||||
|
.tdu2hdu_dmode_req_o ( )
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
);
|
||||||
|
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
assign hwbrk_dsbl = (~dbg_en) | hdu_hwbrk_dsbl;
|
||||||
|
//
|
||||||
|
assign csr2tdu_req_qlfy = dbg_en & csr2tdu_req & pipe2hdu_rdc_qlfy_i;
|
||||||
|
//
|
||||||
|
assign exu2tdu_i_mon_qlfy.vd = exu2tdu_i_mon.vd & pipe2hdu_rdc_qlfy_i;
|
||||||
|
assign exu2tdu_i_mon_qlfy.req = exu2tdu_i_mon.req;
|
||||||
|
assign exu2tdu_i_mon_qlfy.addr = exu2tdu_i_mon.addr;
|
||||||
|
assign lsu2tdu_d_mon_qlfy.vd = lsu2tdu_d_mon.vd & pipe2hdu_rdc_qlfy_i;
|
||||||
|
assign lsu2tdu_d_mon_qlfy.load = lsu2tdu_d_mon.load;
|
||||||
|
assign lsu2tdu_d_mon_qlfy.store = lsu2tdu_d_mon.store;
|
||||||
|
assign lsu2tdu_d_mon_qlfy.addr = lsu2tdu_d_mon.addr;
|
||||||
|
assign exu2tdu_bp_retire_qlfy = exu2tdu_bp_retire & {$bits(exu2tdu_bp_retire){pipe2hdu_rdc_qlfy_i}};
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
|
||||||
|
`endif // SCR1_TDU_EN
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// HART Debug Unit (HDU)
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
scr1_pipe_hdu i_pipe_hdu (
|
||||||
|
// Common signals
|
||||||
|
.rst_n (dbg_rst_n ),
|
||||||
|
.clk_en (dm2pipe_active_i ),
|
||||||
|
`ifdef SCR1_CLKCTRL_EN
|
||||||
|
.clk_pipe_en (clkctl2pipe_clk_en_i ),
|
||||||
|
.clk (clkctl2pipe_clk_dbgc_i),
|
||||||
|
`else
|
||||||
|
.clk (clk ),
|
||||||
|
`endif // SCR1_CLKCTRL_EN
|
||||||
|
|
||||||
|
// Control/status registers i/f
|
||||||
|
.csr2hdu_req_i (csr2hdu_req_qlfy ),
|
||||||
|
.csr2hdu_cmd_i (csr2hdu_cmd ),
|
||||||
|
.csr2hdu_addr_i (csr2hdu_addr ),
|
||||||
|
.csr2hdu_wdata_i (csr2hdu_wdata ),
|
||||||
|
.hdu2csr_resp_o (hdu2csr_resp ),
|
||||||
|
.hdu2csr_rdata_o (hdu2csr_rdata ),
|
||||||
|
|
||||||
|
// HART Run Control i/f
|
||||||
|
.pipe2hdu_rdc_qlfy_i (pipe2hdu_rdc_qlfy_i ),
|
||||||
|
.dm2hdu_cmd_req_i (dm2pipe_cmd_req_i ),
|
||||||
|
.dm2hdu_cmd_i (dm2pipe_cmd_i ),
|
||||||
|
.hdu2dm_cmd_resp_o (pipe2dm_cmd_resp_o ),
|
||||||
|
.hdu2dm_cmd_rcode_o (pipe2dm_cmd_rcode_o ),
|
||||||
|
.hdu2dm_hart_event_o (pipe2dm_hart_event_o ),
|
||||||
|
.hdu2dm_hart_status_o (pipe2dm_hart_status_o ),
|
||||||
|
|
||||||
|
// Program Buffer - HART instruction execution i/f
|
||||||
|
.hdu2dm_pbuf_addr_o (pipe2dm_pbuf_addr_o ),
|
||||||
|
.dm2hdu_pbuf_instr_i (dm2pipe_pbuf_instr_i ),
|
||||||
|
|
||||||
|
// HART Abstract Data regs i/f
|
||||||
|
.hdu2dm_dreg_req_o (pipe2dm_dreg_req_o ),
|
||||||
|
.hdu2dm_dreg_wr_o (pipe2dm_dreg_wr_o ),
|
||||||
|
.hdu2dm_dreg_wdata_o (pipe2dm_dreg_wdata_o ),
|
||||||
|
.dm2hdu_dreg_resp_i (dm2pipe_dreg_resp_i ),
|
||||||
|
.dm2hdu_dreg_fail_i (dm2pipe_dreg_fail_i ),
|
||||||
|
.dm2hdu_dreg_rdata_i (dm2pipe_dreg_rdata_i ),
|
||||||
|
//
|
||||||
|
`ifdef SCR1_TDU_EN
|
||||||
|
// HDU <-> TDU interface
|
||||||
|
.hdu2tdu_hwbrk_dsbl_o (hdu_hwbrk_dsbl ),
|
||||||
|
.tdu2hdu_dmode_req_i (tdu2hdu_dmode_req ),
|
||||||
|
.exu2hdu_ibrkpt_hw_i (brkpt_hw ),
|
||||||
|
`endif // SCR1_TDU_EN
|
||||||
|
|
||||||
|
// HART Run Status
|
||||||
|
.pipe2hdu_exu_busy_i (exu_busy_qlfy ),
|
||||||
|
.pipe2hdu_instret_i (instret_qlfy ),
|
||||||
|
.pipe2hdu_init_pc_i (exu_init_pc_qlfy ),
|
||||||
|
|
||||||
|
// HART Halt Status
|
||||||
|
.pipe2hdu_exu_exc_req_i (exu_exc_req_qlfy ),
|
||||||
|
.pipe2hdu_brkpt_i (brkpt_qlfy ),
|
||||||
|
|
||||||
|
// HART Run Control
|
||||||
|
.hdu2exu_pbuf_fetch_o (fetch_pbuf ),
|
||||||
|
.hdu2exu_no_commit_o (exu_no_commit ),
|
||||||
|
.hdu2exu_irq_dsbl_o (exu_irq_dsbl ),
|
||||||
|
.hdu2exu_pc_advmt_dsbl_o (exu_pc_advmt_dsbl ),
|
||||||
|
.hdu2exu_dmode_sstep_en_o (exu_dmode_sstep_en ),
|
||||||
|
|
||||||
|
// HART state
|
||||||
|
.hdu2exu_dbg_halted_o (dbg_halted ),
|
||||||
|
.hdu2exu_dbg_run2halt_o (dbg_run2halt ),
|
||||||
|
.hdu2exu_dbg_halt2run_o (dbg_halt2run ),
|
||||||
|
.hdu2exu_dbg_run_start_o (dbg_run_start ),
|
||||||
|
|
||||||
|
// PC interface
|
||||||
|
.pipe2hdu_pc_curr_i (curr_pc ),
|
||||||
|
.hdu2exu_dbg_new_pc_o (dbg_new_pc ),
|
||||||
|
|
||||||
|
// Prgram Buffer Instruction interface
|
||||||
|
.ifu2hdu_pbuf_instr_rdy_i (ifu2hdu_pbuf_rdy_qlfy ),
|
||||||
|
.hdu2ifu_pbuf_instr_vd_o (hdu2ifu_pbuf_vd ),
|
||||||
|
.hdu2ifu_pbuf_instr_err_o (hdu2ifu_pbuf_err ),
|
||||||
|
.hdu2ifu_pbuf_instr_o (hdu2ifu_pbuf_instr )
|
||||||
|
);
|
||||||
|
|
||||||
|
assign csr2hdu_req_qlfy = csr2hdu_req & dbg_en & pipe2hdu_rdc_qlfy_i;
|
||||||
|
//
|
||||||
|
assign exu_busy_qlfy = exu_busy & {$bits(exu_busy){pipe2hdu_rdc_qlfy_i}};
|
||||||
|
assign instret_qlfy = instret & {$bits(instret){pipe2hdu_rdc_qlfy_i}};
|
||||||
|
assign exu_init_pc_qlfy = exu_init_pc & {$bits(exu_init_pc){pipe2hdu_rdc_qlfy_i}};
|
||||||
|
assign exu_exc_req_qlfy = exu_exc_req & {$bits(exu_exc_req){pipe2hdu_rdc_qlfy_i}};
|
||||||
|
assign brkpt_qlfy = brkpt & {$bits(brkpt){pipe2hdu_rdc_qlfy_i}};
|
||||||
|
assign ifu2hdu_pbuf_rdy_qlfy = ifu2hdu_pbuf_rdy & {$bits(ifu2hdu_pbuf_rdy){pipe2hdu_rdc_qlfy_i}};
|
||||||
|
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
|
||||||
|
`ifdef SCR1_TRGT_SIMULATION
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Tracelog
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
scr1_tracelog i_tracelog (
|
||||||
|
.rst_n (pipe_rst_n ),
|
||||||
|
.clk (clk )
|
||||||
|
`ifdef SCR1_TRACE_LOG_EN
|
||||||
|
,
|
||||||
|
.soc2pipe_fuse_mhartid_i (soc2pipe_fuse_mhartid_i ),
|
||||||
|
|
||||||
|
// MPRF
|
||||||
|
.mprf2trace_int_i (i_pipe_mprf.mprf_int ),
|
||||||
|
.mprf2trace_wr_en_i (i_pipe_mprf.exu2mprf_w_req_i ),
|
||||||
|
.mprf2trace_wr_addr_i (i_pipe_mprf.exu2mprf_rd_addr_i ),
|
||||||
|
.mprf2trace_wr_data_i (i_pipe_mprf.exu2mprf_rd_data_i ),
|
||||||
|
|
||||||
|
// EXU
|
||||||
|
.exu2trace_update_pc_en_i (i_pipe_exu.update_pc_en ),
|
||||||
|
.exu2trace_update_pc_i (i_pipe_exu.update_pc ),
|
||||||
|
|
||||||
|
// IFU
|
||||||
|
.ifu2trace_instr_i (i_pipe_ifu.ifu2idu_instr_o ),
|
||||||
|
|
||||||
|
// CSR
|
||||||
|
.csr2trace_mstatus_mie_i (i_pipe_csr.csr_mstatus_mie_ff ),
|
||||||
|
.csr2trace_mstatus_mpie_i (i_pipe_csr.csr_mstatus_mpie_ff ),
|
||||||
|
.csr2trace_mtvec_base_i (i_pipe_csr.csr_mtvec_base ),
|
||||||
|
.csr2trace_mtvec_mode_i (i_pipe_csr.csr_mtvec_mode ),
|
||||||
|
.csr2trace_mie_meie_i (i_pipe_csr.csr_mie_meie_ff ),
|
||||||
|
.csr2trace_mie_mtie_i (i_pipe_csr.csr_mie_mtie_ff ),
|
||||||
|
.csr2trace_mie_msie_i (i_pipe_csr.csr_mie_msie_ff ),
|
||||||
|
.csr2trace_mip_meip_i (i_pipe_csr.csr_mip_meip ),
|
||||||
|
.csr2trace_mip_mtip_i (i_pipe_csr.csr_mip_mtip ),
|
||||||
|
.csr2trace_mip_msip_i (i_pipe_csr.csr_mip_msip ),
|
||||||
|
.csr2trace_mepc_i (i_pipe_csr.csr_mepc_ff ),
|
||||||
|
.csr2trace_mcause_irq_i (i_pipe_csr.csr_mcause_i_ff ),
|
||||||
|
.csr2trace_mcause_ec_i (i_pipe_csr.csr_mcause_ec_ff ),
|
||||||
|
.csr2trace_mtval_i (i_pipe_csr.csr_mtval_ff ),
|
||||||
|
|
||||||
|
// Events
|
||||||
|
.csr2trace_e_exc_i (i_pipe_csr.e_exc ),
|
||||||
|
.csr2trace_e_irq_i (i_pipe_csr.e_irq ),
|
||||||
|
.pipe2trace_e_wake_i (pipe2clkctl_wake_req_o )
|
||||||
|
`endif // SCR1_TRACE_LOG_EN
|
||||||
|
);
|
||||||
|
|
||||||
|
`endif // SCR1_TRGT_SIMULATION
|
||||||
|
|
||||||
|
endmodule : scr1_pipe_top
|
||||||
453
src_ref/core/pipeline/scr1_tracelog.sv
Normal file
453
src_ref/core/pipeline/scr1_tracelog.sv
Normal file
@@ -0,0 +1,453 @@
|
|||||||
|
/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
|
||||||
|
/// @file <scr1_tracelog.sv>
|
||||||
|
/// @brief Core tracelog module
|
||||||
|
///
|
||||||
|
|
||||||
|
`include "scr1_arch_description.svh"
|
||||||
|
`include "scr1_arch_types.svh"
|
||||||
|
`include "scr1_csr.svh"
|
||||||
|
|
||||||
|
`ifdef SCR1_TRGT_SIMULATION
|
||||||
|
|
||||||
|
module scr1_tracelog (
|
||||||
|
input logic rst_n, // Tracelog reset
|
||||||
|
input logic clk // Tracelog clock
|
||||||
|
`ifdef SCR1_TRACE_LOG_EN
|
||||||
|
,
|
||||||
|
input logic [`SCR1_XLEN-1:0] soc2pipe_fuse_mhartid_i, // Fuse MHARTID
|
||||||
|
|
||||||
|
// MPRF
|
||||||
|
`ifdef SCR1_MPRF_RAM
|
||||||
|
input logic [`SCR1_XLEN-1:0] mprf2trace_int_i [1:`SCR1_MPRF_SIZE-1], // MPRF registers content
|
||||||
|
`else // SCR1_MPRF_RAM
|
||||||
|
input type_scr1_mprf_v [1:`SCR1_MPRF_SIZE-1] mprf2trace_int_i, // MPRF registers content
|
||||||
|
`endif // SCR1_MPRF_RAM
|
||||||
|
input logic mprf2trace_wr_en_i, // MPRF write enable
|
||||||
|
input logic [`SCR1_MPRF_AWIDTH-1:0] mprf2trace_wr_addr_i, // MPRF write address
|
||||||
|
input logic [`SCR1_XLEN-1:0] mprf2trace_wr_data_i, // MPRF write data
|
||||||
|
|
||||||
|
// EXU
|
||||||
|
input logic exu2trace_update_pc_en_i, // PC updated flag
|
||||||
|
input logic [`SCR1_XLEN-1:0] exu2trace_update_pc_i, // Next PC value
|
||||||
|
|
||||||
|
// IFU
|
||||||
|
input logic [`SCR1_IMEM_DWIDTH-1:0] ifu2trace_instr_i, // Current instruction from IFU stage
|
||||||
|
|
||||||
|
// CSR
|
||||||
|
input logic csr2trace_mstatus_mie_i, // CSR MSTATUS.mie bit
|
||||||
|
input logic csr2trace_mstatus_mpie_i, // CSR MSTATUS.mpie bit
|
||||||
|
input logic [`SCR1_XLEN-1:6] csr2trace_mtvec_base_i, // CSR MTVEC.
|
||||||
|
input logic csr2trace_mtvec_mode_i, // CSR MTVEC.
|
||||||
|
input logic csr2trace_mie_meie_i, // CSR MIE.meie bit
|
||||||
|
input logic csr2trace_mie_mtie_i, // CSR MIE.mtie bit
|
||||||
|
input logic csr2trace_mie_msie_i, // CSR MIE.msie bit
|
||||||
|
input logic csr2trace_mip_meip_i, // CSR MIP.meip bit
|
||||||
|
input logic csr2trace_mip_mtip_i, // CSR MIP.mtip bit
|
||||||
|
input logic csr2trace_mip_msip_i, // CSR MIP.msip bit
|
||||||
|
`ifdef SCR1_RVC_EXT
|
||||||
|
input logic [`SCR1_XLEN-1:1] csr2trace_mepc_i, // CSR MEPC register
|
||||||
|
`else // SCR1_RVC_EXT
|
||||||
|
input logic [`SCR1_XLEN-1:2] csr2trace_mepc_i, // CSR MEPC register
|
||||||
|
`endif // SCR1_RVC_EXT
|
||||||
|
input logic csr2trace_mcause_irq_i, // CSR MCAUSE.interrupt bit
|
||||||
|
input type_scr1_exc_code_e csr2trace_mcause_ec_i, // CSR MCAUSE.exception_code bit
|
||||||
|
input logic [`SCR1_XLEN-1:0] csr2trace_mtval_i, // CSR MTVAL register
|
||||||
|
|
||||||
|
// Events
|
||||||
|
input logic csr2trace_e_exc_i, // exception event
|
||||||
|
input logic csr2trace_e_irq_i, // interrupt event
|
||||||
|
input logic pipe2trace_e_wake_i // pipe wakeup event
|
||||||
|
`endif // SCR1_TRACE_LOG_EN
|
||||||
|
);
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Local types declaration
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
`ifdef SCR1_TRACE_LOG_EN
|
||||||
|
typedef struct {
|
||||||
|
logic [`SCR1_XLEN-1:0] INT_00_ZERO ;
|
||||||
|
logic [`SCR1_XLEN-1:0] INT_01_RA ;
|
||||||
|
logic [`SCR1_XLEN-1:0] INT_02_SP ;
|
||||||
|
logic [`SCR1_XLEN-1:0] INT_03_GP ;
|
||||||
|
logic [`SCR1_XLEN-1:0] INT_04_TP ;
|
||||||
|
logic [`SCR1_XLEN-1:0] INT_05_T0 ;
|
||||||
|
logic [`SCR1_XLEN-1:0] INT_06_T1 ;
|
||||||
|
logic [`SCR1_XLEN-1:0] INT_07_T2 ;
|
||||||
|
logic [`SCR1_XLEN-1:0] INT_08_S0 ;
|
||||||
|
logic [`SCR1_XLEN-1:0] INT_09_S1 ;
|
||||||
|
logic [`SCR1_XLEN-1:0] INT_10_A0 ;
|
||||||
|
logic [`SCR1_XLEN-1:0] INT_11_A1 ;
|
||||||
|
logic [`SCR1_XLEN-1:0] INT_12_A2 ;
|
||||||
|
logic [`SCR1_XLEN-1:0] INT_13_A3 ;
|
||||||
|
logic [`SCR1_XLEN-1:0] INT_14_A4 ;
|
||||||
|
logic [`SCR1_XLEN-1:0] INT_15_A5 ;
|
||||||
|
`ifndef SCR1_RVE_EXT
|
||||||
|
logic [`SCR1_XLEN-1:0] INT_16_A6 ;
|
||||||
|
logic [`SCR1_XLEN-1:0] INT_17_A7 ;
|
||||||
|
logic [`SCR1_XLEN-1:0] INT_18_S2 ;
|
||||||
|
logic [`SCR1_XLEN-1:0] INT_19_S3 ;
|
||||||
|
logic [`SCR1_XLEN-1:0] INT_20_S4 ;
|
||||||
|
logic [`SCR1_XLEN-1:0] INT_21_S5 ;
|
||||||
|
logic [`SCR1_XLEN-1:0] INT_22_S6 ;
|
||||||
|
logic [`SCR1_XLEN-1:0] INT_23_S7 ;
|
||||||
|
logic [`SCR1_XLEN-1:0] INT_24_S8 ;
|
||||||
|
logic [`SCR1_XLEN-1:0] INT_25_S9 ;
|
||||||
|
logic [`SCR1_XLEN-1:0] INT_26_S10 ;
|
||||||
|
logic [`SCR1_XLEN-1:0] INT_27_S11 ;
|
||||||
|
logic [`SCR1_XLEN-1:0] INT_28_T3 ;
|
||||||
|
logic [`SCR1_XLEN-1:0] INT_29_T4 ;
|
||||||
|
logic [`SCR1_XLEN-1:0] INT_30_T5 ;
|
||||||
|
logic [`SCR1_XLEN-1:0] INT_31_T6 ;
|
||||||
|
`endif // SCR1_RVE_EXT
|
||||||
|
} type_scr1_ireg_name_s;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic [`SCR1_XLEN-1:0] mstatus;
|
||||||
|
logic [`SCR1_XLEN-1:0] mtvec;
|
||||||
|
logic [`SCR1_XLEN-1:0] mie;
|
||||||
|
logic [`SCR1_XLEN-1:0] mip;
|
||||||
|
logic [`SCR1_XLEN-1:0] mepc;
|
||||||
|
logic [`SCR1_XLEN-1:0] mcause;
|
||||||
|
logic [`SCR1_XLEN-1:0] mtval;
|
||||||
|
} type_scr1_csr_trace_s;
|
||||||
|
`endif // SCR1_TRACE_LOG_EN
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Local Signal Declaration
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
`ifdef SCR1_TRACE_LOG_EN
|
||||||
|
|
||||||
|
type_scr1_ireg_name_s mprf_int_alias;
|
||||||
|
|
||||||
|
|
||||||
|
time current_time;
|
||||||
|
|
||||||
|
// Tracelog control signals
|
||||||
|
logic trace_flag;
|
||||||
|
logic trace_update;
|
||||||
|
logic trace_update_r;
|
||||||
|
byte event_type;
|
||||||
|
|
||||||
|
logic [`SCR1_XLEN-1:0] trace_pc;
|
||||||
|
logic [`SCR1_XLEN-1:0] trace_npc;
|
||||||
|
logic [`SCR1_IMEM_DWIDTH-1:0] trace_instr;
|
||||||
|
|
||||||
|
type_scr1_csr_trace_s csr_trace1;
|
||||||
|
|
||||||
|
// File handlers
|
||||||
|
int unsigned trace_fhandler_core;
|
||||||
|
|
||||||
|
// MPRF signals
|
||||||
|
logic mprf_up;
|
||||||
|
logic [`SCR1_MPRF_AWIDTH-1:0] mprf_addr;
|
||||||
|
logic [`SCR1_XLEN-1:0] mprf_wdata;
|
||||||
|
|
||||||
|
string hart;
|
||||||
|
string test_name;
|
||||||
|
|
||||||
|
`endif // SCR1_TRACE_LOG_EN
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Local tasks
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
`ifdef SCR1_TRACE_LOG_EN
|
||||||
|
|
||||||
|
task trace_write_common;
|
||||||
|
$fwrite(trace_fhandler_core, "%16d ", current_time);
|
||||||
|
// $fwrite(trace_fhandler_core, " 0 ");
|
||||||
|
$fwrite(trace_fhandler_core, " %s ", event_type);
|
||||||
|
$fwrite(trace_fhandler_core, " %8x ", trace_pc);
|
||||||
|
$fwrite(trace_fhandler_core, " %8x ", trace_instr);
|
||||||
|
$fwrite(trace_fhandler_core, " %8x ", trace_npc);
|
||||||
|
endtask // trace_write_common
|
||||||
|
|
||||||
|
task trace_write_int_walias;
|
||||||
|
case (mprf_addr)
|
||||||
|
0 : $fwrite(trace_fhandler_core, " x00_zero ");
|
||||||
|
1 : $fwrite(trace_fhandler_core, " x01_ra ");
|
||||||
|
2 : $fwrite(trace_fhandler_core, " x02_sp ");
|
||||||
|
3 : $fwrite(trace_fhandler_core, " x03_gp ");
|
||||||
|
4 : $fwrite(trace_fhandler_core, " x04_tp ");
|
||||||
|
5 : $fwrite(trace_fhandler_core, " x05_t0 ");
|
||||||
|
6 : $fwrite(trace_fhandler_core, " x06_t1 ");
|
||||||
|
7 : $fwrite(trace_fhandler_core, " x07_t2 ");
|
||||||
|
8 : $fwrite(trace_fhandler_core, " x08_s0 ");
|
||||||
|
9 : $fwrite(trace_fhandler_core, " x09_s1 ");
|
||||||
|
10 : $fwrite(trace_fhandler_core, " x10_a0 ");
|
||||||
|
11 : $fwrite(trace_fhandler_core, " x11_a1 ");
|
||||||
|
12 : $fwrite(trace_fhandler_core, " x12_a2 ");
|
||||||
|
13 : $fwrite(trace_fhandler_core, " x13_a3 ");
|
||||||
|
14 : $fwrite(trace_fhandler_core, " x14_a4 ");
|
||||||
|
15 : $fwrite(trace_fhandler_core, " x15_a5 ");
|
||||||
|
`ifndef SCR1_RVE_EXT
|
||||||
|
16 : $fwrite(trace_fhandler_core, " x16_a6 ");
|
||||||
|
17 : $fwrite(trace_fhandler_core, " x17_a7 ");
|
||||||
|
18 : $fwrite(trace_fhandler_core, " x18_s2 ");
|
||||||
|
19 : $fwrite(trace_fhandler_core, " x19_s3 ");
|
||||||
|
20 : $fwrite(trace_fhandler_core, " x20_s4 ");
|
||||||
|
21 : $fwrite(trace_fhandler_core, " x21_s5 ");
|
||||||
|
22 : $fwrite(trace_fhandler_core, " x22_s6 ");
|
||||||
|
23 : $fwrite(trace_fhandler_core, " x23_s7 ");
|
||||||
|
24 : $fwrite(trace_fhandler_core, " x24_s8 ");
|
||||||
|
25 : $fwrite(trace_fhandler_core, " x25_s9 ");
|
||||||
|
26 : $fwrite(trace_fhandler_core, " x26_s10 ");
|
||||||
|
27 : $fwrite(trace_fhandler_core, " x27_s11 ");
|
||||||
|
28 : $fwrite(trace_fhandler_core, " x28_t3 ");
|
||||||
|
29 : $fwrite(trace_fhandler_core, " x29_t4 ");
|
||||||
|
30 : $fwrite(trace_fhandler_core, " x30_t5 ");
|
||||||
|
31 : $fwrite(trace_fhandler_core, " x31_t6 ");
|
||||||
|
`endif // SCR1_RVE_EXT
|
||||||
|
default: begin
|
||||||
|
$fwrite(trace_fhandler_core, " xxx ");
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
endtask
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// MPRF Registers assignment
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
assign mprf_int_alias.INT_00_ZERO = '0;
|
||||||
|
assign mprf_int_alias.INT_01_RA = mprf2trace_int_i[1];
|
||||||
|
assign mprf_int_alias.INT_02_SP = mprf2trace_int_i[2];
|
||||||
|
assign mprf_int_alias.INT_03_GP = mprf2trace_int_i[3];
|
||||||
|
assign mprf_int_alias.INT_04_TP = mprf2trace_int_i[4];
|
||||||
|
assign mprf_int_alias.INT_05_T0 = mprf2trace_int_i[5];
|
||||||
|
assign mprf_int_alias.INT_06_T1 = mprf2trace_int_i[6];
|
||||||
|
assign mprf_int_alias.INT_07_T2 = mprf2trace_int_i[7];
|
||||||
|
assign mprf_int_alias.INT_08_S0 = mprf2trace_int_i[8];
|
||||||
|
assign mprf_int_alias.INT_09_S1 = mprf2trace_int_i[9];
|
||||||
|
assign mprf_int_alias.INT_10_A0 = mprf2trace_int_i[10];
|
||||||
|
assign mprf_int_alias.INT_11_A1 = mprf2trace_int_i[11];
|
||||||
|
assign mprf_int_alias.INT_12_A2 = mprf2trace_int_i[12];
|
||||||
|
assign mprf_int_alias.INT_13_A3 = mprf2trace_int_i[13];
|
||||||
|
assign mprf_int_alias.INT_14_A4 = mprf2trace_int_i[14];
|
||||||
|
assign mprf_int_alias.INT_15_A5 = mprf2trace_int_i[15];
|
||||||
|
`ifndef SCR1_RVE_EXT
|
||||||
|
assign mprf_int_alias.INT_16_A6 = mprf2trace_int_i[16];
|
||||||
|
assign mprf_int_alias.INT_17_A7 = mprf2trace_int_i[17];
|
||||||
|
assign mprf_int_alias.INT_18_S2 = mprf2trace_int_i[18];
|
||||||
|
assign mprf_int_alias.INT_19_S3 = mprf2trace_int_i[19];
|
||||||
|
assign mprf_int_alias.INT_20_S4 = mprf2trace_int_i[20];
|
||||||
|
assign mprf_int_alias.INT_21_S5 = mprf2trace_int_i[21];
|
||||||
|
assign mprf_int_alias.INT_22_S6 = mprf2trace_int_i[22];
|
||||||
|
assign mprf_int_alias.INT_23_S7 = mprf2trace_int_i[23];
|
||||||
|
assign mprf_int_alias.INT_24_S8 = mprf2trace_int_i[24];
|
||||||
|
assign mprf_int_alias.INT_25_S9 = mprf2trace_int_i[25];
|
||||||
|
assign mprf_int_alias.INT_26_S10 = mprf2trace_int_i[26];
|
||||||
|
assign mprf_int_alias.INT_27_S11 = mprf2trace_int_i[27];
|
||||||
|
assign mprf_int_alias.INT_28_T3 = mprf2trace_int_i[28];
|
||||||
|
assign mprf_int_alias.INT_29_T4 = mprf2trace_int_i[29];
|
||||||
|
assign mprf_int_alias.INT_30_T5 = mprf2trace_int_i[30];
|
||||||
|
assign mprf_int_alias.INT_31_T6 = mprf2trace_int_i[31];
|
||||||
|
`endif // SCR1_RVE_EXT
|
||||||
|
`endif // SCR1_TRACE_LOG_EN
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Legacy time counter
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// The counter is left for compatibility with the current UVM environment
|
||||||
|
|
||||||
|
int time_cnt;
|
||||||
|
|
||||||
|
always_ff @(negedge rst_n, posedge clk) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
time_cnt <= 0;
|
||||||
|
end else begin
|
||||||
|
time_cnt <= time_cnt + 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Initial part pipeline tracelog
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
`ifdef SCR1_TRACE_LOG_EN
|
||||||
|
// Files opening and writing initial header
|
||||||
|
initial begin
|
||||||
|
$timeformat(-9, 0, " ns", 10);
|
||||||
|
#1 hart.hextoa(soc2pipe_fuse_mhartid_i);
|
||||||
|
|
||||||
|
trace_fhandler_core = $fopen({"tracelog_core_", hart, ".log"}, "w");
|
||||||
|
|
||||||
|
// Writing initial header
|
||||||
|
$fwrite(trace_fhandler_core, "# RTL_ID %h\n", SCR1_CSR_MIMPID);
|
||||||
|
$fwrite(trace_fhandler_core, "#\n");
|
||||||
|
// $fwrite(trace_fhandler_core, "# R - return from trap:\n");
|
||||||
|
// $fwrite(trace_fhandler_core, "# 1 - MRET\n");
|
||||||
|
// $fwrite(trace_fhandler_core, "# 0 - no return\n");
|
||||||
|
$fwrite(trace_fhandler_core, "# Events:\n");
|
||||||
|
$fwrite(trace_fhandler_core, "# N - no event\n");
|
||||||
|
$fwrite(trace_fhandler_core, "# E - exception\n");
|
||||||
|
$fwrite(trace_fhandler_core, "# I - interrupt\n");
|
||||||
|
$fwrite(trace_fhandler_core, "# W - wakeup\n");
|
||||||
|
end
|
||||||
|
|
||||||
|
// Core reset logging and header printing
|
||||||
|
always @(posedge rst_n) begin
|
||||||
|
$fwrite(trace_fhandler_core, "# =====================================================================================\n");
|
||||||
|
`ifndef VERILATOR
|
||||||
|
$fwrite(trace_fhandler_core, "# %16d ns : Core Reset\n", $time());
|
||||||
|
`else
|
||||||
|
$fwrite(trace_fhandler_core, "# : Core Reset\n");
|
||||||
|
`endif
|
||||||
|
$fwrite(trace_fhandler_core, "# =====================================================================================\n");
|
||||||
|
$fwrite(trace_fhandler_core, "# Test: %s\n", test_name);
|
||||||
|
$fwrite(trace_fhandler_core, "# Time ");
|
||||||
|
// $fwrite(trace_fhandler_core, " R ");
|
||||||
|
$fwrite(trace_fhandler_core, " Ev ");
|
||||||
|
$fwrite(trace_fhandler_core, " Curr_PC ");
|
||||||
|
$fwrite(trace_fhandler_core, " Instr ");
|
||||||
|
$fwrite(trace_fhandler_core, " Next_PC ");
|
||||||
|
$fwrite(trace_fhandler_core, " Reg ");
|
||||||
|
$fwrite(trace_fhandler_core, " Value ");
|
||||||
|
$fwrite(trace_fhandler_core, "\n");
|
||||||
|
$fwrite(trace_fhandler_core, "# =====================================================================================\n");
|
||||||
|
end
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Common trace part
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign trace_flag = 1'b1;
|
||||||
|
assign trace_update = (exu2trace_update_pc_en_i | mprf2trace_wr_en_i) & trace_flag;
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
current_time <= 0;
|
||||||
|
event_type <= "N";
|
||||||
|
|
||||||
|
trace_pc <= 'x;
|
||||||
|
trace_npc <= 'x;
|
||||||
|
trace_instr <= 'x;
|
||||||
|
|
||||||
|
trace_update_r <= 1'b0;
|
||||||
|
|
||||||
|
mprf_up <= '0;
|
||||||
|
mprf_addr <= '0;
|
||||||
|
mprf_wdata <= '0;
|
||||||
|
end else begin
|
||||||
|
trace_update_r <= trace_update;
|
||||||
|
if (trace_update) begin
|
||||||
|
`ifdef VERILATOR
|
||||||
|
current_time <= time_cnt;
|
||||||
|
`else
|
||||||
|
current_time <= $time();
|
||||||
|
`endif
|
||||||
|
trace_pc <= trace_npc;
|
||||||
|
trace_npc <= exu2trace_update_pc_i;
|
||||||
|
trace_instr <= ifu2trace_instr_i;
|
||||||
|
|
||||||
|
if (csr2trace_e_exc_i) begin
|
||||||
|
// Exception
|
||||||
|
event_type <= "E";
|
||||||
|
end
|
||||||
|
else if (csr2trace_e_irq_i) begin
|
||||||
|
// IRQ
|
||||||
|
event_type <= "I";
|
||||||
|
end
|
||||||
|
else if (pipe2trace_e_wake_i) begin
|
||||||
|
// Wake
|
||||||
|
event_type <= "W";
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
// No event
|
||||||
|
event_type <= "N";
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// Write log signals
|
||||||
|
mprf_up <= mprf2trace_wr_en_i;
|
||||||
|
mprf_addr <= mprf2trace_wr_en_i ? mprf2trace_wr_addr_i : 'x;
|
||||||
|
mprf_wdata <= mprf2trace_wr_en_i ? mprf2trace_wr_data_i : 'x;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Core MPRF logging
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
always_ff @(negedge rst_n, posedge clk) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
end else begin
|
||||||
|
if (trace_update_r) begin
|
||||||
|
|
||||||
|
trace_write_common();
|
||||||
|
|
||||||
|
case (event_type)
|
||||||
|
"W" : begin
|
||||||
|
// Wakeup
|
||||||
|
if (csr_trace1.mip & csr_trace1.mie) begin
|
||||||
|
$fwrite(trace_fhandler_core, " mip %08x\n", csr_trace1.mip );
|
||||||
|
trace_write_common();
|
||||||
|
$fwrite(trace_fhandler_core, " mie %08x", csr_trace1.mie );
|
||||||
|
end
|
||||||
|
end
|
||||||
|
"N" : begin
|
||||||
|
// Regular
|
||||||
|
if (mprf_up && mprf_addr != 0) begin
|
||||||
|
// $fwrite(trace_fhandler_core, " x%2d %08x", mprf_addr, mprf_wdata);
|
||||||
|
trace_write_int_walias();
|
||||||
|
$fwrite(trace_fhandler_core, " %08x", mprf_wdata);
|
||||||
|
end else begin
|
||||||
|
$fwrite(trace_fhandler_core, " --- --------");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
"R" : begin
|
||||||
|
// MRET
|
||||||
|
$fwrite(trace_fhandler_core, " mstatus %08x", csr_trace1.mstatus);
|
||||||
|
end
|
||||||
|
"E", "I": begin
|
||||||
|
// IRQ/Exception
|
||||||
|
$fwrite(trace_fhandler_core, " mstatus %08x\n", csr_trace1.mstatus);
|
||||||
|
trace_write_common();
|
||||||
|
$fwrite(trace_fhandler_core, " mepc %08x\n", csr_trace1.mepc);
|
||||||
|
trace_write_common();
|
||||||
|
$fwrite(trace_fhandler_core, " mcause %08x\n", csr_trace1.mcause);
|
||||||
|
trace_write_common();
|
||||||
|
$fwrite(trace_fhandler_core, " mtval %08x", csr_trace1.mtval);
|
||||||
|
end
|
||||||
|
default : begin
|
||||||
|
$fwrite(trace_fhandler_core, "\n");
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
$fwrite(trace_fhandler_core, "\n");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Core CSR logging
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
csr_trace1.mtvec = {csr2trace_mtvec_base_i, 4'd0, 2'(csr2trace_mtvec_mode_i)};
|
||||||
|
csr_trace1.mepc =
|
||||||
|
`ifdef SCR1_RVC_EXT
|
||||||
|
{csr2trace_mepc_i, 1'b0};
|
||||||
|
`else // SCR1_RVC_EXT
|
||||||
|
{csr2trace_mepc_i, 2'b00};
|
||||||
|
`endif // SCR1_RVC_EXT
|
||||||
|
csr_trace1.mcause = {csr2trace_mcause_irq_i, type_scr1_csr_mcause_ec_v'(csr2trace_mcause_ec_i)};
|
||||||
|
csr_trace1.mtval = csr2trace_mtval_i;
|
||||||
|
|
||||||
|
csr_trace1.mstatus = '0;
|
||||||
|
csr_trace1.mie = '0;
|
||||||
|
csr_trace1.mip = '0;
|
||||||
|
|
||||||
|
csr_trace1.mstatus[SCR1_CSR_MSTATUS_MIE_OFFSET] = csr2trace_mstatus_mie_i;
|
||||||
|
csr_trace1.mstatus[SCR1_CSR_MSTATUS_MPIE_OFFSET] = csr2trace_mstatus_mpie_i;
|
||||||
|
csr_trace1.mstatus[SCR1_CSR_MSTATUS_MPP_OFFSET+1:SCR1_CSR_MSTATUS_MPP_OFFSET] = SCR1_CSR_MSTATUS_MPP;
|
||||||
|
csr_trace1.mie[SCR1_CSR_MIE_MSIE_OFFSET] = csr2trace_mie_msie_i;
|
||||||
|
csr_trace1.mie[SCR1_CSR_MIE_MTIE_OFFSET] = csr2trace_mie_mtie_i;
|
||||||
|
csr_trace1.mie[SCR1_CSR_MIE_MEIE_OFFSET] = csr2trace_mie_meie_i;
|
||||||
|
csr_trace1.mip[SCR1_CSR_MIE_MSIE_OFFSET] = csr2trace_mip_msip_i;
|
||||||
|
csr_trace1.mip[SCR1_CSR_MIE_MTIE_OFFSET] = csr2trace_mip_mtip_i;
|
||||||
|
csr_trace1.mip[SCR1_CSR_MIE_MEIE_OFFSET] = csr2trace_mip_meip_i;
|
||||||
|
end
|
||||||
|
|
||||||
|
`endif // SCR1_TRACE_LOG_EN
|
||||||
|
|
||||||
|
endmodule : scr1_tracelog
|
||||||
|
|
||||||
|
`endif // SCR1_TRGT_SIMULATION
|
||||||
32
src_ref/core/primitives/scr1_cg.sv
Normal file
32
src_ref/core/primitives/scr1_cg.sv
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
|
||||||
|
/// @file <scr1_cg.sv>
|
||||||
|
/// @brief SCR1 clock gate primitive
|
||||||
|
///
|
||||||
|
|
||||||
|
`include "scr1_arch_description.svh"
|
||||||
|
|
||||||
|
`ifdef SCR1_CLKCTRL_EN
|
||||||
|
module scr1_cg (
|
||||||
|
input logic clk,
|
||||||
|
input logic clk_en,
|
||||||
|
input logic test_mode,
|
||||||
|
output logic clk_out
|
||||||
|
);
|
||||||
|
|
||||||
|
// The code below is a clock gate model for simulation.
|
||||||
|
// For synthesis, it should be replaced by implementation-specific
|
||||||
|
// clock gate code.
|
||||||
|
|
||||||
|
logic latch_en;
|
||||||
|
|
||||||
|
always_latch begin
|
||||||
|
if (~clk) begin
|
||||||
|
latch_en <= test_mode | clk_en;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign clk_out = latch_en & clk;
|
||||||
|
|
||||||
|
endmodule : scr1_cg
|
||||||
|
|
||||||
|
`endif // SCR1_CLKCTRL_EN
|
||||||
231
src_ref/core/primitives/scr1_reset_cells.sv
Normal file
231
src_ref/core/primitives/scr1_reset_cells.sv
Normal file
@@ -0,0 +1,231 @@
|
|||||||
|
/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
|
||||||
|
/// @file <scr1_sync_rstn.sv>
|
||||||
|
/// @brief Cells for reset handling
|
||||||
|
///
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// Reset Buffer Cell
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
module scr1_reset_buf_cell (
|
||||||
|
input logic rst_n,
|
||||||
|
input logic clk,
|
||||||
|
input logic test_mode,
|
||||||
|
input logic test_rst_n,
|
||||||
|
input logic reset_n_in,
|
||||||
|
output logic reset_n_out,
|
||||||
|
output logic reset_n_status
|
||||||
|
);
|
||||||
|
|
||||||
|
logic reset_n_ff;
|
||||||
|
logic reset_n_status_ff;
|
||||||
|
logic rst_n_mux;
|
||||||
|
|
||||||
|
assign rst_n_mux = (test_mode == 1'b1) ? test_rst_n : rst_n;
|
||||||
|
|
||||||
|
always_ff @(negedge rst_n_mux, posedge clk) begin
|
||||||
|
if (~rst_n_mux) begin
|
||||||
|
reset_n_ff <= 1'b0;
|
||||||
|
end else begin
|
||||||
|
reset_n_ff <= reset_n_in;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign reset_n_out = (test_mode == 1'b1) ? test_rst_n : reset_n_ff;
|
||||||
|
|
||||||
|
always_ff @(negedge rst_n_mux, posedge clk) begin
|
||||||
|
if (~rst_n_mux) begin
|
||||||
|
reset_n_status_ff <= 1'b0;
|
||||||
|
end else begin
|
||||||
|
reset_n_status_ff <= reset_n_in;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
assign reset_n_status = reset_n_status_ff;
|
||||||
|
|
||||||
|
endmodule : scr1_reset_buf_cell
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// Reset CDC Synchronization Cell
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
module scr1_reset_sync_cell #(
|
||||||
|
parameter int unsigned STAGES_AMOUNT = 2
|
||||||
|
) (
|
||||||
|
input logic rst_n,
|
||||||
|
input logic clk,
|
||||||
|
input logic test_rst_n,
|
||||||
|
input logic test_mode,
|
||||||
|
input logic rst_n_in,
|
||||||
|
output logic rst_n_out
|
||||||
|
);
|
||||||
|
|
||||||
|
logic [STAGES_AMOUNT-1:0] rst_n_dff;
|
||||||
|
logic local_rst_n_in;
|
||||||
|
|
||||||
|
assign local_rst_n_in = (test_mode == 1'b1) ? test_rst_n : rst_n;
|
||||||
|
|
||||||
|
generate
|
||||||
|
|
||||||
|
if (STAGES_AMOUNT == 1)
|
||||||
|
|
||||||
|
begin : gen_reset_sync_cell_single
|
||||||
|
always_ff @(negedge local_rst_n_in, posedge clk) begin
|
||||||
|
if (~local_rst_n_in) begin
|
||||||
|
rst_n_dff <= 1'b0;
|
||||||
|
end else begin
|
||||||
|
rst_n_dff <= rst_n_in;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end : gen_reset_sync_cell_single
|
||||||
|
|
||||||
|
else // STAGES_AMOUNT > 1
|
||||||
|
|
||||||
|
begin : gen_reset_sync_cell_multi
|
||||||
|
always_ff @(negedge local_rst_n_in, posedge clk)
|
||||||
|
begin
|
||||||
|
if (~local_rst_n_in) begin
|
||||||
|
rst_n_dff <= '0;
|
||||||
|
end else begin
|
||||||
|
rst_n_dff <= {rst_n_dff[STAGES_AMOUNT-2:0], rst_n_in};
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end : gen_reset_sync_cell_multi
|
||||||
|
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
assign rst_n_out = (test_mode == 1'b1) ? test_rst_n : rst_n_dff[STAGES_AMOUNT-1];
|
||||||
|
|
||||||
|
endmodule : scr1_reset_sync_cell
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// Data CDC/RDC Synchronization Cell
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
module scr1_data_sync_cell #(
|
||||||
|
parameter int unsigned STAGES_AMOUNT = 1
|
||||||
|
) (
|
||||||
|
input logic rst_n,
|
||||||
|
input logic clk,
|
||||||
|
input logic data_in,
|
||||||
|
output logic data_out
|
||||||
|
);
|
||||||
|
|
||||||
|
logic [STAGES_AMOUNT-1:0] data_dff;
|
||||||
|
|
||||||
|
generate
|
||||||
|
|
||||||
|
if (STAGES_AMOUNT == 1)
|
||||||
|
|
||||||
|
begin : gen_data_sync_cell_single
|
||||||
|
always_ff @(negedge rst_n, posedge clk)
|
||||||
|
begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
data_dff <= 1'b0;
|
||||||
|
end else begin
|
||||||
|
data_dff <= data_in;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end : gen_data_sync_cell_single
|
||||||
|
|
||||||
|
else // STAGES_AMOUNT > 1
|
||||||
|
|
||||||
|
begin : gen_data_sync_cell_multi
|
||||||
|
always_ff @(negedge rst_n, posedge clk)
|
||||||
|
begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
data_dff <= '0;
|
||||||
|
end else begin
|
||||||
|
data_dff <= {data_dff[STAGES_AMOUNT-2:0], data_in};
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end : gen_data_sync_cell_multi
|
||||||
|
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
assign data_out = data_dff[STAGES_AMOUNT-1];
|
||||||
|
|
||||||
|
endmodule : scr1_data_sync_cell
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// Reset / RDC Qualifyer Adapter Cell
|
||||||
|
// (Reset Generation Cell w/ RDC Qualifyer Adaptation circuitry)
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// Total stages amount =
|
||||||
|
// 1 Front Sync stage \
|
||||||
|
// + 1 (delay introduced by the reset output buffer register)
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
module scr1_reset_qlfy_adapter_cell_sync (
|
||||||
|
input logic rst_n,
|
||||||
|
input logic clk,
|
||||||
|
input logic test_rst_n,
|
||||||
|
input logic test_mode,
|
||||||
|
input logic reset_n_in_sync,
|
||||||
|
output logic reset_n_out_qlfy,
|
||||||
|
output logic reset_n_out,
|
||||||
|
output logic reset_n_status
|
||||||
|
);
|
||||||
|
|
||||||
|
logic rst_n_mux;
|
||||||
|
logic reset_n_front_ff;
|
||||||
|
|
||||||
|
// Front sync stage
|
||||||
|
assign rst_n_mux = (test_mode == 1'b1) ? test_rst_n : rst_n;
|
||||||
|
|
||||||
|
always_ff @(negedge rst_n_mux, posedge clk) begin
|
||||||
|
if (~rst_n_mux) begin
|
||||||
|
reset_n_front_ff <= 1'b0;
|
||||||
|
end else begin
|
||||||
|
reset_n_front_ff <= reset_n_in_sync;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// Sync reset output for all reset qualifier chains targeting this reset domain
|
||||||
|
// (for reset-domain-crossings with the given reset domain as a destination).
|
||||||
|
assign reset_n_out_qlfy = reset_n_front_ff;
|
||||||
|
|
||||||
|
// Reset output buffer
|
||||||
|
scr1_reset_buf_cell
|
||||||
|
i_reset_output_buf (
|
||||||
|
.rst_n (rst_n),
|
||||||
|
.clk (clk),
|
||||||
|
.test_mode (test_mode),
|
||||||
|
.test_rst_n (test_rst_n),
|
||||||
|
.reset_n_in (reset_n_front_ff),
|
||||||
|
.reset_n_out (reset_n_out),
|
||||||
|
.reset_n_status (reset_n_status)
|
||||||
|
);
|
||||||
|
|
||||||
|
endmodule : scr1_reset_qlfy_adapter_cell_sync
|
||||||
|
|
||||||
|
module scr1_reset_and2_cell (
|
||||||
|
input logic [1:0] rst_n_in,
|
||||||
|
input logic test_rst_n,
|
||||||
|
input logic test_mode,
|
||||||
|
output logic rst_n_out
|
||||||
|
);
|
||||||
|
|
||||||
|
assign rst_n_out = (test_mode == 1'b1) ? test_rst_n : (&rst_n_in);
|
||||||
|
|
||||||
|
endmodule : scr1_reset_and2_cell
|
||||||
|
|
||||||
|
|
||||||
|
module scr1_reset_and3_cell (
|
||||||
|
input logic [2:0] rst_n_in,
|
||||||
|
input logic test_rst_n,
|
||||||
|
input logic test_mode,
|
||||||
|
output logic rst_n_out
|
||||||
|
);
|
||||||
|
|
||||||
|
assign rst_n_out = (test_mode == 1'b1) ? test_rst_n : (&rst_n_in);
|
||||||
|
|
||||||
|
endmodule : scr1_reset_and3_cell
|
||||||
|
|
||||||
|
|
||||||
|
module scr1_reset_mux2_cell (
|
||||||
|
input logic [1:0] rst_n_in,
|
||||||
|
input logic select,
|
||||||
|
input logic test_rst_n,
|
||||||
|
input logic test_mode,
|
||||||
|
output logic rst_n_out
|
||||||
|
);
|
||||||
|
|
||||||
|
assign rst_n_out = (test_mode == 1'b1) ? test_rst_n : rst_n_in[select];
|
||||||
|
|
||||||
|
endmodule : scr1_reset_mux2_cell
|
||||||
55
src_ref/core/scr1_clk_ctrl.sv
Normal file
55
src_ref/core/scr1_clk_ctrl.sv
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
|
||||||
|
/// @file <scr1_clk_ctrl.sv>
|
||||||
|
/// @brief SCR1 clock control
|
||||||
|
///
|
||||||
|
|
||||||
|
`include "scr1_arch_description.svh"
|
||||||
|
|
||||||
|
`ifdef SCR1_CLKCTRL_EN
|
||||||
|
module scr1_clk_ctrl (
|
||||||
|
input logic clk, // Clock control module clock
|
||||||
|
input logic rst_n, // Clock control module reset
|
||||||
|
input logic test_mode, // DFT Test Mode
|
||||||
|
input logic test_rst_n, // DFT Test reset
|
||||||
|
|
||||||
|
input logic pipe2clkctl_sleep_req_i, // CLK disable request from pipe
|
||||||
|
input logic pipe2clkctl_wake_req_i, // CLK enable request from pipe
|
||||||
|
|
||||||
|
output logic clkctl2pipe_clk_alw_on_o, // Not gated pipe CLK
|
||||||
|
output logic clkctl2pipe_clk_o, // Gated pipe
|
||||||
|
output logic clkctl2pipe_clk_en_o, // CLK enabled flag
|
||||||
|
output logic clkctl2pipe_clk_dbgc_o // CLK for pipe debug subsystem
|
||||||
|
);
|
||||||
|
|
||||||
|
logic ctrl_rst_n;
|
||||||
|
|
||||||
|
assign clkctl2pipe_clk_alw_on_o = clk;
|
||||||
|
assign clkctl2pipe_clk_dbgc_o = clk;
|
||||||
|
assign ctrl_rst_n = (test_mode) ? test_rst_n : rst_n;
|
||||||
|
|
||||||
|
always_ff @(posedge clk, negedge ctrl_rst_n) begin
|
||||||
|
if (~ctrl_rst_n) begin
|
||||||
|
clkctl2pipe_clk_en_o <= 1'b1;
|
||||||
|
end else begin
|
||||||
|
if (clkctl2pipe_clk_en_o) begin
|
||||||
|
if (pipe2clkctl_sleep_req_i & ~pipe2clkctl_wake_req_i) begin
|
||||||
|
clkctl2pipe_clk_en_o <= 1'b0;
|
||||||
|
end
|
||||||
|
end else begin // ~clkctl2pipe_clk_en_o
|
||||||
|
if (pipe2clkctl_wake_req_i) begin
|
||||||
|
clkctl2pipe_clk_en_o <= 1'b1;
|
||||||
|
end
|
||||||
|
end // pipeline
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
scr1_cg i_scr1_cg_pipe (
|
||||||
|
.clk (clk ),
|
||||||
|
.clk_en (clkctl2pipe_clk_en_o),
|
||||||
|
.test_mode (test_mode ),
|
||||||
|
.clk_out (clkctl2pipe_clk_o )
|
||||||
|
);
|
||||||
|
|
||||||
|
endmodule : scr1_clk_ctrl
|
||||||
|
|
||||||
|
`endif // SCR1_CLKCTRL_EN
|
||||||
521
src_ref/core/scr1_core_top.sv
Normal file
521
src_ref/core/scr1_core_top.sv
Normal file
@@ -0,0 +1,521 @@
|
|||||||
|
/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
|
||||||
|
/// @file <scr1_core_top.sv>
|
||||||
|
/// @brief SCR1 core top
|
||||||
|
///
|
||||||
|
|
||||||
|
`include "scr1_arch_description.svh"
|
||||||
|
`include "scr1_arch_types.svh"
|
||||||
|
`include "scr1_memif.svh"
|
||||||
|
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
`include "scr1_tapc.svh"
|
||||||
|
`include "scr1_dm.svh"
|
||||||
|
`include "scr1_hdu.svh"
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
|
||||||
|
`ifdef SCR1_IPIC_EN
|
||||||
|
`include "scr1_ipic.svh"
|
||||||
|
`endif // SCR1_IPIC_EN
|
||||||
|
|
||||||
|
module scr1_core_top (
|
||||||
|
// Common
|
||||||
|
input logic pwrup_rst_n, // Power-Up reset
|
||||||
|
input logic rst_n, // Regular reset
|
||||||
|
input logic cpu_rst_n, // CPU reset
|
||||||
|
input logic test_mode, // DFT Test Mode
|
||||||
|
input logic test_rst_n, // DFT Test Reset
|
||||||
|
input logic clk, // Core clock
|
||||||
|
output logic core_rst_n_o, // Core reset
|
||||||
|
output logic core_rdc_qlfy_o, // Core RDC qualifier
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
output logic sys_rst_n_o, // System reset
|
||||||
|
output logic sys_rdc_qlfy_o, // System RDC qualifier
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
|
||||||
|
// Fuses
|
||||||
|
input logic [`SCR1_XLEN-1:0] core_fuse_mhartid_i, // Fuse MHARTID value
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
input logic [31:0] tapc_fuse_idcode_i, // Fuse IDCODE value
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
|
||||||
|
// IRQ
|
||||||
|
`ifdef SCR1_IPIC_EN
|
||||||
|
input logic [SCR1_IRQ_LINES_NUM-1:0] core_irq_lines_i, // External interrupt request lines
|
||||||
|
`else
|
||||||
|
input logic core_irq_ext_i, // External interrupt request
|
||||||
|
`endif // SCR1_IPIC_EN
|
||||||
|
input logic core_irq_soft_i, // Software generated interrupt request
|
||||||
|
input logic core_irq_mtimer_i, // Machine timer interrupt request
|
||||||
|
|
||||||
|
// Memory-mapped external timer
|
||||||
|
input logic [63:0] core_mtimer_val_i, // Machine timer value
|
||||||
|
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
// Debug Interface
|
||||||
|
input logic tapc_trst_n, // Test Reset (TRSTn)
|
||||||
|
input logic tapc_tck, // Test Clock (TCK)
|
||||||
|
input logic tapc_tms, // Test Mode Select (TMS)
|
||||||
|
input logic tapc_tdi, // Test Data Input (TDI)
|
||||||
|
output logic tapc_tdo, // Test Data Output (TDO)
|
||||||
|
output logic tapc_tdo_en, // TDO Enable, signal for TDO buffer control
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
|
||||||
|
// Instruction Memory Interface
|
||||||
|
input logic imem2core_req_ack_i, // IMEM request acknowledge
|
||||||
|
output logic core2imem_req_o, // IMEM request
|
||||||
|
output type_scr1_mem_cmd_e core2imem_cmd_o, // IMEM command
|
||||||
|
output logic [`SCR1_IMEM_AWIDTH-1:0] core2imem_addr_o, // IMEM address
|
||||||
|
input logic [`SCR1_IMEM_DWIDTH-1:0] imem2core_rdata_i, // IMEM read data
|
||||||
|
input type_scr1_mem_resp_e imem2core_resp_i, // IMEM response
|
||||||
|
|
||||||
|
// Data Memory Interface
|
||||||
|
input logic dmem2core_req_ack_i, // DMEM request acknowledge
|
||||||
|
output logic core2dmem_req_o, // DMEM request
|
||||||
|
output type_scr1_mem_cmd_e core2dmem_cmd_o, // DMEM command
|
||||||
|
output type_scr1_mem_width_e core2dmem_width_o, // DMEM data width
|
||||||
|
output logic [`SCR1_DMEM_AWIDTH-1:0] core2dmem_addr_o, // DMEM address
|
||||||
|
output logic [`SCR1_DMEM_DWIDTH-1:0] core2dmem_wdata_o, // DMEM write data
|
||||||
|
input logic [`SCR1_DMEM_DWIDTH-1:0] dmem2core_rdata_i, // DMEM read data
|
||||||
|
input type_scr1_mem_resp_e dmem2core_resp_i // DMEM response
|
||||||
|
);
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Local parameters
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
localparam int unsigned SCR1_CORE_TOP_RST_SYNC_STAGES_NUM = 2;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Local signals declaration
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Reset Logic
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
`else // SCR1_DBG_EN
|
||||||
|
logic core_rst_n_in_sync;
|
||||||
|
logic core_rst_n_qlfy;
|
||||||
|
logic core_rst_n_status;
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
logic core_rst_n;
|
||||||
|
logic core_rst_n_status_sync;
|
||||||
|
logic core_rst_status;
|
||||||
|
logic core2hdu_rdc_qlfy;
|
||||||
|
logic core2dm_rdc_qlfy;
|
||||||
|
logic pwrup_rst_n_sync;
|
||||||
|
logic rst_n_sync;
|
||||||
|
logic cpu_rst_n_sync;
|
||||||
|
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
// TAPC-DM Interface
|
||||||
|
logic tapc_dmi_ch_sel;
|
||||||
|
logic [SCR1_DBG_DMI_CH_ID_WIDTH-1:0] tapc_dmi_ch_id;
|
||||||
|
logic tapc_dmi_ch_capture;
|
||||||
|
logic tapc_dmi_ch_shift;
|
||||||
|
logic tapc_dmi_ch_update;
|
||||||
|
logic tapc_dmi_ch_tdi;
|
||||||
|
logic tapc_dmi_ch_tdo;
|
||||||
|
//
|
||||||
|
logic tapc_dmi_ch_sel_tapout;
|
||||||
|
logic [SCR1_DBG_DMI_CH_ID_WIDTH-1:0] tapc_dmi_ch_id_tapout;
|
||||||
|
logic tapc_dmi_ch_capture_tapout;
|
||||||
|
logic tapc_dmi_ch_shift_tapout;
|
||||||
|
logic tapc_dmi_ch_update_tapout;
|
||||||
|
logic tapc_dmi_ch_tdi_tapout;
|
||||||
|
logic tapc_dmi_ch_tdo_tapin;
|
||||||
|
//
|
||||||
|
logic dmi_req;
|
||||||
|
logic dmi_wr;
|
||||||
|
logic [SCR1_DBG_DMI_ADDR_WIDTH-1:0] dmi_addr;
|
||||||
|
logic [SCR1_DBG_DMI_DATA_WIDTH-1:0] dmi_wdata;
|
||||||
|
logic dmi_resp;
|
||||||
|
logic [SCR1_DBG_DMI_DATA_WIDTH-1:0] dmi_rdata;
|
||||||
|
// TAPC-SCU Interface
|
||||||
|
logic tapc_scu_ch_sel;
|
||||||
|
logic tapc_scu_ch_sel_tapout;
|
||||||
|
logic tapc_scu_ch_tdo;
|
||||||
|
logic tapc_ch_tdo;
|
||||||
|
// SCU nets
|
||||||
|
logic sys_rst_n;
|
||||||
|
logic sys_rst_status;
|
||||||
|
logic hdu_rst_n;
|
||||||
|
logic hdu2dm_rdc_qlfy;
|
||||||
|
logic ndm_rst_n;
|
||||||
|
logic dm_rst_n;
|
||||||
|
logic hart_rst_n;
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
// DM-Pipeline Interface
|
||||||
|
// HART Run Control i/f
|
||||||
|
logic dm_active;
|
||||||
|
logic dm_cmd_req;
|
||||||
|
type_scr1_hdu_dbgstates_e dm_cmd;
|
||||||
|
logic dm_cmd_resp;
|
||||||
|
logic dm_cmd_resp_qlfy;
|
||||||
|
logic dm_cmd_rcode;
|
||||||
|
logic dm_hart_event;
|
||||||
|
logic dm_hart_event_qlfy;
|
||||||
|
type_scr1_hdu_hartstatus_s dm_hart_status;
|
||||||
|
type_scr1_hdu_hartstatus_s dm_hart_status_qlfy;
|
||||||
|
|
||||||
|
// Program Buffer - HART instruction execution i/f
|
||||||
|
logic [SCR1_HDU_PBUF_ADDR_WIDTH-1:0] dm_pbuf_addr;
|
||||||
|
logic [SCR1_HDU_PBUF_ADDR_WIDTH-1:0] dm_pbuf_addr_qlfy;
|
||||||
|
logic [SCR1_HDU_CORE_INSTR_WIDTH-1:0] dm_pbuf_instr;
|
||||||
|
|
||||||
|
// HART Abstract Data regs i/f
|
||||||
|
logic dm_dreg_req;
|
||||||
|
logic dm_dreg_req_qlfy;
|
||||||
|
logic dm_dreg_wr;
|
||||||
|
logic [SCR1_HDU_DATA_REG_WIDTH-1:0] dm_dreg_wdata;
|
||||||
|
logic dm_dreg_resp;
|
||||||
|
logic dm_dreg_fail;
|
||||||
|
logic [SCR1_HDU_DATA_REG_WIDTH-1:0] dm_dreg_rdata;
|
||||||
|
|
||||||
|
logic [`SCR1_XLEN-1 : 0] dm_pc_sample;
|
||||||
|
logic [`SCR1_XLEN-1 : 0] dm_pc_sample_qlfy;
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
|
||||||
|
`ifdef SCR1_CLKCTRL_EN
|
||||||
|
// Global clock gating logic
|
||||||
|
logic sleep_pipe;
|
||||||
|
logic wake_pipe;
|
||||||
|
logic clk_pipe;
|
||||||
|
logic clk_pipe_en;
|
||||||
|
logic clk_dbgc;
|
||||||
|
logic clk_alw_on;
|
||||||
|
`endif // SCR1_CLKCTRL_EN
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Reset Logic
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
scr1_scu i_scu (
|
||||||
|
// Global signals
|
||||||
|
.pwrup_rst_n (pwrup_rst_n ),
|
||||||
|
.rst_n (rst_n ),
|
||||||
|
.cpu_rst_n (cpu_rst_n ),
|
||||||
|
.test_mode (test_mode ),
|
||||||
|
.test_rst_n (test_rst_n ),
|
||||||
|
.clk (clk ),
|
||||||
|
|
||||||
|
// TAPC scan-chains
|
||||||
|
.tapcsync2scu_ch_sel_i (tapc_scu_ch_sel ),
|
||||||
|
.tapcsync2scu_ch_id_i ('0 ),
|
||||||
|
.tapcsync2scu_ch_capture_i (tapc_dmi_ch_capture),
|
||||||
|
.tapcsync2scu_ch_shift_i (tapc_dmi_ch_shift ),
|
||||||
|
.tapcsync2scu_ch_update_i (tapc_dmi_ch_update ),
|
||||||
|
.tapcsync2scu_ch_tdi_i (tapc_dmi_ch_tdi ),
|
||||||
|
.scu2tapcsync_ch_tdo_o (tapc_scu_ch_tdo ),
|
||||||
|
|
||||||
|
// Input sync resets:
|
||||||
|
.ndm_rst_n_i (ndm_rst_n ),
|
||||||
|
.hart_rst_n_i (hart_rst_n ),
|
||||||
|
|
||||||
|
// Generated resets
|
||||||
|
.sys_rst_n_o (sys_rst_n ),
|
||||||
|
.core_rst_n_o (core_rst_n ),
|
||||||
|
.dm_rst_n_o (dm_rst_n ),
|
||||||
|
.hdu_rst_n_o (hdu_rst_n ),
|
||||||
|
|
||||||
|
// Resets statuses
|
||||||
|
.sys_rst_status_o (sys_rst_status ),
|
||||||
|
.core_rst_status_o (core_rst_status ),
|
||||||
|
|
||||||
|
// Reset Domain Crossing (RDC) qualifiers
|
||||||
|
.sys_rdc_qlfy_o (sys_rdc_qlfy_o ),
|
||||||
|
.core_rdc_qlfy_o (core_rdc_qlfy_o ),
|
||||||
|
.core2hdu_rdc_qlfy_o (core2hdu_rdc_qlfy ),
|
||||||
|
.core2dm_rdc_qlfy_o (core2dm_rdc_qlfy ),
|
||||||
|
.hdu2dm_rdc_qlfy_o (hdu2dm_rdc_qlfy )
|
||||||
|
);
|
||||||
|
|
||||||
|
assign sys_rst_n_o = sys_rst_n;
|
||||||
|
|
||||||
|
// Reset inputs are assumed synchronous
|
||||||
|
assign pwrup_rst_n_sync = pwrup_rst_n;
|
||||||
|
|
||||||
|
`else // SCR1_DBG_EN
|
||||||
|
|
||||||
|
// Reset inputs are assumed synchronous
|
||||||
|
assign pwrup_rst_n_sync = pwrup_rst_n;
|
||||||
|
assign rst_n_sync = rst_n;
|
||||||
|
assign cpu_rst_n_sync = cpu_rst_n;
|
||||||
|
assign core_rst_n_in_sync = rst_n_sync & cpu_rst_n_sync;
|
||||||
|
|
||||||
|
// Core Reset: core_rst_n
|
||||||
|
scr1_reset_qlfy_adapter_cell_sync i_core_rstn_qlfy_adapter_cell_sync (
|
||||||
|
.rst_n (pwrup_rst_n_sync ),
|
||||||
|
.clk (clk ),
|
||||||
|
.test_rst_n (test_rst_n ),
|
||||||
|
.test_mode (test_mode ),
|
||||||
|
.reset_n_in_sync (core_rst_n_in_sync),
|
||||||
|
.reset_n_out_qlfy (core_rst_n_qlfy ),
|
||||||
|
.reset_n_out (core_rst_n ),
|
||||||
|
.reset_n_status (core_rst_n_status )
|
||||||
|
);
|
||||||
|
|
||||||
|
scr1_data_sync_cell #(
|
||||||
|
.STAGES_AMOUNT (SCR1_CORE_TOP_RST_SYNC_STAGES_NUM)
|
||||||
|
) i_core_rstn_status_sync (
|
||||||
|
.rst_n (pwrup_rst_n_sync ),
|
||||||
|
.clk (clk ),
|
||||||
|
.data_in (core_rst_n_status ),
|
||||||
|
.data_out (core_rst_n_status_sync)
|
||||||
|
);
|
||||||
|
|
||||||
|
assign core_rst_status = ~core_rst_n_status_sync;
|
||||||
|
assign core_rdc_qlfy_o = core_rst_n_qlfy;
|
||||||
|
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
assign core_rst_n_o = core_rst_n;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// SCR1 pipeline
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
scr1_pipe_top i_pipe_top (
|
||||||
|
// Control
|
||||||
|
.pipe_rst_n (core_rst_n ),
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
.pipe2hdu_rdc_qlfy_i (core2hdu_rdc_qlfy ),
|
||||||
|
.dbg_rst_n (hdu_rst_n ),
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
`ifndef SCR1_CLKCTRL_EN
|
||||||
|
.clk (clk ),
|
||||||
|
`else // SCR1_CLKCTRL_EN
|
||||||
|
.clk (clk_pipe ),
|
||||||
|
.pipe2clkctl_sleep_req_o (sleep_pipe ),
|
||||||
|
.pipe2clkctl_wake_req_o (wake_pipe ),
|
||||||
|
.clkctl2pipe_clk_alw_on_i (clk_alw_on ),
|
||||||
|
.clkctl2pipe_clk_dbgc_i (clk_dbgc ),
|
||||||
|
.clkctl2pipe_clk_en_i (clk_pipe_en ),
|
||||||
|
`endif // SCR1_CLKCTRL_EN
|
||||||
|
|
||||||
|
// Instruction memory interface
|
||||||
|
.pipe2imem_req_o (core2imem_req_o ),
|
||||||
|
.pipe2imem_cmd_o (core2imem_cmd_o ),
|
||||||
|
.pipe2imem_addr_o (core2imem_addr_o ),
|
||||||
|
.imem2pipe_req_ack_i (imem2core_req_ack_i ),
|
||||||
|
.imem2pipe_rdata_i (imem2core_rdata_i ),
|
||||||
|
.imem2pipe_resp_i (imem2core_resp_i ),
|
||||||
|
|
||||||
|
// Data memory interface
|
||||||
|
.pipe2dmem_req_o (core2dmem_req_o ),
|
||||||
|
.pipe2dmem_cmd_o (core2dmem_cmd_o ),
|
||||||
|
.pipe2dmem_width_o (core2dmem_width_o ),
|
||||||
|
.pipe2dmem_addr_o (core2dmem_addr_o ),
|
||||||
|
.pipe2dmem_wdata_o (core2dmem_wdata_o ),
|
||||||
|
.dmem2pipe_req_ack_i (dmem2core_req_ack_i ),
|
||||||
|
.dmem2pipe_rdata_i (dmem2core_rdata_i ),
|
||||||
|
.dmem2pipe_resp_i (dmem2core_resp_i ),
|
||||||
|
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
// Debug interface:
|
||||||
|
.dbg_en (1'b1 ),
|
||||||
|
// Debug interface:
|
||||||
|
// DM <-> Pipeline: HART Run Control i/f
|
||||||
|
.dm2pipe_active_i (dm_active ),
|
||||||
|
.dm2pipe_cmd_req_i (dm_cmd_req ),
|
||||||
|
.dm2pipe_cmd_i (dm_cmd ),
|
||||||
|
.pipe2dm_cmd_resp_o (dm_cmd_resp ),
|
||||||
|
.pipe2dm_cmd_rcode_o (dm_cmd_rcode ),
|
||||||
|
.pipe2dm_hart_event_o (dm_hart_event ),
|
||||||
|
.pipe2dm_hart_status_o (dm_hart_status ),
|
||||||
|
|
||||||
|
// DM <-> Pipeline: Program Buffer - HART instruction execution i/f
|
||||||
|
.pipe2dm_pbuf_addr_o (dm_pbuf_addr ),
|
||||||
|
.dm2pipe_pbuf_instr_i (dm_pbuf_instr ),
|
||||||
|
|
||||||
|
// DM <-> Pipeline: HART Abstract Data regs i/f
|
||||||
|
.pipe2dm_dreg_req_o (dm_dreg_req ),
|
||||||
|
.pipe2dm_dreg_wr_o (dm_dreg_wr ),
|
||||||
|
.pipe2dm_dreg_wdata_o (dm_dreg_wdata ),
|
||||||
|
.dm2pipe_dreg_resp_i (dm_dreg_resp ),
|
||||||
|
.dm2pipe_dreg_fail_i (dm_dreg_fail ),
|
||||||
|
.dm2pipe_dreg_rdata_i (dm_dreg_rdata ),
|
||||||
|
|
||||||
|
// DM <-> Pipeline: PC i/f
|
||||||
|
.pipe2dm_pc_sample_o (dm_pc_sample ),
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
|
||||||
|
// IRQ
|
||||||
|
`ifdef SCR1_IPIC_EN
|
||||||
|
.soc2pipe_irq_lines_i (core_irq_lines_i ),
|
||||||
|
`else // SCR1_IPIC_EN
|
||||||
|
.soc2pipe_irq_ext_i (core_irq_ext_i ),
|
||||||
|
`endif // SCR1_IPIC_EN
|
||||||
|
.soc2pipe_irq_soft_i (core_irq_soft_i ),
|
||||||
|
.soc2pipe_irq_mtimer_i (core_irq_mtimer_i ),
|
||||||
|
|
||||||
|
// Memory-mapped external timer
|
||||||
|
.soc2pipe_mtimer_val_i (core_mtimer_val_i ),
|
||||||
|
|
||||||
|
// Fuse
|
||||||
|
.soc2pipe_fuse_mhartid_i (core_fuse_mhartid_i )
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// TAP Controller (TAPC)
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
scr1_tapc i_tapc (
|
||||||
|
// JTAG signals
|
||||||
|
.tapc_trst_n (tapc_trst_n ),
|
||||||
|
.tapc_tck (tapc_tck ),
|
||||||
|
.tapc_tms (tapc_tms ),
|
||||||
|
.tapc_tdi (tapc_tdi ),
|
||||||
|
.tapc_tdo (tapc_tdo ),
|
||||||
|
.tapc_tdo_en (tapc_tdo_en ),
|
||||||
|
|
||||||
|
// Fuses
|
||||||
|
.soc2tapc_fuse_idcode_i (tapc_fuse_idcode_i ),
|
||||||
|
|
||||||
|
// DMI/SCU scan-chains
|
||||||
|
.tapc2tapcsync_scu_ch_sel_o (tapc_scu_ch_sel_tapout ),
|
||||||
|
.tapc2tapcsync_dmi_ch_sel_o (tapc_dmi_ch_sel_tapout ),
|
||||||
|
.tapc2tapcsync_ch_id_o (tapc_dmi_ch_id_tapout ),
|
||||||
|
.tapc2tapcsync_ch_capture_o (tapc_dmi_ch_capture_tapout),
|
||||||
|
.tapc2tapcsync_ch_shift_o (tapc_dmi_ch_shift_tapout ),
|
||||||
|
.tapc2tapcsync_ch_update_o (tapc_dmi_ch_update_tapout ),
|
||||||
|
.tapc2tapcsync_ch_tdi_o (tapc_dmi_ch_tdi_tapout ),
|
||||||
|
.tapcsync2tapc_ch_tdo_i (tapc_dmi_ch_tdo_tapin )
|
||||||
|
);
|
||||||
|
|
||||||
|
scr1_tapc_synchronizer i_tapc_synchronizer (
|
||||||
|
// System common signals
|
||||||
|
.pwrup_rst_n (pwrup_rst_n_sync ),
|
||||||
|
.dm_rst_n (dm_rst_n ),
|
||||||
|
.clk (clk ),
|
||||||
|
|
||||||
|
// JTAG common signals
|
||||||
|
.tapc_trst_n (tapc_trst_n ),
|
||||||
|
.tapc_tck (tapc_tck ),
|
||||||
|
|
||||||
|
// DMI/SCU scan-chains
|
||||||
|
.tapc2tapcsync_scu_ch_sel_i (tapc_scu_ch_sel_tapout ),
|
||||||
|
.tapcsync2scu_ch_sel_o (tapc_scu_ch_sel ),
|
||||||
|
.tapc2tapcsync_dmi_ch_sel_i (tapc_dmi_ch_sel_tapout ),
|
||||||
|
.tapcsync2dmi_ch_sel_o (tapc_dmi_ch_sel ),
|
||||||
|
|
||||||
|
.tapc2tapcsync_ch_id_i (tapc_dmi_ch_id_tapout ),
|
||||||
|
.tapcsync2core_ch_id_o (tapc_dmi_ch_id ),
|
||||||
|
.tapc2tapcsync_ch_capture_i (tapc_dmi_ch_capture_tapout),
|
||||||
|
.tapcsync2core_ch_capture_o (tapc_dmi_ch_capture ),
|
||||||
|
.tapc2tapcsync_ch_shift_i (tapc_dmi_ch_shift_tapout ),
|
||||||
|
.tapcsync2core_ch_shift_o (tapc_dmi_ch_shift ),
|
||||||
|
.tapc2tapcsync_ch_update_i (tapc_dmi_ch_update_tapout ),
|
||||||
|
.tapcsync2core_ch_update_o (tapc_dmi_ch_update ),
|
||||||
|
.tapc2tapcsync_ch_tdi_i (tapc_dmi_ch_tdi_tapout ),
|
||||||
|
.tapcsync2core_ch_tdi_o (tapc_dmi_ch_tdi ),
|
||||||
|
.tapc2tapcsync_ch_tdo_i (tapc_dmi_ch_tdo_tapin ),
|
||||||
|
.tapcsync2core_ch_tdo_o (tapc_ch_tdo )
|
||||||
|
);
|
||||||
|
assign tapc_ch_tdo = (tapc_scu_ch_tdo & tapc_scu_ch_sel)
|
||||||
|
| (tapc_dmi_ch_tdo & tapc_dmi_ch_sel);
|
||||||
|
|
||||||
|
scr1_dmi i_dmi (
|
||||||
|
.rst_n (dm_rst_n ),
|
||||||
|
.clk (clk ),
|
||||||
|
|
||||||
|
// TAP scan-chains
|
||||||
|
.tapcsync2dmi_ch_sel_i (tapc_dmi_ch_sel ),
|
||||||
|
.tapcsync2dmi_ch_id_i (tapc_dmi_ch_id ),
|
||||||
|
.tapcsync2dmi_ch_capture_i (tapc_dmi_ch_capture),
|
||||||
|
.tapcsync2dmi_ch_shift_i (tapc_dmi_ch_shift ),
|
||||||
|
.tapcsync2dmi_ch_update_i (tapc_dmi_ch_update ),
|
||||||
|
.tapcsync2dmi_ch_tdi_i (tapc_dmi_ch_tdi ),
|
||||||
|
.dmi2tapcsync_ch_tdo_o (tapc_dmi_ch_tdo ),
|
||||||
|
|
||||||
|
// DMI
|
||||||
|
.dm2dmi_resp_i (dmi_resp ),
|
||||||
|
.dm2dmi_rdata_i (dmi_rdata ),
|
||||||
|
.dmi2dm_req_o (dmi_req ),
|
||||||
|
.dmi2dm_wr_o (dmi_wr ),
|
||||||
|
.dmi2dm_addr_o (dmi_addr ),
|
||||||
|
.dmi2dm_wdata_o (dmi_wdata )
|
||||||
|
);
|
||||||
|
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
|
||||||
|
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Debug Module (DM)
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
assign dm_cmd_resp_qlfy = dm_cmd_resp & {$bits(dm_cmd_resp){hdu2dm_rdc_qlfy}};
|
||||||
|
assign dm_hart_event_qlfy = dm_hart_event & {$bits(dm_hart_event){hdu2dm_rdc_qlfy}};
|
||||||
|
assign dm_hart_status_qlfy.dbg_state = hdu2dm_rdc_qlfy ? dm_hart_status.dbg_state
|
||||||
|
: SCR1_HDU_DBGSTATE_RESET;
|
||||||
|
assign dm_hart_status_qlfy.except = dm_hart_status.except;
|
||||||
|
assign dm_hart_status_qlfy.ebreak = dm_hart_status.ebreak;
|
||||||
|
assign dm_pbuf_addr_qlfy = dm_pbuf_addr & {$bits(dm_pbuf_addr){hdu2dm_rdc_qlfy}};
|
||||||
|
assign dm_dreg_req_qlfy = dm_dreg_req & {$bits(dm_dreg_req){hdu2dm_rdc_qlfy}};
|
||||||
|
assign dm_pc_sample_qlfy = dm_pc_sample & {$bits(dm_pc_sample){core2dm_rdc_qlfy}};
|
||||||
|
|
||||||
|
scr1_dm i_dm (
|
||||||
|
// Common signals
|
||||||
|
.rst_n (dm_rst_n ),
|
||||||
|
.clk (clk ),
|
||||||
|
|
||||||
|
// DM internal interface
|
||||||
|
.dmi2dm_req_i (dmi_req ),
|
||||||
|
.dmi2dm_wr_i (dmi_wr ),
|
||||||
|
.dmi2dm_addr_i (dmi_addr ),
|
||||||
|
.dmi2dm_wdata_i (dmi_wdata ),
|
||||||
|
.dm2dmi_resp_o (dmi_resp ),
|
||||||
|
.dm2dmi_rdata_o (dmi_rdata ),
|
||||||
|
|
||||||
|
// DM <-> Pipeline: HART Run Control i/f
|
||||||
|
.ndm_rst_n_o (ndm_rst_n ),
|
||||||
|
.hart_rst_n_o (hart_rst_n ),
|
||||||
|
.dm2pipe_active_o (dm_active ),
|
||||||
|
.dm2pipe_cmd_req_o (dm_cmd_req ),
|
||||||
|
.dm2pipe_cmd_o (dm_cmd ),
|
||||||
|
.pipe2dm_cmd_resp_i (dm_cmd_resp_qlfy ),
|
||||||
|
.pipe2dm_cmd_rcode_i (dm_cmd_rcode ),
|
||||||
|
.pipe2dm_hart_event_i (dm_hart_event_qlfy ),
|
||||||
|
.pipe2dm_hart_status_i (dm_hart_status_qlfy ),
|
||||||
|
|
||||||
|
.soc2dm_fuse_mhartid_i (core_fuse_mhartid_i ),
|
||||||
|
.pipe2dm_pc_sample_i (dm_pc_sample_qlfy ),
|
||||||
|
|
||||||
|
// DM <-> Pipeline: HART Abstract Command / Program Buffer i/f
|
||||||
|
.pipe2dm_pbuf_addr_i (dm_pbuf_addr_qlfy ),
|
||||||
|
.dm2pipe_pbuf_instr_o (dm_pbuf_instr ),
|
||||||
|
|
||||||
|
// DM <-> Pipeline: HART Abstract Data regs i/f
|
||||||
|
.pipe2dm_dreg_req_i (dm_dreg_req_qlfy ),
|
||||||
|
.pipe2dm_dreg_wr_i (dm_dreg_wr ),
|
||||||
|
.pipe2dm_dreg_wdata_i (dm_dreg_wdata ),
|
||||||
|
.dm2pipe_dreg_resp_o (dm_dreg_resp ),
|
||||||
|
.dm2pipe_dreg_fail_o (dm_dreg_fail ),
|
||||||
|
.dm2pipe_dreg_rdata_o (dm_dreg_rdata )
|
||||||
|
);
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
|
||||||
|
|
||||||
|
`ifdef SCR1_CLKCTRL_EN
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Global clock gating logic
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
scr1_clk_ctrl i_clk_ctrl (
|
||||||
|
.clk (clk ),
|
||||||
|
.rst_n (core_rst_n ),
|
||||||
|
.test_mode (test_mode ),
|
||||||
|
.test_rst_n (test_rst_n ),
|
||||||
|
|
||||||
|
// Sleep/wake interface
|
||||||
|
.pipe2clkctl_sleep_req_i (sleep_pipe ),
|
||||||
|
.pipe2clkctl_wake_req_i (wake_pipe ),
|
||||||
|
|
||||||
|
// Clocks
|
||||||
|
.clkctl2pipe_clk_alw_on_o (clk_alw_on ),
|
||||||
|
.clkctl2pipe_clk_o (clk_pipe ),
|
||||||
|
.clkctl2pipe_clk_en_o (clk_pipe_en),
|
||||||
|
.clkctl2pipe_clk_dbgc_o (clk_dbgc )
|
||||||
|
);
|
||||||
|
`endif // SCR1_CLKCTRL_EN
|
||||||
|
|
||||||
|
endmodule : scr1_core_top
|
||||||
1427
src_ref/core/scr1_dm.sv
Normal file
1427
src_ref/core/scr1_dm.sv
Normal file
File diff suppressed because it is too large
Load Diff
182
src_ref/core/scr1_dmi.sv
Normal file
182
src_ref/core/scr1_dmi.sv
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
|
||||||
|
/// @file <scr1_dmi.sv>
|
||||||
|
/// @brief Debug Module Interface (DMI)
|
||||||
|
///
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Functionality:
|
||||||
|
// - Provides TAPC with access to Debug Module (DM) and DTMCS
|
||||||
|
//
|
||||||
|
// Structure:
|
||||||
|
// - DMI <-> TAP interface
|
||||||
|
// - DMI <-> DM interface
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
`include "scr1_arch_description.svh"
|
||||||
|
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
`include "scr1_dm.svh"
|
||||||
|
|
||||||
|
module scr1_dmi (
|
||||||
|
// System
|
||||||
|
input logic rst_n, // DMI unit reset
|
||||||
|
input logic clk, // DMI unit clock
|
||||||
|
|
||||||
|
// TAP interface
|
||||||
|
input logic tapcsync2dmi_ch_sel_i, // Debug Transport Module Chain Select
|
||||||
|
input logic [SCR1_DBG_DMI_CH_ID_WIDTH-1:0] tapcsync2dmi_ch_id_i, // Debug Transport Module Chain ID
|
||||||
|
input logic tapcsync2dmi_ch_capture_i, // Debug Transport Module Chain Capture
|
||||||
|
input logic tapcsync2dmi_ch_shift_i, // Debug Transport Module Chain Shift
|
||||||
|
input logic tapcsync2dmi_ch_update_i, // Debug Transport Module Chain Update
|
||||||
|
input logic tapcsync2dmi_ch_tdi_i, // Debug Transport Module Chain TDI
|
||||||
|
output logic dmi2tapcsync_ch_tdo_o, // Debug Transport Module Chain TDO
|
||||||
|
|
||||||
|
// DM interface
|
||||||
|
input logic dm2dmi_resp_i, // DMI response
|
||||||
|
input logic [SCR1_DBG_DMI_DATA_WIDTH-1:0] dm2dmi_rdata_i, // DMI read data
|
||||||
|
output logic dmi2dm_req_o, // DMI request
|
||||||
|
output logic dmi2dm_wr_o, // DMI write
|
||||||
|
output logic [SCR1_DBG_DMI_ADDR_WIDTH-1:0] dmi2dm_addr_o, // DMI address
|
||||||
|
output logic [SCR1_DBG_DMI_DATA_WIDTH-1:0] dmi2dm_wdata_o // DMI write data
|
||||||
|
);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Local parameters declaration
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Debug Transport Module Status parameters
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
localparam DTMCS_RESERVEDB_HI = 5'd31;
|
||||||
|
localparam DTMCS_RESERVEDB_LO = 5'd18;
|
||||||
|
localparam DTMCS_DMIHARDRESET = 5'd17;
|
||||||
|
localparam DTMCS_DMIRESET = 5'd16;
|
||||||
|
localparam DTMCS_RESERVEDA = 5'd15;
|
||||||
|
localparam DTMCS_IDLE_HI = 5'd14;
|
||||||
|
localparam DTMCS_IDLE_LO = 5'd12;
|
||||||
|
localparam DTMCS_DMISTAT_HI = 5'd11;
|
||||||
|
localparam DTMCS_DMISTAT_LO = 5'd10;
|
||||||
|
localparam DTMCS_ABITS_HI = 5'd9;
|
||||||
|
localparam DTMCS_ABITS_LO = 5'd4;
|
||||||
|
localparam DTMCS_VERSION_HI = 5'd3;
|
||||||
|
localparam DTMCS_VERSION_LO = 5'd0;
|
||||||
|
|
||||||
|
// Debug Module Interface parameters
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
localparam DMI_OP_LO = 5'd0;
|
||||||
|
localparam DMI_OP_HI = DMI_OP_LO + SCR1_DBG_DMI_OP_WIDTH - 1;
|
||||||
|
localparam DMI_DATA_LO = DMI_OP_HI + 1;
|
||||||
|
localparam DMI_DATA_HI = DMI_DATA_LO + SCR1_DBG_DMI_DATA_WIDTH - 1;
|
||||||
|
localparam DMI_ADDR_LO = DMI_DATA_HI + 1;
|
||||||
|
localparam DMI_ADDR_HI = DMI_ADDR_LO + SCR1_DBG_DMI_ADDR_WIDTH - 1;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Local signals declaration
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// TAP data register
|
||||||
|
logic tap_dr_upd;
|
||||||
|
logic [SCR1_DBG_DMI_DR_DMI_ACCESS_WIDTH-1:0] tap_dr_ff;
|
||||||
|
logic [SCR1_DBG_DMI_DR_DMI_ACCESS_WIDTH-1:0] tap_dr_shift;
|
||||||
|
logic [SCR1_DBG_DMI_DR_DMI_ACCESS_WIDTH-1:0] tap_dr_rdata;
|
||||||
|
logic [SCR1_DBG_DMI_DR_DMI_ACCESS_WIDTH-1:0] tap_dr_next;
|
||||||
|
|
||||||
|
// DM read data register
|
||||||
|
logic dm_rdata_upd;
|
||||||
|
logic [SCR1_DBG_DMI_DATA_WIDTH-1:0] dm_rdata_ff;
|
||||||
|
|
||||||
|
logic tapc_dmi_access_req;
|
||||||
|
logic tapc_dtmcs_sel;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// DMI <-> TAP interface
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// TAPC read data multiplexer
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign tapc_dtmcs_sel = (tapcsync2dmi_ch_id_i == 1'd1);
|
||||||
|
|
||||||
|
// DMI operation is always successful in the current implementation
|
||||||
|
always_comb begin
|
||||||
|
tap_dr_rdata = '0;
|
||||||
|
|
||||||
|
if(tapc_dtmcs_sel) begin
|
||||||
|
tap_dr_rdata[DTMCS_RESERVEDB_HI:DTMCS_RESERVEDB_LO] = 'b0;
|
||||||
|
tap_dr_rdata[DTMCS_DMIHARDRESET] = 'b0;
|
||||||
|
tap_dr_rdata[DTMCS_DMIRESET] = 'b0;
|
||||||
|
tap_dr_rdata[DTMCS_RESERVEDA] = 'b0;
|
||||||
|
tap_dr_rdata[DTMCS_IDLE_HI:DTMCS_IDLE_LO] = 'b0;
|
||||||
|
tap_dr_rdata[DTMCS_DMISTAT_HI:DTMCS_DMISTAT_LO] = 'b0;
|
||||||
|
tap_dr_rdata[DTMCS_ABITS_HI :DTMCS_ABITS_LO] = SCR1_DBG_DMI_ADDR_WIDTH;
|
||||||
|
tap_dr_rdata[DTMCS_VERSION_LO] = 1'b1;
|
||||||
|
end else begin
|
||||||
|
tap_dr_rdata[DMI_ADDR_HI:DMI_ADDR_LO] = 'b0;
|
||||||
|
tap_dr_rdata[DMI_DATA_HI:DMI_DATA_LO] = dm_rdata_ff;
|
||||||
|
tap_dr_rdata[DMI_OP_HI :DMI_OP_LO] = 'b0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign tap_dr_shift = tapc_dtmcs_sel
|
||||||
|
? {9'b0, tapcsync2dmi_ch_tdi_i, tap_dr_ff[SCR1_DBG_DMI_DR_DTMCS_WIDTH-1:1]}
|
||||||
|
: {tapcsync2dmi_ch_tdi_i, tap_dr_ff[SCR1_DBG_DMI_DR_DMI_ACCESS_WIDTH-1:1]};
|
||||||
|
|
||||||
|
// TAP data register
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign tap_dr_upd = tapcsync2dmi_ch_capture_i | tapcsync2dmi_ch_shift_i;
|
||||||
|
|
||||||
|
always_ff @(posedge clk, negedge rst_n) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
tap_dr_ff <= '0;
|
||||||
|
end else if(tap_dr_upd) begin
|
||||||
|
tap_dr_ff <= tap_dr_next;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign tap_dr_next = tapcsync2dmi_ch_capture_i ? tap_dr_rdata
|
||||||
|
: tapcsync2dmi_ch_shift_i ? tap_dr_shift
|
||||||
|
: tap_dr_ff;
|
||||||
|
|
||||||
|
assign dmi2tapcsync_ch_tdo_o = tap_dr_ff[0];
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// DMI <-> DM interface
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign tapc_dmi_access_req = tapcsync2dmi_ch_update_i & tapcsync2dmi_ch_sel_i
|
||||||
|
& (tapcsync2dmi_ch_id_i == 2'd2);
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
dmi2dm_req_o = 1'b0;
|
||||||
|
dmi2dm_wr_o = 1'b0;
|
||||||
|
dmi2dm_addr_o = 1'b0;
|
||||||
|
dmi2dm_wdata_o = 1'b0;
|
||||||
|
|
||||||
|
if(tapc_dmi_access_req) begin
|
||||||
|
dmi2dm_req_o = tap_dr_ff[DMI_OP_HI :DMI_OP_LO] != 2'b00;
|
||||||
|
dmi2dm_wr_o = tap_dr_ff[DMI_OP_HI :DMI_OP_LO] == 2'b10;
|
||||||
|
dmi2dm_addr_o = tap_dr_ff[DMI_ADDR_HI:DMI_ADDR_LO];
|
||||||
|
dmi2dm_wdata_o = tap_dr_ff[DMI_DATA_HI:DMI_DATA_LO];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// DM read data register
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign dm_rdata_upd = dmi2dm_req_o & dm2dmi_resp_i & ~dmi2dm_wr_o;
|
||||||
|
|
||||||
|
always_ff @(posedge clk, negedge rst_n) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
dm_rdata_ff <= '0;
|
||||||
|
end else if (dm_rdata_upd) begin
|
||||||
|
dm_rdata_ff <= dm2dmi_rdata_i;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule : scr1_dmi
|
||||||
|
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
516
src_ref/core/scr1_scu.sv
Normal file
516
src_ref/core/scr1_scu.sv
Normal file
@@ -0,0 +1,516 @@
|
|||||||
|
/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
|
||||||
|
/// @file <scr1_scu.sv>
|
||||||
|
/// @brief System Control Unit (SCU)
|
||||||
|
///
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Functionality:
|
||||||
|
// - Generates System, Core, HDU and DM resets and their qualifier signals
|
||||||
|
// - Provides debugger with software System and Core resets generation functionality
|
||||||
|
// - Allows to set the behavior of DM and HDU resets
|
||||||
|
// - Shows resets Statuses and Sticky Statuses
|
||||||
|
|
||||||
|
// Structure:
|
||||||
|
// - TAPC scan-chain interface
|
||||||
|
// - SCU CSRs write/read interface
|
||||||
|
// - SCU CSRS:
|
||||||
|
// - CONTROL register
|
||||||
|
// - MODE register
|
||||||
|
// - STATUS register
|
||||||
|
// - STICKY_STATUS register
|
||||||
|
// - Reset logic
|
||||||
|
// - System Reset
|
||||||
|
// - Core Reset
|
||||||
|
// - DM Reset
|
||||||
|
// - HDU Reset
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
`include "scr1_arch_description.svh"
|
||||||
|
`include "scr1_scu.svh"
|
||||||
|
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
|
||||||
|
module scr1_scu (
|
||||||
|
// Global signals
|
||||||
|
input logic pwrup_rst_n, // Power-Up Reset
|
||||||
|
input logic rst_n, // Regular Reset
|
||||||
|
input logic cpu_rst_n, // CPU Reset
|
||||||
|
input logic test_mode, // DFT Test Mode
|
||||||
|
input logic test_rst_n, // DFT Test Reset
|
||||||
|
input logic clk, // SCU clock
|
||||||
|
|
||||||
|
// TAPC scan-chains
|
||||||
|
input logic tapcsync2scu_ch_sel_i, // TAPC Chain Select
|
||||||
|
input logic tapcsync2scu_ch_id_i, // TAPC Chain ID
|
||||||
|
input logic tapcsync2scu_ch_capture_i, // TAPC Chain Capture
|
||||||
|
input logic tapcsync2scu_ch_shift_i, // TAPC Chain Shift
|
||||||
|
input logic tapcsync2scu_ch_update_i, // TAPC Chain Update
|
||||||
|
input logic tapcsync2scu_ch_tdi_i, // TAPC Chain TDI
|
||||||
|
output logic scu2tapcsync_ch_tdo_o, // TAPC Chain TDO
|
||||||
|
|
||||||
|
// Input sync resets:
|
||||||
|
input logic ndm_rst_n_i, // Non-DM Reset input from DM
|
||||||
|
input logic hart_rst_n_i, // HART Reset from DM
|
||||||
|
|
||||||
|
// Generated resets
|
||||||
|
output logic sys_rst_n_o, // System/Cluster Reset
|
||||||
|
output logic core_rst_n_o, // Core Reset
|
||||||
|
output logic dm_rst_n_o, // Debug Module Reset
|
||||||
|
output logic hdu_rst_n_o, // HART Debug Unit Reset
|
||||||
|
|
||||||
|
// Resets statuses
|
||||||
|
output logic sys_rst_status_o, // System Reset Status (sync'ed to POR reset domain)
|
||||||
|
output logic core_rst_status_o, // Core Reset Status (sync'ed to POR reset domain)
|
||||||
|
|
||||||
|
// Reset Domain Crossing (RDC) qualifiers
|
||||||
|
output logic sys_rdc_qlfy_o, // System/Cluster-to-ExternalSOC Reset Domain Crossing Qualifier
|
||||||
|
output logic core_rdc_qlfy_o, // Core-to-ExternalSOC Reset Domain Crossing Qualifier
|
||||||
|
output logic core2hdu_rdc_qlfy_o, // Core-to-HDU Reset Domain Crossing Qualifier
|
||||||
|
output logic core2dm_rdc_qlfy_o, // Core-to-DM Reset Domain Crossing Qualifier
|
||||||
|
output logic hdu2dm_rdc_qlfy_o // HDU-to-DM Reset Domain Crossing Qualifier
|
||||||
|
);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Local Parameters
|
||||||
|
//======================================================================================================================
|
||||||
|
localparam int unsigned SCR1_SCU_RST_SYNC_STAGES_NUM = 2;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Local Signals
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// SCU CSR write/read i/f
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// TAPC scan-chain control logic
|
||||||
|
logic scu_csr_req;
|
||||||
|
logic tapc_dr_cap_req;
|
||||||
|
logic tapc_dr_shft_req;
|
||||||
|
logic tapc_dr_upd_req;
|
||||||
|
|
||||||
|
// TAPC shift register signals
|
||||||
|
logic tapc_shift_upd;
|
||||||
|
type_scr1_scu_sysctrl_dr_s tapc_shift_ff;
|
||||||
|
type_scr1_scu_sysctrl_dr_s tapc_shift_next;
|
||||||
|
|
||||||
|
// TAPC shadow register signals
|
||||||
|
type_scr1_scu_sysctrl_dr_s tapc_shadow_ff;
|
||||||
|
|
||||||
|
// SCU CSR write/read i/f
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
logic [SCR1_SCU_DR_SYSCTRL_DATA_WIDTH-1:0] scu_csr_wdata;
|
||||||
|
logic [SCR1_SCU_DR_SYSCTRL_DATA_WIDTH-1:0] scu_csr_rdata;
|
||||||
|
|
||||||
|
// SCU CSRs signals
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Control register
|
||||||
|
type_scr1_scu_sysctrl_control_reg_s scu_control_ff;
|
||||||
|
logic scu_control_wr_req;
|
||||||
|
|
||||||
|
// Mode register
|
||||||
|
type_scr1_scu_sysctrl_mode_reg_s scu_mode_ff;
|
||||||
|
logic scu_mode_wr_req;
|
||||||
|
|
||||||
|
// Status register
|
||||||
|
type_scr1_scu_sysctrl_status_reg_s scu_status_ff;
|
||||||
|
type_scr1_scu_sysctrl_status_reg_s scu_status_ff_dly;
|
||||||
|
type_scr1_scu_sysctrl_status_reg_s scu_status_ff_posedge;
|
||||||
|
|
||||||
|
// Sticky Status register
|
||||||
|
type_scr1_scu_sysctrl_status_reg_s scu_sticky_sts_ff;
|
||||||
|
logic scu_sticky_sts_wr_req;
|
||||||
|
|
||||||
|
// Reset logic signals
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Input resets synchronization signals
|
||||||
|
logic pwrup_rst_n_sync;
|
||||||
|
logic rst_n_sync;
|
||||||
|
logic cpu_rst_n_sync;
|
||||||
|
|
||||||
|
// System Reset signals
|
||||||
|
logic sys_rst_n_in;
|
||||||
|
logic sys_rst_n_status;
|
||||||
|
logic sys_rst_n_status_sync;
|
||||||
|
logic sys_rst_n_qlfy;
|
||||||
|
logic sys_reset_n;
|
||||||
|
|
||||||
|
// Core Reset signals
|
||||||
|
logic core_rst_n_in_sync;
|
||||||
|
logic core_rst_n_status;
|
||||||
|
logic core_rst_n_status_sync;
|
||||||
|
logic core_rst_n_qlfy;
|
||||||
|
logic core_reset_n;
|
||||||
|
|
||||||
|
// HDU Reset signals
|
||||||
|
logic hdu_rst_n_in_sync;
|
||||||
|
logic hdu_rst_n_status;
|
||||||
|
logic hdu_rst_n_status_sync;
|
||||||
|
logic hdu_rst_n_qlfy;
|
||||||
|
|
||||||
|
// DM Reset signals
|
||||||
|
logic dm_rst_n_in;
|
||||||
|
logic dm_rst_n_status;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// TAPC scan-chain i/f
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Consists of the following functional units:
|
||||||
|
// - TAPC scan-chain control logic
|
||||||
|
// - TAPC shift register
|
||||||
|
// - TAPC shadow register
|
||||||
|
//
|
||||||
|
|
||||||
|
// TAPC scan-chain control logic
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign scu_csr_req = tapcsync2scu_ch_sel_i & (tapcsync2scu_ch_id_i == '0);
|
||||||
|
assign tapc_dr_cap_req = scu_csr_req & tapcsync2scu_ch_capture_i;
|
||||||
|
assign tapc_dr_shft_req = scu_csr_req & tapcsync2scu_ch_shift_i;
|
||||||
|
assign tapc_dr_upd_req = scu_csr_req & tapcsync2scu_ch_update_i;
|
||||||
|
|
||||||
|
// TAPC shift register
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign tapc_shift_upd = tapc_dr_cap_req | tapc_dr_shft_req;
|
||||||
|
|
||||||
|
always_ff @(posedge clk, negedge pwrup_rst_n_sync) begin
|
||||||
|
if (~pwrup_rst_n_sync) begin
|
||||||
|
tapc_shift_ff <= '0;
|
||||||
|
end else if (tapc_shift_upd) begin
|
||||||
|
tapc_shift_ff <= tapc_shift_next;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign tapc_shift_next = tapc_dr_cap_req ? tapc_shadow_ff
|
||||||
|
: tapc_dr_shft_req ? {tapcsync2scu_ch_tdi_i, tapc_shift_ff[$bits(type_scr1_scu_sysctrl_dr_s)-1:1]}
|
||||||
|
: tapc_shift_ff;
|
||||||
|
|
||||||
|
// TAPC shadow register
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
always_ff @(posedge clk, negedge pwrup_rst_n_sync) begin
|
||||||
|
if (~pwrup_rst_n_sync) begin
|
||||||
|
tapc_shadow_ff <= '0;
|
||||||
|
end else if (tapc_dr_upd_req) begin
|
||||||
|
tapc_shadow_ff.op <= tapc_shift_ff.op;
|
||||||
|
tapc_shadow_ff.addr <= tapc_shift_ff.addr;
|
||||||
|
tapc_shadow_ff.data <= scu_csr_wdata;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign scu2tapcsync_ch_tdo_o = tapc_shift_ff[0];
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// SCU CSRs write/read interface
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Write interface
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Register selection logic
|
||||||
|
always_comb begin
|
||||||
|
scu_control_wr_req = 1'b0;
|
||||||
|
scu_mode_wr_req = 1'b0;
|
||||||
|
scu_sticky_sts_wr_req = 1'b0;
|
||||||
|
|
||||||
|
if (tapc_dr_upd_req && (tapc_shift_ff.op != SCR1_SCU_SYSCTRL_OP_READ)) begin
|
||||||
|
case (tapc_shift_ff.addr)
|
||||||
|
SCR1_SCU_SYSCTRL_ADDR_CONTROL: scu_control_wr_req = 1'b1;
|
||||||
|
SCR1_SCU_SYSCTRL_ADDR_MODE : scu_mode_wr_req = 1'b1;
|
||||||
|
SCR1_SCU_SYSCTRL_ADDR_STICKY : scu_sticky_sts_wr_req = (tapc_shift_ff.op == SCR1_SCU_SYSCTRL_OP_CLRBITS);
|
||||||
|
default : begin end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// Write data construction
|
||||||
|
always_comb begin
|
||||||
|
scu_csr_wdata = '0;
|
||||||
|
|
||||||
|
if (tapc_dr_upd_req) begin
|
||||||
|
case (tapc_shift_ff.op)
|
||||||
|
SCR1_SCU_SYSCTRL_OP_WRITE : scu_csr_wdata = tapc_shift_ff.data;
|
||||||
|
SCR1_SCU_SYSCTRL_OP_READ : scu_csr_wdata = scu_csr_rdata;
|
||||||
|
SCR1_SCU_SYSCTRL_OP_SETBITS: scu_csr_wdata = scu_csr_rdata | tapc_shift_ff.data;
|
||||||
|
SCR1_SCU_SYSCTRL_OP_CLRBITS: scu_csr_wdata = scu_csr_rdata & (~tapc_shift_ff.data);
|
||||||
|
default : begin end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// Read interface
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Read data multiplexer
|
||||||
|
always_comb begin
|
||||||
|
scu_csr_rdata = '0;
|
||||||
|
|
||||||
|
if (tapc_dr_upd_req) begin
|
||||||
|
case (tapc_shift_ff.addr)
|
||||||
|
SCR1_SCU_SYSCTRL_ADDR_CONTROL: scu_csr_rdata = scu_control_ff;
|
||||||
|
SCR1_SCU_SYSCTRL_ADDR_MODE : scu_csr_rdata = scu_mode_ff;
|
||||||
|
SCR1_SCU_SYSCTRL_ADDR_STATUS : scu_csr_rdata = scu_status_ff;
|
||||||
|
SCR1_SCU_SYSCTRL_ADDR_STICKY : scu_csr_rdata = scu_sticky_sts_ff;
|
||||||
|
default : scu_csr_rdata = 'x;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// SCU CSRs
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Registers:
|
||||||
|
// - CONTROL register
|
||||||
|
// - MODE register
|
||||||
|
// - STATUS register
|
||||||
|
// - STICKY_STATUS register
|
||||||
|
//
|
||||||
|
|
||||||
|
// CONTROL register
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Allows debugger to generate System and Core resets
|
||||||
|
|
||||||
|
always_ff @(posedge clk, negedge pwrup_rst_n_sync) begin
|
||||||
|
if (~pwrup_rst_n_sync) begin
|
||||||
|
scu_control_ff <= '0;
|
||||||
|
end else if (scu_control_wr_req) begin
|
||||||
|
scu_control_ff <= scu_csr_wdata;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// MODE register
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Sets reset behavior for DM Reset and HDU Reset signals
|
||||||
|
|
||||||
|
always_ff @(posedge clk, negedge pwrup_rst_n_sync) begin
|
||||||
|
if (~pwrup_rst_n_sync) begin
|
||||||
|
scu_mode_ff <= '0;
|
||||||
|
end else if (scu_mode_wr_req) begin
|
||||||
|
scu_mode_ff <= scu_csr_wdata;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// STATUS register
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Holds the status of every output reset signal (System, Core, DM and HDU)
|
||||||
|
|
||||||
|
assign scu_status_ff.sys_reset = sys_rst_status_o ;
|
||||||
|
assign scu_status_ff.core_reset = core_rst_status_o;
|
||||||
|
assign scu_status_ff.dm_reset = ~dm_rst_n_status;
|
||||||
|
assign scu_status_ff.hdu_reset = ~hdu_rst_n_status_sync;
|
||||||
|
|
||||||
|
// Status Register positive edge detection logic
|
||||||
|
always_ff @(posedge clk, negedge pwrup_rst_n_sync) begin
|
||||||
|
if (~pwrup_rst_n_sync) begin
|
||||||
|
scu_status_ff_dly <= '0;
|
||||||
|
end else begin
|
||||||
|
scu_status_ff_dly <= scu_status_ff;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign scu_status_ff_posedge = scu_status_ff & ~scu_status_ff_dly;
|
||||||
|
|
||||||
|
// STICKY_STATUS register
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// For every output reset signal shows if it was asserted since the last bit clearing
|
||||||
|
|
||||||
|
always_ff @(posedge clk, negedge pwrup_rst_n_sync) begin
|
||||||
|
if (~pwrup_rst_n_sync) begin
|
||||||
|
scu_sticky_sts_ff <= '0;
|
||||||
|
end else begin
|
||||||
|
for (int unsigned i = 0; i < $bits(type_scr1_scu_sysctrl_status_reg_s); ++i) begin
|
||||||
|
if (scu_status_ff_posedge[i]) begin
|
||||||
|
scu_sticky_sts_ff[i] <= 1'b1;
|
||||||
|
end else if (scu_sticky_sts_wr_req) begin
|
||||||
|
scu_sticky_sts_ff[i] <= scu_csr_wdata[i];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Reset logic
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Consists of the following functional units:
|
||||||
|
// - System Reset logic
|
||||||
|
// - Core Reset logic
|
||||||
|
// - Hart Debug Unit Reset logic
|
||||||
|
// - Debug Module Reset logic
|
||||||
|
//
|
||||||
|
|
||||||
|
// Reset inputs are assumed synchronous
|
||||||
|
assign pwrup_rst_n_sync = pwrup_rst_n;
|
||||||
|
assign rst_n_sync = rst_n;
|
||||||
|
assign cpu_rst_n_sync = cpu_rst_n;
|
||||||
|
|
||||||
|
// Intermediate resets:
|
||||||
|
assign sys_reset_n = ~scu_control_ff.sys_reset;
|
||||||
|
assign core_reset_n = ~scu_control_ff.core_reset;
|
||||||
|
|
||||||
|
// System/Cluster Reset: sys_rst_n_o
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
scr1_reset_qlfy_adapter_cell_sync i_sys_rstn_qlfy_adapter_cell_sync (
|
||||||
|
.rst_n (pwrup_rst_n_sync),
|
||||||
|
.clk (clk ),
|
||||||
|
.test_rst_n (test_rst_n ),
|
||||||
|
.test_mode (test_mode ),
|
||||||
|
.reset_n_in_sync (sys_rst_n_in ),
|
||||||
|
.reset_n_out_qlfy (sys_rst_n_qlfy ),
|
||||||
|
.reset_n_out (sys_rst_n_o ),
|
||||||
|
.reset_n_status (sys_rst_n_status)
|
||||||
|
);
|
||||||
|
|
||||||
|
assign sys_rst_n_in = sys_reset_n & ndm_rst_n_i & rst_n_sync;
|
||||||
|
|
||||||
|
scr1_data_sync_cell #(
|
||||||
|
.STAGES_AMOUNT (SCR1_SCU_RST_SYNC_STAGES_NUM)
|
||||||
|
) i_sys_rstn_status_sync (
|
||||||
|
.rst_n (pwrup_rst_n_sync ),
|
||||||
|
.clk (clk ),
|
||||||
|
.data_in (sys_rst_n_status ),
|
||||||
|
.data_out (sys_rst_n_status_sync)
|
||||||
|
);
|
||||||
|
|
||||||
|
assign sys_rst_status_o = ~sys_rst_n_status_sync;
|
||||||
|
|
||||||
|
// System/Cluster-to-ExternalSOC RDC qualifier
|
||||||
|
assign sys_rdc_qlfy_o = sys_rst_n_qlfy;
|
||||||
|
|
||||||
|
// Core Reset: core_rst_n_o
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
scr1_reset_qlfy_adapter_cell_sync i_core_rstn_qlfy_adapter_cell_sync (
|
||||||
|
.rst_n (pwrup_rst_n_sync ),
|
||||||
|
.clk (clk ),
|
||||||
|
.test_rst_n (test_rst_n ),
|
||||||
|
.test_mode (test_mode ),
|
||||||
|
.reset_n_in_sync (core_rst_n_in_sync),
|
||||||
|
.reset_n_out_qlfy (core_rst_n_qlfy ),
|
||||||
|
.reset_n_out (core_rst_n_o ),
|
||||||
|
.reset_n_status (core_rst_n_status )
|
||||||
|
);
|
||||||
|
|
||||||
|
assign core_rst_n_in_sync = sys_rst_n_in & hart_rst_n_i & core_reset_n & cpu_rst_n_sync;
|
||||||
|
|
||||||
|
scr1_data_sync_cell #(
|
||||||
|
.STAGES_AMOUNT (SCR1_SCU_RST_SYNC_STAGES_NUM)
|
||||||
|
) i_core_rstn_status_sync (
|
||||||
|
.rst_n (pwrup_rst_n_sync ),
|
||||||
|
.clk (clk ),
|
||||||
|
.data_in (core_rst_n_status ),
|
||||||
|
.data_out (core_rst_n_status_sync)
|
||||||
|
);
|
||||||
|
|
||||||
|
assign core_rst_status_o = ~core_rst_n_status_sync;
|
||||||
|
|
||||||
|
// Core Reset RDC Qualifiers:
|
||||||
|
// - Core-to-ExternalSOC RDC Qlfy
|
||||||
|
assign core_rdc_qlfy_o = core_rst_n_qlfy;
|
||||||
|
// - Core-to-HDU RDC Qlfy
|
||||||
|
assign core2hdu_rdc_qlfy_o = core_rst_n_qlfy;
|
||||||
|
// - Core-to-DebugModule RDC Qlfy
|
||||||
|
assign core2dm_rdc_qlfy_o = core_rst_n_qlfy;
|
||||||
|
|
||||||
|
// Hart Debug Unit Reset: hdu_rst_n_o
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
scr1_reset_qlfy_adapter_cell_sync i_hdu_rstn_qlfy_adapter_cell_sync (
|
||||||
|
.rst_n (pwrup_rst_n_sync ),
|
||||||
|
.clk (clk ),
|
||||||
|
.test_rst_n (test_rst_n ),
|
||||||
|
.test_mode (test_mode ),
|
||||||
|
.reset_n_in_sync (hdu_rst_n_in_sync),
|
||||||
|
.reset_n_out_qlfy (hdu_rst_n_qlfy ),
|
||||||
|
.reset_n_out (hdu_rst_n_o ),
|
||||||
|
.reset_n_status (hdu_rst_n_status )
|
||||||
|
);
|
||||||
|
|
||||||
|
assign hdu_rst_n_in_sync = scu_mode_ff.hdu_rst_bhv | core_rst_n_in_sync;
|
||||||
|
|
||||||
|
scr1_data_sync_cell #(
|
||||||
|
.STAGES_AMOUNT (SCR1_SCU_RST_SYNC_STAGES_NUM)
|
||||||
|
) i_hdu_rstn_status_sync (
|
||||||
|
.rst_n (pwrup_rst_n_sync ),
|
||||||
|
.clk (clk ),
|
||||||
|
.data_in (hdu_rst_n_status ),
|
||||||
|
.data_out (hdu_rst_n_status_sync)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Hart Debug Unit Reset RDC Qualifiers:
|
||||||
|
// - HDU-to-DebugModule RDC Qlfy
|
||||||
|
assign hdu2dm_rdc_qlfy_o = hdu_rst_n_qlfy;
|
||||||
|
|
||||||
|
// Debug Module Reset: dm_rst_n_o
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
scr1_reset_buf_cell i_dm_rstn_buf_cell (
|
||||||
|
.rst_n (pwrup_rst_n_sync),
|
||||||
|
.clk (clk ),
|
||||||
|
.test_mode (test_mode ),
|
||||||
|
.test_rst_n (test_rst_n ),
|
||||||
|
.reset_n_in (dm_rst_n_in ),
|
||||||
|
.reset_n_out (dm_rst_n_o ),
|
||||||
|
.reset_n_status (dm_rst_n_status )
|
||||||
|
);
|
||||||
|
|
||||||
|
assign dm_rst_n_in = ~scu_mode_ff.dm_rst_bhv | sys_reset_n;
|
||||||
|
|
||||||
|
`ifdef SCR1_TRGT_SIMULATION
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// Assertions
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
`ifndef VERILATOR
|
||||||
|
// Preventing some assertions to be raised at 0 sim time or in the first cycle
|
||||||
|
initial begin
|
||||||
|
$assertoff(0, scr1_scu);
|
||||||
|
repeat (2) @(posedge clk) begin end
|
||||||
|
$asserton(0, scr1_scu);
|
||||||
|
end
|
||||||
|
`endif // VERILATOR
|
||||||
|
|
||||||
|
// X checks
|
||||||
|
SCR1_SVA_SCU_RESETS_XCHECK : assert property (
|
||||||
|
@(negedge clk)
|
||||||
|
!$isunknown({pwrup_rst_n, rst_n, cpu_rst_n, ndm_rst_n_i, hart_rst_n_i})
|
||||||
|
) else $error("SCU resets error: unknown values of input resets");
|
||||||
|
|
||||||
|
// Qualifiers checks
|
||||||
|
SCR1_SVA_SCU_SYS2SOC_QLFY_CHECK : assert property (
|
||||||
|
@(negedge clk) disable iff (~pwrup_rst_n)
|
||||||
|
$fell(sys_rst_n_o) |-> $fell($past(sys_rdc_qlfy_o))
|
||||||
|
) else $error("SCU sys2soc qlfy error: qlfy wasn't raised prior to reset");
|
||||||
|
|
||||||
|
SCR1_SVA_SCU_CORE2SOC_QLFY_CHECK : assert property (
|
||||||
|
@(negedge clk) disable iff (~pwrup_rst_n)
|
||||||
|
$fell(core_rst_n_o) |-> $fell($past(core_rdc_qlfy_o))
|
||||||
|
) else $error("SCU core2soc qlfy error: qlfy wasn't raised prior to reset");
|
||||||
|
|
||||||
|
SCR1_SVA_SCU_CORE2HDU_QLFY_CHECK : assert property (
|
||||||
|
@(negedge clk) disable iff (~pwrup_rst_n)
|
||||||
|
$fell(core_rst_n_o) |-> $fell($past(core2hdu_rdc_qlfy_o))
|
||||||
|
) else $error("SCU core2hdu qlfy error: qlfy wasn't raised prior to reset");
|
||||||
|
|
||||||
|
SCR1_SVA_SCU_CORE2DM_QLFY_CHECK : assert property (
|
||||||
|
@(negedge clk) disable iff (~pwrup_rst_n)
|
||||||
|
$fell(core_rst_n_o) |-> $fell($past(core2dm_rdc_qlfy_o))
|
||||||
|
) else $error("SCU core2dm qlfy error: qlfy wasn't raised prior to reset");
|
||||||
|
|
||||||
|
SCR1_SVA_SCU_HDU2DM_QLFY_CHECK : assert property (
|
||||||
|
@(negedge clk) disable iff (~pwrup_rst_n)
|
||||||
|
$fell(hdu_rst_n_o) |-> $fell($past(hdu2dm_rdc_qlfy_o))
|
||||||
|
) else $error("SCU hdu2dm qlfy error: qlfy wasn't raised prior to reset");
|
||||||
|
|
||||||
|
`endif // SCR1_TRGT_SIMULATION
|
||||||
|
|
||||||
|
endmodule : scr1_scu
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
|
||||||
457
src_ref/core/scr1_tapc.sv
Normal file
457
src_ref/core/scr1_tapc.sv
Normal file
@@ -0,0 +1,457 @@
|
|||||||
|
/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
|
||||||
|
/// @file <scr1_tapc.sv>
|
||||||
|
/// @brief TAP Controller (TAPC)
|
||||||
|
///
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Functionality:
|
||||||
|
// - Controls TAP operation
|
||||||
|
// - Allows debugger to access TAP Data registers and DMI/SCU scan-chains via
|
||||||
|
// command written in Instruction register
|
||||||
|
//
|
||||||
|
// Structure:
|
||||||
|
// - Synchronous reset generation
|
||||||
|
// - TAPC FSM
|
||||||
|
// - TAPC Instruction Registers
|
||||||
|
// - TAPC DRs/DMI/SCU scan-chains
|
||||||
|
// - TAPC TDO enable and output Registers
|
||||||
|
// - TAPC Data Registers
|
||||||
|
// - BYPASS
|
||||||
|
// - IDCODE
|
||||||
|
// - BUILD ID
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
`include "scr1_arch_description.svh"
|
||||||
|
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
`include "scr1_tapc.svh"
|
||||||
|
`include "scr1_dm.svh"
|
||||||
|
|
||||||
|
module scr1_tapc (
|
||||||
|
// JTAG signals
|
||||||
|
input logic tapc_trst_n, // Test Reset (TRSTn)
|
||||||
|
input logic tapc_tck, // Test Clock (TCK)
|
||||||
|
input logic tapc_tms, // Test Mode Select (TMS)
|
||||||
|
input logic tapc_tdi, // Test Data Input (TDI)
|
||||||
|
output logic tapc_tdo, // Test Data Output (TDO)
|
||||||
|
output logic tapc_tdo_en, // TDO Enable, signal for TDO buffer control
|
||||||
|
|
||||||
|
// Fuses:
|
||||||
|
input logic [31:0] soc2tapc_fuse_idcode_i, // IDCODE value from fuses
|
||||||
|
|
||||||
|
// DMI/SCU scan-chains
|
||||||
|
output logic tapc2tapcsync_scu_ch_sel_o, // SCU Chain Select
|
||||||
|
output logic tapc2tapcsync_dmi_ch_sel_o, // DMI Chain Select
|
||||||
|
output logic [SCR1_DBG_DMI_CH_ID_WIDTH-1:0] tapc2tapcsync_ch_id_o, // DMI/SCU Chain Identifier
|
||||||
|
output logic tapc2tapcsync_ch_capture_o, // DMI/SCU Chain Capture
|
||||||
|
output logic tapc2tapcsync_ch_shift_o, // DMI/SCU Chain Shift
|
||||||
|
output logic tapc2tapcsync_ch_update_o, // DMI/SCU Chain Update
|
||||||
|
output logic tapc2tapcsync_ch_tdi_o, // DMI/SCU Chain TDI
|
||||||
|
input logic tapcsync2tapc_ch_tdo_i // DMI/SCU Chain TDO
|
||||||
|
);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Local Signals
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
logic trst_n_int; // Sync reset signal
|
||||||
|
|
||||||
|
// TAPC FSM signals
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type_scr1_tap_state_e tap_fsm_ff; // TAP's current state
|
||||||
|
type_scr1_tap_state_e tap_fsm_next; // TAP's next state
|
||||||
|
|
||||||
|
// Control signals
|
||||||
|
logic tap_fsm_reset;
|
||||||
|
logic tap_fsm_ir_upd;
|
||||||
|
logic tap_fsm_ir_cap;
|
||||||
|
logic tap_fsm_ir_shft;
|
||||||
|
|
||||||
|
// Registered control signals
|
||||||
|
logic tap_fsm_ir_shift_ff;
|
||||||
|
logic tap_fsm_ir_shift_next;
|
||||||
|
logic tap_fsm_dr_capture_ff;
|
||||||
|
logic tap_fsm_dr_capture_next;
|
||||||
|
logic tap_fsm_dr_shift_ff;
|
||||||
|
logic tap_fsm_dr_shift_next;
|
||||||
|
logic tap_fsm_dr_update_ff;
|
||||||
|
logic tap_fsm_dr_update_next;
|
||||||
|
|
||||||
|
// TAPC Instruction Registers signals
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
logic [SCR1_TAP_INSTRUCTION_WIDTH-1:0] tap_ir_shift_ff; // Instruction Shift Register
|
||||||
|
logic [SCR1_TAP_INSTRUCTION_WIDTH-1:0] tap_ir_shift_next; // Instruction Shift Register next value
|
||||||
|
logic [SCR1_TAP_INSTRUCTION_WIDTH-1:0] tap_ir_ff; // Instruction Register
|
||||||
|
logic [SCR1_TAP_INSTRUCTION_WIDTH-1:0] tap_ir_next; // Instruction Register next value
|
||||||
|
|
||||||
|
// TAPC Data Registers signals
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// BYPASS register
|
||||||
|
logic dr_bypass_sel;
|
||||||
|
logic dr_bypass_tdo;
|
||||||
|
|
||||||
|
// IDCODE register
|
||||||
|
logic dr_idcode_sel;
|
||||||
|
logic dr_idcode_tdo;
|
||||||
|
|
||||||
|
// BUILD ID register
|
||||||
|
logic dr_bld_id_sel;
|
||||||
|
logic dr_bld_id_tdo;
|
||||||
|
|
||||||
|
logic dr_out;
|
||||||
|
|
||||||
|
// TDO registers
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// TDO enable register
|
||||||
|
logic tdo_en_ff;
|
||||||
|
logic tdo_en_next;
|
||||||
|
|
||||||
|
// TDO output register
|
||||||
|
logic tdo_out_ff;
|
||||||
|
logic tdo_out_next;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// TAPC Synchronous Reset logic
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
always_ff @(negedge tapc_tck, negedge tapc_trst_n) begin
|
||||||
|
if (~tapc_trst_n) begin
|
||||||
|
trst_n_int <= 1'b0;
|
||||||
|
end else begin
|
||||||
|
trst_n_int <= ~tap_fsm_reset;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// TAP's FSM
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
always_ff @(posedge tapc_tck, negedge tapc_trst_n) begin
|
||||||
|
if (~tapc_trst_n) begin
|
||||||
|
tap_fsm_ff <= SCR1_TAP_STATE_RESET;
|
||||||
|
end else begin
|
||||||
|
tap_fsm_ff <= tap_fsm_next;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
case (tap_fsm_ff)
|
||||||
|
SCR1_TAP_STATE_RESET : tap_fsm_next = tapc_tms ? SCR1_TAP_STATE_RESET : SCR1_TAP_STATE_IDLE;
|
||||||
|
SCR1_TAP_STATE_IDLE : tap_fsm_next = tapc_tms ? SCR1_TAP_STATE_DR_SEL_SCAN : SCR1_TAP_STATE_IDLE;
|
||||||
|
SCR1_TAP_STATE_DR_SEL_SCAN: tap_fsm_next = tapc_tms ? SCR1_TAP_STATE_IR_SEL_SCAN : SCR1_TAP_STATE_DR_CAPTURE;
|
||||||
|
SCR1_TAP_STATE_DR_CAPTURE : tap_fsm_next = tapc_tms ? SCR1_TAP_STATE_DR_EXIT1 : SCR1_TAP_STATE_DR_SHIFT;
|
||||||
|
SCR1_TAP_STATE_DR_SHIFT : tap_fsm_next = tapc_tms ? SCR1_TAP_STATE_DR_EXIT1 : SCR1_TAP_STATE_DR_SHIFT;
|
||||||
|
SCR1_TAP_STATE_DR_EXIT1 : tap_fsm_next = tapc_tms ? SCR1_TAP_STATE_DR_UPDATE : SCR1_TAP_STATE_DR_PAUSE;
|
||||||
|
SCR1_TAP_STATE_DR_PAUSE : tap_fsm_next = tapc_tms ? SCR1_TAP_STATE_DR_EXIT2 : SCR1_TAP_STATE_DR_PAUSE;
|
||||||
|
SCR1_TAP_STATE_DR_EXIT2 : tap_fsm_next = tapc_tms ? SCR1_TAP_STATE_DR_UPDATE : SCR1_TAP_STATE_DR_SHIFT;
|
||||||
|
SCR1_TAP_STATE_DR_UPDATE : tap_fsm_next = tapc_tms ? SCR1_TAP_STATE_DR_SEL_SCAN : SCR1_TAP_STATE_IDLE;
|
||||||
|
SCR1_TAP_STATE_IR_SEL_SCAN: tap_fsm_next = tapc_tms ? SCR1_TAP_STATE_RESET : SCR1_TAP_STATE_IR_CAPTURE;
|
||||||
|
SCR1_TAP_STATE_IR_CAPTURE : tap_fsm_next = tapc_tms ? SCR1_TAP_STATE_IR_EXIT1 : SCR1_TAP_STATE_IR_SHIFT;
|
||||||
|
SCR1_TAP_STATE_IR_SHIFT : tap_fsm_next = tapc_tms ? SCR1_TAP_STATE_IR_EXIT1 : SCR1_TAP_STATE_IR_SHIFT;
|
||||||
|
SCR1_TAP_STATE_IR_EXIT1 : tap_fsm_next = tapc_tms ? SCR1_TAP_STATE_IR_UPDATE : SCR1_TAP_STATE_IR_PAUSE;
|
||||||
|
SCR1_TAP_STATE_IR_PAUSE : tap_fsm_next = tapc_tms ? SCR1_TAP_STATE_IR_EXIT2 : SCR1_TAP_STATE_IR_PAUSE;
|
||||||
|
SCR1_TAP_STATE_IR_EXIT2 : tap_fsm_next = tapc_tms ? SCR1_TAP_STATE_IR_UPDATE : SCR1_TAP_STATE_IR_SHIFT;
|
||||||
|
SCR1_TAP_STATE_IR_UPDATE : tap_fsm_next = tapc_tms ? SCR1_TAP_STATE_DR_SEL_SCAN : SCR1_TAP_STATE_IDLE;
|
||||||
|
`ifdef SCR1_XPROP_EN
|
||||||
|
default : tap_fsm_next = SCR1_TAP_STATE_XXX;
|
||||||
|
`else // SCR1_XPROP_EN
|
||||||
|
default : tap_fsm_next = tap_fsm_ff;
|
||||||
|
`endif // SCR1_XPROP_EN
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
assign tap_fsm_reset = (tap_fsm_ff == SCR1_TAP_STATE_RESET);
|
||||||
|
assign tap_fsm_ir_upd = (tap_fsm_ff == SCR1_TAP_STATE_IR_UPDATE);
|
||||||
|
assign tap_fsm_ir_cap = (tap_fsm_ff == SCR1_TAP_STATE_IR_CAPTURE);
|
||||||
|
assign tap_fsm_ir_shft = (tap_fsm_ff == SCR1_TAP_STATE_IR_SHIFT);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// TAPC Instruction Registers
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// TAPC Instruction Shift register
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
always_ff @(posedge tapc_tck, negedge tapc_trst_n) begin
|
||||||
|
if (~tapc_trst_n) begin
|
||||||
|
tap_ir_shift_ff <= '0;
|
||||||
|
end else if (~trst_n_int) begin
|
||||||
|
tap_ir_shift_ff <= '0;
|
||||||
|
end else begin
|
||||||
|
tap_ir_shift_ff <= tap_ir_shift_next;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign tap_ir_shift_next = tap_fsm_ir_cap ? {{($bits(tap_ir_shift_ff)-1){1'b0}}, 1'b1}
|
||||||
|
: tap_fsm_ir_shft ? {tapc_tdi, tap_ir_shift_ff[$left(tap_ir_shift_ff):1]}
|
||||||
|
: tap_ir_shift_ff;
|
||||||
|
|
||||||
|
// TAPC Instruction register
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
always_ff @(negedge tapc_tck, negedge tapc_trst_n) begin
|
||||||
|
if (~tapc_trst_n) begin
|
||||||
|
tap_ir_ff <= SCR1_TAP_INSTR_IDCODE;
|
||||||
|
end else if (~trst_n_int) begin
|
||||||
|
tap_ir_ff <= SCR1_TAP_INSTR_IDCODE;
|
||||||
|
end else begin
|
||||||
|
tap_ir_ff <= tap_ir_next;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign tap_ir_next = tap_fsm_ir_upd ? tap_ir_shift_ff : tap_ir_ff;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Control signals
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
always_ff @(posedge tapc_tck, negedge tapc_trst_n) begin
|
||||||
|
if (~tapc_trst_n) begin
|
||||||
|
tap_fsm_ir_shift_ff <= 1'b0;
|
||||||
|
end else if (~trst_n_int) begin
|
||||||
|
tap_fsm_ir_shift_ff <= 1'b0;
|
||||||
|
end else begin
|
||||||
|
tap_fsm_ir_shift_ff <= tap_fsm_ir_shift_next;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign tap_fsm_ir_shift_next = (tap_fsm_next == SCR1_TAP_STATE_IR_SHIFT);
|
||||||
|
|
||||||
|
always_ff @(posedge tapc_tck, negedge tapc_trst_n) begin
|
||||||
|
if (~tapc_trst_n) begin
|
||||||
|
tap_fsm_dr_capture_ff <= 1'b0;
|
||||||
|
end else if (~trst_n_int) begin
|
||||||
|
tap_fsm_dr_capture_ff <= 1'b0;
|
||||||
|
end else begin
|
||||||
|
tap_fsm_dr_capture_ff <= tap_fsm_dr_capture_next;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign tap_fsm_dr_capture_next = (tap_fsm_next == SCR1_TAP_STATE_DR_CAPTURE);
|
||||||
|
|
||||||
|
always_ff @(posedge tapc_tck, negedge tapc_trst_n) begin
|
||||||
|
if (~tapc_trst_n) begin
|
||||||
|
tap_fsm_dr_shift_ff <= 1'b0;
|
||||||
|
end else if (~trst_n_int) begin
|
||||||
|
tap_fsm_dr_shift_ff <= 1'b0;
|
||||||
|
end else begin
|
||||||
|
tap_fsm_dr_shift_ff <= tap_fsm_dr_shift_next;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign tap_fsm_dr_shift_next = (tap_fsm_next == SCR1_TAP_STATE_DR_SHIFT);
|
||||||
|
|
||||||
|
always_ff @(posedge tapc_tck, negedge tapc_trst_n) begin
|
||||||
|
if (~tapc_trst_n) begin
|
||||||
|
tap_fsm_dr_update_ff <= 1'b0;
|
||||||
|
end else if (~trst_n_int) begin
|
||||||
|
tap_fsm_dr_update_ff <= 1'b0;
|
||||||
|
end else begin
|
||||||
|
tap_fsm_dr_update_ff <= tap_fsm_dr_update_next;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign tap_fsm_dr_update_next = (tap_fsm_next == SCR1_TAP_STATE_DR_UPDATE);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// TAPC DRs/DMI/SCU scan-chains
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Consists of the following functional units:
|
||||||
|
// - Data source/destination decoder
|
||||||
|
// - DMI channel ID decoder
|
||||||
|
|
||||||
|
// - Read data multiplexer
|
||||||
|
// Data source/destination decoder
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
dr_bypass_sel = 1'b0;
|
||||||
|
dr_idcode_sel = 1'b0;
|
||||||
|
dr_bld_id_sel = 1'b0;
|
||||||
|
tapc2tapcsync_scu_ch_sel_o = 1'b0;
|
||||||
|
tapc2tapcsync_dmi_ch_sel_o = 1'b0;
|
||||||
|
case (tap_ir_ff)
|
||||||
|
SCR1_TAP_INSTR_DTMCS : tapc2tapcsync_dmi_ch_sel_o = 1'b1;
|
||||||
|
SCR1_TAP_INSTR_DMI_ACCESS: tapc2tapcsync_dmi_ch_sel_o = 1'b1;
|
||||||
|
SCR1_TAP_INSTR_IDCODE : dr_idcode_sel = 1'b1;
|
||||||
|
SCR1_TAP_INSTR_BYPASS : dr_bypass_sel = 1'b1;
|
||||||
|
SCR1_TAP_INSTR_BLD_ID : dr_bld_id_sel = 1'b1;
|
||||||
|
SCR1_TAP_INSTR_SCU_ACCESS: tapc2tapcsync_scu_ch_sel_o = 1'b1;
|
||||||
|
default : dr_bypass_sel = 1'b1;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
// DMI channel ID decoder
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
tapc2tapcsync_ch_id_o = '0;
|
||||||
|
case (tap_ir_ff)
|
||||||
|
SCR1_TAP_INSTR_DTMCS : tapc2tapcsync_ch_id_o = 'd1;
|
||||||
|
SCR1_TAP_INSTR_DMI_ACCESS: tapc2tapcsync_ch_id_o = 'd2;
|
||||||
|
default : tapc2tapcsync_ch_id_o = '0;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
// Read data multiplexer
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
dr_out = 1'b0;
|
||||||
|
case (tap_ir_ff)
|
||||||
|
SCR1_TAP_INSTR_DTMCS : dr_out = tapcsync2tapc_ch_tdo_i;
|
||||||
|
SCR1_TAP_INSTR_DMI_ACCESS: dr_out = tapcsync2tapc_ch_tdo_i;
|
||||||
|
SCR1_TAP_INSTR_IDCODE : dr_out = dr_idcode_tdo;
|
||||||
|
SCR1_TAP_INSTR_BYPASS : dr_out = dr_bypass_tdo;
|
||||||
|
SCR1_TAP_INSTR_BLD_ID : dr_out = dr_bld_id_tdo;
|
||||||
|
SCR1_TAP_INSTR_SCU_ACCESS: dr_out = tapcsync2tapc_ch_tdo_i;
|
||||||
|
default : dr_out = dr_bypass_tdo;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// TDO enable and output registers
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// TDO enable register
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
always_ff @(negedge tapc_tck, negedge tapc_trst_n) begin
|
||||||
|
if (~tapc_trst_n) begin
|
||||||
|
tdo_en_ff <= 1'b0;
|
||||||
|
end else if (~trst_n_int) begin
|
||||||
|
tdo_en_ff <= 1'b0;
|
||||||
|
end else begin
|
||||||
|
tdo_en_ff <= tdo_en_next;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign tdo_en_next = tap_fsm_dr_shift_ff | tap_fsm_ir_shift_ff;
|
||||||
|
|
||||||
|
// TDO output register
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
always_ff @(negedge tapc_tck, negedge tapc_trst_n) begin
|
||||||
|
if (~tapc_trst_n) begin
|
||||||
|
tdo_out_ff <= 1'b0;
|
||||||
|
end else if (~trst_n_int) begin
|
||||||
|
tdo_out_ff <= 1'b0;
|
||||||
|
end else begin
|
||||||
|
tdo_out_ff <= tdo_out_next;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign tdo_out_next = tap_fsm_dr_shift_ff ? dr_out
|
||||||
|
: tap_fsm_ir_shift_ff ? tap_ir_shift_ff[0]
|
||||||
|
: 1'b0;
|
||||||
|
|
||||||
|
// TAPC TDO signals
|
||||||
|
assign tapc_tdo_en = tdo_en_ff;
|
||||||
|
assign tapc_tdo = tdo_out_ff;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// TAPC Data Registers
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Registers:
|
||||||
|
// - BYPASS register
|
||||||
|
// - IDCODE register
|
||||||
|
// - BUILD ID register
|
||||||
|
|
||||||
|
// BYPASS register
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// 1-bit mandatory IEEE 1149.1 compliant register
|
||||||
|
|
||||||
|
scr1_tapc_shift_reg #(
|
||||||
|
.SCR1_WIDTH (SCR1_TAP_DR_BYPASS_WIDTH),
|
||||||
|
.SCR1_RESET_VALUE (SCR1_TAP_DR_BYPASS_WIDTH'(0))
|
||||||
|
) i_bypass_reg (
|
||||||
|
.clk (tapc_tck ),
|
||||||
|
.rst_n (tapc_trst_n ),
|
||||||
|
.rst_n_sync (trst_n_int ),
|
||||||
|
.fsm_dr_select (dr_bypass_sel ),
|
||||||
|
.fsm_dr_capture (tap_fsm_dr_capture_ff),
|
||||||
|
.fsm_dr_shift (tap_fsm_dr_shift_ff ),
|
||||||
|
.din_serial (tapc_tdi ),
|
||||||
|
.din_parallel (1'b0 ),
|
||||||
|
.dout_serial (dr_bypass_tdo ),
|
||||||
|
.dout_parallel ( )
|
||||||
|
);
|
||||||
|
|
||||||
|
// IDCODE register
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Holds the Device ID value (mandatory IEEE 1149.1 compliant register)
|
||||||
|
|
||||||
|
scr1_tapc_shift_reg #(
|
||||||
|
.SCR1_WIDTH (SCR1_TAP_DR_IDCODE_WIDTH),
|
||||||
|
.SCR1_RESET_VALUE (SCR1_TAP_DR_IDCODE_WIDTH'(0))
|
||||||
|
) i_tap_idcode_reg (
|
||||||
|
.clk (tapc_tck ),
|
||||||
|
.rst_n (tapc_trst_n ),
|
||||||
|
.rst_n_sync (trst_n_int ),
|
||||||
|
.fsm_dr_select (dr_idcode_sel ),
|
||||||
|
.fsm_dr_capture (tap_fsm_dr_capture_ff ),
|
||||||
|
.fsm_dr_shift (tap_fsm_dr_shift_ff ),
|
||||||
|
.din_serial (tapc_tdi ),
|
||||||
|
.din_parallel (soc2tapc_fuse_idcode_i),
|
||||||
|
.dout_serial (dr_idcode_tdo ),
|
||||||
|
.dout_parallel ( )
|
||||||
|
);
|
||||||
|
|
||||||
|
// BUILD ID register
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Holds the BUILD ID value
|
||||||
|
|
||||||
|
scr1_tapc_shift_reg #(
|
||||||
|
.SCR1_WIDTH (SCR1_TAP_DR_BLD_ID_WIDTH),
|
||||||
|
.SCR1_RESET_VALUE (SCR1_TAP_DR_BLD_ID_WIDTH'(0))
|
||||||
|
) i_tap_dr_bld_id_reg (
|
||||||
|
.clk (tapc_tck ),
|
||||||
|
.rst_n (tapc_trst_n ),
|
||||||
|
.rst_n_sync (trst_n_int ),
|
||||||
|
.fsm_dr_select (dr_bld_id_sel ),
|
||||||
|
.fsm_dr_capture (tap_fsm_dr_capture_ff),
|
||||||
|
.fsm_dr_shift (tap_fsm_dr_shift_ff ),
|
||||||
|
.din_serial (tapc_tdi ),
|
||||||
|
.din_parallel (SCR1_TAP_BLD_ID_VALUE),
|
||||||
|
.dout_serial (dr_bld_id_tdo ),
|
||||||
|
.dout_parallel ( )
|
||||||
|
);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// DMI/SCU scan-chains signals
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
assign tapc2tapcsync_ch_tdi_o = tapc_tdi;
|
||||||
|
assign tapc2tapcsync_ch_capture_o = tap_fsm_dr_capture_ff;
|
||||||
|
assign tapc2tapcsync_ch_shift_o = tap_fsm_dr_shift_ff;
|
||||||
|
assign tapc2tapcsync_ch_update_o = tap_fsm_dr_update_ff;
|
||||||
|
|
||||||
|
`ifdef SCR1_TRGT_SIMULATION
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Assertion
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// X checks
|
||||||
|
SCR1_SVA_TAPC_XCHECK : assert property (
|
||||||
|
@(posedge tapc_tck) disable iff (~tapc_trst_n)
|
||||||
|
!$isunknown({tapc_tms, tapc_tdi})
|
||||||
|
) else $error("TAPC error: unknown values");
|
||||||
|
|
||||||
|
SCR1_SVA_TAPC_XCHECK_NEGCLK : assert property (
|
||||||
|
@(negedge tapc_tck) disable iff (tap_fsm_ff != SCR1_TAP_STATE_DR_SHIFT)
|
||||||
|
!$isunknown({tapcsync2tapc_ch_tdo_i})
|
||||||
|
) else $error("TAPC @negedge error: unknown values");
|
||||||
|
|
||||||
|
`endif // SCR1_TRGT_SIMULATION
|
||||||
|
|
||||||
|
endmodule : scr1_tapc
|
||||||
|
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
112
src_ref/core/scr1_tapc_shift_reg.sv
Normal file
112
src_ref/core/scr1_tapc_shift_reg.sv
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
|
||||||
|
/// @file <scr1_tapc_shift_reg.sv>
|
||||||
|
/// @brief TAPC shift register. Parameterized implementation of JTAG TAPC's Shift Register.
|
||||||
|
///
|
||||||
|
|
||||||
|
`include "scr1_arch_description.svh"
|
||||||
|
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
module scr1_tapc_shift_reg #(
|
||||||
|
parameter int unsigned SCR1_WIDTH = 8, // Register width, bits
|
||||||
|
parameter logic [SCR1_WIDTH-1:0] SCR1_RESET_VALUE = '0 // Register's value after reset
|
||||||
|
) (
|
||||||
|
input logic clk, // Clock
|
||||||
|
input logic rst_n, // Async reset
|
||||||
|
input logic rst_n_sync, // Sync reset
|
||||||
|
// TAP FSM's control signals:
|
||||||
|
input logic fsm_dr_select, // - for this DR selection (operation enabling);
|
||||||
|
input logic fsm_dr_capture, // - to capture parallel input's data into shift register;
|
||||||
|
input logic fsm_dr_shift, // - to enable data shifting;
|
||||||
|
// Inputs:
|
||||||
|
input logic din_serial, // - serial (shift_reg[msb/SCR1_WIDTH]);
|
||||||
|
input logic [SCR1_WIDTH-1:0] din_parallel, // - parallel (shift register's input).
|
||||||
|
// Outputs:
|
||||||
|
output logic dout_serial, // - serial (shift_reg[0]);
|
||||||
|
output logic [SCR1_WIDTH-1:0] dout_parallel // - parallel (shift register's output).
|
||||||
|
);
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Local signals declaration
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
logic [SCR1_WIDTH-1:0] shift_reg;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Shift register
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
generate
|
||||||
|
if (SCR1_WIDTH > 1)
|
||||||
|
begin : dr_shift_reg
|
||||||
|
|
||||||
|
always_ff @(posedge clk, negedge rst_n)
|
||||||
|
begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
shift_reg <= SCR1_RESET_VALUE;
|
||||||
|
end
|
||||||
|
else if (~rst_n_sync) begin
|
||||||
|
shift_reg <= SCR1_RESET_VALUE;
|
||||||
|
end
|
||||||
|
else if (fsm_dr_select & fsm_dr_capture) begin
|
||||||
|
shift_reg <= din_parallel;
|
||||||
|
end
|
||||||
|
else if (fsm_dr_select & fsm_dr_shift) begin
|
||||||
|
shift_reg <= {din_serial, shift_reg[SCR1_WIDTH-1:1]};
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
else begin : dr_shift_reg
|
||||||
|
|
||||||
|
always_ff @(posedge clk, negedge rst_n)
|
||||||
|
begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
shift_reg <= SCR1_RESET_VALUE;
|
||||||
|
end
|
||||||
|
else if (~rst_n_sync) begin
|
||||||
|
shift_reg <= SCR1_RESET_VALUE;
|
||||||
|
end
|
||||||
|
else if (fsm_dr_select & fsm_dr_capture) begin
|
||||||
|
shift_reg <= din_parallel;
|
||||||
|
end
|
||||||
|
else if (fsm_dr_select & fsm_dr_shift) begin
|
||||||
|
shift_reg <= din_serial;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Parallel output
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
assign dout_parallel = shift_reg;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Serial output
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
assign dout_serial = shift_reg[0];
|
||||||
|
|
||||||
|
`ifdef SCR1_TRGT_SIMULATION
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Assertion
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// X checks
|
||||||
|
SCR1_SVA_TAPC_SHIFTREG_XCHECK : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
!$isunknown({
|
||||||
|
rst_n_sync,
|
||||||
|
fsm_dr_select,
|
||||||
|
fsm_dr_capture,
|
||||||
|
fsm_dr_shift,
|
||||||
|
din_serial,
|
||||||
|
din_parallel
|
||||||
|
})
|
||||||
|
) else begin
|
||||||
|
$error("TAPC Shift Reg error: unknown values");
|
||||||
|
end
|
||||||
|
|
||||||
|
`endif // SCR1_TRGT_SIMULATION
|
||||||
|
|
||||||
|
endmodule : scr1_tapc_shift_reg
|
||||||
|
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
183
src_ref/core/scr1_tapc_synchronizer.sv
Normal file
183
src_ref/core/scr1_tapc_synchronizer.sv
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
|
||||||
|
/// @file <scr1_tapc_synchronizer.sv>
|
||||||
|
/// @brief TAPC clock domain crossing synchronizer
|
||||||
|
///
|
||||||
|
|
||||||
|
`include "scr1_arch_description.svh"
|
||||||
|
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
`include "scr1_tapc.svh"
|
||||||
|
`include "scr1_dm.svh"
|
||||||
|
|
||||||
|
module scr1_tapc_synchronizer (
|
||||||
|
// System common signals
|
||||||
|
input logic pwrup_rst_n, // Power-Up Reset
|
||||||
|
input logic dm_rst_n, // Debug Module Reset
|
||||||
|
input logic clk, // System Clock (SysCLK)
|
||||||
|
|
||||||
|
// JTAG common signals
|
||||||
|
input logic tapc_trst_n, // JTAG Test Reset (TRSTn)
|
||||||
|
input logic tapc_tck, // JTAG Test Clock (TCK)
|
||||||
|
|
||||||
|
|
||||||
|
// DMI/SCU scan-chains
|
||||||
|
input logic tapc2tapcsync_scu_ch_sel_i, // SCU Chain Select input (TCK domain)
|
||||||
|
output logic tapcsync2scu_ch_sel_o, // SCU Chain Select output (SysCLK domain)
|
||||||
|
input logic tapc2tapcsync_dmi_ch_sel_i, // DMI Chain Select input (TCK domain)
|
||||||
|
output logic tapcsync2dmi_ch_sel_o, // DMI Chain Select output (SysCLK domain)
|
||||||
|
|
||||||
|
input logic [SCR1_DBG_DMI_CH_ID_WIDTH-1:0] tapc2tapcsync_ch_id_i, // DMI/SCU Chain Identifier input (TCK domain)
|
||||||
|
output logic [SCR1_DBG_DMI_CH_ID_WIDTH-1:0] tapcsync2core_ch_id_o, // DMI/SCU Chain Identifier output (SysCLK domain)
|
||||||
|
|
||||||
|
input logic tapc2tapcsync_ch_capture_i, // DMI/SCU Chain Capture input (TCK domain)
|
||||||
|
output logic tapcsync2core_ch_capture_o, // DMI/SCU Chain Capture output (SysCLK domain)
|
||||||
|
|
||||||
|
input logic tapc2tapcsync_ch_shift_i, // DMI/SCU Chain Shift input (TCK domain)
|
||||||
|
output logic tapcsync2core_ch_shift_o, // DMI/SCU Chain Shift output (SysCLK domain)
|
||||||
|
|
||||||
|
input logic tapc2tapcsync_ch_update_i, // DMI/SCU Chain Update input (TCK domain)
|
||||||
|
output logic tapcsync2core_ch_update_o, // DMI/SCU Chain Update output (SysCLK domain)
|
||||||
|
|
||||||
|
input logic tapc2tapcsync_ch_tdi_i, // DMI/SCU Chain TDI input (TCK domain)
|
||||||
|
output logic tapcsync2core_ch_tdi_o, // DMI/SCU Chain TDI output (SysCLK domain)
|
||||||
|
|
||||||
|
output logic tapc2tapcsync_ch_tdo_i, // DMI/SCU Chain TDO output (TCK domain)
|
||||||
|
input logic tapcsync2core_ch_tdo_o // DMI/SCU Chain TDO input (SysCLK domain)
|
||||||
|
);
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Local signals declaration
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
logic tck_divpos;
|
||||||
|
logic tck_divneg;
|
||||||
|
logic tck_rise_load;
|
||||||
|
logic tck_rise_reset;
|
||||||
|
logic tck_fall_load;
|
||||||
|
logic tck_fall_reset;
|
||||||
|
logic [3:0] tck_divpos_sync;
|
||||||
|
logic [3:0] tck_divneg_sync;
|
||||||
|
logic [2:0] dmi_ch_capture_sync;
|
||||||
|
logic [2:0] dmi_ch_shift_sync;
|
||||||
|
logic [2:0] dmi_ch_tdi_sync;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Logic
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
always_ff @(posedge tapc_tck, negedge tapc_trst_n) begin
|
||||||
|
if (~tapc_trst_n) begin
|
||||||
|
tck_divpos <= 1'b0;
|
||||||
|
end else begin
|
||||||
|
tck_divpos <= ~tck_divpos;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_ff @(negedge tapc_tck, negedge tapc_trst_n) begin
|
||||||
|
if (~tapc_trst_n) begin
|
||||||
|
tck_divneg <= 1'b0;
|
||||||
|
end else begin
|
||||||
|
tck_divneg <= ~tck_divneg;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_ff @(posedge clk, negedge pwrup_rst_n) begin
|
||||||
|
if (~pwrup_rst_n) begin
|
||||||
|
tck_divpos_sync <= 4'd0;
|
||||||
|
tck_divneg_sync <= 4'd0;
|
||||||
|
end else begin
|
||||||
|
tck_divpos_sync <= {tck_divpos_sync[2:0], tck_divpos};
|
||||||
|
tck_divneg_sync <= {tck_divneg_sync[2:0], tck_divneg};
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign tck_rise_load = tck_divpos_sync[2] ^ tck_divpos_sync[1];
|
||||||
|
assign tck_rise_reset = tck_divpos_sync[3] ^ tck_divpos_sync[2];
|
||||||
|
assign tck_fall_load = tck_divneg_sync[2] ^ tck_divneg_sync[1];
|
||||||
|
assign tck_fall_reset = tck_divneg_sync[3] ^ tck_divneg_sync[2];
|
||||||
|
|
||||||
|
always_ff @(posedge clk, negedge pwrup_rst_n) begin
|
||||||
|
if (~pwrup_rst_n) begin
|
||||||
|
tapcsync2core_ch_update_o <= '0;
|
||||||
|
end else begin
|
||||||
|
if (tck_fall_load) begin
|
||||||
|
tapcsync2core_ch_update_o <= tapc2tapcsync_ch_update_i;
|
||||||
|
end else if (tck_fall_reset) begin
|
||||||
|
tapcsync2core_ch_update_o <= '0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_ff @(negedge tapc_tck, negedge tapc_trst_n) begin
|
||||||
|
if (~tapc_trst_n) begin
|
||||||
|
dmi_ch_capture_sync[0] <= '0;
|
||||||
|
dmi_ch_shift_sync[0] <= '0;
|
||||||
|
end else begin
|
||||||
|
dmi_ch_capture_sync[0] <= tapc2tapcsync_ch_capture_i;
|
||||||
|
dmi_ch_shift_sync[0] <= tapc2tapcsync_ch_shift_i;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_ff @(posedge clk, negedge pwrup_rst_n) begin
|
||||||
|
if (~pwrup_rst_n) begin
|
||||||
|
dmi_ch_capture_sync[2:1] <= '0;
|
||||||
|
dmi_ch_shift_sync[2:1] <= '0;
|
||||||
|
end else begin
|
||||||
|
dmi_ch_capture_sync[2:1] <= {dmi_ch_capture_sync[1], dmi_ch_capture_sync[0]};
|
||||||
|
dmi_ch_shift_sync[2:1] <= {dmi_ch_shift_sync[1], dmi_ch_shift_sync[0]};
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_ff @(posedge clk, negedge pwrup_rst_n) begin
|
||||||
|
if (~pwrup_rst_n) begin
|
||||||
|
dmi_ch_tdi_sync <= '0;
|
||||||
|
end else begin
|
||||||
|
dmi_ch_tdi_sync <= {dmi_ch_tdi_sync[1:0], tapc2tapcsync_ch_tdi_i};
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_ff @(posedge clk, negedge pwrup_rst_n) begin
|
||||||
|
if (~pwrup_rst_n) begin
|
||||||
|
tapcsync2core_ch_capture_o <= '0;
|
||||||
|
tapcsync2core_ch_shift_o <= '0;
|
||||||
|
tapcsync2core_ch_tdi_o <= '0;
|
||||||
|
end else begin
|
||||||
|
if (tck_rise_load) begin
|
||||||
|
tapcsync2core_ch_capture_o <= dmi_ch_capture_sync[2];
|
||||||
|
tapcsync2core_ch_shift_o <= dmi_ch_shift_sync[2];
|
||||||
|
tapcsync2core_ch_tdi_o <= dmi_ch_tdi_sync[2];
|
||||||
|
end else if (tck_rise_reset) begin
|
||||||
|
tapcsync2core_ch_capture_o <= '0;
|
||||||
|
tapcsync2core_ch_shift_o <= '0;
|
||||||
|
tapcsync2core_ch_tdi_o <= '0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_ff @(posedge clk, negedge dm_rst_n) begin
|
||||||
|
if (~dm_rst_n) begin
|
||||||
|
tapcsync2dmi_ch_sel_o <= '0;
|
||||||
|
tapcsync2core_ch_id_o <= '0;
|
||||||
|
end else begin
|
||||||
|
if (tck_rise_load) begin
|
||||||
|
tapcsync2dmi_ch_sel_o <= tapc2tapcsync_dmi_ch_sel_i;
|
||||||
|
tapcsync2core_ch_id_o <= tapc2tapcsync_ch_id_i;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_ff @(posedge clk, negedge pwrup_rst_n) begin
|
||||||
|
if (~pwrup_rst_n) begin
|
||||||
|
tapcsync2scu_ch_sel_o <= '0;
|
||||||
|
end else begin
|
||||||
|
if (tck_rise_load) begin
|
||||||
|
tapcsync2scu_ch_sel_o <= tapc2tapcsync_scu_ch_sel_i;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign tapc2tapcsync_ch_tdo_i = tapcsync2core_ch_tdo_o;
|
||||||
|
|
||||||
|
endmodule : scr1_tapc_synchronizer
|
||||||
|
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
59
src_ref/includes/scr1_ahb.svh
Normal file
59
src_ref/includes/scr1_ahb.svh
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
|
||||||
|
/// @file <scr1_ahb.svh>
|
||||||
|
/// @brief AHB header file
|
||||||
|
///
|
||||||
|
|
||||||
|
`ifndef SCR1_AHB_SVH
|
||||||
|
`define SCR1_AHB_SVH
|
||||||
|
|
||||||
|
`include "scr1_arch_description.svh"
|
||||||
|
|
||||||
|
parameter SCR1_AHB_WIDTH = 32;
|
||||||
|
|
||||||
|
// Encoding for HTRANS signal
|
||||||
|
parameter logic [1:0] SCR1_HTRANS_IDLE = 2'b00;
|
||||||
|
parameter logic [1:0] SCR1_HTRANS_NONSEQ = 2'b10;
|
||||||
|
`ifdef SCR1_XPROP_EN
|
||||||
|
parameter logic [1:0] SCR1_HTRANS_ERR = 'x;
|
||||||
|
`else // SCR1_XPROP_EN
|
||||||
|
parameter logic [1:0] SCR1_HTRANS_ERR = '0;
|
||||||
|
`endif // SCR1_XPROP_EN
|
||||||
|
|
||||||
|
// Encoding for HBURST signal
|
||||||
|
parameter logic [2:0] SCR1_HBURST_SINGLE = 3'b000;
|
||||||
|
`ifdef SCR1_XPROP_EN
|
||||||
|
parameter logic [2:0] SCR1_HBURST_ERR = 'x;
|
||||||
|
`else // SCR1_XPROP_EN
|
||||||
|
parameter logic [1:0] SCR1_HBURST_ERR = '0;
|
||||||
|
`endif // SCR1_XPROP_EN
|
||||||
|
|
||||||
|
// Encoding for HSIZE signal
|
||||||
|
parameter logic [2:0] SCR1_HSIZE_8B = 3'b000;
|
||||||
|
parameter logic [2:0] SCR1_HSIZE_16B = 3'b001;
|
||||||
|
parameter logic [2:0] SCR1_HSIZE_32B = 3'b010;
|
||||||
|
`ifdef SCR1_XPROP_EN
|
||||||
|
parameter logic [2:0] SCR1_HSIZE_ERR = 'x;
|
||||||
|
`else // SCR1_XPROP_EN
|
||||||
|
parameter logic [2:0] SCR1_HSIZE_ERR = '0;
|
||||||
|
`endif // SCR1_XPROP_EN
|
||||||
|
|
||||||
|
// Encoding HPROT signal
|
||||||
|
// HPROT[0] : 0 - instr; 1 - data
|
||||||
|
// HPROT[1] : 0 - user; 1 - privilege
|
||||||
|
// HPROT[2] : 0 - not buffer; 1 - buffer
|
||||||
|
// HPROT[3] : 0 - cacheable; 1 - cacheable
|
||||||
|
parameter SCR1_HPROT_DATA = 0;
|
||||||
|
parameter SCR1_HPROT_PRV = 1;
|
||||||
|
parameter SCR1_HPROT_BUF = 2;
|
||||||
|
parameter SCR1_HPROT_CACHE = 3;
|
||||||
|
|
||||||
|
// Encoding HRESP signal
|
||||||
|
parameter logic SCR1_HRESP_OKAY = 1'b0;
|
||||||
|
parameter logic SCR1_HRESP_ERROR = 1'b1;
|
||||||
|
`ifdef SCR1_XPROP_EN
|
||||||
|
parameter logic SCR1_HRESP_ERR = 1'bx;
|
||||||
|
`else // SCR1_XPROP_EN
|
||||||
|
parameter logic SCR1_HRESP_ERR = 1'b0;
|
||||||
|
`endif // SCR1_XPROP_EN
|
||||||
|
|
||||||
|
`endif // SCR1_AHB_SVH
|
||||||
72
src_ref/includes/scr1_arch_types.svh
Normal file
72
src_ref/includes/scr1_arch_types.svh
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
|
||||||
|
/// @file <scr1_arch_types.svh>
|
||||||
|
/// @brief Pipeline types description file
|
||||||
|
///
|
||||||
|
|
||||||
|
`ifndef SCR1_ARCH_TYPES_SVH
|
||||||
|
`define SCR1_ARCH_TYPES_SVH
|
||||||
|
|
||||||
|
`include "scr1_arch_description.svh"
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// MPRF and CSR parameters
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
`ifdef SCR1_RVE_EXT
|
||||||
|
`define SCR1_MPRF_AWIDTH 4
|
||||||
|
`define SCR1_MPRF_SIZE 16
|
||||||
|
`else // SCR1_RVE_EXT
|
||||||
|
`define SCR1_MPRF_AWIDTH 5
|
||||||
|
`define SCR1_MPRF_SIZE 32
|
||||||
|
`endif // SCR1_RVE_EXT
|
||||||
|
|
||||||
|
typedef logic [`SCR1_XLEN-1:0] type_scr1_mprf_v;
|
||||||
|
typedef logic [`SCR1_XLEN-1:0] type_scr1_pc_v;
|
||||||
|
|
||||||
|
parameter int unsigned SCR1_CSR_ADDR_WIDTH = 12;
|
||||||
|
parameter int unsigned SCR1_CSR_MTVEC_BASE_ZERO_BITS = 6;
|
||||||
|
parameter int unsigned SCR1_CSR_MTVEC_BASE_VAL_BITS = `SCR1_XLEN-SCR1_CSR_MTVEC_BASE_ZERO_BITS;
|
||||||
|
parameter bit [`SCR1_XLEN-1:SCR1_CSR_MTVEC_BASE_ZERO_BITS] SCR1_CSR_MTVEC_BASE_WR_RST_VAL =
|
||||||
|
SCR1_CSR_MTVEC_BASE_VAL_BITS'(SCR1_ARCH_MTVEC_BASE >> SCR1_CSR_MTVEC_BASE_ZERO_BITS);
|
||||||
|
parameter int unsigned SCR1_CSR_MTVEC_BASE_RO_BITS = (`SCR1_XLEN-(SCR1_CSR_MTVEC_BASE_ZERO_BITS+SCR1_MTVEC_BASE_WR_BITS));
|
||||||
|
|
||||||
|
`define SCR1_MTVAL_ILLEGAL_INSTR_EN
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Exception and IRQ codes
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
parameter int unsigned SCR1_EXC_CODE_WIDTH_E = 4;
|
||||||
|
|
||||||
|
// Exceptions
|
||||||
|
typedef enum logic [SCR1_EXC_CODE_WIDTH_E-1:0] {
|
||||||
|
SCR1_EXC_CODE_INSTR_MISALIGN = 4'd0, // from EXU
|
||||||
|
SCR1_EXC_CODE_INSTR_ACCESS_FAULT = 4'd1, // from IFU
|
||||||
|
SCR1_EXC_CODE_ILLEGAL_INSTR = 4'd2, // from IDU or CSR
|
||||||
|
SCR1_EXC_CODE_BREAKPOINT = 4'd3, // from IDU or BRKM
|
||||||
|
SCR1_EXC_CODE_LD_ADDR_MISALIGN = 4'd4, // from LSU
|
||||||
|
SCR1_EXC_CODE_LD_ACCESS_FAULT = 4'd5, // from LSU
|
||||||
|
SCR1_EXC_CODE_ST_ADDR_MISALIGN = 4'd6, // from LSU
|
||||||
|
SCR1_EXC_CODE_ST_ACCESS_FAULT = 4'd7, // from LSU
|
||||||
|
SCR1_EXC_CODE_ECALL_M = 4'd11 // from IDU
|
||||||
|
} type_scr1_exc_code_e;
|
||||||
|
|
||||||
|
// IRQs, reset
|
||||||
|
parameter bit [SCR1_EXC_CODE_WIDTH_E-1:0] SCR1_EXC_CODE_IRQ_M_SOFTWARE = 4'd3;
|
||||||
|
parameter bit [SCR1_EXC_CODE_WIDTH_E-1:0] SCR1_EXC_CODE_IRQ_M_TIMER = 4'd7;
|
||||||
|
parameter bit [SCR1_EXC_CODE_WIDTH_E-1:0] SCR1_EXC_CODE_IRQ_M_EXTERNAL = 4'd11;
|
||||||
|
parameter bit [SCR1_EXC_CODE_WIDTH_E-1:0] SCR1_EXC_CODE_RESET = 4'd0;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Operand width for BRKM
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
typedef enum logic [1:0] {
|
||||||
|
SCR1_OP_WIDTH_BYTE = 2'b00,
|
||||||
|
SCR1_OP_WIDTH_HALF = 2'b01,
|
||||||
|
SCR1_OP_WIDTH_WORD = 2'b10
|
||||||
|
`ifdef SCR1_XPROP_EN
|
||||||
|
,
|
||||||
|
SCR1_OP_WIDTH_ERROR = 'x
|
||||||
|
`endif // SCR1_XPROP_EN
|
||||||
|
} type_scr1_op_width_e;
|
||||||
|
|
||||||
|
`endif //SCR1_ARCH_TYPES_SVH
|
||||||
196
src_ref/includes/scr1_csr.svh
Normal file
196
src_ref/includes/scr1_csr.svh
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
|
||||||
|
/// @file <scr1_csr.svh>
|
||||||
|
/// @brief CSR mapping/description file
|
||||||
|
///
|
||||||
|
|
||||||
|
`ifndef SCR1_CSR_SVH
|
||||||
|
`define SCR1_CSR_SVH
|
||||||
|
|
||||||
|
`include "scr1_arch_description.svh"
|
||||||
|
`include "scr1_arch_types.svh"
|
||||||
|
`include "scr1_ipic.svh"
|
||||||
|
|
||||||
|
`ifdef SCR1_RVE_EXT
|
||||||
|
`define SCR1_CSR_REDUCED_CNT
|
||||||
|
`endif // SCR1_RVE_EXT
|
||||||
|
|
||||||
|
`ifdef SCR1_CSR_REDUCED_CNT
|
||||||
|
`undef SCR1_MCOUNTEN_EN
|
||||||
|
`endif // SCR1_CSR_REDUCED_CNT
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// CSR addresses (standard)
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Machine Information Registers (read-only)
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_MVENDORID = SCR1_CSR_ADDR_WIDTH'('hF11);
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_MARCHID = SCR1_CSR_ADDR_WIDTH'('hF12);
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_MIMPID = SCR1_CSR_ADDR_WIDTH'('hF13);
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_MHARTID = SCR1_CSR_ADDR_WIDTH'('hF14);
|
||||||
|
|
||||||
|
// Machine Trap Setup (read-write)
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_MSTATUS = SCR1_CSR_ADDR_WIDTH'('h300);
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_MISA = SCR1_CSR_ADDR_WIDTH'('h301);
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_MIE = SCR1_CSR_ADDR_WIDTH'('h304);
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_MTVEC = SCR1_CSR_ADDR_WIDTH'('h305);
|
||||||
|
|
||||||
|
// Machine Trap Handling (read-write)
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_MSCRATCH = SCR1_CSR_ADDR_WIDTH'('h340);
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_MEPC = SCR1_CSR_ADDR_WIDTH'('h341);
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_MCAUSE = SCR1_CSR_ADDR_WIDTH'('h342);
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_MTVAL = SCR1_CSR_ADDR_WIDTH'('h343);
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_MIP = SCR1_CSR_ADDR_WIDTH'('h344);
|
||||||
|
|
||||||
|
// Machine Counters/Timers (read-write)
|
||||||
|
`ifndef SCR1_CSR_REDUCED_CNT
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_MCYCLE = SCR1_CSR_ADDR_WIDTH'('hB00);
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_MINSTRET = SCR1_CSR_ADDR_WIDTH'('hB02);
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_MCYCLEH = SCR1_CSR_ADDR_WIDTH'('hB80);
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_MINSTRETH = SCR1_CSR_ADDR_WIDTH'('hB82);
|
||||||
|
`endif // SCR1_CSR_REDUCED_CNT
|
||||||
|
|
||||||
|
// Shadow Counters/Timers (read-only)
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_TIME = SCR1_CSR_ADDR_WIDTH'('hC01);
|
||||||
|
`ifndef SCR1_CSR_REDUCED_CNT
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_CYCLE = SCR1_CSR_ADDR_WIDTH'('hC00);
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_INSTRET = SCR1_CSR_ADDR_WIDTH'('hC02);
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_TIMEH = SCR1_CSR_ADDR_WIDTH'('hC81);
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_CYCLEH = SCR1_CSR_ADDR_WIDTH'('hC80);
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_INSTRETH = SCR1_CSR_ADDR_WIDTH'('hC82);
|
||||||
|
`endif // SCR1_CSR_REDUCED_CNT
|
||||||
|
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
//parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_DBGC_SCRATCH = 'h7C8;
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_HDU_MBASE = SCR1_CSR_ADDR_WIDTH'('h7B0);
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_HDU_MSPAN = SCR1_CSR_ADDR_WIDTH'('h004); // must be power of 2
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// CSR addresses (non-standard)
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
`ifdef SCR1_MCOUNTEN_EN
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_MCOUNTEN = SCR1_CSR_ADDR_WIDTH'('h7E0);
|
||||||
|
`endif // SCR1_MCOUNTEN_EN
|
||||||
|
|
||||||
|
`ifdef SCR1_TDU_EN
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_TDU_MBASE = SCR1_CSR_ADDR_WIDTH'('h7A0);
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_TDU_MSPAN = SCR1_CSR_ADDR_WIDTH'('h008); // must be power of 2
|
||||||
|
`endif // SCR1_TDU_EN
|
||||||
|
|
||||||
|
`ifdef SCR1_IPIC_EN
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_IPIC_BASE = SCR1_CSR_ADDR_WIDTH'('hBF0);
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_IPIC_CISV = (SCR1_CSR_ADDR_IPIC_BASE + SCR1_IPIC_CISV );
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_IPIC_CICSR = (SCR1_CSR_ADDR_IPIC_BASE + SCR1_IPIC_CICSR);
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_IPIC_IPR = (SCR1_CSR_ADDR_IPIC_BASE + SCR1_IPIC_IPR );
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_IPIC_ISVR = (SCR1_CSR_ADDR_IPIC_BASE + SCR1_IPIC_ISVR );
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_IPIC_EOI = (SCR1_CSR_ADDR_IPIC_BASE + SCR1_IPIC_EOI );
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_IPIC_SOI = (SCR1_CSR_ADDR_IPIC_BASE + SCR1_IPIC_SOI );
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_IPIC_IDX = (SCR1_CSR_ADDR_IPIC_BASE + SCR1_IPIC_IDX );
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_IPIC_ICSR = (SCR1_CSR_ADDR_IPIC_BASE + SCR1_IPIC_ICSR );
|
||||||
|
`endif // SCR1_IPIC_EN
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// CSR definitions
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// General
|
||||||
|
parameter bit [`SCR1_XLEN-1:0] SCR1_RST_VECTOR = SCR1_ARCH_RST_VECTOR;
|
||||||
|
|
||||||
|
// Reset values
|
||||||
|
parameter bit SCR1_CSR_MIE_MSIE_RST_VAL = 1'b0;
|
||||||
|
parameter bit SCR1_CSR_MIE_MTIE_RST_VAL = 1'b0;
|
||||||
|
parameter bit SCR1_CSR_MIE_MEIE_RST_VAL = 1'b0;
|
||||||
|
|
||||||
|
parameter bit SCR1_CSR_MIP_MSIP_RST_VAL = 1'b0;
|
||||||
|
parameter bit SCR1_CSR_MIP_MTIP_RST_VAL = 1'b0;
|
||||||
|
parameter bit SCR1_CSR_MIP_MEIP_RST_VAL = 1'b0;
|
||||||
|
|
||||||
|
parameter bit SCR1_CSR_MSTATUS_MIE_RST_VAL = 1'b0;
|
||||||
|
parameter bit SCR1_CSR_MSTATUS_MPIE_RST_VAL = 1'b1;
|
||||||
|
|
||||||
|
// MISA
|
||||||
|
`define SCR1_RVC_ENC `SCR1_XLEN'h0004
|
||||||
|
`define SCR1_RVE_ENC `SCR1_XLEN'h0010
|
||||||
|
`define SCR1_RVI_ENC `SCR1_XLEN'h0100
|
||||||
|
`define SCR1_RVM_ENC `SCR1_XLEN'h1000
|
||||||
|
parameter bit [1:0] SCR1_MISA_MXL_32 = 2'd1;
|
||||||
|
parameter bit [`SCR1_XLEN-1:0] SCR1_CSR_MISA = (SCR1_MISA_MXL_32 << (`SCR1_XLEN-2))
|
||||||
|
`ifndef SCR1_RVE_EXT
|
||||||
|
| `SCR1_RVI_ENC
|
||||||
|
`else // SCR1_RVE_EXT
|
||||||
|
| `SCR1_RVE_ENC
|
||||||
|
`endif // SCR1_RVE_EXT
|
||||||
|
`ifdef SCR1_RVC_EXT
|
||||||
|
| `SCR1_RVC_ENC
|
||||||
|
`endif // SCR1_RVC_EXT
|
||||||
|
`ifdef SCR1_RVM_EXT
|
||||||
|
| `SCR1_RVM_ENC
|
||||||
|
`endif // SCR1_RVM_EXT
|
||||||
|
;
|
||||||
|
|
||||||
|
// MVENDORID
|
||||||
|
parameter bit [`SCR1_XLEN-1:0] SCR1_CSR_MVENDORID = `SCR1_MVENDORID;
|
||||||
|
|
||||||
|
// MARCHID
|
||||||
|
parameter bit [`SCR1_XLEN-1:0] SCR1_CSR_MARCHID = `SCR1_XLEN'd8;
|
||||||
|
|
||||||
|
// MIMPID
|
||||||
|
parameter bit [`SCR1_XLEN-1:0] SCR1_CSR_MIMPID = `SCR1_MIMPID;
|
||||||
|
|
||||||
|
// MSTATUS
|
||||||
|
parameter bit [1:0] SCR1_CSR_MSTATUS_MPP = 2'b11;
|
||||||
|
parameter int unsigned SCR1_CSR_MSTATUS_MIE_OFFSET = 3;
|
||||||
|
parameter int unsigned SCR1_CSR_MSTATUS_MPIE_OFFSET = 7;
|
||||||
|
parameter int unsigned SCR1_CSR_MSTATUS_MPP_OFFSET = 11;
|
||||||
|
|
||||||
|
// MTVEC
|
||||||
|
// bits [5:0] are always zero
|
||||||
|
parameter bit [`SCR1_XLEN-1:SCR1_CSR_MTVEC_BASE_ZERO_BITS] SCR1_CSR_MTVEC_BASE_RST_VAL = SCR1_CSR_MTVEC_BASE_WR_RST_VAL;
|
||||||
|
|
||||||
|
parameter bit SCR1_CSR_MTVEC_MODE_DIRECT = 1'b0;
|
||||||
|
`ifdef SCR1_MTVEC_MODE_EN
|
||||||
|
parameter bit SCR1_CSR_MTVEC_MODE_VECTORED = 1'b1;
|
||||||
|
`endif // SCR1_MTVEC_MODE_EN
|
||||||
|
|
||||||
|
// MIE, MIP
|
||||||
|
parameter int unsigned SCR1_CSR_MIE_MSIE_OFFSET = 3;
|
||||||
|
parameter int unsigned SCR1_CSR_MIE_MTIE_OFFSET = 7;
|
||||||
|
parameter int unsigned SCR1_CSR_MIE_MEIE_OFFSET = 11;
|
||||||
|
|
||||||
|
`ifdef SCR1_MCOUNTEN_EN
|
||||||
|
// MCOUNTEN
|
||||||
|
parameter int unsigned SCR1_CSR_MCOUNTEN_CY_OFFSET = 0;
|
||||||
|
parameter int unsigned SCR1_CSR_MCOUNTEN_IR_OFFSET = 2;
|
||||||
|
`endif // SCR1_MCOUNTEN_EN
|
||||||
|
|
||||||
|
// MCAUSE
|
||||||
|
typedef logic [`SCR1_XLEN-2:0] type_scr1_csr_mcause_ec_v;
|
||||||
|
|
||||||
|
// MCYCLE, MINSTRET
|
||||||
|
`ifdef SCR1_CSR_REDUCED_CNT
|
||||||
|
parameter int unsigned SCR1_CSR_COUNTERS_WIDTH = 32;
|
||||||
|
`else // ~SCR1_CSR_REDUCED_CNT
|
||||||
|
parameter int unsigned SCR1_CSR_COUNTERS_WIDTH = 64;
|
||||||
|
`endif // ~SCR1_CSR_REDUCED_CNT
|
||||||
|
|
||||||
|
// HPM
|
||||||
|
parameter bit [6:0] SCR1_CSR_ADDR_HPMCOUNTER_MASK = 7'b1100000;
|
||||||
|
parameter bit [6:0] SCR1_CSR_ADDR_HPMCOUNTERH_MASK = 7'b1100100;
|
||||||
|
parameter bit [6:0] SCR1_CSR_ADDR_MHPMCOUNTER_MASK = 7'b1011000;
|
||||||
|
parameter bit [6:0] SCR1_CSR_ADDR_MHPMCOUNTERH_MASK = 7'b1011100;
|
||||||
|
parameter bit [6:0] SCR1_CSR_ADDR_MHPMEVENT_MASK = 7'b0011001;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Types declaration
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
typedef enum logic {
|
||||||
|
SCR1_CSR_RESP_OK,
|
||||||
|
SCR1_CSR_RESP_ER
|
||||||
|
`ifdef SCR1_XPROP_EN
|
||||||
|
,
|
||||||
|
SCR1_CSR_RESP_ERROR = 'x
|
||||||
|
`endif // SCR1_XPROP_EN
|
||||||
|
} type_scr1_csr_resp_e;
|
||||||
|
|
||||||
|
`endif // SCR1_CSR_SVH
|
||||||
141
src_ref/includes/scr1_dm.svh
Normal file
141
src_ref/includes/scr1_dm.svh
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
|
||||||
|
/// @file <scr1_dm.svh>
|
||||||
|
/// @brief Debug Module header file
|
||||||
|
///
|
||||||
|
|
||||||
|
`ifndef SCR1_INCLUDE_DM_DEFS
|
||||||
|
`define SCR1_INCLUDE_DM_DEFS
|
||||||
|
|
||||||
|
`include "scr1_arch_description.svh"
|
||||||
|
`include "scr1_hdu.svh"
|
||||||
|
`include "scr1_csr.svh"
|
||||||
|
|
||||||
|
parameter SCR1_DBG_DMI_ADDR_WIDTH = 6'd7;
|
||||||
|
parameter SCR1_DBG_DMI_DATA_WIDTH = 6'd32;
|
||||||
|
parameter SCR1_DBG_DMI_OP_WIDTH = 2'd2;
|
||||||
|
|
||||||
|
parameter SCR1_DBG_DMI_CH_ID_WIDTH = 2'd2;
|
||||||
|
parameter SCR1_DBG_DMI_DR_DTMCS_WIDTH = 6'd32;
|
||||||
|
parameter SCR1_DBG_DMI_DR_DMI_ACCESS_WIDTH = SCR1_DBG_DMI_OP_WIDTH +
|
||||||
|
SCR1_DBG_DMI_DATA_WIDTH +
|
||||||
|
SCR1_DBG_DMI_ADDR_WIDTH;
|
||||||
|
|
||||||
|
// Debug Module addresses
|
||||||
|
parameter SCR1_DBG_DATA0 = 7'h4;
|
||||||
|
parameter SCR1_DBG_DATA1 = 7'h5;
|
||||||
|
parameter SCR1_DBG_DMCONTROL = 7'h10;
|
||||||
|
parameter SCR1_DBG_DMSTATUS = 7'h11;
|
||||||
|
parameter SCR1_DBG_HARTINFO = 7'h12;
|
||||||
|
parameter SCR1_DBG_ABSTRACTCS = 7'h16;
|
||||||
|
parameter SCR1_DBG_COMMAND = 7'h17;
|
||||||
|
parameter SCR1_DBG_ABSTRACTAUTO = 7'h18;
|
||||||
|
parameter SCR1_DBG_PROGBUF0 = 7'h20;
|
||||||
|
parameter SCR1_DBG_PROGBUF1 = 7'h21;
|
||||||
|
parameter SCR1_DBG_PROGBUF2 = 7'h22;
|
||||||
|
parameter SCR1_DBG_PROGBUF3 = 7'h23;
|
||||||
|
parameter SCR1_DBG_PROGBUF4 = 7'h24;
|
||||||
|
parameter SCR1_DBG_PROGBUF5 = 7'h25;
|
||||||
|
parameter SCR1_DBG_HALTSUM0 = 7'h40;
|
||||||
|
|
||||||
|
// DMCONTROL
|
||||||
|
parameter SCR1_DBG_DMCONTROL_HALTREQ = 5'd31;
|
||||||
|
parameter SCR1_DBG_DMCONTROL_RESUMEREQ = 5'd30;
|
||||||
|
parameter SCR1_DBG_DMCONTROL_HARTRESET = 5'd29;
|
||||||
|
parameter SCR1_DBG_DMCONTROL_ACKHAVERESET = 5'd28;
|
||||||
|
parameter SCR1_DBG_DMCONTROL_RESERVEDB = 5'd27;
|
||||||
|
parameter SCR1_DBG_DMCONTROL_HASEL = 5'd26;
|
||||||
|
parameter SCR1_DBG_DMCONTROL_HARTSELLO_HI = 5'd25;
|
||||||
|
parameter SCR1_DBG_DMCONTROL_HARTSELLO_LO = 5'd16;
|
||||||
|
parameter SCR1_DBG_DMCONTROL_HARTSELHI_HI = 5'd15;
|
||||||
|
parameter SCR1_DBG_DMCONTROL_HARTSELHI_LO = 5'd6;
|
||||||
|
parameter SCR1_DBG_DMCONTROL_RESERVEDA_HI = 5'd5;
|
||||||
|
parameter SCR1_DBG_DMCONTROL_RESERVEDA_LO = 5'd2;
|
||||||
|
parameter SCR1_DBG_DMCONTROL_NDMRESET = 5'd1;
|
||||||
|
parameter SCR1_DBG_DMCONTROL_DMACTIVE = 5'd0;
|
||||||
|
|
||||||
|
// DMSTATUS
|
||||||
|
parameter SCR1_DBG_DMSTATUS_RESERVEDC_HI = 5'd31;
|
||||||
|
parameter SCR1_DBG_DMSTATUS_RESERVEDC_LO = 5'd23;
|
||||||
|
parameter SCR1_DBG_DMSTATUS_IMPEBREAK = 5'd22;
|
||||||
|
parameter SCR1_DBG_DMSTATUS_RESERVEDB_HI = 5'd21;
|
||||||
|
parameter SCR1_DBG_DMSTATUS_RESERVEDB_LO = 5'd20;
|
||||||
|
parameter SCR1_DBG_DMSTATUS_ALLHAVERESET = 5'd19;
|
||||||
|
parameter SCR1_DBG_DMSTATUS_ANYHAVERESET = 5'd18;
|
||||||
|
parameter SCR1_DBG_DMSTATUS_ALLRESUMEACK = 5'd17;
|
||||||
|
parameter SCR1_DBG_DMSTATUS_ANYRESUMEACK = 5'd16;
|
||||||
|
parameter SCR1_DBG_DMSTATUS_ALLNONEXISTENT = 5'd15;
|
||||||
|
parameter SCR1_DBG_DMSTATUS_ANYNONEXISTENT = 5'd14;
|
||||||
|
parameter SCR1_DBG_DMSTATUS_ALLUNAVAIL = 5'd13;
|
||||||
|
parameter SCR1_DBG_DMSTATUS_ANYUNAVAIL = 5'd12;
|
||||||
|
parameter SCR1_DBG_DMSTATUS_ALLRUNNING = 5'd11;
|
||||||
|
parameter SCR1_DBG_DMSTATUS_ANYRUNNING = 5'd10;
|
||||||
|
parameter SCR1_DBG_DMSTATUS_ALLHALTED = 5'd9;
|
||||||
|
parameter SCR1_DBG_DMSTATUS_ANYHALTED = 5'd8;
|
||||||
|
parameter SCR1_DBG_DMSTATUS_AUTHENTICATED = 5'd7;
|
||||||
|
parameter SCR1_DBG_DMSTATUS_AUTHBUSY = 5'd6;
|
||||||
|
parameter SCR1_DBG_DMSTATUS_RESERVEDA = 5'd5;
|
||||||
|
parameter SCR1_DBG_DMSTATUS_DEVTREEVALID = 5'd4;
|
||||||
|
parameter SCR1_DBG_DMSTATUS_VERSION_HI = 5'd3;
|
||||||
|
parameter SCR1_DBG_DMSTATUS_VERSION_LO = 5'd0;
|
||||||
|
|
||||||
|
// COMMANDS
|
||||||
|
parameter SCR1_DBG_COMMAND_TYPE_HI = 5'd31;
|
||||||
|
parameter SCR1_DBG_COMMAND_TYPE_LO = 5'd24;
|
||||||
|
parameter SCR1_DBG_COMMAND_TYPE_WDTH = SCR1_DBG_COMMAND_TYPE_HI
|
||||||
|
- SCR1_DBG_COMMAND_TYPE_LO;
|
||||||
|
|
||||||
|
parameter SCR1_DBG_COMMAND_ACCESSREG_RESERVEDB = 5'd23;
|
||||||
|
parameter SCR1_DBG_COMMAND_ACCESSREG_SIZE_HI = 5'd22;
|
||||||
|
parameter SCR1_DBG_COMMAND_ACCESSREG_SIZE_LO = 5'd20;
|
||||||
|
parameter SCR1_DBG_COMMAND_ACCESSREG_SIZE_WDTH = SCR1_DBG_COMMAND_ACCESSREG_SIZE_HI
|
||||||
|
- SCR1_DBG_COMMAND_ACCESSREG_SIZE_LO;
|
||||||
|
parameter SCR1_DBG_COMMAND_ACCESSREG_RESERVEDA = 5'd19;
|
||||||
|
parameter SCR1_DBG_COMMAND_ACCESSREG_POSTEXEC = 5'd18;
|
||||||
|
parameter SCR1_DBG_COMMAND_ACCESSREG_TRANSFER = 5'd17;
|
||||||
|
parameter SCR1_DBG_COMMAND_ACCESSREG_WRITE = 5'd16;
|
||||||
|
parameter SCR1_DBG_COMMAND_ACCESSREG_REGNO_HI = 5'd15;
|
||||||
|
parameter SCR1_DBG_COMMAND_ACCESSREG_REGNO_LO = 5'd0;
|
||||||
|
|
||||||
|
parameter SCR1_DBG_COMMAND_ACCESSMEM_AAMVIRTUAL = 5'd23;
|
||||||
|
parameter SCR1_DBG_COMMAND_ACCESSMEM_AAMSIZE_HI = 5'd22;
|
||||||
|
parameter SCR1_DBG_COMMAND_ACCESSMEM_AAMSIZE_LO = 5'd20;
|
||||||
|
parameter SCR1_DBG_COMMAND_ACCESSMEM_AAMPOSTINC = 5'd19;
|
||||||
|
parameter SCR1_DBG_COMMAND_ACCESSMEM_RESERVEDB_HI = 5'd18;
|
||||||
|
parameter SCR1_DBG_COMMAND_ACCESSMEM_RESERVEDB_LO = 5'd17;
|
||||||
|
parameter SCR1_DBG_COMMAND_ACCESSMEM_WRITE = 5'd16;
|
||||||
|
parameter SCR1_DBG_COMMAND_ACCESSMEM_RESERVEDA_HI = 5'd13;
|
||||||
|
parameter SCR1_DBG_COMMAND_ACCESSMEM_RESERVEDA_LO = 5'd0;
|
||||||
|
|
||||||
|
// ABSTRACTCS
|
||||||
|
parameter SCR1_DBG_ABSTRACTCS_RESERVEDD_HI = 5'd31;
|
||||||
|
parameter SCR1_DBG_ABSTRACTCS_RESERVEDD_LO = 5'd29;
|
||||||
|
parameter SCR1_DBG_ABSTRACTCS_PROGBUFSIZE_HI = 5'd28;
|
||||||
|
parameter SCR1_DBG_ABSTRACTCS_PROGBUFSIZE_LO = 5'd24;
|
||||||
|
parameter SCR1_DBG_ABSTRACTCS_RESERVEDC_HI = 5'd23;
|
||||||
|
parameter SCR1_DBG_ABSTRACTCS_RESERVEDC_LO = 5'd13;
|
||||||
|
parameter SCR1_DBG_ABSTRACTCS_BUSY = 5'd12;
|
||||||
|
parameter SCR1_DBG_ABSTRACTCS_RESERVEDB = 5'd11;
|
||||||
|
parameter SCR1_DBG_ABSTRACTCS_CMDERR_HI = 5'd10;
|
||||||
|
parameter SCR1_DBG_ABSTRACTCS_CMDERR_LO = 5'd8;
|
||||||
|
parameter SCR1_DBG_ABSTRACTCS_CMDERR_WDTH = SCR1_DBG_ABSTRACTCS_CMDERR_HI
|
||||||
|
- SCR1_DBG_ABSTRACTCS_CMDERR_LO;
|
||||||
|
parameter SCR1_DBG_ABSTRACTCS_RESERVEDA_HI = 5'd7;
|
||||||
|
parameter SCR1_DBG_ABSTRACTCS_RESERVEDA_LO = 5'd4;
|
||||||
|
parameter SCR1_DBG_ABSTRACTCS_DATACOUNT_HI = 5'd3;
|
||||||
|
parameter SCR1_DBG_ABSTRACTCS_DATACOUNT_LO = 5'd0;
|
||||||
|
|
||||||
|
// HARTINFO
|
||||||
|
parameter SCR1_DBG_HARTINFO_RESERVEDB_HI = 5'd31;
|
||||||
|
parameter SCR1_DBG_HARTINFO_RESERVEDB_LO = 5'd24;
|
||||||
|
parameter SCR1_DBG_HARTINFO_NSCRATCH_HI = 5'd23;
|
||||||
|
parameter SCR1_DBG_HARTINFO_NSCRATCH_LO = 5'd20;
|
||||||
|
parameter SCR1_DBG_HARTINFO_RESERVEDA_HI = 5'd19;
|
||||||
|
parameter SCR1_DBG_HARTINFO_RESERVEDA_LO = 5'd17;
|
||||||
|
parameter SCR1_DBG_HARTINFO_DATAACCESS = 5'd16;
|
||||||
|
parameter SCR1_DBG_HARTINFO_DATASIZE_HI = 5'd15;
|
||||||
|
parameter SCR1_DBG_HARTINFO_DATASIZE_LO = 5'd12;
|
||||||
|
parameter SCR1_DBG_HARTINFO_DATAADDR_HI = 5'd11;
|
||||||
|
parameter SCR1_DBG_HARTINFO_DATAADDR_LO = 5'd0;
|
||||||
|
|
||||||
|
|
||||||
|
`endif // SCR1_INCLUDE_DM_DEFS
|
||||||
165
src_ref/includes/scr1_hdu.svh
Normal file
165
src_ref/includes/scr1_hdu.svh
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
|
||||||
|
/// @file <scr1_pipe_hdu.svh>
|
||||||
|
/// @brief HART Debug Unit definitions file
|
||||||
|
///
|
||||||
|
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
`ifndef SCR1_INCLUDE_HDU_DEFS
|
||||||
|
`define SCR1_INCLUDE_HDU_DEFS
|
||||||
|
|
||||||
|
`include "scr1_arch_description.svh"
|
||||||
|
`include "scr1_csr.svh"
|
||||||
|
|
||||||
|
`ifdef SCR1_MMU_EN
|
||||||
|
`define SCR1_HDU_FEATURE_MPRVEN
|
||||||
|
`endif // SCR1_MMU_EN
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Parameters
|
||||||
|
//==============================================================================
|
||||||
|
//localparam int unsigned SCR1_HDU_DEBUGCSR_BASE_ADDR = 12'h7B0;
|
||||||
|
localparam int unsigned SCR1_HDU_DEBUGCSR_ADDR_SPAN = SCR1_CSR_ADDR_HDU_MSPAN;
|
||||||
|
localparam int unsigned SCR1_HDU_DEBUGCSR_ADDR_WIDTH = $clog2(SCR1_HDU_DEBUGCSR_ADDR_SPAN);
|
||||||
|
localparam bit [3:0] SCR1_HDU_DEBUGCSR_DCSR_XDEBUGVER = 4'h4;
|
||||||
|
localparam int unsigned SCR1_HDU_PBUF_ADDR_SPAN = 8;
|
||||||
|
localparam int unsigned SCR1_HDU_PBUF_ADDR_WIDTH = $clog2(SCR1_HDU_PBUF_ADDR_SPAN);
|
||||||
|
localparam int unsigned SCR1_HDU_DATA_REG_WIDTH = 32;
|
||||||
|
localparam int unsigned SCR1_HDU_CORE_INSTR_WIDTH = 32;
|
||||||
|
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Types
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
// HART Debug States:
|
||||||
|
typedef enum logic [1:0] {
|
||||||
|
SCR1_HDU_DBGSTATE_RESET = 2'b00,
|
||||||
|
SCR1_HDU_DBGSTATE_RUN = 2'b01,
|
||||||
|
SCR1_HDU_DBGSTATE_DHALTED = 2'b10,
|
||||||
|
SCR1_HDU_DBGSTATE_DRUN = 2'b11
|
||||||
|
`ifdef SCR1_XPROP_EN
|
||||||
|
,
|
||||||
|
SCR1_HDU_DBGSTATE_XXX = 'X
|
||||||
|
`endif // SCR1_XPROP_EN
|
||||||
|
} type_scr1_hdu_dbgstates_e;
|
||||||
|
|
||||||
|
typedef enum logic [1:0] {
|
||||||
|
SCR1_HDU_PBUFSTATE_IDLE = 2'b00,
|
||||||
|
SCR1_HDU_PBUFSTATE_FETCH = 2'b01,
|
||||||
|
SCR1_HDU_PBUFSTATE_EXCINJECT = 2'b10,
|
||||||
|
SCR1_HDU_PBUFSTATE_WAIT4END = 2'b11
|
||||||
|
`ifdef SCR1_XPROP_EN
|
||||||
|
,
|
||||||
|
SCR1_HDU_PBUFSTATE_XXX = 'X
|
||||||
|
`endif // SCR1_XPROP_EN
|
||||||
|
} type_scr1_hdu_pbufstates_e;
|
||||||
|
|
||||||
|
typedef enum logic {
|
||||||
|
SCR1_HDU_HARTCMD_RESUME = 1'b0,
|
||||||
|
SCR1_HDU_HARTCMD_HALT = 1'b1
|
||||||
|
`ifdef SCR1_XPROP_EN
|
||||||
|
,
|
||||||
|
SCR1_HDU_HARTCMD_XXX = 1'bX
|
||||||
|
`endif // SCR1_XPROP_EN
|
||||||
|
} type_scr1_hdu_hart_command_e;
|
||||||
|
|
||||||
|
typedef enum logic {
|
||||||
|
SCR1_HDU_FETCH_SRC_NORMAL = 1'b0,
|
||||||
|
SCR1_HDU_FETCH_SRC_PBUF = 1'b1
|
||||||
|
`ifdef SCR1_XPROP_EN
|
||||||
|
,
|
||||||
|
SCR1_HDU_FETCH_SRC_XXX = 1'bX
|
||||||
|
`endif // SCR1_XPROP_EN
|
||||||
|
} type_scr1_hdu_fetch_src_e;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
//logic reset_n;
|
||||||
|
logic except;
|
||||||
|
logic ebreak;
|
||||||
|
type_scr1_hdu_dbgstates_e dbg_state;
|
||||||
|
} type_scr1_hdu_hartstatus_s;
|
||||||
|
|
||||||
|
// Debug Mode Redirection control:
|
||||||
|
typedef struct packed {
|
||||||
|
logic sstep; // Single Step
|
||||||
|
logic ebreak; // Redirection after EBREAK execution
|
||||||
|
} type_scr1_hdu_redirect_s;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic irq_dsbl;
|
||||||
|
type_scr1_hdu_fetch_src_e fetch_src;
|
||||||
|
logic pc_advmt_dsbl;
|
||||||
|
logic hwbrkpt_dsbl;
|
||||||
|
type_scr1_hdu_redirect_s redirect;
|
||||||
|
} type_scr1_hdu_runctrl_s;
|
||||||
|
|
||||||
|
// HART Halt Status:
|
||||||
|
typedef enum logic [2:0] {
|
||||||
|
SCR1_HDU_HALTCAUSE_NONE = 3'b000,
|
||||||
|
SCR1_HDU_HALTCAUSE_EBREAK = 3'b001,
|
||||||
|
SCR1_HDU_HALTCAUSE_TMREQ = 3'b010,
|
||||||
|
SCR1_HDU_HALTCAUSE_DMREQ = 3'b011,
|
||||||
|
SCR1_HDU_HALTCAUSE_SSTEP = 3'b100,
|
||||||
|
SCR1_HDU_HALTCAUSE_RSTEXIT = 3'b101
|
||||||
|
`ifdef SCR1_XPROP_EN
|
||||||
|
,
|
||||||
|
SCR1_HDU_HALTCAUSE_XXX = 'X
|
||||||
|
`endif // SCR1_XPROP_EN
|
||||||
|
} type_scr1_hdu_haltcause_e;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic except;
|
||||||
|
type_scr1_hdu_haltcause_e cause;
|
||||||
|
} type_scr1_hdu_haltstatus_s;
|
||||||
|
|
||||||
|
|
||||||
|
// Debug CSR map
|
||||||
|
localparam SCR1_HDU_DBGCSR_OFFS_DCSR = SCR1_HDU_DEBUGCSR_ADDR_WIDTH'( 'd0 );
|
||||||
|
localparam SCR1_HDU_DBGCSR_OFFS_DPC = SCR1_HDU_DEBUGCSR_ADDR_WIDTH'( 'd1 );
|
||||||
|
localparam SCR1_HDU_DBGCSR_OFFS_DSCRATCH0 = SCR1_HDU_DEBUGCSR_ADDR_WIDTH'( 'd2 );
|
||||||
|
localparam SCR1_HDU_DBGCSR_OFFS_DSCRATCH1 = SCR1_HDU_DEBUGCSR_ADDR_WIDTH'( 'd3 );
|
||||||
|
|
||||||
|
localparam bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_HDU_DBGCSR_ADDR_DCSR = SCR1_CSR_ADDR_HDU_MBASE + SCR1_HDU_DBGCSR_OFFS_DCSR;
|
||||||
|
localparam bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_HDU_DBGCSR_ADDR_DPC = SCR1_CSR_ADDR_HDU_MBASE + SCR1_HDU_DBGCSR_OFFS_DPC;
|
||||||
|
localparam bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_HDU_DBGCSR_ADDR_DSCRATCH0 = SCR1_CSR_ADDR_HDU_MBASE + SCR1_HDU_DBGCSR_OFFS_DSCRATCH0;
|
||||||
|
localparam bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_HDU_DBGCSR_ADDR_DSCRATCH1 = SCR1_CSR_ADDR_HDU_MBASE + SCR1_HDU_DBGCSR_OFFS_DSCRATCH1;
|
||||||
|
|
||||||
|
// Debug CSRs :: DCSR
|
||||||
|
typedef enum int {
|
||||||
|
SCR1_HDU_DCSR_PRV_BIT_R = 0,
|
||||||
|
SCR1_HDU_DCSR_PRV_BIT_L = 1,
|
||||||
|
SCR1_HDU_DCSR_STEP_BIT = 2,
|
||||||
|
SCR1_HDU_DCSR_RSRV0_BIT_R = 3,
|
||||||
|
SCR1_HDU_DCSR_RSRV0_BIT_L = 5,
|
||||||
|
SCR1_HDU_DCSR_CAUSE_BIT_R = 6,
|
||||||
|
SCR1_HDU_DCSR_CAUSE_BIT_L = 8,
|
||||||
|
SCR1_HDU_DCSR_RSRV1_BIT_R = 9,
|
||||||
|
SCR1_HDU_DCSR_RSRV1_BIT_L = 10,
|
||||||
|
SCR1_HDU_DCSR_STEPIE_BIT = 11,
|
||||||
|
SCR1_HDU_DCSR_RSRV2_BIT_R = 12,
|
||||||
|
SCR1_HDU_DCSR_RSRV2_BIT_L = 14,
|
||||||
|
SCR1_HDU_DCSR_EBREAKM_BIT = 15,
|
||||||
|
SCR1_HDU_DCSR_RSRV3_BIT_R = 16,
|
||||||
|
SCR1_HDU_DCSR_RSRV3_BIT_L = 27,
|
||||||
|
SCR1_HDU_DCSR_XDEBUGVER_BIT_R = 28,
|
||||||
|
SCR1_HDU_DCSR_XDEBUGVER_BIT_L = 31
|
||||||
|
} type_scr1_hdu_dcsr_bits_e;
|
||||||
|
|
||||||
|
//localparam int unsigned SCR1_HDU_DEBUGCSR_DCSR_PRV_WIDTH = SCR1_HDU_DCSR_PRV_BIT_L-SCR1_HDU_DCSR_PRV_BIT_R+1;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic [SCR1_HDU_DCSR_XDEBUGVER_BIT_L-SCR1_HDU_DCSR_XDEBUGVER_BIT_R:0] xdebugver;
|
||||||
|
logic [SCR1_HDU_DCSR_RSRV3_BIT_L-SCR1_HDU_DCSR_RSRV3_BIT_R:0] rsrv3;
|
||||||
|
logic ebreakm;
|
||||||
|
logic [SCR1_HDU_DCSR_RSRV2_BIT_L-SCR1_HDU_DCSR_RSRV2_BIT_R:0] rsrv2;
|
||||||
|
logic stepie;
|
||||||
|
logic [SCR1_HDU_DCSR_RSRV1_BIT_L-SCR1_HDU_DCSR_RSRV1_BIT_R:0] rsrv1;
|
||||||
|
logic [SCR1_HDU_DCSR_CAUSE_BIT_L-SCR1_HDU_DCSR_CAUSE_BIT_R:0] cause;
|
||||||
|
logic [SCR1_HDU_DCSR_RSRV0_BIT_L-SCR1_HDU_DCSR_RSRV0_BIT_R:0] rsrv0;
|
||||||
|
logic step;
|
||||||
|
logic [SCR1_HDU_DCSR_PRV_BIT_L-SCR1_HDU_DCSR_PRV_BIT_R:0] prv;
|
||||||
|
} type_scr1_hdu_dcsr_s;
|
||||||
|
|
||||||
|
|
||||||
|
`endif // SCR1_INCLUDE_HDU_DEFS
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
58
src_ref/includes/scr1_ipic.svh
Normal file
58
src_ref/includes/scr1_ipic.svh
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
|
||||||
|
/// @file <scr1_ipic.svh>
|
||||||
|
/// @brief IPIC header file
|
||||||
|
///
|
||||||
|
|
||||||
|
`ifndef SCR1_IPIC_SVH
|
||||||
|
`define SCR1_IPIC_SVH
|
||||||
|
|
||||||
|
`include "scr1_arch_description.svh"
|
||||||
|
|
||||||
|
`ifdef SCR1_IPIC_EN
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Parameters declaration
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
parameter SCR1_IRQ_VECT_NUM = 16; // must be power of 2 in the current implementation
|
||||||
|
parameter SCR1_IRQ_VECT_WIDTH = $clog2(SCR1_IRQ_VECT_NUM+1);
|
||||||
|
parameter SCR1_IRQ_LINES_NUM = SCR1_IRQ_VECT_NUM;
|
||||||
|
parameter SCR1_IRQ_LINES_WIDTH = $clog2(SCR1_IRQ_LINES_NUM);
|
||||||
|
parameter logic [SCR1_IRQ_VECT_WIDTH-1:0] SCR1_IRQ_VOID_VECT_NUM = SCR1_IRQ_VECT_WIDTH'(SCR1_IRQ_VECT_NUM);
|
||||||
|
parameter SCR1_IRQ_IDX_WIDTH = $clog2(SCR1_IRQ_VECT_NUM);
|
||||||
|
|
||||||
|
// Address decoding parameters
|
||||||
|
parameter logic [2:0] SCR1_IPIC_CISV = 3'h0; // RO
|
||||||
|
parameter logic [2:0] SCR1_IPIC_CICSR = 3'h1; // {IP, IE}
|
||||||
|
parameter logic [2:0] SCR1_IPIC_IPR = 3'h2; // RW1C
|
||||||
|
parameter logic [2:0] SCR1_IPIC_ISVR = 3'h3; // RO
|
||||||
|
parameter logic [2:0] SCR1_IPIC_EOI = 3'h4; // RZW
|
||||||
|
parameter logic [2:0] SCR1_IPIC_SOI = 3'h5; // RZW
|
||||||
|
parameter logic [2:0] SCR1_IPIC_IDX = 3'h6; // RW
|
||||||
|
parameter logic [2:0] SCR1_IPIC_ICSR = 3'h7; // RW
|
||||||
|
|
||||||
|
parameter SCR1_IPIC_ICSR_IP = 0;
|
||||||
|
parameter SCR1_IPIC_ICSR_IE = 1;
|
||||||
|
parameter SCR1_IPIC_ICSR_IM = 2;
|
||||||
|
parameter SCR1_IPIC_ICSR_INV = 3;
|
||||||
|
parameter SCR1_IPIC_ICSR_IS = 4;
|
||||||
|
parameter SCR1_IPIC_ICSR_PRV_LSB = 8;
|
||||||
|
parameter SCR1_IPIC_ICSR_PRV_MSB = 9;
|
||||||
|
parameter SCR1_IPIC_ICSR_LN_LSB = 12;
|
||||||
|
parameter SCR1_IPIC_ICSR_LN_MSB = SCR1_IPIC_ICSR_LN_LSB
|
||||||
|
+ SCR1_IRQ_LINES_WIDTH;
|
||||||
|
|
||||||
|
parameter logic [1:0] SCR1_IPIC_PRV_M = 2'b11;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Types declaration
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
typedef enum logic {
|
||||||
|
SCR1_CSR2IPIC_RD,
|
||||||
|
SCR1_CSR2IPIC_WR
|
||||||
|
`ifdef SCR1_XPROP_EN
|
||||||
|
,
|
||||||
|
SCR1_CSR2IPIC_ERROR = 'x
|
||||||
|
`endif // SCR1_XPROP_EN
|
||||||
|
} type_scr1_csr2ipic_wr_e;
|
||||||
|
|
||||||
|
`endif // SCR1_IPIC_EN
|
||||||
|
`endif // SCR1_IPIC_SVH
|
||||||
49
src_ref/includes/scr1_memif.svh
Normal file
49
src_ref/includes/scr1_memif.svh
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
|
||||||
|
/// @file <scr1_memif.svh>
|
||||||
|
/// @brief Memory interface definitions file
|
||||||
|
///
|
||||||
|
|
||||||
|
`ifndef SCR1_MEMIF_SVH
|
||||||
|
`define SCR1_MEMIF_SVH
|
||||||
|
|
||||||
|
`include "scr1_arch_description.svh"
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Memory command enum
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
typedef enum logic {
|
||||||
|
SCR1_MEM_CMD_RD = 1'b0,
|
||||||
|
SCR1_MEM_CMD_WR = 1'b1
|
||||||
|
`ifdef SCR1_XPROP_EN
|
||||||
|
,
|
||||||
|
SCR1_MEM_CMD_ERROR = 'x
|
||||||
|
`endif // SCR1_XPROP_EN
|
||||||
|
} type_scr1_mem_cmd_e;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Memory data width enum
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
typedef enum logic[1:0] {
|
||||||
|
SCR1_MEM_WIDTH_BYTE = 2'b00,
|
||||||
|
SCR1_MEM_WIDTH_HWORD = 2'b01,
|
||||||
|
SCR1_MEM_WIDTH_WORD = 2'b10
|
||||||
|
`ifdef SCR1_XPROP_EN
|
||||||
|
,
|
||||||
|
SCR1_MEM_WIDTH_ERROR = 'x
|
||||||
|
`endif // SCR1_XPROP_EN
|
||||||
|
} type_scr1_mem_width_e;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Memory response enum
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
typedef enum logic[1:0] {
|
||||||
|
SCR1_MEM_RESP_NOTRDY = 2'b00,
|
||||||
|
SCR1_MEM_RESP_RDY_OK = 2'b01,
|
||||||
|
SCR1_MEM_RESP_RDY_ER = 2'b10
|
||||||
|
`ifdef SCR1_XPROP_EN
|
||||||
|
,
|
||||||
|
SCR1_MEM_RESP_ERROR = 'x
|
||||||
|
`endif // SCR1_XPROP_EN
|
||||||
|
} type_scr1_mem_resp_e;
|
||||||
|
|
||||||
|
`endif // SCR1_MEMIF_SVH
|
||||||
185
src_ref/includes/scr1_riscv_isa_decoding.svh
Normal file
185
src_ref/includes/scr1_riscv_isa_decoding.svh
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
|
||||||
|
/// @file <scr1_riscv_isa_decoding.svh>
|
||||||
|
/// @brief RISC-V ISA definitions file
|
||||||
|
///
|
||||||
|
|
||||||
|
`ifndef SCR1_RISCV_ISA_DECODING_SVH
|
||||||
|
`define SCR1_RISCV_ISA_DECODING_SVH
|
||||||
|
|
||||||
|
`include "scr1_arch_description.svh"
|
||||||
|
`include "scr1_arch_types.svh"
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Instruction types
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
typedef enum logic [1:0] {
|
||||||
|
SCR1_INSTR_RVC0 = 2'b00,
|
||||||
|
SCR1_INSTR_RVC1 = 2'b01,
|
||||||
|
SCR1_INSTR_RVC2 = 2'b10,
|
||||||
|
SCR1_INSTR_RVI = 2'b11
|
||||||
|
} type_scr1_instr_type_e;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// RV32I opcodes (bits 6:2)
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
typedef enum logic [6:2] {
|
||||||
|
SCR1_OPCODE_LOAD = 5'b00000,
|
||||||
|
SCR1_OPCODE_MISC_MEM = 5'b00011,
|
||||||
|
SCR1_OPCODE_OP_IMM = 5'b00100,
|
||||||
|
SCR1_OPCODE_AUIPC = 5'b00101,
|
||||||
|
SCR1_OPCODE_STORE = 5'b01000,
|
||||||
|
SCR1_OPCODE_OP = 5'b01100,
|
||||||
|
SCR1_OPCODE_LUI = 5'b01101,
|
||||||
|
SCR1_OPCODE_BRANCH = 5'b11000,
|
||||||
|
SCR1_OPCODE_JALR = 5'b11001,
|
||||||
|
SCR1_OPCODE_JAL = 5'b11011,
|
||||||
|
SCR1_OPCODE_SYSTEM = 5'b11100
|
||||||
|
} type_scr1_rvi_opcode_e;
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// IALU main operands
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
localparam SCR1_IALU_OP_ALL_NUM_E = 2;
|
||||||
|
localparam SCR1_IALU_OP_WIDTH_E = $clog2(SCR1_IALU_OP_ALL_NUM_E);
|
||||||
|
typedef enum logic [SCR1_IALU_OP_WIDTH_E-1:0] {
|
||||||
|
SCR1_IALU_OP_REG_IMM, // op1 = rs1; op2 = imm
|
||||||
|
SCR1_IALU_OP_REG_REG // op1 = rs1; op2 = rs2
|
||||||
|
} type_scr1_ialu_op_sel_e;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// IALU main commands
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
`ifdef SCR1_RVM_EXT
|
||||||
|
localparam SCR1_IALU_CMD_ALL_NUM_E = 23;
|
||||||
|
`else // ~SCR1_RVM_EXT
|
||||||
|
localparam SCR1_IALU_CMD_ALL_NUM_E = 15;
|
||||||
|
`endif // ~SCR1_RVM_EXT
|
||||||
|
localparam SCR1_IALU_CMD_WIDTH_E = $clog2(SCR1_IALU_CMD_ALL_NUM_E);
|
||||||
|
typedef enum logic [SCR1_IALU_CMD_WIDTH_E-1:0] {
|
||||||
|
SCR1_IALU_CMD_NONE = '0, // IALU disable
|
||||||
|
SCR1_IALU_CMD_AND, // op1 & op2
|
||||||
|
SCR1_IALU_CMD_OR, // op1 | op2
|
||||||
|
SCR1_IALU_CMD_XOR, // op1 ^ op2
|
||||||
|
SCR1_IALU_CMD_ADD, // op1 + op2
|
||||||
|
SCR1_IALU_CMD_SUB, // op1 - op2
|
||||||
|
SCR1_IALU_CMD_SUB_LT, // op1 < op2
|
||||||
|
SCR1_IALU_CMD_SUB_LTU, // op1 u< op2
|
||||||
|
SCR1_IALU_CMD_SUB_EQ, // op1 = op2
|
||||||
|
SCR1_IALU_CMD_SUB_NE, // op1 != op2
|
||||||
|
SCR1_IALU_CMD_SUB_GE, // op1 >= op2
|
||||||
|
SCR1_IALU_CMD_SUB_GEU, // op1 u>= op2
|
||||||
|
SCR1_IALU_CMD_SLL, // op1 << op2
|
||||||
|
SCR1_IALU_CMD_SRL, // op1 >> op2
|
||||||
|
SCR1_IALU_CMD_SRA // op1 >>> op2
|
||||||
|
`ifdef SCR1_RVM_EXT
|
||||||
|
,
|
||||||
|
SCR1_IALU_CMD_MUL, // low(unsig(op1) * unsig(op2))
|
||||||
|
SCR1_IALU_CMD_MULHU, // high(unsig(op1) * unsig(op2))
|
||||||
|
SCR1_IALU_CMD_MULHSU, // high(op1 * unsig(op2))
|
||||||
|
SCR1_IALU_CMD_MULH, // high(op1 * op2)
|
||||||
|
SCR1_IALU_CMD_DIV, // op1 / op2
|
||||||
|
SCR1_IALU_CMD_DIVU, // op1 u/ op2
|
||||||
|
SCR1_IALU_CMD_REM, // op1 % op2
|
||||||
|
SCR1_IALU_CMD_REMU // op1 u% op2
|
||||||
|
`endif // SCR1_RVM_EXT
|
||||||
|
} type_scr1_ialu_cmd_sel_e;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// IALU SUM2 operands (result is JUMP/BRANCH target, LOAD/STORE address)
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
localparam SCR1_SUM2_OP_ALL_NUM_E = 2;
|
||||||
|
localparam SCR1_SUM2_OP_WIDTH_E = $clog2(SCR1_SUM2_OP_ALL_NUM_E);
|
||||||
|
typedef enum logic [SCR1_SUM2_OP_WIDTH_E-1:0] {
|
||||||
|
SCR1_SUM2_OP_PC_IMM, // op1 = curr_pc; op2 = imm (AUIPC, target new_pc for JAL and branches)
|
||||||
|
SCR1_SUM2_OP_REG_IMM // op1 = rs1; op2 = imm (target new_pc for JALR, LOAD/STORE address)
|
||||||
|
`ifdef SCR1_XPROP_EN
|
||||||
|
,
|
||||||
|
SCR1_SUM2_OP_ERROR = 'x
|
||||||
|
`endif // SCR1_XPROP_EN
|
||||||
|
} type_scr1_ialu_sum2_op_sel_e;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// LSU commands
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
localparam SCR1_LSU_CMD_ALL_NUM_E = 9;
|
||||||
|
localparam SCR1_LSU_CMD_WIDTH_E = $clog2(SCR1_LSU_CMD_ALL_NUM_E);
|
||||||
|
typedef enum logic [SCR1_LSU_CMD_WIDTH_E-1:0] {
|
||||||
|
SCR1_LSU_CMD_NONE = '0,
|
||||||
|
SCR1_LSU_CMD_LB,
|
||||||
|
SCR1_LSU_CMD_LH,
|
||||||
|
SCR1_LSU_CMD_LW,
|
||||||
|
SCR1_LSU_CMD_LBU,
|
||||||
|
SCR1_LSU_CMD_LHU,
|
||||||
|
SCR1_LSU_CMD_SB,
|
||||||
|
SCR1_LSU_CMD_SH,
|
||||||
|
SCR1_LSU_CMD_SW
|
||||||
|
} type_scr1_lsu_cmd_sel_e;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// CSR operands
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
localparam SCR1_CSR_OP_ALL_NUM_E = 2;
|
||||||
|
localparam SCR1_CSR_OP_WIDTH_E = $clog2(SCR1_CSR_OP_ALL_NUM_E);
|
||||||
|
typedef enum logic [SCR1_CSR_OP_WIDTH_E-1:0] {
|
||||||
|
SCR1_CSR_OP_IMM,
|
||||||
|
SCR1_CSR_OP_REG
|
||||||
|
} type_scr1_csr_op_sel_e;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// CSR commands
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
localparam SCR1_CSR_CMD_ALL_NUM_E = 4;
|
||||||
|
localparam SCR1_CSR_CMD_WIDTH_E = $clog2(SCR1_CSR_CMD_ALL_NUM_E);
|
||||||
|
typedef enum logic [SCR1_CSR_CMD_WIDTH_E-1:0] {
|
||||||
|
SCR1_CSR_CMD_NONE = '0,
|
||||||
|
SCR1_CSR_CMD_WRITE,
|
||||||
|
SCR1_CSR_CMD_SET,
|
||||||
|
SCR1_CSR_CMD_CLEAR
|
||||||
|
} type_scr1_csr_cmd_sel_e;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// MPRF rd writeback source
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
localparam SCR1_RD_WB_ALL_NUM_E = 7;
|
||||||
|
localparam SCR1_RD_WB_WIDTH_E = $clog2(SCR1_RD_WB_ALL_NUM_E);
|
||||||
|
typedef enum logic [SCR1_RD_WB_WIDTH_E-1:0] {
|
||||||
|
SCR1_RD_WB_NONE = '0,
|
||||||
|
SCR1_RD_WB_IALU, // IALU main result
|
||||||
|
SCR1_RD_WB_SUM2, // IALU SUM2 result (AUIPC)
|
||||||
|
SCR1_RD_WB_IMM, // LUI
|
||||||
|
SCR1_RD_WB_INC_PC, // JAL(R)
|
||||||
|
SCR1_RD_WB_LSU, // Load from DMEM
|
||||||
|
SCR1_RD_WB_CSR // Read CSR
|
||||||
|
} type_scr1_rd_wb_sel_e;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// IDU to EXU full command structure
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
localparam SCR1_GPR_FIELD_WIDTH = 5;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic instr_rvc; // used with a different meaning for IFU access fault exception
|
||||||
|
type_scr1_ialu_op_sel_e ialu_op;
|
||||||
|
type_scr1_ialu_cmd_sel_e ialu_cmd;
|
||||||
|
type_scr1_ialu_sum2_op_sel_e sum2_op;
|
||||||
|
type_scr1_lsu_cmd_sel_e lsu_cmd;
|
||||||
|
type_scr1_csr_op_sel_e csr_op;
|
||||||
|
type_scr1_csr_cmd_sel_e csr_cmd;
|
||||||
|
type_scr1_rd_wb_sel_e rd_wb_sel;
|
||||||
|
logic jump_req;
|
||||||
|
logic branch_req;
|
||||||
|
logic mret_req;
|
||||||
|
logic fencei_req;
|
||||||
|
logic wfi_req;
|
||||||
|
logic [SCR1_GPR_FIELD_WIDTH-1:0] rs1_addr; // also used as zimm for CSRRxI instructions
|
||||||
|
logic [SCR1_GPR_FIELD_WIDTH-1:0] rs2_addr;
|
||||||
|
logic [SCR1_GPR_FIELD_WIDTH-1:0] rd_addr;
|
||||||
|
logic [`SCR1_XLEN-1:0] imm; // used as {funct3, CSR address} for CSR instructions
|
||||||
|
// used as instruction field for illegal instruction exception
|
||||||
|
logic exc_req;
|
||||||
|
type_scr1_exc_code_e exc_code;
|
||||||
|
} type_scr1_exu_cmd_s;
|
||||||
|
|
||||||
|
`endif // SCR1_RISCV_ISA_DECODING_SVH
|
||||||
|
|
||||||
84
src_ref/includes/scr1_scu.svh
Normal file
84
src_ref/includes/scr1_scu.svh
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
|
||||||
|
/// @file <scr1_scu.svh>
|
||||||
|
/// @brief SCU header file
|
||||||
|
///
|
||||||
|
|
||||||
|
`ifndef SCR1_INCLUDE_SCU_DEFS
|
||||||
|
`define SCR1_INCLUDE_SCU_DEFS
|
||||||
|
|
||||||
|
//`include "scr1_arch_description.svh"
|
||||||
|
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Parameters
|
||||||
|
//==============================================================================
|
||||||
|
localparam int unsigned SCR1_SCU_DR_SYSCTRL_OP_WIDTH = 2;
|
||||||
|
localparam int unsigned SCR1_SCU_DR_SYSCTRL_ADDR_WIDTH = 2;
|
||||||
|
localparam int unsigned SCR1_SCU_DR_SYSCTRL_DATA_WIDTH = 4;
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Types
|
||||||
|
//==============================================================================
|
||||||
|
typedef enum logic [SCR1_SCU_DR_SYSCTRL_OP_WIDTH-1:0] {
|
||||||
|
SCR1_SCU_SYSCTRL_OP_WRITE = 2'h0,
|
||||||
|
SCR1_SCU_SYSCTRL_OP_READ = 2'h1,
|
||||||
|
SCR1_SCU_SYSCTRL_OP_SETBITS = 2'h2,
|
||||||
|
SCR1_SCU_SYSCTRL_OP_CLRBITS = 2'h3
|
||||||
|
`ifdef SCR1_XPROP_EN
|
||||||
|
,
|
||||||
|
SCR1_SCU_SYSCTRL_OP_XXX = 'X
|
||||||
|
`endif // SCR1_XPROP_EN
|
||||||
|
} type_scr1_scu_sysctrl_op_e;
|
||||||
|
|
||||||
|
typedef enum logic [SCR1_SCU_DR_SYSCTRL_ADDR_WIDTH-1:0] {
|
||||||
|
SCR1_SCU_SYSCTRL_ADDR_CONTROL = 2'h0,
|
||||||
|
SCR1_SCU_SYSCTRL_ADDR_MODE = 2'h1,
|
||||||
|
SCR1_SCU_SYSCTRL_ADDR_STATUS = 2'h2,
|
||||||
|
SCR1_SCU_SYSCTRL_ADDR_STICKY = 2'h3
|
||||||
|
`ifdef SCR1_XPROP_EN
|
||||||
|
,
|
||||||
|
SCR1_SCU_SYSCTRL_ADDR_XXX = 'X
|
||||||
|
`endif // SCR1_XPROP_EN
|
||||||
|
} type_scr1_scu_sysctrl_addr_e;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic [SCR1_SCU_DR_SYSCTRL_DATA_WIDTH-1:0] data;
|
||||||
|
logic [SCR1_SCU_DR_SYSCTRL_ADDR_WIDTH-1:0] addr;
|
||||||
|
logic [SCR1_SCU_DR_SYSCTRL_OP_WIDTH-1:0] op;
|
||||||
|
} type_scr1_scu_sysctrl_dr_s;
|
||||||
|
|
||||||
|
typedef enum int unsigned {
|
||||||
|
SCR1_SCU_DR_SYSCTRL_OP_BIT_R = 'h0,
|
||||||
|
SCR1_SCU_DR_SYSCTRL_OP_BIT_L = SCR1_SCU_DR_SYSCTRL_OP_WIDTH-1,
|
||||||
|
SCR1_SCU_DR_SYSCTRL_ADDR_BIT_R = SCR1_SCU_DR_SYSCTRL_OP_WIDTH,
|
||||||
|
SCR1_SCU_DR_SYSCTRL_ADDR_BIT_L = SCR1_SCU_DR_SYSCTRL_OP_WIDTH +
|
||||||
|
SCR1_SCU_DR_SYSCTRL_ADDR_WIDTH - 1,
|
||||||
|
SCR1_SCU_DR_SYSCTRL_DATA_BIT_R = SCR1_SCU_DR_SYSCTRL_OP_WIDTH +
|
||||||
|
SCR1_SCU_DR_SYSCTRL_ADDR_WIDTH,
|
||||||
|
SCR1_SCU_DR_SYSCTRL_DATA_BIT_L = SCR1_SCU_DR_SYSCTRL_OP_WIDTH +
|
||||||
|
SCR1_SCU_DR_SYSCTRL_ADDR_WIDTH +
|
||||||
|
SCR1_SCU_DR_SYSCTRL_DATA_WIDTH - 1
|
||||||
|
} type_scr1_scu_sysctrl_dr_bits_e;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic [1:0] rsrv;
|
||||||
|
logic core_reset;
|
||||||
|
logic sys_reset;
|
||||||
|
} type_scr1_scu_sysctrl_control_reg_s;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic [1:0] rsrv;
|
||||||
|
logic hdu_rst_bhv;
|
||||||
|
logic dm_rst_bhv;
|
||||||
|
} type_scr1_scu_sysctrl_mode_reg_s;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic hdu_reset;
|
||||||
|
logic dm_reset;
|
||||||
|
logic core_reset;
|
||||||
|
logic sys_reset;
|
||||||
|
} type_scr1_scu_sysctrl_status_reg_s;
|
||||||
|
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
`endif // SCR1_INCLUDE_SCU_DEFS
|
||||||
94
src_ref/includes/scr1_search_ms1.svh
Normal file
94
src_ref/includes/scr1_search_ms1.svh
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
|
||||||
|
/// @file <scr1_search_ms1.svh>
|
||||||
|
/// @brief Most significant one search function
|
||||||
|
///
|
||||||
|
|
||||||
|
`ifndef SCR1_SEARCH_MS1_SVH
|
||||||
|
`define SCR1_SEARCH_MS1_SVH
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Local types declaration
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
typedef struct {
|
||||||
|
logic vd;
|
||||||
|
logic idx;
|
||||||
|
} type_scr1_search_one_2_s;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
logic vd;
|
||||||
|
logic [4:0] idx;
|
||||||
|
} type_scr1_search_one_32_s;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Leading Zeros Count Function
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
function automatic type_scr1_search_one_2_s scr1_lead_zeros_cnt_2(
|
||||||
|
input logic [1:0] din
|
||||||
|
);
|
||||||
|
type_scr1_search_one_2_s tmp;
|
||||||
|
begin
|
||||||
|
tmp.vd = |din;
|
||||||
|
tmp.idx = ~din[1];
|
||||||
|
return tmp;
|
||||||
|
end
|
||||||
|
endfunction : scr1_lead_zeros_cnt_2
|
||||||
|
|
||||||
|
function automatic logic [4:0] scr1_lead_zeros_cnt_32(
|
||||||
|
input logic [31:0] din
|
||||||
|
);
|
||||||
|
begin
|
||||||
|
logic [15:0] stage1_vd;
|
||||||
|
logic [7:0] stage2_vd;
|
||||||
|
logic [3:0] stage3_vd;
|
||||||
|
logic [1:0] stage4_vd;
|
||||||
|
|
||||||
|
logic stage1_idx [15:0];
|
||||||
|
logic [1:0] stage2_idx [7:0];
|
||||||
|
logic [2:0] stage3_idx [3:0];
|
||||||
|
logic [3:0] stage4_idx [1:0];
|
||||||
|
type_scr1_search_one_32_s tmp;
|
||||||
|
logic [4:0] res;
|
||||||
|
|
||||||
|
// Stage 1
|
||||||
|
for (int unsigned i=0; i<16; ++i) begin
|
||||||
|
type_scr1_search_one_2_s tmp;
|
||||||
|
tmp = scr1_lead_zeros_cnt_2(din[(i+1)*2-1-:2]);
|
||||||
|
stage1_vd[i] = tmp.vd;
|
||||||
|
stage1_idx[i] = tmp.idx;
|
||||||
|
end
|
||||||
|
|
||||||
|
// Stage 2
|
||||||
|
for (int unsigned i=0; i<8; ++i) begin
|
||||||
|
type_scr1_search_one_2_s tmp;
|
||||||
|
tmp = scr1_lead_zeros_cnt_2(stage1_vd[(i+1)*2-1-:2]);
|
||||||
|
stage2_vd[i] = tmp.vd;
|
||||||
|
stage2_idx[i] = (tmp.idx) ? {tmp.idx, stage1_idx[2*i]} : {tmp.idx, stage1_idx[2*i+1]};
|
||||||
|
end
|
||||||
|
|
||||||
|
// Stage 3
|
||||||
|
for (int unsigned i=0; i<4; ++i) begin
|
||||||
|
type_scr1_search_one_2_s tmp;
|
||||||
|
tmp = scr1_lead_zeros_cnt_2(stage2_vd[(i+1)*2-1-:2]);
|
||||||
|
stage3_vd[i] = tmp.vd;
|
||||||
|
stage3_idx[i] = (tmp.idx) ? {tmp.idx, stage2_idx[2*i]} : {tmp.idx, stage2_idx[2*i+1]};
|
||||||
|
end
|
||||||
|
|
||||||
|
// Stage 4
|
||||||
|
for (int unsigned i=0; i<2; ++i) begin
|
||||||
|
type_scr1_search_one_2_s tmp;
|
||||||
|
tmp = scr1_lead_zeros_cnt_2(stage3_vd[(i+1)*2-1-:2]);
|
||||||
|
stage4_vd[i] = tmp.vd;
|
||||||
|
stage4_idx[i] = (tmp.idx) ? {tmp.idx, stage3_idx[2*i]} : {tmp.idx, stage3_idx[2*i+1]};
|
||||||
|
end
|
||||||
|
|
||||||
|
// Stage 5
|
||||||
|
tmp.vd = |stage4_vd;
|
||||||
|
tmp.idx = (stage4_vd[1]) ? {1'b0, stage4_idx[1]} : {1'b1, stage4_idx[0]};
|
||||||
|
|
||||||
|
res = tmp.idx;
|
||||||
|
|
||||||
|
return res;
|
||||||
|
end
|
||||||
|
endfunction : scr1_lead_zeros_cnt_32
|
||||||
|
|
||||||
|
`endif // SCR1_SEARCH_MS1_SVH
|
||||||
66
src_ref/includes/scr1_tapc.svh
Normal file
66
src_ref/includes/scr1_tapc.svh
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
|
||||||
|
/// @file <scr1_tapc.svh>
|
||||||
|
/// @brief TAPC header file
|
||||||
|
///
|
||||||
|
|
||||||
|
`ifndef SCR1_INCLUDE_TAPC_DEFS
|
||||||
|
`define SCR1_INCLUDE_TAPC_DEFS
|
||||||
|
|
||||||
|
`include "scr1_arch_description.svh"
|
||||||
|
|
||||||
|
`ifdef SCR1_DBG_EN
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Parameters
|
||||||
|
//==============================================================================
|
||||||
|
localparam int unsigned SCR1_TAP_STATE_WIDTH = 4;
|
||||||
|
localparam int unsigned SCR1_TAP_INSTRUCTION_WIDTH = 5;
|
||||||
|
localparam int unsigned SCR1_TAP_DR_IDCODE_WIDTH = 32;
|
||||||
|
localparam int unsigned SCR1_TAP_DR_BLD_ID_WIDTH = 32;
|
||||||
|
localparam int unsigned SCR1_TAP_DR_BYPASS_WIDTH = 1;
|
||||||
|
//localparam bit [SCR1_TAP_DR_IDCODE_WIDTH-1:0] SCR1_TAP_IDCODE_RISCV_SC = `SCR1_TAP_IDCODE;
|
||||||
|
localparam bit [SCR1_TAP_DR_BLD_ID_WIDTH-1:0] SCR1_TAP_BLD_ID_VALUE = `SCR1_MIMPID;
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// Types
|
||||||
|
//==============================================================================
|
||||||
|
typedef enum logic [SCR1_TAP_STATE_WIDTH-1:0] {
|
||||||
|
SCR1_TAP_STATE_RESET,
|
||||||
|
SCR1_TAP_STATE_IDLE,
|
||||||
|
SCR1_TAP_STATE_DR_SEL_SCAN,
|
||||||
|
SCR1_TAP_STATE_DR_CAPTURE,
|
||||||
|
SCR1_TAP_STATE_DR_SHIFT,
|
||||||
|
SCR1_TAP_STATE_DR_EXIT1,
|
||||||
|
SCR1_TAP_STATE_DR_PAUSE,
|
||||||
|
SCR1_TAP_STATE_DR_EXIT2,
|
||||||
|
SCR1_TAP_STATE_DR_UPDATE,
|
||||||
|
SCR1_TAP_STATE_IR_SEL_SCAN,
|
||||||
|
SCR1_TAP_STATE_IR_CAPTURE,
|
||||||
|
SCR1_TAP_STATE_IR_SHIFT,
|
||||||
|
SCR1_TAP_STATE_IR_EXIT1,
|
||||||
|
SCR1_TAP_STATE_IR_PAUSE,
|
||||||
|
SCR1_TAP_STATE_IR_EXIT2,
|
||||||
|
SCR1_TAP_STATE_IR_UPDATE
|
||||||
|
`ifdef SCR1_XPROP_EN
|
||||||
|
,
|
||||||
|
SCR1_TAP_STATE_XXX = 'X
|
||||||
|
`endif // SCR1_XPROP_EN
|
||||||
|
} type_scr1_tap_state_e;
|
||||||
|
|
||||||
|
typedef enum logic [SCR1_TAP_INSTRUCTION_WIDTH - 1:0] {
|
||||||
|
SCR1_TAP_INSTR_IDCODE = 5'h01,
|
||||||
|
SCR1_TAP_INSTR_BLD_ID = 5'h04,
|
||||||
|
SCR1_TAP_INSTR_SCU_ACCESS = 5'h09,
|
||||||
|
|
||||||
|
SCR1_TAP_INSTR_DTMCS = 5'h10,
|
||||||
|
SCR1_TAP_INSTR_DMI_ACCESS = 5'h11,
|
||||||
|
|
||||||
|
SCR1_TAP_INSTR_BYPASS = 5'h1F
|
||||||
|
`ifdef SCR1_XPROP_EN
|
||||||
|
,
|
||||||
|
SCR1_TAP_INSTR_XXX = 'X
|
||||||
|
`endif // SCR1_XPROP_EN
|
||||||
|
} type_scr1_tap_instr_e;
|
||||||
|
|
||||||
|
`endif // SCR1_DBG_EN
|
||||||
|
`endif // SCR1_INCLUDE_TAPC_DEFS
|
||||||
121
src_ref/includes/scr1_tdu.svh
Normal file
121
src_ref/includes/scr1_tdu.svh
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
|
||||||
|
/// @file <scr1_tdu.svh>
|
||||||
|
/// @brief Trigger Debug Module header
|
||||||
|
///
|
||||||
|
|
||||||
|
`ifndef SCR1_INCLUDE_TDU_DEFS
|
||||||
|
`define SCR1_INCLUDE_TDU_DEFS
|
||||||
|
|
||||||
|
//`include "scr1_arch_description.svh"
|
||||||
|
|
||||||
|
`ifdef SCR1_TDU_EN
|
||||||
|
//`include "scr1_csr.svh"
|
||||||
|
|
||||||
|
`include "scr1_arch_description.svh"
|
||||||
|
//`include "scr1_arch_types.svh"
|
||||||
|
`include "scr1_csr.svh"
|
||||||
|
|
||||||
|
parameter int unsigned SCR1_TDU_MTRIG_NUM = SCR1_TDU_TRIG_NUM;
|
||||||
|
`ifdef SCR1_TDU_ICOUNT_EN
|
||||||
|
parameter int unsigned SCR1_TDU_ALLTRIG_NUM = SCR1_TDU_MTRIG_NUM + 1'b1;
|
||||||
|
`else
|
||||||
|
parameter int unsigned SCR1_TDU_ALLTRIG_NUM = SCR1_TDU_MTRIG_NUM;
|
||||||
|
`endif
|
||||||
|
|
||||||
|
parameter int unsigned SCR1_TDU_ADDR_W = `SCR1_XLEN;
|
||||||
|
parameter int unsigned SCR1_TDU_DATA_W = `SCR1_XLEN;
|
||||||
|
|
||||||
|
// Register map
|
||||||
|
parameter SCR1_CSR_ADDR_TDU_OFFS_W = 3;
|
||||||
|
parameter bit [SCR1_CSR_ADDR_TDU_OFFS_W-1:0] SCR1_CSR_ADDR_TDU_OFFS_TSELECT = SCR1_CSR_ADDR_TDU_OFFS_W'(0);
|
||||||
|
parameter bit [SCR1_CSR_ADDR_TDU_OFFS_W-1:0] SCR1_CSR_ADDR_TDU_OFFS_TDATA1 = SCR1_CSR_ADDR_TDU_OFFS_W'(1);
|
||||||
|
parameter bit [SCR1_CSR_ADDR_TDU_OFFS_W-1:0] SCR1_CSR_ADDR_TDU_OFFS_TDATA2 = SCR1_CSR_ADDR_TDU_OFFS_W'(2);
|
||||||
|
parameter bit [SCR1_CSR_ADDR_TDU_OFFS_W-1:0] SCR1_CSR_ADDR_TDU_OFFS_TINFO = SCR1_CSR_ADDR_TDU_OFFS_W'(4);
|
||||||
|
|
||||||
|
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_TDU_TSELECT = SCR1_CSR_ADDR_TDU_MBASE + SCR1_CSR_ADDR_TDU_OFFS_TSELECT;
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_TDU_TDATA1 = SCR1_CSR_ADDR_TDU_MBASE + SCR1_CSR_ADDR_TDU_OFFS_TDATA1;
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_TDU_TDATA2 = SCR1_CSR_ADDR_TDU_MBASE + SCR1_CSR_ADDR_TDU_OFFS_TDATA2;
|
||||||
|
parameter bit [SCR1_CSR_ADDR_WIDTH-1:0] SCR1_CSR_ADDR_TDU_TINFO = SCR1_CSR_ADDR_TDU_MBASE + SCR1_CSR_ADDR_TDU_OFFS_TINFO;
|
||||||
|
|
||||||
|
// TDATA1
|
||||||
|
parameter int unsigned SCR1_TDU_TDATA1_TYPE_HI = `SCR1_XLEN-1;
|
||||||
|
parameter int unsigned SCR1_TDU_TDATA1_TYPE_LO = `SCR1_XLEN-4;
|
||||||
|
parameter int unsigned SCR1_TDU_TDATA1_DMODE = `SCR1_XLEN-5;
|
||||||
|
|
||||||
|
// TDATA1: constant bits values
|
||||||
|
parameter bit SCR1_TDU_TDATA1_DMODE_VAL = 1'b0;
|
||||||
|
|
||||||
|
// MCONTROL: bits number
|
||||||
|
parameter int unsigned SCR1_TDU_MCONTROL_MASKMAX_HI = `SCR1_XLEN-6;
|
||||||
|
parameter int unsigned SCR1_TDU_MCONTROL_MASKMAX_LO = `SCR1_XLEN-11;
|
||||||
|
parameter int unsigned SCR1_TDU_MCONTROL_RESERVEDB_HI = `SCR1_XLEN-12;
|
||||||
|
parameter int unsigned SCR1_TDU_MCONTROL_RESERVEDB_LO = 21;
|
||||||
|
parameter int unsigned SCR1_TDU_MCONTROL_HIT = 20;
|
||||||
|
parameter int unsigned SCR1_TDU_MCONTROL_SELECT = 19;
|
||||||
|
parameter int unsigned SCR1_TDU_MCONTROL_TIMING = 18;
|
||||||
|
parameter int unsigned SCR1_TDU_MCONTROL_ACTION_HI = 17;
|
||||||
|
parameter int unsigned SCR1_TDU_MCONTROL_ACTION_LO = 12;
|
||||||
|
parameter int unsigned SCR1_TDU_MCONTROL_CHAIN = 11;
|
||||||
|
parameter int unsigned SCR1_TDU_MCONTROL_MATCH_HI = 10;
|
||||||
|
parameter int unsigned SCR1_TDU_MCONTROL_MATCH_LO = 7;
|
||||||
|
parameter int unsigned SCR1_TDU_MCONTROL_M = 6;
|
||||||
|
parameter int unsigned SCR1_TDU_MCONTROL_RESERVEDA = 5;
|
||||||
|
parameter int unsigned SCR1_TDU_MCONTROL_S = 4;
|
||||||
|
parameter int unsigned SCR1_TDU_MCONTROL_U = 3;
|
||||||
|
parameter int unsigned SCR1_TDU_MCONTROL_EXECUTE = 2;
|
||||||
|
parameter int unsigned SCR1_TDU_MCONTROL_STORE = 1;
|
||||||
|
parameter int unsigned SCR1_TDU_MCONTROL_LOAD = 0;
|
||||||
|
|
||||||
|
// MCONTROL: constant bits values
|
||||||
|
parameter bit [SCR1_TDU_TDATA1_TYPE_HI-SCR1_TDU_TDATA1_TYPE_LO:0]
|
||||||
|
SCR1_TDU_MCONTROL_TYPE_VAL = 2'd2;
|
||||||
|
|
||||||
|
parameter bit SCR1_TDU_MCONTROL_SELECT_VAL = 1'b0;
|
||||||
|
parameter bit SCR1_TDU_MCONTROL_TIMING_VAL = 1'b0;
|
||||||
|
|
||||||
|
parameter bit [SCR1_TDU_MCONTROL_MASKMAX_HI-SCR1_TDU_MCONTROL_MASKMAX_LO:0]
|
||||||
|
SCR1_TDU_MCONTROL_MASKMAX_VAL = 1'b0;
|
||||||
|
|
||||||
|
parameter bit SCR1_TDU_MCONTROL_RESERVEDA_VAL = 1'b0;
|
||||||
|
|
||||||
|
// ICOUNT: bits number
|
||||||
|
parameter int unsigned SCR1_TDU_ICOUNT_DMODE = `SCR1_XLEN-5;
|
||||||
|
parameter int unsigned SCR1_TDU_ICOUNT_RESERVEDB_HI = `SCR1_XLEN-6;
|
||||||
|
parameter int unsigned SCR1_TDU_ICOUNT_RESERVEDB_LO = 25;
|
||||||
|
parameter int unsigned SCR1_TDU_ICOUNT_HIT = 24;
|
||||||
|
parameter int unsigned SCR1_TDU_ICOUNT_COUNT_HI = 23;
|
||||||
|
parameter int unsigned SCR1_TDU_ICOUNT_COUNT_LO = 10;
|
||||||
|
parameter int unsigned SCR1_TDU_ICOUNT_M = 9;
|
||||||
|
parameter int unsigned SCR1_TDU_ICOUNT_RESERVEDA = 8;
|
||||||
|
parameter int unsigned SCR1_TDU_ICOUNT_S = 7;
|
||||||
|
parameter int unsigned SCR1_TDU_ICOUNT_U = 6;
|
||||||
|
parameter int unsigned SCR1_TDU_ICOUNT_ACTION_HI = 5;
|
||||||
|
parameter int unsigned SCR1_TDU_ICOUNT_ACTION_LO = 0;
|
||||||
|
|
||||||
|
// ICOUNT: constant bits values
|
||||||
|
parameter bit [SCR1_TDU_TDATA1_TYPE_HI-SCR1_TDU_TDATA1_TYPE_LO:0]
|
||||||
|
SCR1_TDU_ICOUNT_TYPE_VAL = 2'd3;
|
||||||
|
|
||||||
|
parameter bit [SCR1_TDU_ICOUNT_RESERVEDB_HI-SCR1_TDU_ICOUNT_RESERVEDB_LO:0]
|
||||||
|
SCR1_TDU_ICOUNT_RESERVEDB_VAL = 1'b0;
|
||||||
|
|
||||||
|
parameter bit SCR1_TDU_ICOUNT_RESERVEDA_VAL = 1'b0;
|
||||||
|
|
||||||
|
// CPU pipeline monitors
|
||||||
|
typedef struct packed {
|
||||||
|
logic vd;
|
||||||
|
logic req;
|
||||||
|
logic [`SCR1_XLEN-1:0] addr;
|
||||||
|
} type_scr1_brkm_instr_mon_s;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic vd;
|
||||||
|
logic load;
|
||||||
|
logic store;
|
||||||
|
logic [`SCR1_XLEN-1:0] addr;
|
||||||
|
} type_scr1_brkm_lsu_mon_s;
|
||||||
|
|
||||||
|
`endif // SCR1_TDU_EN
|
||||||
|
|
||||||
|
`endif // SCR1_INCLUDE_TDU_DEFS
|
||||||
480
src_ref/top/scr1_dmem_ahb.sv
Normal file
480
src_ref/top/scr1_dmem_ahb.sv
Normal file
@@ -0,0 +1,480 @@
|
|||||||
|
/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
|
||||||
|
/// @file <scr1_dmem_ahb.sv>
|
||||||
|
/// @brief Data memory AHB bridge
|
||||||
|
///
|
||||||
|
|
||||||
|
`include "scr1_ahb.svh"
|
||||||
|
`include "scr1_memif.svh"
|
||||||
|
|
||||||
|
module scr1_dmem_ahb (
|
||||||
|
// Control Signals
|
||||||
|
input logic rst_n,
|
||||||
|
input logic clk,
|
||||||
|
|
||||||
|
// Core Interface
|
||||||
|
output logic dmem_req_ack,
|
||||||
|
input logic dmem_req,
|
||||||
|
input type_scr1_mem_cmd_e dmem_cmd,
|
||||||
|
input type_scr1_mem_width_e dmem_width,
|
||||||
|
input logic [SCR1_AHB_WIDTH-1:0] dmem_addr,
|
||||||
|
input logic [SCR1_AHB_WIDTH-1:0] dmem_wdata,
|
||||||
|
output logic [SCR1_AHB_WIDTH-1:0] dmem_rdata,
|
||||||
|
output type_scr1_mem_resp_e dmem_resp,
|
||||||
|
|
||||||
|
// AHB Interface
|
||||||
|
output logic [3:0] hprot,
|
||||||
|
output logic [2:0] hburst,
|
||||||
|
output logic [2:0] hsize,
|
||||||
|
output logic [1:0] htrans,
|
||||||
|
output logic hmastlock,
|
||||||
|
output logic [SCR1_AHB_WIDTH-1:0] haddr,
|
||||||
|
output logic hwrite,
|
||||||
|
output logic [SCR1_AHB_WIDTH-1:0] hwdata,
|
||||||
|
input logic hready,
|
||||||
|
input logic [SCR1_AHB_WIDTH-1:0] hrdata,
|
||||||
|
input logic hresp
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Local Parameters
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
`ifndef SCR1_DMEM_AHB_OUT_BP
|
||||||
|
localparam SCR1_FIFO_WIDTH = 2;
|
||||||
|
localparam SCR1_FIFO_CNT_WIDTH = $clog2(SCR1_FIFO_WIDTH+1);
|
||||||
|
`endif // SCR1_DMEM_AHB_OUT_BP
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Local type declaration
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
typedef enum logic {
|
||||||
|
SCR1_FSM_ADDR = 1'b0,
|
||||||
|
SCR1_FSM_DATA = 1'b1
|
||||||
|
`ifdef SCR1_XPROP_EN
|
||||||
|
,
|
||||||
|
SCR1_FSM_ERR = 1'bx
|
||||||
|
`endif // SCR1_XPROP_EN
|
||||||
|
} type_scr1_fsm_e;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic hwrite;
|
||||||
|
logic [2:0] hwidth;
|
||||||
|
logic [SCR1_AHB_WIDTH-1:0] haddr;
|
||||||
|
logic [SCR1_AHB_WIDTH-1:0] hwdata;
|
||||||
|
} type_scr1_req_fifo_s;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic [2:0] hwidth;
|
||||||
|
logic [1:0] haddr;
|
||||||
|
logic [SCR1_AHB_WIDTH-1:0] hwdata;
|
||||||
|
} type_scr1_data_fifo_s;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic hresp;
|
||||||
|
logic [2:0] hwidth;
|
||||||
|
logic [1:0] haddr;
|
||||||
|
logic [SCR1_AHB_WIDTH-1:0] hrdata;
|
||||||
|
} type_scr1_resp_fifo_s;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Local functions
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
function automatic logic [2:0] scr1_conv_mem2ahb_width (
|
||||||
|
input type_scr1_mem_width_e dmem_width
|
||||||
|
);
|
||||||
|
logic [2:0] tmp;
|
||||||
|
begin
|
||||||
|
case (dmem_width)
|
||||||
|
SCR1_MEM_WIDTH_BYTE : begin
|
||||||
|
tmp = SCR1_HSIZE_8B;
|
||||||
|
end
|
||||||
|
SCR1_MEM_WIDTH_HWORD : begin
|
||||||
|
tmp = SCR1_HSIZE_16B;
|
||||||
|
end
|
||||||
|
SCR1_MEM_WIDTH_WORD : begin
|
||||||
|
tmp = SCR1_HSIZE_32B;
|
||||||
|
end
|
||||||
|
default : begin
|
||||||
|
tmp = SCR1_HSIZE_ERR;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
return tmp;
|
||||||
|
end
|
||||||
|
endfunction : scr1_conv_mem2ahb_width
|
||||||
|
|
||||||
|
function automatic logic[SCR1_AHB_WIDTH-1:0] scr1_conv_mem2ahb_wdata (
|
||||||
|
input logic [1:0] dmem_addr,
|
||||||
|
input type_scr1_mem_width_e dmem_width,
|
||||||
|
input logic [SCR1_AHB_WIDTH-1:0] dmem_wdata
|
||||||
|
);
|
||||||
|
logic [SCR1_AHB_WIDTH-1:0] tmp;
|
||||||
|
begin
|
||||||
|
`ifdef SCR1_XPROP_EN
|
||||||
|
tmp = 'x;
|
||||||
|
`else // SCR1_XPROP_EN
|
||||||
|
tmp = '0;
|
||||||
|
`endif // SCR1_XPROP_EN
|
||||||
|
case (dmem_width)
|
||||||
|
SCR1_MEM_WIDTH_BYTE : begin
|
||||||
|
case (dmem_addr)
|
||||||
|
2'b00 : begin
|
||||||
|
tmp[7:0] = dmem_wdata[7:0];
|
||||||
|
end
|
||||||
|
2'b01 : begin
|
||||||
|
tmp[15:8] = dmem_wdata[7:0];
|
||||||
|
end
|
||||||
|
2'b10 : begin
|
||||||
|
tmp[23:16] = dmem_wdata[7:0];
|
||||||
|
end
|
||||||
|
2'b11 : begin
|
||||||
|
tmp[31:24] = dmem_wdata[7:0];
|
||||||
|
end
|
||||||
|
default : begin
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
SCR1_MEM_WIDTH_HWORD : begin
|
||||||
|
case (dmem_addr[1])
|
||||||
|
1'b0 : begin
|
||||||
|
tmp[15:0] = dmem_wdata[15:0];
|
||||||
|
end
|
||||||
|
1'b1 : begin
|
||||||
|
tmp[31:16] = dmem_wdata[15:0];
|
||||||
|
end
|
||||||
|
default : begin
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
SCR1_MEM_WIDTH_WORD : begin
|
||||||
|
tmp = dmem_wdata;
|
||||||
|
end
|
||||||
|
default : begin
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
return tmp;
|
||||||
|
end
|
||||||
|
endfunction : scr1_conv_mem2ahb_wdata
|
||||||
|
|
||||||
|
function automatic logic[SCR1_AHB_WIDTH-1:0] scr1_conv_ahb2mem_rdata (
|
||||||
|
input logic [2:0] hwidth,
|
||||||
|
input logic [1:0] haddr,
|
||||||
|
input logic [SCR1_AHB_WIDTH-1:0] hrdata
|
||||||
|
);
|
||||||
|
logic [SCR1_AHB_WIDTH-1:0] tmp;
|
||||||
|
begin
|
||||||
|
`ifdef SCR1_XPROP_EN
|
||||||
|
tmp = 'x;
|
||||||
|
`else // SCR1_XPROP_EN
|
||||||
|
tmp = '0;
|
||||||
|
`endif // SCR1_XPROP_EN
|
||||||
|
case (hwidth)
|
||||||
|
SCR1_HSIZE_8B : begin
|
||||||
|
case (haddr)
|
||||||
|
2'b00 : tmp[7:0] = hrdata[7:0];
|
||||||
|
2'b01 : tmp[7:0] = hrdata[15:8];
|
||||||
|
2'b10 : tmp[7:0] = hrdata[23:16];
|
||||||
|
2'b11 : tmp[7:0] = hrdata[31:24];
|
||||||
|
default : begin
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
SCR1_HSIZE_16B : begin
|
||||||
|
case (haddr[1])
|
||||||
|
1'b0 : tmp[15:0] = hrdata[15:0];
|
||||||
|
1'b1 : tmp[15:0] = hrdata[31:16];
|
||||||
|
default : begin
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
SCR1_HSIZE_32B : begin
|
||||||
|
tmp = hrdata;
|
||||||
|
end
|
||||||
|
default : begin
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
return tmp;
|
||||||
|
end
|
||||||
|
endfunction : scr1_conv_ahb2mem_rdata
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Local signal declaration
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
type_scr1_fsm_e fsm;
|
||||||
|
logic req_fifo_rd;
|
||||||
|
logic req_fifo_wr;
|
||||||
|
logic req_fifo_up;
|
||||||
|
`ifdef SCR1_DMEM_AHB_OUT_BP
|
||||||
|
type_scr1_req_fifo_s req_fifo_new;
|
||||||
|
type_scr1_req_fifo_s req_fifo_r;
|
||||||
|
type_scr1_req_fifo_s [0:0] req_fifo;
|
||||||
|
`else // SCR1_DMEM_AHB_OUT_BP
|
||||||
|
type_scr1_req_fifo_s [0:SCR1_FIFO_WIDTH-1] req_fifo;
|
||||||
|
type_scr1_req_fifo_s [0:SCR1_FIFO_WIDTH-1] req_fifo_new;
|
||||||
|
logic [SCR1_FIFO_CNT_WIDTH-1:0] req_fifo_cnt;
|
||||||
|
logic [SCR1_FIFO_CNT_WIDTH-1:0] req_fifo_cnt_new;
|
||||||
|
`endif // SCR1_DMEM_AHB_OUT_BP
|
||||||
|
logic req_fifo_empty;
|
||||||
|
logic req_fifo_full;
|
||||||
|
|
||||||
|
type_scr1_data_fifo_s data_fifo;
|
||||||
|
type_scr1_resp_fifo_s resp_fifo;
|
||||||
|
logic resp_fifo_hready;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Interface to Core
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
assign dmem_req_ack = ~req_fifo_full;
|
||||||
|
assign req_fifo_wr = ~req_fifo_full & dmem_req;
|
||||||
|
|
||||||
|
assign dmem_rdata = scr1_conv_ahb2mem_rdata(resp_fifo.hwidth, resp_fifo.haddr, resp_fifo.hrdata);
|
||||||
|
|
||||||
|
assign dmem_resp = (resp_fifo_hready)
|
||||||
|
? (resp_fifo.hresp == SCR1_HRESP_OKAY)
|
||||||
|
? SCR1_MEM_RESP_RDY_OK
|
||||||
|
: SCR1_MEM_RESP_RDY_ER
|
||||||
|
: SCR1_MEM_RESP_NOTRDY ;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// REQ_FIFO
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
`ifdef SCR1_DMEM_AHB_OUT_BP
|
||||||
|
always_ff @(negedge rst_n, posedge clk) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
req_fifo_full <= 1'b0;
|
||||||
|
end else begin
|
||||||
|
if (~req_fifo_full) begin
|
||||||
|
req_fifo_full <= dmem_req & ~req_fifo_rd;
|
||||||
|
end else begin
|
||||||
|
req_fifo_full <= ~req_fifo_rd;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
assign req_fifo_empty = ~(req_fifo_full | dmem_req);
|
||||||
|
|
||||||
|
assign req_fifo_up = ~req_fifo_rd & req_fifo_wr;
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if (req_fifo_up) begin
|
||||||
|
req_fifo_r <= req_fifo_new;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign req_fifo_new.hwrite = dmem_req ? (dmem_cmd == SCR1_MEM_CMD_WR) : 1'b0;
|
||||||
|
assign req_fifo_new.hwidth = dmem_req ? scr1_conv_mem2ahb_width(dmem_width) : '0;
|
||||||
|
assign req_fifo_new.haddr = dmem_req ? dmem_addr : '0;
|
||||||
|
assign req_fifo_new.hwdata = (dmem_req & (dmem_cmd == SCR1_MEM_CMD_WR))
|
||||||
|
? scr1_conv_mem2ahb_wdata(dmem_addr[1:0], dmem_width, dmem_wdata)
|
||||||
|
: '0;
|
||||||
|
assign req_fifo[0] = (req_fifo_full) ? req_fifo_r: req_fifo_new;
|
||||||
|
|
||||||
|
`else // SCR1_DMEM_AHB_OUT_BP
|
||||||
|
always_comb begin
|
||||||
|
req_fifo_up = 1'b0;
|
||||||
|
req_fifo_cnt_new = req_fifo_cnt;
|
||||||
|
req_fifo_new = req_fifo;
|
||||||
|
case ({req_fifo_rd, req_fifo_wr})
|
||||||
|
2'b00 : begin
|
||||||
|
// nothing todo
|
||||||
|
end
|
||||||
|
2'b01: begin
|
||||||
|
// FIFO write
|
||||||
|
req_fifo_up = 1'b1;
|
||||||
|
req_fifo_new[req_fifo_cnt].hwrite = (dmem_cmd == SCR1_MEM_CMD_WR);
|
||||||
|
req_fifo_new[req_fifo_cnt].hwidth = scr1_conv_mem2ahb_width(dmem_width);
|
||||||
|
req_fifo_new[req_fifo_cnt].haddr = dmem_addr;
|
||||||
|
req_fifo_new[req_fifo_cnt].hwdata = scr1_conv_mem2ahb_wdata(dmem_addr[1:0], dmem_width, dmem_wdata);
|
||||||
|
req_fifo_cnt_new = req_fifo_cnt + 1'b1;
|
||||||
|
end
|
||||||
|
2'b10 : begin
|
||||||
|
// FIFO read
|
||||||
|
req_fifo_up = 1'b1;
|
||||||
|
req_fifo_new[0] = req_fifo_new[1];
|
||||||
|
req_fifo_new[1].hwrite = 1'b0;
|
||||||
|
req_fifo_new[1].hwidth = SCR1_HSIZE_32B;
|
||||||
|
`ifdef SCR1_XPROP_EN
|
||||||
|
req_fifo_new[1].haddr = 'x;
|
||||||
|
req_fifo_new[1].hwdata = 'x;
|
||||||
|
`endif // SCR1_XPROP_EN
|
||||||
|
req_fifo_cnt_new = req_fifo_cnt - 1'b1;
|
||||||
|
end
|
||||||
|
2'b11 : begin
|
||||||
|
// Read and Write FIFO. It is possible only when fifo_cnt = 1
|
||||||
|
req_fifo_up = 1'b1;
|
||||||
|
req_fifo_new[0].hwrite = (dmem_cmd == SCR1_MEM_CMD_WR);
|
||||||
|
req_fifo_new[0].hwidth = scr1_conv_mem2ahb_width(dmem_width);
|
||||||
|
req_fifo_new[0].haddr = dmem_addr;
|
||||||
|
req_fifo_new[0].hwdata = scr1_conv_mem2ahb_wdata(dmem_addr[1:0], dmem_width, dmem_wdata);
|
||||||
|
end
|
||||||
|
default : begin
|
||||||
|
`ifdef SCR1_XPROP_EN
|
||||||
|
req_fifo_up = 'x;
|
||||||
|
req_fifo_cnt_new = 'x;
|
||||||
|
req_fifo_new = 'x;
|
||||||
|
`endif // SCR1_XPROP_EN
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
always_ff @(negedge rst_n, posedge clk) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
req_fifo_cnt <= '0;
|
||||||
|
end else begin
|
||||||
|
if (req_fifo_up) begin
|
||||||
|
req_fifo_cnt <= req_fifo_cnt_new;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
assign req_fifo_full = (req_fifo_cnt == SCR1_FIFO_WIDTH);
|
||||||
|
assign req_fifo_empty = ~(|req_fifo_cnt);
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if (req_fifo_up) begin
|
||||||
|
req_fifo <= req_fifo_new;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
`endif // SCR1_DMEM_AHB_OUT_BP
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// FSM
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
always_ff @(negedge rst_n, posedge clk) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
fsm <= SCR1_FSM_ADDR;
|
||||||
|
end else begin
|
||||||
|
case (fsm)
|
||||||
|
SCR1_FSM_ADDR : begin
|
||||||
|
if (hready) begin
|
||||||
|
fsm <= (req_fifo_empty) ? SCR1_FSM_ADDR : SCR1_FSM_DATA;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
SCR1_FSM_DATA : begin
|
||||||
|
if (hready) begin
|
||||||
|
if (hresp == SCR1_HRESP_OKAY) begin
|
||||||
|
fsm <= (req_fifo_empty) ? SCR1_FSM_ADDR : SCR1_FSM_DATA;
|
||||||
|
end else begin
|
||||||
|
fsm <= SCR1_FSM_ADDR;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
default : begin
|
||||||
|
`ifdef SCR1_XPROP_EN
|
||||||
|
fsm <= SCR1_FSM_ERR;
|
||||||
|
`endif // SCR1_XPROP_EN
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
req_fifo_rd = 1'b0;
|
||||||
|
case (fsm)
|
||||||
|
SCR1_FSM_ADDR : begin
|
||||||
|
if (hready) begin
|
||||||
|
req_fifo_rd = ~req_fifo_empty;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
SCR1_FSM_DATA : begin
|
||||||
|
if (hready) begin
|
||||||
|
req_fifo_rd = ~req_fifo_empty & (hresp == SCR1_HRESP_OKAY);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
default : begin
|
||||||
|
req_fifo_rd = 1'bx;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// FIFO data
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
case (fsm)
|
||||||
|
SCR1_FSM_ADDR : begin
|
||||||
|
if (~req_fifo_empty) begin
|
||||||
|
data_fifo.hwidth <= req_fifo[0].hwidth;
|
||||||
|
data_fifo.haddr <= req_fifo[0].haddr[1:0];
|
||||||
|
data_fifo.hwdata <= req_fifo[0].hwdata;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
SCR1_FSM_DATA : begin
|
||||||
|
if (hready) begin
|
||||||
|
if (hresp == SCR1_HRESP_OKAY) begin
|
||||||
|
if (~req_fifo_empty) begin
|
||||||
|
data_fifo.hwidth <= req_fifo[0].hwidth;
|
||||||
|
data_fifo.haddr <= req_fifo[0].haddr[1:0];
|
||||||
|
data_fifo.hwdata <= req_fifo[0].hwdata;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
default : begin
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// FIFO response
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
`ifdef SCR1_DMEM_AHB_IN_BP
|
||||||
|
assign resp_fifo_hready = (fsm == SCR1_FSM_DATA) ? hready : 1'b0;
|
||||||
|
assign resp_fifo.hresp = hresp;
|
||||||
|
assign resp_fifo.hwidth = data_fifo.hwidth;
|
||||||
|
assign resp_fifo.haddr = data_fifo.haddr;
|
||||||
|
assign resp_fifo.hrdata = hrdata;
|
||||||
|
`else // SCR1_DMEM_AHB_IN_BP
|
||||||
|
always_ff @(negedge rst_n, posedge clk) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
resp_fifo_hready <= 1'b0;
|
||||||
|
end else begin
|
||||||
|
resp_fifo_hready <= (fsm == SCR1_FSM_DATA) ? hready : 1'b0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if (hready & (fsm == SCR1_FSM_DATA)) begin
|
||||||
|
resp_fifo.hresp <= hresp;
|
||||||
|
resp_fifo.hwidth <= data_fifo.hwidth;
|
||||||
|
resp_fifo.haddr <= data_fifo.haddr;
|
||||||
|
resp_fifo.hrdata <= hrdata;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
`endif // SCR1_DMEM_AHB_IN_BP
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Interface to AHB
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
assign hprot[SCR1_HPROT_DATA] = 1'b1;
|
||||||
|
assign hprot[SCR1_HPROT_PRV] = 1'b0;
|
||||||
|
assign hprot[SCR1_HPROT_BUF] = 1'b0;
|
||||||
|
assign hprot[SCR1_HPROT_CACHE] = 1'b0;
|
||||||
|
|
||||||
|
assign hburst = SCR1_HBURST_SINGLE;
|
||||||
|
assign hsize = req_fifo[0].hwidth;
|
||||||
|
assign hmastlock = 1'b0;
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
htrans = SCR1_HTRANS_IDLE;
|
||||||
|
case (fsm)
|
||||||
|
SCR1_FSM_ADDR : begin
|
||||||
|
if (~req_fifo_empty) begin
|
||||||
|
htrans = SCR1_HTRANS_NONSEQ;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
SCR1_FSM_DATA : begin
|
||||||
|
if (hready) begin
|
||||||
|
if (hresp == SCR1_HRESP_OKAY) begin
|
||||||
|
if (~req_fifo_empty) begin
|
||||||
|
htrans = SCR1_HTRANS_NONSEQ;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
default : begin
|
||||||
|
htrans = SCR1_HTRANS_ERR;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
assign haddr = req_fifo[0].haddr;
|
||||||
|
assign hwrite = req_fifo[0].hwrite;
|
||||||
|
assign hwdata = data_fifo.hwdata;
|
||||||
|
|
||||||
|
endmodule : scr1_dmem_ahb
|
||||||
278
src_ref/top/scr1_dmem_router.sv
Normal file
278
src_ref/top/scr1_dmem_router.sv
Normal file
@@ -0,0 +1,278 @@
|
|||||||
|
/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
|
||||||
|
/// @file <scr1_dmem_router.sv>
|
||||||
|
/// @brief Data memory router
|
||||||
|
///
|
||||||
|
`include "scr1_memif.svh"
|
||||||
|
`include "scr1_arch_description.svh"
|
||||||
|
|
||||||
|
module scr1_dmem_router
|
||||||
|
#(
|
||||||
|
parameter SCR1_PORT1_ADDR_MASK = `SCR1_DMEM_AWIDTH'hFFFF0000,
|
||||||
|
parameter SCR1_PORT1_ADDR_PATTERN = `SCR1_DMEM_AWIDTH'h00010000,
|
||||||
|
parameter SCR1_PORT2_ADDR_MASK = `SCR1_DMEM_AWIDTH'hFFFF0000,
|
||||||
|
parameter SCR1_PORT2_ADDR_PATTERN = `SCR1_DMEM_AWIDTH'h00020000
|
||||||
|
)
|
||||||
|
(
|
||||||
|
// Control signals
|
||||||
|
input logic rst_n,
|
||||||
|
input logic clk,
|
||||||
|
|
||||||
|
// Core interface
|
||||||
|
output logic dmem_req_ack,
|
||||||
|
input logic dmem_req,
|
||||||
|
input type_scr1_mem_cmd_e dmem_cmd,
|
||||||
|
input type_scr1_mem_width_e dmem_width,
|
||||||
|
input logic [`SCR1_DMEM_AWIDTH-1:0] dmem_addr,
|
||||||
|
input logic [`SCR1_DMEM_DWIDTH-1:0] dmem_wdata,
|
||||||
|
output logic [`SCR1_DMEM_DWIDTH-1:0] dmem_rdata,
|
||||||
|
output type_scr1_mem_resp_e dmem_resp,
|
||||||
|
|
||||||
|
// PORT0 interface
|
||||||
|
input logic port0_req_ack,
|
||||||
|
output logic port0_req,
|
||||||
|
output type_scr1_mem_cmd_e port0_cmd,
|
||||||
|
output type_scr1_mem_width_e port0_width,
|
||||||
|
output logic [`SCR1_DMEM_AWIDTH-1:0] port0_addr,
|
||||||
|
output logic [`SCR1_DMEM_DWIDTH-1:0] port0_wdata,
|
||||||
|
input logic [`SCR1_DMEM_DWIDTH-1:0] port0_rdata,
|
||||||
|
input type_scr1_mem_resp_e port0_resp,
|
||||||
|
|
||||||
|
// PORT1 interface
|
||||||
|
input logic port1_req_ack,
|
||||||
|
output logic port1_req,
|
||||||
|
output type_scr1_mem_cmd_e port1_cmd,
|
||||||
|
output type_scr1_mem_width_e port1_width,
|
||||||
|
output logic [`SCR1_DMEM_AWIDTH-1:0] port1_addr,
|
||||||
|
output logic [`SCR1_DMEM_DWIDTH-1:0] port1_wdata,
|
||||||
|
input logic [`SCR1_DMEM_DWIDTH-1:0] port1_rdata,
|
||||||
|
input type_scr1_mem_resp_e port1_resp,
|
||||||
|
|
||||||
|
// PORT2 interface
|
||||||
|
input logic port2_req_ack,
|
||||||
|
output logic port2_req,
|
||||||
|
output type_scr1_mem_cmd_e port2_cmd,
|
||||||
|
output type_scr1_mem_width_e port2_width,
|
||||||
|
output logic [`SCR1_DMEM_AWIDTH-1:0] port2_addr,
|
||||||
|
output logic [`SCR1_DMEM_DWIDTH-1:0] port2_wdata,
|
||||||
|
input logic [`SCR1_DMEM_DWIDTH-1:0] port2_rdata,
|
||||||
|
input type_scr1_mem_resp_e port2_resp
|
||||||
|
);
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Local types declaration
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
typedef enum logic {
|
||||||
|
SCR1_FSM_ADDR,
|
||||||
|
SCR1_FSM_DATA
|
||||||
|
} type_scr1_fsm_e;
|
||||||
|
|
||||||
|
typedef enum logic [1:0] {
|
||||||
|
SCR1_SEL_PORT0,
|
||||||
|
SCR1_SEL_PORT1,
|
||||||
|
SCR1_SEL_PORT2
|
||||||
|
} type_scr1_sel_e;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Local signal declaration
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
type_scr1_fsm_e fsm;
|
||||||
|
type_scr1_sel_e port_sel;
|
||||||
|
type_scr1_sel_e port_sel_r;
|
||||||
|
logic [`SCR1_DMEM_DWIDTH-1:0] sel_rdata;
|
||||||
|
type_scr1_mem_resp_e sel_resp;
|
||||||
|
logic sel_req_ack;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// FSM
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
always_comb begin
|
||||||
|
port_sel = SCR1_SEL_PORT0;
|
||||||
|
if ((dmem_addr & SCR1_PORT1_ADDR_MASK) == SCR1_PORT1_ADDR_PATTERN) begin
|
||||||
|
port_sel = SCR1_SEL_PORT1;
|
||||||
|
end else if ((dmem_addr & SCR1_PORT2_ADDR_MASK) == SCR1_PORT2_ADDR_PATTERN) begin
|
||||||
|
port_sel = SCR1_SEL_PORT2;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_ff @(negedge rst_n, posedge clk) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
fsm <= SCR1_FSM_ADDR;
|
||||||
|
port_sel_r <= SCR1_SEL_PORT0;
|
||||||
|
end else begin
|
||||||
|
case (fsm)
|
||||||
|
SCR1_FSM_ADDR : begin
|
||||||
|
if (dmem_req & sel_req_ack) begin
|
||||||
|
fsm <= SCR1_FSM_DATA;
|
||||||
|
port_sel_r <= port_sel;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
SCR1_FSM_DATA : begin
|
||||||
|
case (sel_resp)
|
||||||
|
SCR1_MEM_RESP_RDY_OK : begin
|
||||||
|
if (dmem_req & sel_req_ack) begin
|
||||||
|
fsm <= SCR1_FSM_DATA;
|
||||||
|
port_sel_r <= port_sel;
|
||||||
|
end else begin
|
||||||
|
fsm <= SCR1_FSM_ADDR;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
SCR1_MEM_RESP_RDY_ER : begin
|
||||||
|
fsm <= SCR1_FSM_ADDR;
|
||||||
|
end
|
||||||
|
default : begin
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
default : begin
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
if ((fsm == SCR1_FSM_ADDR) | ((fsm == SCR1_FSM_DATA) & (sel_resp == SCR1_MEM_RESP_RDY_OK))) begin
|
||||||
|
case (port_sel)
|
||||||
|
SCR1_SEL_PORT0 : sel_req_ack = port0_req_ack;
|
||||||
|
SCR1_SEL_PORT1 : sel_req_ack = port1_req_ack;
|
||||||
|
SCR1_SEL_PORT2 : sel_req_ack = port2_req_ack;
|
||||||
|
default : sel_req_ack = 1'b0;
|
||||||
|
endcase
|
||||||
|
end else begin
|
||||||
|
sel_req_ack = 1'b0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
case (port_sel_r)
|
||||||
|
SCR1_SEL_PORT0 : begin
|
||||||
|
sel_rdata = port0_rdata;
|
||||||
|
sel_resp = port0_resp;
|
||||||
|
end
|
||||||
|
SCR1_SEL_PORT1 : begin
|
||||||
|
sel_rdata = port1_rdata;
|
||||||
|
sel_resp = port1_resp;
|
||||||
|
end
|
||||||
|
SCR1_SEL_PORT2 : begin
|
||||||
|
sel_rdata = port2_rdata;
|
||||||
|
sel_resp = port2_resp;
|
||||||
|
end
|
||||||
|
default : begin
|
||||||
|
sel_rdata = '0;
|
||||||
|
sel_resp = SCR1_MEM_RESP_RDY_ER;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Interface to core
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
assign dmem_req_ack = sel_req_ack;
|
||||||
|
assign dmem_rdata = sel_rdata;
|
||||||
|
assign dmem_resp = sel_resp;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Interface to PORT0
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
always_comb begin
|
||||||
|
port0_req = 1'b0;
|
||||||
|
case (fsm)
|
||||||
|
SCR1_FSM_ADDR : begin
|
||||||
|
port0_req = dmem_req & (port_sel == SCR1_SEL_PORT0);
|
||||||
|
end
|
||||||
|
SCR1_FSM_DATA : begin
|
||||||
|
if (sel_resp == SCR1_MEM_RESP_RDY_OK) begin
|
||||||
|
port0_req = dmem_req & (port_sel == SCR1_SEL_PORT0);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
default : begin
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
`ifdef SCR1_XPROP_EN
|
||||||
|
assign port0_cmd = (port_sel == SCR1_SEL_PORT0) ? dmem_cmd : SCR1_MEM_CMD_ERROR;
|
||||||
|
assign port0_width = (port_sel == SCR1_SEL_PORT0) ? dmem_width : SCR1_MEM_WIDTH_ERROR;
|
||||||
|
assign port0_addr = (port_sel == SCR1_SEL_PORT0) ? dmem_addr : 'x;
|
||||||
|
assign port0_wdata = (port_sel == SCR1_SEL_PORT0) ? dmem_wdata : 'x;
|
||||||
|
`else // SCR1_XPROP_EN
|
||||||
|
assign port0_cmd = dmem_cmd ;
|
||||||
|
assign port0_width = dmem_width;
|
||||||
|
assign port0_addr = dmem_addr ;
|
||||||
|
assign port0_wdata = dmem_wdata;
|
||||||
|
`endif // SCR1_XPROP_EN
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Interface to PORT1
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
always_comb begin
|
||||||
|
port1_req = 1'b0;
|
||||||
|
case (fsm)
|
||||||
|
SCR1_FSM_ADDR : begin
|
||||||
|
port1_req = dmem_req & (port_sel == SCR1_SEL_PORT1);
|
||||||
|
end
|
||||||
|
SCR1_FSM_DATA : begin
|
||||||
|
if (sel_resp == SCR1_MEM_RESP_RDY_OK) begin
|
||||||
|
port1_req = dmem_req & (port_sel == SCR1_SEL_PORT1);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
default : begin
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
`ifdef SCR1_XPROP_EN
|
||||||
|
assign port1_cmd = (port_sel == SCR1_SEL_PORT1) ? dmem_cmd : SCR1_MEM_CMD_ERROR;
|
||||||
|
assign port1_width = (port_sel == SCR1_SEL_PORT1) ? dmem_width : SCR1_MEM_WIDTH_ERROR;
|
||||||
|
assign port1_addr = (port_sel == SCR1_SEL_PORT1) ? dmem_addr : 'x;
|
||||||
|
assign port1_wdata = (port_sel == SCR1_SEL_PORT1) ? dmem_wdata : 'x;
|
||||||
|
`else // SCR1_XPROP_EN
|
||||||
|
assign port1_cmd = dmem_cmd ;
|
||||||
|
assign port1_width = dmem_width;
|
||||||
|
assign port1_addr = dmem_addr ;
|
||||||
|
assign port1_wdata = dmem_wdata;
|
||||||
|
`endif // SCR1_XPROP_EN
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Interface to PORT2
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
always_comb begin
|
||||||
|
port2_req = 1'b0;
|
||||||
|
case (fsm)
|
||||||
|
SCR1_FSM_ADDR : begin
|
||||||
|
port2_req = dmem_req & (port_sel == SCR1_SEL_PORT2);
|
||||||
|
end
|
||||||
|
SCR1_FSM_DATA : begin
|
||||||
|
if (sel_resp == SCR1_MEM_RESP_RDY_OK) begin
|
||||||
|
port2_req = dmem_req & (port_sel == SCR1_SEL_PORT2);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
default : begin
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
`ifdef SCR1_XPROP_EN
|
||||||
|
assign port2_cmd = (port_sel == SCR1_SEL_PORT2) ? dmem_cmd : SCR1_MEM_CMD_ERROR;
|
||||||
|
assign port2_width = (port_sel == SCR1_SEL_PORT2) ? dmem_width : SCR1_MEM_WIDTH_ERROR;
|
||||||
|
assign port2_addr = (port_sel == SCR1_SEL_PORT2) ? dmem_addr : 'x;
|
||||||
|
assign port2_wdata = (port_sel == SCR1_SEL_PORT2) ? dmem_wdata : 'x;
|
||||||
|
`else // SCR1_XPROP_EN
|
||||||
|
assign port2_cmd = dmem_cmd ;
|
||||||
|
assign port2_width = dmem_width;
|
||||||
|
assign port2_addr = dmem_addr ;
|
||||||
|
assign port2_wdata = dmem_wdata;
|
||||||
|
`endif // SCR1_XPROP_EN
|
||||||
|
|
||||||
|
`ifdef SCR1_TRGT_SIMULATION
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Assertion
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
SCR1_SVA_DMEM_RT_XCHECK : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
dmem_req |-> !$isunknown({port_sel, dmem_cmd, dmem_width})
|
||||||
|
) else $error("DMEM router Error: unknown values");
|
||||||
|
|
||||||
|
`endif // SCR1_TRGT_SIMULATION
|
||||||
|
|
||||||
|
endmodule : scr1_dmem_router
|
||||||
111
src_ref/top/scr1_dp_memory.sv
Normal file
111
src_ref/top/scr1_dp_memory.sv
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
/// Copyright by Syntacore LLC © 2016-2020. See LICENSE for details
|
||||||
|
/// @file <scr1_dp_memory.sv>
|
||||||
|
/// @brief Dual-port synchronous memory with byte enable inputs
|
||||||
|
///
|
||||||
|
|
||||||
|
`include "scr1_arch_description.svh"
|
||||||
|
|
||||||
|
`ifdef SCR1_TCM_EN
|
||||||
|
module scr1_dp_memory
|
||||||
|
#(
|
||||||
|
parameter SCR1_WIDTH = 32,
|
||||||
|
parameter SCR1_SIZE = `SCR1_IMEM_AWIDTH'h00010000,
|
||||||
|
parameter SCR1_NBYTES = SCR1_WIDTH / 8
|
||||||
|
)
|
||||||
|
(
|
||||||
|
input logic clk,
|
||||||
|
// Port A
|
||||||
|
input logic rena,
|
||||||
|
input logic [$clog2(SCR1_SIZE)-1:2] addra,
|
||||||
|
output logic [SCR1_WIDTH-1:0] qa,
|
||||||
|
// Port B
|
||||||
|
input logic renb,
|
||||||
|
input logic wenb,
|
||||||
|
input logic [SCR1_NBYTES-1:0] webb,
|
||||||
|
input logic [$clog2(SCR1_SIZE)-1:2] addrb,
|
||||||
|
input logic [SCR1_WIDTH-1:0] datab,
|
||||||
|
output logic [SCR1_WIDTH-1:0] qb
|
||||||
|
);
|
||||||
|
|
||||||
|
`ifdef SCR1_TRGT_FPGA_INTEL
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Local signal declaration
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
`ifdef SCR1_TRGT_FPGA_INTEL_MAX10
|
||||||
|
(* ramstyle = "M9K" *) logic [SCR1_NBYTES-1:0][7:0] memory_array [0:(SCR1_SIZE/SCR1_NBYTES)-1];
|
||||||
|
`elsif SCR1_TRGT_FPGA_INTEL_ARRIAV
|
||||||
|
(* ramstyle = "M10K" *) logic [SCR1_NBYTES-1:0][7:0] memory_array [0:(SCR1_SIZE/SCR1_NBYTES)-1];
|
||||||
|
`endif
|
||||||
|
logic [3:0] wenbb;
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Port B memory behavioral description
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
assign wenbb = {4{wenb}} & webb;
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if (wenb) begin
|
||||||
|
if (wenbb[0]) begin
|
||||||
|
memory_array[addrb][0] <= datab[0+:8];
|
||||||
|
end
|
||||||
|
if (wenbb[1]) begin
|
||||||
|
memory_array[addrb][1] <= datab[8+:8];
|
||||||
|
end
|
||||||
|
if (wenbb[2]) begin
|
||||||
|
memory_array[addrb][2] <= datab[16+:8];
|
||||||
|
end
|
||||||
|
if (wenbb[3]) begin
|
||||||
|
memory_array[addrb][3] <= datab[24+:8];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
qb <= memory_array[addrb];
|
||||||
|
end
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Port A memory behavioral description
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
qa <= memory_array[addra];
|
||||||
|
end
|
||||||
|
|
||||||
|
`else // SCR1_TRGT_FPGA_INTEL
|
||||||
|
|
||||||
|
// CASE: OTHERS - SCR1_TRGT_FPGA_XILINX, SIMULATION, ASIC etc
|
||||||
|
|
||||||
|
localparam int unsigned RAM_SIZE_WORDS = SCR1_SIZE/SCR1_NBYTES;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Local signal declaration
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
`ifdef SCR1_TRGT_FPGA_XILINX
|
||||||
|
(* ram_style = "block" *) logic [SCR1_WIDTH-1:0] ram_block [RAM_SIZE_WORDS-1:0];
|
||||||
|
`else // ASIC or SIMULATION
|
||||||
|
logic [SCR1_WIDTH-1:0] ram_block [RAM_SIZE_WORDS-1:0];
|
||||||
|
`endif
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Port A memory behavioral description
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if (rena) begin
|
||||||
|
qa <= ram_block[addra];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Port B memory behavioral description
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if (wenb) begin
|
||||||
|
for (int i=0; i<SCR1_NBYTES; i++) begin
|
||||||
|
if (webb[i]) begin
|
||||||
|
ram_block[addrb][i*8 +: 8] <= datab[i*8 +: 8];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if (renb) begin
|
||||||
|
qb <= ram_block[addrb];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
`endif // SCR1_TRGT_FPGA_INTEL
|
||||||
|
|
||||||
|
endmodule : scr1_dp_memory
|
||||||
|
|
||||||
|
`endif // SCR1_TCM_EN
|
||||||
319
src_ref/top/scr1_imem_ahb.sv
Normal file
319
src_ref/top/scr1_imem_ahb.sv
Normal file
@@ -0,0 +1,319 @@
|
|||||||
|
/// Copyright by Syntacore LLC © 2016-2021. See LICENSE for details
|
||||||
|
/// @file <scr1_imem_ahb.sv>
|
||||||
|
/// @brief Instruction memory AHB bridge
|
||||||
|
///
|
||||||
|
|
||||||
|
`include "scr1_ahb.svh"
|
||||||
|
`include "scr1_memif.svh"
|
||||||
|
|
||||||
|
module scr1_imem_ahb (
|
||||||
|
// Control Signals
|
||||||
|
input logic rst_n,
|
||||||
|
input logic clk,
|
||||||
|
|
||||||
|
// Core Interface
|
||||||
|
output logic imem_req_ack,
|
||||||
|
input logic imem_req,
|
||||||
|
input logic [SCR1_AHB_WIDTH-1:0] imem_addr,
|
||||||
|
output logic [SCR1_AHB_WIDTH-1:0] imem_rdata,
|
||||||
|
output type_scr1_mem_resp_e imem_resp,
|
||||||
|
|
||||||
|
// AHB Interface
|
||||||
|
output logic [3:0] hprot,
|
||||||
|
output logic [2:0] hburst,
|
||||||
|
output logic [2:0] hsize,
|
||||||
|
output logic [1:0] htrans,
|
||||||
|
output logic hmastlock,
|
||||||
|
output logic [SCR1_AHB_WIDTH-1:0] haddr,
|
||||||
|
input logic hready,
|
||||||
|
input logic [SCR1_AHB_WIDTH-1:0] hrdata,
|
||||||
|
input logic hresp
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Local parameters declaration
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
`ifndef SCR1_IMEM_AHB_OUT_BP
|
||||||
|
localparam SCR1_FIFO_WIDTH = 2;
|
||||||
|
localparam SCR1_FIFO_CNT_WIDTH = $clog2(SCR1_FIFO_WIDTH+1);
|
||||||
|
`endif // SCR1_IMEM_AHB_OUT_BP
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Local types declaration
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
typedef enum logic {
|
||||||
|
SCR1_FSM_ADDR = 1'b0,
|
||||||
|
SCR1_FSM_DATA = 1'b1,
|
||||||
|
SCR1_FSM_ERR = 1'bx
|
||||||
|
} type_scr1_fsm_e;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic [SCR1_AHB_WIDTH-1:0] haddr;
|
||||||
|
} type_scr1_req_fifo_s;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic hresp;
|
||||||
|
logic [SCR1_AHB_WIDTH-1:0] hrdata;
|
||||||
|
} type_scr1_resp_fifo_s;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Local signal declaration
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
type_scr1_fsm_e fsm;
|
||||||
|
logic req_fifo_rd;
|
||||||
|
logic req_fifo_wr;
|
||||||
|
logic req_fifo_up;
|
||||||
|
`ifdef SCR1_IMEM_AHB_OUT_BP
|
||||||
|
type_scr1_req_fifo_s req_fifo_r;
|
||||||
|
type_scr1_req_fifo_s [0:0] req_fifo;
|
||||||
|
`else // SCR1_IMEM_AHB_OUT_BP
|
||||||
|
type_scr1_req_fifo_s [0:SCR1_FIFO_WIDTH-1] req_fifo;
|
||||||
|
type_scr1_req_fifo_s [0:SCR1_FIFO_WIDTH-1] req_fifo_new;
|
||||||
|
logic [SCR1_FIFO_CNT_WIDTH-1:0] req_fifo_cnt;
|
||||||
|
logic [SCR1_FIFO_CNT_WIDTH-1:0] req_fifo_cnt_new;
|
||||||
|
`endif // SCR1_IMEM_AHB_OUT_BP
|
||||||
|
logic req_fifo_empty;
|
||||||
|
logic req_fifo_full;
|
||||||
|
|
||||||
|
type_scr1_resp_fifo_s resp_fifo;
|
||||||
|
logic resp_fifo_hready;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Interface to Core
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
assign imem_req_ack = ~req_fifo_full;
|
||||||
|
assign req_fifo_wr = ~req_fifo_full & imem_req;
|
||||||
|
|
||||||
|
assign imem_rdata = resp_fifo.hrdata;
|
||||||
|
|
||||||
|
assign imem_resp = (resp_fifo_hready)
|
||||||
|
? (resp_fifo.hresp == SCR1_HRESP_OKAY)
|
||||||
|
? SCR1_MEM_RESP_RDY_OK
|
||||||
|
: SCR1_MEM_RESP_RDY_ER
|
||||||
|
: SCR1_MEM_RESP_NOTRDY;
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// REQ_FIFO
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
`ifdef SCR1_IMEM_AHB_OUT_BP
|
||||||
|
always_ff @(negedge rst_n, posedge clk) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
req_fifo_full <= 1'b0;
|
||||||
|
end else begin
|
||||||
|
if (~req_fifo_full) begin
|
||||||
|
req_fifo_full <= imem_req & ~req_fifo_rd;
|
||||||
|
end else begin
|
||||||
|
req_fifo_full <= ~req_fifo_rd;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
assign req_fifo_empty = ~(req_fifo_full | imem_req);
|
||||||
|
|
||||||
|
assign req_fifo_up = ~req_fifo_rd & req_fifo_wr;
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if (req_fifo_up) begin
|
||||||
|
req_fifo_r.haddr <= imem_addr;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign req_fifo[0] = (req_fifo_full) ? req_fifo_r : imem_addr;
|
||||||
|
|
||||||
|
`else // SCR1_IMEM_AHB_OUT_BP
|
||||||
|
always_comb begin
|
||||||
|
req_fifo_up = 1'b0;
|
||||||
|
req_fifo_cnt_new = req_fifo_cnt;
|
||||||
|
req_fifo_new = req_fifo;
|
||||||
|
case ({req_fifo_rd, req_fifo_wr})
|
||||||
|
2'b00 : begin
|
||||||
|
// nothing todo
|
||||||
|
end
|
||||||
|
2'b01: begin
|
||||||
|
// FIFO write
|
||||||
|
req_fifo_up = 1'b1;
|
||||||
|
req_fifo_new[req_fifo_cnt].haddr = imem_addr;
|
||||||
|
req_fifo_cnt_new = req_fifo_cnt + 1'b1;
|
||||||
|
end
|
||||||
|
2'b10 : begin
|
||||||
|
// FIFO read
|
||||||
|
req_fifo_up = 1'b1;
|
||||||
|
req_fifo_new[0] = req_fifo_new[1];
|
||||||
|
req_fifo_new[1].haddr = 'x;
|
||||||
|
req_fifo_cnt_new = req_fifo_cnt - 1'b1;
|
||||||
|
end
|
||||||
|
2'b11 : begin
|
||||||
|
// Read and Write FIFO. It is possible only when fifo_cnt = 1
|
||||||
|
req_fifo_up = 1'b1;
|
||||||
|
req_fifo_new[0].haddr = imem_addr;
|
||||||
|
end
|
||||||
|
default : begin
|
||||||
|
req_fifo_up = 'x;
|
||||||
|
req_fifo_cnt_new = 'x;
|
||||||
|
req_fifo_new = 'x;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
always_ff @(negedge rst_n, posedge clk) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
req_fifo_cnt <= '0;
|
||||||
|
end else begin
|
||||||
|
if (req_fifo_up) begin
|
||||||
|
req_fifo_cnt <= req_fifo_cnt_new;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
assign req_fifo_full = (req_fifo_cnt == SCR1_FIFO_WIDTH);
|
||||||
|
assign req_fifo_empty = ~(|req_fifo_cnt);
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if (req_fifo_up) begin
|
||||||
|
req_fifo <= req_fifo_new;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
`endif // SCR1_IMEM_AHB_OUT_BP
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// FSM
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
always_ff @(negedge rst_n, posedge clk) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
fsm <= SCR1_FSM_ADDR;
|
||||||
|
end else begin
|
||||||
|
case (fsm)
|
||||||
|
SCR1_FSM_ADDR : begin
|
||||||
|
if (hready) begin
|
||||||
|
fsm <= (req_fifo_empty) ? SCR1_FSM_ADDR : SCR1_FSM_DATA;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
SCR1_FSM_DATA : begin
|
||||||
|
if (hready) begin
|
||||||
|
if (hresp == SCR1_HRESP_OKAY) begin
|
||||||
|
fsm <= (req_fifo_empty) ? SCR1_FSM_ADDR : SCR1_FSM_DATA;
|
||||||
|
end else begin
|
||||||
|
fsm <= SCR1_FSM_ADDR;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
default : begin
|
||||||
|
fsm <= SCR1_FSM_ERR;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
req_fifo_rd = 1'b0;
|
||||||
|
case (fsm)
|
||||||
|
SCR1_FSM_ADDR : begin
|
||||||
|
if (hready) begin
|
||||||
|
req_fifo_rd = ~req_fifo_empty;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
SCR1_FSM_DATA : begin
|
||||||
|
if (hready) begin
|
||||||
|
req_fifo_rd = ~req_fifo_empty & (hresp == SCR1_HRESP_OKAY);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
default : begin
|
||||||
|
req_fifo_rd = 1'bx;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// FIFO response
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
`ifdef SCR1_IMEM_AHB_IN_BP
|
||||||
|
assign resp_fifo_hready = (fsm == SCR1_FSM_DATA) ? hready : 1'b0;
|
||||||
|
assign resp_fifo.hresp = hresp;
|
||||||
|
assign resp_fifo.hrdata = hrdata;
|
||||||
|
`else // SCR1_IMEM_AHB_IN_BP
|
||||||
|
always_ff @(negedge rst_n, posedge clk) begin
|
||||||
|
if (~rst_n) begin
|
||||||
|
resp_fifo_hready <= 1'b0;
|
||||||
|
end else begin
|
||||||
|
resp_fifo_hready <= (fsm == SCR1_FSM_DATA) ? hready : 1'b0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if (hready & (fsm == SCR1_FSM_DATA)) begin
|
||||||
|
resp_fifo.hresp <= hresp;
|
||||||
|
resp_fifo.hrdata <= hrdata;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
`endif // SCR1_IMEM_AHB_IN_BP
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Interface to AHB
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
assign hprot[SCR1_HPROT_DATA] = 1'b0;
|
||||||
|
assign hprot[SCR1_HPROT_PRV] = 1'b0;
|
||||||
|
assign hprot[SCR1_HPROT_BUF] = 1'b0;
|
||||||
|
assign hprot[SCR1_HPROT_CACHE] = 1'b0;
|
||||||
|
|
||||||
|
assign hburst = SCR1_HBURST_SINGLE;
|
||||||
|
assign hsize = SCR1_HSIZE_32B;
|
||||||
|
assign hmastlock = 1'b0;
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
htrans = SCR1_HTRANS_IDLE;
|
||||||
|
case (fsm)
|
||||||
|
SCR1_FSM_ADDR : begin
|
||||||
|
if (~req_fifo_empty) begin
|
||||||
|
htrans = SCR1_HTRANS_NONSEQ;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
SCR1_FSM_DATA : begin
|
||||||
|
if (hready) begin
|
||||||
|
if (hresp == SCR1_HRESP_OKAY) begin
|
||||||
|
if (~req_fifo_empty) begin
|
||||||
|
htrans = SCR1_HTRANS_NONSEQ;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
default : begin
|
||||||
|
htrans = SCR1_HTRANS_ERR;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
assign haddr = req_fifo[0].haddr;
|
||||||
|
|
||||||
|
`ifdef SCR1_TRGT_SIMULATION
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
// Assertion
|
||||||
|
//-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Check Core interface
|
||||||
|
SCR1_SVA_IMEM_AHB_BRIDGE_REQ_XCHECK : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
!$isunknown(imem_req)
|
||||||
|
) else $error("IMEM AHB bridge Error: imem_req has unknown values");
|
||||||
|
|
||||||
|
SCR1_IMEM_AHB_BRIDGE_ADDR_XCHECK : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
imem_req |-> !$isunknown(imem_addr)
|
||||||
|
) else $error("IMEM AHB bridge Error: imem_addr has unknown values");
|
||||||
|
|
||||||
|
SCR1_IMEM_AHB_BRIDGE_ADDR_ALLIGN : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
imem_req |-> (imem_addr[1:0] == '0)
|
||||||
|
) else $error("IMEM AHB bridge Error: imem_addr has unalign values");
|
||||||
|
|
||||||
|
// Check AHB interface
|
||||||
|
SCR1_IMEM_AHB_BRIDGE_HREADY_XCHECK : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
!$isunknown(hready)
|
||||||
|
) else $error("IMEM AHB bridge Error: hready has unknown values");
|
||||||
|
|
||||||
|
SCR1_IMEM_AHB_BRIDGE_HRESP_XCHECK : assert property (
|
||||||
|
@(negedge clk) disable iff (~rst_n)
|
||||||
|
!$isunknown(hresp)
|
||||||
|
) else $error("IMEM AHB bridge Error: hresp has unknown values");
|
||||||
|
|
||||||
|
`endif // SCR1_TRGT_SIMULATION
|
||||||
|
|
||||||
|
endmodule : scr1_imem_ahb
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user