tinyriscv/rtl/core/tinyriscv_core.sv

350 lines
11 KiB
Systemverilog

/*
Copyright 2019 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
`include "defines.sv"
// tinyriscv处理器核顶层模块
module tinyriscv_core #(
parameter int unsigned DEBUG_HALT_ADDR = 32'h10000800,
parameter int unsigned DEBUG_EXCEPTION_ADDR = 32'h10000808
)(
input wire clk,
input wire rst_n,
// instr fetch interface
output wire instr_req_o,
input wire instr_gnt_i,
input wire instr_rvalid_i,
output wire[31:0] instr_addr_o,
input wire[31:0] instr_rdata_i,
input wire instr_err_i,
// data access interface
output wire data_req_o,
input wire data_gnt_i,
input wire data_rvalid_i,
output wire data_we_o,
output wire[3:0] data_be_o,
output wire[31:0] data_addr_o,
output wire[31:0] data_wdata_o,
input wire[31:0] data_rdata_i,
input wire data_err_i,
// interrupt inputs
input wire irq_software_i,
input wire irq_timer_i,
input wire irq_external_i,
input wire[14:0] irq_fast_i,
// debug req signal
input wire debug_req_i
);
// ifu模块输出信号
wire[31:0] ifetch_inst_o;
wire[31:0] ifetch_pc_o;
wire ifetch_inst_valid_o;
// ifu_idu模块输出信号
wire[31:0] if_inst_o;
wire[31:0] if_inst_addr_o;
wire[`INT_WIDTH-1:0] if_int_flag_o;
wire if_inst_valid_o;
// idu模块输出信号
wire[31:0] id_inst_o;
wire[31:0] id_inst_addr_o;
wire[`DECINFO_WIDTH-1:0] id_dec_info_bus_o;
wire[31:0] id_dec_imm_o;
wire[31:0] id_dec_pc_o;
wire[4:0] id_rs1_raddr_o;
wire[4:0] id_rs2_raddr_o;
wire[4:0] id_rd_waddr_o;
wire id_rd_we_o;
wire id_stall_o;
wire[31:0] id_rs1_rdata_o;
wire[31:0] id_rs2_rdata_o;
// idu_exu模块输出信号
wire[31:0] ie_inst_o;
wire[31:0] ie_inst_addr_o;
wire[`DECINFO_WIDTH-1:0] ie_dec_info_bus_o;
wire[31:0] ie_dec_imm_o;
wire[31:0] ie_dec_pc_o;
wire[31:0] ie_rs1_rdata_o;
wire[31:0] ie_rs2_rdata_o;
wire[4:0] ie_rd_waddr_o;
wire ie_rd_we_o;
wire ie_inst_valid_o;
// exu模块输出信号
wire[31:0] ex_mem_wdata_o;
wire[31:0] ex_mem_addr_o;
wire ex_mem_we_o;
wire[3:0] ex_mem_sel_o;
wire ex_mem_req_valid_o;
wire ex_mem_rsp_ready_o;
wire ex_mem_access_misaligned_o;
wire[31:0] ex_reg_wdata_o;
wire ex_reg_we_o;
wire[4:0] ex_reg_waddr_o;
wire ex_hold_flag_o;
wire ex_jump_flag_o;
wire[31:0] ex_jump_addr_o;
wire[31:0] ex_csr_wdata_o;
wire ex_csr_we_o;
wire[31:0] ex_csr_waddr_o;
wire[31:0] ex_csr_raddr_o;
wire ex_inst_ecall_o;
wire ex_inst_ebreak_o;
wire ex_inst_mret_o;
wire ex_inst_dret_o;
wire ex_inst_valid_o;
// gpr_reg模块输出信号
wire[31:0] regs_rdata1_o;
wire[31:0] regs_rdata2_o;
// csr_reg模块输出信号
wire[31:0] csr_ex_data_o;
wire[31:0] csr_clint_data_o;
wire[31:0] csr_mtvec_o;
wire[31:0] csr_mepc_o;
wire[31:0] csr_mstatus_o;
wire[31:0] csr_mie_o;
wire[31:0] csr_dpc_o;
wire[31:0] csr_dcsr_o;
// pipe_ctrl模块输出信号
wire[31:0] ctrl_flush_addr_o;
wire ctrl_flush_o;
wire[`STALL_WIDTH-1:0] ctrl_stall_o;
// clint模块输出信号
wire clint_csr_we_o;
wire[31:0] clint_csr_waddr_o;
wire[31:0] clint_csr_wdata_o;
wire clint_stall_flag_o;
wire[31:0] clint_int_addr_o;
wire clint_int_assert_o;
ifu u_ifu(
.clk(clk),
.rst_n(rst_n),
.flush_addr_i(ctrl_flush_addr_o),
.stall_i(ctrl_stall_o),
.flush_i(ctrl_flush_o),
.inst_o(ifetch_inst_o),
.pc_o(ifetch_pc_o),
.inst_valid_o(ifetch_inst_valid_o),
.instr_req_o(instr_req_o),
.instr_gnt_i(instr_gnt_i),
.instr_rvalid_i(instr_rvalid_i),
.instr_addr_o(instr_addr_o),
.instr_rdata_i(instr_rdata_i),
.instr_err_i(instr_err_i)
);
pipe_ctrl u_pipe_ctrl(
.clk(clk),
.rst_n(rst_n),
.stall_from_id_i(id_stall_o),
.stall_from_ex_i(ex_hold_flag_o),
.stall_from_jtag_i(1'b0),
.stall_from_clint_i(clint_stall_flag_o),
.jump_assert_i(ex_jump_flag_o),
.jump_addr_i(ex_jump_addr_o),
.flush_o(ctrl_flush_o),
.stall_o(ctrl_stall_o),
.flush_addr_o(ctrl_flush_addr_o)
);
gpr_reg u_gpr_reg(
.clk(clk),
.rst_n(rst_n),
.we_i(ex_reg_we_o),
.waddr_i(ex_reg_waddr_o),
.wdata_i(ex_reg_wdata_o),
.raddr1_i(id_rs1_raddr_o),
.rdata1_o(regs_rdata1_o),
.raddr2_i(id_rs2_raddr_o),
.rdata2_o(regs_rdata2_o)
);
csr_reg u_csr_reg(
.clk(clk),
.rst_n(rst_n),
.exu_we_i(ex_csr_we_o),
.exu_raddr_i(ex_csr_raddr_o),
.exu_waddr_i(ex_csr_waddr_o),
.exu_wdata_i(ex_csr_wdata_o),
.exu_rdata_o(csr_ex_data_o),
.clint_we_i(clint_csr_we_o),
.clint_waddr_i(clint_csr_waddr_o),
.clint_wdata_i(clint_csr_wdata_o),
.mtvec_o(csr_mtvec_o),
.mepc_o(csr_mepc_o),
.mstatus_o(csr_mstatus_o),
.mie_o(csr_mie_o),
.dpc_o(csr_dpc_o),
.dcsr_o(csr_dcsr_o)
);
ifu_idu u_ifu_idu(
.clk(clk),
.rst_n(rst_n),
.inst_i(ifetch_inst_o),
.inst_addr_i(ifetch_pc_o),
.stall_i(ctrl_stall_o),
.flush_i(ctrl_flush_o),
.inst_valid_i(ifetch_inst_valid_o),
.inst_valid_o(if_inst_valid_o),
.inst_o(if_inst_o),
.inst_addr_o(if_inst_addr_o)
);
idu u_idu(
.clk(clk),
.rst_n(rst_n),
.inst_i(if_inst_o),
.rs1_rdata_i(regs_rdata1_o),
.rs2_rdata_i(regs_rdata2_o),
.inst_o(id_inst_o),
.inst_addr_i(if_inst_addr_o),
.rs1_rdata_o(id_rs1_rdata_o),
.rs2_rdata_o(id_rs2_rdata_o),
.stall_o(id_stall_o),
.dec_info_bus_o(id_dec_info_bus_o),
.dec_imm_o(id_dec_imm_o),
.dec_pc_o(id_dec_pc_o),
.rs1_raddr_o(id_rs1_raddr_o),
.rs2_raddr_o(id_rs2_raddr_o),
.rd_waddr_o(id_rd_waddr_o),
.rd_we_o(id_rd_we_o)
);
idu_exu u_idu_exu(
.clk(clk),
.rst_n(rst_n),
.inst_i(id_inst_o),
.stall_i(ctrl_stall_o),
.flush_i(ctrl_flush_o),
.dec_info_bus_i(id_dec_info_bus_o),
.dec_imm_i(id_dec_imm_o),
.dec_pc_i(id_dec_pc_o),
.rs1_rdata_i(id_rs1_rdata_o),
.rs2_rdata_i(id_rs2_rdata_o),
.rd_waddr_i(id_rd_waddr_o),
.rd_we_i(id_rd_we_o),
.inst_valid_i(if_inst_valid_o),
.inst_valid_o(ie_inst_valid_o),
.inst_o(ie_inst_o),
.dec_info_bus_o(ie_dec_info_bus_o),
.dec_imm_o(ie_dec_imm_o),
.dec_pc_o(ie_dec_pc_o),
.rs1_rdata_o(ie_rs1_rdata_o),
.rs2_rdata_o(ie_rs2_rdata_o),
.rd_waddr_o(ie_rd_waddr_o),
.rd_we_o(ie_rd_we_o)
);
exu u_exu(
.clk(clk),
.rst_n(rst_n),
.reg1_rdata_i(ie_rs1_rdata_o),
.reg2_rdata_i(ie_rs2_rdata_o),
.mem_rdata_i(data_rdata_i),
.mem_gnt_i(data_gnt_i),
.mem_rvalid_i(data_rvalid_i),
.mem_wdata_o(data_wdata_o),
.mem_addr_o(data_addr_o),
.mem_we_o(data_we_o),
.mem_be_o(data_be_o),
.mem_req_o(data_req_o),
.mem_access_misaligned_o(ex_mem_access_misaligned_o),
.reg_wdata_o(ex_reg_wdata_o),
.reg_we_o(ex_reg_we_o),
.reg_waddr_o(ex_reg_waddr_o),
.hold_flag_o(ex_hold_flag_o),
.jump_flag_o(ex_jump_flag_o),
.jump_addr_o(ex_jump_addr_o),
.int_assert_i(clint_int_assert_o),
.int_addr_i(clint_int_addr_o),
.inst_ecall_o(ex_inst_ecall_o),
.inst_ebreak_o(ex_inst_ebreak_o),
.inst_mret_o(ex_inst_mret_o),
.inst_dret_o(ex_inst_dret_o),
.int_stall_i(clint_stall_flag_o),
.csr_raddr_o(ex_csr_raddr_o),
.csr_rdata_i(csr_ex_data_o),
.csr_wdata_o(ex_csr_wdata_o),
.csr_we_o(ex_csr_we_o),
.csr_waddr_o(ex_csr_waddr_o),
.inst_valid_o(ex_inst_valid_o),
.inst_valid_i(ie_inst_valid_o),
.inst_i(ie_inst_o),
.dec_info_bus_i(ie_dec_info_bus_o),
.dec_imm_i(ie_dec_imm_o),
.dec_pc_i(ie_dec_pc_o),
.next_pc_i(if_inst_addr_o),
.rd_waddr_i(ie_rd_waddr_o),
.rd_we_i(ie_rd_we_o)
);
exception u_exception(
.clk(clk),
.rst_n(rst_n),
.inst_valid_i(ex_inst_valid_o),
.inst_ecall_i(ex_inst_ecall_o),
.inst_ebreak_i(ex_inst_ebreak_o),
.inst_mret_i(ex_inst_mret_o),
.inst_dret_i(ex_inst_dret_o),
.inst_addr_i(ie_dec_pc_o),
.mtvec_i(csr_mtvec_o),
.mepc_i(csr_mepc_o),
.mstatus_i(csr_mstatus_o),
.mie_i(csr_mie_o),
.dpc_i(csr_dpc_o),
.dcsr_i(csr_dcsr_o),
.irq_software_i(irq_software_i),
.irq_timer_i(irq_timer_i),
.irq_external_i(irq_external_i),
.irq_fast_i(irq_fast_i),
.debug_halt_addr_i(DEBUG_HALT_ADDR),
.debug_req_i(debug_req_i),
.csr_we_o(clint_csr_we_o),
.csr_waddr_o(clint_csr_waddr_o),
.csr_wdata_o(clint_csr_wdata_o),
.stall_flag_o(clint_stall_flag_o),
.int_addr_o(clint_int_addr_o),
.int_assert_o(clint_int_assert_o)
);
`ifdef TRACE_ENABLED
tracer u_tracer(
.clk(clk),
.rst_n(rst_n),
.inst_i(ie_inst_o),
.pc_i(ie_dec_pc_o),
.inst_valid_i(ex_inst_valid_o)
);
`endif
endmodule