diff options
Diffstat (limited to 'src/control_unit.v')
-rw-r--r-- | src/control_unit.v | 122 |
1 files changed, 70 insertions, 52 deletions
diff --git a/src/control_unit.v b/src/control_unit.v index 9a5b413..dfed9cc 100644 --- a/src/control_unit.v +++ b/src/control_unit.v @@ -16,7 +16,7 @@ module control_unit ( output reg rf_we, output [4:0] ra1, ra2, wa3, - output reg [1:0] alu_a_src, + output reg [2:0] alu_a_src, output reg [1:0] alu_b_src, output [3:0] alu_op, @@ -29,6 +29,10 @@ wire [6:0] opcode; wire [2:0] funct3; wire [6:0] funct7; +reg branch; +reg pc_update; +reg alu_ctrl; + assign opcode = instr[6:0]; assign funct3 = instr[14:12]; assign funct7 = instr[31:25]; @@ -37,26 +41,35 @@ assign ra1 = instr[19:15]; assign ra2 = instr[24:20]; assign wa3 = instr[11:7]; +assign pc_we = ((alu_zero ^ funct3[0] ^ funct3[2]) & branch) | pc_update; + +reg [3:0] state, next_state; + +alu_op_decode alu_op_decode ( + .opcode(opcode), + .alu_ctrl(alu_ctrl), + .funct3(funct3), + .funct7(funct7), + .alu_op(alu_op) +); always @ (*) begin case (opcode) - OPCODE_REG: imm_src <= INSTR_FORMAT_R; // ADD, SUB, SLL, SLT, SLTU, XOR, SRL, SRA, OR, AND - OPCODE_IMM: imm_src <= INSTR_FORMAT_I; // ADDI, SLTI, SLTIU, XORI, ORI, ANDI, SLLI, SRLI, SRAI - OPCODE_LOAD: imm_src <= INSTR_FORMAT_I; // LB, LH, LW, LBU, LHU - OPCODE_JALR: imm_src <= INSTR_FORMAT_I; // JALR - OPCODE_STORE: imm_src <= INSTR_FORMAT_S; // SB, SH, SW - OPCODE_BRANCH: imm_src <= INSTR_FORMAT_B; // BEQ, BNE, BLT, BGE, BLTU, BGEU - OPCODE_LUI: imm_src <= INSTR_FORMAT_U; // LUI - OPCODE_AUIPC: imm_src <= INSTR_FORMAT_U; // AUIPC - OPCODE_JAL: imm_src <= INSTR_FORMAT_J; // JAL - OPCODE_SYNC: imm_src <= INSTR_FORMAT_I; // FENCE - OPCODE_SYS: imm_src <= INSTR_FORMAT_I; // ECALL, EBREAK - default: imm_src <= INSTR_FORMAT_UNKNOWN; + OPCODE_REG: imm_src = INSTR_FORMAT_R; // ADD, SUB, SLL, SLT, SLTU, XOR, SRL, SRA, OR, AND + OPCODE_IMM: imm_src = INSTR_FORMAT_I; // ADDI, SLTI, SLTIU, XORI, ORI, ANDI, SLLI, SRLI, SRAI + OPCODE_LOAD: imm_src = INSTR_FORMAT_I; // LB, LH, LW, LBU, LHU + OPCODE_JALR: imm_src = INSTR_FORMAT_I; // JALR + OPCODE_STORE: imm_src = INSTR_FORMAT_S; // SB, SH, SW + OPCODE_BRANCH: imm_src = INSTR_FORMAT_B; // BEQ, BNE, BLT, BGE, BLTU, BGEU + OPCODE_LUI: imm_src = INSTR_FORMAT_U; // LUI + OPCODE_AUIPC: imm_src = INSTR_FORMAT_U; // AUIPC + OPCODE_JAL: imm_src = INSTR_FORMAT_J; // JAL + OPCODE_SYNC: imm_src = INSTR_FORMAT_I; // FENCE + OPCODE_SYS: imm_src = INSTR_FORMAT_I; // ECALL, EBREAK + default: imm_src = INSTR_FORMAT_UNKNOWN; endcase end -reg [3:0] state, next_state; - always @ (posedge clk or negedge rstn) begin if (!rstn) state <= STATE_FETCH; else state <= next_state; @@ -64,40 +77,40 @@ end always @ (*) begin case(state) - STATE_FETCH: next_state <= STATE_DECODE; + STATE_FETCH: next_state = STATE_DECODE; STATE_DECODE: case(opcode) - OPCODE_LOAD: next_state <= STATE_MEM_ADDR; - OPCODE_STORE: next_state <= STATE_MEM_ADDR; - OPCODE_REG: next_state <= STATE_EXECUTE_R; - OPCODE_IMM: next_state <= STATE_EXECUTE_I; - OPCODE_JAL: next_state <= STATE_JAL; - OPCODE_JALR: next_state <= STATE_JALR; - OPCODE_BRANCH: next_state <= STATE_BRANCH; - default: next_state <= STATE_FETCH; + OPCODE_LOAD: next_state = STATE_MEM_ADDR; + OPCODE_STORE: next_state = STATE_MEM_ADDR; + OPCODE_REG: next_state = STATE_EXECUTE_R; + OPCODE_IMM: next_state = STATE_EXECUTE_I; + OPCODE_JAL: next_state = STATE_JAL; + OPCODE_JALR: next_state = STATE_JALR; + OPCODE_LUI: next_state = STATE_LUI; + OPCODE_AUIPC: next_state = STATE_AUIPC; + OPCODE_BRANCH: next_state = STATE_BRANCH; + default: next_state = STATE_FETCH; endcase STATE_MEM_ADDR: case(opcode) - OPCODE_LOAD: next_state <= STATE_MEM_LOAD; - OPCODE_STORE: next_state <= STATE_MEM_STORE; - default: next_state <= STATE_FETCH; + OPCODE_LOAD: next_state = STATE_MEM_LOAD; + OPCODE_STORE: next_state = STATE_MEM_STORE; + default: next_state = STATE_FETCH; endcase - STATE_MEM_LOAD: next_state <= STATE_MEM_WB; - STATE_MEM_WB: next_state <= STATE_FETCH; - STATE_MEM_STORE: next_state <= STATE_FETCH; - STATE_EXECUTE_R: next_state <= STATE_ALU_WB; - STATE_ALU_WB: next_state <= STATE_FETCH; - STATE_EXECUTE_I: next_state <= STATE_ALU_WB; - STATE_JAL: next_state <= STATE_ALU_WB; - STATE_JALR: next_state <= STATE_ALU_WB; - STATE_BRANCH: next_state <= STATE_FETCH; - default: next_state <= STATE_FETCH; + STATE_MEM_LOAD: next_state = STATE_MEM_WB; + STATE_MEM_WB: next_state = STATE_FETCH; + STATE_MEM_STORE: next_state = STATE_FETCH; + STATE_EXECUTE_R: next_state = STATE_ALU_WB; + STATE_ALU_WB: next_state = STATE_FETCH; + STATE_EXECUTE_I: next_state = STATE_ALU_WB; + STATE_JAL: next_state = STATE_ALU_WB; + STATE_JALR: next_state = STATE_ALU_WB; + STATE_LUI: next_state = STATE_ALU_WB; + STATE_AUIPC: next_state = STATE_FETCH; + STATE_BRANCH: next_state = STATE_FETCH; + default: next_state = STATE_FETCH; endcase end -reg branch; -reg pc_update; -reg alu_ctrl; -assign pc_we = ((alu_zero ^ funct3[0] ^ funct3[2]) & branch) | pc_update; always @ (*) begin mem_addr_src = MEM_ADDR_SRC_RESULT; @@ -121,7 +134,7 @@ always @ (*) begin pc_update = PC_UPDATE_ENABLE; end STATE_DECODE: begin - alu_a_src = ALU_A_SRC_PC_BUF; + alu_a_src = (opcode == OPCODE_JALR) ? ALU_A_SRC_RD1 : ALU_A_SRC_PC_BUF; alu_b_src = ALU_B_SRC_IMM; alu_ctrl = ALU_CTRL_ADD; end @@ -165,11 +178,24 @@ always @ (*) begin pc_update = PC_UPDATE_ENABLE; end STATE_JALR: begin - alu_a_src = ALU_A_SRC_RD1_BUF; + alu_a_src = ALU_A_SRC_PC_BUF; + alu_b_src = ALU_B_SRC_4; + alu_ctrl = ALU_CTRL_ADD; + result_src = RESULT_SRC_ALU_RESULT_BUF; + pc_update = PC_UPDATE_ENABLE; + end + STATE_LUI: begin + alu_a_src = ALU_A_SRC_0; alu_b_src = ALU_B_SRC_IMM; alu_ctrl = ALU_CTRL_ADD; - result_src = RESULT_SRC_ALU_RESULT; + end + STATE_AUIPC: begin + alu_a_src = ALU_A_SRC_PC_BUF; + alu_b_src = ALU_B_SRC_IMM; + alu_ctrl = ALU_CTRL_ADD; + result_src = RESULT_SRC_ALU_RESULT_BUF; pc_update = PC_UPDATE_ENABLE; + end STATE_BRANCH: begin alu_a_src = ALU_A_SRC_RD1_BUF; @@ -181,12 +207,4 @@ always @ (*) begin endcase end -alu_op_decode alu_op_decode ( - .opcode(opcode), - .alu_ctrl(alu_ctrl), - .funct3(funct3), - .funct7(funct7), - .alu_op(alu_op) -); - endmodule |