Add initial CSR support
This commit is contained in:
parent
de1f936cdd
commit
4b6218c2a8
9 changed files with 292 additions and 38 deletions
2
Makefile
2
Makefile
|
|
@ -16,7 +16,7 @@ DEVICE = 8k
|
||||||
PACKAGE = ct256
|
PACKAGE = ct256
|
||||||
PCF = ice40hx8k-b-evn.pcf
|
PCF = ice40hx8k-b-evn.pcf
|
||||||
FREQ_OSC = 12
|
FREQ_OSC = 12
|
||||||
FREQ_PLL = 32
|
FREQ_PLL = 24
|
||||||
TARGET = riscv64-unknown-elf
|
TARGET = riscv64-unknown-elf
|
||||||
AS = $(TARGET)-as
|
AS = $(TARGET)-as
|
||||||
ASFLAGS = -march=rv32i -mabi=ilp32
|
ASFLAGS = -march=rv32i -mabi=ilp32
|
||||||
|
|
|
||||||
33
rv32.sv
33
rv32.sv
|
|
@ -51,6 +51,7 @@ module rv32 (
|
||||||
logic decode_mem_fence_unreg;
|
logic decode_mem_fence_unreg;
|
||||||
|
|
||||||
/* decode -> execute control */
|
/* decode -> execute control */
|
||||||
|
logic decode_valid;
|
||||||
logic [4:0] decode_rs1;
|
logic [4:0] decode_rs1;
|
||||||
logic [4:0] decode_rs2;
|
logic [4:0] decode_rs2;
|
||||||
logic [2:0] decode_alu_op;
|
logic [2:0] decode_alu_op;
|
||||||
|
|
@ -62,6 +63,9 @@ module rv32 (
|
||||||
logic [1:0] decode_mem_width;
|
logic [1:0] decode_mem_width;
|
||||||
logic decode_mem_zero_extend;
|
logic decode_mem_zero_extend;
|
||||||
logic decode_mem_fence;
|
logic decode_mem_fence;
|
||||||
|
logic decode_csr_read;
|
||||||
|
logic decode_csr_write;
|
||||||
|
logic [1:0] decode_csr_write_op;
|
||||||
logic [1:0] decode_branch_op;
|
logic [1:0] decode_branch_op;
|
||||||
logic decode_branch_pc_src;
|
logic decode_branch_pc_src;
|
||||||
logic [4:0] decode_rd;
|
logic [4:0] decode_rd;
|
||||||
|
|
@ -72,10 +76,15 @@ module rv32 (
|
||||||
logic [31:0] decode_rs1_value;
|
logic [31:0] decode_rs1_value;
|
||||||
logic [31:0] decode_rs2_value;
|
logic [31:0] decode_rs2_value;
|
||||||
logic [31:0] decode_imm_value;
|
logic [31:0] decode_imm_value;
|
||||||
|
logic [11:0] decode_csr;
|
||||||
|
|
||||||
/* execute -> mem control */
|
/* execute -> mem control */
|
||||||
|
logic execute_valid;
|
||||||
logic execute_mem_read;
|
logic execute_mem_read;
|
||||||
logic execute_mem_write;
|
logic execute_mem_write;
|
||||||
|
logic execute_csr_read;
|
||||||
|
logic execute_csr_write;
|
||||||
|
logic [1:0] execute_csr_write_op;
|
||||||
logic [1:0] execute_mem_width;
|
logic [1:0] execute_mem_width;
|
||||||
logic execute_mem_zero_extend;
|
logic execute_mem_zero_extend;
|
||||||
logic execute_mem_fence;
|
logic execute_mem_fence;
|
||||||
|
|
@ -86,6 +95,7 @@ module rv32 (
|
||||||
/* execute -> mem data */
|
/* execute -> mem data */
|
||||||
logic [31:0] execute_result;
|
logic [31:0] execute_result;
|
||||||
logic [31:0] execute_rs2_value;
|
logic [31:0] execute_rs2_value;
|
||||||
|
logic [11:0] execute_csr;
|
||||||
logic [31:0] execute_branch_pc;
|
logic [31:0] execute_branch_pc;
|
||||||
|
|
||||||
/* mem -> writeback control */
|
/* mem -> writeback control */
|
||||||
|
|
@ -109,6 +119,7 @@ module rv32 (
|
||||||
|
|
||||||
.decode_mem_read_in(decode_mem_read),
|
.decode_mem_read_in(decode_mem_read),
|
||||||
.decode_mem_fence_in(decode_mem_fence),
|
.decode_mem_fence_in(decode_mem_fence),
|
||||||
|
.decode_csr_read_in(decode_csr_read),
|
||||||
.decode_rd_in(decode_rd),
|
.decode_rd_in(decode_rd),
|
||||||
.decode_rd_write_in(decode_rd_write),
|
.decode_rd_write_in(decode_rd_write),
|
||||||
|
|
||||||
|
|
@ -188,6 +199,7 @@ module rv32 (
|
||||||
.mem_fence_unreg_out(decode_mem_fence_unreg),
|
.mem_fence_unreg_out(decode_mem_fence_unreg),
|
||||||
|
|
||||||
/* control out */
|
/* control out */
|
||||||
|
.valid_out(decode_valid),
|
||||||
.rs1_out(decode_rs1),
|
.rs1_out(decode_rs1),
|
||||||
.rs2_out(decode_rs2),
|
.rs2_out(decode_rs2),
|
||||||
.alu_op_out(decode_alu_op),
|
.alu_op_out(decode_alu_op),
|
||||||
|
|
@ -199,6 +211,9 @@ module rv32 (
|
||||||
.mem_width_out(decode_mem_width),
|
.mem_width_out(decode_mem_width),
|
||||||
.mem_zero_extend_out(decode_mem_zero_extend),
|
.mem_zero_extend_out(decode_mem_zero_extend),
|
||||||
.mem_fence_out(decode_mem_fence),
|
.mem_fence_out(decode_mem_fence),
|
||||||
|
.csr_read_out(decode_csr_read),
|
||||||
|
.csr_write_out(decode_csr_write),
|
||||||
|
.csr_write_op_out(decode_csr_write_op),
|
||||||
.branch_op_out(decode_branch_op),
|
.branch_op_out(decode_branch_op),
|
||||||
.branch_pc_src_out(decode_branch_pc_src),
|
.branch_pc_src_out(decode_branch_pc_src),
|
||||||
.rd_out(decode_rd),
|
.rd_out(decode_rd),
|
||||||
|
|
@ -208,7 +223,8 @@ module rv32 (
|
||||||
.pc_out(decode_pc),
|
.pc_out(decode_pc),
|
||||||
.rs1_value_out(decode_rs1_value),
|
.rs1_value_out(decode_rs1_value),
|
||||||
.rs2_value_out(decode_rs2_value),
|
.rs2_value_out(decode_rs2_value),
|
||||||
.imm_value_out(decode_imm_value)
|
.imm_value_out(decode_imm_value),
|
||||||
|
.csr_out(decode_csr)
|
||||||
);
|
);
|
||||||
|
|
||||||
rv32_execute execute (
|
rv32_execute execute (
|
||||||
|
|
@ -219,6 +235,7 @@ module rv32 (
|
||||||
.flush_in(execute_flush),
|
.flush_in(execute_flush),
|
||||||
|
|
||||||
/* control in */
|
/* control in */
|
||||||
|
.valid_in(decode_valid),
|
||||||
.rs1_in(decode_rs1),
|
.rs1_in(decode_rs1),
|
||||||
.rs2_in(decode_rs2),
|
.rs2_in(decode_rs2),
|
||||||
.alu_op_in(decode_alu_op),
|
.alu_op_in(decode_alu_op),
|
||||||
|
|
@ -230,6 +247,9 @@ module rv32 (
|
||||||
.mem_width_in(decode_mem_width),
|
.mem_width_in(decode_mem_width),
|
||||||
.mem_zero_extend_in(decode_mem_zero_extend),
|
.mem_zero_extend_in(decode_mem_zero_extend),
|
||||||
.mem_fence_in(decode_mem_fence),
|
.mem_fence_in(decode_mem_fence),
|
||||||
|
.csr_read_in(decode_csr_read),
|
||||||
|
.csr_write_in(decode_csr_write),
|
||||||
|
.csr_write_op_in(decode_csr_write_op),
|
||||||
.branch_op_in(decode_branch_op),
|
.branch_op_in(decode_branch_op),
|
||||||
.branch_pc_src_in(decode_branch_pc_src),
|
.branch_pc_src_in(decode_branch_pc_src),
|
||||||
.rd_in(decode_rd),
|
.rd_in(decode_rd),
|
||||||
|
|
@ -244,16 +264,21 @@ module rv32 (
|
||||||
.rs1_value_in(decode_rs1_value),
|
.rs1_value_in(decode_rs1_value),
|
||||||
.rs2_value_in(decode_rs2_value),
|
.rs2_value_in(decode_rs2_value),
|
||||||
.imm_value_in(decode_imm_value),
|
.imm_value_in(decode_imm_value),
|
||||||
|
.csr_in(decode_csr),
|
||||||
|
|
||||||
/* data in (from writeback) */
|
/* data in (from writeback) */
|
||||||
.writeback_rd_value_in(mem_rd_value),
|
.writeback_rd_value_in(mem_rd_value),
|
||||||
|
|
||||||
/* control out */
|
/* control out */
|
||||||
|
.valid_out(execute_valid),
|
||||||
.mem_read_out(execute_mem_read),
|
.mem_read_out(execute_mem_read),
|
||||||
.mem_write_out(execute_mem_write),
|
.mem_write_out(execute_mem_write),
|
||||||
.mem_width_out(execute_mem_width),
|
.mem_width_out(execute_mem_width),
|
||||||
.mem_zero_extend_out(execute_mem_zero_extend),
|
.mem_zero_extend_out(execute_mem_zero_extend),
|
||||||
.mem_fence_out(execute_mem_fence),
|
.mem_fence_out(execute_mem_fence),
|
||||||
|
.csr_read_out(execute_csr_read),
|
||||||
|
.csr_write_out(execute_csr_write),
|
||||||
|
.csr_write_op_out(execute_csr_write_op),
|
||||||
.branch_op_out(execute_branch_op),
|
.branch_op_out(execute_branch_op),
|
||||||
.rd_out(execute_rd),
|
.rd_out(execute_rd),
|
||||||
.rd_write_out(execute_rd_write),
|
.rd_write_out(execute_rd_write),
|
||||||
|
|
@ -261,6 +286,7 @@ module rv32 (
|
||||||
/* data out */
|
/* data out */
|
||||||
.result_out(execute_result),
|
.result_out(execute_result),
|
||||||
.rs2_value_out(execute_rs2_value),
|
.rs2_value_out(execute_rs2_value),
|
||||||
|
.csr_out(execute_csr),
|
||||||
.branch_pc_out(execute_branch_pc)
|
.branch_pc_out(execute_branch_pc)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -272,10 +298,14 @@ module rv32 (
|
||||||
.flush_in(mem_flush),
|
.flush_in(mem_flush),
|
||||||
|
|
||||||
/* control in */
|
/* control in */
|
||||||
|
.valid_in(execute_valid),
|
||||||
.read_in(execute_mem_read),
|
.read_in(execute_mem_read),
|
||||||
.write_in(execute_mem_write),
|
.write_in(execute_mem_write),
|
||||||
.width_in(execute_mem_width),
|
.width_in(execute_mem_width),
|
||||||
.zero_extend_in(execute_mem_zero_extend),
|
.zero_extend_in(execute_mem_zero_extend),
|
||||||
|
.csr_read_in(execute_csr_read),
|
||||||
|
.csr_write_in(execute_csr_write),
|
||||||
|
.csr_write_op_in(execute_csr_write_op),
|
||||||
.branch_op_in(execute_branch_op),
|
.branch_op_in(execute_branch_op),
|
||||||
.rd_in(execute_rd),
|
.rd_in(execute_rd),
|
||||||
.rd_write_in(execute_rd_write),
|
.rd_write_in(execute_rd_write),
|
||||||
|
|
@ -283,6 +313,7 @@ module rv32 (
|
||||||
/* data in */
|
/* data in */
|
||||||
.result_in(execute_result),
|
.result_in(execute_result),
|
||||||
.rs2_value_in(execute_rs2_value),
|
.rs2_value_in(execute_rs2_value),
|
||||||
|
.csr_in(execute_csr),
|
||||||
.branch_pc_in(execute_branch_pc),
|
.branch_pc_in(execute_branch_pc),
|
||||||
|
|
||||||
/* data in (from memory bus) */
|
/* data in (from memory bus) */
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,8 @@
|
||||||
|
|
||||||
`define RV32_ALU_SRC2_REG 2'b00
|
`define RV32_ALU_SRC2_REG 2'b00
|
||||||
`define RV32_ALU_SRC2_IMM 2'b01
|
`define RV32_ALU_SRC2_IMM 2'b01
|
||||||
`define RV32_ALU_SRC2_FOUR 2'b10
|
`define RV32_ALU_SRC2_ZERO 2'b10
|
||||||
|
`define RV32_ALU_SRC2_FOUR 2'b11
|
||||||
|
|
||||||
module rv32_alu (
|
module rv32_alu (
|
||||||
/* control in */
|
/* control in */
|
||||||
|
|
@ -63,8 +64,8 @@ module rv32_alu (
|
||||||
case (src2_in)
|
case (src2_in)
|
||||||
`RV32_ALU_SRC2_REG: src2 = rs2_value_in;
|
`RV32_ALU_SRC2_REG: src2 = rs2_value_in;
|
||||||
`RV32_ALU_SRC2_IMM: src2 = imm_value_in;
|
`RV32_ALU_SRC2_IMM: src2 = imm_value_in;
|
||||||
|
`RV32_ALU_SRC2_ZERO: src2 = 0;
|
||||||
`RV32_ALU_SRC2_FOUR: src2 = 4;
|
`RV32_ALU_SRC2_FOUR: src2 = 4;
|
||||||
default: src2 = 32'bx;
|
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
`define RV32_CONTROL
|
`define RV32_CONTROL
|
||||||
|
|
||||||
`include "rv32_alu.sv"
|
`include "rv32_alu.sv"
|
||||||
|
`include "rv32_csrs.sv"
|
||||||
`include "rv32_branch.sv"
|
`include "rv32_branch.sv"
|
||||||
`include "rv32_imm.sv"
|
`include "rv32_imm.sv"
|
||||||
`include "rv32_mem.sv"
|
`include "rv32_mem.sv"
|
||||||
|
|
@ -11,6 +12,10 @@ module rv32_control_unit (
|
||||||
/* data in */
|
/* data in */
|
||||||
input [31:0] instr_in,
|
input [31:0] instr_in,
|
||||||
|
|
||||||
|
/* control in */
|
||||||
|
input [4:0] rs1_in,
|
||||||
|
input [4:0] rd_in,
|
||||||
|
|
||||||
/* control out */
|
/* control out */
|
||||||
output logic valid_out,
|
output logic valid_out,
|
||||||
output logic [2:0] imm_out,
|
output logic [2:0] imm_out,
|
||||||
|
|
@ -23,6 +28,9 @@ module rv32_control_unit (
|
||||||
output logic [1:0] mem_width_out,
|
output logic [1:0] mem_width_out,
|
||||||
output logic mem_zero_extend_out,
|
output logic mem_zero_extend_out,
|
||||||
output logic mem_fence_out,
|
output logic mem_fence_out,
|
||||||
|
output logic csr_read_out,
|
||||||
|
output logic csr_write_out,
|
||||||
|
output logic [1:0] csr_write_op_out,
|
||||||
output logic [1:0] branch_op_out,
|
output logic [1:0] branch_op_out,
|
||||||
output logic branch_pc_src_out,
|
output logic branch_pc_src_out,
|
||||||
output logic rd_write_out
|
output logic rd_write_out
|
||||||
|
|
@ -39,6 +47,9 @@ module rv32_control_unit (
|
||||||
mem_width_out = 2'bx;
|
mem_width_out = 2'bx;
|
||||||
mem_zero_extend_out = 1'bx;
|
mem_zero_extend_out = 1'bx;
|
||||||
mem_fence_out = 0;
|
mem_fence_out = 0;
|
||||||
|
csr_read_out = 0;
|
||||||
|
csr_write_out = 0;
|
||||||
|
csr_write_op_out = 2'bx;
|
||||||
branch_op_out = `RV32_BRANCH_OP_NEVER;
|
branch_op_out = `RV32_BRANCH_OP_NEVER;
|
||||||
branch_pc_src_out = 1'bx;
|
branch_pc_src_out = 1'bx;
|
||||||
rd_write_out = 0;
|
rd_write_out = 0;
|
||||||
|
|
@ -410,27 +421,72 @@ module rv32_control_unit (
|
||||||
end
|
end
|
||||||
`RV32_INSTR_CSRRW: begin
|
`RV32_INSTR_CSRRW: begin
|
||||||
valid_out = 1;
|
valid_out = 1;
|
||||||
// TODO
|
alu_op_out = `RV32_ALU_OP_ADD_SUB;
|
||||||
|
alu_sub_sra_out = 0;
|
||||||
|
alu_src1_out = `RV32_ALU_SRC1_REG;
|
||||||
|
alu_src2_out = `RV32_ALU_SRC2_ZERO;
|
||||||
|
csr_read_out = |rd_in;
|
||||||
|
csr_write_out = 1;
|
||||||
|
csr_write_op_out = `RV32_CSR_WRITE_OP_RW;
|
||||||
|
rd_write_out = |rd_in;
|
||||||
end
|
end
|
||||||
`RV32_INSTR_CSRRS: begin
|
`RV32_INSTR_CSRRS: begin
|
||||||
valid_out = 1;
|
valid_out = 1;
|
||||||
// TODO
|
alu_op_out = `RV32_ALU_OP_ADD_SUB;
|
||||||
|
alu_sub_sra_out = 0;
|
||||||
|
alu_src1_out = `RV32_ALU_SRC1_REG;
|
||||||
|
alu_src2_out = `RV32_ALU_SRC2_ZERO;
|
||||||
|
csr_read_out = 1;
|
||||||
|
csr_write_out = |rs1_in;
|
||||||
|
csr_write_op_out = `RV32_CSR_WRITE_OP_RS;
|
||||||
|
rd_write_out = 1;
|
||||||
end
|
end
|
||||||
`RV32_INSTR_CSRRC: begin
|
`RV32_INSTR_CSRRC: begin
|
||||||
valid_out = 1;
|
valid_out = 1;
|
||||||
// TODO
|
alu_op_out = `RV32_ALU_OP_ADD_SUB;
|
||||||
|
alu_sub_sra_out = 0;
|
||||||
|
alu_src1_out = `RV32_ALU_SRC1_REG;
|
||||||
|
alu_src2_out = `RV32_ALU_SRC2_ZERO;
|
||||||
|
csr_read_out = 1;
|
||||||
|
csr_write_out = |rs1_in;
|
||||||
|
csr_write_op_out = `RV32_CSR_WRITE_OP_RC;
|
||||||
|
rd_write_out = 1;
|
||||||
end
|
end
|
||||||
`RV32_INSTR_CSRRWI: begin
|
`RV32_INSTR_CSRRWI: begin
|
||||||
valid_out = 1;
|
valid_out = 1;
|
||||||
// TODO
|
imm_out = `RV32_IMM_ZIMM;
|
||||||
|
alu_op_out = `RV32_ALU_OP_ADD_SUB;
|
||||||
|
alu_sub_sra_out = 0;
|
||||||
|
alu_src1_out = `RV32_ALU_SRC1_ZERO;
|
||||||
|
alu_src2_out = `RV32_ALU_SRC2_IMM;
|
||||||
|
csr_read_out = |rd_in;
|
||||||
|
csr_write_out = 1;
|
||||||
|
csr_write_op_out = `RV32_CSR_WRITE_OP_RW;
|
||||||
|
rd_write_out = |rd_in;
|
||||||
end
|
end
|
||||||
`RV32_INSTR_CSRRSI: begin
|
`RV32_INSTR_CSRRSI: begin
|
||||||
valid_out = 1;
|
valid_out = 1;
|
||||||
// TODO
|
imm_out = `RV32_IMM_ZIMM;
|
||||||
|
alu_op_out = `RV32_ALU_OP_ADD_SUB;
|
||||||
|
alu_sub_sra_out = 0;
|
||||||
|
alu_src1_out = `RV32_ALU_SRC1_ZERO;
|
||||||
|
alu_src2_out = `RV32_ALU_SRC2_IMM;
|
||||||
|
csr_read_out = 1;
|
||||||
|
csr_write_out = |rs1_in;
|
||||||
|
csr_write_op_out = `RV32_CSR_WRITE_OP_RS;
|
||||||
|
rd_write_out = 1;
|
||||||
end
|
end
|
||||||
`RV32_INSTR_CSRRCI: begin
|
`RV32_INSTR_CSRRCI: begin
|
||||||
valid_out = 1;
|
valid_out = 1;
|
||||||
// TODO
|
imm_out = `RV32_IMM_ZIMM;
|
||||||
|
alu_op_out = `RV32_ALU_OP_ADD_SUB;
|
||||||
|
alu_sub_sra_out = 0;
|
||||||
|
alu_src1_out = `RV32_ALU_SRC1_ZERO;
|
||||||
|
alu_src2_out = `RV32_ALU_SRC2_IMM;
|
||||||
|
csr_read_out = 1;
|
||||||
|
csr_write_out = |rs1_in;
|
||||||
|
csr_write_op_out = `RV32_CSR_WRITE_OP_RC;
|
||||||
|
rd_write_out = 1;
|
||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
|
||||||
73
rv32_csrs.sv
Normal file
73
rv32_csrs.sv
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
`ifndef RV32_CSRS
|
||||||
|
`define RV32_CSRS
|
||||||
|
|
||||||
|
/* |rw|pl| id | */
|
||||||
|
`define RV32_CSR_CYCLE 12'b11_00_00000000
|
||||||
|
`define RV32_CSR_TIME 12'b11_00_00000001
|
||||||
|
`define RV32_CSR_INSTRET 12'b11_00_00000010
|
||||||
|
`define RV32_CSR_CYCLEH 12'b11_00_10000000
|
||||||
|
`define RV32_CSR_TIMEH 12'b11_00_10000001
|
||||||
|
`define RV32_CSR_INSTRETH 12'b11_00_10000010
|
||||||
|
|
||||||
|
`define RV32_CSR_WRITE_OP_RW 2'b00
|
||||||
|
`define RV32_CSR_WRITE_OP_RS 2'b01
|
||||||
|
`define RV32_CSR_WRITE_OP_RC 2'b10
|
||||||
|
|
||||||
|
module rv32_csrs (
|
||||||
|
input clk,
|
||||||
|
|
||||||
|
/* control in (from hazard) */
|
||||||
|
input stall_in,
|
||||||
|
|
||||||
|
/* control in */
|
||||||
|
input read_in,
|
||||||
|
input write_in,
|
||||||
|
input [1:0] write_op_in,
|
||||||
|
|
||||||
|
/* control in (from writeback) */
|
||||||
|
input instr_retired_in,
|
||||||
|
|
||||||
|
/* data in */
|
||||||
|
input [31:0] result_in,
|
||||||
|
input [11:0] csr_in,
|
||||||
|
|
||||||
|
/* data out */
|
||||||
|
output logic [31:0] read_value_out
|
||||||
|
);
|
||||||
|
logic [31:0] write_value;
|
||||||
|
|
||||||
|
logic [31:0] cycleh;
|
||||||
|
logic [31:0] cycle;
|
||||||
|
|
||||||
|
logic [31:0] instreth;
|
||||||
|
logic [31:0] instret;
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
case (csr_in)
|
||||||
|
`RV32_CSR_CYCLE: read_value_out = cycle;
|
||||||
|
`RV32_CSR_TIME: read_value_out = cycle;
|
||||||
|
`RV32_CSR_INSTRET: read_value_out = instret;
|
||||||
|
`RV32_CSR_CYCLEH: read_value_out = cycleh;
|
||||||
|
`RV32_CSR_TIMEH: read_value_out = cycleh;
|
||||||
|
`RV32_CSR_INSTRETH: read_value_out = instreth;
|
||||||
|
default: read_value_out = 32'bx;
|
||||||
|
endcase
|
||||||
|
|
||||||
|
case (write_op_in)
|
||||||
|
`RV32_CSR_WRITE_OP_RW: write_value = result_in;
|
||||||
|
`RV32_CSR_WRITE_OP_RS: write_value = read_value_out | result_in;
|
||||||
|
`RV32_CSR_WRITE_OP_RC: write_value = read_value_out & ~result_in;
|
||||||
|
default: write_value = 32'bx;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
cycleh <= cycleh + &cycle;
|
||||||
|
cycle <= cycle + 1;
|
||||||
|
|
||||||
|
instreth <= instreth + &instret;
|
||||||
|
instret <= instret + instr_retired_in;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
`endif
|
||||||
|
|
@ -28,6 +28,7 @@ module rv32_decode (
|
||||||
output logic mem_fence_unreg_out,
|
output logic mem_fence_unreg_out,
|
||||||
|
|
||||||
/* control out */
|
/* control out */
|
||||||
|
output logic valid_out,
|
||||||
output logic [4:0] rs1_out,
|
output logic [4:0] rs1_out,
|
||||||
output logic [4:0] rs2_out,
|
output logic [4:0] rs2_out,
|
||||||
output logic [2:0] alu_op_out,
|
output logic [2:0] alu_op_out,
|
||||||
|
|
@ -39,6 +40,9 @@ module rv32_decode (
|
||||||
output logic [1:0] mem_width_out,
|
output logic [1:0] mem_width_out,
|
||||||
output logic mem_zero_extend_out,
|
output logic mem_zero_extend_out,
|
||||||
output logic mem_fence_out,
|
output logic mem_fence_out,
|
||||||
|
output logic csr_read_out,
|
||||||
|
output logic csr_write_out,
|
||||||
|
output logic [1:0] csr_write_op_out,
|
||||||
output logic [1:0] branch_op_out,
|
output logic [1:0] branch_op_out,
|
||||||
output logic branch_pc_src_out,
|
output logic branch_pc_src_out,
|
||||||
output logic [4:0] rd_out,
|
output logic [4:0] rd_out,
|
||||||
|
|
@ -48,7 +52,8 @@ module rv32_decode (
|
||||||
output logic [31:0] pc_out,
|
output logic [31:0] pc_out,
|
||||||
output logic [31:0] rs1_value_out,
|
output logic [31:0] rs1_value_out,
|
||||||
output logic [31:0] rs2_value_out,
|
output logic [31:0] rs2_value_out,
|
||||||
output logic [31:0] imm_value_out
|
output logic [31:0] imm_value_out,
|
||||||
|
output logic [11:0] csr_out
|
||||||
);
|
);
|
||||||
logic [4:0] rs2;
|
logic [4:0] rs2;
|
||||||
logic [4:0] rs1;
|
logic [4:0] rs1;
|
||||||
|
|
@ -90,6 +95,9 @@ module rv32_decode (
|
||||||
logic [1:0] mem_width;
|
logic [1:0] mem_width;
|
||||||
logic mem_zero_extend;
|
logic mem_zero_extend;
|
||||||
logic mem_fence;
|
logic mem_fence;
|
||||||
|
logic csr_read;
|
||||||
|
logic csr_write;
|
||||||
|
logic [1:0] csr_write_op;
|
||||||
logic [1:0] branch_op;
|
logic [1:0] branch_op;
|
||||||
logic branch_pc_src;
|
logic branch_pc_src;
|
||||||
logic rd_write;
|
logic rd_write;
|
||||||
|
|
@ -100,6 +108,10 @@ module rv32_decode (
|
||||||
/* data in */
|
/* data in */
|
||||||
.instr_in(instr_in),
|
.instr_in(instr_in),
|
||||||
|
|
||||||
|
/* control in */
|
||||||
|
.rs1_in(rs1),
|
||||||
|
.rd_in(rd),
|
||||||
|
|
||||||
/* control out */
|
/* control out */
|
||||||
.valid_out(valid),
|
.valid_out(valid),
|
||||||
.imm_out(imm),
|
.imm_out(imm),
|
||||||
|
|
@ -112,6 +124,9 @@ module rv32_decode (
|
||||||
.mem_width_out(mem_width),
|
.mem_width_out(mem_width),
|
||||||
.mem_zero_extend_out(mem_zero_extend),
|
.mem_zero_extend_out(mem_zero_extend),
|
||||||
.mem_fence_out(mem_fence),
|
.mem_fence_out(mem_fence),
|
||||||
|
.csr_read_out(csr_read),
|
||||||
|
.csr_write_out(csr_write),
|
||||||
|
.csr_write_op_out(csr_write_op),
|
||||||
.branch_op_out(branch_op),
|
.branch_op_out(branch_op),
|
||||||
.branch_pc_src_out(branch_pc_src),
|
.branch_pc_src_out(branch_pc_src),
|
||||||
.rd_write_out(rd_write)
|
.rd_write_out(rd_write)
|
||||||
|
|
@ -130,8 +145,13 @@ module rv32_decode (
|
||||||
.imm_value_out(imm_value)
|
.imm_value_out(imm_value)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
logic [11:0] csr;
|
||||||
|
|
||||||
|
assign csr = instr_in[31:20];
|
||||||
|
|
||||||
always_ff @(posedge clk) begin
|
always_ff @(posedge clk) begin
|
||||||
if (!stall_in) begin
|
if (!stall_in) begin
|
||||||
|
valid_out <= valid;
|
||||||
rs1_out <= rs1;
|
rs1_out <= rs1;
|
||||||
rs2_out <= rs2;
|
rs2_out <= rs2;
|
||||||
alu_op_out <= alu_op;
|
alu_op_out <= alu_op;
|
||||||
|
|
@ -143,6 +163,9 @@ module rv32_decode (
|
||||||
mem_width_out <= mem_width;
|
mem_width_out <= mem_width;
|
||||||
mem_zero_extend_out <= mem_zero_extend;
|
mem_zero_extend_out <= mem_zero_extend;
|
||||||
mem_fence_out <= mem_fence;
|
mem_fence_out <= mem_fence;
|
||||||
|
csr_read_out <= csr_read;
|
||||||
|
csr_write_out <= csr_write;
|
||||||
|
csr_write_op_out <= csr_write_op;
|
||||||
branch_op_out <= branch_op;
|
branch_op_out <= branch_op;
|
||||||
branch_pc_src_out <= branch_pc_src;
|
branch_pc_src_out <= branch_pc_src;
|
||||||
rd_out <= rd;
|
rd_out <= rd;
|
||||||
|
|
@ -150,10 +173,14 @@ module rv32_decode (
|
||||||
|
|
||||||
pc_out <= pc_in;
|
pc_out <= pc_in;
|
||||||
imm_value_out <= imm_value;
|
imm_value_out <= imm_value;
|
||||||
|
csr_out <= csr;
|
||||||
|
|
||||||
if (flush_in) begin
|
if (flush_in) begin
|
||||||
|
valid_out <= 0;
|
||||||
mem_read_out <= 0;
|
mem_read_out <= 0;
|
||||||
mem_write_out <= 0;
|
mem_write_out <= 0;
|
||||||
|
csr_read_out <= 0;
|
||||||
|
csr_write_out <= 0;
|
||||||
branch_op_out <= `RV32_BRANCH_OP_NEVER;
|
branch_op_out <= `RV32_BRANCH_OP_NEVER;
|
||||||
rd_write_out <= 0;
|
rd_write_out <= 0;
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ module rv32_execute (
|
||||||
input flush_in,
|
input flush_in,
|
||||||
|
|
||||||
/* control in */
|
/* control in */
|
||||||
|
input valid_in,
|
||||||
input [4:0] rs1_in,
|
input [4:0] rs1_in,
|
||||||
input [4:0] rs2_in,
|
input [4:0] rs2_in,
|
||||||
input [2:0] alu_op_in,
|
input [2:0] alu_op_in,
|
||||||
|
|
@ -23,6 +24,9 @@ module rv32_execute (
|
||||||
input [1:0] mem_width_in,
|
input [1:0] mem_width_in,
|
||||||
input mem_zero_extend_in,
|
input mem_zero_extend_in,
|
||||||
input mem_fence_in,
|
input mem_fence_in,
|
||||||
|
input csr_read_in,
|
||||||
|
input csr_write_in,
|
||||||
|
input [1:0] csr_write_op_in,
|
||||||
input [1:0] branch_op_in,
|
input [1:0] branch_op_in,
|
||||||
input branch_pc_src_in,
|
input branch_pc_src_in,
|
||||||
input [4:0] rd_in,
|
input [4:0] rd_in,
|
||||||
|
|
@ -37,16 +41,21 @@ module rv32_execute (
|
||||||
input [31:0] rs1_value_in,
|
input [31:0] rs1_value_in,
|
||||||
input [31:0] rs2_value_in,
|
input [31:0] rs2_value_in,
|
||||||
input [31:0] imm_value_in,
|
input [31:0] imm_value_in,
|
||||||
|
input [11:0] csr_in,
|
||||||
|
|
||||||
/* data in (from writeback) */
|
/* data in (from writeback) */
|
||||||
input [31:0] writeback_rd_value_in,
|
input [31:0] writeback_rd_value_in,
|
||||||
|
|
||||||
/* control out */
|
/* control out */
|
||||||
|
output logic valid_out,
|
||||||
output logic mem_read_out,
|
output logic mem_read_out,
|
||||||
output logic mem_write_out,
|
output logic mem_write_out,
|
||||||
output logic [1:0] mem_width_out,
|
output logic [1:0] mem_width_out,
|
||||||
output logic mem_zero_extend_out,
|
output logic mem_zero_extend_out,
|
||||||
output logic mem_fence_out,
|
output logic mem_fence_out,
|
||||||
|
output logic csr_read_out,
|
||||||
|
output logic csr_write_out,
|
||||||
|
output logic [1:0] csr_write_op_out,
|
||||||
output logic [1:0] branch_op_out,
|
output logic [1:0] branch_op_out,
|
||||||
output logic [4:0] rd_out,
|
output logic [4:0] rd_out,
|
||||||
output logic rd_write_out,
|
output logic rd_write_out,
|
||||||
|
|
@ -54,6 +63,7 @@ module rv32_execute (
|
||||||
/* data out */
|
/* data out */
|
||||||
output logic [31:0] result_out,
|
output logic [31:0] result_out,
|
||||||
output logic [31:0] rs2_value_out,
|
output logic [31:0] rs2_value_out,
|
||||||
|
output logic [11:0] csr_out,
|
||||||
output logic [31:0] branch_pc_out
|
output logic [31:0] branch_pc_out
|
||||||
);
|
);
|
||||||
logic [31:0] rs1_value;
|
logic [31:0] rs1_value;
|
||||||
|
|
@ -111,21 +121,29 @@ module rv32_execute (
|
||||||
|
|
||||||
always_ff @(posedge clk) begin
|
always_ff @(posedge clk) begin
|
||||||
if (!stall_in) begin
|
if (!stall_in) begin
|
||||||
|
valid_out <= valid_in;
|
||||||
mem_read_out <= mem_read_in;
|
mem_read_out <= mem_read_in;
|
||||||
mem_write_out <= mem_write_in;
|
mem_write_out <= mem_write_in;
|
||||||
mem_width_out <= mem_width_in;
|
mem_width_out <= mem_width_in;
|
||||||
mem_zero_extend_out <= mem_zero_extend_in;
|
mem_zero_extend_out <= mem_zero_extend_in;
|
||||||
mem_fence_out <= mem_fence_in;
|
mem_fence_out <= mem_fence_in;
|
||||||
|
csr_read_out <= csr_read_in;
|
||||||
|
csr_write_out <= csr_write_in;
|
||||||
|
csr_write_op_out <= csr_write_op_in;
|
||||||
branch_op_out <= branch_op_in;
|
branch_op_out <= branch_op_in;
|
||||||
rd_out <= rd_in;
|
rd_out <= rd_in;
|
||||||
rd_write_out <= rd_write_in;
|
rd_write_out <= rd_write_in;
|
||||||
result_out <= result;
|
result_out <= result;
|
||||||
rs2_value_out <= rs2_value;
|
rs2_value_out <= rs2_value;
|
||||||
|
csr_out <= csr_in;
|
||||||
branch_pc_out <= branch_pc;
|
branch_pc_out <= branch_pc;
|
||||||
|
|
||||||
if (flush_in) begin
|
if (flush_in) begin
|
||||||
|
valid_out <= 0;
|
||||||
mem_read_out <= 0;
|
mem_read_out <= 0;
|
||||||
mem_write_out <= 0;
|
mem_write_out <= 0;
|
||||||
|
csr_read_out <= 0;
|
||||||
|
csr_write_out <= 0;
|
||||||
branch_op_out <= `RV32_BRANCH_OP_NEVER;
|
branch_op_out <= `RV32_BRANCH_OP_NEVER;
|
||||||
rd_write_out <= 0;
|
rd_write_out <= 0;
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ module rv32_hazard_unit (
|
||||||
|
|
||||||
input decode_mem_read_in,
|
input decode_mem_read_in,
|
||||||
input decode_mem_fence_in,
|
input decode_mem_fence_in,
|
||||||
|
input decode_csr_read_in,
|
||||||
input [4:0] decode_rd_in,
|
input [4:0] decode_rd_in,
|
||||||
input decode_rd_write_in,
|
input decode_rd_write_in,
|
||||||
|
|
||||||
|
|
@ -42,7 +43,7 @@ module rv32_hazard_unit (
|
||||||
logic mem_wait_for_bus;
|
logic mem_wait_for_bus;
|
||||||
|
|
||||||
assign fetch_wait_for_bus = instr_read_in && !instr_ready_in;
|
assign fetch_wait_for_bus = instr_read_in && !instr_ready_in;
|
||||||
assign fetch_wait_for_mem_read = (decode_rs1_unreg_in == decode_rd_in || decode_rs2_unreg_in == decode_rd_in) && |decode_rd_in && decode_mem_read_in && decode_rd_write_in;
|
assign fetch_wait_for_mem_read = (decode_rs1_unreg_in == decode_rd_in || decode_rs2_unreg_in == decode_rd_in) && |decode_rd_in && (decode_mem_read_in || decode_csr_read_in) && decode_rd_write_in;
|
||||||
assign fetch_wait_for_mem_fence = decode_mem_fence_unreg_in || decode_mem_fence_in || execute_mem_fence_in;
|
assign fetch_wait_for_mem_fence = decode_mem_fence_unreg_in || decode_mem_fence_in || execute_mem_fence_in;
|
||||||
assign mem_wait_for_bus = (data_read_in || data_write_in) && !data_ready_in;
|
assign mem_wait_for_bus = (data_read_in || data_write_in) && !data_ready_in;
|
||||||
|
|
||||||
|
|
|
||||||
99
rv32_mem.sv
99
rv32_mem.sv
|
|
@ -15,10 +15,14 @@ module rv32_mem (
|
||||||
input flush_in,
|
input flush_in,
|
||||||
|
|
||||||
/* control in */
|
/* control in */
|
||||||
|
input valid_in,
|
||||||
input read_in,
|
input read_in,
|
||||||
input write_in,
|
input write_in,
|
||||||
input [1:0] width_in,
|
input [1:0] width_in,
|
||||||
input zero_extend_in,
|
input zero_extend_in,
|
||||||
|
input csr_read_in,
|
||||||
|
input csr_write_in,
|
||||||
|
input [1:0] csr_write_op_in,
|
||||||
input [1:0] branch_op_in,
|
input [1:0] branch_op_in,
|
||||||
input [4:0] rd_in,
|
input [4:0] rd_in,
|
||||||
input rd_write_in,
|
input rd_write_in,
|
||||||
|
|
@ -26,12 +30,14 @@ module rv32_mem (
|
||||||
/* data in */
|
/* data in */
|
||||||
input [31:0] result_in,
|
input [31:0] result_in,
|
||||||
input [31:0] rs2_value_in,
|
input [31:0] rs2_value_in,
|
||||||
|
input [11:0] csr_in,
|
||||||
input [31:0] branch_pc_in,
|
input [31:0] branch_pc_in,
|
||||||
|
|
||||||
/* data in (from data memory bus) */
|
/* data in (from data memory bus) */
|
||||||
input [31:0] data_read_value_in,
|
input [31:0] data_read_value_in,
|
||||||
|
|
||||||
/* control out */
|
/* control out */
|
||||||
|
output logic valid_out,
|
||||||
output logic branch_taken_out,
|
output logic branch_taken_out,
|
||||||
output logic [4:0] rd_out,
|
output logic [4:0] rd_out,
|
||||||
output logic rd_write_out,
|
output logic rd_write_out,
|
||||||
|
|
@ -49,6 +55,7 @@ module rv32_mem (
|
||||||
output logic [31:0] data_address_out,
|
output logic [31:0] data_address_out,
|
||||||
output logic [31:0] data_write_value_out
|
output logic [31:0] data_write_value_out
|
||||||
);
|
);
|
||||||
|
/* branch unit */
|
||||||
rv32_branch_unit branch_unit (
|
rv32_branch_unit branch_unit (
|
||||||
/* control in */
|
/* control in */
|
||||||
.op_in(branch_op_in),
|
.op_in(branch_op_in),
|
||||||
|
|
@ -62,11 +69,40 @@ module rv32_mem (
|
||||||
|
|
||||||
assign branch_pc_out = branch_pc_in;
|
assign branch_pc_out = branch_pc_in;
|
||||||
|
|
||||||
|
/* csr file */
|
||||||
|
logic [31:0] csr_read_value;
|
||||||
|
|
||||||
|
rv32_csrs csrs (
|
||||||
|
.clk(clk),
|
||||||
|
|
||||||
|
/* control in (from hazard) */
|
||||||
|
.stall_in(stall_in),
|
||||||
|
|
||||||
|
/* control in */
|
||||||
|
.read_in(csr_read_in),
|
||||||
|
.write_in(csr_write_in),
|
||||||
|
.write_op_in(csr_write_op_in),
|
||||||
|
|
||||||
|
/* control in (from writeback) */
|
||||||
|
.instr_retired_in(valid_out),
|
||||||
|
|
||||||
|
/* data in */
|
||||||
|
.result_in(result_in),
|
||||||
|
.csr_in(csr_in),
|
||||||
|
|
||||||
|
/* data out */
|
||||||
|
.read_value_out(csr_read_value)
|
||||||
|
);
|
||||||
|
|
||||||
|
logic [31:0] mem_read_value;
|
||||||
|
|
||||||
|
/* memory access unit */
|
||||||
assign data_read_out = read_in;
|
assign data_read_out = read_in;
|
||||||
assign data_write_out = write_in;
|
assign data_write_out = write_in;
|
||||||
assign data_address_out = result_in;
|
assign data_address_out = result_in;
|
||||||
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
|
/* write port */
|
||||||
if (write_in) begin
|
if (write_in) begin
|
||||||
case (width_in)
|
case (width_in)
|
||||||
`RV32_MEM_WIDTH_WORD: begin
|
`RV32_MEM_WIDTH_WORD: begin
|
||||||
|
|
@ -114,42 +150,53 @@ module rv32_mem (
|
||||||
data_write_value_out = 32'bx;
|
data_write_value_out = 32'bx;
|
||||||
data_write_mask_out = 4'b0;
|
data_write_mask_out = 4'b0;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
/* read port */
|
||||||
|
if (read_in) begin
|
||||||
|
case (width_in)
|
||||||
|
`RV32_MEM_WIDTH_WORD: begin
|
||||||
|
mem_read_value = data_read_value_in;
|
||||||
|
end
|
||||||
|
`RV32_MEM_WIDTH_HALF: begin
|
||||||
|
case (result_in[0])
|
||||||
|
1'b0: mem_read_value = {{16{zero_extend_in ? 1'b0 : data_read_value_in[15]}}, data_read_value_in[15:0]};
|
||||||
|
1'b1: mem_read_value = {{16{zero_extend_in ? 1'b0 : data_read_value_in[31]}}, data_read_value_in[31:16]};
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
`RV32_MEM_WIDTH_BYTE: begin
|
||||||
|
case (result_in[1:0])
|
||||||
|
2'b00: mem_read_value = {{24{zero_extend_in ? 1'b0 : data_read_value_in[7]}}, data_read_value_in[7:0]};
|
||||||
|
2'b01: mem_read_value = {{24{zero_extend_in ? 1'b0 : data_read_value_in[15]}}, data_read_value_in[15:8]};
|
||||||
|
2'b10: mem_read_value = {{24{zero_extend_in ? 1'b0 : data_read_value_in[23]}}, data_read_value_in[23:16]};
|
||||||
|
2'b11: mem_read_value = {{24{zero_extend_in ? 1'b0 : data_read_value_in[31]}}, data_read_value_in[31:24]};
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
default: begin
|
||||||
|
mem_read_value = 32'bx;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end else begin
|
||||||
|
mem_read_value = 32'bx;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
always_ff @(posedge clk) begin
|
always_ff @(posedge clk) begin
|
||||||
if (!stall_in) begin
|
if (!stall_in) begin
|
||||||
|
valid_out <= valid_in;
|
||||||
rd_out <= rd_in;
|
rd_out <= rd_in;
|
||||||
rd_write_out <= rd_write_in;
|
rd_write_out <= rd_write_in;
|
||||||
|
|
||||||
if (read_in) begin
|
if (csr_read_in)
|
||||||
case (width_in)
|
rd_value_out <= csr_read_value;
|
||||||
`RV32_MEM_WIDTH_WORD: begin
|
else if (read_in)
|
||||||
rd_value_out <= data_read_value_in;
|
rd_value_out <= mem_read_value;
|
||||||
end
|
else
|
||||||
`RV32_MEM_WIDTH_HALF: begin
|
|
||||||
case (result_in[0])
|
|
||||||
1'b0: rd_value_out <= {{16{zero_extend_in ? 1'b0 : data_read_value_in[15]}}, data_read_value_in[15:0]};
|
|
||||||
1'b1: rd_value_out <= {{16{zero_extend_in ? 1'b0 : data_read_value_in[31]}}, data_read_value_in[31:16]};
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
`RV32_MEM_WIDTH_BYTE: begin
|
|
||||||
case (result_in[1:0])
|
|
||||||
2'b00: rd_value_out <= {{24{zero_extend_in ? 1'b0 : data_read_value_in[7]}}, data_read_value_in[7:0]};
|
|
||||||
2'b01: rd_value_out <= {{24{zero_extend_in ? 1'b0 : data_read_value_in[15]}}, data_read_value_in[15:8]};
|
|
||||||
2'b10: rd_value_out <= {{24{zero_extend_in ? 1'b0 : data_read_value_in[23]}}, data_read_value_in[23:16]};
|
|
||||||
2'b11: rd_value_out <= {{24{zero_extend_in ? 1'b0 : data_read_value_in[31]}}, data_read_value_in[31:24]};
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
default: begin
|
|
||||||
rd_value_out <= 32'bx;
|
|
||||||
end
|
|
||||||
endcase
|
|
||||||
end else begin
|
|
||||||
rd_value_out <= result_in;
|
rd_value_out <= result_in;
|
||||||
end
|
|
||||||
|
|
||||||
if (flush_in)
|
if (flush_in) begin
|
||||||
|
valid_out <= 0;
|
||||||
rd_write_out <= 0;
|
rd_write_out <= 0;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue