Add flush and stall inputs to every stage

This commit is contained in:
Graham Edgecombe 2017-12-03 20:56:47 +00:00
parent 29e4c40af4
commit eff39ad19b
6 changed files with 485 additions and 441 deletions

View file

@ -9,6 +9,8 @@
module rv32_decode (
input clk,
input stall,
input flush,
/* control in (from writeback) */
input [4:0] rd_in,
@ -63,6 +65,7 @@ module rv32_decode (
rv32_regs regs (
.clk(clk),
.stall(stall),
/* control in */
.rs1_in(rs1),
@ -79,408 +82,417 @@ module rv32_decode (
);
always_ff @(posedge clk) begin
rs1_out <= rs1;
rs2_out <= rs2;
rd_out <= rd;
pc_out <= pc_in;
if (!stall) begin
rs1_out <= rs1;
rs2_out <= rs2;
rd_out <= rd;
pc_out <= pc_in;
valid_out <= 0;
alu_op_out <= 4'bx;
alu_sub_sra_out <= 1'bx;
alu_src1_out <= 1'bx;
alu_src2_out <= 1'bx;
rd_writeback_out <= 0;
mem_read_en_out <= 0;
mem_write_en_out <= 0;
mem_width_out <= 2'bx;
mem_zero_extend_out <= 1'bx;
branch_op_out <= RV32_BRANCH_OP_NEVER;
branch_pc_src_out <= 1'bx;
imm_out <= 32'bx;
valid_out <= 0;
alu_op_out <= 4'bx;
alu_sub_sra_out <= 1'bx;
alu_src1_out <= 1'bx;
alu_src2_out <= 1'bx;
rd_writeback_out <= 0;
mem_read_en_out <= 0;
mem_write_en_out <= 0;
mem_width_out <= 2'bx;
mem_zero_extend_out <= 1'bx;
branch_op_out <= RV32_BRANCH_OP_NEVER;
branch_pc_src_out <= 1'bx;
imm_out <= 32'bx;
casez ({opcode, funct3, funct7})
{RV32_OPCODE_LUI, RV32_FUNCT3_ANY, RV32_FUNCT7_ANY}: begin
/* LUI */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_SRC2;
alu_src2_out <= RV32_ALU_SRC2_IMM;
rd_writeback_out <= 1;
imm_out <= imm_u;
casez ({opcode, funct3, funct7})
{RV32_OPCODE_LUI, RV32_FUNCT3_ANY, RV32_FUNCT7_ANY}: begin
/* LUI */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_SRC2;
alu_src2_out <= RV32_ALU_SRC2_IMM;
rd_writeback_out <= 1;
imm_out <= imm_u;
end
{RV32_OPCODE_AUIPC, RV32_FUNCT3_ANY, RV32_FUNCT7_ANY}: begin
/* AUIPC */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_ADD_SUB;
alu_sub_sra_out <= 0;
alu_src1_out <= RV32_ALU_SRC1_PC;
alu_src2_out <= RV32_ALU_SRC2_IMM;
rd_writeback_out <= 1;
imm_out <= imm_u;
end
{RV32_OPCODE_JAL, RV32_FUNCT3_ANY, RV32_FUNCT7_ANY}: begin
/* JAL */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_SRC1P4;
alu_src1_out <= RV32_ALU_SRC1_PC;
branch_op_out <= RV32_BRANCH_OP_ALWAYS;
branch_pc_src_out <= RV32_BRANCH_PC_SRC_IMM;
rd_writeback_out <= 1;
imm_out <= imm_j;
end
{RV32_OPCODE_JALR, RV32_FUNCT3_ZERO, RV32_FUNCT7_ANY}: begin
/* JALR */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_SRC1P4;
alu_src1_out <= RV32_ALU_SRC1_PC;
branch_op_out <= RV32_BRANCH_OP_ALWAYS;
branch_pc_src_out <= RV32_BRANCH_PC_SRC_REG;
rd_writeback_out <= 1;
imm_out <= imm_i;
end
{RV32_OPCODE_BRANCH, RV32_FUNCT3_BRANCH_BEQ, RV32_FUNCT7_ANY}: begin
/* BEQ */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_ADD_SUB;
alu_sub_sra_out <= 1;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_REG;
branch_op_out <= RV32_BRANCH_OP_ZERO;
branch_pc_src_out <= RV32_BRANCH_PC_SRC_IMM;
imm_out <= imm_b;
end
{RV32_OPCODE_BRANCH, RV32_FUNCT3_BRANCH_BNE, RV32_FUNCT7_ANY}: begin
/* BNE */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_ADD_SUB;
alu_sub_sra_out <= 1;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_REG;
branch_op_out <= RV32_BRANCH_OP_NON_ZERO;
branch_pc_src_out <= RV32_BRANCH_PC_SRC_IMM;
imm_out <= imm_b;
end
{RV32_OPCODE_BRANCH, RV32_FUNCT3_BRANCH_BLT, RV32_FUNCT7_ANY}: begin
/* BLT */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_SLT;
alu_sub_sra_out <= 1;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_REG;
branch_op_out <= RV32_BRANCH_OP_NON_ZERO;
branch_pc_src_out <= RV32_BRANCH_PC_SRC_IMM;
imm_out <= imm_b;
end
{RV32_OPCODE_BRANCH, RV32_FUNCT3_BRANCH_BGE, RV32_FUNCT7_ANY}: begin
/* BGE */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_SLT;
alu_sub_sra_out <= 1;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_REG;
branch_op_out <= RV32_BRANCH_OP_ZERO;
branch_pc_src_out <= RV32_BRANCH_PC_SRC_IMM;
imm_out <= imm_b;
end
{RV32_OPCODE_BRANCH, RV32_FUNCT3_BRANCH_BLTU, RV32_FUNCT7_ANY}: begin
/* BLTU */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_SLTU;
alu_sub_sra_out <= 1;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_REG;
branch_op_out <= RV32_BRANCH_OP_NON_ZERO;
branch_pc_src_out <= RV32_BRANCH_PC_SRC_IMM;
imm_out <= imm_b;
end
{RV32_OPCODE_BRANCH, RV32_FUNCT3_BRANCH_BGEU, RV32_FUNCT7_ANY}: begin
/* BGEU */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_SLTU;
alu_sub_sra_out <= 1;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_REG;
branch_op_out <= RV32_BRANCH_OP_ZERO;
branch_pc_src_out <= RV32_BRANCH_PC_SRC_IMM;
imm_out <= imm_b;
end
{RV32_OPCODE_LOAD, RV32_FUNCT3_LOAD_LB, RV32_FUNCT7_ANY}: begin
/* LB */
valid_out <= 1;
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_IMM;
mem_read_en_out <= 1;
mem_width_out <= RV32_MEM_WIDTH_BYTE;
mem_zero_extend_out <= 0;
rd_writeback_out <= 1;
imm_out <= imm_i;
end
{RV32_OPCODE_LOAD, RV32_FUNCT3_LOAD_LH, RV32_FUNCT7_ANY}: begin
/* LH */
valid_out <= 1;
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_IMM;
mem_read_en_out <= 1;
mem_width_out <= RV32_MEM_WIDTH_HALF;
mem_zero_extend_out <= 0;
rd_writeback_out <= 1;
imm_out <= imm_i;
end
{RV32_OPCODE_LOAD, RV32_FUNCT3_LOAD_LW, RV32_FUNCT7_ANY}: begin
/* LW */
valid_out <= 1;
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_IMM;
mem_read_en_out <= 1;
mem_width_out <= RV32_MEM_WIDTH_WORD;
rd_writeback_out <= 1;
imm_out <= imm_i;
end
{RV32_OPCODE_LOAD, RV32_FUNCT3_LOAD_LBU, RV32_FUNCT7_ANY}: begin
/* LBU */
valid_out <= 1;
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_IMM;
mem_read_en_out <= 1;
mem_width_out <= RV32_MEM_WIDTH_BYTE;
mem_zero_extend_out <= 1;
rd_writeback_out <= 1;
imm_out <= imm_i;
end
{RV32_OPCODE_LOAD, RV32_FUNCT3_LOAD_LHU, RV32_FUNCT7_ANY}: begin
/* LHU */
valid_out <= 1;
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_IMM;
mem_read_en_out <= 1;
mem_width_out <= RV32_MEM_WIDTH_HALF;
mem_zero_extend_out <= 1;
rd_writeback_out <= 1;
imm_out <= imm_i;
end
{RV32_OPCODE_STORE, RV32_FUNCT3_STORE_SB, RV32_FUNCT7_ANY}: begin
/* SB */
valid_out <= 1;
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_IMM;
mem_write_en_out <= 1;
mem_width_out <= RV32_MEM_WIDTH_BYTE;
imm_out <= imm_s;
end
{RV32_OPCODE_STORE, RV32_FUNCT3_STORE_SH, RV32_FUNCT7_ANY}: begin
/* SH */
valid_out <= 1;
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_IMM;
mem_write_en_out <= 1;
mem_width_out <= RV32_MEM_WIDTH_HALF;
imm_out <= imm_s;
end
{RV32_OPCODE_STORE, RV32_FUNCT3_STORE_SW, RV32_FUNCT7_ANY}: begin
/* SW */
valid_out <= 1;
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_IMM;
mem_write_en_out <= 1;
mem_width_out <= RV32_MEM_WIDTH_WORD;
imm_out <= imm_s;
end
{RV32_OPCODE_OP_IMM, RV32_FUNCT3_OP_ADD_SUB, RV32_FUNCT7_ANY}: begin
/* ADDI */
valid_out <= 1;
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_IMM;
rd_writeback_out <= 1;
imm_out <= imm_i;
end
{RV32_OPCODE_OP_IMM, RV32_FUNCT3_OP_SLT, RV32_FUNCT7_ANY}: begin
/* SLTI */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_SLT;
alu_sub_sra_out <= 1;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_IMM;
rd_writeback_out <= 1;
imm_out <= imm_i;
end
{RV32_OPCODE_OP_IMM, RV32_FUNCT3_OP_SLTU, RV32_FUNCT7_ANY}: begin
/* SLTIU */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_SLTU;
alu_sub_sra_out <= 1;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_IMM;
rd_writeback_out <= 1;
imm_out <= imm_i;
end
{RV32_OPCODE_OP_IMM, RV32_FUNCT3_OP_XOR, RV32_FUNCT7_ANY}: begin
/* XORI */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_XOR;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_IMM;
rd_writeback_out <= 1;
imm_out <= imm_i;
end
{RV32_OPCODE_OP_IMM, RV32_FUNCT3_OP_OR, RV32_FUNCT7_ANY}: begin
/* ORI */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_OR;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_IMM;
rd_writeback_out <= 1;
imm_out <= imm_i;
end
{RV32_OPCODE_OP_IMM, RV32_FUNCT3_OP_AND, RV32_FUNCT7_ANY}: begin
/* ANDI */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_AND;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_IMM;
rd_writeback_out <= 1;
imm_out <= imm_i;
end
{RV32_OPCODE_OP_IMM, RV32_FUNCT3_OP_SLL, RV32_FUNCT7_ZERO}: begin
/* SLLI */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_SLL;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_IMM;
rd_writeback_out <= 1;
imm_out <= shamt;
end
{RV32_OPCODE_OP_IMM, RV32_FUNCT3_OP_SRL_SRA, RV32_FUNCT7_ZERO}: begin
/* SRLI */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_SRL_SRA;
alu_sub_sra_out <= 0;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_IMM;
rd_writeback_out <= 1;
imm_out <= shamt;
end
{RV32_OPCODE_OP_IMM, RV32_FUNCT3_OP_SRL_SRA, RV32_FUNCT7_OP_SRA}: begin
/* SRAI */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_SRL_SRA;
alu_sub_sra_out <= 1;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_IMM;
rd_writeback_out <= 1;
imm_out <= shamt;
end
{RV32_OPCODE_OP, RV32_FUNCT3_OP_ADD_SUB, RV32_FUNCT7_ZERO}: begin
/* ADD */
valid_out <= 1;
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_REG;
rd_writeback_out <= 1;
end
{RV32_OPCODE_OP, RV32_FUNCT3_OP_ADD_SUB, RV32_FUNCT7_OP_SUB}: begin
/* SUB */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_ADD_SUB;
alu_sub_sra_out <= 1;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_REG;
rd_writeback_out <= 1;
end
{RV32_OPCODE_OP, RV32_FUNCT3_OP_SLL, RV32_FUNCT7_ZERO}: begin
/* SLL */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_SLL;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_REG;
rd_writeback_out <= 1;
end
{RV32_OPCODE_OP, RV32_FUNCT3_OP_SLT, RV32_FUNCT7_ZERO}: begin
/* SLT */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_SLT;
alu_sub_sra_out <= 1;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_REG;
rd_writeback_out <= 1;
end
{RV32_OPCODE_OP, RV32_FUNCT3_OP_SLTU, RV32_FUNCT7_ZERO}: begin
/* SLTU */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_SLTU;
alu_sub_sra_out <= 1;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_REG;
rd_writeback_out <= 1;
end
{RV32_OPCODE_OP, RV32_FUNCT3_OP_XOR, RV32_FUNCT7_ZERO}: begin
/* XOR */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_XOR;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_REG;
rd_writeback_out <= 1;
end
{RV32_OPCODE_OP, RV32_FUNCT3_OP_SRL_SRA, RV32_FUNCT7_ZERO}: begin
/* SRL */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_SRL_SRA;
alu_sub_sra_out <= 0;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_REG;
rd_writeback_out <= 1;
end
{RV32_OPCODE_OP, RV32_FUNCT3_OP_SRL_SRA, RV32_FUNCT7_OP_SRA}: begin
/* SRA */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_SRL_SRA;
alu_sub_sra_out <= 1;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_REG;
rd_writeback_out <= 1;
end
{RV32_OPCODE_OP, RV32_FUNCT3_OP_OR, RV32_FUNCT7_ZERO}: begin
/* OR */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_OR;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_REG;
rd_writeback_out <= 1;
end
{RV32_OPCODE_OP, RV32_FUNCT3_OP_AND, RV32_FUNCT7_ZERO}: begin
/* AND */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_AND;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_REG;
rd_writeback_out <= 1;
end
{RV32_OPCODE_MISC_MEM, RV32_FUNCT3_MISC_MEM_FENCE, RV32_FUNCT7_ANY}: begin
/* FENCE */
valid_out <= 1;
end
{RV32_OPCODE_MISC_MEM, RV32_FUNCT3_MISC_MEM_FENCE_I, RV32_FUNCT7_ANY}: begin
/* FENCE.I */
valid_out <= 1;
end
endcase
if (flush) begin
mem_read_en_out <= 0;
mem_write_en_out <= 0;
branch_op_out <= RV32_BRANCH_OP_NEVER;
rd_writeback_out <= 0;
end
{RV32_OPCODE_AUIPC, RV32_FUNCT3_ANY, RV32_FUNCT7_ANY}: begin
/* AUIPC */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_ADD_SUB;
alu_sub_sra_out <= 0;
alu_src1_out <= RV32_ALU_SRC1_PC;
alu_src2_out <= RV32_ALU_SRC2_IMM;
rd_writeback_out <= 1;
imm_out <= imm_u;
end
{RV32_OPCODE_JAL, RV32_FUNCT3_ANY, RV32_FUNCT7_ANY}: begin
/* JAL */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_SRC1P4;
alu_src1_out <= RV32_ALU_SRC1_PC;
branch_op_out <= RV32_BRANCH_OP_ALWAYS;
branch_pc_src_out <= RV32_BRANCH_PC_SRC_IMM;
rd_writeback_out <= 1;
imm_out <= imm_j;
end
{RV32_OPCODE_JALR, RV32_FUNCT3_ZERO, RV32_FUNCT7_ANY}: begin
/* JALR */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_SRC1P4;
alu_src1_out <= RV32_ALU_SRC1_PC;
branch_op_out <= RV32_BRANCH_OP_ALWAYS;
branch_pc_src_out <= RV32_BRANCH_PC_SRC_REG;
rd_writeback_out <= 1;
imm_out <= imm_i;
end
{RV32_OPCODE_BRANCH, RV32_FUNCT3_BRANCH_BEQ, RV32_FUNCT7_ANY}: begin
/* BEQ */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_ADD_SUB;
alu_sub_sra_out <= 1;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_REG;
branch_op_out <= RV32_BRANCH_OP_ZERO;
branch_pc_src_out <= RV32_BRANCH_PC_SRC_IMM;
imm_out <= imm_b;
end
{RV32_OPCODE_BRANCH, RV32_FUNCT3_BRANCH_BNE, RV32_FUNCT7_ANY}: begin
/* BNE */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_ADD_SUB;
alu_sub_sra_out <= 1;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_REG;
branch_op_out <= RV32_BRANCH_OP_NON_ZERO;
branch_pc_src_out <= RV32_BRANCH_PC_SRC_IMM;
imm_out <= imm_b;
end
{RV32_OPCODE_BRANCH, RV32_FUNCT3_BRANCH_BLT, RV32_FUNCT7_ANY}: begin
/* BLT */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_SLT;
alu_sub_sra_out <= 1;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_REG;
branch_op_out <= RV32_BRANCH_OP_NON_ZERO;
branch_pc_src_out <= RV32_BRANCH_PC_SRC_IMM;
imm_out <= imm_b;
end
{RV32_OPCODE_BRANCH, RV32_FUNCT3_BRANCH_BGE, RV32_FUNCT7_ANY}: begin
/* BGE */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_SLT;
alu_sub_sra_out <= 1;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_REG;
branch_op_out <= RV32_BRANCH_OP_ZERO;
branch_pc_src_out <= RV32_BRANCH_PC_SRC_IMM;
imm_out <= imm_b;
end
{RV32_OPCODE_BRANCH, RV32_FUNCT3_BRANCH_BLTU, RV32_FUNCT7_ANY}: begin
/* BLTU */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_SLTU;
alu_sub_sra_out <= 1;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_REG;
branch_op_out <= RV32_BRANCH_OP_NON_ZERO;
branch_pc_src_out <= RV32_BRANCH_PC_SRC_IMM;
imm_out <= imm_b;
end
{RV32_OPCODE_BRANCH, RV32_FUNCT3_BRANCH_BGEU, RV32_FUNCT7_ANY}: begin
/* BGEU */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_SLTU;
alu_sub_sra_out <= 1;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_REG;
branch_op_out <= RV32_BRANCH_OP_ZERO;
branch_pc_src_out <= RV32_BRANCH_PC_SRC_IMM;
imm_out <= imm_b;
end
{RV32_OPCODE_LOAD, RV32_FUNCT3_LOAD_LB, RV32_FUNCT7_ANY}: begin
/* LB */
valid_out <= 1;
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_IMM;
mem_read_en_out <= 1;
mem_width_out <= RV32_MEM_WIDTH_BYTE;
mem_zero_extend_out <= 0;
rd_writeback_out <= 1;
imm_out <= imm_i;
end
{RV32_OPCODE_LOAD, RV32_FUNCT3_LOAD_LH, RV32_FUNCT7_ANY}: begin
/* LH */
valid_out <= 1;
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_IMM;
mem_read_en_out <= 1;
mem_width_out <= RV32_MEM_WIDTH_HALF;
mem_zero_extend_out <= 0;
rd_writeback_out <= 1;
imm_out <= imm_i;
end
{RV32_OPCODE_LOAD, RV32_FUNCT3_LOAD_LW, RV32_FUNCT7_ANY}: begin
/* LW */
valid_out <= 1;
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_IMM;
mem_read_en_out <= 1;
mem_width_out <= RV32_MEM_WIDTH_WORD;
rd_writeback_out <= 1;
imm_out <= imm_i;
end
{RV32_OPCODE_LOAD, RV32_FUNCT3_LOAD_LBU, RV32_FUNCT7_ANY}: begin
/* LBU */
valid_out <= 1;
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_IMM;
mem_read_en_out <= 1;
mem_width_out <= RV32_MEM_WIDTH_BYTE;
mem_zero_extend_out <= 1;
rd_writeback_out <= 1;
imm_out <= imm_i;
end
{RV32_OPCODE_LOAD, RV32_FUNCT3_LOAD_LHU, RV32_FUNCT7_ANY}: begin
/* LHU */
valid_out <= 1;
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_IMM;
mem_read_en_out <= 1;
mem_width_out <= RV32_MEM_WIDTH_HALF;
mem_zero_extend_out <= 1;
rd_writeback_out <= 1;
imm_out <= imm_i;
end
{RV32_OPCODE_STORE, RV32_FUNCT3_STORE_SB, RV32_FUNCT7_ANY}: begin
/* SB */
valid_out <= 1;
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_IMM;
mem_write_en_out <= 1;
mem_width_out <= RV32_MEM_WIDTH_BYTE;
imm_out <= imm_s;
end
{RV32_OPCODE_STORE, RV32_FUNCT3_STORE_SH, RV32_FUNCT7_ANY}: begin
/* SH */
valid_out <= 1;
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_IMM;
mem_write_en_out <= 1;
mem_width_out <= RV32_MEM_WIDTH_HALF;
imm_out <= imm_s;
end
{RV32_OPCODE_STORE, RV32_FUNCT3_STORE_SW, RV32_FUNCT7_ANY}: begin
/* SW */
valid_out <= 1;
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_IMM;
mem_write_en_out <= 1;
mem_width_out <= RV32_MEM_WIDTH_WORD;
imm_out <= imm_s;
end
{RV32_OPCODE_OP_IMM, RV32_FUNCT3_OP_ADD_SUB, RV32_FUNCT7_ANY}: begin
/* ADDI */
valid_out <= 1;
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_IMM;
rd_writeback_out <= 1;
imm_out <= imm_i;
end
{RV32_OPCODE_OP_IMM, RV32_FUNCT3_OP_SLT, RV32_FUNCT7_ANY}: begin
/* SLTI */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_SLT;
alu_sub_sra_out <= 1;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_IMM;
rd_writeback_out <= 1;
imm_out <= imm_i;
end
{RV32_OPCODE_OP_IMM, RV32_FUNCT3_OP_SLTU, RV32_FUNCT7_ANY}: begin
/* SLTIU */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_SLTU;
alu_sub_sra_out <= 1;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_IMM;
rd_writeback_out <= 1;
imm_out <= imm_i;
end
{RV32_OPCODE_OP_IMM, RV32_FUNCT3_OP_XOR, RV32_FUNCT7_ANY}: begin
/* XORI */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_XOR;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_IMM;
rd_writeback_out <= 1;
imm_out <= imm_i;
end
{RV32_OPCODE_OP_IMM, RV32_FUNCT3_OP_OR, RV32_FUNCT7_ANY}: begin
/* ORI */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_OR;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_IMM;
rd_writeback_out <= 1;
imm_out <= imm_i;
end
{RV32_OPCODE_OP_IMM, RV32_FUNCT3_OP_AND, RV32_FUNCT7_ANY}: begin
/* ANDI */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_AND;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_IMM;
rd_writeback_out <= 1;
imm_out <= imm_i;
end
{RV32_OPCODE_OP_IMM, RV32_FUNCT3_OP_SLL, RV32_FUNCT7_ZERO}: begin
/* SLLI */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_SLL;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_IMM;
rd_writeback_out <= 1;
imm_out <= shamt;
end
{RV32_OPCODE_OP_IMM, RV32_FUNCT3_OP_SRL_SRA, RV32_FUNCT7_ZERO}: begin
/* SRLI */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_SRL_SRA;
alu_sub_sra_out <= 0;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_IMM;
rd_writeback_out <= 1;
imm_out <= shamt;
end
{RV32_OPCODE_OP_IMM, RV32_FUNCT3_OP_SRL_SRA, RV32_FUNCT7_OP_SRA}: begin
/* SRAI */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_SRL_SRA;
alu_sub_sra_out <= 1;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_IMM;
rd_writeback_out <= 1;
imm_out <= shamt;
end
{RV32_OPCODE_OP, RV32_FUNCT3_OP_ADD_SUB, RV32_FUNCT7_ZERO}: begin
/* ADD */
valid_out <= 1;
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_REG;
rd_writeback_out <= 1;
end
{RV32_OPCODE_OP, RV32_FUNCT3_OP_ADD_SUB, RV32_FUNCT7_OP_SUB}: begin
/* SUB */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_ADD_SUB;
alu_sub_sra_out <= 1;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_REG;
rd_writeback_out <= 1;
end
{RV32_OPCODE_OP, RV32_FUNCT3_OP_SLL, RV32_FUNCT7_ZERO}: begin
/* SLL */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_SLL;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_REG;
rd_writeback_out <= 1;
end
{RV32_OPCODE_OP, RV32_FUNCT3_OP_SLT, RV32_FUNCT7_ZERO}: begin
/* SLT */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_SLT;
alu_sub_sra_out <= 1;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_REG;
rd_writeback_out <= 1;
end
{RV32_OPCODE_OP, RV32_FUNCT3_OP_SLTU, RV32_FUNCT7_ZERO}: begin
/* SLTU */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_SLTU;
alu_sub_sra_out <= 1;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_REG;
rd_writeback_out <= 1;
end
{RV32_OPCODE_OP, RV32_FUNCT3_OP_XOR, RV32_FUNCT7_ZERO}: begin
/* XOR */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_XOR;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_REG;
rd_writeback_out <= 1;
end
{RV32_OPCODE_OP, RV32_FUNCT3_OP_SRL_SRA, RV32_FUNCT7_ZERO}: begin
/* SRL */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_SRL_SRA;
alu_sub_sra_out <= 0;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_REG;
rd_writeback_out <= 1;
end
{RV32_OPCODE_OP, RV32_FUNCT3_OP_SRL_SRA, RV32_FUNCT7_OP_SRA}: begin
/* SRA */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_SRL_SRA;
alu_sub_sra_out <= 1;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_REG;
rd_writeback_out <= 1;
end
{RV32_OPCODE_OP, RV32_FUNCT3_OP_OR, RV32_FUNCT7_ZERO}: begin
/* OR */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_OR;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_REG;
rd_writeback_out <= 1;
end
{RV32_OPCODE_OP, RV32_FUNCT3_OP_AND, RV32_FUNCT7_ZERO}: begin
/* AND */
valid_out <= 1;
alu_op_out <= RV32_ALU_OP_AND;
alu_src1_out <= RV32_ALU_SRC1_REG;
alu_src2_out <= RV32_ALU_SRC2_REG;
rd_writeback_out <= 1;
end
{RV32_OPCODE_MISC_MEM, RV32_FUNCT3_MISC_MEM_FENCE, RV32_FUNCT7_ANY}: begin
/* FENCE */
valid_out <= 1;
end
{RV32_OPCODE_MISC_MEM, RV32_FUNCT3_MISC_MEM_FENCE_I, RV32_FUNCT7_ANY}: begin
/* FENCE.I */
valid_out <= 1;
end
endcase
end
end
endmodule

View file

@ -6,6 +6,8 @@
module rv32_execute (
input clk,
input stall,
input flush,
/* control in */
input [4:0] rs1_in,
@ -104,16 +106,25 @@ module rv32_execute (
);
always_ff @(posedge clk) begin
mem_read_en_out <= mem_read_en_in;
mem_write_en_out <= mem_write_en_in;
mem_width_out <= mem_width_in;
mem_zero_extend_out <= mem_zero_extend_in;
branch_op_out <= branch_op_in;
rd_out <= rd_in;
rd_writeback_out <= rd_writeback_in;
result_out <= result;
rs2_value_out <= rs2_value_in;
branch_pc_out <= branch_pc;
if (!stall) begin
mem_read_en_out <= mem_read_en_in;
mem_write_en_out <= mem_write_en_in;
mem_width_out <= mem_width_in;
mem_zero_extend_out <= mem_zero_extend_in;
branch_op_out <= branch_op_in;
rd_out <= rd_in;
rd_writeback_out <= rd_writeback_in;
result_out <= result;
rs2_value_out <= rs2_value_in;
branch_pc_out <= branch_pc;
if (flush) begin
mem_read_en_out <= 0;
mem_write_en_out <= 0;
branch_op_out <= RV32_BRANCH_OP_NEVER;
rd_writeback_out <= 0;
end
end
end
endmodule

View file

@ -1,8 +1,12 @@
`ifndef RV32_FETCH
`define RV32_FETCH
`include "rv32_opcodes.sv"
module rv32_fetch (
input clk,
input stall,
input flush,
/* control in (from mem) */
input branch_taken_in,
@ -23,9 +27,14 @@ module rv32_fetch (
$readmemh("progmem_syn.hex", instr_mem);
always_ff @(posedge clk) begin
instr_out <= instr_mem[pc[31:2]];
next_pc <= pc + 4;
pc_out <= pc;
if (!stall) begin
instr_out <= instr_mem[pc[31:2]];
next_pc <= pc + 4;
pc_out <= pc;
if (flush)
instr_out <= RV32_INSTR_NOP;
end
end
endmodule

View file

@ -6,6 +6,8 @@
module rv32_mem (
input clk,
input stall,
input flush,
/* control in */
input read_en_in,
@ -110,34 +112,39 @@ module rv32_mem (
end
always_ff @(posedge clk) begin
rd_out <= rd_in;
rd_writeback_out <= rd_writeback_in;
if (!stall) begin
rd_out <= rd_in;
rd_writeback_out <= rd_writeback_in;
if (read_en_in) begin
case (width_in)
RV32_MEM_WIDTH_WORD: begin
rd_value_out <= read_value;
end
RV32_MEM_WIDTH_HALF: begin
case (result_in[0])
1'b0: rd_value_out <= {{16{zero_extend_in ? 1'b0 : read_value[31]}}, read_value[31:16]};
1'b1: rd_value_out <= {{16{zero_extend_in ? 1'b0 : read_value[15]}}, read_value[15:0]};
endcase
end
RV32_MEM_WIDTH_BYTE: begin
case (result_in[1:0])
2'b00: rd_value_out <= {{24{zero_extend_in ? 1'b0 : read_value[31]}}, read_value[31:24]};
2'b01: rd_value_out <= {{24{zero_extend_in ? 1'b0 : read_value[23]}}, read_value[23:16]};
2'b10: rd_value_out <= {{24{zero_extend_in ? 1'b0 : read_value[15]}}, read_value[15:8]};
2'b11: rd_value_out <= {{24{zero_extend_in ? 1'b0 : read_value[7]}}, read_value[7:0]};
endcase
end
default: begin
rd_value_out <= 32'bx;
end
endcase
end else begin
rd_value_out <= result_in;
if (read_en_in) begin
case (width_in)
RV32_MEM_WIDTH_WORD: begin
rd_value_out <= read_value;
end
RV32_MEM_WIDTH_HALF: begin
case (result_in[0])
1'b0: rd_value_out <= {{16{zero_extend_in ? 1'b0 : read_value[31]}}, read_value[31:16]};
1'b1: rd_value_out <= {{16{zero_extend_in ? 1'b0 : read_value[15]}}, read_value[15:0]};
endcase
end
RV32_MEM_WIDTH_BYTE: begin
case (result_in[1:0])
2'b00: rd_value_out <= {{24{zero_extend_in ? 1'b0 : read_value[31]}}, read_value[31:24]};
2'b01: rd_value_out <= {{24{zero_extend_in ? 1'b0 : read_value[23]}}, read_value[23:16]};
2'b10: rd_value_out <= {{24{zero_extend_in ? 1'b0 : read_value[15]}}, read_value[15:8]};
2'b11: rd_value_out <= {{24{zero_extend_in ? 1'b0 : read_value[7]}}, read_value[7:0]};
endcase
end
default: begin
rd_value_out <= 32'bx;
end
endcase
end else begin
rd_value_out <= result_in;
end
if (flush)
rd_writeback_out <= 0;
end
end
endmodule

View file

@ -51,4 +51,6 @@ localparam RV32_FUNCT7_ZERO = 7'b0000000;
localparam RV32_FUNCT7_OP_SRA = 7'b0100000;
localparam RV32_FUNCT7_OP_SUB = 7'b0100000;
localparam RV32_INSTR_NOP = {12'bx, 5'b0, 3'bx, 5'b0, RV32_OPCODE_OP_IMM};
`endif

View file

@ -3,6 +3,7 @@
module rv32_regs (
input clk,
input stall,
/* control in */
input [4:0] rs1_in,
@ -20,8 +21,10 @@ module rv32_regs (
logic [31:0] regs [31:0];
always_ff @(posedge clk) begin
rs1_value_out <= regs[rs1_in];
rs2_value_out <= regs[rs2_in];
if (!stall) begin
rs1_value_out <= regs[rs1_in];
rs2_value_out <= regs[rs2_in];
end
if (rd_writeback_in && |rd_in)
regs[rd_in] <= rd_value_in;