init repo: update to RV32IMA (M mode)

This commit is contained in:
2025-05-23 00:15:19 +08:00
commit 9135170576
18 changed files with 3509 additions and 0 deletions

37
.gitignore vendored Normal file
View File

@@ -0,0 +1,37 @@
*
!*/
# track this file or dic
!.gitignore
!readme.md
doc/**
!others/**
# vivado
!rv_cpu.xpr
## srcs
!rv_cpu.srcs/constrs_1/**
!rv_cpu.srcs/sources_1/ip/*/*.xci
!rv_cpu.srcs/sources_1/ip/*/*.coe
!rv_cpu.srcs/sources_1/new/**
!rv_cpu.srcs/sources_1/imports/**
!rv_cpu.srcs/sources_1/bd/**
## sims
!rv_cpu.srcs/sim_1/**
!rv_cpu.sim/sim_1/behav/modelsim/*.do
rv_cpu.sim/sim_1/behav/xsim/*.wdb
!rv_cpu.sim/sim_1/*.wcfg
## bits
!rv_cpu.runs/impl_1/*.bit
!rv_cpu.runs/impl_1/*.bin
!rv_cpu.runs/impl_1/*.ltx
!rv_cpu.runs/bits/*.bit
!rv_cpu.runs/bits/*.bin
!rv_cpu.runs/bits/*.ltx

View File

@@ -0,0 +1,271 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2025/05/17 14:00:00
// Design Name: cpu_top
// Module Name: cpu_top
// Project Name: rv_cpu
// Target Devices:
// Tool Versions:
// Description: Top module for the RISC-V CPU, connecting pipeline stages.
//
// Dependencies: if_stage, id_stage, exe_stage, mem_stage, wb_stage
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module cpu_top (
// Global signals
input clk_i,
input rstn_i,
// Instruction SRAM interface
output inst_sram_en_o,
output [ 3:0] inst_sram_wen_o,
output [31:0] inst_sram_addr_o,
output [31:0] inst_sram_wdata_o,
input [31:0] inst_sram_rdata_i,
// Data SRAM interface
output data_sram_en_o,
output [ 3:0] data_sram_wen_o,
output [31:0] data_sram_addr_o,
output [31:0] data_sram_wdata_o,
input [31:0] data_sram_rdata_i,
// Debug signals from WB stage
output [31:0] debug_wb_pc_o,
output [ 3:0] debug_wb_rf_wen_o,
output [ 4:0] debug_wb_rf_waddr_o,
output [31:0] debug_wb_rf_wdata_o
);
// Define local parameters for bus widths based on stage module parameters
localparam FS_TO_DS_BUS_WIDTH = 65;
localparam DS_TO_ES_BUS_WIDTH = 315;
localparam ES_TO_MS_BUS_WIDTH = 164;
localparam MS_TO_WS_BUS_WIDTH = 70;
localparam WS_TO_DS_BUS_WIDTH = 38;
localparam ES_TO_DS_FWD_BUS_WIDTH = 39;
localparam MS_TO_DS_FWD_BUS_WIDTH = 38;
// Wires for IF <-> ID pipeline registers
wire [FS_TO_DS_BUS_WIDTH-1:0] fs_to_ds_bus_data;
wire fs_to_ds_bus_valid;
wire fs_to_ds_bus_ready;
// Wires for ID <-> EXE pipeline registers
wire [DS_TO_ES_BUS_WIDTH-1:0] ds_to_es_bus_data;
wire ds_to_es_bus_valid;
wire ds_to_es_bus_ready;
// Wires for EXE <-> MEM pipeline registers
wire [ES_TO_MS_BUS_WIDTH-1:0] es_to_ms_bus_data;
wire es_to_ms_bus_valid;
wire es_to_ms_bus_ready;
// Wires for MEM <-> WB pipeline registers
wire [MS_TO_WS_BUS_WIDTH-1:0] ms_to_ws_bus_data;
wire ms_to_ws_bus_valid;
wire ms_to_ws_bus_ready;
// Wires for WB -> ID (write-back path)
wire [WS_TO_DS_BUS_WIDTH-1:0] ws_to_ds_bus_data;
wire ws_to_ds_bus_valid;
// Wires for branch prediction (EXE -> IF)
wire [31:0] br_target;
wire br_taken;
// Fowarding buses for ID stage
wire [ES_TO_DS_FWD_BUS_WIDTH-1:0] es_to_ds_fwd_bus_data;
wire [MS_TO_DS_FWD_BUS_WIDTH-1:0] ms_to_ds_fwd_bus_data;
wire [ 1:0] csr_mpp;
wire es_a_ext_stall;
wire ms_a_ext_stall;
wire load_stall;
wire m_ext_stall;
wire a_ext_stall;
wire csr_flush;
wire br_flush;
wire es_data_sram_en;
wire [ 3:0] es_data_sram_wen;
wire [31:0] es_data_sram_addr;
wire [31:0] es_data_sram_wdata;
wire ms_data_sram_en;
wire [ 3:0] ms_data_sram_wen;
wire [31:0] ms_data_sram_addr;
wire [31:0] ms_data_sram_wdata;
assign a_ext_stall = es_a_ext_stall | ms_a_ext_stall;
// Instantiate IF Stage
if_stage #(
.FS_TO_DS_BUS_WIDTH(FS_TO_DS_BUS_WIDTH)
) inst_if_stage (
.clk_i (clk_i),
.rstn_i (rstn_i),
.load_stall_i (load_stall),
.m_ext_stall_i (m_ext_stall),
.a_ext_stall_i (a_ext_stall),
.br_flush_i (br_flush),
.csr_flush_i (csr_flush),
.br_target_i (br_target),
.br_taken_i (br_taken),
.fs_to_ds_bus_ready_i (fs_to_ds_bus_ready),
.fs_to_ds_bus_data_o (fs_to_ds_bus_data),
.fs_to_ds_bus_valid_o (fs_to_ds_bus_valid),
.inst_sram_en_o (inst_sram_en_o),
.inst_sram_wen_o (inst_sram_wen_o),
.inst_sram_addr_o (inst_sram_addr_o),
.inst_sram_wdata_o (inst_sram_wdata_o),
.inst_sram_rdata_i (inst_sram_rdata_i)
);
// Instantiate ID Stage
id_stage #(
.FS_TO_DS_BUS_WIDTH(FS_TO_DS_BUS_WIDTH),
.DS_TO_ES_BUS_WIDTH(DS_TO_ES_BUS_WIDTH),
.WS_TO_DS_BUS_WIDTH(WS_TO_DS_BUS_WIDTH),
.ES_TO_DS_FWD_BUS_WIDTH(ES_TO_DS_FWD_BUS_WIDTH),
.MS_TO_DS_FWD_BUS_WIDTH(MS_TO_DS_FWD_BUS_WIDTH)
) inst_id_stage (
.clk_i (clk_i),
.rstn_i (rstn_i),
.csr_mpp_i (csr_mpp),
.csr_flush_i (csr_flush),
.m_ext_stall_i (m_ext_stall),
.a_ext_stall_i (a_ext_stall),
.fs_to_ds_bus_ready_o (fs_to_ds_bus_ready),
.fs_to_ds_bus_data_i (fs_to_ds_bus_data),
.fs_to_ds_bus_valid_i (fs_to_ds_bus_valid),
.ds_to_es_bus_ready_i (ds_to_es_bus_ready),
.ds_to_es_bus_data_o (ds_to_es_bus_data),
.ds_to_es_bus_valid_o (ds_to_es_bus_valid),
.ws_to_ds_bus_data_i (ws_to_ds_bus_data),
.ws_to_ds_bus_valid_i (ws_to_ds_bus_valid),
.es_to_ds_fwd_bus_data_i (es_to_ds_fwd_bus_data),
.ms_to_ds_fwd_bus_data_i (ms_to_ds_fwd_bus_data),
.br_flush_o (br_flush),
.load_stall_o (load_stall)
);
// Instantiate EXE Stage
exe_stage #(
.DS_TO_ES_BUS_WIDTH(DS_TO_ES_BUS_WIDTH),
.ES_TO_MS_BUS_WIDTH(ES_TO_MS_BUS_WIDTH),
.ES_TO_DS_FWD_BUS_WIDTH(ES_TO_DS_FWD_BUS_WIDTH)
) inst_exe_stage (
.clk_i (clk_i),
.rstn_i (rstn_i),
.ds_to_es_bus_ready_o (ds_to_es_bus_ready),
.ds_to_es_bus_data_i (ds_to_es_bus_data),
.ds_to_es_bus_valid_i (ds_to_es_bus_valid),
.es_to_ms_bus_ready_i (es_to_ms_bus_ready),
.es_to_ms_bus_data_o (es_to_ms_bus_data),
.es_to_ms_bus_valid_o (es_to_ms_bus_valid),
.br_target_o (br_target),
.br_taken_o (br_taken),
.data_sram_en_o (es_data_sram_en),
.data_sram_wen_o (es_data_sram_wen),
.data_sram_addr_o (es_data_sram_addr),
.data_sram_wdata_o (es_data_sram_wdata),
.es_to_ds_fwd_bus_data_o(es_to_ds_fwd_bus_data),
.csr_mpp_o (csr_mpp),
.m_ext_stall_o (m_ext_stall),
.a_ext_stall_o (es_a_ext_stall),
.csr_flush_o (csr_flush)
);
// Instantiate MEM Stage
mem_stage #(
.ES_TO_MS_BUS_WIDTH(ES_TO_MS_BUS_WIDTH),
.MS_TO_WS_BUS_WIDTH(MS_TO_WS_BUS_WIDTH),
.MS_TO_DS_FWD_BUS_WIDTH(MS_TO_DS_FWD_BUS_WIDTH)
) inst_mem_stage (
.clk_i (clk_i),
.rstn_i (rstn_i),
.csr_flush_i (csr_flush),
.es_to_ms_bus_ready_o (es_to_ms_bus_ready),
.es_to_ms_bus_data_i (es_to_ms_bus_data),
.es_to_ms_bus_valid_i (es_to_ms_bus_valid),
.ms_to_ws_bus_ready_i (ms_to_ws_bus_ready),
.ms_to_ws_bus_data_o (ms_to_ws_bus_data),
.ms_to_ws_bus_valid_o (ms_to_ws_bus_valid),
.data_sram_rdata_i (data_sram_rdata_i),
.data_sram_en_o (ms_data_sram_en),
.data_sram_wen_o (ms_data_sram_wen),
.data_sram_addr_o (ms_data_sram_addr),
.data_sram_wdata_o (ms_data_sram_wdata),
.a_ext_stall_o (ms_a_ext_stall),
.ms_to_ds_fwd_bus_data_o(ms_to_ds_fwd_bus_data)
);
// Instantiate WB Stage
wb_stage #(
.MS_TO_WS_BUS_WIDTH(MS_TO_WS_BUS_WIDTH),
.WS_TO_DS_BUS_WIDTH(WS_TO_DS_BUS_WIDTH)
) inst_wb_stage (
.clk_i (clk_i),
.rstn_i (rstn_i),
.ms_to_ws_bus_ready_o (ms_to_ws_bus_ready),
.ms_to_ws_bus_data_i (ms_to_ws_bus_data),
.ms_to_ws_bus_valid_i (ms_to_ws_bus_valid),
.ws_to_ds_bus_data_o (ws_to_ds_bus_data),
.ws_to_ds_bus_valid_o (ws_to_ds_bus_valid),
.debug_wb_pc_o (debug_wb_pc_o),
.debug_wb_rf_wen_o (debug_wb_rf_wen_o),
.debug_wb_rf_waddr_o (debug_wb_rf_waddr_o),
.debug_wb_rf_wdata_o (debug_wb_rf_wdata_o)
);
assign data_sram_en_o = es_data_sram_en
| ms_data_sram_en;
assign data_sram_wen_o = {4{es_data_sram_en}} & es_data_sram_wen
| {4{ms_data_sram_en}} & ms_data_sram_wen;
assign data_sram_addr_o = {32{es_data_sram_en}} & es_data_sram_addr
| {32{ms_data_sram_en}} & ms_data_sram_addr;
assign data_sram_wdata_o = {32{es_data_sram_en}} & es_data_sram_wdata
| {32{ms_data_sram_en}} & ms_data_sram_wdata;
endmodule

View File

@@ -0,0 +1,287 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2025/05/17 04:05:18
// Design Name:
// Module Name: exe_stage
// Project Name:
// Target Devices:
// Tool Versions:
// Desrciption:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module exe_stage #(
parameter DS_TO_ES_BUS_WIDTH = 315,
parameter ES_TO_MS_BUS_WIDTH = 164,
parameter ES_TO_DS_FWD_BUS_WIDTH = 39
)
(
input clk_i,
input rstn_i,
output ds_to_es_bus_ready_o,
input [DS_TO_ES_BUS_WIDTH-1:0] ds_to_es_bus_data_i,
input ds_to_es_bus_valid_i,
input es_to_ms_bus_ready_i,
output [ES_TO_MS_BUS_WIDTH-1:0] es_to_ms_bus_data_o,
output es_to_ms_bus_valid_o,
output [31:0] br_target_o,
output br_taken_o,
output data_sram_en_o,
output [ 3:0] data_sram_wen_o,
output [31:0] data_sram_addr_o,
output [31:0] data_sram_wdata_o,
// fowarding bus to ID stage
output [ES_TO_DS_FWD_BUS_WIDTH-1:0] es_to_ds_fwd_bus_data_o,
output [ 1:0] csr_mpp_o,
output m_ext_stall_o,
output a_ext_stall_o,
output csr_flush_o
);
reg ds_to_es_bus_valid;
reg [DS_TO_ES_BUS_WIDTH-1:0] ds_to_es_bus_data;
wire es_pipeline_stall;
wire es_to_ms_bus_valid;
wire [31:0] es_inst;
wire [31:0] es_pc;
wire [ 4:0] es_rs1;
wire [ 4:0] es_rs2;
wire [ 4:0] es_rd;
wire [31:0] es_imm;
wire [ 4:0] es_shamt;
wire [11:0] es_csr;
wire [ 4:0] es_zimm;
wire [10:0] es_alu_op;
wire [ 3:0] es_calc_src1_sel;
wire [ 3:0] es_calc_src2_sel;
wire [ 1:0] es_jump_op;
wire [ 5:0] es_load_op;
wire [ 2:0] es_store_op;
wire [11:0] es_amo_op;
wire [31:0] es_rs1_value;
wire [31:0] es_rs2_value;
wire [31:0] es_br_target;
wire es_br_taken;
wire [ 2:0] es_csr_op;
wire [ 7:0] es_m_ext_op;
wire es_op_is_alu;
wire es_op_is_m_ext;
wire es_op_is_jump;
wire es_op_is_branch;
wire es_op_is_load;
wire es_op_is_store;
wire es_op_is_csr;
wire es_op_is_amo;
wire [31:0] es_calc_src1;
wire [31:0] es_calc_src2;
wire [31:0] es_excp_vec;
wire [31:0] es_alu_result;
wire [31:0] es_result;
wire [ 2:0] es_result_sel;
wire [31:0] es_m_ext_result;
wire es_m_ext_valid;
wire [31:0] es_csr_result;
wire es_csr_taken;
wire [31:0] es_csr_target;
assign es_pipeline_stall = m_ext_stall_o;
assign {
es_excp_vec, // 314:283 (32 bits)
es_amo_op, // 282:271 (12 bits)
es_csr_op, // 270:268 (3 bits)
es_m_ext_op, // 267:260 (8 bits)
es_br_taken, // 259:259 (1 bit)
es_br_target, // 258:227 (32 bits)
es_store_op, // 226:224 (3 bits)
es_load_op, // 223:218 (6 bits)
es_jump_op, // 217:216 (2 bits)
es_alu_op, // 215:205 (11 bits)
es_calc_src2_sel, // 204:201 (4 bits)
es_calc_src1_sel, // 200:197 (4 bits)
es_rd, // 196:192 (5 bits)
es_rs2, // 191:187 (5 bits)
es_rs1, // 186:182 (5 bits)
es_zimm, // 181:177 (5 bits)
es_csr, // 176:165 (12 bits)
es_shamt, // 164:160 (5 bits)
es_imm, // 159:128 (32 bits)
es_rs2_value, // 127:96 (32 bits)
es_rs1_value, // 95:64 (32 bits)
es_pc, // 63:32 (32 bits)
es_inst // 31:0 (32 bits)
} = ds_to_es_bus_data;
assign es_to_ms_bus_valid = !es_pipeline_stall;
always @(posedge clk_i or negedge rstn_i) begin
if (!rstn_i) begin
ds_to_es_bus_valid <= 1'b0;
end
else if (csr_flush_o) begin
ds_to_es_bus_valid <= 1'b0;
end
else if (ds_to_es_bus_ready_o) begin
ds_to_es_bus_valid <= ds_to_es_bus_valid_i;
end
else begin
ds_to_es_bus_valid <= ds_to_es_bus_valid;
end
end
always @(posedge clk_i or negedge rstn_i) begin
if (!rstn_i) begin
ds_to_es_bus_data <= {DS_TO_ES_BUS_WIDTH{1'b0}};
end
else if (ds_to_es_bus_valid_i && ds_to_es_bus_ready_o) begin
ds_to_es_bus_data <= ds_to_es_bus_data_i;
end
else begin
ds_to_es_bus_data <= ds_to_es_bus_data;
end
end
assign es_op_is_alu = |es_alu_op;
assign es_op_is_m_ext = |es_m_ext_op;
assign es_op_is_jump = |es_jump_op;
assign es_op_is_branch = |es_br_taken;
assign es_op_is_load = |es_load_op;
assign es_op_is_store = |es_store_op;
assign es_op_is_csr = |es_csr_op;
assign es_op_is_amo = |es_amo_op;
assign es_calc_src1 = {32{es_calc_src1_sel[0]}} & es_rs1_value
| {32{es_calc_src1_sel[1]}} & es_pc
| {32{es_calc_src1_sel[2]}} & 32'b0
| {32{es_calc_src1_sel[3]}} & es_zimm;
assign es_calc_src2 = {32{es_calc_src2_sel[0]}} & es_rs2_value
| {32{es_calc_src2_sel[1]}} & es_imm
| {32{es_calc_src2_sel[2]}} & 32'h4
| {32{es_calc_src2_sel[3]}} & es_shamt;
alu inst_alu(
.alu_op_i (es_alu_op),
.alu_src1_i (es_calc_src1),
.alu_src2_i (es_calc_src2),
.alu_result_o (es_alu_result)
);
m_ext_unit inst_m_ext_unit (
.clk_i (clk_i),
.rstn_i (rstn_i),
.m_ext_op_i (es_m_ext_op),
.m_ext_src1_i (es_calc_src1),
.m_ext_src2_i (es_calc_src2),
.m_ext_result_o (es_m_ext_result),
.m_ext_valid_o (es_m_ext_valid),
.m_ext_stall_o (m_ext_stall_o)
);
csr_reg_file inst_csr_reg_file (
.clk_i (clk_i),
.rstn_i (rstn_i),
.csr_pc_i (es_pc),
.csr_inst_i (es_inst),
.csr_op_i (es_csr_op),
.csr_addr_i (es_csr),
.csr_wdata_i (es_calc_src1),
.csr_rdata_o (es_csr_result),
.csr_excp_vec_i (es_excp_vec),
.csr_mpp_o (csr_mpp_o),
.csr_taken_o (es_csr_taken),
.csr_target_o (es_csr_target)
);
assign data_sram_en_o = ds_to_es_bus_valid && (es_op_is_store || es_op_is_load || es_op_is_amo);
assign data_sram_wen_o = {4{(ds_to_es_bus_valid && es_op_is_store)}}
& (
(
{4{es_store_op[0]}}
& ({4{es_alu_result[1:0] == 2'b00}} & 4'b0001)
| ({4{es_alu_result[1:0] == 2'b01}} & 4'b0010)
| ({4{es_alu_result[1:0] == 2'b10}} & 4'b0100)
| ({4{es_alu_result[1:0] == 2'b11}} & 4'b1000)
)
| (
{4{es_store_op[1]}}
& ({4{es_alu_result[1:0] == 2'b00}} & 4'b0011)
| ({4{es_alu_result[1:0] == 2'b10}} & 4'b1100)
)
| (
{4{es_store_op[2]}} & 4'b1111
)
);
assign data_sram_addr_o = es_op_is_amo ? es_calc_src1 : es_alu_result;
assign data_sram_wdata_o = ({32{es_store_op[0]}} & {4{es_rs2_value[ 7:0]}})
| ({32{es_store_op[1]}} & {2{es_rs2_value[15:0]}})
| ({32{es_store_op[2]}} & es_rs2_value );
assign es_result_sel = {es_op_is_amo, es_op_is_load, (es_op_is_csr || es_op_is_jump || (es_op_is_alu || es_op_is_m_ext) && !(es_op_is_store || es_op_is_load))};
assign es_result = {32{es_op_is_alu }} & es_alu_result
| {32{es_op_is_m_ext}} & es_m_ext_result
| {32{es_op_is_csr }} & es_csr_result;
assign es_to_ms_bus_data_o = { // Total 164 bits
es_result_sel, // 163:161 (3 bits)
es_result, // 160:129 (32 bits)
es_calc_src2, // 128:97 (32 bits)
es_calc_src1, // 96:65 (32 bits)
es_amo_op, // 64:53 (12 bits)
es_load_op, // 52:47 (6 bits)
es_rd, // 46:42 (5 bits)
es_rs2, // 41:37 (5 bits)
es_rs1, // 36:32 (5 bits)
es_pc // 31:0 (32 bits)
};
assign br_target_o = {32{es_br_taken}} & es_br_target
| {32{es_csr_taken}} & es_csr_target;
assign br_taken_o = ds_to_es_bus_valid && (es_br_taken || es_csr_taken);
assign ds_to_es_bus_ready_o = !ds_to_es_bus_valid || (es_to_ms_bus_valid && es_to_ms_bus_ready_i);
assign es_to_ms_bus_valid_o = ds_to_es_bus_valid && es_to_ms_bus_valid;
assign es_to_ds_fwd_bus_data_o = {
ds_to_es_bus_valid && es_op_is_load, // 38:38
ds_to_es_bus_valid && (es_op_is_jump || es_op_is_m_ext || es_op_is_csr || (es_op_is_alu && !(es_op_is_store || es_op_is_load))), // 37:37
es_rd, // 36:32
es_result // 31:0
};
assign a_ext_stall_o = ds_to_es_bus_valid && es_op_is_amo;
assign csr_flush_o = ds_to_es_bus_valid && es_csr_taken;
endmodule

View File

@@ -0,0 +1,308 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2025/05/17 01:26:38
// Design Name:
// Module Name: id_stage
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module id_stage #(
parameter FS_TO_DS_BUS_WIDTH = 65,
parameter DS_TO_ES_BUS_WIDTH = 315,
parameter WS_TO_DS_BUS_WIDTH = 38,
parameter ES_TO_DS_FWD_BUS_WIDTH = 39,
parameter MS_TO_DS_FWD_BUS_WIDTH = 38
)
(
input clk_i,
input rstn_i,
input m_ext_stall_i,
input a_ext_stall_i,
input csr_flush_i,
input [1:0] csr_mpp_i,
output fs_to_ds_bus_ready_o,
input [FS_TO_DS_BUS_WIDTH-1:0] fs_to_ds_bus_data_i,
input fs_to_ds_bus_valid_i,
input ds_to_es_bus_ready_i,
output [DS_TO_ES_BUS_WIDTH-1:0] ds_to_es_bus_data_o,
output ds_to_es_bus_valid_o,
input [WS_TO_DS_BUS_WIDTH-1:0] ws_to_ds_bus_data_i,
input ws_to_ds_bus_valid_i,
input [ES_TO_DS_FWD_BUS_WIDTH-1:0] es_to_ds_fwd_bus_data_i,
input [MS_TO_DS_FWD_BUS_WIDTH-1:0] ms_to_ds_fwd_bus_data_i,
output br_flush_o,
output load_stall_o
);
reg fs_to_ds_bus_valid;
reg [FS_TO_DS_BUS_WIDTH-1:0] fs_to_ds_bus_data;
wire ds_pipeline_stall;
wire ds_pipeline_flush;
wire ds_to_es_bus_valid;
wire [31:0] ds_inst;
wire [31:0] ds_pc;
wire ds_we;
wire [ 4:0] ds_waddr;
wire [31:0] ds_wdata;
wire [ 4:0] ds_rs1;
wire [ 4:0] ds_rs2;
wire [ 4:0] ds_rd;
wire [31:0] ds_imm;
wire [ 4:0] ds_shamt;
wire [11:0] ds_csr;
wire [ 4:0] ds_zimm;
wire [10:0] ds_alu_op;
wire [ 3:0] ds_calc_src1_sel;
wire [ 3:0] ds_calc_src2_sel;
wire [ 1:0] ds_jump_op;
wire [ 5:0] ds_load_op;
wire [ 2:0] ds_store_op;
wire [ 5:0] ds_branch_op;
wire [ 7:0] ds_m_ext_op;
wire [ 2:0] ds_csr_op;
wire [11:0] ds_amo_op;
wire ds_excp_illegal_inst;
wire ds_excp_breakpoint;
wire ds_excp_env_call;
wire [31:0] ds_excp_vec;
wire ds_op_is_calc;
wire ds_op_is_jump;
wire ds_op_is_branch;
wire ds_op_is_load;
wire ds_op_is_store;
wire [ 4:0] ds_raddr1;
wire [31:0] ds_rdata1;
wire [ 4:0] ds_raddr2;
wire [31:0] ds_rdata2;
wire [31:0] ds_rs1_value;
wire [31:0] ds_rs2_value;
wire ds_rs1_eq_rs2;
wire ds_rs1_lt_rs2;
wire ds_rs1_lt_rs2u;
wire [31:0] ds_br_target;
wire ds_br_taken;
wire es_fwd_we;
wire [ 4:0] es_fwd_rd;
wire [31:0] es_fwd_value;
wire es_load_use;
wire ms_fwd_we;
wire [ 4:0] ms_fwd_rd;
wire [31:0] ms_fwd_value;
assign ds_pipeline_stall = load_stall_o || m_ext_stall_i || a_ext_stall_i;
assign ds_pipeline_flush = br_flush_o || csr_flush_i;
assign {
ds_excp_inst_addr_misalign, // 64:64
ds_inst, // 63:32
ds_pc // 31:0
} = fs_to_ds_bus_data;
assign {
ds_we, // 37:37
ds_waddr, // 36:32
ds_wdata // 31:0
} = {38{ws_to_ds_bus_valid_i}} & ws_to_ds_bus_data_i;
assign {
es_load_use,
es_fwd_we,
es_fwd_rd,
es_fwd_value
} = es_to_ds_fwd_bus_data_i;
assign {
ms_fwd_we,
ms_fwd_rd,
ms_fwd_value
} = ms_to_ds_fwd_bus_data_i;
assign ds_to_es_bus_valid = !ds_pipeline_stall;
always @(posedge clk_i or negedge rstn_i) begin
if (!rstn_i) begin
fs_to_ds_bus_valid <= 1'b0;
end
else if (ds_pipeline_flush) begin
fs_to_ds_bus_valid <= 1'b0;
end
else if (fs_to_ds_bus_ready_o) begin
fs_to_ds_bus_valid <= fs_to_ds_bus_valid_i;
end
else begin
fs_to_ds_bus_valid <= fs_to_ds_bus_valid;
end
end
always @(posedge clk_i or negedge rstn_i) begin
if (!rstn_i) begin
fs_to_ds_bus_data <= {FS_TO_DS_BUS_WIDTH{1'b0}};
end
else if (fs_to_ds_bus_valid_i && fs_to_ds_bus_ready_o) begin
fs_to_ds_bus_data <= fs_to_ds_bus_data_i;
end
else begin
fs_to_ds_bus_data <= fs_to_ds_bus_data;
end
end
inst_decoder inst_inst_decoder(
.inst_i (ds_inst),
.rs1_o (ds_rs1),
.rs2_o (ds_rs2),
.rd_o (ds_rd),
.imm_o (ds_imm),
.shamt_o (ds_shamt),
.pred_o (),
.succ_o (),
.csr_o (ds_csr),
.zimm_o (ds_zimm),
.alu_op_o (ds_alu_op),
.calc_src1_sel_o (ds_calc_src1_sel),
.calc_src2_sel_o (ds_calc_src2_sel),
.jump_op_o (ds_jump_op),
.load_op_o (ds_load_op),
.store_op_o (ds_store_op),
.branch_op_o (ds_branch_op),
.m_ext_op_o (ds_m_ext_op),
.csr_op_o (ds_csr_op),
.amo_op_o (ds_amo_op),
.amo_aq_o (),
.amo_rl_o (),
.excp_illegal_inst_o (ds_excp_illegal_inst),
.excp_breakpoint_o (ds_excp_breakpoint),
.excp_env_call_o (ds_excp_env_call)
);
reg_file inst_reg_file(
.clk_i (clk_i),
.rstn_i (rstn_i),
.raddr1_i (ds_raddr1),
.rdata1_o (ds_rdata1),
.raddr2_i (ds_raddr2),
.rdata2_o (ds_rdata2),
.we_i (ds_we),
.waddr_i (ds_waddr),
.wdata_i (ds_wdata)
);
assign ds_excp_vec = {
16'b0, // reserved
1'b0, // store page fault
1'b0, // expc code 14
2'b0, // isnt & load page fault
ds_excp_env_call && (csr_mpp_i == 2'b11),
1'b0, // excp code 10
ds_excp_env_call && (csr_mpp_i == 2'b01),
1'b0, // env call from u mode
4'b0, // load & store addr misalign & access fault
ds_excp_breakpoint,
ds_excp_illegal_inst,
1'b0, // ds_excp_inst_access_fault
ds_excp_inst_addr_misalign
};
assign ds_op_is_calc = |ds_alu_op || |ds_m_ext_op || |ds_csr_op;
assign ds_op_is_jump = |ds_jump_op;
assign ds_op_is_branch = |ds_branch_op;
assign ds_op_is_load = |ds_load_op;
assign ds_op_is_store = |ds_store_op;
assign ds_raddr1 = ds_rs1;
assign ds_raddr2 = ds_rs2;
assign ds_rs1_value = ((es_fwd_rd != 5'b0) && es_fwd_we && (es_fwd_rd == ds_rs1)) ? es_fwd_value :
((ms_fwd_rd != 5'b0) && ms_fwd_we && (ms_fwd_rd == ds_rs1)) ? ms_fwd_value :
ds_rdata1;
assign ds_rs2_value = ((es_fwd_rd != 5'b0) && es_fwd_we && (es_fwd_rd == ds_rs2)) ? es_fwd_value :
((ms_fwd_rd != 5'b0) && ms_fwd_we && (ms_fwd_rd == ds_rs2)) ? ms_fwd_value :
ds_rdata2;
assign ds_rs1_eq_rs2 = (ds_rs1_value == ds_rs2_value);
assign ds_rs1_lt_rs2 = ($signed(ds_rs1_value) < $signed(ds_rs2_value));
assign ds_rs1_lt_rs2u = (ds_rs1_value < ds_rs2_value);
assign ds_to_es_bus_data_o = { // Total 315 bits
ds_excp_vec, // 314:283 (32 bits)
ds_amo_op, // 282:271 (12 bits)
ds_csr_op, // 270:268 (3 bits)
ds_m_ext_op, // 267:260 (8 bits)
ds_br_taken, // 259:259 (1 bit)
ds_br_target, // 258:227 (32 bits)
ds_store_op, // 226:224 (3 bits)
ds_load_op, // 223:218 (6 bits)
ds_jump_op, // 217:216 (2 bits)
ds_alu_op, // 215:205 (11 bits)
ds_calc_src2_sel, // 204:201 (4 bits)
ds_calc_src1_sel, // 200:197 (4 bits)
ds_rd, // 196:192 (5 bits)
ds_rs2, // 191:187 (5 bits)
ds_rs1, // 186:182 (5 bits)
ds_zimm, // 181:177 (5 bits)
ds_csr, // 176:165 (12 bits)
ds_shamt, // 164:160 (5 bits)
ds_imm, // 159:128 (32 bits)
ds_rs2_value, // 127:96 (32 bits)
ds_rs1_value, // 95:64 (32 bits)
ds_pc, // 63:32 (32 bits)
ds_inst // 31:0 (32 bits)
};
assign ds_br_target = ({32{ ds_jump_op[0] }} & (ds_pc + ds_imm) )
| ({32{ ds_jump_op[1] }} & (ds_rs1_value + ds_imm) & ~32'b1)
| ({32{ds_branch_op[0] & ds_rs1_eq_rs2 }} & (ds_pc + ds_imm) )
| ({32{ds_branch_op[1] & !ds_rs1_eq_rs2 }} & (ds_pc + ds_imm) )
| ({32{ds_branch_op[2] & ds_rs1_lt_rs2 }} & (ds_pc + ds_imm) )
| ({32{ds_branch_op[3] & !ds_rs1_lt_rs2 }} & (ds_pc + ds_imm) )
| ({32{ds_branch_op[4] & ds_rs1_lt_rs2u}} & (ds_pc + ds_imm) )
| ({32{ds_branch_op[5] & !ds_rs1_lt_rs2u}} & (ds_pc + ds_imm) );
assign ds_br_taken = ds_jump_op[0]
| ds_jump_op[1]
| (ds_branch_op[0] & ds_rs1_eq_rs2 )
| (ds_branch_op[1] & !ds_rs1_eq_rs2 )
| (ds_branch_op[2] & ds_rs1_lt_rs2 )
| (ds_branch_op[3] & !ds_rs1_lt_rs2 )
| (ds_branch_op[4] & ds_rs1_lt_rs2u)
| (ds_branch_op[5] & !ds_rs1_lt_rs2u);
assign fs_to_ds_bus_ready_o = !fs_to_ds_bus_valid || (ds_to_es_bus_valid && ds_to_es_bus_ready_i);
assign ds_to_es_bus_valid_o = fs_to_ds_bus_valid && ds_to_es_bus_valid;
assign br_flush_o = fs_to_ds_bus_valid && ds_br_taken && !ds_pipeline_stall;
assign load_stall_o = fs_to_ds_bus_valid && es_load_use && (ds_op_is_branch || ds_op_is_jump || (ds_op_is_calc && !(ds_op_is_store || ds_op_is_load))) && ((es_fwd_rd != 5'b0) && (es_fwd_rd == ds_rs1 || (es_fwd_rd == ds_rs2)));
endmodule

View File

@@ -0,0 +1,146 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2025/05/16 19:31:31
// Design Name:
// Module Name: if_stage
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module if_stage #(
parameter FS_TO_DS_BUS_WIDTH = 65
)
(
input clk_i,
input rstn_i,
input br_flush_i,
input csr_flush_i,
input load_stall_i,
input m_ext_stall_i,
input a_ext_stall_i,
input [31:0] br_target_i,
input br_taken_i,
input fs_to_ds_bus_ready_i,
output [FS_TO_DS_BUS_WIDTH-1:0] fs_to_ds_bus_data_o,
output fs_to_ds_bus_valid_o,
output inst_sram_en_o,
output [ 3:0] inst_sram_wen_o,
output [31:0] inst_sram_addr_o,
output [31:0] inst_sram_wdata_o,
input [31:0] inst_sram_rdata_i
);
reg pre_fs_to_fs_valid;
reg [31:0] fs_pc;
reg fs_excp_inst_addr_misalign;
wire fs_pipeline_stall;
wire fs_pipeline_flush;
wire pre_fs_to_fs_ready;
wire fs_to_ds_bus_valid;
wire pre_fs_to_fs_valid_internal;
wire [31:0] fs_next_pc;
wire [31:0] fs_inst;
assign fs_pipeline_stall = load_stall_i || m_ext_stall_i || a_ext_stall_i;
assign fs_pipeline_flush = br_flush_i;
assign fs_inst = inst_sram_rdata_i;
pre_if_stage inst_pre_if_stage(
.rstn_i (rstn_i),
.pre_fs_to_fs_ready_i (pre_fs_to_fs_ready),
.pre_fs_to_fs_pc_o (fs_next_pc),
.pre_fs_to_fs_valid_o (pre_fs_to_fs_valid_internal),
.load_stall_i (load_stall_i),
.m_ext_stall_i (m_ext_stall_i),
.a_ext_stall_i (a_ext_stall_i),
.br_target_i (br_target_i),
.br_taken_i (br_taken_i),
.fs_pc_i (fs_pc),
.inst_sram_en_o (inst_sram_en_o),
.inst_sram_wen_o (inst_sram_wen_o),
.inst_sram_addr_o (inst_sram_addr_o),
.inst_sram_data_o (inst_sram_wdata_o)
);
assign fs_to_ds_bus_valid = !fs_pipeline_stall;
assign pre_fs_to_fs_ready = !pre_fs_to_fs_valid || (fs_to_ds_bus_valid && fs_to_ds_bus_ready_i);
always @(posedge clk_i or negedge rstn_i) begin
if (!rstn_i) begin
pre_fs_to_fs_valid <= 1'b0;
end
else if (fs_pipeline_flush) begin
pre_fs_to_fs_valid <= 1'b0;
end
else if (pre_fs_to_fs_ready) begin
pre_fs_to_fs_valid <= pre_fs_to_fs_valid_internal;
end
else begin
pre_fs_to_fs_valid <= pre_fs_to_fs_valid;
end
end
always @(posedge clk_i or negedge rstn_i) begin
if (!rstn_i) begin
fs_pc <= 32'h7fff_fffc;
end
else if (pre_fs_to_fs_valid_internal && pre_fs_to_fs_ready) begin
fs_pc <= fs_next_pc;
end
else begin
fs_pc <= fs_pc;
end
end
always @(posedge clk_i or negedge rstn_i) begin
if (!rstn_i) begin
fs_excp_inst_addr_misalign <= 1'b0;
end
else if(pre_fs_to_fs_valid_internal && pre_fs_to_fs_ready) begin
if (fs_next_pc[1:0] != 2'b00) begin
fs_excp_inst_addr_misalign <= 1'b1;
end
else begin
fs_excp_inst_addr_misalign <= 1'b0;
end
end
else begin
fs_excp_inst_addr_misalign <= fs_excp_inst_addr_misalign;
end
end
assign fs_to_ds_bus_data_o = {
fs_excp_inst_addr_misalign, // 64:64
fs_inst, // 63:32
fs_pc // 31:0
};
assign fs_to_ds_bus_valid_o = pre_fs_to_fs_valid && fs_to_ds_bus_valid;
endmodule

View File

@@ -0,0 +1,180 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2025/05/17 10:24:07
// Design Name:
// Module Name: mem_stage
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module mem_stage #(
parameter ES_TO_MS_BUS_WIDTH = 164,
parameter MS_TO_WS_BUS_WIDTH = 70,
parameter MS_TO_DS_FWD_BUS_WIDTH = 38
)(
input clk_i,
input rstn_i,
input csr_flush_i,
output es_to_ms_bus_ready_o,
input [ES_TO_MS_BUS_WIDTH-1:0] es_to_ms_bus_data_i,
input es_to_ms_bus_valid_i,
input ms_to_ws_bus_ready_i,
output [MS_TO_WS_BUS_WIDTH-1:0] ms_to_ws_bus_data_o,
output ms_to_ws_bus_valid_o,
input [ 31:0] data_sram_rdata_i,
output data_sram_en_o,
output [ 3:0] data_sram_wen_o,
output [31:0] data_sram_addr_o,
output [31:0] data_sram_wdata_o,
output a_ext_stall_o,
// fowarding bus to ID stage
output [MS_TO_DS_FWD_BUS_WIDTH-1:0] ms_to_ds_fwd_bus_data_o
);
reg es_to_ms_bus_valid;
reg [ES_TO_MS_BUS_WIDTH-1:0] es_to_ms_bus_data;
wire ms_to_ws_bus_valid;
wire [ 2:0] ms_result_sel;
wire [ 31:0] ms_es_result;
wire [ 31:0] ms_calc_src2;
wire [ 31:0] ms_calc_src1;
wire [ 11:0] ms_amo_op;
wire [ 5:0] ms_load_op;
wire [ 4:0] ms_rd;
wire [ 4:0] ms_rs2;
wire [ 4:0] ms_rs1;
wire [ 31:0] ms_pc;
wire [ 31:0] ms_lb_result;
wire [ 31:0] ms_lh_result;
wire [ 31:0] ms_lw_result;
wire [ 31:0] ms_load_result;
wire [ 31:0] ms_amo_result;
wire [ 31:0] ms_result;
wire [ 31:0] ms_rf_wdata;
wire [ 4:0] ms_rf_waddr;
wire ms_rf_we;
assign {
ms_result_sel, // 163:161 (3 bits)
ms_es_result, // 160:129 (32 bits)
ms_calc_src2, // 128:97 (32 bits)
ms_calc_src1, // 96:65 (32 bits)
ms_amo_op, // 64:53 (12 bits)
ms_load_op, // 52:47 (6 bits)
ms_rd, // 46:42 (5 bits)
ms_rs2, // 41:37 (5 bits)
ms_rs1, // 36:32 (5 bits)
ms_pc // 31:0 (32 bits)
} = es_to_ms_bus_data;
assign ms_to_ws_bus_valid = 1'b1;
always @(posedge clk_i or negedge rstn_i) begin
if (!rstn_i) begin
es_to_ms_bus_valid <= 1'b0;
end
else if (csr_flush_i) begin
es_to_ms_bus_valid <= 1'b0;
end
else if (es_to_ms_bus_ready_o) begin
es_to_ms_bus_valid <= es_to_ms_bus_valid_i;
end
else begin
es_to_ms_bus_valid <= es_to_ms_bus_valid;
end
end
always @(posedge clk_i or negedge rstn_i) begin
if (!rstn_i) begin
es_to_ms_bus_data <= {ES_TO_MS_BUS_WIDTH{1'b0}};
end
else if (es_to_ms_bus_valid_i && es_to_ms_bus_ready_o) begin
es_to_ms_bus_data <= es_to_ms_bus_data_i;
end
else begin
es_to_ms_bus_data <= es_to_ms_bus_data;
end
end
assign ms_lb_result = ({32{(ms_es_result[1:0] == 2'b00)}} & {{24{ms_load_op[0] ? data_sram_rdata_i[ 7] : 1'b0 }}, data_sram_rdata_i[ 7:0 ]})
| ({32{(ms_es_result[1:0] == 2'b01)}} & {{24{ms_load_op[0] ? data_sram_rdata_i[15] : 1'b0 }}, data_sram_rdata_i[15:8 ]})
| ({32{(ms_es_result[1:0] == 2'b10)}} & {{24{ms_load_op[0] ? data_sram_rdata_i[23] : 1'b0 }}, data_sram_rdata_i[23:16]})
| ({32{(ms_es_result[1:0] == 2'b11)}} & {{24{ms_load_op[0] ? data_sram_rdata_i[31] : 1'b0 }}, data_sram_rdata_i[31:24]});
assign ms_lh_result = ({32{(ms_es_result[1:0] == 2'b00)}} & {{16{ms_load_op[1] ? data_sram_rdata_i[15] : 1'b0 }}, data_sram_rdata_i[15:0 ]})
| ({32{(ms_es_result[1:0] == 2'b10)}} & {{16{ms_load_op[1] ? data_sram_rdata_i[31] : 1'b0 }}, data_sram_rdata_i[31:16]});
assign ms_lw_result = data_sram_rdata_i;
assign ms_load_result = ({32{ms_load_op[0] || ms_load_op[3]}} & ms_lb_result)
| ({32{ms_load_op[1] || ms_load_op[4]}} & ms_lh_result)
| ({32{ms_load_op[2] }} & ms_lw_result);
assign ms_amo_result = data_sram_rdata_i;
assign ms_result = {32{ms_result_sel[0]}} & ms_es_result
| {32{ms_result_sel[1]}} & ms_load_result
| {32{ms_result_sel[2]}} & ms_amo_result;
assign ms_rf_wdata = ms_result;
assign ms_rf_waddr = ms_rd;
assign ms_rf_we = es_to_ms_bus_valid && |ms_result_sel;
assign ms_to_ws_bus_data_o = {
ms_rf_we, // 69:69
ms_rf_waddr, // 68:64
ms_rf_wdata, // 63:32
ms_pc // 31:0
};
assign es_to_ms_bus_ready_o = !es_to_ms_bus_valid || (ms_to_ws_bus_valid && ms_to_ws_bus_ready_i);
assign ms_to_ws_bus_valid_o = es_to_ms_bus_valid && ms_to_ws_bus_valid;
assign ms_to_ds_fwd_bus_data_o = {
ms_rf_we, // 37:37
ms_rf_waddr, // 36:32
ms_rf_wdata // 31:0
};
wire ms_mem_lt_rs2;
wire ms_mem_lt_rs2u;
assign ms_mem_lt_rs2 = ($signed(data_sram_rdata_i) < $signed(ms_calc_src2));
assign ms_mem_lt_rs2u = (data_sram_rdata_i < ms_calc_src2);
assign data_sram_en_o = es_to_ms_bus_valid && (|ms_result_sel || |ms_amo_op[9:0]);
assign data_sram_wen_o = {4{es_to_ms_bus_valid && |ms_amo_op[9:0]}};
assign data_sram_addr_o = ms_calc_src1;
assign data_sram_wdata_o = {32{ms_amo_op[0]}} & (({32{ ms_mem_lt_rs2u}} & ms_calc_src2) | ({32{!ms_mem_lt_rs2u}} & data_sram_rdata_i)) // inst_amomaxu_w
| {32{ms_amo_op[1]}} & (({32{!ms_mem_lt_rs2u}} & ms_calc_src2) | ({32{ ms_mem_lt_rs2u}} & data_sram_rdata_i)) // inst_amominu_w
| {32{ms_amo_op[2]}} & (({32{ ms_mem_lt_rs2 }} & ms_calc_src2) | ({32{!ms_mem_lt_rs2 }} & data_sram_rdata_i)) // inst_amomax_w
| {32{ms_amo_op[3]}} & (({32{!ms_mem_lt_rs2 }} & ms_calc_src2) | ({32{ ms_mem_lt_rs2 }} & data_sram_rdata_i)) // inst_amomin_w
| {32{ms_amo_op[4]}} & (data_sram_rdata_i | ms_calc_src2) // inst_amoor_w
| {32{ms_amo_op[5]}} & (data_sram_rdata_i & ms_calc_src2) // inst_amoand_w
| {32{ms_amo_op[6]}} & (data_sram_rdata_i ^ ms_calc_src2) // inst_amoxor_w
| {32{ms_amo_op[7]}} & (data_sram_rdata_i + ms_calc_src2) // inst_amoadd_w
| {32{ms_amo_op[8]}} & (ms_calc_src2) // inst_amoswap_w
| {32{ms_amo_op[9]}} & (ms_calc_src2); // inst_sc_w
assign a_ext_stall_o = ms_to_ws_bus_valid && |ms_amo_op;
endmodule

View File

@@ -0,0 +1,116 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2025/05/17 00:11:46
// Design Name:
// Module Name: alu
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module alu(
input [10:0] alu_op_i ,
input [31:0] alu_src1_i ,
input [31:0] alu_src2_i ,
output [31:0] alu_result_o
);
wire op_lui;
wire op_add;
wire op_sub;
wire op_or;
wire op_slt;
wire op_sltu;
wire op_xor;
wire op_and;
wire op_sll;
wire op_srl;
wire op_sra;
assign {
op_lui,
op_add,
op_sub,
op_slt,
op_sltu,
op_xor,
op_or,
op_and,
op_sll,
op_srl,
op_sra
} = alu_op_i;
wire [31:0] lui_result;
wire [31:0] add_sub_result;
wire [31:0] slt_result;
wire [31:0] sltu_result;
wire [31:0] xor_result;
wire [31:0] or_result;
wire [31:0] and_result;
wire [31:0] sll_result;
wire [31:0] sr64_result;
wire [31:0] sr_result;
// 32-bit adder
wire [31:0] adder_a;
wire [31:0] adder_b;
wire adder_cin;
wire [31:0] adder_result;
wire adder_cout;
assign adder_a = alu_src1_i;
assign adder_b = (op_sub | op_slt | op_sltu) ? ~alu_src2_i : alu_src2_i;
assign adder_cin = (op_sub | op_slt | op_sltu) ? 1'b1 : 1'b0;
assign {adder_cout, adder_result} = adder_a + adder_b + adder_cin;
// ADD, SUB result
assign add_sub_result = adder_result;
// SLT result
assign slt_result[31:1] = 31'b0;
assign slt_result[0] = (alu_src1_i[31] & ~alu_src2_i[31])
| ((alu_src1_i[31] ~^ alu_src2_i[31]) & adder_result[31]);
// SLTU result
assign sltu_result[31:1] = 31'b0;
assign sltu_result[0] = ~adder_cout;
// bitwise operation
assign or_result = alu_src1_i | alu_src2_i;
assign and_result = alu_src1_i & alu_src2_i;
assign xor_result = alu_src1_i ^ alu_src2_i;
assign lui_result = alu_src2_i;
// SLL result
assign sll_result = alu_src1_i << alu_src2_i[4:0];
// SRL, SRA result
assign sr64_result = {{32{op_sra & alu_src1_i[31]}}, alu_src1_i[31:0]} >> alu_src2_i[4:0];
assign sr_result = sr64_result[31:0];
// final result mux
assign alu_result_o = ({32{op_add|op_sub}} & add_sub_result)
| ({32{op_slt }} & slt_result)
| ({32{op_sltu }} & sltu_result)
| ({32{op_or }} & or_result)
| ({32{op_xor }} & xor_result)
| ({32{op_and }} & and_result)
| ({32{op_lui }} & lui_result)
| ({32{op_sll }} & sll_result)
| ({32{op_srl|op_sra}} & sr_result);
endmodule

View File

@@ -0,0 +1,387 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2025/05/19 09:13:42
// Design Name:
// Module Name: csr_csr_reg_file
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module csr_reg_file(
input clk_i,
input rstn_i,
input csr_pc_i,
input csr_inst_i,
input [ 2:0] csr_op_i,
input [11:0] csr_addr_i,
input [31:0] csr_wdata_i,
output [31:0] csr_rdata_o,
input [ 4:0] csr_intr_vec_i,
input [31:0] csr_excp_vec_i,
output [ 1:0] csr_mpp_o,
output csr_taken_o,
output [31:0] csr_target_o
);
reg [31:0] csr_mstatus_reg; // 0x300
reg [31:0] csr_misa_reg; // 0x301
reg [31:0] csr_medeleg_reg; // 0x302 not used
reg [31:0] csr_mideleg_reg; // 0x303 not used
reg [31:0] csr_mie_reg; // 0x304
reg [31:0] csr_mtvec_reg; // 0x305
reg [31:0] csr_mcounteren_reg; // 0x306 not used
reg [31:0] csr_medelegh_reg; // 0x312 not used
reg [31:0] csr_mepc_reg; // 0x341
reg [31:0] csr_mcause_reg; // 0x342
reg [31:0] csr_mtval_reg; // 0x343
reg [31:0] csr_mip_reg; // 0x344
reg [31:0] csr_mscratch_reg; // 0x340
reg [31:0] csr_pmpcfg0_reg; // 0x3A0 not used
reg [31:0] csr_pmpcfg1_reg; // 0x3A1 not used
reg [31:0] csr_pmpcfg2_reg; // 0x3A2 not used
reg [31:0] csr_pmpcfg3_reg; // 0x3A3 not used
reg [31:0] csr_pmpcfg4_reg; // 0x3A4 not used
reg [31:0] csr_pmpcfg5_reg; // 0x3A5 not used
reg [31:0] csr_pmpcfg6_reg; // 0x3A6 not used
reg [31:0] csr_pmpcfg7_reg; // 0x3A7 not used
reg [31:0] csr_pmpcfg8_reg; // 0x3A8 not used
reg [31:0] csr_pmpcfg9_reg; // 0x3A9 not used
reg [31:0] csr_pmpcfg10_reg; // 0x3AA not used
reg [31:0] csr_pmpcfg11_reg; // 0x3AB not used
reg [31:0] csr_pmpcfg12_reg; // 0x3AC not used
reg [31:0] csr_pmpcfg13_reg; // 0x3AD not used
reg [31:0] csr_pmpcfg14_reg; // 0x3AE not used
reg [31:0] csr_pmpcfg15_reg; // 0x3AF not used
reg [31:0] csr_pmpaddr0_reg; // 0x3B0 not used
reg [31:0] csr_pmpaddr1_reg; // 0x3B1 not used
reg [31:0] csr_pmpaddr2_reg; // 0x3B2 not used
reg [31:0] csr_pmpaddr3_reg; // 0x3B3 not used
reg [31:0] csr_pmpaddr4_reg; // 0x3B4 not used
reg [31:0] csr_pmpaddr5_reg; // 0x3B5 not used
reg [31:0] csr_pmpaddr6_reg; // 0x3B6 not used
reg [31:0] csr_pmpaddr7_reg; // 0x3B7 not used
reg [31:0] csr_pmpaddr8_reg; // 0x3B8 not used
reg [31:0] csr_pmpaddr9_reg; // 0x3B9 not used
reg [31:0] csr_pmpaddr10_reg; // 0x3BA not used
reg [31:0] csr_pmpaddr11_reg; // 0x3BB not used
reg [31:0] csr_pmpaddr12_reg; // 0x3BC not used
reg [31:0] csr_pmpaddr13_reg; // 0x3BD not used
reg [31:0] csr_pmpaddr14_reg; // 0x3BE not used
reg [31:0] csr_pmpaddr15_reg; // 0x3BF not used
reg [31:0] csr_pmpaddr16_reg; // 0x3C0 not used
reg [31:0] csr_pmpaddr17_reg; // 0x3C1 not used
reg [31:0] csr_pmpaddr18_reg; // 0x3C2 not used
reg [31:0] csr_pmpaddr19_reg; // 0x3C3 not used
reg [31:0] csr_pmpaddr20_reg; // 0x3C4 not used
reg [31:0] csr_pmpaddr21_reg; // 0x3C5 not used
reg [31:0] csr_pmpaddr22_reg; // 0x3C6 not used
reg [31:0] csr_pmpaddr23_reg; // 0x3C7 not used
reg [31:0] csr_pmpaddr24_reg; // 0x3C8 not used
reg [31:0] csr_pmpaddr25_reg; // 0x3C9 not used
reg [31:0] csr_pmpaddr26_reg; // 0x3CA not used
reg [31:0] csr_pmpaddr27_reg; // 0x3CB not used
reg [31:0] csr_pmpaddr28_reg; // 0x3CC not used
reg [31:0] csr_pmpaddr29_reg; // 0x3CD not used
reg [31:0] csr_pmpaddr30_reg; // 0x3CE not used
reg [31:0] csr_pmpaddr31_reg; // 0x3CF not used
reg [31:0] csr_pmpaddr32_reg; // 0x3D0 not used
reg [31:0] csr_pmpaddr33_reg; // 0x3D1 not used
reg [31:0] csr_pmpaddr34_reg; // 0x3D2 not used
reg [31:0] csr_pmpaddr35_reg; // 0x3D3 not used
reg [31:0] csr_pmpaddr36_reg; // 0x3D4 not used
reg [31:0] csr_pmpaddr37_reg; // 0x3D5 not used
reg [31:0] csr_pmpaddr38_reg; // 0x3D6 not used
reg [31:0] csr_pmpaddr39_reg; // 0x3D7 not used
reg [31:0] csr_pmpaddr40_reg; // 0x3D8 not used
reg [31:0] csr_pmpaddr41_reg; // 0x3D9 not used
reg [31:0] csr_pmpaddr42_reg; // 0x3DA not used
reg [31:0] csr_pmpaddr43_reg; // 0x3DB not used
reg [31:0] csr_pmpaddr44_reg; // 0x3DC not used
reg [31:0] csr_pmpaddr45_reg; // 0x3DD not used
reg [31:0] csr_pmpaddr46_reg; // 0x3DE not used
reg [31:0] csr_pmpaddr47_reg; // 0x3DF not used
reg [31:0] csr_pmpaddr48_reg; // 0x3E0 not used
reg [31:0] csr_pmpaddr49_reg; // 0x3E1 not used
reg [31:0] csr_pmpaddr50_reg; // 0x3E2 not used
reg [31:0] csr_pmpaddr51_reg; // 0x3E3 not used
reg [31:0] csr_pmpaddr52_reg; // 0x3E4 not used
reg [31:0] csr_pmpaddr53_reg; // 0x3E5 not used
reg [31:0] csr_pmpaddr54_reg; // 0x3E6 not used
reg [31:0] csr_pmpaddr55_reg; // 0x3E7 not used
reg [31:0] csr_pmpaddr56_reg; // 0x3E8 not used
reg [31:0] csr_pmpaddr57_reg; // 0x3E9 not used
reg [31:0] csr_pmpaddr58_reg; // 0x3EA not used
reg [31:0] csr_pmpaddr59_reg; // 0x3EB not used
reg [31:0] csr_pmpaddr60_reg; // 0x3EC not used
reg [31:0] csr_pmpaddr61_reg; // 0x3ED not used
reg [31:0] csr_pmpaddr62_reg; // 0x3EE not used
reg [31:0] csr_pmpaddr63_reg; // 0x3EF not used
reg [31:0] csr_rdata_internal;
wire csr_we;
wire excp_inst_addr_misalign;
wire excp_inst_access_fault; // not used
wire excp_illegal_inst;
wire excp_breakpoint;
wire excp_load_addr_misalign; // hardware solved
wire excp_load_access_fault; // not used
wire excp_store_addr_misalign; // hardware solved
wire excp_store_access_fault; // not used
wire excp_env_call_from_u; // not used
wire excp_env_call_from_s;
wire excp_reserved_code_10; // reserved
wire excp_env_call_from_m;
wire excp_inst_page_fault; // not used
wire excp_load_page_fault; // not used
wire excp_reserved_code_14; // reserved
wire excp_store_page_fault; // not used
wire [15:0] excp_reserved; // reserved
wire [31:0] csr_wdata_internal;
wire csr_excp;
wire [ 4:0] csr_excp_code;
wire csr_mstatus_uie;
wire csr_mstatus_sie;
wire csr_mstatus_mie;
wire csr_mstatus_upie;
wire csr_mstatus_spie;
wire csr_mstatus_mpie;
wire csr_mstatus_spp;
wire [1:0] csr_mstatus_mpp;
wire [1:0] csr_mstatus_fs;
wire [1:0] csr_mstatus_xs;
wire csr_mstatus_mprv;
wire csr_mstatus_sum;
wire csr_mstatus_mxr;
wire csr_mstatus_tvm;
wire csr_mstatus_tw;
wire csr_mstatus_tsr;
wire csr_mstatus_sd;
assign csr_we = (csr_op_i[0] ) // read & write
|| (csr_op_i[1] && (|csr_wdata_i)) // if wdata == 0, only read
|| (csr_op_i[2] && (|csr_wdata_i)); // if wdata == 0, only read
assign {
excp_reserved,
excp_store_page_fault,
excp_reserved_code_14,
excp_load_page_fault,
excp_inst_page_fault,
excp_reserved_code_10,
excp_env_call_from_m,
excp_env_call_from_s,
excp_env_call_from_u,
excp_store_access_fault,
excp_store_addr_misalign,
excp_load_access_fault,
excp_load_addr_misalign,
excp_breakpoint,
excp_illegal_inst,
excp_inst_access_fault,
excp_inst_addr_misalign
} = csr_excp_vec_i;
assign csr_mstatus_uie = csr_mstatus_reg[ 0]; // not used in current design
assign csr_mstatus_sie = csr_mstatus_reg[ 1];
assign csr_mstatus_mie = csr_mstatus_reg[ 3];
assign csr_mstatus_upie = csr_mstatus_reg[ 4]; // not used in current design
assign csr_mstatus_spie = csr_mstatus_reg[ 5];
assign csr_mstatus_mpie = csr_mstatus_reg[ 7];
assign csr_mstatus_spp = csr_mstatus_reg[ 8];
assign csr_mstatus_mpp = csr_mstatus_reg[12:11];
assign csr_mstatus_fs = csr_mstatus_reg[14:13]; // not used in current design
assign csr_mstatus_xs = csr_mstatus_reg[16:15]; // not used in current design
assign csr_mstatus_mprv = csr_mstatus_reg[17]; // not used in current design
assign csr_mstatus_sum = csr_mstatus_reg[18];
assign csr_mstatus_mxr = csr_mstatus_reg[19];
assign csr_mstatus_tvm = csr_mstatus_reg[20];
assign csr_mstatus_tw = csr_mstatus_reg[21]; // not used in current design
assign csr_mstatus_tsr = csr_mstatus_reg[22];
assign csr_mstatus_sd = csr_mstatus_reg[31]; // not used in current design
assign csr_wdata_internal = {32{csr_op_i[0]}} & csr_wdata_i
| {32{csr_op_i[1]}} & (csr_rdata_internal | csr_wdata_i)
| {32{csr_op_i[2]}} & (csr_rdata_internal & ~csr_wdata_i);
assign csr_excp = |csr_excp_vec_i;
// csr read logic
always @(*) begin
case (csr_addr_i)
// 0x300-0x3FF Standard read/write
12'h300: begin // mstatus
csr_rdata_internal = csr_mstatus_reg;
end
12'h301: begin // misa
csr_rdata_internal = csr_misa_reg;
end
12'h304: begin // mie
csr_rdata_internal = csr_mie_reg;
end
12'h305: begin // mtvec
csr_rdata_internal = csr_mtvec_reg;
end
12'h340: begin // mscratch
csr_rdata_internal = csr_mscratch_reg;
end
12'h341: begin // mepc
csr_rdata_internal = csr_mepc_reg;
end
12'h342: begin // mcause
csr_rdata_internal = csr_mcause_reg;
end
12'h343: begin // mtval
csr_rdata_internal = csr_mtval_reg;
end
12'h344: begin // mip
csr_rdata_internal = csr_mip_reg;
end
default: begin
csr_rdata_internal = 32'b0;
end
endcase
end
onehot32_to_hex5_decoder inst_onehot32_to_hex5_decoder(
.onehot_i (csr_excp_vec_i),
.hex_o (csr_excp_code)
);
// csr write logic
always @(posedge clk_i or negedge rstn_i) begin
if (!rstn_i) begin
// Reset mstatus: MPP is set to M-mode (2'b11 at bits 12:11), other fields are typically 0.
// 32'h00001800 corresponds to:
// MPP (bits 12:11) = 2'b11 (Machine mode)
// All other implemented bits are 0.
// For RV32, SD bit (bit 31) is 0. FS and XS fields (bits 14:13, 16:15) are 0 (initial/dirty).
csr_mstatus_reg <= 32'h0000_1800;
//csr_misa_reg <= 32'h4000_1101; // RV32IMA
csr_misa_reg <= 32'h4040_1101; // test only
csr_mie_reg <= 32'b0;
csr_mtvec_reg <= 32'b0;
csr_mscratch_reg <= 32'b0;
csr_mepc_reg <= 32'b0;
csr_mcause_reg <= 32'b0;
csr_mtval_reg <= 32'b0;
csr_mip_reg <= 32'b0;
end
else if(csr_excp) begin
csr_mstatus_reg <= {
csr_mstatus_sd,
8'b0, // reserved
csr_mstatus_tsr,
csr_mstatus_tw,
csr_mstatus_tvm,
csr_mstatus_mxr,
csr_mstatus_sum,
csr_mstatus_mprv,
csr_mstatus_xs,
csr_mstatus_fs,
2'b11, // MPP (bits 12:11) set to M-mode (2'b11)
2'b0, // reserved
csr_mstatus_spp, // Bit 8 (SPP, typically unchanged or reflects S-mode if coming from S)
csr_mstatus_mie, // MPIE (bit 7) gets the old MIE (bit 3) value
1'b0, // reserved
csr_mstatus_spie,
csr_mstatus_upie,
1'b0, // MIE (bit 3) is cleared
1'b0, // reserved
csr_mstatus_sie,
csr_mstatus_uie
};
csr_mepc_reg <= csr_pc_i;
csr_mcause_reg <= {1'b0, 26'b0, csr_excp_code}; // {excp_sign, reserved, excp_code}
csr_mtval_reg <= {32{excp_inst_addr_misalign}} & csr_pc_i
| {32{excp_illegal_inst }} & csr_inst_i
| {32{excp_breakpoint }} & 32'b0
| {32{excp_env_call_from_m }} & 32'b0;
end
else begin
case({32{csr_we}} & csr_addr_i)
// 0x300-0x3FF Standard read/write
12'h300: begin // mstatus
csr_mstatus_reg <= {
csr_mstatus_sd, // read-only
8'b0, // reserved
csr_wdata_internal[22], // TSR
csr_mstatus_tw, // not used
csr_wdata_internal[20], // TVM
csr_wdata_internal[19], // MXR
csr_wdata_internal[18], // SUM
csr_mstatus_mprv, // not used
csr_mstatus_xs, // not used
csr_mstatus_fs, // not used
csr_wdata_internal[12:11], // MPP
2'b0, // reserved
csr_wdata_internal[8], // SPP
csr_wdata_internal[7], // MPIE
1'b0, // reserved
csr_wdata_internal[5], // SPIE
csr_mstatus_upie, // not used
csr_wdata_internal[3], // MIE
1'b0, // reserved
csr_wdata_internal[1], // SIE
csr_mstatus_uie // not used
}; // WARL
end
12'h301: begin // misa
csr_misa_reg <= {2'b01, 4'b0, 13'b0, csr_wdata_internal[12], 3'b0, csr_wdata_internal[8], 7'b0, csr_wdata_internal[0]}; // WARL
end
12'h304: begin // mie
csr_mie_reg <= csr_wdata_internal;
end
12'h305: begin // mtvec
csr_mtvec_reg <= csr_wdata_internal;
end
12'h340: begin // mscratch
csr_mscratch_reg <= csr_wdata_internal;
end
12'h341: begin // mepc
csr_mepc_reg <= csr_wdata_internal;
end
12'h342: begin // mcause
csr_mcause_reg <= csr_wdata_internal;
end
12'h343: begin // mtval
csr_mtval_reg <= csr_wdata_internal;
end
12'h344: begin // mip
csr_mip_reg <= csr_wdata_internal;
end
default: begin
// do nothing
end
endcase
end
end
assign csr_mpp_o = csr_mstatus_mpp;
assign csr_taken_o = csr_excp;
assign csr_target_o = csr_mtvec_reg;
assign csr_rdata_o = csr_rdata_internal;
endmodule

View File

@@ -0,0 +1,31 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2025/05/21 15:47:30
// Design Name:
// Module Name: onehot_i32_to_hex_o5_decoder
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module onehot32_to_hex5_decoder (
input [31:0] onehot_i,
output [ 4:0] hex_o
);
assign hex_o[0] = |(onehot_i & 32'haaaa_aaaa);
assign hex_o[1] = |(onehot_i & 32'hcccc_cccc);
assign hex_o[2] = |(onehot_i & 32'hf0f0_f0f0);
assign hex_o[3] = |(onehot_i & 32'hff00_ff00);
assign hex_o[4] = |(onehot_i & 32'hffff_0000);
endmodule

View File

@@ -0,0 +1,266 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2025/05/19 09:13:42
// Design Name:
// Module Name: csr_csr_reg_file
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module csr_reg_file(
input clk_i,
input rstn_i,
input csr_pc_i,
input csr_inst_i,
input [ 2:0] csr_op_i,
input [11:0] csr_addr_i,
input [31:0] csr_wdata_i,
output [31:0] csr_rdata_o,
input [31:0] csr_excp_vec_i,
output csr_taken_o,
output [31:0] csr_target_o
);
reg [31:0] csr_mstatus_reg;
reg [31:0] csr_mie_reg;
reg [31:0] csr_mtvec_reg;
reg [31:0] csr_mepc_reg;
reg [31:0] csr_mcause_reg;
reg [31:0] csr_mtval_reg;
reg [31:0] csr_mip_reg;
reg [31:0] csr_mscratch_reg;
reg [31:0] csr_rdata_internal;
wire csr_re;
wire csr_we;
wire excp_inst_addr_misalign;
wire excp_inst_access_fault; // not used in current design
wire excp_illegal_inst;
wire excp_breakpoint;
wire excp_load_addr_misalign; // hardware solved
wire excp_load_access_fault; // not used in current design
wire excp_store_addr_misalign; // hardware solved
wire excp_store_access_fault; // not used in current design
wire excp_env_call_from_u; // not used in current design
wire excp_env_call_from_s; // not used in current design
wire excp_reserved_code_10; // not used in current design
wire excp_env_call_from_m;
wire excp_inst_page_fault; // not used in current design
wire excp_load_page_fault; // not used in current design
wire excp_reserved_code_14; // not used in current design
wire excp_store_page_fault; // not used in current design
wire [15:0] excp_reserved; // not used in current design
wire [31:0] csr_wdata_internal;
wire csr_excp;
wire [ 4:0] csr_excp_code;
wire csr_mstatus_uie;
wire csr_mstatus_sie;
wire csr_mstatus_mie;
wire csr_mstatus_upie;
wire csr_mstatus_spie;
wire csr_mstatus_mpie;
wire csr_mstatus_spp;
wire [1:0] csr_mstatus_mpp;
wire [1:0] csr_mstatus_fs;
wire [1:0] csr_mstatus_xs;
wire csr_mstatus_mprv;
wire csr_mstatus_sum;
wire csr_mstatus_mxr;
wire csr_mstatus_tvm;
wire csr_mstatus_tw;
wire csr_mstatus_tsr;
wire csr_mstatus_sd;
assign csr_re = |csr_op_i;
assign csr_we = |csr_op_i;
assign {
excp_reserved,
excp_store_page_fault,
excp_reserverd_code_14,
excp_load_page_fault,
excp_inst_page_fault,
excp_reserved_code_10,
excp_env_call_from_m,
excp_env_call_from_s,
excp_env_call_from_u,
excp_store_access_fault,
excp_store_addr_misalign,
excp_load_access_fault,
excp_load_addr_misalign,
excp_breakpoint,
excp_illegal_inst,
excp_inst_access_fault,
excp_inst_addr_misalign
} = csr_excp_vec_i;
assign csr_mstatus_uie = csr_mstatus_reg[ 0];
assign csr_mstatus_sie = csr_mstatus_reg[ 1];
assign csr_mstatus_mie = csr_mstatus_reg[ 3];
assign csr_mstatus_upie = csr_mstatus_reg[ 4];
assign csr_mstatus_spie = csr_mstatus_reg[ 5];
assign csr_mstatus_mpie = csr_mstatus_reg[ 7];
assign csr_mstatus_spp = csr_mstatus_reg[ 8];
assign csr_mstatus_mpp = csr_mstatus_reg[12:11];
assign csr_mstatus_fs = csr_mstatus_reg[14:13];
assign csr_mstatus_xs = csr_mstatus_reg[16:15];
assign csr_mstatus_mprv = csr_mstatus_reg[17];
assign csr_mstatus_sum = csr_mstatus_reg[18];
assign csr_mstatus_mxr = csr_mstatus_reg[19];
assign csr_mstatus_tvm = csr_mstatus_reg[20];
assign csr_mstatus_tw = csr_mstatus_reg[21];
assign csr_mstatus_tsr = csr_mstatus_reg[22];
assign csr_mstatus_sd = csr_mstatus_reg[31];
assign csr_wdata_internal = {32{csr_op_i[0]}} & csr_wdata_i
| {32{csr_op_i[1]}} & (csr_rdata_internal | csr_wdata_i)
| {32{csr_op_i[2]}} & (csr_rdata_internal & ~csr_wdata_i);
assign csr_excp = |csr_excp_vec_i;
// csr read logic
always @(*) begin
case (csr_addr_i)
// 0x300-0x3FF Standard read/write
12'h300: begin // mstatus
csr_rdata_internal = csr_mstatus_reg;
end
12'h304: begin // mie
csr_rdata_internal = csr_mie_reg;
end
12'h305: begin // mtvec
csr_rdata_internal = csr_mtvec_reg;
end
12'h341: begin // mepc
csr_rdata_internal = csr_mepc_reg;
end
12'h342: begin // mcause
csr_rdata_internal = csr_mcause_reg;
end
12'h343: begin // mtval
csr_rdata_internal = csr_mtval_reg;
end
12'h344: begin // mip
csr_rdata_internal = csr_mip_reg;
end
12'h340: begin // mscratch
csr_rdata_internal = csr_mscratch_reg;
end
default: begin
csr_rdata_internal = 32'b0;
end
endcase
end
onehot32_to_hex5_decoder inst_onehot32_to_hex5_decoder(
.onehot_i (csr_excp_vec_i),
.hex_o (csr_excp_code)
);
// csr write logic
always @(posedge clk_i or negedge rstn_i) begin
if (!rstn_i) begin
// Reset mstatus: MPP is set to M-mode (2'b11 at bits 12:11), other fields are typically 0.
// 32'h00001800 corresponds to:
// MPP (bits 12:11) = 2'b11 (Machine mode)
// All other implemented bits are 0.
// For RV32, SD bit (bit 31) is 0. FS and XS fields (bits 14:13, 16:15) are 0 (initial/dirty).
csr_mstatus_reg <= 32'h00001800;
csr_mie_reg <= 32'b0;
csr_mtvec_reg <= 32'b0;
csr_mepc_reg <= 32'b0;
csr_mcause_reg <= 32'b0;
csr_mtval_reg <= 32'b0;
csr_mip_reg <= 32'b0;
csr_mscratch_reg <= 32'b0;
end
else if(csr_excp) begin
csr_mstatus_reg <= {
csr_mstatus_sd,
csr_mstatus_reg[30:23], // hard wired, keep old value
csr_mstatus_tsr,
csr_mstatus_tw,
csr_mstatus_tvm,
csr_mstatus_mxr,
csr_mstatus_sum,
csr_mstatus_mprv,
csr_mstatus_xs,
csr_mstatus_fs,
2'b11, // MPP (bits 12:11) set to M-mode (2'b11)
csr_mstatus_reg[10:9], // hard wired, keep old value
csr_mstatus_spp, // Bit 8 (SPP, typically unchanged or reflects S-mode if coming from S)
csr_mstatus_mie, // MPIE (bit 7) gets the old MIE (bit 3) value
csr_mstatus_reg[6], // hard wired, keep old value
csr_mstatus_spie,
csr_mstatus_upie,
1'b0, // MIE (bit 3) is cleared
csr_mstatus_reg[2], // hard wired, keep old value
csr_mstatus_sie,
csr_mstatus_uie
};
csr_mepc_reg <= csr_pc_i;
csr_mcause_reg <= {1'b0, 26'b0, csr_excp_code}; // {excp_sign, reserved, excp_code}
csr_mtval_reg <= {32{excp_inst_addr_misalign}} & csr_pc_i
| {32{excp_illegal_inst }} & csr_inst_i
| {32{excp_breakpoint }} & 32'b0
| {32{excp_env_call_from_m }} & 32'b0;
end
else begin
case({32{csr_we}} & csr_addr_i)
// 0x300-0x3FF Standard read/write
12'h300: begin // mstatus
csr_mstatus_reg <= csr_wdata_internal;
end
12'h304: begin // mie
csr_mie_reg <= csr_wdata_internal;
end
12'h305: begin // mtvec
csr_mtvec_reg <= csr_wdata_internal;
end
12'h341: begin // mepc
csr_mepc_reg <= csr_wdata_internal;
end
12'h342: begin // mcause
csr_mcause_reg <= csr_wdata_internal;
end
12'h343: begin // mtval
csr_mtval_reg <= csr_wdata_internal;
end
12'h344: begin // mip
csr_mip_reg <= csr_wdata_internal;
end
12'h340: begin // mscratch
csr_mscratch_reg <= csr_wdata_internal;
end
default: begin
// do nothing
end
endcase
end
end
assign csr_taken_o = csr_excp;
assign csr_target_o = csr_mtvec_reg;
assign csr_rdata_o = csr_rdata_internal;
endmodule

View File

@@ -0,0 +1,336 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2025/05/16 20:10:16
// Design Name:
// Module Name: inst_decoder
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module inst_decoder(
input [31:0] inst_i,
output [ 4:0] rs1_o,
output [ 4:0] rs2_o,
output [ 4:0] rd_o,
output [31:0] imm_o,
output [ 4:0] shamt_o,
output [ 3:0] pred_o, // reserved
output [ 3:0] succ_o, // reserved
output [11:0] csr_o,
output [ 4:0] zimm_o,
output [10:0] alu_op_o,
output [ 3:0] calc_src1_sel_o,
output [ 3:0] calc_src2_sel_o,
output [ 1:0] jump_op_o,
output [ 5:0] load_op_o,
output [ 2:0] store_op_o,
output [ 5:0] branch_op_o,
output [ 7:0] m_ext_op_o,
output [ 2:0] csr_op_o,
output [11:0] amo_op_o,
output amo_aq_o, // reserved
output amo_rl_o, // reserved
output excp_illegal_inst_o,
output excp_breakpoint_o,
output excp_env_call_o
);
wire [ 7:0] opcode;
wire [ 2:0] funct3;
wire [ 4:0] funct5;
wire [ 6:0] funct7;
wire [ 1:0] r_type;
wire [ 4:0] i_type;
wire [ 0:0] s_type;
wire [ 0:0] b_type;
wire [ 1:0] u_type;
wire [ 0:0] j_type;
wire [31:0] i_type_imm;
wire [31:0] s_type_imm;
wire [31:0] b_type_imm;
wire [31:0] u_type_imm;
wire [31:0] j_type_imm;
wire inst_lui;
wire inst_auipc;
wire inst_jal;
wire inst_jalr;
wire inst_beq;
wire inst_bne;
wire inst_blt;
wire inst_bge;
wire inst_bltu;
wire inst_bgeu;
wire inst_lb;
wire inst_lh;
wire inst_lw;
wire inst_lbu;
wire inst_lhu;
wire inst_sb;
wire inst_sh;
wire inst_sw;
wire inst_addi;
wire inst_slti;
wire inst_sltiu;
wire inst_xori;
wire inst_ori;
wire inst_andi;
wire inst_slli;
wire inst_srli;
wire inst_srai;
wire inst_add;
wire inst_sub;
wire inst_sll;
wire inst_slt;
wire inst_sltu;
wire inst_xor;
wire inst_srl;
wire inst_sra;
wire inst_or;
wire inst_and;
wire inst_fence;
wire inst_fence_i;
wire inst_ecall;
wire inst_ebreak;
wire inst_mret; // TODO
wire inst_sret; // TODO
wire inst_csrrw;
wire inst_csrrs;
wire inst_csrrc;
wire inst_csrrwi;
wire inst_csrrsi;
wire inst_csrrci;
wire inst_mul;
wire inst_mulh;
wire inst_mulhsu;
wire inst_mulhu;
wire inst_div;
wire inst_divu;
wire inst_rem;
wire inst_remu;
wire inst_lr_w;
wire inst_sc_w;
wire inst_amoswap_w;
wire inst_amoadd_w;
wire inst_amoxor_w;
wire inst_amoand_w;
wire inst_amoor_w;
wire inst_amomin_w;
wire inst_amomax_w;
wire inst_amominu_w;
wire inst_amomaxu_w;
wire calc_src1_is_rs1;
wire calc_src1_is_pc;
wire calc_src1_is_zero;
wire calc_src1_is_zimm;
wire calc_src2_is_rs2;
wire calc_src2_is_imm;
wire calc_src2_is_4;
assign opcode = inst_i[6:0];
assign funct3 = inst_i[14:12];
assign funct5 = inst_i[31:27];
assign funct7 = inst_i[31:25];
assign r_type = {(opcode == 7'b0101111), (opcode == 7'b0110011)};
assign i_type = {(opcode == 7'b1110011), (opcode == 7'b0001111), (opcode == 7'b0010011), (opcode == 7'b0000011), (opcode == 7'b1100111)};
assign s_type = {(opcode == 7'b0100011)};
assign b_type = {(opcode == 7'b1100011)};
assign u_type = {(opcode == 7'b0110111), (opcode == 7'b0010111)};
assign j_type = {(opcode == 7'b1101111)};
// basic instructions
assign inst_lui = u_type[1];
assign inst_auipc = u_type[0];
assign inst_jal = j_type[0];
assign inst_jalr = i_type[0];
assign inst_beq = b_type[0] && (funct3 == 3'b000);
assign inst_bne = b_type[0] && (funct3 == 3'b001);
assign inst_blt = b_type[0] && (funct3 == 3'b100);
assign inst_bge = b_type[0] && (funct3 == 3'b101);
assign inst_bltu = b_type[0] && (funct3 == 3'b110);
assign inst_bgeu = b_type[0] && (funct3 == 3'b111);
assign inst_lb = i_type[1] && (funct3 == 3'b000);
assign inst_lh = i_type[1] && (funct3 == 3'b001);
assign inst_lw = i_type[1] && (funct3 == 3'b010);
assign inst_lbu = i_type[1] && (funct3 == 3'b100);
assign inst_lhu = i_type[1] && (funct3 == 3'b101);
assign inst_sb = s_type[0] && (funct3 == 3'b000);
assign inst_sh = s_type[0] && (funct3 == 3'b001);
assign inst_sw = s_type[0] && (funct3 == 3'b010);
assign inst_addi = i_type[2] && (funct3 == 3'b000);
assign inst_slti = i_type[2] && (funct3 == 3'b010);
assign inst_sltiu = i_type[2] && (funct3 == 3'b011);
assign inst_xori = i_type[2] && (funct3 == 3'b100);
assign inst_ori = i_type[2] && (funct3 == 3'b110);
assign inst_andi = i_type[2] && (funct3 == 3'b111);
assign inst_slli = i_type[2] && (funct3 == 3'b001) && (funct7 == 7'b0000000);
assign inst_srli = i_type[2] && (funct3 == 3'b101) && (funct7 == 7'b0000000);
assign inst_srai = i_type[2] && (funct3 == 3'b101) && (funct7 == 7'b0100000);
assign inst_add = r_type[0] && (funct3 == 3'b000) && (funct7 == 7'b0000000);
assign inst_sub = r_type[0] && (funct3 == 3'b000) && (funct7 == 7'b0100000);
assign inst_sll = r_type[0] && (funct3 == 3'b001) && (funct7 == 7'b0000000);
assign inst_slt = r_type[0] && (funct3 == 3'b010) && (funct7 == 7'b0000000);
assign inst_sltu = r_type[0] && (funct3 == 3'b011) && (funct7 == 7'b0000000);
assign inst_xor = r_type[0] && (funct3 == 3'b100) && (funct7 == 7'b0000000);
assign inst_srl = r_type[0] && (funct3 == 3'b101) && (funct7 == 7'b0000000);
assign inst_sra = r_type[0] && (funct3 == 3'b101) && (funct7 == 7'b0100000);
assign inst_or = r_type[0] && (funct3 == 3'b110) && (funct7 == 7'b0000000);
assign inst_and = r_type[0] && (funct3 == 3'b111) && (funct7 == 7'b0000000);
// csr instructions
assign inst_fence = i_type[3] && (funct3 == 3'b000);
assign inst_fence_i = i_type[3] && (funct3 == 3'b001);
assign inst_ecall = i_type[4] && (funct3 == 3'b000) && (funct7 == 7'b0000000);
assign inst_ebreak = i_type[4] && (funct3 == 3'b000) && (funct7 == 7'b0000001);
assign inst_mret = i_type[4] && (funct3 == 3'b000) && (funct7 == 7'b0011000);
assign inst_sret = i_type[4] && (funct3 == 3'b000) && (funct7 == 7'b0011001);
assign inst_csrrw = i_type[4] && (funct3 == 3'b001);
assign inst_csrrs = i_type[4] && (funct3 == 3'b010);
assign inst_csrrc = i_type[4] && (funct3 == 3'b011);
assign inst_csrrwi = i_type[4] && (funct3 == 3'b101);
assign inst_csrrsi = i_type[4] && (funct3 == 3'b110);
assign inst_csrrci = i_type[4] && (funct3 == 3'b111);
// m_extension instructions
assign inst_mul = r_type[0] && (funct3 == 3'b000) && (funct7 == 7'b0000001);
assign inst_mulh = r_type[0] && (funct3 == 3'b001) && (funct7 == 7'b0000001);
assign inst_mulhsu = r_type[0] && (funct3 == 3'b010) && (funct7 == 7'b0000001);
assign inst_mulhu = r_type[0] && (funct3 == 3'b011) && (funct7 == 7'b0000001);
assign inst_div = r_type[0] && (funct3 == 3'b100) && (funct7 == 7'b0000001);
assign inst_divu = r_type[0] && (funct3 == 3'b101) && (funct7 == 7'b0000001);
assign inst_rem = r_type[0] && (funct3 == 3'b110) && (funct7 == 7'b0000001);
assign inst_remu = r_type[0] && (funct3 == 3'b111) && (funct7 == 7'b0000001);
// a_extension instructions
assign inst_lr_w = r_type[1] && (funct3 == 3'b010) && (funct5 == 5'b00010);
assign inst_sc_w = r_type[1] && (funct3 == 3'b010) && (funct5 == 5'b00011);
assign inst_amoswap_w = r_type[1] && (funct3 == 3'b010) && (funct5 == 5'b00001);
assign inst_amoadd_w = r_type[1] && (funct3 == 3'b010) && (funct5 == 5'b00000);
assign inst_amoxor_w = r_type[1] && (funct3 == 3'b010) && (funct5 == 5'b00100);
assign inst_amoand_w = r_type[1] && (funct3 == 3'b010) && (funct5 == 5'b01100);
assign inst_amoor_w = r_type[1] && (funct3 == 3'b010) && (funct5 == 5'b01000);
assign inst_amomin_w = r_type[1] && (funct3 == 3'b010) && (funct5 == 5'b10000);
assign inst_amomax_w = r_type[1] && (funct3 == 3'b010) && (funct5 == 5'b10100);
assign inst_amominu_w = r_type[1] && (funct3 == 3'b010) && (funct5 == 5'b11000);
assign inst_amomaxu_w = r_type[1] && (funct3 == 3'b010) && (funct5 == 5'b11100);
assign i_type_imm = {{20{inst_i[31]}}, inst_i[31:20]};
assign s_type_imm = {{20{inst_i[31]}}, inst_i[31:25], inst_i[11:7]};
assign b_type_imm = {{20{inst_i[31]}}, inst_i[7], inst_i[30:25], inst_i[11:8], 1'b0};
assign u_type_imm = {inst_i[31:12], 12'b0};
assign j_type_imm = {{12{inst_i[31]}}, inst_i[19:12], inst_i[20], inst_i[30:21], 1'b0};
assign calc_src1_is_rs1 = inst_lb | inst_lh | inst_lw | inst_lbu | inst_lhu | inst_sb | inst_sh | inst_sw
| inst_addi | inst_slti | inst_sltiu | inst_xori | inst_ori | inst_andi
| inst_add | inst_sub | inst_sll | inst_slt | inst_sltu | inst_xor | inst_srl | inst_sra | inst_or | inst_and
| inst_slli | inst_srli | inst_srai
| inst_mul | inst_mulh | inst_mulhsu | inst_mulhu | inst_div | inst_divu | inst_rem | inst_remu
| inst_csrrw | inst_csrrs | inst_csrrc
| inst_lr_w | inst_sc_w
| inst_amoswap_w | inst_amoadd_w | inst_amoxor_w | inst_amoand_w | inst_amoor_w | inst_amomin_w | inst_amomax_w | inst_amominu_w | inst_amomaxu_w;
assign calc_src1_is_pc = inst_auipc | inst_jal | inst_jalr;
assign calc_src1_is_zero = inst_lui;
assign calc_src1_is_zimm = inst_csrrwi | inst_csrrsi | inst_csrrci;
assign calc_src2_is_rs2 = inst_add | inst_sub | inst_sll | inst_slt | inst_sltu | inst_xor | inst_srl | inst_sra | inst_or | inst_and
| inst_mul | inst_mulh | inst_mulhsu | inst_mulhu | inst_div | inst_divu | inst_rem | inst_remu
| inst_sc_w
| inst_amoswap_w | inst_amoadd_w | inst_amoxor_w | inst_amoand_w | inst_amoor_w | inst_amomin_w | inst_amomax_w | inst_amominu_w | inst_amomaxu_w;
assign calc_src2_is_imm = inst_lui | inst_auipc | inst_lb | inst_lh | inst_lw | inst_lbu | inst_lhu
| inst_sb | inst_sh | inst_sw | inst_addi | inst_slti | inst_sltiu | inst_xori | inst_ori | inst_andi;
assign calc_src2_is_4 = inst_jal | inst_jalr;
assign calc_src2_is_shamt = inst_slli | inst_srli | inst_srai;
assign rs1_o = inst_i[19:15];
assign rs2_o = inst_i[24:20];
assign rd_o = inst_i[11:7];
assign imm_o = ({32{|i_type}} & i_type_imm)
| ({32{|s_type}} & s_type_imm)
| ({32{|b_type}} & b_type_imm)
| ({32{|u_type}} & u_type_imm)
| ({32{|j_type}} & j_type_imm);
assign shamt_o = inst_i[24:20];
assign pred_o = inst_i[27:24];
assign succ_o = inst_i[23:20];
assign csr_o = inst_i[31:20];
assign zimm_o = inst_i[19:15];
assign alu_op_o = {
// op_lui
inst_lui,
// op_add
inst_auipc | inst_jal | inst_jalr | inst_lb | inst_lh | inst_lw | inst_lbu | inst_lhu | inst_sb | inst_sh | inst_sw | inst_addi | inst_add,
// op_sub
inst_sub,
// op_slt
inst_slti | inst_slt,
// op_sltu
inst_sltiu | inst_sltu,
// op_xor
inst_xori | inst_xor,
// op_or
inst_ori | inst_or,
// op_and
inst_andi | inst_and,
// op_sll
inst_slli | inst_sll,
// op_srl
inst_srli | inst_srl,
// op_sra
inst_srai | inst_sra
};
assign calc_src1_sel_o = {calc_src1_is_zimm, calc_src1_is_zero, calc_src1_is_pc, calc_src1_is_rs1};
assign calc_src2_sel_o = {calc_src2_is_shamt, calc_src2_is_4, calc_src2_is_imm, calc_src2_is_rs2};
assign jump_op_o = {inst_jalr, inst_jal};
assign branch_op_o = {inst_bgeu, inst_bltu, inst_bge, inst_blt, inst_bne, inst_beq};
assign load_op_o = {inst_lhu, inst_lbu, inst_lw, inst_lh, inst_lb};
assign store_op_o = {inst_sw, inst_sh, inst_sb};
assign m_ext_op_o = {inst_mul, inst_mulh, inst_mulhsu, inst_mulhu, inst_div, inst_divu, inst_rem, inst_remu};
assign csr_op_o = {
inst_csrrci | inst_csrrc,
inst_csrrsi | inst_csrrs,
inst_csrrwi | inst_csrrw
};
assign amo_op_o = {1'b0, inst_lr_w, inst_sc_w, inst_amoswap_w, inst_amoadd_w, inst_amoxor_w, inst_amoand_w, inst_amoor_w, inst_amomin_w, inst_amomax_w, inst_amominu_w, inst_amomaxu_w};
assign amo_aq_o = inst_i[26];
assign amo_rl_o = inst_i[25];
assign excp_illegal_inst_o = !(r_type || i_type || s_type || b_type || u_type || j_type);
assign excp_breakpoint_o = inst_ebreak;
assign excp_env_call_o = inst_ecall;
endmodule

View File

@@ -0,0 +1,274 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2025/05/17 23:19:17
// Design Name:
// Module Name: divider
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
`define TEST_PROG_DIV_0_NO_CONSIDER_SIGN
module divider(
// Inputs
input wire clk_i,
input wire rstn_i,
input wire start_i, // Start signal for division
input wire signed_mode_i, // 0 for unsigned, 1 for signed
input wire [31:0] dividend_i, // 被除数
input wire [31:0] divisor_i, // 除数
// Outputs
output reg [31:0] quotient_o, //
output reg [31:0] remainder_o, // 余数
output reg done_o, // Calculation done signal
output reg busy_o, // Divider is busy
output reg div_by_zero_o // Division by zero error
);
localparam DATA_WIDTH = 32;
// FSM States
localparam S_IDLE = 3'd0; // Increased state reg width slightly for safety if more states added
localparam S_PREPARE = 3'd1;
localparam S_DIV_STEP = 3'd2;
localparam S_ADJUST_SIGN = 3'd3;
localparam S_FINISH = 3'd4;
reg [2:0] current_state_reg;
reg [2:0] next_state_reg;
// Internal Registers for algorithm
reg [DATA_WIDTH-1:0] dividend_abs_reg; // Holds dividend, then quotient bits are shifted in
reg [DATA_WIDTH-1:0] divisor_abs_reg; // Absolute value of divisor
reg [DATA_WIDTH:0] partial_remainder_reg; // Partial remainder (N+1 bits for subtract sign)
reg [5:0] iter_count_reg; // Iteration counter (0 to DATA_WIDTH)
reg original_dividend_sign;
reg original_divisor_sign;
reg is_signed_mode_reg;
reg div_by_zero_flag;
// Temporary variables for calculations within clocked always block (module scope Verilog regs)
reg [DATA_WIDTH:0] p_shifted_in_A_msb_temp;
reg [DATA_WIDTH:0] subtract_result_temp;
reg new_quotient_bit_temp;
reg [DATA_WIDTH-1:0] final_quotient_temp;
reg [DATA_WIDTH-1:0] final_remainder_temp;
reg quotient_sign_temp;
reg remainder_sign_temp;
//--------------------------------------------------------------------------
// FSM State Register
//--------------------------------------------------------------------------
always @(posedge clk_i or negedge rstn_i) begin
if (!rstn_i) begin
current_state_reg <= S_IDLE;
end else begin
current_state_reg <= next_state_reg;
end
end
//--------------------------------------------------------------------------
// FSM Next State Logic & Combinational Output (done_o)
//--------------------------------------------------------------------------
always @(*) begin // Verilog-2001 equivalent of always_comb
next_state_reg = current_state_reg; // Default: stay in current state
done_o = 1'b0; // Default done_o to low
case (current_state_reg)
S_IDLE: begin
if (start_i) begin
next_state_reg = S_PREPARE;
end
end
S_PREPARE: begin
if (div_by_zero_flag) begin
next_state_reg = S_FINISH;
end else begin
next_state_reg = S_DIV_STEP;
end
end
S_DIV_STEP: begin
if (iter_count_reg == DATA_WIDTH) begin // Completed N iterations
next_state_reg = S_ADJUST_SIGN;
end else begin
next_state_reg = S_DIV_STEP; // Stay for next iteration
end
end
S_ADJUST_SIGN: begin
next_state_reg = S_FINISH;
end
S_FINISH: begin
done_o = 1'b1; // Assert done for one cycle
next_state_reg = S_IDLE;
end
default: begin
next_state_reg = S_IDLE;
end
endcase
end
//--------------------------------------------------------------------------
// Datapath Logic (Sequential - Register Updates)
//--------------------------------------------------------------------------
always @(posedge clk_i or negedge rstn_i) begin
if (!rstn_i) begin
busy_o <= 1'b0;
div_by_zero_o <= 1'b0;
quotient_o <= {DATA_WIDTH{1'b0}};
remainder_o <= {DATA_WIDTH{1'b0}};
dividend_abs_reg <= {DATA_WIDTH{1'b0}};
divisor_abs_reg <= {DATA_WIDTH{1'b0}};
partial_remainder_reg <= {DATA_WIDTH+1{1'b0}};
iter_count_reg <= 6'd0;
original_dividend_sign <= 1'b0;
original_divisor_sign <= 1'b0;
is_signed_mode_reg <= 1'b0;
div_by_zero_flag <= 1'b0;
end else begin
// busy_o is set high when IDLE sees start_i and calculation begins
// busy_o is set low when FSM transitions out of S_FINISH (or after done pulse)
if (current_state_reg == S_FINISH && next_state_reg == S_IDLE) begin
busy_o <= 1'b0;
end
case (current_state_reg)
S_IDLE: begin
if (start_i) begin
busy_o <= 1'b1;
div_by_zero_o <= 1'b0;
quotient_o <= {DATA_WIDTH{1'b0}};
remainder_o <= {DATA_WIDTH{1'b0}};
is_signed_mode_reg <= signed_mode_i;
if (divisor_i == {DATA_WIDTH{1'b0}}) begin
div_by_zero_flag <= 1'b1;
// For div by zero, abs regs don't matter as much, but init them
dividend_abs_reg <= dividend_i; // Store original dividend for remainder
original_dividend_sign <= signed_mode_i ? dividend_i[DATA_WIDTH-1] : 1'b0;
end else begin
div_by_zero_flag <= 1'b0;
if (signed_mode_i) begin
original_dividend_sign <= dividend_i[DATA_WIDTH-1];
original_divisor_sign <= divisor_i[DATA_WIDTH-1];
dividend_abs_reg <= (dividend_i[DATA_WIDTH-1]) ? -dividend_i : dividend_i;
divisor_abs_reg <= (divisor_i[DATA_WIDTH-1]) ? -divisor_i : divisor_i;
end else begin
original_dividend_sign <= 1'b0; // Unused for unsigned
original_divisor_sign <= 1'b0; // Unused for unsigned
dividend_abs_reg <= dividend_i;
divisor_abs_reg <= divisor_i;
end
partial_remainder_reg <= {DATA_WIDTH+1{1'b0}}; // P = 0
iter_count_reg <= 6'd0;
end
end
end // S_IDLE
S_PREPARE: begin
// This state is mainly for FSM transition;
// actual data loading happens in S_IDLE based on start_i.
// If div_by_zero_flag was set, next_state_reg (combinatorially) points to S_FINISH.
end
S_DIV_STEP: begin
if (iter_count_reg < DATA_WIDTH) begin
// Temporary variables are calculated based on current reg values
p_shifted_in_A_msb_temp = {partial_remainder_reg[DATA_WIDTH-1:0], dividend_abs_reg[DATA_WIDTH-1]};
subtract_result_temp = p_shifted_in_A_msb_temp - {1'b0, divisor_abs_reg};
if (subtract_result_temp[DATA_WIDTH] == 1'b0) begin // No borrow / P_trial >= 0
partial_remainder_reg <= subtract_result_temp; // Update P
new_quotient_bit_temp = 1'b1;
end else begin // Borrow / P_trial < 0
partial_remainder_reg <= p_shifted_in_A_msb_temp; // Restore P
new_quotient_bit_temp = 1'b0;
end
// Shift A (dividend_abs_reg) and place new quotient bit
dividend_abs_reg <= {dividend_abs_reg[DATA_WIDTH-2:0], new_quotient_bit_temp};
iter_count_reg <= iter_count_reg + 1;
end
end // S_DIV_STEP
S_ADJUST_SIGN: begin
// Use temporary regs for calculation before assigning to outputs
final_quotient_temp = dividend_abs_reg; // Now contains absolute quotient
final_remainder_temp = partial_remainder_reg[DATA_WIDTH-1:0]; // Lower N bits of P
if (is_signed_mode_reg) begin
quotient_sign_temp = original_dividend_sign ^ original_divisor_sign;
remainder_sign_temp = original_dividend_sign; // Remainder sign matches dividend
if (quotient_sign_temp && final_quotient_temp != {DATA_WIDTH{1'b0}}) begin
final_quotient_temp = -final_quotient_temp;
end
if (remainder_sign_temp && final_remainder_temp != {DATA_WIDTH{1'b0}}) begin
final_remainder_temp = -final_remainder_temp;
end
end
// Assign to outputs here, they will be stable when S_FINISH asserts done_o
quotient_o <= final_quotient_temp;
remainder_o <= final_remainder_temp;
end // S_ADJUST_SIGN
S_FINISH: begin
// Outputs (quotient_o, remainder_o) were assigned in S_ADJUST_SIGN.
// Handle div_by_zero case outputs specifically for this state if they weren't already.
if (div_by_zero_flag) begin
div_by_zero_o <= 1'b1;
// Define output values for division by zero
`ifdef TEST_PROG_DIV_0_NO_CONSIDER_SIGN
quotient_o <= {DATA_WIDTH{1'b1}};
remainder_o <= dividend_abs_reg;
`else
if (is_signed_mode_reg) begin
// Example: if dividend was negative -> INT_MIN, else INT_MAX
quotient_o <= (original_dividend_sign) ? {1'b1, {(DATA_WIDTH-1){1'b0}}} : {1'b0, {(DATA_WIDTH-1){1'b1}}};
end else begin
quotient_o <= {DATA_WIDTH{1'b1}}; // Max unsigned
end
// Remainder for div by zero is often the original dividend.
// dividend_abs_reg was loaded with original dividend_i if div_by_zero was detected early.
// For signed remainder, apply original_dividend_sign.
if (is_signed_mode_reg && original_dividend_sign && dividend_abs_reg != 0) begin
remainder_o <= -dividend_abs_reg;
end else begin
remainder_o <= dividend_abs_reg; // Which was set to dividend_i in S_IDLE for div_by_zero
end
`endif
end else begin
div_by_zero_o <= 1'b0;
// quotient_o and remainder_o already set by S_ADJUST_SIGN
end
// busy_o will be de-asserted when FSM actually transitions from S_FINISH to S_IDLE
// (handled at the top of the clocked always block)
end // S_FINISH
endcase
end
end
endmodule

View File

@@ -0,0 +1,109 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2025/05/18 00:30:20
// Design Name:
// Module Name: m_ext_unit
// Project Name:
// Target Devices:
// Tool Versions:
// Description: Module to encapsulate multiplier and divider units.
//
// Dependencies: multiplier, divider
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module m_ext_unit(
// Global Signals
input clk_i,
input rstn_i,
input [ 7:0] m_ext_op_i,
input [31:0] m_ext_src1_i,
input [31:0] m_ext_src2_i,
output [31:0] m_ext_result_o,
output m_ext_valid_o,
output m_ext_stall_o
);
reg [ 7:0] m_ext_op;
reg m_ext_valid;
wire [ 3:0] div_op;
wire [ 4:0] mult_op;
// Multiplier Interface
wire [63:0] mult_product;
wire mult_done;
wire mult_busy;
// Divider Interface
wire [31:0] div_quotient;
wire [31:0] div_remainder;
wire div_done;
wire div_busy;
wire div_by_zero;
assign div_op = m_ext_op_i[3:0];
assign mult_op = m_ext_op_i[7:4];
// Instantiate Multiplier
multiplier u_multiplier (
.clk_i (clk_i),
.rstn_i (rstn_i),
.start_i (!m_ext_valid && |mult_op),
.signed_mode_i ({mult_op[1], mult_op[2] || mult_op[3]}),
.operand_a_i (m_ext_src1_i),
.operand_b_i (m_ext_src2_i),
.product_o (mult_product),
.done_o (mult_done),
.busy_o (mult_busy)
);
// Instantiate Divider
divider u_divider (
.clk_i (clk_i),
.rstn_i (rstn_i),
.start_i (!m_ext_valid && |div_op),
.signed_mode_i (div_op[1] || div_op[3]),
.dividend_i (m_ext_src1_i),
.divisor_i (m_ext_src2_i),
.quotient_o (div_quotient),
.remainder_o (div_remainder),
.done_o (div_done),
.busy_o (div_busy),
.div_by_zero_o (div_by_zero)
);
always @(posedge clk_i or negedge rstn_i) begin
if (!rstn_i) begin
m_ext_valid <= 1'b0;
end
else begin
m_ext_valid <= mult_done || div_done;
end
end
// If any m_ext_op_i bit is set (meaning an operation is requested for the current cycle),
// or if either the multiplier or divider is busy from a previous start,
// then the m_ext_unit should signal stall.
assign m_ext_stall_o = !m_ext_valid && (|m_ext_op_i || mult_busy || div_busy);
assign m_ext_valid_o = m_ext_valid;
assign m_ext_result_o = ({32{m_ext_op_i[7]}} & mult_product[31:0 ]) // MUL
| ({32{m_ext_op_i[6]}} & mult_product[63:32]) // MULH
| ({32{m_ext_op_i[5]}} & mult_product[63:32]) // MULHSU
| ({32{m_ext_op_i[4]}} & mult_product[63:32]) // MULHU
| ({32{m_ext_op_i[3]}} & div_quotient ) // DIV
| ({32{m_ext_op_i[2]}} & div_quotient ) // DIVU
| ({32{m_ext_op_i[1]}} & div_remainder ) // REM
| ({32{m_ext_op_i[0]}} & div_remainder );// REMU
endmodule

View File

@@ -0,0 +1,231 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2025/05/17 23:37:37
// Design Name:
// Module Name: multiplier
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module multiplier(
// Inputs
input wire clk_i,
input wire rstn_i,
input wire start_i, // Start signal for multiplication
input wire [ 1:0] signed_mode_i, // 0 for unsigned, 1 for signed
input wire [31:0] operand_a_i, // 32-bit Operand A (Multiplicand)
input wire [31:0] operand_b_i, // 32-bit Operand B (Multiplier)
// Outputs
output reg [63:0] product_o, // 64-bit Product
output reg done_o, // Calculation done signal
output reg busy_o // Multiplier is busy
// No div_by_zero for multiplier
);
localparam DATA_WIDTH = 32;
localparam PRODUCT_WIDTH = 64;
// FSM States
localparam S_IDLE = 3'd0;
localparam S_PREPARE = 3'd1;
localparam S_MULTIPLY_STEP = 3'd2;
localparam S_ADJUST_SIGN = 3'd3;
localparam S_FINISH = 3'd4;
reg [2:0] current_state_reg, next_state_reg;
// Internal Registers for algorithm
reg [DATA_WIDTH-1:0] m_reg; // Stores Multiplicand's absolute value
reg [DATA_WIDTH-1:0] q_reg; // Stores Multiplier's absolute value, shifts right
reg [DATA_WIDTH-1:0] acc_reg; // Accumulator for upper part of product
reg [5:0] iter_count_reg; // Iteration counter (0 to DATA_WIDTH-1)
reg operand_a_sign_reg;
reg operand_b_sign_reg;
reg [1:0] is_signed_mode_reg_internal;
// Temporary registers for calculations within clocked always block
reg [DATA_WIDTH:0] adder_result_temp; // Holds {carry, sum} from ACC + M
reg [DATA_WIDTH-1:0] final_prod_abs_q_part_temp;
reg [DATA_WIDTH-1:0] final_prod_abs_acc_part_temp;
reg [PRODUCT_WIDTH-1:0] final_product_abs;
reg final_product_sign;
//--------------------------------------------------------------------------
// FSM State Register
//--------------------------------------------------------------------------
always @(posedge clk_i or negedge rstn_i) begin
if (!rstn_i) begin
current_state_reg <= S_IDLE;
end else begin
current_state_reg <= next_state_reg;
end
end
//--------------------------------------------------------------------------
// FSM Next State Logic & Combinational Output (done_o)
//--------------------------------------------------------------------------
always @(*) begin // Verilog-2001: sensitive to all RHS signals
next_state_reg = current_state_reg; // Default
done_o = 1'b0; // Default
case (current_state_reg)
S_IDLE: begin
if (start_i) begin
next_state_reg = S_PREPARE;
end
end
S_PREPARE: begin
next_state_reg = S_MULTIPLY_STEP;
end
S_MULTIPLY_STEP: begin
if (iter_count_reg == DATA_WIDTH - 1) begin // After N iterations (0 to N-1)
next_state_reg = S_ADJUST_SIGN;
end else begin
next_state_reg = S_MULTIPLY_STEP; // Continue iteration
end
end
S_ADJUST_SIGN: begin
next_state_reg = S_FINISH;
end
S_FINISH: begin
done_o = 1'b1; // Assert done for one cycle
next_state_reg = S_IDLE;
end
default: begin
next_state_reg = S_IDLE;
end
endcase
end
//--------------------------------------------------------------------------
// Datapath Logic (Sequential - Register Updates)
//--------------------------------------------------------------------------
always @(posedge clk_i or negedge rstn_i) begin
if (!rstn_i) begin
busy_o <= 1'b0;
product_o <= {PRODUCT_WIDTH{1'b0}};
m_reg <= {DATA_WIDTH{1'b0}};
q_reg <= {DATA_WIDTH{1'b0}};
acc_reg <= {DATA_WIDTH{1'b0}};
iter_count_reg <= 6'd0;
operand_a_sign_reg <= 1'b0;
operand_b_sign_reg <= 1'b0;
is_signed_mode_reg_internal <= 2'b0;
end else begin
// busy_o is set high when IDLE sees start_i
// busy_o is set low when FSM transitions out of S_FINISH
if (current_state_reg == S_FINISH && next_state_reg == S_IDLE) begin
busy_o <= 1'b0;
end
case (current_state_reg)
S_IDLE: begin
if (start_i) begin
busy_o <= 1'b1;
product_o <= {PRODUCT_WIDTH{1'b0}}; // Clear previous product
is_signed_mode_reg_internal <= signed_mode_i;
if (signed_mode_i[0]) begin
operand_a_sign_reg <= operand_a_i[DATA_WIDTH-1];
operand_b_sign_reg <= operand_b_i[DATA_WIDTH-1];
m_reg <= operand_a_i[DATA_WIDTH-1] ? -operand_a_i : operand_a_i; // Abs A
q_reg <= operand_b_i[DATA_WIDTH-1] ? -operand_b_i : operand_b_i; // Abs B
end
else if(signed_mode_i[1]) begin
operand_a_sign_reg <= operand_a_i[DATA_WIDTH-1];
operand_b_sign_reg <= 1'b0; // Unused in unsigned mode
m_reg <= operand_a_i[DATA_WIDTH-1] ? -operand_a_i : operand_a_i; // Abs A
q_reg <= operand_b_i; // B is unsigned
end
else begin
operand_a_sign_reg <= 1'b0; // Unused
operand_b_sign_reg <= 1'b0; // Unused
m_reg <= operand_a_i;
q_reg <= operand_b_i;
end
acc_reg <= {DATA_WIDTH{1'b0}}; // ACC = 0
iter_count_reg <= 6'd0;
end
end // S_IDLE
S_PREPARE: begin
// Data loading happened in S_IDLE based on start_i.
// This state ensures one cycle for setup before iterations.
end
S_MULTIPLY_STEP: begin
if (iter_count_reg < DATA_WIDTH) begin
// Calculate ACC + M if Q[0] is 1
if (q_reg[0] == 1'b1) begin
// {Carry, Sum} = ACC + M
adder_result_temp = {1'b0, acc_reg} + {1'b0, m_reg}; // Zero-extend for N+1 bit sum
end else begin
adder_result_temp = {1'b0, acc_reg}; // ACC + 0
end
// Shift right {Carry_from_adder, ACC_from_adder, Q}
// New ACC MSB is carry_from_adder
// New Q MSB is ACC_from_adder LSB
acc_reg <= {adder_result_temp[DATA_WIDTH], adder_result_temp[DATA_WIDTH-1:1]};
q_reg <= {adder_result_temp[0], q_reg[DATA_WIDTH-1:1]};
iter_count_reg <= iter_count_reg + 1;
end
end // S_MULTIPLY_STEP
S_ADJUST_SIGN: begin
// Iteration complete. {acc_reg, q_reg} is the absolute product.
final_prod_abs_acc_part_temp = acc_reg;
final_prod_abs_q_part_temp = q_reg;
// product_o will be assigned in S_FINISH after sign adjustment
end // S_ADJUST_SIGN
S_FINISH: begin
final_product_abs = {final_prod_abs_acc_part_temp, final_prod_abs_q_part_temp};
// Check for signed multiplication modes
if (is_signed_mode_reg_internal[0]) begin // Mode: operand_a signed, operand_b signed (e.g., MULH)
final_product_sign = operand_a_sign_reg ^ operand_b_sign_reg;
if (final_product_sign && final_product_abs != {PRODUCT_WIDTH{1'b0}}) begin
product_o <= -final_product_abs; // Two's complement
end else begin
product_o <= final_product_abs;
end
end else if (is_signed_mode_reg_internal[1]) begin // Mode: operand_a signed, operand_b unsigned (e.g., MULHSU)
// For MULHSU, only operand_a's sign affects the final product's sign.
// operand_b is treated as unsigned, so its original sign bit (operand_b_sign_reg) is irrelevant here.
final_product_sign = operand_a_sign_reg; // Sign is determined by operand_a only
if (final_product_sign && final_product_abs != {PRODUCT_WIDTH{1'b0}}) begin
product_o <= -final_product_abs; // Two's complement
end else begin
product_o <= final_product_abs;
end
end else begin // Mode: Both unsigned (e.g., MULHU or standard MUL lower part)
product_o <= final_product_abs;
end
// busy_o will be de-asserted when FSM actually transitions from S_FINISH to S_IDLE
end // S_FINISH
endcase
end
end
endmodule

View File

@@ -0,0 +1,67 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2025/05/19 20:28:17
// Design Name:
// Module Name: pre_if_stage
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module pre_if_stage(
input rstn_i,
input pre_fs_to_fs_ready_i, // no use in this module, cause pre_if_stage is the first stage
output [31:0] pre_fs_to_fs_pc_o,
output pre_fs_to_fs_valid_o,
input [31:0] fs_pc_i,
input [31:0] br_target_i,
input br_taken_i,
input load_stall_i,
input m_ext_stall_i,
input a_ext_stall_i,
output inst_sram_en_o,
output [ 3:0] inst_sram_wen_o,
output [31:0] inst_sram_addr_o,
output [31:0] inst_sram_data_o
);
wire pre_fs_valid;
wire [31:0] pre_fs_next_pc;
wire pre_fs_pipeline_stall;
wire [31:0] seq_pc;
assign pre_fs_pipeline_stall = load_stall_i || m_ext_stall_i || a_ext_stall_i;
assign seq_pc = fs_pc_i + 4;
assign pre_fs_next_pc = br_taken_i ? br_target_i :
pre_fs_pipeline_stall ? fs_pc_i :
seq_pc;
assign pre_fs_valid = rstn_i && !pre_fs_pipeline_stall;
assign pre_fs_to_fs_pc_o = pre_fs_next_pc;
assign pre_fs_to_fs_valid_o = pre_fs_valid;
assign inst_sram_en_o = pre_fs_valid;
assign inst_sram_wen_o = 4'b0000; // Read only
assign inst_sram_addr_o = pre_fs_next_pc;
assign inst_sram_data_o = 32'h00000000; // No write data needed
endmodule

View File

@@ -0,0 +1,63 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2025/05/17 02:15:22
// Design Name:
// Module Name: reg_file
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module reg_file(
input clk_i,
input rstn_i,
// READ PORT 1
input [ 4:0] raddr1_i,
output [31:0] rdata1_o,
// READ PORT 2
input [ 4:0] raddr2_i,
output [31:0] rdata2_o,
// WRITE PORT
input we_i,
input [ 4:0] waddr_i,
input [31:0] wdata_i
);
reg [31:0] register[31:0];
integer i = 0;
//WRITE
always @(posedge clk_i) begin
if (!rstn_i) begin
for(i = 0; i < 32; i = i + 1) begin
register[i] <= 32'b0;
end
end
else if (we_i && (waddr_i != 5'b0)) begin
register[waddr_i]<= wdata_i;
end
end
//READ OUT 1
assign rdata1_o = ( raddr1_i == 5'b0 ) ? 32'b0 :
(we_i & (raddr1_i == waddr_i)) ? wdata_i :
register[raddr1_i];
//READ OUT 2
assign rdata2_o = ( raddr2_i == 5'b0 ) ? 32'b0 :
(we_i & (raddr2_i == waddr_i)) ? wdata_i :
register[raddr2_i];
endmodule

View File

@@ -0,0 +1,98 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2025/05/17 12:29:36
// Design Name:
// Module Name: wb_stage
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module wb_stage #(
parameter MS_TO_WS_BUS_WIDTH = 70,
parameter WS_TO_DS_BUS_WIDTH = 38
)(
input clk_i,
input rstn_i,
output ms_to_ws_bus_ready_o,
input [MS_TO_WS_BUS_WIDTH-1:0] ms_to_ws_bus_data_i,
input ms_to_ws_bus_valid_i,
output [WS_TO_DS_BUS_WIDTH-1:0] ws_to_ds_bus_data_o,
output ws_to_ds_bus_valid_o,
output [31:0] debug_wb_pc_o,
output [ 3:0] debug_wb_rf_wen_o,
output [ 4:0] debug_wb_rf_waddr_o,
output [31:0] debug_wb_rf_wdata_o
);
reg ms_to_ws_bus_valid;
reg [MS_TO_WS_BUS_WIDTH-1:0] ms_to_ws_bus_data;
wire ws_to_ds_bus_valid;
wire ws_rf_we;
wire [ 4:0] ws_rf_addr;
wire [31:0] ws_rf_wdata;
wire [31:0] ws_pc;
assign {
ws_rf_we, // 69:69
ws_rf_addr, // 68:64
ws_rf_wdata, // 63:32
ws_pc // 31:0
} = ms_to_ws_bus_data;
assign ws_to_ds_bus_valid = 1'b1;
always @(posedge clk_i or negedge rstn_i) begin
if (!rstn_i) begin
ms_to_ws_bus_valid <= 1'b0;
end
else if(ms_to_ws_bus_ready_o) begin
ms_to_ws_bus_valid <= ms_to_ws_bus_valid_i;
end
else begin
ms_to_ws_bus_valid <= ms_to_ws_bus_valid;
end
end
always @(posedge clk_i or negedge rstn_i) begin
if (!rstn_i) begin
ms_to_ws_bus_data <= {MS_TO_WS_BUS_WIDTH{1'b0}};
end
else if(ms_to_ws_bus_valid_i && ms_to_ws_bus_ready_o) begin
ms_to_ws_bus_data <= ms_to_ws_bus_data_i;
end
else begin
ms_to_ws_bus_data <= ms_to_ws_bus_data;
end
end
assign ws_to_ds_bus_data_o = {
ws_rf_we, // 37:37
ws_rf_addr, // 36:32
ws_rf_wdata // 31:0
};
assign ms_to_ws_bus_ready_o = !ms_to_ws_bus_valid || ws_to_ds_bus_valid;
assign ws_to_ds_bus_valid_o = ms_to_ws_bus_valid && ws_to_ds_bus_valid;
assign debug_wb_pc_o = ws_pc;
assign debug_wb_rf_wen_o = {4{ms_to_ws_bus_valid && ws_rf_we}};
assign debug_wb_rf_waddr_o = ws_rf_addr;
assign debug_wb_rf_wdata_o = ws_rf_wdata;
endmodule

302
rv_cpu.xpr Normal file
View File

@@ -0,0 +1,302 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Product Version: Vivado v2022.2.2 (64-bit) -->
<!-- -->
<!-- Copyright 1986-2023 Xilinx, Inc. All Rights Reserved. -->
<Project Version="7" Minor="61" Path="D:/Project/Vivado/AXKU15/rv_cpu/rv_cpu.xpr">
<DefaultLaunch Dir="$PRUNDIR"/>
<Configuration>
<Option Name="Id" Val="9057efca55624d1197d61829bb5a855e"/>
<Option Name="Part" Val="xcku15p-ffve1517-2-i"/>
<Option Name="CompiledLibDir" Val="$PCACHEDIR/compile_simlib"/>
<Option Name="CompiledLibDirXSim" Val=""/>
<Option Name="CompiledLibDirModelSim" Val="$PCACHEDIR/compile_simlib/modelsim"/>
<Option Name="CompiledLibDirQuesta" Val="$PCACHEDIR/compile_simlib/questa"/>
<Option Name="CompiledLibDirXcelium" Val="$PCACHEDIR/compile_simlib/xcelium"/>
<Option Name="CompiledLibDirVCS" Val="$PCACHEDIR/compile_simlib/vcs"/>
<Option Name="CompiledLibDirRiviera" Val="$PCACHEDIR/compile_simlib/riviera"/>
<Option Name="CompiledLibDirActivehdl" Val="$PCACHEDIR/compile_simlib/activehdl"/>
<Option Name="SimulatorInstallDirModelSim" Val=""/>
<Option Name="SimulatorInstallDirQuesta" Val=""/>
<Option Name="SimulatorInstallDirXcelium" Val=""/>
<Option Name="SimulatorInstallDirVCS" Val=""/>
<Option Name="SimulatorInstallDirRiviera" Val=""/>
<Option Name="SimulatorInstallDirActiveHdl" Val=""/>
<Option Name="SimulatorGccInstallDirModelSim" Val=""/>
<Option Name="SimulatorGccInstallDirQuesta" Val=""/>
<Option Name="SimulatorGccInstallDirXcelium" Val=""/>
<Option Name="SimulatorGccInstallDirVCS" Val=""/>
<Option Name="SimulatorGccInstallDirRiviera" Val=""/>
<Option Name="SimulatorGccInstallDirActiveHdl" Val=""/>
<Option Name="SimulatorVersionXsim" Val="2022.2"/>
<Option Name="SimulatorVersionModelSim" Val="2022.2"/>
<Option Name="SimulatorVersionQuesta" Val="2022.2"/>
<Option Name="SimulatorVersionXcelium" Val="21.09.009"/>
<Option Name="SimulatorVersionVCS" Val="S-2021.09"/>
<Option Name="SimulatorVersionRiviera" Val="2022.04"/>
<Option Name="SimulatorVersionActiveHdl" Val="13.0"/>
<Option Name="SimulatorGccVersionXsim" Val="6.2.0"/>
<Option Name="SimulatorGccVersionModelSim" Val="7.4.0"/>
<Option Name="SimulatorGccVersionQuesta" Val="7.4.0"/>
<Option Name="SimulatorGccVersionXcelium" Val="9.3.0"/>
<Option Name="SimulatorGccVersionVCS" Val="9.2.0"/>
<Option Name="SimulatorGccVersionRiviera" Val="9.3.0"/>
<Option Name="SimulatorGccVersionActiveHdl" Val="9.3.0"/>
<Option Name="BoardPart" Val=""/>
<Option Name="ActiveSimSet" Val="sim_1"/>
<Option Name="DefaultLib" Val="xil_defaultlib"/>
<Option Name="ProjectType" Val="Default"/>
<Option Name="IPOutputRepo" Val="$PCACHEDIR/ip"/>
<Option Name="IPDefaultOutputPath" Val="$PGENDIR/sources_1"/>
<Option Name="IPCachePermission" Val="read"/>
<Option Name="IPCachePermission" Val="write"/>
<Option Name="EnableCoreContainer" Val="FALSE"/>
<Option Name="EnableResourceEstimation" Val="FALSE"/>
<Option Name="SimCompileState" Val="TRUE"/>
<Option Name="CreateRefXciForCoreContainers" Val="FALSE"/>
<Option Name="IPUserFilesDir" Val="$PIPUSERFILESDIR"/>
<Option Name="IPStaticSourceDir" Val="$PIPUSERFILESDIR/ipstatic"/>
<Option Name="EnableBDX" Val="FALSE"/>
<Option Name="WTXSimLaunchSim" Val="1"/>
<Option Name="WTModelSimLaunchSim" Val="0"/>
<Option Name="WTQuestaLaunchSim" Val="0"/>
<Option Name="WTIesLaunchSim" Val="0"/>
<Option Name="WTVcsLaunchSim" Val="0"/>
<Option Name="WTRivieraLaunchSim" Val="0"/>
<Option Name="WTActivehdlLaunchSim" Val="0"/>
<Option Name="WTXSimExportSim" Val="0"/>
<Option Name="WTModelSimExportSim" Val="0"/>
<Option Name="WTQuestaExportSim" Val="0"/>
<Option Name="WTIesExportSim" Val="0"/>
<Option Name="WTVcsExportSim" Val="0"/>
<Option Name="WTRivieraExportSim" Val="0"/>
<Option Name="WTActivehdlExportSim" Val="0"/>
<Option Name="GenerateIPUpgradeLog" Val="TRUE"/>
<Option Name="XSimRadix" Val="hex"/>
<Option Name="XSimTimeUnit" Val="ns"/>
<Option Name="XSimArrayDisplayLimit" Val="1024"/>
<Option Name="XSimTraceLimit" Val="65536"/>
<Option Name="SimTypes" Val="rtl"/>
<Option Name="SimTypes" Val="bfm"/>
<Option Name="SimTypes" Val="tlm"/>
<Option Name="SimTypes" Val="tlm_dpi"/>
<Option Name="MEMEnableMemoryMapGeneration" Val="TRUE"/>
<Option Name="DcpsUptoDate" Val="TRUE"/>
<Option Name="ClassicSocBoot" Val="FALSE"/>
<Option Name="LocalIPRepoLeafDirName" Val="ip_repo"/>
</Configuration>
<FileSets Version="1" Minor="31">
<FileSet Name="sources_1" Type="DesignSrcs" RelSrcDir="$PSRCDIR/sources_1" RelGenDir="$PGENDIR/sources_1">
<Filter Type="Srcs"/>
<File Path="$PSRCDIR/sources_1/new/sub_unit/alu.v">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="implementation"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<File Path="$PSRCDIR/sources_1/new/sub_unit/m_ext_unit/divider.v">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="implementation"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<File Path="$PSRCDIR/sources_1/new/exe_stage.v">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="implementation"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<File Path="$PSRCDIR/sources_1/new/id_stage.v">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="implementation"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<File Path="$PSRCDIR/sources_1/new/if_stage.v">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="implementation"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<File Path="$PSRCDIR/sources_1/new/sub_unit/inst_decoder.v">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="implementation"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<File Path="$PSRCDIR/sources_1/new/sub_unit/m_ext_unit/m_ext_unit.v">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="implementation"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<File Path="$PSRCDIR/sources_1/new/mem_stage.v">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="implementation"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<File Path="$PSRCDIR/sources_1/new/sub_unit/m_ext_unit/multiplier.v">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="implementation"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<File Path="$PSRCDIR/sources_1/new/sub_unit/pre_if_stage.v">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="implementation"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<File Path="$PSRCDIR/sources_1/new/sub_unit/reg_file.v">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="implementation"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<File Path="$PSRCDIR/sources_1/new/wb_stage.v">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="implementation"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<File Path="$PSRCDIR/sources_1/new/cpu_top.v">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="implementation"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<File Path="$PSRCDIR/sources_1/new/sub_unit/csr_reg_file.v">
<FileInfo>
<Attr Name="AutoDisabled" Val="1"/>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="implementation"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<Config>
<Option Name="DesignMode" Val="RTL"/>
<Option Name="TopModule" Val="cpu_top"/>
<Option Name="TopAutoSet" Val="TRUE"/>
</Config>
</FileSet>
<FileSet Name="constrs_1" Type="Constrs" RelSrcDir="$PSRCDIR/constrs_1" RelGenDir="$PGENDIR/constrs_1">
<Filter Type="Constrs"/>
<Config>
<Option Name="ConstrsType" Val="XDC"/>
</Config>
</FileSet>
<FileSet Name="sim_1" Type="SimulationSrcs" RelSrcDir="$PSRCDIR/sim_1" RelGenDir="$PGENDIR/sim_1">
<Filter Type="Srcs"/>
<Config>
<Option Name="DesignMode" Val="RTL"/>
<Option Name="TopModule" Val="cpu_top"/>
<Option Name="TopLib" Val="xil_defaultlib"/>
<Option Name="TopAutoSet" Val="TRUE"/>
<Option Name="TransportPathDelay" Val="0"/>
<Option Name="TransportIntDelay" Val="0"/>
<Option Name="SelectedSimModel" Val="rtl"/>
<Option Name="PamDesignTestbench" Val=""/>
<Option Name="PamDutBypassFile" Val="xil_dut_bypass"/>
<Option Name="PamSignalDriverFile" Val="xil_bypass_driver"/>
<Option Name="PamPseudoTop" Val="pseudo_tb"/>
<Option Name="SrcSet" Val="sources_1"/>
</Config>
</FileSet>
<FileSet Name="utils_1" Type="Utils" RelSrcDir="$PSRCDIR/utils_1" RelGenDir="$PGENDIR/utils_1">
<Filter Type="Utils"/>
<Config>
<Option Name="TopAutoSet" Val="TRUE"/>
</Config>
</FileSet>
</FileSets>
<Simulators>
<Simulator Name="XSim">
<Option Name="Description" Val="Vivado Simulator"/>
<Option Name="CompiledLib" Val="0"/>
</Simulator>
<Simulator Name="ModelSim">
<Option Name="Description" Val="ModelSim Simulator"/>
</Simulator>
<Simulator Name="Questa">
<Option Name="Description" Val="Questa Advanced Simulator"/>
</Simulator>
<Simulator Name="Riviera">
<Option Name="Description" Val="Riviera-PRO Simulator"/>
</Simulator>
<Simulator Name="ActiveHDL">
<Option Name="Description" Val="Active-HDL Simulator"/>
</Simulator>
</Simulators>
<Runs Version="1" Minor="19">
<Run Id="synth_1" Type="Ft3:Synth" SrcSet="sources_1" Part="xcku15p-ffve1517-2-i" ConstrsSet="constrs_1" Description="Vivado Synthesis Defaults" AutoIncrementalCheckpoint="true" WriteIncrSynthDcp="false" State="current" IncludeInArchive="true" IsChild="false" AutoIncrementalDir="$PSRCDIR/utils_1/imports/synth_1" AutoRQSDir="$PSRCDIR/utils_1/imports/synth_1">
<Strategy Version="1" Minor="2">
<StratHandle Name="Vivado Synthesis Defaults" Flow="Vivado Synthesis 2022"/>
<Step Id="synth_design"/>
</Strategy>
<ReportStrategy Name="Vivado Synthesis Default Reports" Flow="Vivado Synthesis 2022"/>
<Report Name="ROUTE_DESIGN.REPORT_METHODOLOGY" Enabled="1"/>
<RQSFiles/>
</Run>
<Run Id="impl_1" Type="Ft2:EntireDesign" Part="xcku15p-ffve1517-2-i" ConstrsSet="constrs_1" Description="Default settings for Implementation." AutoIncrementalCheckpoint="false" WriteIncrSynthDcp="false" State="current" SynthRun="synth_1" IncludeInArchive="true" IsChild="false" GenFullBitstream="true" AutoIncrementalDir="$PSRCDIR/utils_1/imports/impl_1" AutoRQSDir="$PSRCDIR/utils_1/imports/impl_1">
<Strategy Version="1" Minor="2">
<StratHandle Name="Vivado Implementation Defaults" Flow="Vivado Implementation 2022"/>
<Step Id="init_design"/>
<Step Id="opt_design"/>
<Step Id="power_opt_design"/>
<Step Id="place_design"/>
<Step Id="post_place_power_opt_design"/>
<Step Id="phys_opt_design"/>
<Step Id="route_design"/>
<Step Id="post_route_phys_opt_design"/>
<Step Id="write_bitstream"/>
</Strategy>
<ReportStrategy Name="Vivado Implementation Default Reports" Flow="Vivado Implementation 2022"/>
<Report Name="ROUTE_DESIGN.REPORT_METHODOLOGY" Enabled="1"/>
<RQSFiles/>
</Run>
</Runs>
<Board/>
<DashboardSummary Version="1" Minor="0">
<Dashboards>
<Dashboard Name="default_dashboard">
<Gadgets>
<Gadget Name="drc_1" Type="drc" Version="1" Row="2" Column="0">
<GadgetParam Name="REPORTS" Type="string_list" Value="impl_1#impl_1_route_report_drc_0 "/>
</Gadget>
<Gadget Name="methodology_1" Type="methodology" Version="1" Row="2" Column="1">
<GadgetParam Name="REPORTS" Type="string_list" Value="impl_1#impl_1_route_report_methodology_0 "/>
</Gadget>
<Gadget Name="power_1" Type="power" Version="1" Row="1" Column="0">
<GadgetParam Name="REPORTS" Type="string_list" Value="impl_1#impl_1_route_report_power_0 "/>
</Gadget>
<Gadget Name="timing_1" Type="timing" Version="1" Row="0" Column="1">
<GadgetParam Name="REPORTS" Type="string_list" Value="impl_1#impl_1_route_report_timing_summary_0 "/>
</Gadget>
<Gadget Name="utilization_1" Type="utilization" Version="1" Row="0" Column="0">
<GadgetParam Name="REPORTS" Type="string_list" Value="synth_1#synth_1_synth_report_utilization_0 "/>
<GadgetParam Name="RUN.STEP" Type="string" Value="synth_design"/>
<GadgetParam Name="RUN.TYPE" Type="string" Value="synthesis"/>
</Gadget>
<Gadget Name="utilization_2" Type="utilization" Version="1" Row="1" Column="1">
<GadgetParam Name="REPORTS" Type="string_list" Value="impl_1#impl_1_place_report_utilization_0 "/>
</Gadget>
</Gadgets>
</Dashboard>
<CurrentDashboard>default_dashboard</CurrentDashboard>
</Dashboards>
</DashboardSummary>
</Project>