From eff39ad19bf75b96933a3f038723c97eda58b0d4 Mon Sep 17 00:00:00 2001 From: Graham Edgecombe Date: Sun, 3 Dec 2017 20:56:47 +0000 Subject: [PATCH] Add flush and stall inputs to every stage --- rv32_decode.sv | 810 ++++++++++++++++++++++++------------------------ rv32_execute.sv | 31 +- rv32_fetch.sv | 15 +- rv32_mem.sv | 61 ++-- rv32_opcodes.sv | 2 + rv32_regs.sv | 7 +- 6 files changed, 485 insertions(+), 441 deletions(-) diff --git a/rv32_decode.sv b/rv32_decode.sv index 54029fe..c0fab65 100644 --- a/rv32_decode.sv +++ b/rv32_decode.sv @@ -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 diff --git a/rv32_execute.sv b/rv32_execute.sv index dc27889..ea67421 100644 --- a/rv32_execute.sv +++ b/rv32_execute.sv @@ -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 diff --git a/rv32_fetch.sv b/rv32_fetch.sv index 3813087..6c16d01 100644 --- a/rv32_fetch.sv +++ b/rv32_fetch.sv @@ -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 diff --git a/rv32_mem.sv b/rv32_mem.sv index 8b21b30..d09c766 100644 --- a/rv32_mem.sv +++ b/rv32_mem.sv @@ -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 diff --git a/rv32_opcodes.sv b/rv32_opcodes.sv index cafee94..e2298f7 100644 --- a/rv32_opcodes.sv +++ b/rv32_opcodes.sv @@ -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 diff --git a/rv32_regs.sv b/rv32_regs.sv index f2d3b12..3f0c0b4 100644 --- a/rv32_regs.sv +++ b/rv32_regs.sv @@ -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;