├── report ├── goal 05 │ ├── encode.xlsx │ └── goal 05.docx ├── goal 06 │ ├── encode.xlsx │ └── goal 06.docx ├── goal 07 │ ├── goal 07.docx │ └── signals.xlsx ├── goal 08 │ ├── goal 08.docx │ └── signals.xlsx └── goal 09 │ ├── goal 09.docx │ └── signals.xlsx ├── code ├── goal 07 │ ├── mycpu_top.h │ ├── regfile.v │ ├── tools.v │ ├── wb_stage.v │ ├── mem_stage.v │ ├── if_stage.v │ ├── exe_stage.v │ ├── alu.v │ ├── mycpu_top.v │ └── id_stage.v ├── goal 08 │ ├── mycpu_top.h │ ├── regfile.v │ ├── tools.v │ ├── wb_stage.v │ ├── mem_stage.v │ ├── if_stage.v │ ├── exe_stage.v │ ├── alu.v │ ├── mycpu_top.v │ └── id_stage.v ├── goal 09 │ ├── mycpu_top.h │ ├── regfile.v │ ├── tools.v │ ├── wb_stage.v │ ├── mem_stage.v │ ├── if_stage.v │ ├── exe_stage.v │ ├── alu.v │ ├── mycpu_top.v │ └── id_stage.v ├── goal 05 │ ├── regfile.v │ ├── tools.v │ └── minicpu_top.v └── goal 06 │ ├── regfile.v │ ├── tools.v │ ├── alu.v │ └── mycpu_top.v └── README.md /report/goal 05/encode.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlyMachinee/project-pipeline/HEAD/report/goal 05/encode.xlsx -------------------------------------------------------------------------------- /report/goal 05/goal 05.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlyMachinee/project-pipeline/HEAD/report/goal 05/goal 05.docx -------------------------------------------------------------------------------- /report/goal 06/encode.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlyMachinee/project-pipeline/HEAD/report/goal 06/encode.xlsx -------------------------------------------------------------------------------- /report/goal 06/goal 06.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlyMachinee/project-pipeline/HEAD/report/goal 06/goal 06.docx -------------------------------------------------------------------------------- /report/goal 07/goal 07.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlyMachinee/project-pipeline/HEAD/report/goal 07/goal 07.docx -------------------------------------------------------------------------------- /report/goal 07/signals.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlyMachinee/project-pipeline/HEAD/report/goal 07/signals.xlsx -------------------------------------------------------------------------------- /report/goal 08/goal 08.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlyMachinee/project-pipeline/HEAD/report/goal 08/goal 08.docx -------------------------------------------------------------------------------- /report/goal 08/signals.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlyMachinee/project-pipeline/HEAD/report/goal 08/signals.xlsx -------------------------------------------------------------------------------- /report/goal 09/goal 09.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlyMachinee/project-pipeline/HEAD/report/goal 09/goal 09.docx -------------------------------------------------------------------------------- /report/goal 09/signals.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlyMachinee/project-pipeline/HEAD/report/goal 09/signals.xlsx -------------------------------------------------------------------------------- /code/goal 07/mycpu_top.h: -------------------------------------------------------------------------------- 1 | `ifndef MYCPU_TOP_H 2 | `define MYCPU_TOP_H 3 | `define IF_TO_ID_BUS_WIDTH 64 4 | `define ID_TO_EXE_BUS_WIDTH 154 5 | `define EXE_TO_MEM_BUS_WIDTH 71 6 | `define MEM_TO_WB_BUS_WIDTH 70 7 | `define WB_TO_ID_BUS_WIDTH 38 8 | `define ID_TO_IF_BUS_WIDTH 33 9 | `endif -------------------------------------------------------------------------------- /code/goal 08/mycpu_top.h: -------------------------------------------------------------------------------- 1 | `ifndef MYCPU_TOP_H 2 | `define MYCPU_TOP_H 3 | `define IF_TO_ID_BUS_WIDTH 64 4 | `define ID_TO_EXE_BUS_WIDTH 154 5 | `define EXE_TO_MEM_BUS_WIDTH 71 6 | `define MEM_TO_WB_BUS_WIDTH 70 7 | `define WB_TO_ID_BUS_WIDTH 38 8 | `define ID_TO_IF_BUS_WIDTH 34 9 | `endif -------------------------------------------------------------------------------- /code/goal 09/mycpu_top.h: -------------------------------------------------------------------------------- 1 | `ifndef MYCPU_TOP_H 2 | `define MYCPU_TOP_H 3 | `define IF_TO_ID_BUS_WIDTH 64 4 | `define ID_TO_EXE_BUS_WIDTH 154 5 | `define EXE_TO_MEM_BUS_WIDTH 71 6 | `define MEM_TO_WB_BUS_WIDTH 70 7 | `define WB_TO_ID_BUS_WIDTH 38 8 | `define ID_TO_IF_BUS_WIDTH 34 9 | `define BYPASS_BUS_WIDTH 38 10 | `endif -------------------------------------------------------------------------------- /code/goal 05/regfile.v: -------------------------------------------------------------------------------- 1 | module regfile( 2 | input wire clk, 3 | // READ PORT 1 4 | input wire [ 4:0] raddr1, 5 | output wire [31:0] rdata1, 6 | // READ PORT 2 7 | input wire [ 4:0] raddr2, 8 | output wire [31:0] rdata2, 9 | // WRITE PORT 10 | input wire we, //write enable, HIGH valid 11 | input wire [ 4:0] waddr, 12 | input wire [31:0] wdata 13 | ); 14 | reg [31:0] rf[31:0]; 15 | 16 | //WRITE 17 | always @(posedge clk) begin 18 | if (we) rf[waddr]<= wdata; 19 | end 20 | 21 | //READ OUT 1 22 | assign rdata1 = (raddr1==5'b0) ? 32'b0 : rf[raddr1]; 23 | 24 | //READ OUT 2 25 | assign rdata2 = (raddr2==5'b0) ? 32'b0 : rf[raddr2]; 26 | 27 | endmodule 28 | -------------------------------------------------------------------------------- /code/goal 06/regfile.v: -------------------------------------------------------------------------------- 1 | module regfile( 2 | input wire clk, 3 | // READ PORT 1 4 | input wire [ 4:0] raddr1, 5 | output wire [31:0] rdata1, 6 | // READ PORT 2 7 | input wire [ 4:0] raddr2, 8 | output wire [31:0] rdata2, 9 | // WRITE PORT 10 | input wire we, //write enable, HIGH valid 11 | input wire [ 4:0] waddr, 12 | input wire [31:0] wdata 13 | ); 14 | reg [31:0] rf[31:0]; 15 | 16 | //WRITE 17 | always @(posedge clk) begin 18 | if (we) rf[waddr] <= wdata; 19 | end 20 | 21 | //READ OUT 1 22 | assign rdata1 = (raddr1==5'b0) ? 32'b0 : rf[raddr1]; 23 | 24 | //READ OUT 2 25 | assign rdata2 = (raddr2==5'b0) ? 32'b0 : rf[raddr2]; 26 | 27 | endmodule 28 | -------------------------------------------------------------------------------- /code/goal 07/regfile.v: -------------------------------------------------------------------------------- 1 | module regfile( 2 | input wire clk, 3 | // READ PORT 1 4 | input wire [ 4:0] raddr1, 5 | output wire [31:0] rdata1, 6 | // READ PORT 2 7 | input wire [ 4:0] raddr2, 8 | output wire [31:0] rdata2, 9 | // WRITE PORT 10 | input wire we, //write enable, HIGH valid 11 | input wire [ 4:0] waddr, 12 | input wire [31:0] wdata 13 | ); 14 | reg [31:0] rf[31:0]; 15 | 16 | //WRITE 17 | always @(posedge clk) begin 18 | if (we) rf[waddr] <= wdata; 19 | end 20 | 21 | //READ OUT 1 22 | assign rdata1 = (raddr1==5'b0) ? 32'b0 : rf[raddr1]; 23 | 24 | //READ OUT 2 25 | assign rdata2 = (raddr2==5'b0) ? 32'b0 : rf[raddr2]; 26 | 27 | endmodule 28 | -------------------------------------------------------------------------------- /code/goal 08/regfile.v: -------------------------------------------------------------------------------- 1 | module regfile( 2 | input wire clk, 3 | // READ PORT 1 4 | input wire [ 4:0] raddr1, 5 | output wire [31:0] rdata1, 6 | // READ PORT 2 7 | input wire [ 4:0] raddr2, 8 | output wire [31:0] rdata2, 9 | // WRITE PORT 10 | input wire we, //write enable, HIGH valid 11 | input wire [ 4:0] waddr, 12 | input wire [31:0] wdata 13 | ); 14 | reg [31:0] rf[31:0]; 15 | 16 | //WRITE 17 | always @(posedge clk) begin 18 | if (we) rf[waddr] <= wdata; 19 | end 20 | 21 | //READ OUT 1 22 | assign rdata1 = (raddr1==5'b0) ? 32'b0 : rf[raddr1]; 23 | 24 | //READ OUT 2 25 | assign rdata2 = (raddr2==5'b0) ? 32'b0 : rf[raddr2]; 26 | 27 | endmodule 28 | -------------------------------------------------------------------------------- /code/goal 09/regfile.v: -------------------------------------------------------------------------------- 1 | module regfile( 2 | input wire clk, 3 | // READ PORT 1 4 | input wire [ 4:0] raddr1, 5 | output wire [31:0] rdata1, 6 | // READ PORT 2 7 | input wire [ 4:0] raddr2, 8 | output wire [31:0] rdata2, 9 | // WRITE PORT 10 | input wire we, //write enable, HIGH valid 11 | input wire [ 4:0] waddr, 12 | input wire [31:0] wdata 13 | ); 14 | reg [31:0] rf[31:0]; 15 | 16 | //WRITE 17 | always @(posedge clk) begin 18 | if (we) rf[waddr] <= wdata; 19 | end 20 | 21 | //READ OUT 1 22 | assign rdata1 = (raddr1==5'b0) ? 32'b0 : rf[raddr1]; 23 | 24 | //READ OUT 2 25 | assign rdata2 = (raddr2==5'b0) ? 32'b0 : rf[raddr2]; 26 | 27 | endmodule 28 | -------------------------------------------------------------------------------- /code/goal 06/tools.v: -------------------------------------------------------------------------------- 1 | module decoder_2_4( 2 | input wire [ 1:0] in, 3 | output wire [ 3:0] out 4 | ); 5 | 6 | genvar i; 7 | generate for (i=0; i<4; i=i+1) begin : gen_for_dec_2_4 8 | assign out[i] = (in == i); 9 | end endgenerate 10 | 11 | endmodule 12 | 13 | 14 | module decoder_4_16( 15 | input wire [ 3:0] in, 16 | output wire [15:0] out 17 | ); 18 | 19 | genvar i; 20 | generate for (i=0; i<16; i=i+1) begin : gen_for_dec_4_16 21 | assign out[i] = (in == i); 22 | end endgenerate 23 | 24 | endmodule 25 | 26 | 27 | module decoder_5_32( 28 | input wire [ 4:0] in, 29 | output wire [31:0] out 30 | ); 31 | 32 | genvar i; 33 | generate for (i=0; i<32; i=i+1) begin : gen_for_dec_5_32 34 | assign out[i] = (in == i); 35 | end endgenerate 36 | 37 | endmodule 38 | 39 | 40 | module decoder_6_64( 41 | input wire [ 5:0] in, 42 | output wire [63:0] out 43 | ); 44 | 45 | genvar i; 46 | generate for (i=0; i<64; i=i+1) begin : gen_for_dec_6_64 47 | assign out[i] = (in == i); 48 | end endgenerate 49 | 50 | endmodule 51 | -------------------------------------------------------------------------------- /code/goal 07/tools.v: -------------------------------------------------------------------------------- 1 | module decoder_2_4( 2 | input wire [ 1:0] in, 3 | output wire [ 3:0] out 4 | ); 5 | 6 | genvar i; 7 | generate for (i=0; i<4; i=i+1) begin : gen_for_dec_2_4 8 | assign out[i] = (in == i); 9 | end endgenerate 10 | 11 | endmodule 12 | 13 | 14 | module decoder_4_16( 15 | input wire [ 3:0] in, 16 | output wire [15:0] out 17 | ); 18 | 19 | genvar i; 20 | generate for (i=0; i<16; i=i+1) begin : gen_for_dec_4_16 21 | assign out[i] = (in == i); 22 | end endgenerate 23 | 24 | endmodule 25 | 26 | 27 | module decoder_5_32( 28 | input wire [ 4:0] in, 29 | output wire [31:0] out 30 | ); 31 | 32 | genvar i; 33 | generate for (i=0; i<32; i=i+1) begin : gen_for_dec_5_32 34 | assign out[i] = (in == i); 35 | end endgenerate 36 | 37 | endmodule 38 | 39 | 40 | module decoder_6_64( 41 | input wire [ 5:0] in, 42 | output wire [63:0] out 43 | ); 44 | 45 | genvar i; 46 | generate for (i=0; i<64; i=i+1) begin : gen_for_dec_6_64 47 | assign out[i] = (in == i); 48 | end endgenerate 49 | 50 | endmodule 51 | -------------------------------------------------------------------------------- /code/goal 08/tools.v: -------------------------------------------------------------------------------- 1 | module decoder_2_4( 2 | input wire [ 1:0] in, 3 | output wire [ 3:0] out 4 | ); 5 | 6 | genvar i; 7 | generate for (i=0; i<4; i=i+1) begin : gen_for_dec_2_4 8 | assign out[i] = (in == i); 9 | end endgenerate 10 | 11 | endmodule 12 | 13 | 14 | module decoder_4_16( 15 | input wire [ 3:0] in, 16 | output wire [15:0] out 17 | ); 18 | 19 | genvar i; 20 | generate for (i=0; i<16; i=i+1) begin : gen_for_dec_4_16 21 | assign out[i] = (in == i); 22 | end endgenerate 23 | 24 | endmodule 25 | 26 | 27 | module decoder_5_32( 28 | input wire [ 4:0] in, 29 | output wire [31:0] out 30 | ); 31 | 32 | genvar i; 33 | generate for (i=0; i<32; i=i+1) begin : gen_for_dec_5_32 34 | assign out[i] = (in == i); 35 | end endgenerate 36 | 37 | endmodule 38 | 39 | 40 | module decoder_6_64( 41 | input wire [ 5:0] in, 42 | output wire [63:0] out 43 | ); 44 | 45 | genvar i; 46 | generate for (i=0; i<64; i=i+1) begin : gen_for_dec_6_64 47 | assign out[i] = (in == i); 48 | end endgenerate 49 | 50 | endmodule 51 | -------------------------------------------------------------------------------- /code/goal 09/tools.v: -------------------------------------------------------------------------------- 1 | module decoder_2_4( 2 | input wire [ 1:0] in, 3 | output wire [ 3:0] out 4 | ); 5 | 6 | genvar i; 7 | generate for (i=0; i<4; i=i+1) begin : gen_for_dec_2_4 8 | assign out[i] = (in == i); 9 | end endgenerate 10 | 11 | endmodule 12 | 13 | 14 | module decoder_4_16( 15 | input wire [ 3:0] in, 16 | output wire [15:0] out 17 | ); 18 | 19 | genvar i; 20 | generate for (i=0; i<16; i=i+1) begin : gen_for_dec_4_16 21 | assign out[i] = (in == i); 22 | end endgenerate 23 | 24 | endmodule 25 | 26 | 27 | module decoder_5_32( 28 | input wire [ 4:0] in, 29 | output wire [31:0] out 30 | ); 31 | 32 | genvar i; 33 | generate for (i=0; i<32; i=i+1) begin : gen_for_dec_5_32 34 | assign out[i] = (in == i); 35 | end endgenerate 36 | 37 | endmodule 38 | 39 | 40 | module decoder_6_64( 41 | input wire [ 5:0] in, 42 | output wire [63:0] out 43 | ); 44 | 45 | genvar i; 46 | generate for (i=0; i<64; i=i+1) begin : gen_for_dec_6_64 47 | assign out[i] = (in == i); 48 | end endgenerate 49 | 50 | endmodule 51 | -------------------------------------------------------------------------------- /code/goal 05/tools.v: -------------------------------------------------------------------------------- 1 | module decoder_2_4( 2 | input wire [ 1:0] in, 3 | output wire [ 3:0] co 4 | ); 5 | 6 | genvar i; 7 | generate for (i=0; i<4; i=i+1) begin : gen_for_dec_2_4 8 | assign co[i] = (in == i); 9 | end endgenerate 10 | 11 | endmodule 12 | 13 | 14 | module decoder_4_16( 15 | input wire [ 3:0] in, 16 | output wire [15:0] co 17 | ); 18 | 19 | genvar i; 20 | generate for (i=0; i<16; i=i+1) begin : gen_for_dec_4_16 21 | assign co[i] = (in == i); 22 | end endgenerate 23 | 24 | endmodule 25 | 26 | 27 | module decoder_5_32( 28 | input wire [ 4:0] in, 29 | output wire [31:0] co 30 | ); 31 | 32 | genvar i; 33 | generate for (i=0; i<32; i=i+1) begin : gen_for_dec_5_32 34 | assign co[i] = (in == i); 35 | end endgenerate 36 | 37 | endmodule 38 | 39 | 40 | module decoder_6_64( 41 | input wire [ 5:0] in, 42 | output wire [63:0] co 43 | ); 44 | 45 | genvar i; 46 | generate for (i=0; i<64; i=i+1) begin : gen_for_dec_6_64 47 | assign co[i] = (in == i); 48 | end endgenerate 49 | 50 | endmodule 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /code/goal 07/wb_stage.v: -------------------------------------------------------------------------------- 1 | `include "mycpu_top.h" 2 | `default_nettype wire 3 | 4 | module wb_stage ( 5 | input clk, 6 | input reset, 7 | 8 | // pipeline control 9 | output wb_allow_in, 10 | input mem_to_wb_valid, 11 | 12 | // bus from mem 13 | input [`MEM_TO_WB_BUS_WIDTH-1:0] mem_to_wb_bus, 14 | 15 | // bus to id (for regfile) 16 | output [`WB_TO_ID_BUS_WIDTH-1:0] wb_to_id_bus, 17 | 18 | // debug interface 19 | output [31:0] debug_wb_pc, 20 | output [ 3:0] debug_wb_rf_we, 21 | output [ 4:0] debug_wb_rf_wnum, 22 | output [31:0] debug_wb_rf_wdata 23 | ); 24 | 25 | // pipeline registers 26 | reg [`MEM_TO_WB_BUS_WIDTH-1:0] wb_reg; 27 | wire [31:0] wb_pc; 28 | wire [31:0] wb_final_result; 29 | wire wb_reg_we; 30 | wire [4:0] wb_reg_waddr; 31 | assign {wb_pc, wb_final_result, wb_reg_we, wb_reg_waddr} = wb_reg; 32 | 33 | // output bus to ID 34 | assign wb_to_id_bus = {wb_reg_we, wb_reg_waddr, wb_final_result}; 35 | 36 | // pipeline control 37 | reg wb_valid; 38 | wire wb_ready_go; 39 | 40 | assign wb_ready_go = 1; 41 | assign wb_allow_in = !wb_valid || wb_ready_go; 42 | 43 | always @(posedge clk) begin 44 | if (reset) begin 45 | wb_valid <= 1'b0; 46 | end else if (wb_allow_in) begin 47 | wb_valid <= mem_to_wb_valid; 48 | end 49 | end 50 | 51 | always @(posedge clk) begin 52 | if (wb_allow_in && mem_to_wb_valid) begin 53 | wb_reg <= mem_to_wb_bus; 54 | end 55 | end 56 | 57 | // debug interface 58 | assign debug_wb_pc = wb_pc; 59 | assign debug_wb_rf_we = {4{wb_reg_we}}; 60 | assign debug_wb_rf_wnum = wb_reg_waddr; 61 | assign debug_wb_rf_wdata = wb_final_result; 62 | 63 | endmodule 64 | -------------------------------------------------------------------------------- /code/goal 07/mem_stage.v: -------------------------------------------------------------------------------- 1 | `include "mycpu_top.h" 2 | 3 | module mem_stage ( 4 | input clk, 5 | input reset, 6 | 7 | // pipeline control 8 | output mem_allow_in, 9 | input exe_to_mem_valid, 10 | input wb_allow_in, 11 | output mem_to_wb_valid, 12 | 13 | // bus from exe 14 | input [`EXE_TO_MEM_BUS_WIDTH-1:0] exe_to_mem_bus, 15 | 16 | // bus to wb 17 | output [`MEM_TO_WB_BUS_WIDTH-1:0] mem_to_wb_bus, 18 | 19 | // cpu interface 20 | input [31:0] data_sram_rdata 21 | ); 22 | 23 | // pipeline registers 24 | reg [`EXE_TO_MEM_BUS_WIDTH-1:0] mem_reg; 25 | 26 | wire [31:0] mem_pc; 27 | wire [31:0] mem_alu_result; 28 | wire mem_res_from_mem; 29 | wire mem_reg_we; 30 | wire [4:0] mem_reg_waddr; 31 | assign {mem_pc, mem_alu_result, mem_res_from_mem, mem_reg_we, mem_reg_waddr} = mem_reg; 32 | 33 | // output bus to WB 34 | wire [31:0] final_result; 35 | assign mem_to_wb_bus = {mem_pc, final_result, mem_reg_we, mem_reg_waddr}; 36 | 37 | // pipeline control 38 | reg mem_valid; 39 | wire mem_ready_go; 40 | 41 | assign mem_ready_go = 1; 42 | assign mem_allow_in = !mem_valid || (mem_ready_go && wb_allow_in); 43 | assign mem_to_wb_valid = mem_valid && mem_ready_go; 44 | 45 | always @(posedge clk) begin 46 | if (reset) begin 47 | mem_valid <= 1'b0; 48 | end else if (mem_allow_in) begin 49 | mem_valid <= exe_to_mem_valid; 50 | end 51 | end 52 | 53 | always @(posedge clk) begin 54 | if (mem_allow_in && exe_to_mem_valid) begin 55 | mem_reg <= exe_to_mem_bus; 56 | end 57 | end 58 | 59 | // internal signals 60 | wire [31:0] mem_result; 61 | 62 | // MEM stage 63 | assign mem_result = data_sram_rdata; 64 | assign final_result = mem_res_from_mem ? mem_result : mem_alu_result; 65 | 66 | endmodule 67 | -------------------------------------------------------------------------------- /code/goal 08/wb_stage.v: -------------------------------------------------------------------------------- 1 | `include "mycpu_top.h" 2 | `default_nettype wire 3 | 4 | module wb_stage ( 5 | input clk, 6 | input reset, 7 | 8 | // pipeline control 9 | output wb_allow_in, 10 | input mem_to_wb_valid, 11 | output reg wb_valid, 12 | 13 | // bus from mem 14 | input [`MEM_TO_WB_BUS_WIDTH-1:0] mem_to_wb_bus, 15 | 16 | // bus to id (for regfile) 17 | output [`WB_TO_ID_BUS_WIDTH-1:0] wb_to_id_bus, 18 | 19 | // debug interface 20 | output [31:0] debug_wb_pc, 21 | output [ 3:0] debug_wb_rf_we, 22 | output [ 4:0] debug_wb_rf_wnum, 23 | output [31:0] debug_wb_rf_wdata 24 | ); 25 | 26 | // pipeline registers 27 | reg [`MEM_TO_WB_BUS_WIDTH-1:0] wb_reg; 28 | wire [31:0] wb_pc; 29 | wire [31:0] wb_final_result; 30 | wire wb_reg_we; 31 | wire [4:0] wb_reg_waddr; 32 | assign {wb_pc, wb_final_result, wb_reg_we, wb_reg_waddr} = wb_reg; 33 | 34 | // output bus to ID 35 | assign wb_to_id_bus = {wb_reg_we, wb_reg_waddr, wb_final_result}; 36 | 37 | // pipeline control 38 | // reg wb_valid; 39 | wire wb_ready_go; 40 | wire wb_to_id_valid; 41 | 42 | assign wb_ready_go = 1; 43 | assign wb_allow_in = !wb_valid || wb_ready_go; 44 | assign wb_to_id_valid = wb_valid && wb_ready_go; 45 | 46 | always @(posedge clk) begin 47 | if (reset) begin 48 | wb_valid <= 1'b0; 49 | end else if (wb_allow_in) begin 50 | wb_valid <= mem_to_wb_valid; 51 | end 52 | end 53 | 54 | always @(posedge clk) begin 55 | if (wb_allow_in && mem_to_wb_valid) begin 56 | wb_reg <= mem_to_wb_bus; 57 | end 58 | end 59 | 60 | // debug interface 61 | assign debug_wb_pc = wb_pc; 62 | assign debug_wb_rf_we = {4{wb_to_id_valid ? wb_reg_we : 1'b0}}; 63 | assign debug_wb_rf_wnum = wb_reg_waddr; 64 | assign debug_wb_rf_wdata = wb_final_result; 65 | 66 | endmodule 67 | -------------------------------------------------------------------------------- /code/goal 09/wb_stage.v: -------------------------------------------------------------------------------- 1 | `include "mycpu_top.h" 2 | `default_nettype wire 3 | 4 | module wb_stage ( 5 | input clk, 6 | input reset, 7 | 8 | // pipeline control 9 | output wb_allow_in, 10 | input mem_to_wb_valid, 11 | output reg wb_valid, 12 | 13 | // bus from mem 14 | input [`MEM_TO_WB_BUS_WIDTH-1:0] mem_to_wb_bus, 15 | 16 | // bus to id (for regfile) 17 | output [`WB_TO_ID_BUS_WIDTH-1:0] wb_to_id_bus, 18 | 19 | // debug interface 20 | output [31:0] debug_wb_pc, 21 | output [ 3:0] debug_wb_rf_we, 22 | output [ 4:0] debug_wb_rf_wnum, 23 | output [31:0] debug_wb_rf_wdata 24 | ); 25 | 26 | // pipeline registers 27 | reg [`MEM_TO_WB_BUS_WIDTH-1:0] wb_reg; 28 | wire [31:0] wb_pc; 29 | wire [31:0] wb_final_result; 30 | wire wb_reg_we; 31 | wire [4:0] wb_reg_waddr; 32 | assign {wb_pc, wb_final_result, wb_reg_we, wb_reg_waddr} = wb_reg; 33 | 34 | // output bus to ID 35 | assign wb_to_id_bus = {wb_reg_we, wb_reg_waddr, wb_final_result}; 36 | 37 | // pipeline control 38 | // reg wb_valid; 39 | wire wb_ready_go; 40 | wire wb_to_id_valid; 41 | 42 | assign wb_ready_go = 1; 43 | assign wb_allow_in = !wb_valid || wb_ready_go; 44 | assign wb_to_id_valid = wb_valid && wb_ready_go; 45 | 46 | always @(posedge clk) begin 47 | if (reset) begin 48 | wb_valid <= 1'b0; 49 | end else if (wb_allow_in) begin 50 | wb_valid <= mem_to_wb_valid; 51 | end 52 | end 53 | 54 | always @(posedge clk) begin 55 | if (wb_allow_in && mem_to_wb_valid) begin 56 | wb_reg <= mem_to_wb_bus; 57 | end 58 | end 59 | 60 | // debug interface 61 | assign debug_wb_pc = wb_pc; 62 | assign debug_wb_rf_we = {4{wb_to_id_valid ? wb_reg_we : 1'b0}}; 63 | assign debug_wb_rf_wnum = wb_reg_waddr; 64 | assign debug_wb_rf_wdata = wb_final_result; 65 | 66 | endmodule 67 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Project-Pipeline 2 | 3 | 本仓库为《[HIT] 32位流水线CPU的设计与实践——Verilog实现》系列视频的参考代码仓库 4 | 5 | 视频链接:https://www.bilibili.com/video/BV1xzBHYgE3c/ 6 | 7 | 05-09 分别对应了《CPU设计实战:LoongArch版》中的实践任务 05-09 8 | 9 | 《实战》实践任务部分的电子书:https://bookdown.org/loongson/_book3/ 10 | 11 | 《实战》实践任务的测试环境:https://gitee.com/loongson-edu/cdp_ede_local 12 | 13 | ## 仓库解释 14 | 15 | `code`:参考代码 16 | 17 | `report`:参考实验过程 18 | 19 | `README.md`:本文件 20 | 21 | ## 目录结构 22 | 23 | ``` 24 | repo 25 | │ 26 | │ README.md 27 | │ 28 | ├─code 29 | │ ├─goal 05 30 | │ │ minicpu_top.v 31 | │ │ regfile.v 32 | │ │ tools.v 33 | │ │ 34 | │ ├─goal 06 35 | │ │ alu.v 36 | │ │ mycpu_top.v 37 | │ │ regfile.v 38 | │ │ tools.v 39 | │ │ 40 | │ ├─goal 07 41 | │ │ alu.v 42 | │ │ exe_stage.v 43 | │ │ id_stage.v 44 | │ │ if_stage.v 45 | │ │ mem_stage.v 46 | │ │ mycpu_top.h 47 | │ │ mycpu_top.v 48 | │ │ regfile.v 49 | │ │ tools.v 50 | │ │ wb_stage.v 51 | │ │ 52 | │ ├─goal 08 53 | │ │ alu.v 54 | │ │ exe_stage.v 55 | │ │ id_stage.v 56 | │ │ if_stage.v 57 | │ │ mem_stage.v 58 | │ │ mycpu_top.h 59 | │ │ mycpu_top.v 60 | │ │ regfile.v 61 | │ │ tools.v 62 | │ │ wb_stage.v 63 | │ │ 64 | │ └─goal 09 65 | │ alu.v 66 | │ exe_stage.v 67 | │ id_stage.v 68 | │ if_stage.v 69 | │ mem_stage.v 70 | │ mycpu_top.h 71 | │ mycpu_top.v 72 | │ regfile.v 73 | │ tools.v 74 | │ wb_stage.v 75 | │ 76 | └─report 77 | ├─goal 05 78 | │ encode.xlsx 79 | │ goal 05.docx 80 | │ 81 | ├─goal 06 82 | │ encode.xlsx 83 | │ goal 06.docx 84 | │ 85 | ├─goal 07 86 | │ goal 07.docx 87 | │ signals.xlsx 88 | │ 89 | ├─goal 08 90 | │ goal 08.docx 91 | │ signals.xlsx 92 | │ 93 | └─goal 09 94 | goal 09.docx 95 | signals.xlsx 96 | ``` -------------------------------------------------------------------------------- /code/goal 09/mem_stage.v: -------------------------------------------------------------------------------- 1 | `include "mycpu_top.h" 2 | 3 | module mem_stage ( 4 | input clk, 5 | input reset, 6 | 7 | // pipeline control 8 | output mem_allow_in, 9 | input exe_to_mem_valid, 10 | input wb_allow_in, 11 | output mem_to_wb_valid, 12 | 13 | // bypass 14 | output reg mem_valid, 15 | output [`BYPASS_BUS_WIDTH-1:0] mem_to_id_bypass_bus, 16 | 17 | // bus from exe 18 | input [`EXE_TO_MEM_BUS_WIDTH-1:0] exe_to_mem_bus, 19 | 20 | // bus to wb 21 | output [`MEM_TO_WB_BUS_WIDTH-1:0] mem_to_wb_bus, 22 | 23 | // cpu interface 24 | input [31:0] data_sram_rdata 25 | ); 26 | 27 | // pipeline registers 28 | reg [`EXE_TO_MEM_BUS_WIDTH-1:0] mem_reg; 29 | 30 | wire [31:0] mem_pc; 31 | wire [31:0] mem_alu_result; 32 | wire mem_res_from_mem; 33 | wire mem_reg_we; 34 | wire [4:0] mem_reg_waddr; 35 | assign {mem_pc, mem_alu_result, mem_res_from_mem, mem_reg_we, mem_reg_waddr} = mem_reg; 36 | 37 | // output bus to WB 38 | wire [31:0] final_result; 39 | assign mem_to_wb_bus = {mem_pc, final_result, mem_reg_we, mem_reg_waddr}; 40 | 41 | // pipeline control 42 | // reg mem_valid; 43 | wire mem_ready_go; 44 | 45 | assign mem_ready_go = 1; 46 | assign mem_allow_in = !mem_valid || (mem_ready_go && wb_allow_in); 47 | assign mem_to_wb_valid = mem_valid && mem_ready_go; 48 | 49 | always @(posedge clk) begin 50 | if (reset) begin 51 | mem_valid <= 1'b0; 52 | end else if (mem_allow_in) begin 53 | mem_valid <= exe_to_mem_valid; 54 | end 55 | end 56 | 57 | always @(posedge clk) begin 58 | if (mem_allow_in && exe_to_mem_valid) begin 59 | mem_reg <= exe_to_mem_bus; 60 | end 61 | end 62 | 63 | // internal signals 64 | wire [31:0] mem_result; 65 | 66 | // MEM stage 67 | assign mem_result = data_sram_rdata; 68 | assign final_result = mem_res_from_mem ? mem_result : mem_alu_result; 69 | 70 | // bypass to ID 71 | assign mem_to_id_bypass_bus = {mem_reg_we, mem_reg_waddr, final_result}; 72 | 73 | endmodule 74 | -------------------------------------------------------------------------------- /code/goal 08/mem_stage.v: -------------------------------------------------------------------------------- 1 | `include "mycpu_top.h" 2 | 3 | module mem_stage ( 4 | input clk, 5 | input reset, 6 | 7 | // pipeline control 8 | output mem_allow_in, 9 | input exe_to_mem_valid, 10 | input wb_allow_in, 11 | output mem_to_wb_valid, 12 | 13 | // hazard detection 14 | output mem_rf_we, 15 | output [4:0] mem_rf_waddr, 16 | output reg mem_valid, 17 | 18 | // bus from exe 19 | input [`EXE_TO_MEM_BUS_WIDTH-1:0] exe_to_mem_bus, 20 | 21 | // bus to wb 22 | output [`MEM_TO_WB_BUS_WIDTH-1:0] mem_to_wb_bus, 23 | 24 | // cpu interface 25 | input [31:0] data_sram_rdata 26 | ); 27 | 28 | // pipeline registers 29 | reg [`EXE_TO_MEM_BUS_WIDTH-1:0] mem_reg; 30 | 31 | wire [31:0] mem_pc; 32 | wire [31:0] mem_alu_result; 33 | wire mem_res_from_mem; 34 | wire mem_reg_we; 35 | wire [4:0] mem_reg_waddr; 36 | assign {mem_pc, mem_alu_result, mem_res_from_mem, mem_reg_we, mem_reg_waddr} = mem_reg; 37 | 38 | // output bus to WB 39 | wire [31:0] final_result; 40 | assign mem_to_wb_bus = {mem_pc, final_result, mem_reg_we, mem_reg_waddr}; 41 | 42 | // pipeline control 43 | // reg mem_valid; 44 | wire mem_ready_go; 45 | 46 | assign mem_ready_go = 1; 47 | assign mem_allow_in = !mem_valid || (mem_ready_go && wb_allow_in); 48 | assign mem_to_wb_valid = mem_valid && mem_ready_go; 49 | 50 | always @(posedge clk) begin 51 | if (reset) begin 52 | mem_valid <= 1'b0; 53 | end else if (mem_allow_in) begin 54 | mem_valid <= exe_to_mem_valid; 55 | end 56 | end 57 | 58 | always @(posedge clk) begin 59 | if (mem_allow_in && exe_to_mem_valid) begin 60 | mem_reg <= exe_to_mem_bus; 61 | end 62 | end 63 | 64 | // internal signals 65 | wire [31:0] mem_result; 66 | 67 | // MEM stage 68 | assign mem_result = data_sram_rdata; 69 | assign final_result = mem_res_from_mem ? mem_result : mem_alu_result; 70 | 71 | // hazard detection 72 | assign mem_rf_we = mem_reg_we; 73 | assign mem_rf_waddr = mem_reg_waddr; 74 | 75 | endmodule 76 | -------------------------------------------------------------------------------- /code/goal 07/if_stage.v: -------------------------------------------------------------------------------- 1 | `include "mycpu_top.h" 2 | 3 | module if_stage ( 4 | input clk, 5 | input reset, 6 | 7 | // pipeline control 8 | input id_allow_in, 9 | output if_to_id_valid, 10 | 11 | // bus to id 12 | output [`IF_TO_ID_BUS_WIDTH-1:0] if_to_id_bus, 13 | 14 | // bus from id 15 | input [`ID_TO_IF_BUS_WIDTH-1:0] id_to_if_bus, 16 | 17 | // cpu interface 18 | output inst_sram_en, 19 | output [ 3:0] inst_sram_we, 20 | output [31:0] inst_sram_addr, 21 | output [31:0] inst_sram_wdata, 22 | input [31:0] inst_sram_rdata 23 | ); 24 | 25 | // input bus from ID (for branch) 26 | wire br_taken; 27 | wire [31:0] br_target; 28 | assign {br_taken, br_target} = id_to_if_bus; 29 | 30 | // output bus to ID 31 | reg [31:0] if_pc; 32 | wire [31:0] inst; 33 | assign if_to_id_bus = {if_pc, inst}; 34 | 35 | // internal signals 36 | wire [31:0] seq_pc; 37 | wire [31:0] nextpc; 38 | 39 | // pipeline control 40 | reg if_valid; 41 | wire pre_if_valid; 42 | wire if_allow_in; 43 | wire if_ready_go; 44 | 45 | always @(posedge clk) begin 46 | if (reset) begin 47 | if_valid <= 1'b0; 48 | end else if (if_allow_in) begin 49 | if_valid <= pre_if_valid; 50 | end 51 | end 52 | 53 | // pre-IF stage 54 | assign seq_pc = if_pc + 3'h4; 55 | assign nextpc = br_taken ? br_target : seq_pc; 56 | assign pre_if_valid = ~reset; // && if_allow_in; 57 | 58 | // IF stage 59 | assign if_ready_go = 1; 60 | assign if_to_id_valid = if_valid && if_ready_go; 61 | assign if_allow_in = !if_valid || (if_ready_go && id_allow_in); 62 | 63 | always @(posedge clk) begin 64 | if (reset) begin 65 | if_pc <= 32'h1bfffffc; //trick: to make nextpc be 0x1c000000 during reset 66 | end else if (if_allow_in && pre_if_valid) begin 67 | if_pc <= nextpc; 68 | end 69 | end 70 | 71 | assign inst_sram_en = pre_if_valid && if_allow_in; 72 | assign inst_sram_we = 4'b0000; 73 | assign inst_sram_addr = nextpc; 74 | assign inst_sram_wdata = 32'b0; 75 | assign inst = inst_sram_rdata; 76 | 77 | endmodule 78 | -------------------------------------------------------------------------------- /code/goal 08/if_stage.v: -------------------------------------------------------------------------------- 1 | `include "mycpu_top.h" 2 | 3 | module if_stage ( 4 | input clk, 5 | input reset, 6 | 7 | // pipeline control 8 | input id_allow_in, 9 | output if_to_id_valid, 10 | 11 | // bus to id 12 | output [`IF_TO_ID_BUS_WIDTH-1:0] if_to_id_bus, 13 | 14 | // bus from id 15 | input [`ID_TO_IF_BUS_WIDTH-1:0] id_to_if_bus, 16 | 17 | // cpu interface 18 | output inst_sram_en, 19 | output [ 3:0] inst_sram_we, 20 | output [31:0] inst_sram_addr, 21 | output [31:0] inst_sram_wdata, 22 | input [31:0] inst_sram_rdata 23 | ); 24 | 25 | // input bus from ID (for branch) 26 | wire br_taken; 27 | wire [31:0] br_target; 28 | wire br_taken_cancel; 29 | assign {br_taken, br_target, br_taken_cancel} = id_to_if_bus; 30 | 31 | // output bus to ID 32 | reg [31:0] if_pc; 33 | wire [31:0] inst; 34 | assign if_to_id_bus = {if_pc, inst}; 35 | 36 | // internal signals 37 | wire [31:0] seq_pc; 38 | wire [31:0] nextpc; 39 | 40 | // pipeline control 41 | reg if_valid; 42 | wire pre_if_valid; 43 | wire if_allow_in; 44 | wire if_ready_go; 45 | 46 | always @(posedge clk) begin 47 | if (reset) begin 48 | if_valid <= 1'b0; 49 | end else if (if_allow_in) begin 50 | if_valid <= pre_if_valid; 51 | end else if (br_taken_cancel) begin 52 | if_valid <= 1'b0; 53 | end 54 | end 55 | 56 | // pre-IF stage 57 | assign seq_pc = if_pc + 3'h4; 58 | assign nextpc = br_taken ? br_target : seq_pc; 59 | assign pre_if_valid = ~reset; // && if_allow_in; 60 | 61 | // IF stage 62 | assign if_ready_go = 1; 63 | assign if_to_id_valid = if_valid && if_ready_go; 64 | assign if_allow_in = !if_valid || (if_ready_go && id_allow_in); 65 | 66 | always @(posedge clk) begin 67 | if (reset) begin 68 | if_pc <= 32'h1bfffffc; //trick: to make nextpc be 0x1c000000 during reset 69 | end else if (if_allow_in && pre_if_valid) begin 70 | if_pc <= nextpc; 71 | end 72 | end 73 | 74 | assign inst_sram_en = pre_if_valid && if_allow_in; 75 | assign inst_sram_we = 4'b0000; 76 | assign inst_sram_addr = nextpc; 77 | assign inst_sram_wdata = 32'b0; 78 | assign inst = inst_sram_rdata; 79 | 80 | endmodule 81 | -------------------------------------------------------------------------------- /code/goal 09/if_stage.v: -------------------------------------------------------------------------------- 1 | `include "mycpu_top.h" 2 | 3 | module if_stage ( 4 | input clk, 5 | input reset, 6 | 7 | // pipeline control 8 | input id_allow_in, 9 | output if_to_id_valid, 10 | 11 | // bus to id 12 | output [`IF_TO_ID_BUS_WIDTH-1:0] if_to_id_bus, 13 | 14 | // bus from id 15 | input [`ID_TO_IF_BUS_WIDTH-1:0] id_to_if_bus, 16 | 17 | // cpu interface 18 | output inst_sram_en, 19 | output [ 3:0] inst_sram_we, 20 | output [31:0] inst_sram_addr, 21 | output [31:0] inst_sram_wdata, 22 | input [31:0] inst_sram_rdata 23 | ); 24 | 25 | // input bus from ID (for branch) 26 | wire br_taken; 27 | wire [31:0] br_target; 28 | wire br_taken_cancel; 29 | assign {br_taken, br_target, br_taken_cancel} = id_to_if_bus; 30 | 31 | // output bus to ID 32 | reg [31:0] if_pc; 33 | wire [31:0] inst; 34 | assign if_to_id_bus = {if_pc, inst}; 35 | 36 | // internal signals 37 | wire [31:0] seq_pc; 38 | wire [31:0] nextpc; 39 | 40 | // pipeline control 41 | reg if_valid; 42 | wire pre_if_valid; 43 | wire if_allow_in; 44 | wire if_ready_go; 45 | 46 | always @(posedge clk) begin 47 | if (reset) begin 48 | if_valid <= 1'b0; 49 | end else if (if_allow_in) begin 50 | if_valid <= pre_if_valid; 51 | end else if (br_taken_cancel) begin 52 | if_valid <= 1'b0; 53 | end 54 | end 55 | 56 | // pre-IF stage 57 | assign seq_pc = if_pc + 3'h4; 58 | assign nextpc = br_taken ? br_target : seq_pc; 59 | assign pre_if_valid = ~reset; // && if_allow_in; 60 | 61 | // IF stage 62 | assign if_ready_go = 1; 63 | assign if_to_id_valid = if_valid && if_ready_go; 64 | assign if_allow_in = !if_valid || (if_ready_go && id_allow_in); 65 | 66 | always @(posedge clk) begin 67 | if (reset) begin 68 | if_pc <= 32'h1bfffffc; //trick: to make nextpc be 0x1c000000 during reset 69 | end else if (if_allow_in && pre_if_valid) begin 70 | if_pc <= nextpc; 71 | end 72 | end 73 | 74 | assign inst_sram_en = pre_if_valid && if_allow_in; 75 | assign inst_sram_we = 4'b0000; 76 | assign inst_sram_addr = nextpc; 77 | assign inst_sram_wdata = 32'b0; 78 | assign inst = inst_sram_rdata; 79 | 80 | endmodule 81 | -------------------------------------------------------------------------------- /code/goal 07/exe_stage.v: -------------------------------------------------------------------------------- 1 | `include "mycpu_top.h" 2 | 3 | module exe_stage ( 4 | input clk, 5 | input reset, 6 | 7 | // pipeline control 8 | output exe_allow_in, 9 | input id_to_exe_valid, 10 | input mem_allow_in, 11 | output exe_to_mem_valid, 12 | 13 | // bus from id 14 | input [`ID_TO_EXE_BUS_WIDTH-1:0] id_to_exe_bus, 15 | 16 | // bus to mem 17 | output [`EXE_TO_MEM_BUS_WIDTH-1:0] exe_to_mem_bus, 18 | 19 | // cpu interface 20 | output data_sram_en, 21 | output [ 3:0] data_sram_we, 22 | output [31:0] data_sram_addr, 23 | output [31:0] data_sram_wdata 24 | ); 25 | 26 | // pipeline registers 27 | reg [`ID_TO_EXE_BUS_WIDTH-1:0] exe_reg; 28 | 29 | wire [31:0] exe_pc; 30 | wire [31:0] exe_rj_value; 31 | wire [31:0] exe_rkd_value; 32 | wire [31:0] exe_imm; 33 | wire [11:0] exe_alu_op; 34 | wire exe_src1_is_pc; 35 | wire exe_src2_is_imm; 36 | wire exe_res_from_mem; 37 | wire exe_reg_we; 38 | wire exe_mem_en; 39 | wire [3:0] exe_mem_we; 40 | wire [4:0] exe_reg_waddr; 41 | assign { 42 | exe_pc, 43 | exe_rj_value, 44 | exe_rkd_value, 45 | exe_imm, 46 | exe_alu_op, 47 | exe_src1_is_pc, 48 | exe_src2_is_imm, 49 | exe_res_from_mem, 50 | exe_reg_we, 51 | exe_mem_en, 52 | exe_mem_we, 53 | exe_reg_waddr 54 | } = exe_reg; 55 | 56 | // output bus to MEM 57 | wire [31:0] alu_result; 58 | assign exe_to_mem_bus = {exe_pc, alu_result, exe_res_from_mem, exe_reg_we, exe_reg_waddr}; 59 | 60 | // pipeline control 61 | reg exe_valid; 62 | wire exe_ready_go; 63 | 64 | assign exe_ready_go = 1; 65 | assign exe_allow_in = !exe_valid || (exe_ready_go && mem_allow_in); 66 | assign exe_to_mem_valid = exe_valid && exe_ready_go; 67 | 68 | always @(posedge clk) begin 69 | if (reset) begin 70 | exe_valid <= 1'b0; 71 | end else if (exe_allow_in) begin 72 | exe_valid <= id_to_exe_valid; 73 | end 74 | end 75 | 76 | always @(posedge clk) begin 77 | if (exe_allow_in && id_to_exe_valid) begin 78 | exe_reg <= id_to_exe_bus; 79 | end 80 | end 81 | 82 | // internal signals 83 | wire [11:0] alu_op; 84 | wire [31:0] alu_src1; 85 | wire [31:0] alu_src2; 86 | // wire [31:0] alu_result; 87 | 88 | // EXE stage 89 | assign alu_op = exe_alu_op; 90 | assign alu_src1 = exe_src1_is_pc ? exe_pc : exe_rj_value; 91 | assign alu_src2 = exe_src2_is_imm ? exe_imm : exe_rkd_value; 92 | 93 | alu u_alu ( 94 | .alu_op (alu_op), 95 | .alu_src1 (alu_src1), 96 | .alu_src2 (alu_src2), 97 | .alu_result(alu_result) 98 | ); 99 | 100 | assign data_sram_en = exe_mem_en && exe_valid; 101 | assign data_sram_we = exe_mem_we; 102 | assign data_sram_addr = data_sram_en ? alu_result : 32'b0; 103 | assign data_sram_wdata = exe_rkd_value; 104 | 105 | endmodule 106 | -------------------------------------------------------------------------------- /code/goal 08/exe_stage.v: -------------------------------------------------------------------------------- 1 | `include "mycpu_top.h" 2 | 3 | module exe_stage ( 4 | input clk, 5 | input reset, 6 | 7 | // pipeline control 8 | output exe_allow_in, 9 | input id_to_exe_valid, 10 | input mem_allow_in, 11 | output exe_to_mem_valid, 12 | 13 | // hazard detection 14 | output exe_rf_we, 15 | output [4:0] exe_rf_waddr, 16 | output reg exe_valid, 17 | 18 | // bus from id 19 | input [`ID_TO_EXE_BUS_WIDTH-1:0] id_to_exe_bus, 20 | 21 | // bus to mem 22 | output [`EXE_TO_MEM_BUS_WIDTH-1:0] exe_to_mem_bus, 23 | 24 | // cpu interface 25 | output data_sram_en, 26 | output [ 3:0] data_sram_we, 27 | output [31:0] data_sram_addr, 28 | output [31:0] data_sram_wdata 29 | ); 30 | 31 | // pipeline registers 32 | reg [`ID_TO_EXE_BUS_WIDTH-1:0] exe_reg; 33 | 34 | wire [31:0] exe_pc; 35 | wire [31:0] exe_rj_value; 36 | wire [31:0] exe_rkd_value; 37 | wire [31:0] exe_imm; 38 | wire [11:0] exe_alu_op; 39 | wire exe_src1_is_pc; 40 | wire exe_src2_is_imm; 41 | wire exe_res_from_mem; 42 | wire exe_reg_we; 43 | wire exe_mem_en; 44 | wire [3:0] exe_mem_we; 45 | wire [4:0] exe_reg_waddr; 46 | assign { 47 | exe_pc, 48 | exe_rj_value, 49 | exe_rkd_value, 50 | exe_imm, 51 | exe_alu_op, 52 | exe_src1_is_pc, 53 | exe_src2_is_imm, 54 | exe_res_from_mem, 55 | exe_reg_we, 56 | exe_mem_en, 57 | exe_mem_we, 58 | exe_reg_waddr 59 | } = exe_reg; 60 | 61 | // output bus to MEM 62 | wire [31:0] alu_result; 63 | assign exe_to_mem_bus = {exe_pc, alu_result, exe_res_from_mem, exe_reg_we, exe_reg_waddr}; 64 | 65 | // pipeline control 66 | // reg exe_valid; 67 | wire exe_ready_go; 68 | 69 | assign exe_ready_go = 1; 70 | assign exe_allow_in = !exe_valid || (exe_ready_go && mem_allow_in); 71 | assign exe_to_mem_valid = exe_valid && exe_ready_go; 72 | 73 | always @(posedge clk) begin 74 | if (reset) begin 75 | exe_valid <= 1'b0; 76 | end else if (exe_allow_in) begin 77 | exe_valid <= id_to_exe_valid; 78 | end 79 | end 80 | 81 | always @(posedge clk) begin 82 | if (exe_allow_in && id_to_exe_valid) begin 83 | exe_reg <= id_to_exe_bus; 84 | end 85 | end 86 | 87 | // internal signals 88 | wire [11:0] alu_op; 89 | wire [31:0] alu_src1; 90 | wire [31:0] alu_src2; 91 | // wire [31:0] alu_result; 92 | 93 | // EXE stage 94 | assign alu_op = exe_alu_op; 95 | assign alu_src1 = exe_src1_is_pc ? exe_pc : exe_rj_value; 96 | assign alu_src2 = exe_src2_is_imm ? exe_imm : exe_rkd_value; 97 | 98 | alu u_alu ( 99 | .alu_op (alu_op), 100 | .alu_src1 (alu_src1), 101 | .alu_src2 (alu_src2), 102 | .alu_result(alu_result) 103 | ); 104 | 105 | assign data_sram_en = exe_mem_en && exe_valid; 106 | assign data_sram_we = exe_mem_we; 107 | assign data_sram_addr = data_sram_en ? alu_result : 32'b0; 108 | assign data_sram_wdata = exe_rkd_value; 109 | 110 | // hazard detection 111 | assign exe_rf_we = exe_reg_we; 112 | assign exe_rf_waddr = exe_reg_waddr; 113 | 114 | endmodule 115 | -------------------------------------------------------------------------------- /code/goal 09/exe_stage.v: -------------------------------------------------------------------------------- 1 | `include "mycpu_top.h" 2 | 3 | module exe_stage ( 4 | input clk, 5 | input reset, 6 | 7 | // pipeline control 8 | output exe_allow_in, 9 | input id_to_exe_valid, 10 | input mem_allow_in, 11 | output exe_to_mem_valid, 12 | 13 | // hazard detection && bypass 14 | output reg exe_valid, 15 | output [`BYPASS_BUS_WIDTH-1:0] exe_to_id_bypass_bus, 16 | output exe_is_load, 17 | 18 | // bus from id 19 | input [`ID_TO_EXE_BUS_WIDTH-1:0] id_to_exe_bus, 20 | 21 | // bus to mem 22 | output [`EXE_TO_MEM_BUS_WIDTH-1:0] exe_to_mem_bus, 23 | 24 | // cpu interface 25 | output data_sram_en, 26 | output [ 3:0] data_sram_we, 27 | output [31:0] data_sram_addr, 28 | output [31:0] data_sram_wdata 29 | ); 30 | 31 | // pipeline registers 32 | reg [`ID_TO_EXE_BUS_WIDTH-1:0] exe_reg; 33 | 34 | wire [31:0] exe_pc; 35 | wire [31:0] exe_rj_value; 36 | wire [31:0] exe_rkd_value; 37 | wire [31:0] exe_imm; 38 | wire [11:0] exe_alu_op; 39 | wire exe_src1_is_pc; 40 | wire exe_src2_is_imm; 41 | wire exe_res_from_mem; 42 | wire exe_reg_we; 43 | wire exe_mem_en; 44 | wire [3:0] exe_mem_we; 45 | wire [4:0] exe_reg_waddr; 46 | assign { 47 | exe_pc, 48 | exe_rj_value, 49 | exe_rkd_value, 50 | exe_imm, 51 | exe_alu_op, 52 | exe_src1_is_pc, 53 | exe_src2_is_imm, 54 | exe_res_from_mem, 55 | exe_reg_we, 56 | exe_mem_en, 57 | exe_mem_we, 58 | exe_reg_waddr 59 | } = exe_reg; 60 | 61 | // output bus to MEM 62 | wire [31:0] alu_result; 63 | assign exe_to_mem_bus = {exe_pc, alu_result, exe_res_from_mem, exe_reg_we, exe_reg_waddr}; 64 | 65 | // pipeline control 66 | // reg exe_valid; 67 | wire exe_ready_go; 68 | 69 | assign exe_ready_go = 1; 70 | assign exe_allow_in = !exe_valid || (exe_ready_go && mem_allow_in); 71 | assign exe_to_mem_valid = exe_valid && exe_ready_go; 72 | 73 | always @(posedge clk) begin 74 | if (reset) begin 75 | exe_valid <= 1'b0; 76 | end else if (exe_allow_in) begin 77 | exe_valid <= id_to_exe_valid; 78 | end 79 | end 80 | 81 | always @(posedge clk) begin 82 | if (exe_allow_in && id_to_exe_valid) begin 83 | exe_reg <= id_to_exe_bus; 84 | end 85 | end 86 | 87 | // internal signals 88 | wire [11:0] alu_op; 89 | wire [31:0] alu_src1; 90 | wire [31:0] alu_src2; 91 | // wire [31:0] alu_result; 92 | 93 | // EXE stage 94 | assign alu_op = exe_alu_op; 95 | assign alu_src1 = exe_src1_is_pc ? exe_pc : exe_rj_value; 96 | assign alu_src2 = exe_src2_is_imm ? exe_imm : exe_rkd_value; 97 | 98 | alu u_alu ( 99 | .alu_op (alu_op), 100 | .alu_src1 (alu_src1), 101 | .alu_src2 (alu_src2), 102 | .alu_result(alu_result) 103 | ); 104 | 105 | assign data_sram_en = exe_mem_en && exe_valid; 106 | assign data_sram_we = exe_mem_we; 107 | assign data_sram_addr = data_sram_en ? alu_result : 32'b0; 108 | assign data_sram_wdata = exe_rkd_value; 109 | 110 | // hazard detection && bypass to ID 111 | assign exe_to_id_bypass_bus = {exe_reg_we, exe_reg_waddr, alu_result}; 112 | assign exe_is_load = exe_mem_en && !exe_mem_we[0]; 113 | 114 | endmodule 115 | -------------------------------------------------------------------------------- /code/goal 06/alu.v: -------------------------------------------------------------------------------- 1 | module alu ( 2 | input wire [11:0] alu_op, 3 | input wire [31:0] alu_src1, 4 | input wire [31:0] alu_src2, 5 | output wire [31:0] alu_result 6 | ); 7 | 8 | wire op_add; //add operation 9 | wire op_sub; //sub operation 10 | wire op_slt; //signed compared and set less than 11 | wire op_sltu; //unsigned compared and set less than 12 | wire op_and; //bitwise and 13 | wire op_nor; //bitwise nor 14 | wire op_or; //bitwise or 15 | wire op_xor; //bitwise xor 16 | wire op_sll; //logic left shift 17 | wire op_srl; //logic right shift 18 | wire op_sra; //arithmetic right shift 19 | wire op_lui; //Load Upper Immediate 20 | 21 | // control code decomposition 22 | assign op_add = alu_op[0]; 23 | assign op_sub = alu_op[1]; 24 | assign op_slt = alu_op[2]; 25 | assign op_sltu = alu_op[3]; 26 | assign op_and = alu_op[4]; 27 | assign op_nor = alu_op[5]; 28 | assign op_or = alu_op[6]; 29 | assign op_xor = alu_op[7]; 30 | assign op_sll = alu_op[8]; 31 | assign op_srl = alu_op[9]; 32 | assign op_sra = alu_op[10]; 33 | assign op_lui = alu_op[11]; 34 | 35 | wire [31:0] add_sub_result; 36 | wire [31:0] slt_result; 37 | wire [31:0] sltu_result; 38 | wire [31:0] and_result; 39 | wire [31:0] nor_result; 40 | wire [31:0] or_result; 41 | wire [31:0] xor_result; 42 | wire [31:0] lui_result; 43 | wire [31:0] sll_result; 44 | wire [63:0] sr64_result; 45 | wire [31:0] sr_result; 46 | 47 | 48 | // 32-bit adder 49 | wire [31:0] adder_a; 50 | wire [31:0] adder_b; 51 | wire adder_cin; 52 | wire [31:0] adder_result; 53 | wire adder_cout; 54 | 55 | assign adder_a = alu_src1; 56 | assign adder_b = (op_sub | op_slt | op_sltu) ? ~alu_src2 : alu_src2; //src1 - src2 rj-rk 57 | assign adder_cin = (op_sub | op_slt | op_sltu) ? 1'b1 : 1'b0; 58 | assign {adder_cout, adder_result} = adder_a + adder_b + adder_cin; 59 | 60 | // ADD, SUB result 61 | assign add_sub_result = adder_result; 62 | 63 | // SLT result 64 | assign slt_result[31:1] = 31'b0; //rj < rk 1 65 | assign slt_result[0] = (alu_src1[31] & ~alu_src2[31]) 66 | | ((alu_src1[31] ~^ alu_src2[31]) & adder_result[31]); 67 | // 有符号数比较,如果rj的符号位为1,rk的符号位为0(即rj小于零,rk大于等于零),那么slt为1 68 | // 或者如果rj的符号位和rk的符号位相同,且rj-rk的符号位为1,那么slt为1 69 | 70 | // SLTU result 71 | assign sltu_result[31:1] = 31'b0; 72 | assign sltu_result[0] = ~adder_cout; 73 | // 无符号数比较,如果rj-rk的进位位为0,那么slt为1 74 | 75 | // bitwise operation 76 | assign and_result = alu_src1 & alu_src2; 77 | assign or_result = alu_src1 | alu_src2; // ! error 78 | assign nor_result = ~or_result; 79 | assign xor_result = alu_src1 ^ alu_src2; 80 | assign lui_result = alu_src2; 81 | 82 | // SLL result 83 | assign sll_result = alu_src1 << alu_src2[4:0]; //rj << i5 // ! error 84 | 85 | // SRL, SRA result 86 | assign sr64_result = {{32{op_sra & alu_src1[31]}}, alu_src1[31:0]} >> alu_src2[4:0]; //rj >> i5 // ! error 87 | 88 | assign sr_result = sr64_result[31:0]; // ! error 89 | 90 | // final result mux 91 | assign alu_result = ({32{op_add|op_sub}} & add_sub_result) 92 | | ({32{op_slt }} & slt_result) 93 | | ({32{op_sltu }} & sltu_result) 94 | | ({32{op_and }} & and_result) 95 | | ({32{op_nor }} & nor_result) 96 | | ({32{op_or }} & or_result) 97 | | ({32{op_xor }} & xor_result) 98 | | ({32{op_lui }} & lui_result) 99 | | ({32{op_sll }} & sll_result) 100 | | ({32{op_srl|op_sra}} & sr_result); 101 | 102 | endmodule 103 | -------------------------------------------------------------------------------- /code/goal 07/alu.v: -------------------------------------------------------------------------------- 1 | module alu ( 2 | input wire [11:0] alu_op, 3 | input wire [31:0] alu_src1, 4 | input wire [31:0] alu_src2, 5 | output wire [31:0] alu_result 6 | ); 7 | 8 | wire op_add; //add operation 9 | wire op_sub; //sub operation 10 | wire op_slt; //signed compared and set less than 11 | wire op_sltu; //unsigned compared and set less than 12 | wire op_and; //bitwise and 13 | wire op_nor; //bitwise nor 14 | wire op_or; //bitwise or 15 | wire op_xor; //bitwise xor 16 | wire op_sll; //logic left shift 17 | wire op_srl; //logic right shift 18 | wire op_sra; //arithmetic right shift 19 | wire op_lui; //Load Upper Immediate 20 | 21 | // control code decomposition 22 | assign op_add = alu_op[0]; 23 | assign op_sub = alu_op[1]; 24 | assign op_slt = alu_op[2]; 25 | assign op_sltu = alu_op[3]; 26 | assign op_and = alu_op[4]; 27 | assign op_nor = alu_op[5]; 28 | assign op_or = alu_op[6]; 29 | assign op_xor = alu_op[7]; 30 | assign op_sll = alu_op[8]; 31 | assign op_srl = alu_op[9]; 32 | assign op_sra = alu_op[10]; 33 | assign op_lui = alu_op[11]; 34 | 35 | wire [31:0] add_sub_result; 36 | wire [31:0] slt_result; 37 | wire [31:0] sltu_result; 38 | wire [31:0] and_result; 39 | wire [31:0] nor_result; 40 | wire [31:0] or_result; 41 | wire [31:0] xor_result; 42 | wire [31:0] lui_result; 43 | wire [31:0] sll_result; 44 | wire [63:0] sr64_result; 45 | wire [31:0] sr_result; 46 | 47 | 48 | // 32-bit adder 49 | wire [31:0] adder_a; 50 | wire [31:0] adder_b; 51 | wire adder_cin; 52 | wire [31:0] adder_result; 53 | wire adder_cout; 54 | 55 | assign adder_a = alu_src1; 56 | assign adder_b = (op_sub | op_slt | op_sltu) ? ~alu_src2 : alu_src2; //src1 - src2 rj-rk 57 | assign adder_cin = (op_sub | op_slt | op_sltu) ? 1'b1 : 1'b0; 58 | assign {adder_cout, adder_result} = adder_a + adder_b + adder_cin; 59 | 60 | // ADD, SUB result 61 | assign add_sub_result = adder_result; 62 | 63 | // SLT result 64 | assign slt_result[31:1] = 31'b0; //rj < rk 1 65 | assign slt_result[0] = (alu_src1[31] & ~alu_src2[31]) 66 | | ((alu_src1[31] ~^ alu_src2[31]) & adder_result[31]); 67 | // 有符号数比较,如果rj的符号位为1,rk的符号位为0(即rj小于零,rk大于等于零),那么slt为1 68 | // 或者如果rj的符号位和rk的符号位相同,且rj-rk的符号位为1,那么slt为1 69 | 70 | // SLTU result 71 | assign sltu_result[31:1] = 31'b0; 72 | assign sltu_result[0] = ~adder_cout; 73 | // 无符号数比较,如果rj-rk的进位位为0,那么slt为1 74 | 75 | // bitwise operation 76 | assign and_result = alu_src1 & alu_src2; 77 | assign or_result = alu_src1 | alu_src2; // ! error 78 | assign nor_result = ~or_result; 79 | assign xor_result = alu_src1 ^ alu_src2; 80 | assign lui_result = alu_src2; 81 | 82 | // SLL result 83 | assign sll_result = alu_src1 << alu_src2[4:0]; //rj << i5 // ! error 84 | 85 | // SRL, SRA result 86 | assign sr64_result = {{32{op_sra & alu_src1[31]}}, alu_src1[31:0]} >> alu_src2[4:0]; //rj >> i5 // ! error 87 | 88 | assign sr_result = sr64_result[31:0]; // ! error 89 | 90 | // final result mux 91 | assign alu_result = ({32{op_add|op_sub}} & add_sub_result) 92 | | ({32{op_slt }} & slt_result) 93 | | ({32{op_sltu }} & sltu_result) 94 | | ({32{op_and }} & and_result) 95 | | ({32{op_nor }} & nor_result) 96 | | ({32{op_or }} & or_result) 97 | | ({32{op_xor }} & xor_result) 98 | | ({32{op_lui }} & lui_result) 99 | | ({32{op_sll }} & sll_result) 100 | | ({32{op_srl|op_sra}} & sr_result); 101 | 102 | endmodule 103 | -------------------------------------------------------------------------------- /code/goal 08/alu.v: -------------------------------------------------------------------------------- 1 | module alu ( 2 | input wire [11:0] alu_op, 3 | input wire [31:0] alu_src1, 4 | input wire [31:0] alu_src2, 5 | output wire [31:0] alu_result 6 | ); 7 | 8 | wire op_add; //add operation 9 | wire op_sub; //sub operation 10 | wire op_slt; //signed compared and set less than 11 | wire op_sltu; //unsigned compared and set less than 12 | wire op_and; //bitwise and 13 | wire op_nor; //bitwise nor 14 | wire op_or; //bitwise or 15 | wire op_xor; //bitwise xor 16 | wire op_sll; //logic left shift 17 | wire op_srl; //logic right shift 18 | wire op_sra; //arithmetic right shift 19 | wire op_lui; //Load Upper Immediate 20 | 21 | // control code decomposition 22 | assign op_add = alu_op[0]; 23 | assign op_sub = alu_op[1]; 24 | assign op_slt = alu_op[2]; 25 | assign op_sltu = alu_op[3]; 26 | assign op_and = alu_op[4]; 27 | assign op_nor = alu_op[5]; 28 | assign op_or = alu_op[6]; 29 | assign op_xor = alu_op[7]; 30 | assign op_sll = alu_op[8]; 31 | assign op_srl = alu_op[9]; 32 | assign op_sra = alu_op[10]; 33 | assign op_lui = alu_op[11]; 34 | 35 | wire [31:0] add_sub_result; 36 | wire [31:0] slt_result; 37 | wire [31:0] sltu_result; 38 | wire [31:0] and_result; 39 | wire [31:0] nor_result; 40 | wire [31:0] or_result; 41 | wire [31:0] xor_result; 42 | wire [31:0] lui_result; 43 | wire [31:0] sll_result; 44 | wire [63:0] sr64_result; 45 | wire [31:0] sr_result; 46 | 47 | 48 | // 32-bit adder 49 | wire [31:0] adder_a; 50 | wire [31:0] adder_b; 51 | wire adder_cin; 52 | wire [31:0] adder_result; 53 | wire adder_cout; 54 | 55 | assign adder_a = alu_src1; 56 | assign adder_b = (op_sub | op_slt | op_sltu) ? ~alu_src2 : alu_src2; //src1 - src2 rj-rk 57 | assign adder_cin = (op_sub | op_slt | op_sltu) ? 1'b1 : 1'b0; 58 | assign {adder_cout, adder_result} = adder_a + adder_b + adder_cin; 59 | 60 | // ADD, SUB result 61 | assign add_sub_result = adder_result; 62 | 63 | // SLT result 64 | assign slt_result[31:1] = 31'b0; //rj < rk 1 65 | assign slt_result[0] = (alu_src1[31] & ~alu_src2[31]) 66 | | ((alu_src1[31] ~^ alu_src2[31]) & adder_result[31]); 67 | // 有符号数比较,如果rj的符号位为1,rk的符号位为0(即rj小于零,rk大于等于零),那么slt为1 68 | // 或者如果rj的符号位和rk的符号位相同,且rj-rk的符号位为1,那么slt为1 69 | 70 | // SLTU result 71 | assign sltu_result[31:1] = 31'b0; 72 | assign sltu_result[0] = ~adder_cout; 73 | // 无符号数比较,如果rj-rk的进位位为0,那么slt为1 74 | 75 | // bitwise operation 76 | assign and_result = alu_src1 & alu_src2; 77 | assign or_result = alu_src1 | alu_src2; // ! error 78 | assign nor_result = ~or_result; 79 | assign xor_result = alu_src1 ^ alu_src2; 80 | assign lui_result = alu_src2; 81 | 82 | // SLL result 83 | assign sll_result = alu_src1 << alu_src2[4:0]; //rj << i5 // ! error 84 | 85 | // SRL, SRA result 86 | assign sr64_result = {{32{op_sra & alu_src1[31]}}, alu_src1[31:0]} >> alu_src2[4:0]; //rj >> i5 // ! error 87 | 88 | assign sr_result = sr64_result[31:0]; // ! error 89 | 90 | // final result mux 91 | assign alu_result = ({32{op_add|op_sub}} & add_sub_result) 92 | | ({32{op_slt }} & slt_result) 93 | | ({32{op_sltu }} & sltu_result) 94 | | ({32{op_and }} & and_result) 95 | | ({32{op_nor }} & nor_result) 96 | | ({32{op_or }} & or_result) 97 | | ({32{op_xor }} & xor_result) 98 | | ({32{op_lui }} & lui_result) 99 | | ({32{op_sll }} & sll_result) 100 | | ({32{op_srl|op_sra}} & sr_result); 101 | 102 | endmodule 103 | -------------------------------------------------------------------------------- /code/goal 09/alu.v: -------------------------------------------------------------------------------- 1 | module alu ( 2 | input wire [11:0] alu_op, 3 | input wire [31:0] alu_src1, 4 | input wire [31:0] alu_src2, 5 | output wire [31:0] alu_result 6 | ); 7 | 8 | wire op_add; //add operation 9 | wire op_sub; //sub operation 10 | wire op_slt; //signed compared and set less than 11 | wire op_sltu; //unsigned compared and set less than 12 | wire op_and; //bitwise and 13 | wire op_nor; //bitwise nor 14 | wire op_or; //bitwise or 15 | wire op_xor; //bitwise xor 16 | wire op_sll; //logic left shift 17 | wire op_srl; //logic right shift 18 | wire op_sra; //arithmetic right shift 19 | wire op_lui; //Load Upper Immediate 20 | 21 | // control code decomposition 22 | assign op_add = alu_op[0]; 23 | assign op_sub = alu_op[1]; 24 | assign op_slt = alu_op[2]; 25 | assign op_sltu = alu_op[3]; 26 | assign op_and = alu_op[4]; 27 | assign op_nor = alu_op[5]; 28 | assign op_or = alu_op[6]; 29 | assign op_xor = alu_op[7]; 30 | assign op_sll = alu_op[8]; 31 | assign op_srl = alu_op[9]; 32 | assign op_sra = alu_op[10]; 33 | assign op_lui = alu_op[11]; 34 | 35 | wire [31:0] add_sub_result; 36 | wire [31:0] slt_result; 37 | wire [31:0] sltu_result; 38 | wire [31:0] and_result; 39 | wire [31:0] nor_result; 40 | wire [31:0] or_result; 41 | wire [31:0] xor_result; 42 | wire [31:0] lui_result; 43 | wire [31:0] sll_result; 44 | wire [63:0] sr64_result; 45 | wire [31:0] sr_result; 46 | 47 | 48 | // 32-bit adder 49 | wire [31:0] adder_a; 50 | wire [31:0] adder_b; 51 | wire adder_cin; 52 | wire [31:0] adder_result; 53 | wire adder_cout; 54 | 55 | assign adder_a = alu_src1; 56 | assign adder_b = (op_sub | op_slt | op_sltu) ? ~alu_src2 : alu_src2; //src1 - src2 rj-rk 57 | assign adder_cin = (op_sub | op_slt | op_sltu) ? 1'b1 : 1'b0; 58 | assign {adder_cout, adder_result} = adder_a + adder_b + adder_cin; 59 | 60 | // ADD, SUB result 61 | assign add_sub_result = adder_result; 62 | 63 | // SLT result 64 | assign slt_result[31:1] = 31'b0; //rj < rk 1 65 | assign slt_result[0] = (alu_src1[31] & ~alu_src2[31]) 66 | | ((alu_src1[31] ~^ alu_src2[31]) & adder_result[31]); 67 | // 有符号数比较,如果rj的符号位为1,rk的符号位为0(即rj小于零,rk大于等于零),那么slt为1 68 | // 或者如果rj的符号位和rk的符号位相同,且rj-rk的符号位为1,那么slt为1 69 | 70 | // SLTU result 71 | assign sltu_result[31:1] = 31'b0; 72 | assign sltu_result[0] = ~adder_cout; 73 | // 无符号数比较,如果rj-rk的进位位为0,那么slt为1 74 | 75 | // bitwise operation 76 | assign and_result = alu_src1 & alu_src2; 77 | assign or_result = alu_src1 | alu_src2; // ! error 78 | assign nor_result = ~or_result; 79 | assign xor_result = alu_src1 ^ alu_src2; 80 | assign lui_result = alu_src2; 81 | 82 | // SLL result 83 | assign sll_result = alu_src1 << alu_src2[4:0]; //rj << i5 // ! error 84 | 85 | // SRL, SRA result 86 | assign sr64_result = {{32{op_sra & alu_src1[31]}}, alu_src1[31:0]} >> alu_src2[4:0]; //rj >> i5 // ! error 87 | 88 | assign sr_result = sr64_result[31:0]; // ! error 89 | 90 | // final result mux 91 | assign alu_result = ({32{op_add|op_sub}} & add_sub_result) 92 | | ({32{op_slt }} & slt_result) 93 | | ({32{op_sltu }} & sltu_result) 94 | | ({32{op_and }} & and_result) 95 | | ({32{op_nor }} & nor_result) 96 | | ({32{op_or }} & or_result) 97 | | ({32{op_xor }} & xor_result) 98 | | ({32{op_lui }} & lui_result) 99 | | ({32{op_sll }} & sll_result) 100 | | ({32{op_srl|op_sra}} & sr_result); 101 | 102 | endmodule 103 | -------------------------------------------------------------------------------- /code/goal 07/mycpu_top.v: -------------------------------------------------------------------------------- 1 | `include "mycpu_top.h" 2 | 3 | module mycpu_top ( 4 | input wire clk, 5 | input wire resetn, 6 | // inst sram interface 7 | output wire inst_sram_en, 8 | output wire [ 3:0] inst_sram_we, 9 | output wire [31:0] inst_sram_addr, 10 | output wire [31:0] inst_sram_wdata, 11 | input wire [31:0] inst_sram_rdata, 12 | // data sram interface 13 | output wire data_sram_en, 14 | output wire [ 3:0] data_sram_we, 15 | output wire [31:0] data_sram_addr, 16 | output wire [31:0] data_sram_wdata, 17 | input wire [31:0] data_sram_rdata, 18 | // trace debug interface 19 | output wire [31:0] debug_wb_pc, 20 | output wire [ 3:0] debug_wb_rf_we, 21 | output wire [ 4:0] debug_wb_rf_wnum, 22 | output wire [31:0] debug_wb_rf_wdata 23 | ); 24 | reg reset; 25 | always @(posedge clk) reset <= ~resetn; 26 | 27 | reg valid; 28 | always @(posedge clk) begin 29 | if (reset) begin 30 | valid <= 1'b0; 31 | end else begin 32 | valid <= 1'b1; 33 | end 34 | end 35 | 36 | // IF 37 | wire if_to_id_valid; 38 | wire [`IF_TO_ID_BUS_WIDTH-1:0] if_to_id_bus; 39 | 40 | // ID 41 | wire id_allow_in; 42 | wire id_to_exe_valid; 43 | wire [`ID_TO_EXE_BUS_WIDTH-1:0] id_to_exe_bus; 44 | wire [`ID_TO_IF_BUS_WIDTH-1:0] id_to_if_bus; 45 | 46 | // EXE 47 | wire exe_allow_in; 48 | wire exe_to_mem_valid; 49 | wire [`EXE_TO_MEM_BUS_WIDTH-1:0] exe_to_mem_bus; 50 | 51 | // MEM 52 | wire mem_allow_in; 53 | wire mem_to_wb_valid; 54 | wire [`MEM_TO_WB_BUS_WIDTH-1:0] mem_to_wb_bus; 55 | 56 | // WB 57 | wire wb_allow_in; 58 | wire [`WB_TO_ID_BUS_WIDTH-1:0] wb_to_id_bus; 59 | 60 | if_stage if_stage ( 61 | .clk(clk), 62 | .reset(reset), 63 | .id_allow_in(id_allow_in), 64 | .if_to_id_valid(if_to_id_valid), 65 | .if_to_id_bus(if_to_id_bus), 66 | .id_to_if_bus(id_to_if_bus), 67 | .inst_sram_en(inst_sram_en), 68 | .inst_sram_we(inst_sram_we), 69 | .inst_sram_addr(inst_sram_addr), 70 | .inst_sram_wdata(inst_sram_wdata), 71 | .inst_sram_rdata(inst_sram_rdata) 72 | ); 73 | 74 | id_stage id_stage ( 75 | .clk(clk), 76 | .reset(reset), 77 | .id_allow_in(id_allow_in), 78 | .if_to_id_valid(if_to_id_valid), 79 | .exe_allow_in(exe_allow_in), 80 | .id_to_exe_valid(id_to_exe_valid), 81 | .if_to_id_bus(if_to_id_bus), 82 | .id_to_exe_bus(id_to_exe_bus), 83 | .id_to_if_bus(id_to_if_bus), 84 | .wb_to_id_bus(wb_to_id_bus) 85 | ); 86 | 87 | exe_stage exe_stage ( 88 | .clk(clk), 89 | .reset(reset), 90 | .exe_allow_in(exe_allow_in), 91 | .id_to_exe_valid(id_to_exe_valid), 92 | .mem_allow_in(mem_allow_in), 93 | .exe_to_mem_valid(exe_to_mem_valid), 94 | .id_to_exe_bus(id_to_exe_bus), 95 | .exe_to_mem_bus(exe_to_mem_bus), 96 | .data_sram_en(data_sram_en), 97 | .data_sram_we(data_sram_we), 98 | .data_sram_addr(data_sram_addr), 99 | .data_sram_wdata(data_sram_wdata) 100 | ); 101 | 102 | mem_stage mem_stage ( 103 | .clk(clk), 104 | .reset(reset), 105 | .mem_allow_in(mem_allow_in), 106 | .exe_to_mem_valid(exe_to_mem_valid), 107 | .wb_allow_in(wb_allow_in), 108 | .mem_to_wb_valid(mem_to_wb_valid), 109 | .exe_to_mem_bus(exe_to_mem_bus), 110 | .mem_to_wb_bus(mem_to_wb_bus), 111 | .data_sram_rdata(data_sram_rdata) 112 | ); 113 | 114 | wb_stage wb_stage ( 115 | .clk(clk), 116 | .reset(reset), 117 | .wb_allow_in(wb_allow_in), 118 | .mem_to_wb_valid(mem_to_wb_valid), 119 | .mem_to_wb_bus(mem_to_wb_bus), 120 | .wb_to_id_bus(wb_to_id_bus), 121 | .debug_wb_pc(debug_wb_pc), 122 | .debug_wb_rf_we(debug_wb_rf_we), 123 | .debug_wb_rf_wnum(debug_wb_rf_wnum), 124 | .debug_wb_rf_wdata(debug_wb_rf_wdata) 125 | ); 126 | 127 | endmodule 128 | -------------------------------------------------------------------------------- /code/goal 08/mycpu_top.v: -------------------------------------------------------------------------------- 1 | `include "mycpu_top.h" 2 | 3 | module mycpu_top ( 4 | input wire clk, 5 | input wire resetn, 6 | // inst sram interface 7 | output wire inst_sram_en, 8 | output wire [ 3:0] inst_sram_we, 9 | output wire [31:0] inst_sram_addr, 10 | output wire [31:0] inst_sram_wdata, 11 | input wire [31:0] inst_sram_rdata, 12 | // data sram interface 13 | output wire data_sram_en, 14 | output wire [ 3:0] data_sram_we, 15 | output wire [31:0] data_sram_addr, 16 | output wire [31:0] data_sram_wdata, 17 | input wire [31:0] data_sram_rdata, 18 | // trace debug interface 19 | output wire [31:0] debug_wb_pc, 20 | output wire [ 3:0] debug_wb_rf_we, 21 | output wire [ 4:0] debug_wb_rf_wnum, 22 | output wire [31:0] debug_wb_rf_wdata 23 | ); 24 | reg reset; 25 | always @(posedge clk) reset <= ~resetn; 26 | 27 | reg valid; 28 | always @(posedge clk) begin 29 | if (reset) begin 30 | valid <= 1'b0; 31 | end else begin 32 | valid <= 1'b1; 33 | end 34 | end 35 | 36 | // IF 37 | wire if_to_id_valid; 38 | wire [`IF_TO_ID_BUS_WIDTH-1:0] if_to_id_bus; 39 | 40 | // ID 41 | wire id_allow_in; 42 | wire id_to_exe_valid; 43 | wire [`ID_TO_EXE_BUS_WIDTH-1:0] id_to_exe_bus; 44 | wire [`ID_TO_IF_BUS_WIDTH-1:0] id_to_if_bus; 45 | 46 | // EXE 47 | wire exe_allow_in; 48 | wire exe_to_mem_valid; 49 | wire [`EXE_TO_MEM_BUS_WIDTH-1:0] exe_to_mem_bus; 50 | wire exe_rf_we; 51 | wire [4:0] exe_rf_waddr; 52 | wire exe_valid; 53 | 54 | // MEM 55 | wire mem_allow_in; 56 | wire mem_to_wb_valid; 57 | wire [`MEM_TO_WB_BUS_WIDTH-1:0] mem_to_wb_bus; 58 | wire mem_rf_we; 59 | wire [4:0] mem_rf_waddr; 60 | wire mem_valid; 61 | 62 | // WB 63 | wire wb_allow_in; 64 | wire [`WB_TO_ID_BUS_WIDTH-1:0] wb_to_id_bus; 65 | wire wb_valid; 66 | 67 | if_stage if_stage ( 68 | .clk(clk), 69 | .reset(reset), 70 | .id_allow_in(id_allow_in), 71 | .if_to_id_valid(if_to_id_valid), 72 | .if_to_id_bus(if_to_id_bus), 73 | .id_to_if_bus(id_to_if_bus), 74 | .inst_sram_en(inst_sram_en), 75 | .inst_sram_we(inst_sram_we), 76 | .inst_sram_addr(inst_sram_addr), 77 | .inst_sram_wdata(inst_sram_wdata), 78 | .inst_sram_rdata(inst_sram_rdata) 79 | ); 80 | 81 | id_stage id_stage ( 82 | .clk(clk), 83 | .reset(reset), 84 | .id_allow_in(id_allow_in), 85 | .if_to_id_valid(if_to_id_valid), 86 | .exe_allow_in(exe_allow_in), 87 | .id_to_exe_valid(id_to_exe_valid), 88 | .exe_rf_we(exe_rf_we), 89 | .exe_rf_waddr(exe_rf_waddr), 90 | .exe_valid(exe_valid), 91 | .mem_rf_we(mem_rf_we), 92 | .mem_rf_waddr(mem_rf_waddr), 93 | .mem_valid(mem_valid), 94 | .wb_valid(wb_valid), 95 | .if_to_id_bus(if_to_id_bus), 96 | .id_to_exe_bus(id_to_exe_bus), 97 | .id_to_if_bus(id_to_if_bus), 98 | .wb_to_id_bus(wb_to_id_bus) 99 | ); 100 | 101 | exe_stage exe_stage ( 102 | .clk(clk), 103 | .reset(reset), 104 | .exe_allow_in(exe_allow_in), 105 | .id_to_exe_valid(id_to_exe_valid), 106 | .mem_allow_in(mem_allow_in), 107 | .exe_to_mem_valid(exe_to_mem_valid), 108 | .exe_rf_we(exe_rf_we), 109 | .exe_rf_waddr(exe_rf_waddr), 110 | .exe_valid(exe_valid), 111 | .id_to_exe_bus(id_to_exe_bus), 112 | .exe_to_mem_bus(exe_to_mem_bus), 113 | .data_sram_en(data_sram_en), 114 | .data_sram_we(data_sram_we), 115 | .data_sram_addr(data_sram_addr), 116 | .data_sram_wdata(data_sram_wdata) 117 | ); 118 | 119 | mem_stage mem_stage ( 120 | .clk(clk), 121 | .reset(reset), 122 | .mem_allow_in(mem_allow_in), 123 | .exe_to_mem_valid(exe_to_mem_valid), 124 | .wb_allow_in(wb_allow_in), 125 | .mem_to_wb_valid(mem_to_wb_valid), 126 | .mem_rf_we(mem_rf_we), 127 | .mem_rf_waddr(mem_rf_waddr), 128 | .mem_valid(mem_valid), 129 | .exe_to_mem_bus(exe_to_mem_bus), 130 | .mem_to_wb_bus(mem_to_wb_bus), 131 | .data_sram_rdata(data_sram_rdata) 132 | ); 133 | 134 | wb_stage wb_stage ( 135 | .clk(clk), 136 | .reset(reset), 137 | .wb_allow_in(wb_allow_in), 138 | .mem_to_wb_valid(mem_to_wb_valid), 139 | .wb_valid(wb_valid), 140 | .mem_to_wb_bus(mem_to_wb_bus), 141 | .wb_to_id_bus(wb_to_id_bus), 142 | .debug_wb_pc(debug_wb_pc), 143 | .debug_wb_rf_we(debug_wb_rf_we), 144 | .debug_wb_rf_wnum(debug_wb_rf_wnum), 145 | .debug_wb_rf_wdata(debug_wb_rf_wdata) 146 | ); 147 | 148 | endmodule 149 | -------------------------------------------------------------------------------- /code/goal 09/mycpu_top.v: -------------------------------------------------------------------------------- 1 | `include "mycpu_top.h" 2 | 3 | module mycpu_top ( 4 | input wire clk, 5 | input wire resetn, 6 | // inst sram interface 7 | output wire inst_sram_en, 8 | output wire [ 3:0] inst_sram_we, 9 | output wire [31:0] inst_sram_addr, 10 | output wire [31:0] inst_sram_wdata, 11 | input wire [31:0] inst_sram_rdata, 12 | // data sram interface 13 | output wire data_sram_en, 14 | output wire [ 3:0] data_sram_we, 15 | output wire [31:0] data_sram_addr, 16 | output wire [31:0] data_sram_wdata, 17 | input wire [31:0] data_sram_rdata, 18 | // trace debug interface 19 | output wire [31:0] debug_wb_pc, 20 | output wire [ 3:0] debug_wb_rf_we, 21 | output wire [ 4:0] debug_wb_rf_wnum, 22 | output wire [31:0] debug_wb_rf_wdata 23 | ); 24 | reg reset; 25 | always @(posedge clk) reset <= ~resetn; 26 | 27 | reg valid; 28 | always @(posedge clk) begin 29 | if (reset) begin 30 | valid <= 1'b0; 31 | end else begin 32 | valid <= 1'b1; 33 | end 34 | end 35 | 36 | // IF 37 | wire if_to_id_valid; 38 | wire [`IF_TO_ID_BUS_WIDTH-1:0] if_to_id_bus; 39 | 40 | // ID 41 | wire id_allow_in; 42 | wire id_to_exe_valid; 43 | wire [`ID_TO_EXE_BUS_WIDTH-1:0] id_to_exe_bus; 44 | wire [`ID_TO_IF_BUS_WIDTH-1:0] id_to_if_bus; 45 | 46 | // EXE 47 | wire exe_allow_in; 48 | wire exe_to_mem_valid; 49 | wire exe_valid; 50 | wire [`BYPASS_BUS_WIDTH-1:0] exe_to_id_bypass_bus; 51 | wire exe_is_load; 52 | wire [`EXE_TO_MEM_BUS_WIDTH-1:0] exe_to_mem_bus; 53 | 54 | // MEM 55 | wire mem_allow_in; 56 | wire mem_to_wb_valid; 57 | wire mem_valid; 58 | wire [`BYPASS_BUS_WIDTH-1:0] mem_to_id_bypass_bus; 59 | wire [`MEM_TO_WB_BUS_WIDTH-1:0] mem_to_wb_bus; 60 | 61 | // WB 62 | wire wb_allow_in; 63 | wire [`WB_TO_ID_BUS_WIDTH-1:0] wb_to_id_bus; 64 | wire wb_valid; 65 | 66 | if_stage if_stage ( 67 | .clk(clk), 68 | .reset(reset), 69 | .id_allow_in(id_allow_in), 70 | .if_to_id_valid(if_to_id_valid), 71 | .if_to_id_bus(if_to_id_bus), 72 | .id_to_if_bus(id_to_if_bus), 73 | .inst_sram_en(inst_sram_en), 74 | .inst_sram_we(inst_sram_we), 75 | .inst_sram_addr(inst_sram_addr), 76 | .inst_sram_wdata(inst_sram_wdata), 77 | .inst_sram_rdata(inst_sram_rdata) 78 | ); 79 | 80 | id_stage id_stage ( 81 | .clk(clk), 82 | .reset(reset), 83 | .id_allow_in(id_allow_in), 84 | .if_to_id_valid(if_to_id_valid), 85 | .exe_allow_in(exe_allow_in), 86 | .id_to_exe_valid(id_to_exe_valid), 87 | .exe_valid(exe_valid), 88 | .exe_to_id_bypass_bus(exe_to_id_bypass_bus), 89 | .exe_is_load(exe_is_load), 90 | .mem_valid(mem_valid), 91 | .mem_to_id_bypass_bus(mem_to_id_bypass_bus), 92 | .wb_valid(wb_valid), 93 | .if_to_id_bus(if_to_id_bus), 94 | .id_to_exe_bus(id_to_exe_bus), 95 | .id_to_if_bus(id_to_if_bus), 96 | .wb_to_id_bus(wb_to_id_bus) 97 | ); 98 | 99 | exe_stage exe_stage ( 100 | .clk(clk), 101 | .reset(reset), 102 | .exe_allow_in(exe_allow_in), 103 | .id_to_exe_valid(id_to_exe_valid), 104 | .mem_allow_in(mem_allow_in), 105 | .exe_to_mem_valid(exe_to_mem_valid), 106 | .exe_valid(exe_valid), 107 | .exe_to_id_bypass_bus(exe_to_id_bypass_bus), 108 | .exe_is_load(exe_is_load), 109 | .id_to_exe_bus(id_to_exe_bus), 110 | .exe_to_mem_bus(exe_to_mem_bus), 111 | .data_sram_en(data_sram_en), 112 | .data_sram_we(data_sram_we), 113 | .data_sram_addr(data_sram_addr), 114 | .data_sram_wdata(data_sram_wdata) 115 | ); 116 | 117 | mem_stage mem_stage ( 118 | .clk(clk), 119 | .reset(reset), 120 | .mem_allow_in(mem_allow_in), 121 | .exe_to_mem_valid(exe_to_mem_valid), 122 | .wb_allow_in(wb_allow_in), 123 | .mem_to_wb_valid(mem_to_wb_valid), 124 | .mem_valid(mem_valid), 125 | .mem_to_id_bypass_bus(mem_to_id_bypass_bus), 126 | .exe_to_mem_bus(exe_to_mem_bus), 127 | .mem_to_wb_bus(mem_to_wb_bus), 128 | .data_sram_rdata(data_sram_rdata) 129 | ); 130 | 131 | wb_stage wb_stage ( 132 | .clk(clk), 133 | .reset(reset), 134 | .wb_allow_in(wb_allow_in), 135 | .mem_to_wb_valid(mem_to_wb_valid), 136 | .wb_valid(wb_valid), 137 | .mem_to_wb_bus(mem_to_wb_bus), 138 | .wb_to_id_bus(wb_to_id_bus), 139 | .debug_wb_pc(debug_wb_pc), 140 | .debug_wb_rf_we(debug_wb_rf_we), 141 | .debug_wb_rf_wnum(debug_wb_rf_wnum), 142 | .debug_wb_rf_wdata(debug_wb_rf_wdata) 143 | ); 144 | 145 | endmodule 146 | -------------------------------------------------------------------------------- /code/goal 05/minicpu_top.v: -------------------------------------------------------------------------------- 1 | module minicpu_top ( 2 | input wire clk, 3 | input wire resetn, 4 | 5 | output wire inst_sram_we, 6 | output wire [31:0] inst_sram_addr, 7 | output wire [31:0] inst_sram_wdata, 8 | input wire [31:0] inst_sram_rdata, 9 | 10 | output wire data_sram_we, 11 | output wire [31:0] data_sram_addr, 12 | output wire [31:0] data_sram_wdata, 13 | input wire [31:0] data_sram_rdata 14 | ); 15 | 16 | reg reset; 17 | always @(posedge clk) reset <= ~resetn; 18 | 19 | reg valid; 20 | always @(posedge clk) begin 21 | if (reset) begin 22 | valid <= 1'b0; 23 | end else begin 24 | valid <= 1'b1; 25 | end 26 | end 27 | 28 | reg [31:0] pc; 29 | wire [31:0] nextpc; // 下一个pc值,pc+4或分支目标地址 30 | 31 | wire [31:0] inst; 32 | 33 | wire [ 5:0] op_31_26; 34 | wire [ 3:0] op_25_22; 35 | wire [ 1:0] op_21_20; 36 | wire [ 4:0] op_19_15; 37 | wire [63:0] op_31_26_d; 38 | wire [15:0] op_25_22_d; 39 | wire [ 3:0] op_21_20_d; 40 | wire [31:0] op_19_15_d; 41 | wire [ 4:0] rd; 42 | wire [ 4:0] rj; 43 | wire [ 4:0] rk; 44 | wire [11:0] i12; 45 | wire [15:0] i16; 46 | 47 | wire inst_add_w; 48 | wire inst_addi_w; 49 | wire inst_ld_w; 50 | wire inst_st_w; 51 | wire inst_bne; 52 | 53 | wire src2_is_imm; // 第二个操作数是否是立即数 54 | wire res_from_mem; // 结果是否来自内存 55 | wire gr_we; // 是否写寄存器 56 | wire mem_we; // 是否写内存 57 | wire src_reg_is_rd; // 第二个操作数寄存器是否是rd 58 | wire [31:0] rj_value; 59 | wire [31:0] rkd_value; // rk或rd的值 60 | 61 | wire [ 4:0] rf_raddr1; 62 | wire [ 4:0] rf_raddr2; 63 | wire [31:0] rf_wdata; 64 | 65 | wire br_taken; // 是否分支 66 | wire rj_eq_rd; // rj是否等于rd 67 | wire [31:0] br_offs; // 分支偏移 68 | wire [31:0] br_target; // 分支目标地址 69 | 70 | wire [31:0] imm; 71 | wire [31:0] alu_src1; 72 | wire [31:0] alu_src2; 73 | wire [31:0] alu_result; 74 | 75 | 76 | always @(posedge clk) begin 77 | if (reset) begin 78 | pc <= 32'h1bfffffc; //trick: to make nextpc be 0x1c000000 during reset 79 | end else begin 80 | pc <= nextpc; 81 | end 82 | end 83 | 84 | assign inst_sram_we = 1'b0; 85 | assign inst_sram_addr = pc; 86 | assign inst_sram_wdata = 32'b0; 87 | assign inst = inst_sram_rdata; 88 | 89 | assign op_31_26 = inst[31:26]; 90 | assign op_25_22 = inst[25:22]; 91 | assign op_21_20 = inst[21:20]; 92 | assign op_19_15 = inst[19:15]; 93 | assign rd = inst[4:0]; 94 | assign rj = inst[9:5]; 95 | assign rk = inst[14:10]; 96 | assign i12 = inst[21:10]; 97 | assign i16 = inst[25:10]; 98 | 99 | decoder_6_64 u_dec0 ( 100 | .in(op_31_26), 101 | .co(op_31_26_d) 102 | ); 103 | decoder_4_16 u_dec1 ( 104 | .in(op_25_22), 105 | .co(op_25_22_d) 106 | ); 107 | decoder_2_4 u_dec2 ( 108 | .in(op_21_20), 109 | .co(op_21_20_d) 110 | ); 111 | decoder_5_32 u_dec3 ( 112 | .in(op_19_15), 113 | .co(op_19_15_d) 114 | ); 115 | 116 | assign inst_add_w = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h00]; 117 | assign inst_addi_w = op_31_26_d[6'h00] & op_25_22_d[4'ha]; 118 | assign inst_ld_w = op_31_26_d[6'h0a] & op_25_22_d[4'h2]; 119 | assign inst_st_w = op_31_26_d[6'h0a] & op_25_22_d[4'h6];//在这里实现inst_st_w指令的译码 120 | assign inst_bne = op_31_26_d[6'h17]; 121 | 122 | assign src2_is_imm = inst_addi_w | inst_ld_w | inst_st_w; //在这里实现立即数选择信号 123 | assign res_from_mem = inst_ld_w; 124 | assign gr_we = inst_add_w | inst_ld_w | inst_addi_w; 125 | assign mem_we = inst_st_w; 126 | assign src_reg_is_rd = inst_bne | inst_st_w; 127 | 128 | assign rf_raddr1 = rj; 129 | assign rf_raddr2 = src_reg_is_rd ? rd : rk; 130 | regfile u_regfile ( 131 | .clk (clk), 132 | .raddr1(rf_raddr1), 133 | .rdata1(rj_value), 134 | .raddr2(rf_raddr2), 135 | .rdata2(rkd_value), 136 | .we (gr_we), 137 | .waddr (rd), 138 | .wdata (rf_wdata) 139 | ); //在空出的括号里完成引脚匹配 140 | 141 | assign br_offs = {{14{i16[15]}}, i16[15:0], 2'b00}; //在这里完成br_offs信号的生成 142 | assign br_target = pc + br_offs; 143 | assign rj_eq_rd = (rj_value == rkd_value); 144 | assign br_taken = valid && inst_bne && !rj_eq_rd; 145 | assign nextpc = br_taken ? br_target : pc + 4; //在这里实现nextpc信号的生成 146 | 147 | assign imm = {{20{i12[11]}}, i12[11:0]}; 148 | assign alu_src1 = rj_value; 149 | assign alu_src2 = src2_is_imm ? imm : rkd_value; //在这里实现alu_src2信号 150 | 151 | assign alu_result = alu_src1 + alu_src2; 152 | 153 | assign data_sram_we = mem_we; 154 | assign data_sram_addr = alu_result; 155 | assign data_sram_wdata = rkd_value; 156 | 157 | assign rf_wdata = res_from_mem ? data_sram_rdata : alu_result;//在这里完成写回寄存器值的选择 158 | 159 | endmodule 160 | 161 | -------------------------------------------------------------------------------- /code/goal 07/id_stage.v: -------------------------------------------------------------------------------- 1 | `include "mycpu_top.h" 2 | 3 | module id_stage ( 4 | input clk, 5 | input reset, 6 | 7 | // pipeline control 8 | output id_allow_in, 9 | input if_to_id_valid, 10 | input exe_allow_in, 11 | output id_to_exe_valid, 12 | 13 | // bus from if 14 | input [`IF_TO_ID_BUS_WIDTH-1:0] if_to_id_bus, 15 | 16 | // bus to exe 17 | output [`ID_TO_EXE_BUS_WIDTH-1:0] id_to_exe_bus, 18 | 19 | // bus to if (for branch) 20 | output [`ID_TO_IF_BUS_WIDTH-1:0] id_to_if_bus, 21 | 22 | // bus from wb (for regfile) 23 | input [`WB_TO_ID_BUS_WIDTH-1:0] wb_to_id_bus 24 | ); 25 | // pipeline registers 26 | reg [`IF_TO_ID_BUS_WIDTH-1:0] id_reg; 27 | wire [31:0] id_pc; 28 | wire [31:0] id_inst; 29 | assign {id_pc, id_inst} = id_reg; 30 | 31 | // input bus from WB (for regfile) 32 | wire wb_rf_we; 33 | wire [4:0] wb_rf_waddr; 34 | wire [31:0] wb_rf_wdata; 35 | assign {wb_rf_we, wb_rf_waddr, wb_rf_wdata} = wb_to_id_bus; 36 | 37 | // output bus to EXE 38 | wire [31:0] rj_value; 39 | wire [31:0] rkd_value; 40 | wire [31:0] imm; 41 | wire [11:0] alu_op; 42 | wire src1_is_pc; 43 | wire src2_is_imm; 44 | wire res_from_mem; 45 | wire reg_we; 46 | wire mem_en; 47 | wire [ 3:0] mem_we; 48 | wire [ 4:0] reg_waddr; 49 | assign id_to_exe_bus = { 50 | id_pc, 51 | rj_value, 52 | rkd_value, 53 | imm, 54 | alu_op, 55 | src1_is_pc, 56 | src2_is_imm, 57 | res_from_mem, 58 | reg_we, 59 | mem_en, 60 | mem_we, 61 | reg_waddr 62 | }; 63 | 64 | // output bus to IF (for branch) 65 | wire br_taken; 66 | wire [31:0] br_target; 67 | assign id_to_if_bus = {br_taken, br_target}; 68 | 69 | // pipeline control 70 | reg id_valid; 71 | wire id_ready_go; 72 | 73 | assign id_ready_go = 1; 74 | assign id_allow_in = !id_valid || (id_ready_go && exe_allow_in); 75 | assign id_to_exe_valid = id_valid && id_ready_go; 76 | 77 | always @(posedge clk) begin 78 | if (reset) begin 79 | id_valid <= 1'b0; 80 | end else if (id_allow_in) begin 81 | id_valid <= if_to_id_valid; 82 | end 83 | end 84 | 85 | always @(posedge clk) begin 86 | if (id_allow_in && if_to_id_valid) begin 87 | id_reg <= if_to_id_bus; 88 | end 89 | end 90 | 91 | // internal signals 92 | wire dst_is_r1; 93 | wire src_reg_is_rd; 94 | wire [31:0] br_offs; 95 | wire [31:0] jirl_offs; 96 | 97 | wire [ 5:0] op_31_26; 98 | wire [ 3:0] op_25_22; 99 | wire [ 1:0] op_21_20; 100 | wire [ 4:0] op_19_15; 101 | wire [ 4:0] rd; 102 | wire [ 4:0] rj; 103 | wire [ 4:0] rk; 104 | wire [11:0] i12; 105 | wire [19:0] i20; 106 | wire [15:0] i16; 107 | wire [25:0] i26; 108 | 109 | wire [63:0] op_31_26_d; 110 | wire [15:0] op_25_22_d; 111 | wire [ 3:0] op_21_20_d; 112 | wire [31:0] op_19_15_d; 113 | 114 | wire inst_add_w; 115 | wire inst_sub_w; 116 | wire inst_slt; 117 | wire inst_sltu; 118 | wire inst_nor; 119 | wire inst_and; 120 | wire inst_or; 121 | wire inst_xor; 122 | wire inst_slli_w; 123 | wire inst_srli_w; 124 | wire inst_srai_w; 125 | wire inst_addi_w; 126 | wire inst_ld_w; 127 | wire inst_st_w; 128 | wire inst_jirl; 129 | wire inst_b; 130 | wire inst_bl; 131 | wire inst_beq; 132 | wire inst_bne; 133 | wire inst_lu12i_w; 134 | 135 | wire need_ui5; 136 | wire need_si12; 137 | wire need_si16; 138 | wire need_si20; 139 | wire need_si26; 140 | wire src2_is_4; 141 | 142 | wire [ 4:0] rf_raddr1; 143 | wire [31:0] rf_rdata1; 144 | wire [ 4:0] rf_raddr2; 145 | wire [31:0] rf_rdata2; 146 | wire rf_we; 147 | wire [ 4:0] rf_waddr; 148 | wire [31:0] rf_wdata; 149 | 150 | // ID stage 151 | assign op_31_26 = id_inst[31:26]; 152 | assign op_25_22 = id_inst[25:22]; 153 | assign op_21_20 = id_inst[21:20]; 154 | assign op_19_15 = id_inst[19:15]; 155 | assign rd = id_inst[4:0]; 156 | assign rj = id_inst[9:5]; 157 | assign rk = id_inst[14:10]; 158 | assign i12 = id_inst[21:10]; 159 | assign i20 = id_inst[24:5]; 160 | assign i16 = id_inst[25:10]; 161 | assign i26 = {id_inst[9:0], id_inst[25:10]}; 162 | decoder_6_64 u_dec0 ( 163 | .in (op_31_26), 164 | .out(op_31_26_d) 165 | ); 166 | decoder_4_16 u_dec1 ( 167 | .in (op_25_22), 168 | .out(op_25_22_d) 169 | ); 170 | decoder_2_4 u_dec2 ( 171 | .in (op_21_20), 172 | .out(op_21_20_d) 173 | ); 174 | decoder_5_32 u_dec3 ( 175 | .in (op_19_15), 176 | .out(op_19_15_d) 177 | ); 178 | 179 | assign inst_add_w = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h00]; 180 | assign inst_sub_w = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h02]; 181 | assign inst_slt = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h04]; 182 | assign inst_sltu = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h05]; 183 | assign inst_nor = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h08]; 184 | assign inst_and = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h09]; 185 | assign inst_or = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h0a]; 186 | assign inst_xor = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h0b]; 187 | assign inst_slli_w = op_31_26_d[6'h00] & op_25_22_d[4'h1] & op_21_20_d[2'h0] & op_19_15_d[5'h01]; 188 | assign inst_srli_w = op_31_26_d[6'h00] & op_25_22_d[4'h1] & op_21_20_d[2'h0] & op_19_15_d[5'h09]; 189 | assign inst_srai_w = op_31_26_d[6'h00] & op_25_22_d[4'h1] & op_21_20_d[2'h0] & op_19_15_d[5'h11]; 190 | assign inst_addi_w = op_31_26_d[6'h00] & op_25_22_d[4'ha]; 191 | assign inst_ld_w = op_31_26_d[6'h0a] & op_25_22_d[4'h2]; 192 | assign inst_st_w = op_31_26_d[6'h0a] & op_25_22_d[4'h6]; 193 | assign inst_jirl = op_31_26_d[6'h13]; 194 | assign inst_b = op_31_26_d[6'h14]; 195 | assign inst_bl = op_31_26_d[6'h15]; 196 | assign inst_beq = op_31_26_d[6'h16]; 197 | assign inst_bne = op_31_26_d[6'h17]; 198 | assign inst_lu12i_w = op_31_26_d[6'h05] & ~id_inst[25]; 199 | 200 | assign alu_op[0] = inst_add_w | inst_addi_w | inst_ld_w | inst_st_w | inst_jirl | inst_bl; // add 201 | assign alu_op[1] = inst_sub_w; // sub 202 | assign alu_op[2] = inst_slt; // slt 203 | assign alu_op[3] = inst_sltu; // sltu 204 | assign alu_op[4] = inst_and; // and 205 | assign alu_op[5] = inst_nor; // nor 206 | assign alu_op[6] = inst_or; // or 207 | assign alu_op[7] = inst_xor; // xor 208 | assign alu_op[8] = inst_slli_w; // sll 209 | assign alu_op[9] = inst_srli_w; // srl 210 | assign alu_op[10] = inst_srai_w; // sra 211 | assign alu_op[11] = inst_lu12i_w; // lui 212 | 213 | assign need_ui5 = inst_slli_w | inst_srli_w | inst_srai_w; 214 | assign need_si12 = inst_addi_w | inst_ld_w | inst_st_w; 215 | assign need_si16 = inst_jirl | inst_beq | inst_bne; 216 | assign need_si20 = inst_lu12i_w; 217 | assign need_si26 = inst_b | inst_bl; 218 | assign src2_is_4 = inst_jirl | inst_bl; 219 | 220 | assign imm = src2_is_4 ? 32'h4 : need_si20 ? {i20[19:0], 12'b0} : 221 | /*need_ui5 || need_si12*/{{20{i12[11]}}, i12[11:0]}; 222 | 223 | assign br_offs = need_si26 ? {{4{i26[25]}}, i26[25:0], 2'b0} : {{14{i16[15]}}, i16[15:0], 2'b0}; 224 | 225 | assign jirl_offs = {{14{i16[15]}}, i16[15:0], 2'b0}; 226 | 227 | assign src_reg_is_rd = inst_beq | inst_bne | inst_st_w; 228 | 229 | assign src1_is_pc = inst_jirl | inst_bl; 230 | 231 | assign src2_is_imm = inst_slli_w | 232 | inst_srli_w | 233 | inst_srai_w | 234 | inst_addi_w | 235 | inst_ld_w | 236 | inst_st_w | 237 | inst_lu12i_w| 238 | inst_jirl | 239 | inst_bl ; 240 | 241 | assign res_from_mem = inst_ld_w; 242 | assign dst_is_r1 = inst_bl; 243 | assign reg_waddr = dst_is_r1 ? 5'd1 : rd; 244 | assign reg_we = id_valid && (~inst_st_w & ~inst_beq & ~inst_bne & ~inst_b) && |(reg_waddr); 245 | 246 | assign mem_en = inst_ld_w || inst_st_w; 247 | assign mem_we = {4{inst_st_w}}; 248 | 249 | assign rf_raddr1 = rj; 250 | assign rf_raddr2 = src_reg_is_rd ? rd : rk; 251 | regfile u_regfile ( 252 | .clk (clk), 253 | .raddr1(rf_raddr1), 254 | .rdata1(rf_rdata1), 255 | .raddr2(rf_raddr2), 256 | .rdata2(rf_rdata2), 257 | .we (rf_we), 258 | .waddr (rf_waddr), 259 | .wdata (rf_wdata) 260 | ); 261 | assign rj_value = rf_rdata1; 262 | assign rkd_value = rf_rdata2; 263 | 264 | wire rj_eq_rd = (rj_value == rkd_value); 265 | assign br_taken = ( inst_beq && rj_eq_rd 266 | || inst_bne && !rj_eq_rd 267 | || inst_jirl 268 | || inst_bl 269 | || inst_b 270 | ) && id_valid; 271 | assign br_target = (inst_beq || inst_bne || inst_bl || inst_b) ? (id_pc + br_offs) : 272 | /*inst_jirl*/ (rj_value + jirl_offs); 273 | 274 | 275 | assign rf_we = wb_rf_we; 276 | assign rf_waddr = wb_rf_waddr; 277 | assign rf_wdata = wb_rf_wdata; 278 | 279 | endmodule 280 | -------------------------------------------------------------------------------- /code/goal 06/mycpu_top.v: -------------------------------------------------------------------------------- 1 | module mycpu_top ( 2 | input wire clk, 3 | input wire resetn, 4 | // inst sram interface 5 | output wire inst_sram_we, 6 | output wire [31:0] inst_sram_addr, 7 | output wire [31:0] inst_sram_wdata, 8 | input wire [31:0] inst_sram_rdata, 9 | // data sram interface 10 | output wire data_sram_we, 11 | output wire [31:0] data_sram_addr, 12 | output wire [31:0] data_sram_wdata, 13 | input wire [31:0] data_sram_rdata, 14 | // trace debug interface 15 | output wire [31:0] debug_wb_pc, 16 | output wire [ 3:0] debug_wb_rf_we, 17 | output wire [ 4:0] debug_wb_rf_wnum, 18 | output wire [31:0] debug_wb_rf_wdata 19 | ); 20 | reg reset; 21 | always @(posedge clk) reset <= ~resetn; 22 | 23 | reg valid; 24 | always @(posedge clk) begin 25 | if (reset) begin 26 | valid <= 1'b0; 27 | end else begin 28 | valid <= 1'b1; 29 | end 30 | end 31 | 32 | wire [31:0] seq_pc; 33 | wire [31:0] nextpc; 34 | wire br_taken; 35 | wire [31:0] br_target; 36 | wire [31:0] inst; 37 | reg [31:0] pc; 38 | 39 | wire [11:0] alu_op; 40 | wire load_op; 41 | wire src1_is_pc; 42 | wire src2_is_imm; 43 | wire res_from_mem; 44 | wire dst_is_r1; 45 | wire gr_we; 46 | wire mem_we; 47 | wire src_reg_is_rd; 48 | wire [ 4:0] dest; 49 | wire [31:0] rj_value; 50 | wire [31:0] rkd_value; 51 | wire [31:0] imm; 52 | wire [31:0] br_offs; 53 | wire [31:0] jirl_offs; 54 | 55 | wire [ 5:0] op_31_26; 56 | wire [ 3:0] op_25_22; 57 | wire [ 1:0] op_21_20; 58 | wire [ 4:0] op_19_15; 59 | wire [ 4:0] rd; 60 | wire [ 4:0] rj; 61 | wire [ 4:0] rk; 62 | wire [11:0] i12; 63 | wire [19:0] i20; 64 | wire [15:0] i16; 65 | wire [25:0] i26; 66 | 67 | wire [63:0] op_31_26_d; 68 | wire [15:0] op_25_22_d; 69 | wire [ 3:0] op_21_20_d; 70 | wire [31:0] op_19_15_d; 71 | 72 | wire inst_add_w; 73 | wire inst_sub_w; 74 | wire inst_slt; 75 | wire inst_sltu; 76 | wire inst_nor; 77 | wire inst_and; 78 | wire inst_or; 79 | wire inst_xor; 80 | wire inst_slli_w; 81 | wire inst_srli_w; 82 | wire inst_srai_w; 83 | wire inst_addi_w; 84 | wire inst_ld_w; 85 | wire inst_st_w; 86 | wire inst_jirl; 87 | wire inst_b; 88 | wire inst_bl; 89 | wire inst_beq; 90 | wire inst_bne; 91 | wire inst_lu12i_w; 92 | 93 | wire need_ui5; 94 | wire need_si12; 95 | wire need_si16; 96 | wire need_si20; 97 | wire need_si26; 98 | wire src2_is_4; 99 | 100 | wire [ 4:0] rf_raddr1; 101 | wire [31:0] rf_rdata1; 102 | wire [ 4:0] rf_raddr2; 103 | wire [31:0] rf_rdata2; 104 | wire rf_we; 105 | wire [ 4:0] rf_waddr; 106 | wire [31:0] rf_wdata; 107 | 108 | wire [31:0] alu_src1; 109 | wire [31:0] alu_src2; 110 | wire [31:0] alu_result; 111 | 112 | wire [31:0] mem_result; 113 | 114 | assign seq_pc = pc + 3'h4; 115 | assign nextpc = br_taken ? br_target : seq_pc; 116 | 117 | always @(posedge clk) begin 118 | if (reset) begin 119 | pc <= 32'h1bfffffc; //trick: to make nextpc be 0x1c000000 during reset 120 | end else begin 121 | pc <= nextpc; 122 | end 123 | end 124 | 125 | assign inst_sram_we = 1'b0; 126 | assign inst_sram_addr = pc; 127 | assign inst_sram_wdata = 32'b0; 128 | assign inst = inst_sram_rdata; 129 | 130 | assign op_31_26 = inst[31:26]; 131 | assign op_25_22 = inst[25:22]; 132 | assign op_21_20 = inst[21:20]; 133 | assign op_19_15 = inst[19:15]; 134 | 135 | assign rd = inst[4:0]; 136 | assign rj = inst[9:5]; 137 | assign rk = inst[14:10]; 138 | 139 | assign i12 = inst[21:10]; 140 | assign i20 = inst[24:5]; 141 | assign i16 = inst[25:10]; 142 | assign i26 = {inst[9:0], inst[25:10]}; 143 | 144 | decoder_6_64 u_dec0 ( 145 | .in (op_31_26), 146 | .out(op_31_26_d) 147 | ); 148 | decoder_4_16 u_dec1 ( 149 | .in (op_25_22), 150 | .out(op_25_22_d) 151 | ); 152 | decoder_2_4 u_dec2 ( 153 | .in (op_21_20), 154 | .out(op_21_20_d) 155 | ); 156 | decoder_5_32 u_dec3 ( 157 | .in (op_19_15), 158 | .out(op_19_15_d) 159 | ); 160 | 161 | assign inst_add_w = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h00]; 162 | assign inst_sub_w = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h02]; 163 | assign inst_slt = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h04]; 164 | assign inst_sltu = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h05]; 165 | assign inst_nor = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h08]; 166 | assign inst_and = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h09]; 167 | assign inst_or = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h0a]; 168 | assign inst_xor = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h0b]; 169 | assign inst_slli_w = op_31_26_d[6'h00] & op_25_22_d[4'h1] & op_21_20_d[2'h0] & op_19_15_d[5'h01]; 170 | assign inst_srli_w = op_31_26_d[6'h00] & op_25_22_d[4'h1] & op_21_20_d[2'h0] & op_19_15_d[5'h09]; 171 | assign inst_srai_w = op_31_26_d[6'h00] & op_25_22_d[4'h1] & op_21_20_d[2'h0] & op_19_15_d[5'h11]; 172 | assign inst_addi_w = op_31_26_d[6'h00] & op_25_22_d[4'ha]; 173 | assign inst_ld_w = op_31_26_d[6'h0a] & op_25_22_d[4'h2]; 174 | assign inst_st_w = op_31_26_d[6'h0a] & op_25_22_d[4'h6]; 175 | assign inst_jirl = op_31_26_d[6'h13]; 176 | assign inst_b = op_31_26_d[6'h14]; 177 | assign inst_bl = op_31_26_d[6'h15]; 178 | assign inst_beq = op_31_26_d[6'h16]; 179 | assign inst_bne = op_31_26_d[6'h17]; 180 | assign inst_lu12i_w = op_31_26_d[6'h05] & ~inst[25]; 181 | 182 | assign alu_op[0] = inst_add_w | inst_addi_w | inst_ld_w | inst_st_w | inst_jirl | inst_bl; // add 183 | assign alu_op[1] = inst_sub_w; // sub 184 | assign alu_op[2] = inst_slt; // slt 185 | assign alu_op[3] = inst_sltu; // sltu 186 | assign alu_op[4] = inst_and; // and 187 | assign alu_op[5] = inst_nor; // nor 188 | assign alu_op[6] = inst_or; // or 189 | assign alu_op[7] = inst_xor; // xor 190 | assign alu_op[8] = inst_slli_w; // sll 191 | assign alu_op[9] = inst_srli_w; // srl 192 | assign alu_op[10] = inst_srai_w; // sra 193 | assign alu_op[11] = inst_lu12i_w; // lui 194 | 195 | assign need_ui5 = inst_slli_w | inst_srli_w | inst_srai_w; 196 | assign need_si12 = inst_addi_w | inst_ld_w | inst_st_w; 197 | assign need_si16 = inst_jirl | inst_beq | inst_bne; 198 | assign need_si20 = inst_lu12i_w; 199 | assign need_si26 = inst_b | inst_bl; 200 | assign src2_is_4 = inst_jirl | inst_bl; 201 | 202 | assign imm = src2_is_4 ? 32'h4 : need_si20 ? {i20[19:0], 12'b0} : 203 | /*need_ui5 || need_si12*/{{20{i12[11]}}, i12[11:0]}; 204 | 205 | assign br_offs = need_si26 ? {{4{i26[25]}}, i26[25:0], 2'b0} : {{14{i16[15]}}, i16[15:0], 2'b0}; 206 | 207 | assign jirl_offs = {{14{i16[15]}}, i16[15:0], 2'b0}; 208 | 209 | assign src_reg_is_rd = inst_beq | inst_bne | inst_st_w; 210 | 211 | assign src1_is_pc = inst_jirl | inst_bl; 212 | 213 | assign src2_is_imm = inst_slli_w | 214 | inst_srli_w | 215 | inst_srai_w | 216 | inst_addi_w | 217 | inst_ld_w | 218 | inst_st_w | 219 | inst_lu12i_w| 220 | inst_jirl | 221 | inst_bl ; 222 | 223 | assign res_from_mem = inst_ld_w; 224 | assign dst_is_r1 = inst_bl; 225 | assign gr_we = ~inst_st_w & ~inst_beq & ~inst_bne & ~inst_b; // ! error 226 | assign mem_we = inst_st_w; 227 | assign dest = dst_is_r1 ? 5'd1 : rd; 228 | 229 | assign rf_raddr1 = rj; 230 | assign rf_raddr2 = src_reg_is_rd ? rd : rk; 231 | regfile u_regfile ( 232 | .clk (clk), 233 | .raddr1(rf_raddr1), 234 | .rdata1(rf_rdata1), 235 | .raddr2(rf_raddr2), 236 | .rdata2(rf_rdata2), 237 | .we (rf_we), 238 | .waddr (rf_waddr), 239 | .wdata (rf_wdata) 240 | ); 241 | 242 | assign rj_value = rf_rdata1; 243 | assign rkd_value = rf_rdata2; 244 | 245 | wire rj_eq_rd = (rj_value == rkd_value); // ! error 246 | assign br_taken = ( inst_beq && rj_eq_rd 247 | || inst_bne && !rj_eq_rd 248 | || inst_jirl 249 | || inst_bl 250 | || inst_b 251 | ) && valid; 252 | assign br_target = (inst_beq || inst_bne || inst_bl || inst_b) ? (pc + br_offs) : 253 | /*inst_jirl*/ (rj_value + jirl_offs); 254 | 255 | assign alu_src1 = src1_is_pc ? pc[31:0] : rj_value; 256 | assign alu_src2 = src2_is_imm ? imm : rkd_value; 257 | 258 | alu u_alu ( 259 | .alu_op (alu_op), 260 | .alu_src1 (alu_src1), // ! error 261 | .alu_src2 (alu_src2), 262 | .alu_result(alu_result) 263 | ); 264 | 265 | assign data_sram_we = mem_we && valid; 266 | assign data_sram_addr = inst_st_w | inst_ld_w ? alu_result : 32'b0; // ! warn: addr out of bound 267 | assign data_sram_wdata = rkd_value; 268 | 269 | assign mem_result = data_sram_rdata; 270 | wire [31:0] final_result = res_from_mem ? mem_result : alu_result; // ! error 271 | 272 | assign rf_we = gr_we && valid; 273 | assign rf_waddr = dest; 274 | assign rf_wdata = final_result; 275 | 276 | // debug info generate 277 | assign debug_wb_pc = pc; 278 | assign debug_wb_rf_wen = {4{rf_we}}; 279 | assign debug_wb_rf_wnum = dest; 280 | assign debug_wb_rf_wdata = final_result; 281 | 282 | endmodule 283 | -------------------------------------------------------------------------------- /code/goal 08/id_stage.v: -------------------------------------------------------------------------------- 1 | `include "mycpu_top.h" 2 | 3 | module id_stage ( 4 | input clk, 5 | input reset, 6 | 7 | // pipeline control 8 | output id_allow_in, 9 | input if_to_id_valid, 10 | input exe_allow_in, 11 | output id_to_exe_valid, 12 | 13 | // hazard detection 14 | input exe_rf_we, 15 | input [4:0] exe_rf_waddr, 16 | input exe_valid, 17 | input mem_rf_we, 18 | input [4:0] mem_rf_waddr, 19 | input mem_valid, 20 | input wb_valid, 21 | 22 | // bus from if 23 | input [`IF_TO_ID_BUS_WIDTH-1:0] if_to_id_bus, 24 | 25 | // bus to exe 26 | output [`ID_TO_EXE_BUS_WIDTH-1:0] id_to_exe_bus, 27 | 28 | // bus to if (for branch) 29 | output [`ID_TO_IF_BUS_WIDTH-1:0] id_to_if_bus, 30 | 31 | // bus from wb (for regfile) 32 | input [`WB_TO_ID_BUS_WIDTH-1:0] wb_to_id_bus 33 | ); 34 | // pipeline registers 35 | reg [`IF_TO_ID_BUS_WIDTH-1:0] id_reg; 36 | wire [31:0] id_pc; 37 | wire [31:0] id_inst; 38 | assign {id_pc, id_inst} = id_reg; 39 | 40 | // input bus from WB (for regfile) 41 | wire wb_rf_we; 42 | wire [4:0] wb_rf_waddr; 43 | wire [31:0] wb_rf_wdata; 44 | assign {wb_rf_we, wb_rf_waddr, wb_rf_wdata} = wb_to_id_bus; 45 | 46 | // output bus to EXE 47 | wire [31:0] rj_value; 48 | wire [31:0] rkd_value; 49 | wire [31:0] imm; 50 | wire [11:0] alu_op; 51 | wire src1_is_pc; 52 | wire src2_is_imm; 53 | wire res_from_mem; 54 | wire reg_we; 55 | wire mem_en; 56 | wire [ 3:0] mem_we; 57 | wire [ 4:0] reg_waddr; 58 | assign id_to_exe_bus = { 59 | id_pc, 60 | rj_value, 61 | rkd_value, 62 | imm, 63 | alu_op, 64 | src1_is_pc, 65 | src2_is_imm, 66 | res_from_mem, 67 | reg_we, 68 | mem_en, 69 | mem_we, 70 | reg_waddr 71 | }; 72 | 73 | // output bus to IF (for branch) 74 | wire br_taken; 75 | wire [31:0] br_target; 76 | wire br_taken_cancel; // for branch cancel 77 | assign id_to_if_bus = {br_taken, br_target, br_taken_cancel}; 78 | 79 | // pipeline control 80 | reg id_valid; 81 | wire id_ready_go; 82 | 83 | // assign id_ready_go = 1; nope for hazard happening 84 | assign id_allow_in = !id_valid || (id_ready_go && exe_allow_in); 85 | assign id_to_exe_valid = id_valid && id_ready_go; 86 | 87 | always @(posedge clk) begin 88 | if (reset) begin 89 | id_valid <= 1'b0; 90 | end else if (br_taken_cancel) begin 91 | id_valid <= 1'b0; 92 | end else if (id_allow_in) begin 93 | id_valid <= if_to_id_valid; 94 | end 95 | end 96 | 97 | always @(posedge clk) begin 98 | if (id_allow_in && if_to_id_valid) begin 99 | id_reg <= if_to_id_bus; 100 | end 101 | end 102 | 103 | // internal signals 104 | wire dst_is_r1; 105 | wire src_reg_is_rd; 106 | wire [31:0] br_offs; 107 | wire [31:0] jirl_offs; 108 | 109 | wire [ 5:0] op_31_26; 110 | wire [ 3:0] op_25_22; 111 | wire [ 1:0] op_21_20; 112 | wire [ 4:0] op_19_15; 113 | wire [ 4:0] rd; 114 | wire [ 4:0] rj; 115 | wire [ 4:0] rk; 116 | wire [11:0] i12; 117 | wire [19:0] i20; 118 | wire [15:0] i16; 119 | wire [25:0] i26; 120 | 121 | wire [63:0] op_31_26_d; 122 | wire [15:0] op_25_22_d; 123 | wire [ 3:0] op_21_20_d; 124 | wire [31:0] op_19_15_d; 125 | 126 | wire inst_add_w; 127 | wire inst_sub_w; 128 | wire inst_slt; 129 | wire inst_sltu; 130 | wire inst_nor; 131 | wire inst_and; 132 | wire inst_or; 133 | wire inst_xor; 134 | wire inst_slli_w; 135 | wire inst_srli_w; 136 | wire inst_srai_w; 137 | wire inst_addi_w; 138 | wire inst_ld_w; 139 | wire inst_st_w; 140 | wire inst_jirl; 141 | wire inst_b; 142 | wire inst_bl; 143 | wire inst_beq; 144 | wire inst_bne; 145 | wire inst_lu12i_w; 146 | 147 | wire need_ui5; 148 | wire need_si12; 149 | wire need_si16; 150 | wire need_si20; 151 | wire need_si26; 152 | wire src2_is_4; 153 | 154 | wire [ 4:0] rf_raddr1; 155 | wire [31:0] rf_rdata1; 156 | wire [ 4:0] rf_raddr2; 157 | wire [31:0] rf_rdata2; 158 | wire rf_we; 159 | wire [ 4:0] rf_waddr; 160 | wire [31:0] rf_wdata; 161 | 162 | // ID stage 163 | assign op_31_26 = id_inst[31:26]; 164 | assign op_25_22 = id_inst[25:22]; 165 | assign op_21_20 = id_inst[21:20]; 166 | assign op_19_15 = id_inst[19:15]; 167 | assign rd = id_inst[4:0]; 168 | assign rj = id_inst[9:5]; 169 | assign rk = id_inst[14:10]; 170 | assign i12 = id_inst[21:10]; 171 | assign i20 = id_inst[24:5]; 172 | assign i16 = id_inst[25:10]; 173 | assign i26 = {id_inst[9:0], id_inst[25:10]}; 174 | decoder_6_64 u_dec0 ( 175 | .in (op_31_26), 176 | .out(op_31_26_d) 177 | ); 178 | decoder_4_16 u_dec1 ( 179 | .in (op_25_22), 180 | .out(op_25_22_d) 181 | ); 182 | decoder_2_4 u_dec2 ( 183 | .in (op_21_20), 184 | .out(op_21_20_d) 185 | ); 186 | decoder_5_32 u_dec3 ( 187 | .in (op_19_15), 188 | .out(op_19_15_d) 189 | ); 190 | 191 | assign inst_add_w = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h00]; 192 | assign inst_sub_w = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h02]; 193 | assign inst_slt = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h04]; 194 | assign inst_sltu = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h05]; 195 | assign inst_nor = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h08]; 196 | assign inst_and = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h09]; 197 | assign inst_or = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h0a]; 198 | assign inst_xor = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h0b]; 199 | assign inst_slli_w = op_31_26_d[6'h00] & op_25_22_d[4'h1] & op_21_20_d[2'h0] & op_19_15_d[5'h01]; 200 | assign inst_srli_w = op_31_26_d[6'h00] & op_25_22_d[4'h1] & op_21_20_d[2'h0] & op_19_15_d[5'h09]; 201 | assign inst_srai_w = op_31_26_d[6'h00] & op_25_22_d[4'h1] & op_21_20_d[2'h0] & op_19_15_d[5'h11]; 202 | assign inst_addi_w = op_31_26_d[6'h00] & op_25_22_d[4'ha]; 203 | assign inst_ld_w = op_31_26_d[6'h0a] & op_25_22_d[4'h2]; 204 | assign inst_st_w = op_31_26_d[6'h0a] & op_25_22_d[4'h6]; 205 | assign inst_jirl = op_31_26_d[6'h13]; 206 | assign inst_b = op_31_26_d[6'h14]; 207 | assign inst_bl = op_31_26_d[6'h15]; 208 | assign inst_beq = op_31_26_d[6'h16]; 209 | assign inst_bne = op_31_26_d[6'h17]; 210 | assign inst_lu12i_w = op_31_26_d[6'h05] & ~id_inst[25]; 211 | 212 | assign alu_op[0] = inst_add_w | inst_addi_w | inst_ld_w | inst_st_w | inst_jirl | inst_bl; // add 213 | assign alu_op[1] = inst_sub_w; // sub 214 | assign alu_op[2] = inst_slt; // slt 215 | assign alu_op[3] = inst_sltu; // sltu 216 | assign alu_op[4] = inst_and; // and 217 | assign alu_op[5] = inst_nor; // nor 218 | assign alu_op[6] = inst_or; // or 219 | assign alu_op[7] = inst_xor; // xor 220 | assign alu_op[8] = inst_slli_w; // sll 221 | assign alu_op[9] = inst_srli_w; // srl 222 | assign alu_op[10] = inst_srai_w; // sra 223 | assign alu_op[11] = inst_lu12i_w; // lui 224 | 225 | assign need_ui5 = inst_slli_w | inst_srli_w | inst_srai_w; 226 | assign need_si12 = inst_addi_w | inst_ld_w | inst_st_w; 227 | assign need_si16 = inst_jirl | inst_beq | inst_bne; 228 | assign need_si20 = inst_lu12i_w; 229 | assign need_si26 = inst_b | inst_bl; 230 | assign src2_is_4 = inst_jirl | inst_bl; 231 | 232 | assign imm = src2_is_4 ? 32'h4 : need_si20 ? {i20[19:0], 12'b0} : 233 | /*need_ui5 || need_si12*/{{20{i12[11]}}, i12[11:0]}; 234 | 235 | assign br_offs = need_si26 ? {{4{i26[25]}}, i26[25:0], 2'b0} : {{14{i16[15]}}, i16[15:0], 2'b0}; 236 | 237 | assign jirl_offs = {{14{i16[15]}}, i16[15:0], 2'b0}; 238 | 239 | assign src_reg_is_rd = inst_beq | inst_bne | inst_st_w; 240 | 241 | assign src1_is_pc = inst_jirl | inst_bl; 242 | 243 | assign src2_is_imm = inst_slli_w | 244 | inst_srli_w | 245 | inst_srai_w | 246 | inst_addi_w | 247 | inst_ld_w | 248 | inst_st_w | 249 | inst_lu12i_w| 250 | inst_jirl | 251 | inst_bl ; 252 | 253 | assign res_from_mem = inst_ld_w; 254 | assign dst_is_r1 = inst_bl; 255 | assign reg_waddr = dst_is_r1 ? 5'd1 : rd; 256 | assign reg_we = id_valid && (~inst_st_w & ~inst_beq & ~inst_bne & ~inst_b) && |(reg_waddr); 257 | 258 | assign mem_en = inst_ld_w || inst_st_w; 259 | assign mem_we = {4{inst_st_w}}; 260 | 261 | assign rf_raddr1 = rj; 262 | assign rf_raddr2 = src_reg_is_rd ? rd : rk; 263 | regfile u_regfile ( 264 | .clk (clk), 265 | .raddr1(rf_raddr1), 266 | .rdata1(rf_rdata1), 267 | .raddr2(rf_raddr2), 268 | .rdata2(rf_rdata2), 269 | .we (rf_we), 270 | .waddr (rf_waddr), 271 | .wdata (rf_wdata) 272 | ); 273 | assign rj_value = rf_rdata1; 274 | assign rkd_value = rf_rdata2; 275 | 276 | wire rj_eq_rd = (rj_value == rkd_value); 277 | assign br_taken = id_valid && ( inst_beq && rj_eq_rd 278 | || inst_bne && !rj_eq_rd 279 | || inst_jirl 280 | || inst_bl 281 | || inst_b 282 | ) && id_ready_go; 283 | assign br_target = (inst_beq || inst_bne || inst_bl || inst_b) ? (id_pc + br_offs) : 284 | /*inst_jirl*/ (rj_value + jirl_offs); 285 | 286 | 287 | assign rf_we = wb_rf_we; 288 | assign rf_waddr = wb_rf_waddr; 289 | assign rf_wdata = wb_rf_wdata; 290 | 291 | // hazard detection 292 | wire use_rf_rdata1 = id_valid && (!inst_lu12i_w && !inst_b && !inst_bl); 293 | wire use_rf_rdata2 = id_valid && ( 294 | inst_add_w || 295 | inst_sub_w || 296 | inst_slt || 297 | inst_sltu || 298 | inst_nor || 299 | inst_and || 300 | inst_or || 301 | inst_xor || 302 | inst_st_w || 303 | inst_beq || 304 | inst_bne 305 | ); 306 | 307 | // case waddr is 0 has already been handled in line 250 308 | // which means that if waddr is 0, rf_we is 0 309 | wire rf_rdata1_hazard = use_rf_rdata1 && ( 310 | (exe_valid && exe_rf_we && (rf_raddr1 == exe_rf_waddr)) || 311 | (mem_valid && mem_rf_we && (rf_raddr1 == mem_rf_waddr)) || 312 | (wb_valid && wb_rf_we && (rf_raddr1 == wb_rf_waddr)) 313 | ); 314 | wire rf_rdata2_hazard = use_rf_rdata2 && ( 315 | (exe_valid && exe_rf_we && (rf_raddr2 == exe_rf_waddr)) || 316 | (mem_valid && mem_rf_we && (rf_raddr2 == mem_rf_waddr)) || 317 | (wb_valid && wb_rf_we && (rf_raddr2 == wb_rf_waddr)) 318 | ); 319 | assign id_ready_go = !rf_rdata1_hazard && !rf_rdata2_hazard; 320 | 321 | assign br_taken_cancel = id_valid && id_ready_go && br_taken; 322 | endmodule 323 | -------------------------------------------------------------------------------- /code/goal 09/id_stage.v: -------------------------------------------------------------------------------- 1 | `include "mycpu_top.h" 2 | 3 | module id_stage ( 4 | input clk, 5 | input reset, 6 | 7 | // pipeline control 8 | output id_allow_in, 9 | input if_to_id_valid, 10 | input exe_allow_in, 11 | output id_to_exe_valid, 12 | 13 | // hazard detection && bypass 14 | input exe_valid, 15 | input [`BYPASS_BUS_WIDTH-1:0] exe_to_id_bypass_bus, 16 | input exe_is_load, 17 | input mem_valid, 18 | input [`BYPASS_BUS_WIDTH-1:0] mem_to_id_bypass_bus, 19 | input wb_valid, 20 | 21 | // bus from if 22 | input [`IF_TO_ID_BUS_WIDTH-1:0] if_to_id_bus, 23 | 24 | // bus to exe 25 | output [`ID_TO_EXE_BUS_WIDTH-1:0] id_to_exe_bus, 26 | 27 | // bus to if (for branch) 28 | output [`ID_TO_IF_BUS_WIDTH-1:0] id_to_if_bus, 29 | 30 | // bus from wb (for regfile) 31 | input [`WB_TO_ID_BUS_WIDTH-1:0] wb_to_id_bus 32 | ); 33 | // pipeline registers 34 | reg [`IF_TO_ID_BUS_WIDTH-1:0] id_reg; 35 | wire [31:0] id_pc; 36 | wire [31:0] id_inst; 37 | assign {id_pc, id_inst} = id_reg; 38 | 39 | // input bus from WB (for regfile) 40 | wire wb_rf_we; 41 | wire [4:0] wb_rf_waddr; 42 | wire [31:0] wb_rf_wdata; 43 | assign {wb_rf_we, wb_rf_waddr, wb_rf_wdata} = wb_to_id_bus; 44 | 45 | // output bus to EXE 46 | wire [31:0] rj_value; 47 | wire [31:0] rkd_value; 48 | wire [31:0] imm; 49 | wire [11:0] alu_op; 50 | wire src1_is_pc; 51 | wire src2_is_imm; 52 | wire res_from_mem; 53 | wire reg_we; 54 | wire mem_en; 55 | wire [ 3:0] mem_we; 56 | wire [ 4:0] reg_waddr; 57 | assign id_to_exe_bus = { 58 | id_pc, 59 | rj_value, 60 | rkd_value, 61 | imm, 62 | alu_op, 63 | src1_is_pc, 64 | src2_is_imm, 65 | res_from_mem, 66 | reg_we, 67 | mem_en, 68 | mem_we, 69 | reg_waddr 70 | }; 71 | 72 | // output bus to IF (for branch) 73 | wire br_taken; 74 | wire [31:0] br_target; 75 | wire br_taken_cancel; // for branch cancel 76 | assign id_to_if_bus = {br_taken, br_target, br_taken_cancel}; 77 | 78 | // pipeline control 79 | reg id_valid; 80 | wire id_ready_go; 81 | 82 | // assign id_ready_go = 1; nope for hazard happening 83 | assign id_allow_in = !id_valid || (id_ready_go && exe_allow_in); 84 | assign id_to_exe_valid = id_valid && id_ready_go; 85 | 86 | always @(posedge clk) begin 87 | if (reset) begin 88 | id_valid <= 1'b0; 89 | end else if (br_taken_cancel) begin 90 | id_valid <= 1'b0; 91 | end else if (id_allow_in) begin 92 | id_valid <= if_to_id_valid; 93 | end 94 | end 95 | 96 | always @(posedge clk) begin 97 | if (id_allow_in && if_to_id_valid) begin 98 | id_reg <= if_to_id_bus; 99 | end 100 | end 101 | 102 | // bypass 103 | wire exe_rf_we; 104 | wire [4:0] exe_rf_waddr; 105 | wire [31:0] exe_rf_wdata; 106 | assign {exe_rf_we, exe_rf_waddr, exe_rf_wdata} = exe_to_id_bypass_bus; 107 | wire mem_rf_we; 108 | wire [4:0] mem_rf_waddr; 109 | wire [31:0] mem_rf_wdata; 110 | assign {mem_rf_we, mem_rf_waddr, mem_rf_wdata} = mem_to_id_bypass_bus; 111 | 112 | // internal signals 113 | wire dst_is_r1; 114 | wire src_reg_is_rd; 115 | wire [31:0] br_offs; 116 | wire [31:0] jirl_offs; 117 | 118 | wire [ 5:0] op_31_26; 119 | wire [ 3:0] op_25_22; 120 | wire [ 1:0] op_21_20; 121 | wire [ 4:0] op_19_15; 122 | wire [ 4:0] rd; 123 | wire [ 4:0] rj; 124 | wire [ 4:0] rk; 125 | wire [11:0] i12; 126 | wire [19:0] i20; 127 | wire [15:0] i16; 128 | wire [25:0] i26; 129 | 130 | wire [63:0] op_31_26_d; 131 | wire [15:0] op_25_22_d; 132 | wire [ 3:0] op_21_20_d; 133 | wire [31:0] op_19_15_d; 134 | 135 | wire inst_add_w; 136 | wire inst_sub_w; 137 | wire inst_slt; 138 | wire inst_sltu; 139 | wire inst_nor; 140 | wire inst_and; 141 | wire inst_or; 142 | wire inst_xor; 143 | wire inst_slli_w; 144 | wire inst_srli_w; 145 | wire inst_srai_w; 146 | wire inst_addi_w; 147 | wire inst_ld_w; 148 | wire inst_st_w; 149 | wire inst_jirl; 150 | wire inst_b; 151 | wire inst_bl; 152 | wire inst_beq; 153 | wire inst_bne; 154 | wire inst_lu12i_w; 155 | 156 | wire need_ui5; 157 | wire need_si12; 158 | wire need_si16; 159 | wire need_si20; 160 | wire need_si26; 161 | wire src2_is_4; 162 | 163 | wire [ 4:0] rf_raddr1; 164 | wire [31:0] rf_rdata1; 165 | wire [ 4:0] rf_raddr2; 166 | wire [31:0] rf_rdata2; 167 | wire rf_we; 168 | wire [ 4:0] rf_waddr; 169 | wire [31:0] rf_wdata; 170 | 171 | // ID stage 172 | assign op_31_26 = id_inst[31:26]; 173 | assign op_25_22 = id_inst[25:22]; 174 | assign op_21_20 = id_inst[21:20]; 175 | assign op_19_15 = id_inst[19:15]; 176 | assign rd = id_inst[4:0]; 177 | assign rj = id_inst[9:5]; 178 | assign rk = id_inst[14:10]; 179 | assign i12 = id_inst[21:10]; 180 | assign i20 = id_inst[24:5]; 181 | assign i16 = id_inst[25:10]; 182 | assign i26 = {id_inst[9:0], id_inst[25:10]}; 183 | decoder_6_64 u_dec0 ( 184 | .in (op_31_26), 185 | .out(op_31_26_d) 186 | ); 187 | decoder_4_16 u_dec1 ( 188 | .in (op_25_22), 189 | .out(op_25_22_d) 190 | ); 191 | decoder_2_4 u_dec2 ( 192 | .in (op_21_20), 193 | .out(op_21_20_d) 194 | ); 195 | decoder_5_32 u_dec3 ( 196 | .in (op_19_15), 197 | .out(op_19_15_d) 198 | ); 199 | 200 | assign inst_add_w = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h00]; 201 | assign inst_sub_w = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h02]; 202 | assign inst_slt = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h04]; 203 | assign inst_sltu = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h05]; 204 | assign inst_nor = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h08]; 205 | assign inst_and = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h09]; 206 | assign inst_or = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h0a]; 207 | assign inst_xor = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h0b]; 208 | assign inst_slli_w = op_31_26_d[6'h00] & op_25_22_d[4'h1] & op_21_20_d[2'h0] & op_19_15_d[5'h01]; 209 | assign inst_srli_w = op_31_26_d[6'h00] & op_25_22_d[4'h1] & op_21_20_d[2'h0] & op_19_15_d[5'h09]; 210 | assign inst_srai_w = op_31_26_d[6'h00] & op_25_22_d[4'h1] & op_21_20_d[2'h0] & op_19_15_d[5'h11]; 211 | assign inst_addi_w = op_31_26_d[6'h00] & op_25_22_d[4'ha]; 212 | assign inst_ld_w = op_31_26_d[6'h0a] & op_25_22_d[4'h2]; 213 | assign inst_st_w = op_31_26_d[6'h0a] & op_25_22_d[4'h6]; 214 | assign inst_jirl = op_31_26_d[6'h13]; 215 | assign inst_b = op_31_26_d[6'h14]; 216 | assign inst_bl = op_31_26_d[6'h15]; 217 | assign inst_beq = op_31_26_d[6'h16]; 218 | assign inst_bne = op_31_26_d[6'h17]; 219 | assign inst_lu12i_w = op_31_26_d[6'h05] & ~id_inst[25]; 220 | 221 | assign alu_op[0] = inst_add_w | inst_addi_w | inst_ld_w | inst_st_w | inst_jirl | inst_bl; // add 222 | assign alu_op[1] = inst_sub_w; // sub 223 | assign alu_op[2] = inst_slt; // slt 224 | assign alu_op[3] = inst_sltu; // sltu 225 | assign alu_op[4] = inst_and; // and 226 | assign alu_op[5] = inst_nor; // nor 227 | assign alu_op[6] = inst_or; // or 228 | assign alu_op[7] = inst_xor; // xor 229 | assign alu_op[8] = inst_slli_w; // sll 230 | assign alu_op[9] = inst_srli_w; // srl 231 | assign alu_op[10] = inst_srai_w; // sra 232 | assign alu_op[11] = inst_lu12i_w; // lui 233 | 234 | assign need_ui5 = inst_slli_w | inst_srli_w | inst_srai_w; 235 | assign need_si12 = inst_addi_w | inst_ld_w | inst_st_w; 236 | assign need_si16 = inst_jirl | inst_beq | inst_bne; 237 | assign need_si20 = inst_lu12i_w; 238 | assign need_si26 = inst_b | inst_bl; 239 | assign src2_is_4 = inst_jirl | inst_bl; 240 | 241 | assign imm = src2_is_4 ? 32'h4 : need_si20 ? {i20[19:0], 12'b0} : 242 | /*need_ui5 || need_si12*/{{20{i12[11]}}, i12[11:0]}; 243 | 244 | assign br_offs = need_si26 ? {{4{i26[25]}}, i26[25:0], 2'b0} : {{14{i16[15]}}, i16[15:0], 2'b0}; 245 | 246 | assign jirl_offs = {{14{i16[15]}}, i16[15:0], 2'b0}; 247 | 248 | assign src_reg_is_rd = inst_beq | inst_bne | inst_st_w; 249 | 250 | assign src1_is_pc = inst_jirl | inst_bl; 251 | 252 | assign src2_is_imm = inst_slli_w | 253 | inst_srli_w | 254 | inst_srai_w | 255 | inst_addi_w | 256 | inst_ld_w | 257 | inst_st_w | 258 | inst_lu12i_w| 259 | inst_jirl | 260 | inst_bl ; 261 | 262 | assign res_from_mem = inst_ld_w; 263 | assign dst_is_r1 = inst_bl; 264 | assign reg_waddr = dst_is_r1 ? 5'd1 : rd; 265 | assign reg_we = id_valid && (~inst_st_w & ~inst_beq & ~inst_bne & ~inst_b) && |(reg_waddr); 266 | 267 | assign mem_en = inst_ld_w || inst_st_w; 268 | assign mem_we = {4{inst_st_w}}; 269 | 270 | assign rf_raddr1 = rj; 271 | assign rf_raddr2 = src_reg_is_rd ? rd : rk; 272 | regfile u_regfile ( 273 | .clk (clk), 274 | .raddr1(rf_raddr1), 275 | .rdata1(rf_rdata1), 276 | .raddr2(rf_raddr2), 277 | .rdata2(rf_rdata2), 278 | .we (rf_we), 279 | .waddr (rf_waddr), 280 | .wdata (rf_wdata) 281 | ); 282 | 283 | // deprecated, use bypass instead 284 | // assign rj_value = rf_rdata1; 285 | // assign rkd_value = rf_rdata2; 286 | 287 | wire rj_eq_rd = (rj_value == rkd_value); 288 | assign br_taken = id_valid && ( inst_beq && rj_eq_rd 289 | || inst_bne && !rj_eq_rd 290 | || inst_jirl 291 | || inst_bl 292 | || inst_b 293 | ) && id_ready_go; 294 | assign br_target = (inst_beq || inst_bne || inst_bl || inst_b) ? (id_pc + br_offs) : 295 | /*inst_jirl*/ (rj_value + jirl_offs); 296 | 297 | 298 | assign rf_we = wb_rf_we; 299 | assign rf_waddr = wb_rf_waddr; 300 | assign rf_wdata = wb_rf_wdata; 301 | 302 | // hazard detection 303 | wire use_rf_rdata1 = id_valid && (!inst_lu12i_w && !inst_b && !inst_bl); 304 | wire use_rf_rdata2 = id_valid && ( 305 | inst_add_w || 306 | inst_sub_w || 307 | inst_slt || 308 | inst_sltu || 309 | inst_nor || 310 | inst_and || 311 | inst_or || 312 | inst_xor || 313 | inst_st_w || 314 | inst_beq || 315 | inst_bne 316 | ); 317 | 318 | // case waddr is 0 has already been handled in line 250 319 | // which means that if waddr is 0, rf_we is 0 320 | wire rf_rdata1_hazard = use_rf_rdata1 && ( 321 | (exe_valid && exe_is_load && exe_rf_we && (rf_raddr1 == exe_rf_waddr)) 322 | ); 323 | wire rf_rdata2_hazard = use_rf_rdata2 && ( 324 | (exe_valid && exe_is_load && exe_rf_we && (rf_raddr2 == exe_rf_waddr)) 325 | ); 326 | assign id_ready_go = !rf_rdata1_hazard && !rf_rdata2_hazard; 327 | 328 | // branch cancel 329 | assign br_taken_cancel = id_valid && id_ready_go && exe_allow_in && br_taken; 330 | 331 | // bypass 332 | assign rj_value = 333 | (exe_valid && exe_rf_we && (rf_raddr1 == exe_rf_waddr)) ? exe_rf_wdata : 334 | (mem_valid && mem_rf_we && (rf_raddr1 == mem_rf_waddr)) ? mem_rf_wdata : 335 | (wb_valid && wb_rf_we && (rf_raddr1 == wb_rf_waddr)) ? wb_rf_wdata : 336 | rf_rdata1; 337 | 338 | assign rkd_value = 339 | (exe_valid && exe_rf_we && (rf_raddr2 == exe_rf_waddr)) ? exe_rf_wdata : 340 | (mem_valid && mem_rf_we && (rf_raddr2 == mem_rf_waddr)) ? mem_rf_wdata : 341 | (wb_valid && wb_rf_we && (rf_raddr2 == wb_rf_waddr)) ? wb_rf_wdata : 342 | rf_rdata2; 343 | 344 | endmodule 345 | --------------------------------------------------------------------------------