wire illegal_instr_w; //illegal Instruction assign illegal_instr_w = !( lui_w || lw_w ||sw_w || jal_w || jalr_w || beq_w || bgeu_w ||bltu_w || add_w || sub_w ||addi_w || and_w || or_w ||xor_w || andi_w || ori_w ||xori_w || srl_w || sll_w ); wire [31:0] imm_switch_w; //switch which kind of immediate is using in current Instruction assign imm_switch_w[31:0] = (lui_w) ? imm_u_w : (beq_w || bgeu_w ||bltu_w) ? imm_b_w : (lw_w || jalr_w || addi_w || xori_w || ori_w || andi_w) ? imm_i_w : (sw_w) ? imm_s_w : (jal_w) ? imm_j_w : 32'h0; wire [4:0] rd_switch_w, ra_switch_w, rb_switch_w; //switch whether need reg's addr value in current Instruction assign rd_switch_w[4:0] = ( lui_w || lw_w || jal_w || jalr_w || add_w || addi_w || sub_w || and_w || or_w || xor_w || andi_w || ori_w || xori_w || srl_w || sll_w) ? rd_w : 5'd0;//rd assign ra_switch_w[4:0] = ( lw_w || sw_w || jalr_w || beq_w || bgeu_w || bltu_w || add_w || addi_w || sub_w || and_w || or_w || xor_w || andi_w || ori_w || xori_w || srl_w || sll_w) ? ra_w : 5'd0;//rs1 assign rb_switch_w[4:0] = ( sw_w || beq_w || bgeu_w || bltu_w || add_w || sub_w || and_w || or_w || xor_w || srl_w || sll_w ) ? rb_w : 5'd0;//rs2 wire [3:0] alu_operate_w; assign alu_operate_w[3:0] = (add_w || addi_w || lui_w || lw_w || sw_w) ? ALU_ADD : (andi_w || and_w) ? ALU_AND : (ori_w || or_w) ? ALU_OR : (xori_w || xor_w) ? ALU_XOR : (sll_w) ? ALU_SHL : (srl_w) ? ALU_SHR : (jal_w || jalr_w) ? ALU_NPC : ALU_SUB; //----------------------------------------------------------------------------- //- Lock control //----------------------------------------------------------------------------- reg lock_r; always @(posedge clk_i) if(reset_i) lock_r = 1'b0; else if(phase_r == 4'd3 && illegal_instr_w) begin lock_r = 1'b1; $display("%t Illegal Instruction. CPU is locked.\n", $time); end
assign lock_o = lock_r; //----------------------------------------------------------------------------- //- Register Fetch //----------------------------------------------------------------------------- reg [31:0] reg_r [31:0];//register_file reg [31:0] operator_a_r; reg [31:0] operator_b_r;
always @(posedge clk_i) if(reset_i | lock_o) begin operator_a_r <= 32'h0; operator_b_r <= 32'h0; end else if(phase_r == 4'd3) begin operator_a_r <= reg_r[ra_switch_w];//x[rs1] operator_b_r <= reg_r[rb_switch_w];//x[rs2] end //----------------------------------------------------------------------------- //- load immediate //----------------------------------------------------------------------------- reg [31:0] imm_switch_r; always @(posedge clk_i) if(reset_i | lock_o) imm_switch_r <= 32'h0; else if(phase_r == 4'd3) imm_switch_r <= imm_switch_w; //----------------------------------------------------------------------------- //- ALU calculate //----------------------------------------------------------------------------- reg [31:0] alu_result_r;
always @(*) if(reset_i | lock_o) alu_result_r = 32'h0; else case(alu_operate_w[3:0]) ALU_ADD: if(add_w) alu_result_r = operator_a_r + operator_b_r; else if(addi_w) alu_result_r = operator_a_r + imm_switch_r; else if(lui_w) alu_result_r = imm_switch_r; else if(lw_w) alu_result_r = operator_a_r + imm_switch_r; else if(sw_w) alu_result_r = operator_a_r + imm_switch_r; ALU_AND: if(and_w) alu_result_r = operator_a_r & operator_b_r; else if(andi_w) alu_result_r = operator_a_r & imm_switch_r; ALU_OR : if(or_w) alu_result_r = operator_a_r | operator_b_r; else if(ori_w) alu_result_r = operator_a_r | imm_switch_r; ALU_XOR: if(xor_w) alu_result_r = operator_a_r ^ operator_b_r; else if(xori_w) alu_result_r = operator_a_r ^ imm_switch_r; ALU_SHL: alu_result_r = operator_a_r << operator_b_r; ALU_SHR: alu_result_r = operator_a_r >> operator_b_r; ALU_NPC: if(jal_w) alu_result_r = pc_r + imm_switch_r; else if(jalr_w) alu_result_r = operator_a_r + imm_switch_r; ALU_SUB: if(sub_w) alu_result_r = operator_a_r - operator_b_r;
default: if(beq_w || bgeu_w || bltu_w) alu_result_r = pc_r + imm_switch_r; else alu_result_r = 32'h0;
endcase
reg [31:0] alu_result_buff_r;//make alu_result output from DFF
always @(posedge clk_i) if(reset_i | lock_o) alu_result_buff_r <= 32'h0; else if(phase_r == 4'd4) alu_result_buff_r <= alu_result_r;
//----------------------------------------------------------------------------- //- Branch Taken //----------------------------------------------------------------------------- reg branch_taken_r; reg [PC_SIZE-1:0] pc_jump_r;
always @(posedge clk_i) if(reset_i | lock_o) begin branch_taken_r <= 1'b0; pc_jump_r <= 'h0; end else if(phase_r == 4'd4) begin branch_taken_r <= ( jal_w || jalr_w || (beq_w && (operator_a_r == operator_b_r)) || (bgeu_w && (operator_a_r >= operator_b_r)) || (bltu_w && (operator_a_r < operator_b_r)) ); pc_jump_r <= alu_result_r; end
//----------------------------------------------------------------------------- //- Memory Access //----------------------------------------------------------------------------- reg mem_rd_en_r; reg [31:0] mem_rd_addr_r;
reg mem_wr_en_r; reg [31:0] mem_wr_addr_r; reg [31:0] mem_wr_data_r;
always @(posedge clk_i) if(reset_i | lock_o) begin mem_rd_en_r <= 1'b0; mem_rd_addr_r <= 32'h0;
mem_wr_en_r <= 1'b0; mem_wr_addr_r <= 32'h0; mem_wr_data_r <= 32'h0; end else if(phase_r == 4'd5) begin if(lw_w) begin mem_rd_en_r <= 1'b1; mem_rd_addr_r <= alu_result_buff_r;//x[rs1] + imm end else if(sw_w) begin mem_wr_en_r <= 1'b1; mem_wr_addr_r <= alu_result_buff_r;//x[rs1] + imm mem_wr_data_r <= operator_b_r;//x[rs2] end end else begin mem_rd_en_r <= 1'b0; mem_wr_en_r <= 1'b0; end
assign daddr_o = lw_w ? mem_rd_addr_r : mem_wr_addr_r; //BUS (wr & rd)_addr assign dwdata_o = mem_wr_data_r; //BUS wr_data assign drd_o = mem_rd_en_r; //BUS rd_en assign dwr_o = mem_wr_en_r; //BUS wr_en
//----------------------------------------------------------------------------- //- PC control //----------------------------------------------------------------------------- //reg [PC_SIZE-1:0] pc_r;//"PC" reg
// PC start from 0 ; // if(ird_en_r) PC = PC + 4; // else if(jump_en) PC = PC_jump;
always @(posedge clk_i) if(reset_i | lock_o) pc_r <= 'h0; else if(phase_r == 4'd5) pc_r <= pc_r + 4; else if(branch_taken_r) pc_r <= pc_jump_r;
assign iaddr_o = pc_r; //----------------------------------------------------------------------------- //- Write Back //----------------------------------------------------------------------------- wire regfile_wr_en_w; wire [31:0] regfile_wr_data_w;
assign regfile_wr_en_w = (lui_w || lw_w || jal_w || jalr_w || add_w || addi_w || sub_w || and_w || or_w || xor_w || andi_w || ori_w || xori_w || srl_w || sll_w);
assign regfile_wr_data_w = lui_w ? imm_switch_r : lw_w ? alu_result_r : jal_w ? pc_r + 4 : jalr_w ? pc_r + 4 : (add_w || addi_w || sub_w || and_w || or_w || xor_w || andi_w || ori_w || xori_w || srl_w || sll_w) ? alu_result_r : 32'h0; integer k; always @(posedge clk_i) begin if(reset_i | lock_o) begin for(k=0;k<32;k++) reg_r[k] <= 32'h0; end else if(phase_r == 4'd7 && regfile_wr_en_w) reg_r[rd_switch_w] <= regfile_wr_data_w;//write data into register_file end endmodule
|