├── pipeline ├── forward │ ├── onBoard │ │ ├── alu.v │ │ ├── aluop_selector.v │ │ ├── arithmetic_unit.v │ │ ├── branch_unit.v │ │ ├── clock_divider.v │ │ ├── compare_unit.v │ │ ├── controler.v │ │ ├── data_hazard_detect.v │ │ ├── display.v │ │ ├── execute.v │ │ ├── forward_unit.v │ │ ├── imm_gen.v │ │ ├── instruction_decoder.v │ │ ├── instruction_fetch.v │ │ ├── irom.v │ │ ├── jump_examine.v │ │ ├── logic_unit.v │ │ ├── mem.v │ │ ├── my_cpu.v │ │ ├── npc.v │ │ ├── pc.v │ │ ├── reg_exe_mem.v │ │ ├── reg_file.v │ │ ├── reg_file_8.v │ │ ├── reg_id_exe.v │ │ ├── reg_if_id.v │ │ ├── reg_mem_wb.v │ │ ├── shift_unit.v │ │ └── top.v │ └── trace │ │ ├── alu.v │ │ ├── aluop_selector.v │ │ ├── arithmetic_unit.v │ │ ├── branch_unit.v │ │ ├── clock_divider.v │ │ ├── compare_unit.v │ │ ├── controler.v │ │ ├── data_hazard_detect.v │ │ ├── display.v │ │ ├── execute.v │ │ ├── forward_unit.v │ │ ├── imm_gen.v │ │ ├── instruction_decoder.v │ │ ├── instruction_fetch.v │ │ ├── irom.v │ │ ├── jump_examine.v │ │ ├── logic_unit.v │ │ ├── mem.v │ │ ├── my_cpu.v │ │ ├── npc.v │ │ ├── pc.v │ │ ├── reg_exe_mem.v │ │ ├── reg_file.v │ │ ├── reg_file_8.v │ │ ├── reg_id_exe.v │ │ ├── reg_if_id.v │ │ ├── reg_mem_wb.v │ │ ├── shift_unit.v │ │ └── top.v └── suspend │ ├── onBoard │ ├── alu.v │ ├── aluop_selector.v │ ├── arithmetic_unit.v │ ├── branch_unit.v │ ├── clock_divider.v │ ├── compare_unit.v │ ├── controler.v │ ├── data_hazard_detect.v │ ├── display.v │ ├── execute.v │ ├── imm_gen.v │ ├── instruction_decoder.v │ ├── instruction_fetch.v │ ├── irom.v │ ├── jump_examine.v │ ├── logic_unit.v │ ├── mem.v │ ├── my_cpu.v │ ├── npc.v │ ├── pc.v │ ├── reg_exe_mem.v │ ├── reg_file.v │ ├── reg_file_8.v │ ├── reg_id_exe.v │ ├── reg_if_id.v │ ├── reg_mem_wb.v │ ├── shift_unit.v │ └── top.v │ └── trace │ ├── alu.v │ ├── aluop_selector.v │ ├── arithmetic_unit.v │ ├── branch_unit.v │ ├── clock_divider.v │ ├── compare_unit.v │ ├── controler.v │ ├── data_hazard_detect.v │ ├── display.v │ ├── execute.v │ ├── imm_gen.v │ ├── instruction_decoder.v │ ├── instruction_fetch.v │ ├── irom.v │ ├── jump_examine.v │ ├── logic_unit.v │ ├── mem.v │ ├── my_cpu.v │ ├── npc.v │ ├── pc.v │ ├── reg_exe_mem.v │ ├── reg_file.v │ ├── reg_file_8.v │ ├── reg_id_exe.v │ ├── reg_if_id.v │ ├── reg_mem_wb.v │ ├── shift_unit.v │ └── top.v ├── readme.md └── single_cycle ├── obBoard ├── alu.v ├── aluop_selector.v ├── arithmetic_unit.v ├── branch_unit.v ├── clock_divider.v ├── compare_unit.v ├── controler.v ├── display.v ├── execute.v ├── imm_gen.v ├── instruction_decoder.v ├── instruction_fetch.v ├── irom.v ├── logic_unit.v ├── mem.v ├── my_cpu.v ├── npc.v ├── pc.v ├── reg_file.v ├── reg_file_8.v ├── shift_unit.v ├── tmp └── top.v └── trace ├── alu.v ├── aluop_selector.v ├── arithmetic_unit.v ├── branch_unit.v ├── compare_unit.v ├── controler.v ├── execute.v ├── imm_gen.v ├── instruction_decoder.v ├── instruction_fetch.v ├── irom.v ├── logic_unit.v ├── mem.v ├── my_cpu.v ├── npc.v ├── pc.v ├── reg_file.v ├── reg_file_8.v ├── shift_unit.v └── top.v /pipeline/forward/onBoard/alu.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 15:34:04 7 | // Design Name: 8 | // Module Name: alu 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 集成算数单元,逻辑运算单元,比较单元,移位单元,以及专用于b型指令的运算单元 14 | // alu_opcode的【3:2】用于选择不同单元的输出结果作为最终输出 15 | // alu_opcode的【1:0】作为不同单元的操作码 16 | // alu_opcode【4】专门用于lui指令直接输出op_b 17 | // Dependencies: 18 | // arithmetic_unit, compare_unit,logic_unit,shift_unit,branch_unit 19 | // Revision: 20 | // Revision 0.01 - File Created 21 | // Additional Comments: 22 | // 23 | ////////////////////////////////////////////////////////////////////////////////// 24 | module alu #( 25 | parameter ARITHMETiC = 2'b00, 26 | parameter COMPARE = 2'b01, 27 | parameter LOGIC = 2'b10, 28 | parameter SHIFT = 2'b11 29 | ) 30 | ( 31 | input [4:0] alu_opcode_i, 32 | input [31:0] alu_op_a_i, 33 | input [31:0] alu_op_b_i, 34 | output reg [31:0] alu_result_o, 35 | output branch_o 36 | ); 37 | wire [31:0] result_arithmetic; 38 | wire [31:0] result_compare; 39 | wire [31:0] result_logic; 40 | wire [31:0] result_shift; 41 | // 算数运算单元 42 | arithmetic_unit u_arithmetic_unit( 43 | .op_a_i (alu_op_a_i), 44 | .op_b_i (alu_op_b_i), 45 | .opcode_i(alu_opcode_i[1:0]), 46 | .result_o(result_arithmetic) 47 | ); 48 | // 比较操作单元 49 | compare_unit u_compare_unit( 50 | .op_a_i (alu_op_a_i), 51 | .op_b_i (alu_op_b_i), 52 | .opcode_i(alu_opcode_i[1:0]), 53 | .result_o(result_compare) 54 | ); 55 | // 逻辑运算单元 56 | logic_unit u_logic_unit( 57 | .op_a_i (alu_op_a_i), 58 | .op_b_i (alu_op_b_i), 59 | .opcode_i(alu_opcode_i[1:0]), 60 | .result_o(result_logic) 61 | ); 62 | // 移位运算单元 63 | shift_unit u_shift_unit( 64 | .op_a_i (alu_op_a_i), 65 | .op_b_i (alu_op_b_i), 66 | .opcode_i(alu_opcode_i[1:0]), 67 | .result_o(result_shift) 68 | ); 69 | // B型指令专用branch分支运算单元 70 | branch_unit u_branch_unit( 71 | .op_a_i (alu_op_a_i), 72 | .op_b_i (alu_op_b_i), 73 | .opcode_i(alu_opcode_i[3:0]), 74 | .branch (branch_o) 75 | ); 76 | // 根据opcode选择输出哪个单元的结果 77 | always @(*) begin 78 | // lui指令 79 | if(alu_opcode_i[4]) 80 | alu_result_o = alu_op_b_i; 81 | else 82 | case(alu_opcode_i[3:2]) 83 | ARITHMETiC: alu_result_o = result_arithmetic; 84 | COMPARE: alu_result_o = result_compare; 85 | LOGIC: alu_result_o = result_logic; 86 | SHIFT: alu_result_o = result_shift; 87 | endcase 88 | end 89 | 90 | endmodule 91 | -------------------------------------------------------------------------------- /pipeline/forward/onBoard/aluop_selector.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 14:47:37 7 | // Design Name: 8 | // Module Name: aluop_selector 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 根据op_A_sel和op_B_sel选择送入alu的操作输 14 | // op_A:1'b0: 当前pc 15 | // 1'b1: rD1 16 | // op_B:1'b0: imm 17 | // 1'b1: rD2 18 | // Dependencies: 19 | // 20 | // Revision: 21 | // Revision 0.01 - File Created 22 | // Additional Comments: 23 | // 24 | ////////////////////////////////////////////////////////////////////////////////// 25 | module aluop_selector #( 26 | parameter CURRENTPC = 1'b0, 27 | parameter RD1 = 1'b1, 28 | parameter EXT = 1'b0, 29 | parameter RD2 = 1'b1 30 | ) 31 | ( 32 | input op_A_sel_i, 33 | input op_B_sel_i, 34 | input [31:0] current_pc_i, 35 | input [31:0] rD1_i, 36 | input [31:0] rD2_i, 37 | input [31:0] ext_i, 38 | output reg [31:0] alu_op_a_o, 39 | output reg [31:0] alu_op_b_o 40 | ); 41 | // alu_a选择 42 | always @(*) begin 43 | case(op_A_sel_i) 44 | CURRENTPC: alu_op_a_o = current_pc_i; 45 | RD1: alu_op_a_o = rD1_i; 46 | default: alu_op_a_o = 32'h0; 47 | endcase 48 | end 49 | // alu_b选择 50 | always @(*) begin 51 | case(op_B_sel_i) 52 | EXT: alu_op_b_o = ext_i; 53 | RD2: alu_op_b_o = rD2_i; 54 | default: alu_op_b_o = 32'h0; 55 | endcase 56 | end 57 | endmodule 58 | -------------------------------------------------------------------------------- /pipeline/forward/onBoard/arithmetic_unit.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 15:41:40 7 | // Design Name: 8 | // Module Name: arithmetic_unit 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 算数运算单元,根据传入的两个操作数和操作码进行算术运算 14 | // opcode:00:加法 15 | // 01:减法 16 | // Dependencies: 17 | // 18 | // Revision: 19 | // Revision 0.01 - File Created 20 | // Additional Comments: 21 | // 22 | ////////////////////////////////////////////////////////////////////////////////// 23 | module arithmetic_unit #( 24 | parameter PLUS = 2'b00, 25 | parameter SUB = 2'b01, 26 | parameter UNKNOWN_OPCODE_RESULT = 32'h0 27 | ) 28 | ( 29 | input [31:0] op_a_i, 30 | input [31:0] op_b_i, 31 | input [1:0] opcode_i, 32 | output reg [31:0] result_o 33 | ); 34 | always @(*) begin 35 | case(opcode_i) 36 | PLUS: result_o = op_a_i + op_b_i; 37 | SUB: result_o = op_a_i + (~op_b_i+1'b1); // 采用加补码的方式实现减法 38 | default: result_o = UNKNOWN_OPCODE_RESULT; 39 | endcase 40 | end 41 | endmodule 42 | -------------------------------------------------------------------------------- /pipeline/forward/onBoard/branch_unit.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 16:45:19 7 | // Design Name: 8 | // Module Name: branch_unit 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // B型指令专用branch运算单元 14 | // 15 | // Dependencies: 16 | // 17 | // Revision: 18 | // Revision 0.01 - File Created 19 | // Additional Comments: 20 | // 21 | ////////////////////////////////////////////////////////////////////////////////// 22 | module branch_unit#( 23 | parameter EQ = 4'h0, 24 | parameter NEQ = 4'h1, 25 | parameter UNSIGNED_LT = 4'h2, 26 | parameter SIGNED_LT = 4'h3, 27 | parameter UNSIGNED_GE = 4'h4, 28 | parameter SIGNED_GE = 4'h5, 29 | parameter SUCCESS = 1'b1, 30 | parameter UNSUCCESS = 1'b0, 31 | parameter UNKNOWN_OPCODE_RESULT = 1'b0 32 | ) 33 | ( 34 | input [31:0] op_a_i, 35 | input [31:0] op_b_i, 36 | input [3:0] opcode_i, 37 | output reg branch 38 | ); 39 | reg [31:0] tmp; 40 | always @(*) begin 41 | tmp = op_a_i - op_b_i; 42 | end 43 | always @(*) begin 44 | case(opcode_i) 45 | EQ: branch = (tmp == 32'h0)?SUCCESS:UNSUCCESS; 46 | NEQ: branch = (tmp == 32'h0)?UNSUCCESS:SUCCESS; 47 | UNSIGNED_LT: branch = (op_a_i < op_b_i)?SUCCESS:UNSUCCESS; 48 | SIGNED_LT: begin 49 | // 对符号不同的情况特殊处理,防止发生溢出 50 | if(op_a_i[31] ^ op_b_i[31]) 51 | branch = op_a_i[31]; 52 | else 53 | branch = (tmp[31] == 1'b1)?SUCCESS:UNSUCCESS; 54 | end 55 | UNSIGNED_GE: branch = (op_a_i < op_b_i)?UNSUCCESS:SUCCESS; 56 | SIGNED_GE: begin 57 | // 对符号不同的情况特殊处理,防止发生溢出 58 | if(op_a_i[31] ^ op_b_i[31]) 59 | branch = op_b_i[31]; 60 | else 61 | branch = (tmp[31] == 1'b1)?UNSUCCESS:SUCCESS; 62 | end 63 | default: branch = UNKNOWN_OPCODE_RESULT; 64 | endcase 65 | end 66 | endmodule 67 | -------------------------------------------------------------------------------- /pipeline/forward/onBoard/clock_divider.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/05/11 18:57:50 7 | // Design Name: 8 | // Module Name: time 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | // 分频器,将高频时钟信号转化为低频时钟信号用于驱动数码管 22 | // 输入:时钟信号clk 23 | // 输出:低频时钟信号out 24 | module clock_divider( 25 | input clk, 26 | output reg out 27 | ); 28 | reg [15:0] cnt = 0; 29 | reg tag = 1'b0; 30 | always @ (posedge clk) begin 31 | if(tag == 1'b0) begin 32 | out = 1'b0; 33 | tag = 1'b1; 34 | end 35 | else begin 36 | if(cnt == 16'b1010_0001_0010_0000) begin //27'b101_1111_0101_1110_0001_0000_0000 37 | out = ~out; 38 | cnt = 0; 39 | end 40 | else begin 41 | cnt = cnt+1'b1; 42 | end 43 | end 44 | end 45 | endmodule 46 | -------------------------------------------------------------------------------- /pipeline/forward/onBoard/compare_unit.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 15:41:40 7 | // Design Name: 8 | // Module Name: compare_unit 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 比较运算单元,用于R型与I型指令 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module compare_unit #( 22 | parameter SIGNED = 2'b00, 23 | parameter UNSIGNED = 2'b01, 24 | parameter OTHERS = 32'h0, 25 | parameter SIGNED_LT = 32'h1, 26 | parameter UNSIGNED_LT = 32'h1, 27 | parameter UNKNOWN_OPCODE_RESULT = 32'h0 28 | ) 29 | ( 30 | input [31:0] op_a_i, 31 | input [31:0] op_b_i, 32 | input [1:0] opcode_i, 33 | output reg [31:0] result_o 34 | ); 35 | reg [31:0] tmp; 36 | always@(*) begin 37 | case(opcode_i) 38 | SIGNED: begin 39 | tmp = op_a_i - op_b_i; 40 | // 不同号 41 | if(op_a_i[31]^op_b_i[31]) 42 | result_o = op_a_i[31]; 43 | else 44 | result_o = (tmp[31]==1'b1)?SIGNED_LT:OTHERS; 45 | end 46 | UNSIGNED: begin 47 | result_o = (op_a_i < op_b_i)?UNSIGNED_LT:OTHERS; 48 | end 49 | default: 50 | result_o = UNKNOWN_OPCODE_RESULT; 51 | endcase 52 | end 53 | endmodule 54 | -------------------------------------------------------------------------------- /pipeline/forward/onBoard/data_hazard_detect.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/16 14:16:30 7 | // Design Name: 8 | // Module Name: suspend_o 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | 22 | 23 | module data_hazard_detect( 24 | input [4:0] rR1_id_exe_i, 25 | input [4:0] rR2_id_exe_i, 26 | input [4:0] wr_exe_mem_i, 27 | input [4:0] wr_mem_wb_i, 28 | input [4:0] wr_wb_i, 29 | input detect_r1, 30 | input detect_r2, 31 | output suspend_o 32 | ); 33 | // reg [1:0] cnt; 34 | // always @(posedge clk_i or posedge rst_i) begin 35 | // if(rst_i) 36 | // suspend_o <= 1'b0; 37 | // else begin 38 | // // 第一类数据冒险,相邻情况 39 | // if(rR1_id_exe_i == wr_exe_mem_i || rR2_id_exe_i == wr_exe_mem_i) 40 | // suspend_o <= 1'b1; 41 | // // 第二类数据冒险,相隔1条指令;第三类数据冒险,访存-读取型 42 | // else if(rR1_id_exe_i == wr_mem_wb_i || rR2_id_exe_i == wr_mem_wb_i) 43 | // suspend_o <= 1'b1; 44 | // else 45 | // suspend_o <= 1'b0; 46 | // end 47 | // end 48 | // always @(posedge clk_i or posedge rst_i) begin 49 | // if(rst_i) 50 | // cnt <= 2'h0; 51 | // else 52 | // if(cnt == 2'h0) begin 53 | // if((rR1_id_exe_i == wr_exe_mem_i || rR2_id_exe_i == wr_exe_mem_i)&&wr_exe_mem_i!=5'h0) 54 | // cnt <= 2'h3; 55 | // else if((rR1_id_exe_i == wr_mem_wb_i || rR2_id_exe_i == wr_mem_wb_i)&&wr_mem_wb_i!=5'h0) 56 | // cnt <= 2'h2; 57 | // else if((rR1_id_exe_i == wr_wb_i || rR2_id_exe_i == wr_wb_i)&&wr_wb_i!=5'h0) 58 | // cnt <= 2'h1; 59 | // else 60 | // cnt <= cnt; 61 | // end 62 | // else 63 | // cnt <= cnt - 1'h1; 64 | // end 65 | // assign suspend_o = (cnt==2'h0)?1'b0:1'b1; 66 | wire rR1_id_exe_hazard = (rR1_id_exe_i == wr_exe_mem_i)?(wr_exe_mem_i!=5'h0):1'b0; 67 | wire rR2_id_exe_hazard = (rR2_id_exe_i == wr_exe_mem_i)?(wr_exe_mem_i!=5'h0):1'b0; 68 | wire rR1_id_mem_hazard = (rR1_id_exe_i == wr_mem_wb_i)?(wr_mem_wb_i!=5'h0):1'b0; 69 | wire rR2_id_mem_hazard = (rR2_id_exe_i == wr_mem_wb_i)?(wr_mem_wb_i!=5'h0):1'b0; 70 | wire rR1_id_wb_hazard = (rR1_id_exe_i == wr_wb_i)?(wr_wb_i!=5'h0):1'b0; 71 | wire rR2_id_wb_hazard = (rR2_id_exe_i == wr_wb_i)?(wr_wb_i!=5'h0):1'b0; 72 | assign suspend_o = ((rR1_id_exe_hazard | rR1_id_mem_hazard | rR1_id_wb_hazard) & detect_r1) 73 | |((rR2_id_exe_hazard | rR2_id_mem_hazard | rR2_id_wb_hazard) & detect_r2); 74 | 75 | endmodule 76 | -------------------------------------------------------------------------------- /pipeline/forward/onBoard/execute.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 17:22:25 7 | // Design Name: 8 | // Module Name: execute 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 执行模块,集成alu和alu的数据选择器 14 | // Dependencies: 15 | // aluop_selector, alu 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module execute( 22 | input reset_i, 23 | input [1:0] pc_sel_i, 24 | input [31:0] pc_i, 25 | input branch_controler_i, 26 | input op_A_sel_i, 27 | input op_B_sel_i, 28 | input [31:0] current_pc_i, 29 | input [31:0] rD1_i, 30 | input [31:0] rD2_i, 31 | input [31:0] ext_i, 32 | input [4:0] alu_opcode_i, 33 | output [31:0] alu_result_o, 34 | // output alu_branch_o, 35 | output [31:0] next_pc_o 36 | ); 37 | wire [31:0] alu_op_a; 38 | wire [31:0] alu_op_b; 39 | wire alu_branch; 40 | wire branch = branch_controler_i & alu_branch; 41 | aluop_selector u_aluop_selector( 42 | .op_A_sel_i (op_A_sel_i), 43 | .op_B_sel_i (op_B_sel_i), 44 | .current_pc_i(current_pc_i), 45 | .rD1_i (rD1_i), 46 | .rD2_i (rD2_i), 47 | .ext_i (ext_i ), 48 | .alu_op_a_o (alu_op_a), 49 | .alu_op_b_o (alu_op_b) 50 | ); 51 | alu u_alu( 52 | .alu_opcode_i (alu_opcode_i), 53 | .alu_op_a_i (alu_op_a), 54 | .alu_op_b_i (alu_op_b), 55 | .alu_result_o (alu_result_o), 56 | .branch_o (alu_branch) 57 | ); 58 | npc u_npc( 59 | .reset_i (reset_i), 60 | .pc_sel_i (pc_sel_i), 61 | .pc_i (pc_i), 62 | .offset_i (ext_i), 63 | .rD1_i (rD1_i), 64 | .branch_i (branch), 65 | .next_pc_o(next_pc_o) 66 | ); 67 | endmodule 68 | -------------------------------------------------------------------------------- /pipeline/forward/onBoard/forward_unit.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ps 2 | module forward_unit( 3 | input clk_i, 4 | input rst_i, 5 | input [4:0] rR1_id_exe_i, 6 | input [4:0] rR2_id_exe_i, 7 | input [4:0] wr_exe_mem_i, 8 | input [4:0] wr_mem_wb_i, 9 | input [4:0] wr_wb_i, 10 | input [31:0] data_exe_i, 11 | input [31:0] data_mem_i, 12 | input [31:0] data_wb_i, 13 | input detect_r1_i, 14 | input detect_r2_i, 15 | input is_load_i, 16 | input is_sb_exe_i, 17 | input is_sb_mem_i, 18 | output [31:0] forward_data_1_o, 19 | output [31:0] forward_data_2_o, 20 | output reg r1_select_i, 21 | output reg r2_select_i, 22 | output suspend_o 23 | ); 24 | reg [31:0] data_1; 25 | reg [31:0] data_2; 26 | always @(*) begin 27 | if(detect_r1_i) begin 28 | if(rR1_id_exe_i == wr_exe_mem_i) begin 29 | data_1 = data_exe_i; 30 | r1_select_i = (wr_exe_mem_i!=5'h0) & ~is_sb_exe_i; 31 | end 32 | else if(rR1_id_exe_i == wr_mem_wb_i) begin 33 | data_1 = data_mem_i; 34 | r1_select_i = (wr_mem_wb_i!=5'h0) & ~is_sb_mem_i; 35 | end 36 | else if(rR1_id_exe_i == wr_wb_i) begin 37 | data_1 = data_wb_i; 38 | r1_select_i = (wr_wb_i!=5'h0); 39 | end 40 | else 41 | r1_select_i = 1'b0; 42 | end 43 | else 44 | r1_select_i = 1'b0; 45 | end 46 | 47 | always @(*) begin 48 | if(detect_r2_i) begin 49 | if(rR2_id_exe_i == wr_exe_mem_i) begin 50 | data_2 = data_exe_i; 51 | r2_select_i = (wr_exe_mem_i!=5'h0) & ~is_sb_exe_i; 52 | end 53 | else if(rR2_id_exe_i == wr_mem_wb_i) begin 54 | data_2 = data_mem_i; 55 | r2_select_i = (wr_mem_wb_i!=5'h0) & ~is_sb_mem_i; 56 | end 57 | else if(rR2_id_exe_i == wr_wb_i) begin 58 | data_2 = data_wb_i; 59 | r2_select_i = (wr_wb_i!=5'h0); 60 | end 61 | else 62 | r2_select_i = 1'b0; 63 | end 64 | else 65 | r2_select_i = 1'b0; 66 | end 67 | 68 | assign forward_data_1_o = data_1; 69 | assign forward_data_2_o = data_2; 70 | // always @(posedge clk_i or posedge rst_i) begin 71 | // if(rst_i) 72 | // suspend_o <= 1'b0; 73 | // else 74 | // if(is_load_i) begin 75 | // if(rR1_id_exe_i == wr_exe_mem_i) 76 | // suspend_o <= 1'b1; 77 | // else if(rR2_id_exe_i == wr_exe_mem_i) 78 | // suspend_o <= 1'b1; 79 | // else 80 | // suspend_o <= 1'b0; 81 | // end 82 | // else 83 | // suspend_o <= 1'b0; 84 | // end 85 | wire suspend_1 = is_load_i & (rR1_id_exe_i == wr_exe_mem_i) & detect_r1_i; 86 | wire suspend_2 = is_load_i & (rR2_id_exe_i == wr_exe_mem_i) & detect_r2_i; 87 | assign suspend_o = suspend_1 | suspend_2; 88 | endmodule -------------------------------------------------------------------------------- /pipeline/forward/onBoard/imm_gen.v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yikai-coder/HITsz_CPU_design/c1d6cea65b82fd382c3bf34725d2e8ccb11a9936/pipeline/forward/onBoard/imm_gen.v -------------------------------------------------------------------------------- /pipeline/forward/onBoard/instruction_decoder.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/01 17:00:09 7 | // Design Name: 8 | // Module Name: imm_gen 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 译码模块,集成寄存器堆和立即数生成模块 14 | // Dependencies: 15 | // reg_file,imm_gen 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module instruction_decoder #( 22 | parameter RETURN_PC = 2'b00, 23 | parameter ALU_RESULT = 2'b01, 24 | parameter MEM_DATA = 2'b10 25 | ) 26 | ( 27 | input reset_i, 28 | input [31:0] return_pc_i, 29 | input [31:0] ALU_result_i, 30 | input [31:0] mem_data_i, 31 | input [1:0] wd_sel_i, 32 | input [4:0] wr_i, 33 | input we_i, 34 | input clk_i, 35 | input [31:0] inst_i, 36 | input [2:0] imm_sel_i, 37 | input [31:0] forward_data_1_i, 38 | input [31:0] forward_data_2_i, 39 | input r1_select_i, 40 | input r2_select_i, 41 | output [31:0] wd_o, // test 42 | output [31:0] ext_o, 43 | output [31:0] rD1_o, 44 | output [31:0] rD2_o, 45 | output [31:0] rD19_o 46 | // output reg write_back // 写回阶段信号 47 | ); 48 | 49 | reg [31:0] wD; 50 | reg [4:0] wr; 51 | wire [31:0] rD1; 52 | wire [31:0] rD2; 53 | 54 | // 根据wd_sel选择写入数据 55 | // 写入寄存器恒为inst[11:7] 56 | always @(*) begin 57 | case(wd_sel_i) 58 | RETURN_PC: begin 59 | wD = return_pc_i; 60 | end 61 | ALU_RESULT: begin 62 | wD = ALU_result_i; 63 | end 64 | MEM_DATA: begin 65 | wD = mem_data_i; 66 | end 67 | default: begin 68 | wD = 32'h0; 69 | end 70 | endcase 71 | end 72 | assign wd_o = wD; 73 | 74 | reg_file u_reg_file( 75 | .clk_i (clk_i), 76 | .reset_i (reset_i), 77 | .rR1_i (inst_i[19:15]), 78 | .rR2_i (inst_i[24:20]), 79 | .wR_i (wr_i), 80 | .wD_i (wD), 81 | .WE_i (we_i), 82 | .rD1_o (rD1), 83 | .rD2_o (rD2), 84 | .rD19_o (rD19_o) 85 | ); 86 | // assign we_o = we_i; 87 | // assign wD_o = wD; 88 | // assign wR_o = wr; 89 | assign rD1_o = (r1_select_i==1'b1)?forward_data_1_i:rD1; 90 | assign rD2_o = (r2_select_i==1'b1)?forward_data_2_i:rD2; 91 | 92 | imm_gen u_imm_gen( 93 | .reset_i (reset_i), 94 | .inst_i (inst_i), 95 | .imm_sel_i (imm_sel_i), 96 | .ext_o (ext_o) 97 | ); 98 | endmodule 99 | -------------------------------------------------------------------------------- /pipeline/forward/onBoard/instruction_fetch.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/01 15:31:29 7 | // Design Name: 8 | // Module Name: instruction_fetch 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 取指模块 14 | // 包含pc,npc,irom三个子模块 15 | // Dependencies: 16 | // 17 | // Revision: 18 | // Revision 0.01 - File Created 19 | // Additional Comments: 20 | // 21 | ////////////////////////////////////////////////////////////////////////////////// 22 | module instruction_fetch( 23 | input clk_i, 24 | input reset_i, 25 | input [31:0] next_pc_i, 26 | input data_suspend_i, 27 | input flush_i, 28 | output [31:0] inst_o, 29 | output [31:0] return_pc_o, 30 | output [31:0] current_pc_o // 用于auipc 31 | ); 32 | // wire [31:0] npc; 33 | wire [31:0] pc; 34 | assign current_pc_o = pc; 35 | assign return_pc_o = pc + 3'h4; 36 | pc u_pc( 37 | .npc_i (next_pc_i), 38 | .clk_i (clk_i), 39 | .reset_i (reset_i), 40 | .data_suspend_i (data_suspend_i), 41 | .flush_i (flush_i), 42 | .pc_o (pc) 43 | ); 44 | // npc模块转移到EXE中 45 | // npc u_npc( 46 | // .reset_i (reset_i), 47 | // .pc_sel_i (pc_sel_i), 48 | // .pc_i (pc), 49 | // .offset_i (offset_i), 50 | // .rD1_i (rD1_i), 51 | // .branch_i (branch_i), 52 | // .next_pc_o (npc), 53 | // .pc_plus_4_o(return_pc_o) 54 | // // ); 55 | irom u_irom( 56 | .pc_i (pc), 57 | .inst_o(inst_o) 58 | ); 59 | // prgom u_prgom( 60 | // .pc_i (pc), 61 | // .inst_o(inst_o) 62 | // ); 63 | endmodule 64 | -------------------------------------------------------------------------------- /pipeline/forward/onBoard/irom.v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yikai-coder/HITsz_CPU_design/c1d6cea65b82fd382c3bf34725d2e8ccb11a9936/pipeline/forward/onBoard/irom.v -------------------------------------------------------------------------------- /pipeline/forward/onBoard/jump_examine.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/16 15:03:15 7 | // Design Name: 8 | // Module Name: jump_examine 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 放置在if模块后方检测跳转指令的出现 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | 22 | 23 | module jump_examine #( 24 | parameter JALR_OPCODE = 7'b1100111, 25 | parameter B_OPCODE = 7'b1100011, 26 | parameter JAL_OPCODE = 7'b1101111 27 | ) 28 | ( 29 | input clk_i, 30 | input rst_i, 31 | input [31:0] npc_i, 32 | input [31:0] current_pc_i, 33 | output flush_o 34 | ); 35 | // reg [31:0] pc_1; 36 | // reg [31:0] pc_2; 37 | // always @(posedge clk_i or posedge rst_i) begin 38 | // if(rst_i) begin 39 | // pc_1 <= 32'hfffffffc; 40 | // pc_2 <= 32'hfffffffc; 41 | // end 42 | // else begin 43 | // pc_2 <= pc_1; 44 | // pc_1 <= current_pc_i; 45 | // end 46 | // end 47 | assign flush_o = (npc_i!=current_pc_i+3'h4); 48 | endmodule 49 | -------------------------------------------------------------------------------- /pipeline/forward/onBoard/logic_unit.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 15:41:40 7 | // Design Name: 8 | // Module Name: logic_unit 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // alu下的逻辑运算单元 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module logic_unit #( 22 | parameter AND = 2'b00, 23 | parameter OR = 2'b01, 24 | parameter XOR = 2'b10, 25 | parameter UNKNOWN_OPCODE_RESULT = 32'h0 26 | ) 27 | ( 28 | input [31:0] op_a_i, 29 | input [31:0] op_b_i, 30 | input [1:0] opcode_i, 31 | output reg [31:0] result_o 32 | ); 33 | always @(*) begin 34 | case(opcode_i) 35 | AND: result_o = op_a_i & op_b_i; 36 | OR: result_o = op_a_i | op_b_i; 37 | XOR: result_o = op_a_i ^ op_b_i; 38 | default: result_o = UNKNOWN_OPCODE_RESULT; 39 | endcase 40 | end 41 | endmodule 42 | -------------------------------------------------------------------------------- /pipeline/forward/onBoard/npc.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/01 14:28:45 7 | // Design Name: 8 | // Module Name: npc 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // npc数据处理,根据pc_sel输出不同指令对应的下一周期pc信号 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module npc #( 22 | parameter INTERPRETER_NPC = 32'b0 // 对应pc_sel信号异常,转入中断处理 23 | ) 24 | ( 25 | input reset_i, 26 | input [1:0] pc_sel_i, 27 | input [31:0] pc_i, 28 | input [31:0] offset_i, 29 | input [31:0] rD1_i, 30 | input branch_i, 31 | output reg [31:0] next_pc_o, 32 | output [31:0] pc_plus_4_o // 用于jal指令与jalr指令 33 | ); 34 | always @(*) begin 35 | if(reset_i == 1'b1) 36 | next_pc_o = pc_i; 37 | else begin 38 | case (pc_sel_i) 39 | 2'b00: next_pc_o = pc_i + 3'b100; // pc+4 40 | 2'b01: next_pc_o = (branch_i==1'b1)?pc_i+offset_i:pc_i+3'b100; //Branch 41 | 2'b10: next_pc_o = pc_i+offset_i; // jal 42 | 2'b11: next_pc_o = (rD1_i+offset_i)&(~1); // jalr 43 | default: 44 | next_pc_o = INTERPRETER_NPC; 45 | endcase 46 | end 47 | end 48 | assign pc_plus_4_o = pc_i+3'b100; 49 | endmodule 50 | -------------------------------------------------------------------------------- /pipeline/forward/onBoard/pc.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/01 14:22:58 7 | // Design Name: 8 | // Module Name: pc 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // PC寄存器,在每个时钟上升沿将前一个周期送入的npc输出 14 | // 在复位信号送来时输出复位后首条指令的PC值 15 | // Dependencies: 16 | // 17 | // Revision: 18 | // Revision 0.01 - File Created 19 | // Additional Comments: 20 | // 21 | ////////////////////////////////////////////////////////////////////////////////// 22 | module pc#( 23 | parameter INIT_PC = 32'hfffffffc // 假设0为CPU复位后的首条指令对应地址 24 | ) 25 | ( 26 | input [31:0] npc_i, 27 | input clk_i, 28 | input reset_i, 29 | input data_suspend_i, 30 | input flush_i, 31 | output reg [31:0] pc_o 32 | ); 33 | reg first_time; // 用于防止reset失效的当个周期时间不够无法完成一条指令,将第一条指令的执行时间推迟到下一次时钟上升沿到来 34 | // always @(posedge clk_i or posedge reset_i) begin 35 | // if(reset_i) begin 36 | // pc_o <= INIT_PC; 37 | // first_time <= 1'b0; 38 | // end 39 | // else begin 40 | // first_time <= 1'b1; 41 | // if(first_time == 1'b0) 42 | // pc_o <= INIT_PC; 43 | // else 44 | // // pc_o <= npc_i; 45 | // if(data_suspend_i) 46 | // pc_o <= pc_o; 47 | // else if(flush_i) 48 | // pc_o <= npc_i; 49 | // else 50 | // pc_o <= pc_o + 3'h4; 51 | // end 52 | // end 53 | always @(posedge clk_i or posedge reset_i) begin 54 | if(reset_i) 55 | pc_o <= INIT_PC; 56 | else 57 | if(flush_i) 58 | pc_o <= npc_i; 59 | else if(data_suspend_i) 60 | pc_o <= pc_o; 61 | else 62 | pc_o <= pc_o + 3'h4; 63 | end 64 | endmodule 65 | -------------------------------------------------------------------------------- /pipeline/forward/onBoard/reg_exe_mem.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ps 2 | module reg_exe_mem( 3 | input clk_i, 4 | input rst_i, 5 | input [31:0] alu_result_i, 6 | input [31:0] mem_wd_i, 7 | input mem_we_i, 8 | input [1:0] mem_data_sel_i, 9 | input [4:0] wr_i, 10 | input [1:0] wd_sel_i, 11 | input regfile_we_i, 12 | input [31:0] return_pc_i, 13 | input [31:0] current_pc_i, 14 | input is_sb_i, 15 | output reg [31:0] current_pc_o, 16 | output reg [31:0] alu_result_o, 17 | output reg [31:0] mem_wd_o, 18 | output reg mem_we_o, 19 | output reg [1:0] mem_data_sel_o, 20 | output reg [4:0] wr_o, 21 | output reg [1:0] wd_sel_o, 22 | output reg regfile_we_o, 23 | output reg [31:0] return_pc_o, 24 | output reg is_sb_o 25 | ); 26 | always @(posedge clk_i or posedge rst_i) begin 27 | if(rst_i) 28 | alu_result_o <= 32'h0; 29 | else 30 | alu_result_o <= alu_result_i; 31 | end 32 | always @(posedge clk_i or posedge rst_i) begin 33 | if(rst_i) 34 | mem_wd_o <= 32'h0; 35 | else 36 | mem_wd_o <= mem_wd_i; 37 | end 38 | always @(posedge clk_i or posedge rst_i) begin 39 | if(rst_i) 40 | mem_we_o <= 1'b0; 41 | else 42 | mem_we_o <= mem_we_i; 43 | end 44 | always @(posedge clk_i or posedge rst_i) begin 45 | if(rst_i) 46 | mem_data_sel_o <= 2'h0; 47 | else 48 | mem_data_sel_o <= mem_data_sel_i; 49 | end 50 | always @(posedge clk_i or posedge rst_i) begin 51 | if(rst_i) 52 | wr_o <= 4'h0; 53 | else 54 | wr_o <= wr_i; 55 | end 56 | always @(posedge clk_i or posedge rst_i) begin 57 | if(rst_i) 58 | wd_sel_o <= 2'h0; 59 | else 60 | wd_sel_o <= wd_sel_i; 61 | end 62 | always @(posedge clk_i or posedge rst_i) begin 63 | if(rst_i) 64 | regfile_we_o <= 1'b0; 65 | else 66 | regfile_we_o <= regfile_we_i; 67 | end 68 | always @(posedge clk_i or posedge rst_i) begin 69 | if(rst_i) 70 | return_pc_o <= 32'h0; 71 | else 72 | return_pc_o <= return_pc_i; 73 | end 74 | always @(posedge clk_i or posedge rst_i) begin 75 | if(rst_i) 76 | current_pc_o <= 32'h0; 77 | else 78 | current_pc_o <= current_pc_i; 79 | end 80 | always @(posedge clk_i or posedge rst_i) begin 81 | if(rst_i) 82 | is_sb_o <= 1'b0; 83 | else 84 | is_sb_o <= is_sb_i; 85 | end 86 | 87 | endmodule -------------------------------------------------------------------------------- /pipeline/forward/onBoard/reg_file_8.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/01 14:22:58 7 | // Design Name: 8 | // Module Name: pc 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 寄存器堆模块的子模块,每个模块存储8个寄存器 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module reg_file_8( 22 | input clk_i, 23 | input reset_i, 24 | input [4:0] rR1_i, 25 | input [4:0] rR2_i, 26 | input [4:0] wR_i, 27 | input [31:0] wD_i, 28 | input WE_i, 29 | output reg [31:0] rD1_o, 30 | output reg [31:0] rD2_o, 31 | output [31:0] rD19_o 32 | ); 33 | reg [31:0] reg_0; 34 | reg [31:0] reg_1; 35 | reg [31:0] reg_2; 36 | reg [31:0] reg_3; 37 | reg [31:0] reg_4; 38 | reg [31:0] reg_5; 39 | reg [31:0] reg_6; 40 | reg [31:0] reg_7; 41 | assign rD19_o = reg_3; 42 | // rD1_o 43 | always @ (*) begin 44 | case(rR1_i[2:0]) 45 | 3'b000: rD1_o = (rR1_i[4:3]==2'b00)?32'h0:reg_0; // x0不可被修改 46 | 3'b001: rD1_o = reg_1; 47 | 3'b010: rD1_o = reg_2; 48 | 3'b011: rD1_o = reg_3; 49 | 3'b100: rD1_o = reg_4; 50 | 3'b101: rD1_o = reg_5; 51 | 3'b110: rD1_o = reg_6; 52 | 3'b111: rD1_o = reg_7; 53 | default: rD1_o = 32'h0; 54 | endcase 55 | end 56 | // rD2_o 57 | always @ (*) begin 58 | case(rR2_i[2:0]) 59 | 3'b000: rD2_o = (rR2_i[4:3]==2'b00)?32'h0:reg_0; 60 | 3'b001: rD2_o = reg_1; 61 | 3'b010: rD2_o = reg_2; 62 | 3'b011: rD2_o = reg_3; 63 | 3'b100: rD2_o = reg_4; 64 | 3'b101: rD2_o = reg_5; 65 | 3'b110: rD2_o = reg_6; 66 | 3'b111: rD2_o = reg_7; 67 | default: rD2_o = 32'h0; 68 | endcase 69 | end 70 | // wirte 71 | always @ (posedge clk_i or posedge reset_i) begin 72 | if(reset_i == 1'b1) begin 73 | reg_0 = 32'h0; 74 | reg_1 = 32'h0; 75 | reg_2 = 32'h0; 76 | reg_3 = 32'h0; 77 | reg_4 = 32'h0; 78 | reg_5 = 32'h0; 79 | reg_6 = 32'h0; 80 | reg_7 = 32'h0; 81 | end 82 | else 83 | if(WE_i == 1'b1) begin 84 | case(wR_i[2:0]) 85 | 3'b000: reg_0 = (wR_i[4:3]==2'b00)?32'h0:wD_i; 86 | 3'b001: reg_1 = wD_i; 87 | 3'b010: reg_2 = wD_i; 88 | 3'b011: reg_3 = wD_i; 89 | 3'b100: reg_4 = wD_i; 90 | 3'b101: reg_5 = wD_i; 91 | 3'b110: reg_6 = wD_i; 92 | 3'b111: reg_7 = wD_i; 93 | default:; 94 | endcase 95 | end 96 | else; 97 | end 98 | endmodule 99 | -------------------------------------------------------------------------------- /pipeline/forward/onBoard/reg_if_id.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ps 2 | // IF/ID流水线寄存器 3 | module reg_if_id #( 4 | parameter INIT_PC = 32'h0 5 | ) 6 | ( 7 | input clk_i, 8 | input rst_i, 9 | input [31:0] inst_i, 10 | input [31:0] current_pc_i, 11 | input [31:0] return_pc_i, 12 | input suspend_i, 13 | input flush_i, 14 | output reg [31:0] inst_o, 15 | output reg [31:0] current_pc_o, 16 | output reg [31:0] return_pc_o 17 | ); 18 | always @(posedge clk_i or posedge rst_i) begin 19 | if(rst_i) 20 | inst_o <= INIT_PC; 21 | else 22 | if(flush_i) 23 | inst_o <= INIT_PC; 24 | else if(suspend_i) 25 | inst_o <= inst_o; 26 | else 27 | inst_o <= inst_i; 28 | end 29 | always @(posedge clk_i or posedge rst_i) begin 30 | if(rst_i) 31 | current_pc_o <= 32'h0; 32 | else 33 | if(flush_i) 34 | current_pc_o <= 32'h0; 35 | else if(suspend_i) 36 | current_pc_o <= current_pc_o; 37 | else 38 | current_pc_o <= current_pc_i; 39 | end 40 | always @(posedge clk_i or posedge rst_i) begin 41 | if(rst_i) 42 | return_pc_o <= 32'h0; 43 | else 44 | if(flush_i) 45 | return_pc_o <= 32'h0; 46 | else if(suspend_i) 47 | return_pc_o <= return_pc_o; 48 | else 49 | return_pc_o <= return_pc_i; 50 | end 51 | endmodule -------------------------------------------------------------------------------- /pipeline/forward/onBoard/reg_mem_wb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/14 09:22:34 7 | // Design Name: 8 | // Module Name: reg_mem_wb 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module reg_mem_wb( 22 | input clk_i, 23 | input rst_i, 24 | input [31:0] return_pc_i, 25 | input [31:0] alu_result_i, 26 | input [31:0] mem_rd_i, 27 | input [4:0] wr_i, 28 | input [1:0] wd_sel_i, 29 | input regfile_we_i, 30 | input [31:0] current_pc_i, 31 | output reg [31:0] current_pc_o, 32 | output reg [31:0] return_pc_o, 33 | output reg [31:0] alu_result_o, 34 | output reg [31:0] mem_rd_o, 35 | output reg [4:0] wr_o, 36 | output reg [1:0] wd_sel_o, 37 | output reg regfile_we_o 38 | ); 39 | always @(posedge clk_i or posedge rst_i) begin 40 | if(rst_i) 41 | return_pc_o <= 32'h0; 42 | else 43 | return_pc_o <= return_pc_i; 44 | end 45 | always @(posedge clk_i or posedge rst_i) begin 46 | if(rst_i) 47 | alu_result_o <= 32'h0; 48 | else 49 | alu_result_o <= alu_result_i; 50 | end 51 | always @(posedge clk_i or posedge rst_i) begin 52 | if(rst_i) 53 | mem_rd_o <= 32'h0; 54 | else 55 | mem_rd_o <= mem_rd_i; 56 | end 57 | always @(posedge clk_i or posedge rst_i) begin 58 | if(rst_i) 59 | wr_o <= 5'h0; 60 | else 61 | wr_o <= wr_i; 62 | end 63 | always @(posedge clk_i or posedge rst_i) begin 64 | if(rst_i) 65 | wd_sel_o <= 2'h0; 66 | else 67 | wd_sel_o <= wd_sel_i; 68 | end 69 | always @(posedge clk_i or posedge rst_i) begin 70 | if(rst_i) 71 | regfile_we_o <= 1'b0; 72 | else 73 | regfile_we_o <= regfile_we_i; 74 | end 75 | always @(posedge clk_i or posedge rst_i) begin 76 | if(rst_i) 77 | current_pc_o <= 32'h0; 78 | else 79 | current_pc_o <= current_pc_i; 80 | end 81 | endmodule 82 | -------------------------------------------------------------------------------- /pipeline/forward/onBoard/shift_unit.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 15:41:40 7 | // Design Name: 8 | // Module Name: shift_unit 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // alu下的移位操作单元,通过桶形移位器实现 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module shift_unit #( 22 | parameter LEFT_SHIFT = 2'b00, 23 | parameter RIGHT_LOGIC_SHIFT = 2'b01, 24 | parameter RIGHT_ARITHMETIC_SHIFT = 2'b10, 25 | parameter UNKNOWN_OPCODE_RESULT = 32'h0 26 | ) 27 | ( 28 | input [31:0] op_a_i, 29 | input [31:0] op_b_i, // 实际只有低5位有效,高位是拓展而来 30 | input [1:0] opcode_i, 31 | output [31:0] result_o 32 | ); 33 | reg [31:0] tmp; 34 | always @(*) begin 35 | case(opcode_i) 36 | LEFT_SHIFT:begin 37 | tmp = (op_b_i[0]==1'b1)?{op_a_i[30:0], 1'b0} :op_a_i; 38 | tmp = (op_b_i[1]==1'b1)?{tmp[29:0], 2'b0} :tmp; 39 | tmp = (op_b_i[2]==1'b1)?{tmp[27:0], 4'b0} :tmp; 40 | tmp = (op_b_i[3]==1'b1)?{tmp[23:0], 8'b0} :tmp; 41 | tmp = (op_b_i[4]==1'b1)?{tmp[15:0], 16'b0} :tmp; 42 | end 43 | RIGHT_LOGIC_SHIFT:begin 44 | tmp = (op_b_i[0]==1'b1)?{1'b0, op_a_i[31:1]}:op_a_i; 45 | tmp = (op_b_i[1]==1'b1)?{2'b0, tmp[31:2]} :tmp; 46 | tmp = (op_b_i[2]==1'b1)?{4'b0, tmp[31:4]} :tmp; 47 | tmp = (op_b_i[3]==1'b1)?{8'b0, tmp[31:8]} :tmp; 48 | tmp = (op_b_i[4]==1'b1)?{16'b0, tmp[31:16]} :tmp; 49 | end 50 | RIGHT_ARITHMETIC_SHIFT: begin 51 | tmp = (op_b_i[0]==1'b1)?{{1{op_a_i[31]}}, op_a_i[31:1]}:op_a_i; 52 | tmp = (op_b_i[1]==1'b1)?{{2{op_a_i[31]}}, tmp[31:2]} :tmp; 53 | tmp = (op_b_i[2]==1'b1)?{{4{op_a_i[31]}}, tmp[31:4]} :tmp; 54 | tmp = (op_b_i[3]==1'b1)?{{8{op_a_i[31]}}, tmp[31:8]} :tmp; 55 | tmp = (op_b_i[4]==1'b1)?{{16{op_a_i[31]}}, tmp[31:16]} :tmp; 56 | end 57 | default: tmp = UNKNOWN_OPCODE_RESULT; 58 | endcase 59 | end 60 | assign result_o = tmp; 61 | endmodule 62 | -------------------------------------------------------------------------------- /pipeline/forward/onBoard/top.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/08 14:10:06 7 | // Design Name: 8 | // Module Name: top 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module top( 22 | input clk_i, 23 | input rst_i, 24 | output wire led0_en, 25 | output wire led1_en, 26 | output wire led2_en, 27 | output wire led3_en, 28 | output wire led4_en, 29 | output wire led5_en, 30 | output wire led6_en, 31 | output wire led7_en, 32 | output wire led_ca , 33 | output wire led_cb , 34 | output wire led_cc , 35 | output wire led_cd , 36 | output wire led_ce , 37 | output wire led_cf , 38 | output wire led_cg , 39 | output wire led_dp 40 | ); 41 | wire [31:0] rD19; 42 | wire clk_display; 43 | wire rst_n = ~rst_i; 44 | my_cpu u_my_cpu( 45 | .sysclk_i(clk_i), 46 | .reset_i (rst_i), 47 | .rD19_o (rD19) 48 | ); 49 | clock_divider u_clock_divider( 50 | .clk(clk_i), 51 | .out(clk_display) 52 | ); 53 | display u_display( 54 | .clk (clk_display), 55 | .rst_n(rst_n), 56 | .busy (1'b0), 57 | .z1 (rD19[31:24]), 58 | .r1 (rD19[23:16]), 59 | .z2 (rD19[15:8]), 60 | .r2 (rD19[7:0]), 61 | .led0_en(led0_en), 62 | .led1_en(led1_en), 63 | .led2_en(led2_en), 64 | .led3_en(led3_en), 65 | .led4_en(led4_en), 66 | .led5_en(led5_en), 67 | .led6_en(led6_en), 68 | .led7_en(led7_en), 69 | .led_ca (led_ca), 70 | .led_cb (led_cb), 71 | .led_cc (led_cc), 72 | .led_cd (led_cd), 73 | .led_ce (led_ce), 74 | .led_cf (led_cf), 75 | .led_cg (led_cg), 76 | .led_dp (led_dp) 77 | ); 78 | 79 | endmodule 80 | -------------------------------------------------------------------------------- /pipeline/forward/trace/alu.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 15:34:04 7 | // Design Name: 8 | // Module Name: alu 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 集成算数单元,逻辑运算单元,比较单元,移位单元,以及专用于b型指令的运算单元 14 | // alu_opcode的【3:2】用于选择不同单元的输出结果作为最终输出 15 | // alu_opcode的【1:0】作为不同单元的操作码 16 | // alu_opcode【4】专门用于lui指令直接输出op_b 17 | // Dependencies: 18 | // arithmetic_unit, compare_unit,logic_unit,shift_unit,branch_unit 19 | // Revision: 20 | // Revision 0.01 - File Created 21 | // Additional Comments: 22 | // 23 | ////////////////////////////////////////////////////////////////////////////////// 24 | module alu #( 25 | parameter ARITHMETiC = 2'b00, 26 | parameter COMPARE = 2'b01, 27 | parameter LOGIC = 2'b10, 28 | parameter SHIFT = 2'b11 29 | ) 30 | ( 31 | input [4:0] alu_opcode_i, 32 | input [31:0] alu_op_a_i, 33 | input [31:0] alu_op_b_i, 34 | output reg [31:0] alu_result_o, 35 | output branch_o 36 | ); 37 | wire [31:0] result_arithmetic; 38 | wire [31:0] result_compare; 39 | wire [31:0] result_logic; 40 | wire [31:0] result_shift; 41 | // 算数运算单元 42 | arithmetic_unit u_arithmetic_unit( 43 | .op_a_i (alu_op_a_i), 44 | .op_b_i (alu_op_b_i), 45 | .opcode_i(alu_opcode_i[1:0]), 46 | .result_o(result_arithmetic) 47 | ); 48 | // 比较操作单元 49 | compare_unit u_compare_unit( 50 | .op_a_i (alu_op_a_i), 51 | .op_b_i (alu_op_b_i), 52 | .opcode_i(alu_opcode_i[1:0]), 53 | .result_o(result_compare) 54 | ); 55 | // 逻辑运算单元 56 | logic_unit u_logic_unit( 57 | .op_a_i (alu_op_a_i), 58 | .op_b_i (alu_op_b_i), 59 | .opcode_i(alu_opcode_i[1:0]), 60 | .result_o(result_logic) 61 | ); 62 | // 移位运算单元 63 | shift_unit u_shift_unit( 64 | .op_a_i (alu_op_a_i), 65 | .op_b_i (alu_op_b_i), 66 | .opcode_i(alu_opcode_i[1:0]), 67 | .result_o(result_shift) 68 | ); 69 | // B型指令专用branch分支运算单元 70 | branch_unit u_branch_unit( 71 | .op_a_i (alu_op_a_i), 72 | .op_b_i (alu_op_b_i), 73 | .opcode_i(alu_opcode_i[3:0]), 74 | .branch (branch_o) 75 | ); 76 | // 根据opcode选择输出哪个单元的结果 77 | always @(*) begin 78 | // lui指令 79 | if(alu_opcode_i[4]) 80 | alu_result_o = alu_op_b_i; 81 | else 82 | case(alu_opcode_i[3:2]) 83 | ARITHMETiC: alu_result_o = result_arithmetic; 84 | COMPARE: alu_result_o = result_compare; 85 | LOGIC: alu_result_o = result_logic; 86 | SHIFT: alu_result_o = result_shift; 87 | endcase 88 | end 89 | 90 | endmodule 91 | -------------------------------------------------------------------------------- /pipeline/forward/trace/aluop_selector.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 14:47:37 7 | // Design Name: 8 | // Module Name: aluop_selector 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 根据op_A_sel和op_B_sel选择送入alu的操作输 14 | // op_A:1'b0: 当前pc 15 | // 1'b1: rD1 16 | // op_B:1'b0: imm 17 | // 1'b1: rD2 18 | // Dependencies: 19 | // 20 | // Revision: 21 | // Revision 0.01 - File Created 22 | // Additional Comments: 23 | // 24 | ////////////////////////////////////////////////////////////////////////////////// 25 | module aluop_selector #( 26 | parameter CURRENTPC = 1'b0, 27 | parameter RD1 = 1'b1, 28 | parameter EXT = 1'b0, 29 | parameter RD2 = 1'b1 30 | ) 31 | ( 32 | input op_A_sel_i, 33 | input op_B_sel_i, 34 | input [31:0] current_pc_i, 35 | input [31:0] rD1_i, 36 | input [31:0] rD2_i, 37 | input [31:0] ext_i, 38 | output reg [31:0] alu_op_a_o, 39 | output reg [31:0] alu_op_b_o 40 | ); 41 | // alu_a选择 42 | always @(*) begin 43 | case(op_A_sel_i) 44 | CURRENTPC: alu_op_a_o = current_pc_i; 45 | RD1: alu_op_a_o = rD1_i; 46 | default: alu_op_a_o = 32'h0; 47 | endcase 48 | end 49 | // alu_b选择 50 | always @(*) begin 51 | case(op_B_sel_i) 52 | EXT: alu_op_b_o = ext_i; 53 | RD2: alu_op_b_o = rD2_i; 54 | default: alu_op_b_o = 32'h0; 55 | endcase 56 | end 57 | endmodule 58 | -------------------------------------------------------------------------------- /pipeline/forward/trace/arithmetic_unit.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 15:41:40 7 | // Design Name: 8 | // Module Name: arithmetic_unit 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 算数运算单元,根据传入的两个操作数和操作码进行算术运算 14 | // opcode:00:加法 15 | // 01:减法 16 | // Dependencies: 17 | // 18 | // Revision: 19 | // Revision 0.01 - File Created 20 | // Additional Comments: 21 | // 22 | ////////////////////////////////////////////////////////////////////////////////// 23 | module arithmetic_unit #( 24 | parameter PLUS = 2'b00, 25 | parameter SUB = 2'b01, 26 | parameter UNKNOWN_OPCODE_RESULT = 32'h0 27 | ) 28 | ( 29 | input [31:0] op_a_i, 30 | input [31:0] op_b_i, 31 | input [1:0] opcode_i, 32 | output reg [31:0] result_o 33 | ); 34 | always @(*) begin 35 | case(opcode_i) 36 | PLUS: result_o = op_a_i + op_b_i; 37 | SUB: result_o = op_a_i + (~op_b_i+1'b1); // 采用加补码的方式实现减法 38 | default: result_o = UNKNOWN_OPCODE_RESULT; 39 | endcase 40 | end 41 | endmodule 42 | -------------------------------------------------------------------------------- /pipeline/forward/trace/branch_unit.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 16:45:19 7 | // Design Name: 8 | // Module Name: branch_unit 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // B型指令专用branch运算单元 14 | // 15 | // Dependencies: 16 | // 17 | // Revision: 18 | // Revision 0.01 - File Created 19 | // Additional Comments: 20 | // 21 | ////////////////////////////////////////////////////////////////////////////////// 22 | module branch_unit#( 23 | parameter EQ = 4'h0, 24 | parameter NEQ = 4'h1, 25 | parameter UNSIGNED_LT = 4'h2, 26 | parameter SIGNED_LT = 4'h3, 27 | parameter UNSIGNED_GE = 4'h4, 28 | parameter SIGNED_GE = 4'h5, 29 | parameter SUCCESS = 1'b1, 30 | parameter UNSUCCESS = 1'b0, 31 | parameter UNKNOWN_OPCODE_RESULT = 1'b0 32 | ) 33 | ( 34 | input [31:0] op_a_i, 35 | input [31:0] op_b_i, 36 | input [3:0] opcode_i, 37 | output reg branch 38 | ); 39 | reg [31:0] tmp; 40 | always @(*) begin 41 | tmp = op_a_i - op_b_i; 42 | end 43 | always @(*) begin 44 | case(opcode_i) 45 | EQ: branch = (tmp == 32'h0)?SUCCESS:UNSUCCESS; 46 | NEQ: branch = (tmp == 32'h0)?UNSUCCESS:SUCCESS; 47 | UNSIGNED_LT: branch = (op_a_i < op_b_i)?SUCCESS:UNSUCCESS; 48 | SIGNED_LT: begin 49 | // 对符号不同的情况特殊处理,防止发生溢出 50 | if(op_a_i[31] ^ op_b_i[31]) 51 | branch = op_a_i[31]; 52 | else 53 | branch = (tmp[31] == 1'b1)?SUCCESS:UNSUCCESS; 54 | end 55 | UNSIGNED_GE: branch = (op_a_i < op_b_i)?UNSUCCESS:SUCCESS; 56 | SIGNED_GE: begin 57 | // 对符号不同的情况特殊处理,防止发生溢出 58 | if(op_a_i[31] ^ op_b_i[31]) 59 | branch = op_b_i[31]; 60 | else 61 | branch = (tmp[31] == 1'b1)?UNSUCCESS:SUCCESS; 62 | end 63 | default: branch = UNKNOWN_OPCODE_RESULT; 64 | endcase 65 | end 66 | endmodule 67 | -------------------------------------------------------------------------------- /pipeline/forward/trace/clock_divider.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/05/11 18:57:50 7 | // Design Name: 8 | // Module Name: time 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | // 分频器,将高频时钟信号转化为低频时钟信号用于驱动数码管 22 | // 输入:时钟信号clk 23 | // 输出:低频时钟信号out 24 | module clock_divider( 25 | input clk, 26 | output reg out 27 | ); 28 | reg [15:0] cnt = 0; 29 | reg tag = 1'b0; 30 | always @ (posedge clk) begin 31 | if(tag == 1'b0) begin 32 | out = 1'b0; 33 | tag = 1'b1; 34 | end 35 | else begin 36 | if(cnt == 16'b1010_0001_0010_0000) begin //27'b101_1111_0101_1110_0001_0000_0000 37 | out = ~out; 38 | cnt = 0; 39 | end 40 | else begin 41 | cnt = cnt+1'b1; 42 | end 43 | end 44 | end 45 | endmodule 46 | -------------------------------------------------------------------------------- /pipeline/forward/trace/compare_unit.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 15:41:40 7 | // Design Name: 8 | // Module Name: compare_unit 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 比较运算单元,用于R型与I型指令 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module compare_unit #( 22 | parameter SIGNED = 2'b00, 23 | parameter UNSIGNED = 2'b01, 24 | parameter OTHERS = 32'h0, 25 | parameter SIGNED_LT = 32'h1, 26 | parameter UNSIGNED_LT = 32'h1, 27 | parameter UNKNOWN_OPCODE_RESULT = 32'h0 28 | ) 29 | ( 30 | input [31:0] op_a_i, 31 | input [31:0] op_b_i, 32 | input [1:0] opcode_i, 33 | output reg [31:0] result_o 34 | ); 35 | reg [31:0] tmp; 36 | always@(*) begin 37 | case(opcode_i) 38 | SIGNED: begin 39 | tmp = op_a_i - op_b_i; 40 | // 不同号 41 | if(op_a_i[31]^op_b_i[31]) 42 | result_o = op_a_i[31]; 43 | else 44 | result_o = (tmp[31]==1'b1)?SIGNED_LT:OTHERS; 45 | end 46 | UNSIGNED: begin 47 | result_o = (op_a_i < op_b_i)?UNSIGNED_LT:OTHERS; 48 | end 49 | default: 50 | result_o = UNKNOWN_OPCODE_RESULT; 51 | endcase 52 | end 53 | endmodule 54 | -------------------------------------------------------------------------------- /pipeline/forward/trace/data_hazard_detect.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/16 14:16:30 7 | // Design Name: 8 | // Module Name: suspend_o 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | 22 | 23 | module data_hazard_detect( 24 | input [4:0] rR1_id_exe_i, 25 | input [4:0] rR2_id_exe_i, 26 | input [4:0] wr_exe_mem_i, 27 | input [4:0] wr_mem_wb_i, 28 | input [4:0] wr_wb_i, 29 | input detect_r1, 30 | input detect_r2, 31 | output suspend_o 32 | ); 33 | // reg [1:0] cnt; 34 | // always @(posedge clk_i or posedge rst_i) begin 35 | // if(rst_i) 36 | // suspend_o <= 1'b0; 37 | // else begin 38 | // // 第一类数据冒险,相邻情况 39 | // if(rR1_id_exe_i == wr_exe_mem_i || rR2_id_exe_i == wr_exe_mem_i) 40 | // suspend_o <= 1'b1; 41 | // // 第二类数据冒险,相隔1条指令;第三类数据冒险,访存-读取型 42 | // else if(rR1_id_exe_i == wr_mem_wb_i || rR2_id_exe_i == wr_mem_wb_i) 43 | // suspend_o <= 1'b1; 44 | // else 45 | // suspend_o <= 1'b0; 46 | // end 47 | // end 48 | // always @(posedge clk_i or posedge rst_i) begin 49 | // if(rst_i) 50 | // cnt <= 2'h0; 51 | // else 52 | // if(cnt == 2'h0) begin 53 | // if((rR1_id_exe_i == wr_exe_mem_i || rR2_id_exe_i == wr_exe_mem_i)&&wr_exe_mem_i!=5'h0) 54 | // cnt <= 2'h3; 55 | // else if((rR1_id_exe_i == wr_mem_wb_i || rR2_id_exe_i == wr_mem_wb_i)&&wr_mem_wb_i!=5'h0) 56 | // cnt <= 2'h2; 57 | // else if((rR1_id_exe_i == wr_wb_i || rR2_id_exe_i == wr_wb_i)&&wr_wb_i!=5'h0) 58 | // cnt <= 2'h1; 59 | // else 60 | // cnt <= cnt; 61 | // end 62 | // else 63 | // cnt <= cnt - 1'h1; 64 | // end 65 | // assign suspend_o = (cnt==2'h0)?1'b0:1'b1; 66 | wire rR1_id_exe_hazard = (rR1_id_exe_i == wr_exe_mem_i)?(wr_exe_mem_i!=5'h0):1'b0; 67 | wire rR2_id_exe_hazard = (rR2_id_exe_i == wr_exe_mem_i)?(wr_exe_mem_i!=5'h0):1'b0; 68 | wire rR1_id_mem_hazard = (rR1_id_exe_i == wr_mem_wb_i)?(wr_mem_wb_i!=5'h0):1'b0; 69 | wire rR2_id_mem_hazard = (rR2_id_exe_i == wr_mem_wb_i)?(wr_mem_wb_i!=5'h0):1'b0; 70 | wire rR1_id_wb_hazard = (rR1_id_exe_i == wr_wb_i)?(wr_wb_i!=5'h0):1'b0; 71 | wire rR2_id_wb_hazard = (rR2_id_exe_i == wr_wb_i)?(wr_wb_i!=5'h0):1'b0; 72 | assign suspend_o = ((rR1_id_exe_hazard | rR1_id_mem_hazard | rR1_id_wb_hazard) & detect_r1) 73 | |((rR2_id_exe_hazard | rR2_id_mem_hazard | rR2_id_wb_hazard) & detect_r2); 74 | 75 | endmodule 76 | -------------------------------------------------------------------------------- /pipeline/forward/trace/execute.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 17:22:25 7 | // Design Name: 8 | // Module Name: execute 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 执行模块,集成alu和alu的数据选择器 14 | // Dependencies: 15 | // aluop_selector, alu 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module execute( 22 | input reset_i, 23 | input [1:0] pc_sel_i, 24 | input [31:0] pc_i, 25 | input branch_controler_i, 26 | input op_A_sel_i, 27 | input op_B_sel_i, 28 | input [31:0] current_pc_i, 29 | input [31:0] rD1_i, 30 | input [31:0] rD2_i, 31 | input [31:0] ext_i, 32 | input [4:0] alu_opcode_i, 33 | output [31:0] alu_result_o, 34 | // output alu_branch_o, 35 | output [31:0] next_pc_o 36 | ); 37 | wire [31:0] alu_op_a; 38 | wire [31:0] alu_op_b; 39 | wire alu_branch; 40 | wire branch = branch_controler_i & alu_branch; 41 | aluop_selector u_aluop_selector( 42 | .op_A_sel_i (op_A_sel_i), 43 | .op_B_sel_i (op_B_sel_i), 44 | .current_pc_i(current_pc_i), 45 | .rD1_i (rD1_i), 46 | .rD2_i (rD2_i), 47 | .ext_i (ext_i ), 48 | .alu_op_a_o (alu_op_a), 49 | .alu_op_b_o (alu_op_b) 50 | ); 51 | alu u_alu( 52 | .alu_opcode_i (alu_opcode_i), 53 | .alu_op_a_i (alu_op_a), 54 | .alu_op_b_i (alu_op_b), 55 | .alu_result_o (alu_result_o), 56 | .branch_o (alu_branch) 57 | ); 58 | npc u_npc( 59 | .reset_i (reset_i), 60 | .pc_sel_i (pc_sel_i), 61 | .pc_i (pc_i), 62 | .offset_i (ext_i), 63 | .rD1_i (rD1_i), 64 | .branch_i (branch), 65 | .next_pc_o(next_pc_o) 66 | ); 67 | endmodule 68 | -------------------------------------------------------------------------------- /pipeline/forward/trace/forward_unit.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ps 2 | // 前递模块,用于数据冒险使用前递的方式传送数据 3 | // 对于load-use型无法用前递实现的冒险采用暂停处理 4 | module forward_unit( 5 | input clk_i, 6 | input rst_i, 7 | input [4:0] rR1_id_exe_i, 8 | input [4:0] rR2_id_exe_i, 9 | input [4:0] wr_exe_mem_i, 10 | input [4:0] wr_mem_wb_i, 11 | input [4:0] wr_wb_i, 12 | input [31:0] data_exe_i, 13 | input [31:0] data_mem_i, 14 | input [31:0] data_wb_i, 15 | input detect_r1_i, 16 | input detect_r2_i, 17 | input is_load_i, 18 | input is_sb_exe_i, 19 | input is_sb_mem_i, 20 | output [31:0] forward_data_1_o, 21 | output [31:0] forward_data_2_o, 22 | output reg r1_select_i, 23 | output reg r2_select_i, 24 | output suspend_o 25 | ); 26 | reg [31:0] data_1; 27 | reg [31:0] data_2; 28 | always @(*) begin 29 | if(detect_r1_i) begin 30 | if(rR1_id_exe_i == wr_exe_mem_i) begin 31 | data_1 = data_exe_i; 32 | r1_select_i = (wr_exe_mem_i!=5'h0) & ~is_sb_exe_i; 33 | end 34 | else if(rR1_id_exe_i == wr_mem_wb_i) begin 35 | data_1 = data_mem_i; 36 | r1_select_i = (wr_mem_wb_i!=5'h0) & ~is_sb_mem_i; 37 | end 38 | else if(rR1_id_exe_i == wr_wb_i) begin 39 | data_1 = data_wb_i; 40 | r1_select_i = (wr_wb_i!=5'h0); 41 | end 42 | else 43 | r1_select_i = 1'b0; 44 | end 45 | else 46 | r1_select_i = 1'b0; 47 | end 48 | 49 | always @(*) begin 50 | if(detect_r2_i) begin 51 | if(rR2_id_exe_i == wr_exe_mem_i) begin 52 | data_2 = data_exe_i; 53 | r2_select_i = (wr_exe_mem_i!=5'h0) & ~is_sb_exe_i; 54 | end 55 | else if(rR2_id_exe_i == wr_mem_wb_i) begin 56 | data_2 = data_mem_i; 57 | r2_select_i = (wr_mem_wb_i!=5'h0) & ~is_sb_mem_i; 58 | end 59 | else if(rR2_id_exe_i == wr_wb_i) begin 60 | data_2 = data_wb_i; 61 | r2_select_i = (wr_wb_i!=5'h0); 62 | end 63 | else 64 | r2_select_i = 1'b0; 65 | end 66 | else 67 | r2_select_i = 1'b0; 68 | end 69 | 70 | assign forward_data_1_o = data_1; 71 | assign forward_data_2_o = data_2; 72 | // 暂停信号处理 73 | wire suspend_1 = is_load_i & (rR1_id_exe_i == wr_exe_mem_i) & detect_r1_i; 74 | wire suspend_2 = is_load_i & (rR2_id_exe_i == wr_exe_mem_i) & detect_r2_i; 75 | assign suspend_o = suspend_1 | suspend_2; 76 | endmodule -------------------------------------------------------------------------------- /pipeline/forward/trace/imm_gen.v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yikai-coder/HITsz_CPU_design/c1d6cea65b82fd382c3bf34725d2e8ccb11a9936/pipeline/forward/trace/imm_gen.v -------------------------------------------------------------------------------- /pipeline/forward/trace/instruction_decoder.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/01 17:00:09 7 | // Design Name: 8 | // Module Name: imm_gen 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 译码模块,集成寄存器堆和立即数生成模块 14 | // Dependencies: 15 | // reg_file,imm_gen 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module instruction_decoder #( 22 | parameter RETURN_PC = 2'b00, 23 | parameter ALU_RESULT = 2'b01, 24 | parameter MEM_DATA = 2'b10 25 | ) 26 | ( 27 | input reset_i, 28 | input [31:0] return_pc_i, 29 | input [31:0] ALU_result_i, 30 | input [31:0] mem_data_i, 31 | input [1:0] wd_sel_i, 32 | input [4:0] wr_i, 33 | input we_i, 34 | input clk_i, 35 | input [31:0] inst_i, 36 | input [2:0] imm_sel_i, 37 | input [31:0] forward_data_1_i, 38 | input [31:0] forward_data_2_i, 39 | input r1_select_i, 40 | input r2_select_i, 41 | output [31:0] wd_o, // test 42 | output [31:0] ext_o, 43 | output [31:0] rD1_o, 44 | output [31:0] rD2_o 45 | // output reg write_back // 写回阶段信号 46 | ); 47 | 48 | reg [31:0] wD; 49 | reg [4:0] wr; 50 | wire [31:0] rD1; 51 | wire [31:0] rD2; 52 | 53 | // 根据wd_sel选择写入数据 54 | // 写入寄存器恒为inst[11:7] 55 | always @(*) begin 56 | case(wd_sel_i) 57 | RETURN_PC: begin 58 | wD = return_pc_i; 59 | end 60 | ALU_RESULT: begin 61 | wD = ALU_result_i; 62 | end 63 | MEM_DATA: begin 64 | wD = mem_data_i; 65 | end 66 | default: begin 67 | wD = 32'h0; 68 | end 69 | endcase 70 | end 71 | assign wd_o = wD; 72 | 73 | reg_file u_reg_file( 74 | .clk_i (clk_i), 75 | .reset_i (reset_i), 76 | .rR1_i (inst_i[19:15]), 77 | .rR2_i (inst_i[24:20]), 78 | .wR_i (wr_i), 79 | .wD_i (wD), 80 | .WE_i (we_i), 81 | .rD1_o (rD1), 82 | .rD2_o (rD2) 83 | ); 84 | // assign we_o = we_i; 85 | // assign wD_o = wD; 86 | // assign wR_o = wr; 87 | assign rD1_o = (r1_select_i==1'b1)?forward_data_1_i:rD1; 88 | assign rD2_o = (r2_select_i==1'b1)?forward_data_2_i:rD2; 89 | 90 | imm_gen u_imm_gen( 91 | .reset_i (reset_i), 92 | .inst_i (inst_i), 93 | .imm_sel_i (imm_sel_i), 94 | .ext_o (ext_o) 95 | ); 96 | endmodule 97 | -------------------------------------------------------------------------------- /pipeline/forward/trace/instruction_fetch.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/01 15:31:29 7 | // Design Name: 8 | // Module Name: instruction_fetch 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 取指模块 14 | // 包含pc,npc,irom三个子模块 15 | // Dependencies: 16 | // 17 | // Revision: 18 | // Revision 0.01 - File Created 19 | // Additional Comments: 20 | // 21 | ////////////////////////////////////////////////////////////////////////////////// 22 | module instruction_fetch( 23 | input clk_i, 24 | input reset_i, 25 | input [31:0] next_pc_i, 26 | input data_suspend_i, 27 | input flush_i, 28 | output [31:0] inst_o, 29 | output [31:0] return_pc_o, 30 | output [31:0] current_pc_o, // 用于auipc 31 | output [31:0] pc_o 32 | ); 33 | // wire [31:0] npc; 34 | wire [31:0] pc; 35 | assign pc_o = pc; 36 | assign current_pc_o = pc; 37 | assign return_pc_o = pc + 3'h4; 38 | pc u_pc( 39 | .npc_i (next_pc_i), 40 | .clk_i (clk_i), 41 | .reset_i (reset_i), 42 | .data_suspend_i (data_suspend_i), 43 | .flush_i (flush_i), 44 | .pc_o (pc) 45 | ); 46 | // npc模块转移到EXE中 47 | // npc u_npc( 48 | // .reset_i (reset_i), 49 | // .pc_sel_i (pc_sel_i), 50 | // .pc_i (pc), 51 | // .offset_i (offset_i), 52 | // .rD1_i (rD1_i), 53 | // .branch_i (branch_i), 54 | // .next_pc_o (npc), 55 | // .pc_plus_4_o(return_pc_o) 56 | // // ); 57 | // irom u_irom( 58 | // .pc_i (pc), 59 | // .inst_o(inst_o) 60 | // ); 61 | endmodule 62 | -------------------------------------------------------------------------------- /pipeline/forward/trace/irom.v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yikai-coder/HITsz_CPU_design/c1d6cea65b82fd382c3bf34725d2e8ccb11a9936/pipeline/forward/trace/irom.v -------------------------------------------------------------------------------- /pipeline/forward/trace/jump_examine.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/16 15:03:15 7 | // Design Name: 8 | // Module Name: jump_examine 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 放置在if模块后方检测跳转指令的出现 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | 22 | 23 | module jump_examine #( 24 | parameter JALR_OPCODE = 7'b1100111, 25 | parameter B_OPCODE = 7'b1100011, 26 | parameter JAL_OPCODE = 7'b1101111 27 | ) 28 | ( 29 | input clk_i, 30 | input rst_i, 31 | input [31:0] npc_i, 32 | input [31:0] current_pc_i, 33 | output flush_o 34 | ); 35 | // reg [31:0] pc_1; 36 | // reg [31:0] pc_2; 37 | // always @(posedge clk_i or posedge rst_i) begin 38 | // if(rst_i) begin 39 | // pc_1 <= 32'hfffffffc; 40 | // pc_2 <= 32'hfffffffc; 41 | // end 42 | // else begin 43 | // pc_2 <= pc_1; 44 | // pc_1 <= current_pc_i; 45 | // end 46 | // end 47 | assign flush_o = (npc_i!=current_pc_i+3'h4); 48 | endmodule 49 | -------------------------------------------------------------------------------- /pipeline/forward/trace/logic_unit.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 15:41:40 7 | // Design Name: 8 | // Module Name: logic_unit 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // alu下的逻辑运算单元 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module logic_unit #( 22 | parameter AND = 2'b00, 23 | parameter OR = 2'b01, 24 | parameter XOR = 2'b10, 25 | parameter UNKNOWN_OPCODE_RESULT = 32'h0 26 | ) 27 | ( 28 | input [31:0] op_a_i, 29 | input [31:0] op_b_i, 30 | input [1:0] opcode_i, 31 | output reg [31:0] result_o 32 | ); 33 | always @(*) begin 34 | case(opcode_i) 35 | AND: result_o = op_a_i & op_b_i; 36 | OR: result_o = op_a_i | op_b_i; 37 | XOR: result_o = op_a_i ^ op_b_i; 38 | default: result_o = UNKNOWN_OPCODE_RESULT; 39 | endcase 40 | end 41 | endmodule 42 | -------------------------------------------------------------------------------- /pipeline/forward/trace/npc.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/01 14:28:45 7 | // Design Name: 8 | // Module Name: npc 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // npc数据处理,根据pc_sel输出不同指令对应的下一周期pc信号 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module npc #( 22 | parameter INTERPRETER_NPC = 32'b0 // 对应pc_sel信号异常,转入中断处理 23 | ) 24 | ( 25 | input reset_i, 26 | input [1:0] pc_sel_i, 27 | input [31:0] pc_i, 28 | input [31:0] offset_i, 29 | input [31:0] rD1_i, 30 | input branch_i, 31 | output reg [31:0] next_pc_o, 32 | output [31:0] pc_plus_4_o // 用于jal指令与jalr指令 33 | ); 34 | always @(*) begin 35 | if(reset_i == 1'b1) 36 | next_pc_o = pc_i; 37 | else begin 38 | case (pc_sel_i) 39 | 2'b00: next_pc_o = pc_i + 3'b100; // pc+4 40 | 2'b01: next_pc_o = (branch_i==1'b1)?pc_i+offset_i:pc_i+3'b100; //Branch 41 | 2'b10: next_pc_o = pc_i+offset_i; // jal 42 | 2'b11: next_pc_o = (rD1_i+offset_i)&(~1); // jalr 43 | default: 44 | next_pc_o = INTERPRETER_NPC; 45 | endcase 46 | end 47 | end 48 | assign pc_plus_4_o = pc_i+3'b100; 49 | endmodule 50 | -------------------------------------------------------------------------------- /pipeline/forward/trace/pc.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/01 14:22:58 7 | // Design Name: 8 | // Module Name: pc 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // PC寄存器,在每个时钟上升沿将前一个周期送入的npc输出 14 | // 在复位信号送来时输出复位后首条指令的PC值 15 | // Dependencies: 16 | // 17 | // Revision: 18 | // Revision 0.01 - File Created 19 | // Additional Comments: 20 | // 21 | ////////////////////////////////////////////////////////////////////////////////// 22 | module pc#( 23 | parameter INIT_PC = 32'hfffffffc // 假设0为CPU复位后的首条指令对应地址 24 | ) 25 | ( 26 | input [31:0] npc_i, 27 | input clk_i, 28 | input reset_i, 29 | input data_suspend_i, 30 | input flush_i, 31 | output reg [31:0] pc_o 32 | ); 33 | reg first_time; // 用于防止reset失效的当个周期时间不够无法完成一条指令,将第一条指令的执行时间推迟到下一次时钟上升沿到来 34 | // always @(posedge clk_i or posedge reset_i) begin 35 | // if(reset_i) begin 36 | // pc_o <= INIT_PC; 37 | // first_time <= 1'b0; 38 | // end 39 | // else begin 40 | // first_time <= 1'b1; 41 | // if(first_time == 1'b0) 42 | // pc_o <= INIT_PC; 43 | // else 44 | // // pc_o <= npc_i; 45 | // if(data_suspend_i) 46 | // pc_o <= pc_o; 47 | // else if(flush_i) 48 | // pc_o <= npc_i; 49 | // else 50 | // pc_o <= pc_o + 3'h4; 51 | // end 52 | // end 53 | always @(posedge clk_i or posedge reset_i) begin 54 | if(reset_i) 55 | pc_o <= INIT_PC; 56 | else 57 | if(flush_i) 58 | pc_o <= npc_i; 59 | else if(data_suspend_i) 60 | pc_o <= pc_o; 61 | else 62 | pc_o <= pc_o + 3'h4; 63 | end 64 | endmodule 65 | -------------------------------------------------------------------------------- /pipeline/forward/trace/reg_exe_mem.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ps 2 | module reg_exe_mem( 3 | input clk_i, 4 | input rst_i, 5 | input [31:0] alu_result_i, 6 | input [31:0] mem_wd_i, 7 | input mem_we_i, 8 | input [1:0] mem_data_sel_i, 9 | input [4:0] wr_i, 10 | input [1:0] wd_sel_i, 11 | input regfile_we_i, 12 | input [31:0] return_pc_i, 13 | input [31:0] current_pc_i, 14 | input is_sb_i, 15 | output reg [31:0] current_pc_o, 16 | output reg [31:0] alu_result_o, 17 | output reg [31:0] mem_wd_o, 18 | output reg mem_we_o, 19 | output reg [1:0] mem_data_sel_o, 20 | output reg [4:0] wr_o, 21 | output reg [1:0] wd_sel_o, 22 | output reg regfile_we_o, 23 | output reg [31:0] return_pc_o, 24 | output reg is_sb_o 25 | ); 26 | always @(posedge clk_i or posedge rst_i) begin 27 | if(rst_i) 28 | alu_result_o <= 32'h0; 29 | else 30 | alu_result_o <= alu_result_i; 31 | end 32 | always @(posedge clk_i or posedge rst_i) begin 33 | if(rst_i) 34 | mem_wd_o <= 32'h0; 35 | else 36 | mem_wd_o <= mem_wd_i; 37 | end 38 | always @(posedge clk_i or posedge rst_i) begin 39 | if(rst_i) 40 | mem_we_o <= 1'b0; 41 | else 42 | mem_we_o <= mem_we_i; 43 | end 44 | always @(posedge clk_i or posedge rst_i) begin 45 | if(rst_i) 46 | mem_data_sel_o <= 2'h0; 47 | else 48 | mem_data_sel_o <= mem_data_sel_i; 49 | end 50 | always @(posedge clk_i or posedge rst_i) begin 51 | if(rst_i) 52 | wr_o <= 4'h0; 53 | else 54 | wr_o <= wr_i; 55 | end 56 | always @(posedge clk_i or posedge rst_i) begin 57 | if(rst_i) 58 | wd_sel_o <= 2'h0; 59 | else 60 | wd_sel_o <= wd_sel_i; 61 | end 62 | always @(posedge clk_i or posedge rst_i) begin 63 | if(rst_i) 64 | regfile_we_o <= 1'b0; 65 | else 66 | regfile_we_o <= regfile_we_i; 67 | end 68 | always @(posedge clk_i or posedge rst_i) begin 69 | if(rst_i) 70 | return_pc_o <= 32'h0; 71 | else 72 | return_pc_o <= return_pc_i; 73 | end 74 | always @(posedge clk_i or posedge rst_i) begin 75 | if(rst_i) 76 | current_pc_o <= 32'h0; 77 | else 78 | current_pc_o <= current_pc_i; 79 | end 80 | always @(posedge clk_i or posedge rst_i) begin 81 | if(rst_i) 82 | is_sb_o <= 1'b0; 83 | else 84 | is_sb_o <= is_sb_i; 85 | end 86 | 87 | endmodule -------------------------------------------------------------------------------- /pipeline/forward/trace/reg_file_8.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/01 14:22:58 7 | // Design Name: 8 | // Module Name: pc 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 寄存器堆模块的子模块,每个模块存储8个寄存器 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module reg_file_8( 22 | input clk_i, 23 | input reset_i, 24 | input [4:0] rR1_i, 25 | input [4:0] rR2_i, 26 | input [4:0] wR_i, 27 | input [31:0] wD_i, 28 | input WE_i, 29 | output reg [31:0] rD1_o, 30 | output reg [31:0] rD2_o 31 | ); 32 | reg [31:0] reg_0; 33 | reg [31:0] reg_1; 34 | reg [31:0] reg_2; 35 | reg [31:0] reg_3; 36 | reg [31:0] reg_4; 37 | reg [31:0] reg_5; 38 | reg [31:0] reg_6; 39 | reg [31:0] reg_7; 40 | // rD1_o 41 | always @ (*) begin 42 | case(rR1_i[2:0]) 43 | 3'b000: rD1_o = (rR1_i[4:3]==2'b00)?32'h0:reg_0; // x0不可被修改 44 | 3'b001: rD1_o = reg_1; 45 | 3'b010: rD1_o = reg_2; 46 | 3'b011: rD1_o = reg_3; 47 | 3'b100: rD1_o = reg_4; 48 | 3'b101: rD1_o = reg_5; 49 | 3'b110: rD1_o = reg_6; 50 | 3'b111: rD1_o = reg_7; 51 | default: rD1_o = 32'h0; 52 | endcase 53 | end 54 | // rD2_o 55 | always @ (*) begin 56 | case(rR2_i[2:0]) 57 | 3'b000: rD2_o = (rR2_i[4:3]==2'b00)?32'h0:reg_0; 58 | 3'b001: rD2_o = reg_1; 59 | 3'b010: rD2_o = reg_2; 60 | 3'b011: rD2_o = reg_3; 61 | 3'b100: rD2_o = reg_4; 62 | 3'b101: rD2_o = reg_5; 63 | 3'b110: rD2_o = reg_6; 64 | 3'b111: rD2_o = reg_7; 65 | default: rD2_o = 32'h0; 66 | endcase 67 | end 68 | // wirte 69 | always @ (posedge clk_i or posedge reset_i) begin 70 | if(reset_i == 1'b1) begin 71 | reg_0 = 32'h0; 72 | reg_1 = 32'h0; 73 | reg_2 = 32'h0; 74 | reg_3 = 32'h0; 75 | reg_4 = 32'h0; 76 | reg_5 = 32'h0; 77 | reg_6 = 32'h0; 78 | reg_7 = 32'h0; 79 | end 80 | else 81 | if(WE_i == 1'b1) begin 82 | case(wR_i[2:0]) 83 | 3'b000: reg_0 = (wR_i[4:3]==2'b00)?32'h0:wD_i; 84 | 3'b001: reg_1 = wD_i; 85 | 3'b010: reg_2 = wD_i; 86 | 3'b011: reg_3 = wD_i; 87 | 3'b100: reg_4 = wD_i; 88 | 3'b101: reg_5 = wD_i; 89 | 3'b110: reg_6 = wD_i; 90 | 3'b111: reg_7 = wD_i; 91 | default:; 92 | endcase 93 | end 94 | else; 95 | end 96 | endmodule 97 | -------------------------------------------------------------------------------- /pipeline/forward/trace/reg_if_id.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ps 2 | // IF/ID流水线寄存器 3 | module reg_if_id #( 4 | parameter INIT_PC = 32'h0 5 | ) 6 | ( 7 | input clk_i, 8 | input rst_i, 9 | input [31:0] inst_i, 10 | input [31:0] current_pc_i, 11 | input [31:0] return_pc_i, 12 | input suspend_i, 13 | input flush_i, 14 | output reg [31:0] inst_o, 15 | output reg [31:0] current_pc_o, 16 | output reg [31:0] return_pc_o 17 | ); 18 | always @(posedge clk_i or posedge rst_i) begin 19 | if(rst_i) 20 | inst_o <= INIT_PC; 21 | else 22 | if(flush_i) 23 | inst_o <= INIT_PC; 24 | else if(suspend_i) 25 | inst_o <= inst_o; 26 | else 27 | inst_o <= inst_i; 28 | end 29 | always @(posedge clk_i or posedge rst_i) begin 30 | if(rst_i) 31 | current_pc_o <= 32'h0; 32 | else 33 | if(flush_i) 34 | current_pc_o <= 32'h0; 35 | else if(suspend_i) 36 | current_pc_o <= current_pc_o; 37 | else 38 | current_pc_o <= current_pc_i; 39 | end 40 | always @(posedge clk_i or posedge rst_i) begin 41 | if(rst_i) 42 | return_pc_o <= 32'h0; 43 | else 44 | if(flush_i) 45 | return_pc_o <= 32'h0; 46 | else if(suspend_i) 47 | return_pc_o <= return_pc_o; 48 | else 49 | return_pc_o <= return_pc_i; 50 | end 51 | endmodule -------------------------------------------------------------------------------- /pipeline/forward/trace/reg_mem_wb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/14 09:22:34 7 | // Design Name: 8 | // Module Name: reg_mem_wb 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module reg_mem_wb( 22 | input clk_i, 23 | input rst_i, 24 | input [31:0] return_pc_i, 25 | input [31:0] alu_result_i, 26 | input [31:0] mem_rd_i, 27 | input [4:0] wr_i, 28 | input [1:0] wd_sel_i, 29 | input regfile_we_i, 30 | input [31:0] current_pc_i, 31 | output reg [31:0] current_pc_o, 32 | output reg [31:0] return_pc_o, 33 | output reg [31:0] alu_result_o, 34 | output reg [31:0] mem_rd_o, 35 | output reg [4:0] wr_o, 36 | output reg [1:0] wd_sel_o, 37 | output reg regfile_we_o 38 | ); 39 | always @(posedge clk_i or posedge rst_i) begin 40 | if(rst_i) 41 | return_pc_o <= 32'h0; 42 | else 43 | return_pc_o <= return_pc_i; 44 | end 45 | always @(posedge clk_i or posedge rst_i) begin 46 | if(rst_i) 47 | alu_result_o <= 32'h0; 48 | else 49 | alu_result_o <= alu_result_i; 50 | end 51 | always @(posedge clk_i or posedge rst_i) begin 52 | if(rst_i) 53 | mem_rd_o <= 32'h0; 54 | else 55 | mem_rd_o <= mem_rd_i; 56 | end 57 | always @(posedge clk_i or posedge rst_i) begin 58 | if(rst_i) 59 | wr_o <= 5'h0; 60 | else 61 | wr_o <= wr_i; 62 | end 63 | always @(posedge clk_i or posedge rst_i) begin 64 | if(rst_i) 65 | wd_sel_o <= 2'h0; 66 | else 67 | wd_sel_o <= wd_sel_i; 68 | end 69 | always @(posedge clk_i or posedge rst_i) begin 70 | if(rst_i) 71 | regfile_we_o <= 1'b0; 72 | else 73 | regfile_we_o <= regfile_we_i; 74 | end 75 | always @(posedge clk_i or posedge rst_i) begin 76 | if(rst_i) 77 | current_pc_o <= 32'h0; 78 | else 79 | current_pc_o <= current_pc_i; 80 | end 81 | endmodule 82 | -------------------------------------------------------------------------------- /pipeline/forward/trace/shift_unit.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 15:41:40 7 | // Design Name: 8 | // Module Name: shift_unit 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // alu下的移位操作单元,通过桶形移位器实现 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module shift_unit #( 22 | parameter LEFT_SHIFT = 2'b00, 23 | parameter RIGHT_LOGIC_SHIFT = 2'b01, 24 | parameter RIGHT_ARITHMETIC_SHIFT = 2'b10, 25 | parameter UNKNOWN_OPCODE_RESULT = 32'h0 26 | ) 27 | ( 28 | input [31:0] op_a_i, 29 | input [31:0] op_b_i, // 实际只有低5位有效,高位是拓展而来 30 | input [1:0] opcode_i, 31 | output [31:0] result_o 32 | ); 33 | reg [31:0] tmp; 34 | always @(*) begin 35 | case(opcode_i) 36 | LEFT_SHIFT:begin 37 | tmp = (op_b_i[0]==1'b1)?{op_a_i[30:0], 1'b0} :op_a_i; 38 | tmp = (op_b_i[1]==1'b1)?{tmp[29:0], 2'b0} :tmp; 39 | tmp = (op_b_i[2]==1'b1)?{tmp[27:0], 4'b0} :tmp; 40 | tmp = (op_b_i[3]==1'b1)?{tmp[23:0], 8'b0} :tmp; 41 | tmp = (op_b_i[4]==1'b1)?{tmp[15:0], 16'b0} :tmp; 42 | end 43 | RIGHT_LOGIC_SHIFT:begin 44 | tmp = (op_b_i[0]==1'b1)?{1'b0, op_a_i[31:1]}:op_a_i; 45 | tmp = (op_b_i[1]==1'b1)?{2'b0, tmp[31:2]} :tmp; 46 | tmp = (op_b_i[2]==1'b1)?{4'b0, tmp[31:4]} :tmp; 47 | tmp = (op_b_i[3]==1'b1)?{8'b0, tmp[31:8]} :tmp; 48 | tmp = (op_b_i[4]==1'b1)?{16'b0, tmp[31:16]} :tmp; 49 | end 50 | RIGHT_ARITHMETIC_SHIFT: begin 51 | tmp = (op_b_i[0]==1'b1)?{{1{op_a_i[31]}}, op_a_i[31:1]}:op_a_i; 52 | tmp = (op_b_i[1]==1'b1)?{{2{op_a_i[31]}}, tmp[31:2]} :tmp; 53 | tmp = (op_b_i[2]==1'b1)?{{4{op_a_i[31]}}, tmp[31:4]} :tmp; 54 | tmp = (op_b_i[3]==1'b1)?{{8{op_a_i[31]}}, tmp[31:8]} :tmp; 55 | tmp = (op_b_i[4]==1'b1)?{{16{op_a_i[31]}}, tmp[31:16]} :tmp; 56 | end 57 | default: tmp = UNKNOWN_OPCODE_RESULT; 58 | endcase 59 | end 60 | assign result_o = tmp; 61 | endmodule 62 | -------------------------------------------------------------------------------- /pipeline/suspend/onBoard/alu.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 15:34:04 7 | // Design Name: 8 | // Module Name: alu 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 集成算数单元,逻辑运算单元,比较单元,移位单元,以及专用于b型指令的运算单元 14 | // alu_opcode的【3:2】用于选择不同单元的输出结果作为最终输出 15 | // alu_opcode的【1:0】作为不同单元的操作码 16 | // alu_opcode【4】专门用于lui指令直接输出op_b 17 | // Dependencies: 18 | // arithmetic_unit, compare_unit,logic_unit,shift_unit,branch_unit 19 | // Revision: 20 | // Revision 0.01 - File Created 21 | // Additional Comments: 22 | // 23 | ////////////////////////////////////////////////////////////////////////////////// 24 | module alu #( 25 | parameter ARITHMETiC = 2'b00, 26 | parameter COMPARE = 2'b01, 27 | parameter LOGIC = 2'b10, 28 | parameter SHIFT = 2'b11 29 | ) 30 | ( 31 | input [4:0] alu_opcode_i, 32 | input [31:0] alu_op_a_i, 33 | input [31:0] alu_op_b_i, 34 | output reg [31:0] alu_result_o, 35 | output branch_o 36 | ); 37 | wire [31:0] result_arithmetic; 38 | wire [31:0] result_compare; 39 | wire [31:0] result_logic; 40 | wire [31:0] result_shift; 41 | // 算数运算单元 42 | arithmetic_unit u_arithmetic_unit( 43 | .op_a_i (alu_op_a_i), 44 | .op_b_i (alu_op_b_i), 45 | .opcode_i(alu_opcode_i[1:0]), 46 | .result_o(result_arithmetic) 47 | ); 48 | // 比较操作单元 49 | compare_unit u_compare_unit( 50 | .op_a_i (alu_op_a_i), 51 | .op_b_i (alu_op_b_i), 52 | .opcode_i(alu_opcode_i[1:0]), 53 | .result_o(result_compare) 54 | ); 55 | // 逻辑运算单元 56 | logic_unit u_logic_unit( 57 | .op_a_i (alu_op_a_i), 58 | .op_b_i (alu_op_b_i), 59 | .opcode_i(alu_opcode_i[1:0]), 60 | .result_o(result_logic) 61 | ); 62 | // 移位运算单元 63 | shift_unit u_shift_unit( 64 | .op_a_i (alu_op_a_i), 65 | .op_b_i (alu_op_b_i), 66 | .opcode_i(alu_opcode_i[1:0]), 67 | .result_o(result_shift) 68 | ); 69 | // B型指令专用branch分支运算单元 70 | branch_unit u_branch_unit( 71 | .op_a_i (alu_op_a_i), 72 | .op_b_i (alu_op_b_i), 73 | .opcode_i(alu_opcode_i[3:0]), 74 | .branch (branch_o) 75 | ); 76 | // 根据opcode选择输出哪个单元的结果 77 | always @(*) begin 78 | // lui指令 79 | if(alu_opcode_i[4]) 80 | alu_result_o = alu_op_b_i; 81 | else 82 | case(alu_opcode_i[3:2]) 83 | ARITHMETiC: alu_result_o = result_arithmetic; 84 | COMPARE: alu_result_o = result_compare; 85 | LOGIC: alu_result_o = result_logic; 86 | SHIFT: alu_result_o = result_shift; 87 | endcase 88 | end 89 | 90 | endmodule 91 | -------------------------------------------------------------------------------- /pipeline/suspend/onBoard/aluop_selector.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 14:47:37 7 | // Design Name: 8 | // Module Name: aluop_selector 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 根据op_A_sel和op_B_sel选择送入alu的操作输 14 | // op_A:1'b0: 当前pc 15 | // 1'b1: rD1 16 | // op_B:1'b0: imm 17 | // 1'b1: rD2 18 | // Dependencies: 19 | // 20 | // Revision: 21 | // Revision 0.01 - File Created 22 | // Additional Comments: 23 | // 24 | ////////////////////////////////////////////////////////////////////////////////// 25 | module aluop_selector #( 26 | parameter CURRENTPC = 1'b0, 27 | parameter RD1 = 1'b1, 28 | parameter EXT = 1'b0, 29 | parameter RD2 = 1'b1 30 | ) 31 | ( 32 | input op_A_sel_i, 33 | input op_B_sel_i, 34 | input [31:0] current_pc_i, 35 | input [31:0] rD1_i, 36 | input [31:0] rD2_i, 37 | input [31:0] ext_i, 38 | output reg [31:0] alu_op_a_o, 39 | output reg [31:0] alu_op_b_o 40 | ); 41 | // alu_a选择 42 | always @(*) begin 43 | case(op_A_sel_i) 44 | CURRENTPC: alu_op_a_o = current_pc_i; 45 | RD1: alu_op_a_o = rD1_i; 46 | default: alu_op_a_o = 32'h0; 47 | endcase 48 | end 49 | // alu_b选择 50 | always @(*) begin 51 | case(op_B_sel_i) 52 | EXT: alu_op_b_o = ext_i; 53 | RD2: alu_op_b_o = rD2_i; 54 | default: alu_op_b_o = 32'h0; 55 | endcase 56 | end 57 | endmodule 58 | -------------------------------------------------------------------------------- /pipeline/suspend/onBoard/arithmetic_unit.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 15:41:40 7 | // Design Name: 8 | // Module Name: arithmetic_unit 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 算数运算单元,根据传入的两个操作数和操作码进行算术运算 14 | // opcode:00:加法 15 | // 01:减法 16 | // Dependencies: 17 | // 18 | // Revision: 19 | // Revision 0.01 - File Created 20 | // Additional Comments: 21 | // 22 | ////////////////////////////////////////////////////////////////////////////////// 23 | module arithmetic_unit #( 24 | parameter PLUS = 2'b00, 25 | parameter SUB = 2'b01, 26 | parameter UNKNOWN_OPCODE_RESULT = 32'h0 27 | ) 28 | ( 29 | input [31:0] op_a_i, 30 | input [31:0] op_b_i, 31 | input [1:0] opcode_i, 32 | output reg [31:0] result_o 33 | ); 34 | always @(*) begin 35 | case(opcode_i) 36 | PLUS: result_o = op_a_i + op_b_i; 37 | SUB: result_o = op_a_i + (~op_b_i+1'b1); // 采用加补码的方式实现减法 38 | default: result_o = UNKNOWN_OPCODE_RESULT; 39 | endcase 40 | end 41 | endmodule 42 | -------------------------------------------------------------------------------- /pipeline/suspend/onBoard/branch_unit.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 16:45:19 7 | // Design Name: 8 | // Module Name: branch_unit 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // B型指令专用branch运算单元 14 | // 15 | // Dependencies: 16 | // 17 | // Revision: 18 | // Revision 0.01 - File Created 19 | // Additional Comments: 20 | // 21 | ////////////////////////////////////////////////////////////////////////////////// 22 | module branch_unit#( 23 | parameter EQ = 4'h0, 24 | parameter NEQ = 4'h1, 25 | parameter UNSIGNED_LT = 4'h2, 26 | parameter SIGNED_LT = 4'h3, 27 | parameter UNSIGNED_GE = 4'h4, 28 | parameter SIGNED_GE = 4'h5, 29 | parameter SUCCESS = 1'b1, 30 | parameter UNSUCCESS = 1'b0, 31 | parameter UNKNOWN_OPCODE_RESULT = 1'b0 32 | ) 33 | ( 34 | input [31:0] op_a_i, 35 | input [31:0] op_b_i, 36 | input [3:0] opcode_i, 37 | output reg branch 38 | ); 39 | reg [31:0] tmp; 40 | always @(*) begin 41 | tmp = op_a_i - op_b_i; 42 | end 43 | always @(*) begin 44 | case(opcode_i) 45 | EQ: branch = (tmp == 32'h0)?SUCCESS:UNSUCCESS; 46 | NEQ: branch = (tmp == 32'h0)?UNSUCCESS:SUCCESS; 47 | UNSIGNED_LT: branch = (op_a_i < op_b_i)?SUCCESS:UNSUCCESS; 48 | SIGNED_LT: begin 49 | // 对符号不同的情况特殊处理,防止发生溢出 50 | if(op_a_i[31] ^ op_b_i[31]) 51 | branch = op_a_i[31]; 52 | else 53 | branch = (tmp[31] == 1'b1)?SUCCESS:UNSUCCESS; 54 | end 55 | UNSIGNED_GE: branch = (op_a_i < op_b_i)?UNSUCCESS:SUCCESS; 56 | SIGNED_GE: begin 57 | // 对符号不同的情况特殊处理,防止发生溢出 58 | if(op_a_i[31] ^ op_b_i[31]) 59 | branch = op_b_i[31]; 60 | else 61 | branch = (tmp[31] == 1'b1)?UNSUCCESS:SUCCESS; 62 | end 63 | default: branch = UNKNOWN_OPCODE_RESULT; 64 | endcase 65 | end 66 | endmodule 67 | -------------------------------------------------------------------------------- /pipeline/suspend/onBoard/clock_divider.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/05/11 18:57:50 7 | // Design Name: 8 | // Module Name: time 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | // 分频器,将高频时钟信号转化为低频时钟信号用于驱动数码管 22 | // 输入:时钟信号clk 23 | // 输出:低频时钟信号out 24 | module clock_divider( 25 | input clk, 26 | output reg out 27 | ); 28 | reg [15:0] cnt = 0; 29 | reg tag = 1'b0; 30 | always @ (posedge clk) begin 31 | if(tag == 1'b0) begin 32 | out = 1'b0; 33 | tag = 1'b1; 34 | end 35 | else begin 36 | if(cnt == 16'b1010_0001_0010_0000) begin //27'b101_1111_0101_1110_0001_0000_0000 37 | out = ~out; 38 | cnt = 0; 39 | end 40 | else begin 41 | cnt = cnt+1'b1; 42 | end 43 | end 44 | end 45 | endmodule 46 | -------------------------------------------------------------------------------- /pipeline/suspend/onBoard/compare_unit.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 15:41:40 7 | // Design Name: 8 | // Module Name: compare_unit 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 比较运算单元,用于R型与I型指令 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module compare_unit #( 22 | parameter SIGNED = 2'b00, 23 | parameter UNSIGNED = 2'b01, 24 | parameter OTHERS = 32'h0, 25 | parameter SIGNED_LT = 32'h1, 26 | parameter UNSIGNED_LT = 32'h1, 27 | parameter UNKNOWN_OPCODE_RESULT = 32'h0 28 | ) 29 | ( 30 | input [31:0] op_a_i, 31 | input [31:0] op_b_i, 32 | input [1:0] opcode_i, 33 | output reg [31:0] result_o 34 | ); 35 | reg [31:0] tmp; 36 | always@(*) begin 37 | case(opcode_i) 38 | SIGNED: begin 39 | tmp = op_a_i - op_b_i; 40 | // 不同号 41 | if(op_a_i[31]^op_b_i[31]) 42 | result_o = op_a_i[31]; 43 | else 44 | result_o = (tmp[31]==1'b1)?SIGNED_LT:OTHERS; 45 | end 46 | UNSIGNED: begin 47 | result_o = (op_a_i < op_b_i)?UNSIGNED_LT:OTHERS; 48 | end 49 | default: 50 | result_o = UNKNOWN_OPCODE_RESULT; 51 | endcase 52 | end 53 | endmodule 54 | -------------------------------------------------------------------------------- /pipeline/suspend/onBoard/data_hazard_detect.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/16 14:16:30 7 | // Design Name: 8 | // Module Name: suspend_o 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | 22 | 23 | module data_hazard_detect( 24 | input clk_i, 25 | input rst_i, 26 | // input re1_i, 27 | // input re2_i, 28 | input [4:0] rR1_id_exe_i, 29 | input [4:0] rR2_id_exe_i, 30 | input [4:0] wr_exe_mem_i, 31 | input [4:0] wr_mem_wb_i, 32 | input [4:0] wr_wb_i, 33 | input detect_r1, 34 | input detect_r2, 35 | output suspend_o 36 | ); 37 | // reg [1:0] cnt; 38 | // always @(posedge clk_i or posedge rst_i) begin 39 | // if(rst_i) 40 | // suspend_o <= 1'b0; 41 | // else begin 42 | // // 第一类数据冒险,相邻情况 43 | // if(rR1_id_exe_i == wr_exe_mem_i || rR2_id_exe_i == wr_exe_mem_i) 44 | // suspend_o <= 1'b1; 45 | // // 第二类数据冒险,相隔1条指令;第三类数据冒险,访存-读取型 46 | // else if(rR1_id_exe_i == wr_mem_wb_i || rR2_id_exe_i == wr_mem_wb_i) 47 | // suspend_o <= 1'b1; 48 | // else 49 | // suspend_o <= 1'b0; 50 | // end 51 | // end 52 | // always @(posedge clk_i or posedge rst_i) begin 53 | // if(rst_i) 54 | // cnt <= 2'h0; 55 | // else 56 | // if(cnt == 2'h0) begin 57 | // if((rR1_id_exe_i == wr_exe_mem_i || rR2_id_exe_i == wr_exe_mem_i)&&wr_exe_mem_i!=5'h0) 58 | // cnt <= 2'h3; 59 | // else if((rR1_id_exe_i == wr_mem_wb_i || rR2_id_exe_i == wr_mem_wb_i)&&wr_mem_wb_i!=5'h0) 60 | // cnt <= 2'h2; 61 | // else if((rR1_id_exe_i == wr_wb_i || rR2_id_exe_i == wr_wb_i)&&wr_wb_i!=5'h0) 62 | // cnt <= 2'h1; 63 | // else 64 | // cnt <= cnt; 65 | // end 66 | // else 67 | // cnt <= cnt - 1'h1; 68 | // end 69 | // assign suspend_o = (cnt==2'h0)?1'b0:1'b1; 70 | wire rR1_id_exe_hazard = (rR1_id_exe_i == wr_exe_mem_i)?(wr_exe_mem_i!=5'h0):1'b0; 71 | wire rR2_id_exe_hazard = (rR2_id_exe_i == wr_exe_mem_i)?(wr_exe_mem_i!=5'h0):1'b0; 72 | wire rR1_id_mem_hazard = (rR1_id_exe_i == wr_mem_wb_i)?(wr_mem_wb_i!=5'h0):1'b0; 73 | wire rR2_id_mem_hazard = (rR2_id_exe_i == wr_mem_wb_i)?(wr_mem_wb_i!=5'h0):1'b0; 74 | wire rR1_id_wb_hazard = (rR1_id_exe_i == wr_wb_i)?(wr_wb_i!=5'h0):1'b0; 75 | wire rR2_id_wb_hazard = (rR2_id_exe_i == wr_wb_i)?(wr_wb_i!=5'h0):1'b0; 76 | assign suspend_o = ((rR1_id_exe_hazard | rR1_id_mem_hazard | rR1_id_wb_hazard) & detect_r1) 77 | |((rR2_id_exe_hazard | rR2_id_mem_hazard | rR2_id_wb_hazard) & detect_r2); 78 | 79 | endmodule 80 | -------------------------------------------------------------------------------- /pipeline/suspend/onBoard/execute.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 17:22:25 7 | // Design Name: 8 | // Module Name: execute 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 执行模块,集成alu和alu的数据选择器 14 | // Dependencies: 15 | // aluop_selector, alu 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module execute( 22 | input reset_i, 23 | input [1:0] pc_sel_i, 24 | input [31:0] pc_i, 25 | input branch_controler_i, 26 | input op_A_sel_i, 27 | input op_B_sel_i, 28 | input [31:0] current_pc_i, 29 | input [31:0] rD1_i, 30 | input [31:0] rD2_i, 31 | input [31:0] ext_i, 32 | input [4:0] alu_opcode_i, 33 | output [31:0] alu_result_o, 34 | // output alu_branch_o, 35 | output [31:0] next_pc_o 36 | ); 37 | wire [31:0] alu_op_a; 38 | wire [31:0] alu_op_b; 39 | wire alu_branch; 40 | wire branch = branch_controler_i & alu_branch; 41 | aluop_selector u_aluop_selector( 42 | .op_A_sel_i (op_A_sel_i), 43 | .op_B_sel_i (op_B_sel_i), 44 | .current_pc_i(current_pc_i), 45 | .rD1_i (rD1_i), 46 | .rD2_i (rD2_i), 47 | .ext_i (ext_i ), 48 | .alu_op_a_o (alu_op_a), 49 | .alu_op_b_o (alu_op_b) 50 | ); 51 | alu u_alu( 52 | .alu_opcode_i (alu_opcode_i), 53 | .alu_op_a_i (alu_op_a), 54 | .alu_op_b_i (alu_op_b), 55 | .alu_result_o (alu_result_o), 56 | .branch_o (alu_branch) 57 | ); 58 | npc u_npc( 59 | .reset_i (reset_i), 60 | .pc_sel_i (pc_sel_i), 61 | .pc_i (pc_i), 62 | .offset_i (ext_i), 63 | .rD1_i (rD1_i), 64 | .branch_i (branch), 65 | .next_pc_o(next_pc_o) 66 | ); 67 | endmodule 68 | -------------------------------------------------------------------------------- /pipeline/suspend/onBoard/imm_gen.v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yikai-coder/HITsz_CPU_design/c1d6cea65b82fd382c3bf34725d2e8ccb11a9936/pipeline/suspend/onBoard/imm_gen.v -------------------------------------------------------------------------------- /pipeline/suspend/onBoard/instruction_decoder.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/01 17:00:09 7 | // Design Name: 8 | // Module Name: imm_gen 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 译码模块,集成寄存器堆和立即数生成模块 14 | // Dependencies: 15 | // reg_file,imm_gen 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module instruction_decoder #( 22 | parameter RETURN_PC = 2'b00, 23 | parameter ALU_RESULT = 2'b01, 24 | parameter MEM_DATA = 2'b10 25 | ) 26 | ( 27 | input reset_i, 28 | input [31:0] return_pc_i, 29 | input [31:0] ALU_result_i, 30 | input [31:0] mem_data_i, 31 | input [1:0] wd_sel_i, 32 | input [4:0] wr_i, 33 | input we_i, 34 | input clk_i, 35 | input [31:0] inst_i, 36 | input [2:0] imm_sel_i, 37 | output [31:0] ext_o, 38 | output [31:0] rD1_o, 39 | output [31:0] rD2_o, 40 | output [31:0] rD19_o 41 | // output reg write_back // 写回阶段信号 42 | ); 43 | 44 | reg [31:0] wD; 45 | reg [4:0] wr; 46 | // 根据wd_sel选择写入数据 47 | // 写入寄存器恒为inst[11:7] 48 | always @(*) begin 49 | case(wd_sel_i) 50 | RETURN_PC: begin 51 | wD = return_pc_i; 52 | end 53 | ALU_RESULT: begin 54 | wD = ALU_result_i; 55 | end 56 | MEM_DATA: begin 57 | wD = mem_data_i; 58 | end 59 | default: begin 60 | wD = 32'h0; 61 | end 62 | endcase 63 | end 64 | 65 | reg_file u_reg_file( 66 | .clk_i (clk_i), 67 | .reset_i (reset_i), 68 | .rR1_i (inst_i[19:15]), 69 | .rR2_i (inst_i[24:20]), 70 | .wR_i (wr_i), 71 | .wD_i (wD), 72 | .WE_i (we_i), 73 | .rD1_o (rD1_o), 74 | .rD2_o (rD2_o), 75 | .rD19_o (rD19_o) 76 | ); 77 | // assign we_o = we_i; 78 | // assign wD_o = wD; 79 | // assign wR_o = wr; 80 | 81 | imm_gen u_imm_gen( 82 | .reset_i (reset_i), 83 | .inst_i (inst_i), 84 | .imm_sel_i (imm_sel_i), 85 | .ext_o (ext_o) 86 | ); 87 | endmodule 88 | -------------------------------------------------------------------------------- /pipeline/suspend/onBoard/instruction_fetch.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/01 15:31:29 7 | // Design Name: 8 | // Module Name: instruction_fetch 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 取指模块 14 | // 包含pc,npc,irom三个子模块 15 | // Dependencies: 16 | // 17 | // Revision: 18 | // Revision 0.01 - File Created 19 | // Additional Comments: 20 | // 21 | ////////////////////////////////////////////////////////////////////////////////// 22 | module instruction_fetch( 23 | input clk_i, 24 | input reset_i, 25 | input [31:0] next_pc_i, 26 | input data_suspend_i, 27 | input flush_i, 28 | output [31:0] inst_o, 29 | output [31:0] return_pc_o, 30 | output [31:0] current_pc_o // 用于auipc 31 | ); 32 | // wire [31:0] npc; 33 | wire [31:0] pc; 34 | assign current_pc_o = pc; 35 | assign return_pc_o = pc + 3'h4; 36 | pc u_pc( 37 | .npc_i (next_pc_i), 38 | .clk_i (clk_i), 39 | .reset_i (reset_i), 40 | .data_suspend_i (data_suspend_i), 41 | .flush_i (flush_i), 42 | .pc_o (pc) 43 | ); 44 | // npc模块转移到EXE中 45 | // npc u_npc( 46 | // .reset_i (reset_i), 47 | // .pc_sel_i (pc_sel_i), 48 | // .pc_i (pc), 49 | // .offset_i (offset_i), 50 | // .rD1_i (rD1_i), 51 | // .branch_i (branch_i), 52 | // .next_pc_o (npc), 53 | // .pc_plus_4_o(return_pc_o) 54 | // // ); 55 | irom u_irom( 56 | .pc_i (pc), 57 | .inst_o(inst_o) 58 | ); 59 | // prgom u_prgom( 60 | // .pc_i (pc), 61 | // .inst_o(inst_o) 62 | // ); 63 | endmodule 64 | -------------------------------------------------------------------------------- /pipeline/suspend/onBoard/irom.v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yikai-coder/HITsz_CPU_design/c1d6cea65b82fd382c3bf34725d2e8ccb11a9936/pipeline/suspend/onBoard/irom.v -------------------------------------------------------------------------------- /pipeline/suspend/onBoard/jump_examine.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/16 15:03:15 7 | // Design Name: 8 | // Module Name: jump_examine 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 放置在if模块后方检测跳转指令的出现 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | 22 | 23 | module jump_examine #( 24 | parameter JALR_OPCODE = 7'b1100111, 25 | parameter B_OPCODE = 7'b1100011, 26 | parameter JAL_OPCODE = 7'b1101111 27 | ) 28 | ( 29 | input clk_i, 30 | input rst_i, 31 | input [31:0] npc_i, 32 | input [31:0] current_pc_i, 33 | output flush_o 34 | ); 35 | // reg [31:0] pc_1; 36 | // reg [31:0] pc_2; 37 | // always @(posedge clk_i or posedge rst_i) begin 38 | // if(rst_i) begin 39 | // pc_1 <= 32'hfffffffc; 40 | // pc_2 <= 32'hfffffffc; 41 | // end 42 | // else begin 43 | // pc_2 <= pc_1; 44 | // pc_1 <= current_pc_i; 45 | // end 46 | // end 47 | assign flush_o = (npc_i!=current_pc_i+3'h4); 48 | endmodule 49 | -------------------------------------------------------------------------------- /pipeline/suspend/onBoard/logic_unit.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 15:41:40 7 | // Design Name: 8 | // Module Name: logic_unit 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // alu下的逻辑运算单元 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module logic_unit #( 22 | parameter AND = 2'b00, 23 | parameter OR = 2'b01, 24 | parameter XOR = 2'b10, 25 | parameter UNKNOWN_OPCODE_RESULT = 32'h0 26 | ) 27 | ( 28 | input [31:0] op_a_i, 29 | input [31:0] op_b_i, 30 | input [1:0] opcode_i, 31 | output reg [31:0] result_o 32 | ); 33 | always @(*) begin 34 | case(opcode_i) 35 | AND: result_o = op_a_i & op_b_i; 36 | OR: result_o = op_a_i | op_b_i; 37 | XOR: result_o = op_a_i ^ op_b_i; 38 | default: result_o = UNKNOWN_OPCODE_RESULT; 39 | endcase 40 | end 41 | endmodule 42 | -------------------------------------------------------------------------------- /pipeline/suspend/onBoard/npc.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/01 14:28:45 7 | // Design Name: 8 | // Module Name: npc 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // npc数据处理,根据pc_sel输出不同指令对应的下一周期pc信号 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module npc #( 22 | parameter INTERPRETER_NPC = 32'b0 // 对应pc_sel信号异常,转入中断处理 23 | ) 24 | ( 25 | input reset_i, 26 | input [1:0] pc_sel_i, 27 | input [31:0] pc_i, 28 | input [31:0] offset_i, 29 | input [31:0] rD1_i, 30 | input branch_i, 31 | output reg [31:0] next_pc_o, 32 | output [31:0] pc_plus_4_o // 用于jal指令与jalr指令 33 | ); 34 | always @(*) begin 35 | if(reset_i == 1'b1) 36 | next_pc_o = pc_i; 37 | else begin 38 | case (pc_sel_i) 39 | 2'b00: next_pc_o = pc_i + 3'b100; // pc+4 40 | 2'b01: next_pc_o = (branch_i==1'b1)?pc_i+offset_i:pc_i+3'b100; //Branch 41 | 2'b10: next_pc_o = pc_i+offset_i; // jal 42 | 2'b11: next_pc_o = (rD1_i+offset_i)&(~1); // jalr 43 | default: 44 | next_pc_o = INTERPRETER_NPC; 45 | endcase 46 | end 47 | end 48 | assign pc_plus_4_o = pc_i+3'b100; 49 | endmodule 50 | -------------------------------------------------------------------------------- /pipeline/suspend/onBoard/pc.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/01 14:22:58 7 | // Design Name: 8 | // Module Name: pc 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // PC寄存器,在每个时钟上升沿将前一个周期送入的npc输出 14 | // 在复位信号送来时输出复位后首条指令的PC值 15 | // Dependencies: 16 | // 17 | // Revision: 18 | // Revision 0.01 - File Created 19 | // Additional Comments: 20 | // 21 | ////////////////////////////////////////////////////////////////////////////////// 22 | module pc#( 23 | parameter INIT_PC = 32'hfffffffc // 假设0为CPU复位后的首条指令对应地址 24 | ) 25 | ( 26 | input [31:0] npc_i, 27 | input clk_i, 28 | input reset_i, 29 | input data_suspend_i, 30 | input flush_i, 31 | output reg [31:0] pc_o 32 | ); 33 | reg first_time; // 用于防止reset失效的当个周期时间不够无法完成一条指令,将第一条指令的执行时间推迟到下一次时钟上升沿到来 34 | // always @(posedge clk_i or posedge reset_i) begin 35 | // if(reset_i) begin 36 | // pc_o <= INIT_PC; 37 | // first_time <= 1'b0; 38 | // end 39 | // else begin 40 | // first_time <= 1'b1; 41 | // if(first_time == 1'b0) 42 | // pc_o <= INIT_PC; 43 | // else 44 | // // pc_o <= npc_i; 45 | // if(data_suspend_i) 46 | // pc_o <= pc_o; 47 | // else if(flush_i) 48 | // pc_o <= npc_i; 49 | // else 50 | // pc_o <= pc_o + 3'h4; 51 | // end 52 | // end 53 | always @(posedge clk_i or posedge reset_i) begin 54 | if(reset_i) 55 | pc_o <= INIT_PC; 56 | else 57 | if(flush_i) 58 | pc_o <= npc_i; 59 | else if(data_suspend_i) 60 | pc_o <= pc_o; 61 | else 62 | pc_o <= pc_o + 3'h4; 63 | end 64 | endmodule 65 | -------------------------------------------------------------------------------- /pipeline/suspend/onBoard/reg_exe_mem.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ps 2 | module reg_exe_mem( 3 | input clk_i, 4 | input rst_i, 5 | input [31:0] alu_result_i, 6 | input [31:0] mem_wd_i, 7 | input mem_we_i, 8 | input [1:0] mem_data_sel_i, 9 | input [4:0] wr_i, 10 | input [1:0] wd_sel_i, 11 | input regfile_we_i, 12 | input [31:0] return_pc_i, 13 | input [31:0] current_pc_i, 14 | output reg [31:0] current_pc_o, 15 | output reg [31:0] alu_result_o, 16 | output reg [31:0] mem_wd_o, 17 | output reg mem_we_o, 18 | output reg [1:0] mem_data_sel_o, 19 | output reg [4:0] wr_o, 20 | output reg [1:0] wd_sel_o, 21 | output reg regfile_we_o, 22 | output reg [31:0] return_pc_o 23 | ); 24 | always @(posedge clk_i or posedge rst_i) begin 25 | if(rst_i) 26 | alu_result_o <= 32'h0; 27 | else 28 | alu_result_o <= alu_result_i; 29 | end 30 | always @(posedge clk_i or posedge rst_i) begin 31 | if(rst_i) 32 | mem_wd_o <= 32'h0; 33 | else 34 | mem_wd_o <= mem_wd_i; 35 | end 36 | always @(posedge clk_i or posedge rst_i) begin 37 | if(rst_i) 38 | mem_we_o <= 1'b0; 39 | else 40 | mem_we_o <= mem_we_i; 41 | end 42 | always @(posedge clk_i or posedge rst_i) begin 43 | if(rst_i) 44 | mem_data_sel_o <= 2'h0; 45 | else 46 | mem_data_sel_o <= mem_data_sel_i; 47 | end 48 | always @(posedge clk_i or posedge rst_i) begin 49 | if(rst_i) 50 | wr_o <= 4'h0; 51 | else 52 | wr_o <= wr_i; 53 | end 54 | always @(posedge clk_i or posedge rst_i) begin 55 | if(rst_i) 56 | wd_sel_o <= 2'h0; 57 | else 58 | wd_sel_o <= wd_sel_i; 59 | end 60 | always @(posedge clk_i or posedge rst_i) begin 61 | if(rst_i) 62 | regfile_we_o <= 1'b0; 63 | else 64 | regfile_we_o <= regfile_we_i; 65 | end 66 | always @(posedge clk_i or posedge rst_i) begin 67 | if(rst_i) 68 | return_pc_o <= 32'h0; 69 | else 70 | return_pc_o <= return_pc_i; 71 | end 72 | always @(posedge clk_i or posedge rst_i) begin 73 | if(rst_i) 74 | current_pc_o <= 32'h0; 75 | else 76 | current_pc_o <= current_pc_i; 77 | end 78 | 79 | endmodule -------------------------------------------------------------------------------- /pipeline/suspend/onBoard/reg_if_id.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ps 2 | // IF/ID流水线寄存器 3 | module reg_if_id #( 4 | parameter INIT_PC = 32'h0 5 | ) 6 | ( 7 | input clk_i, 8 | input rst_i, 9 | input [31:0] inst_i, 10 | input [31:0] current_pc_i, 11 | input [31:0] return_pc_i, 12 | input suspend_i, 13 | input flush_i, 14 | output reg [31:0] inst_o, 15 | output reg [31:0] current_pc_o, 16 | output reg [31:0] return_pc_o 17 | ); 18 | always @(posedge clk_i or posedge rst_i) begin 19 | if(rst_i) 20 | inst_o <= INIT_PC; 21 | else 22 | if(flush_i) 23 | inst_o <= INIT_PC; 24 | else if(suspend_i) 25 | inst_o <= inst_o; 26 | else 27 | inst_o <= inst_i; 28 | end 29 | always @(posedge clk_i or posedge rst_i) begin 30 | if(rst_i) 31 | current_pc_o <= 32'h0; 32 | else 33 | if(flush_i) 34 | current_pc_o <= 32'h0; 35 | else if(suspend_i) 36 | current_pc_o <= current_pc_o; 37 | else 38 | current_pc_o <= current_pc_i; 39 | end 40 | always @(posedge clk_i or posedge rst_i) begin 41 | if(rst_i) 42 | return_pc_o <= 32'h0; 43 | else 44 | if(flush_i) 45 | return_pc_o <= 32'h0; 46 | else if(suspend_i) 47 | return_pc_o <= return_pc_o; 48 | else 49 | return_pc_o <= return_pc_i; 50 | end 51 | endmodule -------------------------------------------------------------------------------- /pipeline/suspend/onBoard/reg_mem_wb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/14 09:22:34 7 | // Design Name: 8 | // Module Name: reg_mem_wb 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module reg_mem_wb( 22 | input clk_i, 23 | input rst_i, 24 | input [31:0] return_pc_i, 25 | input [31:0] alu_result_i, 26 | input [31:0] mem_rd_i, 27 | input [4:0] wr_i, 28 | input [1:0] wd_sel_i, 29 | input regfile_we_i, 30 | input [31:0] current_pc_i, 31 | output reg [31:0] current_pc_o, 32 | output reg [31:0] return_pc_o, 33 | output reg [31:0] alu_result_o, 34 | output reg [31:0] mem_rd_o, 35 | output reg [4:0] wr_o, 36 | output reg [1:0] wd_sel_o, 37 | output reg regfile_we_o 38 | ); 39 | always @(posedge clk_i or posedge rst_i) begin 40 | if(rst_i) 41 | return_pc_o <= 32'h0; 42 | else 43 | return_pc_o <= return_pc_i; 44 | end 45 | always @(posedge clk_i or posedge rst_i) begin 46 | if(rst_i) 47 | alu_result_o <= 32'h0; 48 | else 49 | alu_result_o <= alu_result_i; 50 | end 51 | always @(posedge clk_i or posedge rst_i) begin 52 | if(rst_i) 53 | mem_rd_o <= 32'h0; 54 | else 55 | mem_rd_o <= mem_rd_i; 56 | end 57 | always @(posedge clk_i or posedge rst_i) begin 58 | if(rst_i) 59 | wr_o <= 5'h0; 60 | else 61 | wr_o <= wr_i; 62 | end 63 | always @(posedge clk_i or posedge rst_i) begin 64 | if(rst_i) 65 | wd_sel_o <= 2'h0; 66 | else 67 | wd_sel_o <= wd_sel_i; 68 | end 69 | always @(posedge clk_i or posedge rst_i) begin 70 | if(rst_i) 71 | regfile_we_o <= 1'b0; 72 | else 73 | regfile_we_o <= regfile_we_i; 74 | end 75 | always @(posedge clk_i or posedge rst_i) begin 76 | if(rst_i) 77 | current_pc_o <= 32'h0; 78 | else 79 | current_pc_o <= current_pc_i; 80 | end 81 | endmodule 82 | -------------------------------------------------------------------------------- /pipeline/suspend/onBoard/shift_unit.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 15:41:40 7 | // Design Name: 8 | // Module Name: shift_unit 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // alu下的移位操作单元,通过桶形移位器实现 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module shift_unit #( 22 | parameter LEFT_SHIFT = 2'b00, 23 | parameter RIGHT_LOGIC_SHIFT = 2'b01, 24 | parameter RIGHT_ARITHMETIC_SHIFT = 2'b10, 25 | parameter UNKNOWN_OPCODE_RESULT = 32'h0 26 | ) 27 | ( 28 | input [31:0] op_a_i, 29 | input [31:0] op_b_i, // 实际只有低5位有效,高位是拓展而来 30 | input [1:0] opcode_i, 31 | output [31:0] result_o 32 | ); 33 | reg [31:0] tmp; 34 | always @(*) begin 35 | case(opcode_i) 36 | LEFT_SHIFT:begin 37 | tmp = (op_b_i[0]==1'b1)?{op_a_i[30:0], 1'b0} :op_a_i; 38 | tmp = (op_b_i[1]==1'b1)?{tmp[29:0], 2'b0} :tmp; 39 | tmp = (op_b_i[2]==1'b1)?{tmp[27:0], 4'b0} :tmp; 40 | tmp = (op_b_i[3]==1'b1)?{tmp[23:0], 8'b0} :tmp; 41 | tmp = (op_b_i[4]==1'b1)?{tmp[15:0], 16'b0} :tmp; 42 | end 43 | RIGHT_LOGIC_SHIFT:begin 44 | tmp = (op_b_i[0]==1'b1)?{1'b0, op_a_i[31:1]}:op_a_i; 45 | tmp = (op_b_i[1]==1'b1)?{2'b0, tmp[31:2]} :tmp; 46 | tmp = (op_b_i[2]==1'b1)?{4'b0, tmp[31:4]} :tmp; 47 | tmp = (op_b_i[3]==1'b1)?{8'b0, tmp[31:8]} :tmp; 48 | tmp = (op_b_i[4]==1'b1)?{16'b0, tmp[31:16]} :tmp; 49 | end 50 | RIGHT_ARITHMETIC_SHIFT: begin 51 | tmp = (op_b_i[0]==1'b1)?{{1{op_a_i[31]}}, op_a_i[31:1]}:op_a_i; 52 | tmp = (op_b_i[1]==1'b1)?{{2{op_a_i[31]}}, tmp[31:2]} :tmp; 53 | tmp = (op_b_i[2]==1'b1)?{{4{op_a_i[31]}}, tmp[31:4]} :tmp; 54 | tmp = (op_b_i[3]==1'b1)?{{8{op_a_i[31]}}, tmp[31:8]} :tmp; 55 | tmp = (op_b_i[4]==1'b1)?{{16{op_a_i[31]}}, tmp[31:16]} :tmp; 56 | end 57 | default: tmp = UNKNOWN_OPCODE_RESULT; 58 | endcase 59 | end 60 | assign result_o = tmp; 61 | endmodule 62 | -------------------------------------------------------------------------------- /pipeline/suspend/onBoard/top.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/08 14:10:06 7 | // Design Name: 8 | // Module Name: top 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | 22 | 23 | module top( 24 | input clk_i, 25 | input rst_i, 26 | output wire led0_en, 27 | output wire led1_en, 28 | output wire led2_en, 29 | output wire led3_en, 30 | output wire led4_en, 31 | output wire led5_en, 32 | output wire led6_en, 33 | output wire led7_en, 34 | output wire led_ca , 35 | output wire led_cb , 36 | output wire led_cc , 37 | output wire led_cd , 38 | output wire led_ce , 39 | output wire led_cf , 40 | output wire led_cg , 41 | output wire led_dp 42 | ); 43 | wire [31:0] rD19; 44 | wire clk_display; 45 | wire rst_n = ~rst_i; 46 | my_cpu u_my_cpu( 47 | .sysclk_i(clk_i), 48 | .reset_i (rst_i), 49 | .rD19_o (rD19) 50 | ); 51 | clock_divider u_clock_divider( 52 | .clk(clk_i), 53 | .out(clk_display) 54 | ); 55 | display u_display( 56 | .clk (clk_display), 57 | .rst_n(rst_n), 58 | .busy (1'b0), 59 | .z1 (rD19[31:24]), 60 | .r1 (rD19[23:16]), 61 | .z2 (rD19[15:8]), 62 | .r2 (rD19[7:0]), 63 | .led0_en(led0_en), 64 | .led1_en(led1_en), 65 | .led2_en(led2_en), 66 | .led3_en(led3_en), 67 | .led4_en(led4_en), 68 | .led5_en(led5_en), 69 | .led6_en(led6_en), 70 | .led7_en(led7_en), 71 | .led_ca (led_ca), 72 | .led_cb (led_cb), 73 | .led_cc (led_cc), 74 | .led_cd (led_cd), 75 | .led_ce (led_ce), 76 | .led_cf (led_cf), 77 | .led_cg (led_cg), 78 | .led_dp (led_dp) 79 | ); 80 | 81 | endmodule 82 | -------------------------------------------------------------------------------- /pipeline/suspend/trace/alu.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 15:34:04 7 | // Design Name: 8 | // Module Name: alu 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 集成算数单元,逻辑运算单元,比较单元,移位单元,以及专用于b型指令的运算单元 14 | // alu_opcode的【3:2】用于选择不同单元的输出结果作为最终输出 15 | // alu_opcode的【1:0】作为不同单元的操作码 16 | // alu_opcode【4】专门用于lui指令直接输出op_b 17 | // Dependencies: 18 | // arithmetic_unit, compare_unit,logic_unit,shift_unit,branch_unit 19 | // Revision: 20 | // Revision 0.01 - File Created 21 | // Additional Comments: 22 | // 23 | ////////////////////////////////////////////////////////////////////////////////// 24 | module alu #( 25 | parameter ARITHMETiC = 2'b00, 26 | parameter COMPARE = 2'b01, 27 | parameter LOGIC = 2'b10, 28 | parameter SHIFT = 2'b11 29 | ) 30 | ( 31 | input [4:0] alu_opcode_i, 32 | input [31:0] alu_op_a_i, 33 | input [31:0] alu_op_b_i, 34 | output reg [31:0] alu_result_o, 35 | output branch_o 36 | ); 37 | wire [31:0] result_arithmetic; 38 | wire [31:0] result_compare; 39 | wire [31:0] result_logic; 40 | wire [31:0] result_shift; 41 | // 算数运算单元 42 | arithmetic_unit u_arithmetic_unit( 43 | .op_a_i (alu_op_a_i), 44 | .op_b_i (alu_op_b_i), 45 | .opcode_i(alu_opcode_i[1:0]), 46 | .result_o(result_arithmetic) 47 | ); 48 | // 比较操作单元 49 | compare_unit u_compare_unit( 50 | .op_a_i (alu_op_a_i), 51 | .op_b_i (alu_op_b_i), 52 | .opcode_i(alu_opcode_i[1:0]), 53 | .result_o(result_compare) 54 | ); 55 | // 逻辑运算单元 56 | logic_unit u_logic_unit( 57 | .op_a_i (alu_op_a_i), 58 | .op_b_i (alu_op_b_i), 59 | .opcode_i(alu_opcode_i[1:0]), 60 | .result_o(result_logic) 61 | ); 62 | // 移位运算单元 63 | shift_unit u_shift_unit( 64 | .op_a_i (alu_op_a_i), 65 | .op_b_i (alu_op_b_i), 66 | .opcode_i(alu_opcode_i[1:0]), 67 | .result_o(result_shift) 68 | ); 69 | // B型指令专用branch分支运算单元 70 | branch_unit u_branch_unit( 71 | .op_a_i (alu_op_a_i), 72 | .op_b_i (alu_op_b_i), 73 | .opcode_i(alu_opcode_i[3:0]), 74 | .branch (branch_o) 75 | ); 76 | // 根据opcode选择输出哪个单元的结果 77 | always @(*) begin 78 | // lui指令 79 | if(alu_opcode_i[4]) 80 | alu_result_o = alu_op_b_i; 81 | else 82 | case(alu_opcode_i[3:2]) 83 | ARITHMETiC: alu_result_o = result_arithmetic; 84 | COMPARE: alu_result_o = result_compare; 85 | LOGIC: alu_result_o = result_logic; 86 | SHIFT: alu_result_o = result_shift; 87 | endcase 88 | end 89 | 90 | endmodule 91 | -------------------------------------------------------------------------------- /pipeline/suspend/trace/aluop_selector.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 14:47:37 7 | // Design Name: 8 | // Module Name: aluop_selector 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 根据op_A_sel和op_B_sel选择送入alu的操作输 14 | // op_A:1'b0: 当前pc 15 | // 1'b1: rD1 16 | // op_B:1'b0: imm 17 | // 1'b1: rD2 18 | // Dependencies: 19 | // 20 | // Revision: 21 | // Revision 0.01 - File Created 22 | // Additional Comments: 23 | // 24 | ////////////////////////////////////////////////////////////////////////////////// 25 | module aluop_selector #( 26 | parameter CURRENTPC = 1'b0, 27 | parameter RD1 = 1'b1, 28 | parameter EXT = 1'b0, 29 | parameter RD2 = 1'b1 30 | ) 31 | ( 32 | input op_A_sel_i, 33 | input op_B_sel_i, 34 | input [31:0] current_pc_i, 35 | input [31:0] rD1_i, 36 | input [31:0] rD2_i, 37 | input [31:0] ext_i, 38 | output reg [31:0] alu_op_a_o, 39 | output reg [31:0] alu_op_b_o 40 | ); 41 | // alu_a选择 42 | always @(*) begin 43 | case(op_A_sel_i) 44 | CURRENTPC: alu_op_a_o = current_pc_i; 45 | RD1: alu_op_a_o = rD1_i; 46 | default: alu_op_a_o = 32'h0; 47 | endcase 48 | end 49 | // alu_b选择 50 | always @(*) begin 51 | case(op_B_sel_i) 52 | EXT: alu_op_b_o = ext_i; 53 | RD2: alu_op_b_o = rD2_i; 54 | default: alu_op_b_o = 32'h0; 55 | endcase 56 | end 57 | endmodule 58 | -------------------------------------------------------------------------------- /pipeline/suspend/trace/arithmetic_unit.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 15:41:40 7 | // Design Name: 8 | // Module Name: arithmetic_unit 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 算数运算单元,根据传入的两个操作数和操作码进行算术运算 14 | // opcode:00:加法 15 | // 01:减法 16 | // Dependencies: 17 | // 18 | // Revision: 19 | // Revision 0.01 - File Created 20 | // Additional Comments: 21 | // 22 | ////////////////////////////////////////////////////////////////////////////////// 23 | module arithmetic_unit #( 24 | parameter PLUS = 2'b00, 25 | parameter SUB = 2'b01, 26 | parameter UNKNOWN_OPCODE_RESULT = 32'h0 27 | ) 28 | ( 29 | input [31:0] op_a_i, 30 | input [31:0] op_b_i, 31 | input [1:0] opcode_i, 32 | output reg [31:0] result_o 33 | ); 34 | always @(*) begin 35 | case(opcode_i) 36 | PLUS: result_o = op_a_i + op_b_i; 37 | SUB: result_o = op_a_i + (~op_b_i+1'b1); // 采用加补码的方式实现减法 38 | default: result_o = UNKNOWN_OPCODE_RESULT; 39 | endcase 40 | end 41 | endmodule 42 | -------------------------------------------------------------------------------- /pipeline/suspend/trace/branch_unit.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 16:45:19 7 | // Design Name: 8 | // Module Name: branch_unit 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // B型指令专用branch运算单元 14 | // 15 | // Dependencies: 16 | // 17 | // Revision: 18 | // Revision 0.01 - File Created 19 | // Additional Comments: 20 | // 21 | ////////////////////////////////////////////////////////////////////////////////// 22 | module branch_unit#( 23 | parameter EQ = 4'h0, 24 | parameter NEQ = 4'h1, 25 | parameter UNSIGNED_LT = 4'h2, 26 | parameter SIGNED_LT = 4'h3, 27 | parameter UNSIGNED_GE = 4'h4, 28 | parameter SIGNED_GE = 4'h5, 29 | parameter SUCCESS = 1'b1, 30 | parameter UNSUCCESS = 1'b0, 31 | parameter UNKNOWN_OPCODE_RESULT = 1'b0 32 | ) 33 | ( 34 | input [31:0] op_a_i, 35 | input [31:0] op_b_i, 36 | input [3:0] opcode_i, 37 | output reg branch 38 | ); 39 | reg [31:0] tmp; 40 | always @(*) begin 41 | tmp = op_a_i - op_b_i; 42 | end 43 | always @(*) begin 44 | case(opcode_i) 45 | EQ: branch = (tmp == 32'h0)?SUCCESS:UNSUCCESS; 46 | NEQ: branch = (tmp == 32'h0)?UNSUCCESS:SUCCESS; 47 | UNSIGNED_LT: branch = (op_a_i < op_b_i)?SUCCESS:UNSUCCESS; 48 | SIGNED_LT: begin 49 | // 对符号不同的情况特殊处理,防止发生溢出 50 | if(op_a_i[31] ^ op_b_i[31]) 51 | branch = op_a_i[31]; 52 | else 53 | branch = (tmp[31] == 1'b1)?SUCCESS:UNSUCCESS; 54 | end 55 | UNSIGNED_GE: branch = (op_a_i < op_b_i)?UNSUCCESS:SUCCESS; 56 | SIGNED_GE: begin 57 | // 对符号不同的情况特殊处理,防止发生溢出 58 | if(op_a_i[31] ^ op_b_i[31]) 59 | branch = op_b_i[31]; 60 | else 61 | branch = (tmp[31] == 1'b1)?UNSUCCESS:SUCCESS; 62 | end 63 | default: branch = UNKNOWN_OPCODE_RESULT; 64 | endcase 65 | end 66 | endmodule 67 | -------------------------------------------------------------------------------- /pipeline/suspend/trace/clock_divider.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/05/11 18:57:50 7 | // Design Name: 8 | // Module Name: time 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | // 分频器,将高频时钟信号转化为低频时钟信号用于驱动数码管 22 | // 输入:时钟信号clk 23 | // 输出:低频时钟信号out 24 | module clock_divider( 25 | input clk, 26 | output reg out 27 | ); 28 | reg [15:0] cnt = 0; 29 | reg tag = 1'b0; 30 | always @ (posedge clk) begin 31 | if(tag == 1'b0) begin 32 | out = 1'b0; 33 | tag = 1'b1; 34 | end 35 | else begin 36 | if(cnt == 16'b1010_0001_0010_0000) begin //27'b101_1111_0101_1110_0001_0000_0000 37 | out = ~out; 38 | cnt = 0; 39 | end 40 | else begin 41 | cnt = cnt+1'b1; 42 | end 43 | end 44 | end 45 | endmodule 46 | -------------------------------------------------------------------------------- /pipeline/suspend/trace/compare_unit.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 15:41:40 7 | // Design Name: 8 | // Module Name: compare_unit 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 比较运算单元,用于R型与I型指令 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module compare_unit #( 22 | parameter SIGNED = 2'b00, 23 | parameter UNSIGNED = 2'b01, 24 | parameter OTHERS = 32'h0, 25 | parameter SIGNED_LT = 32'h1, 26 | parameter UNSIGNED_LT = 32'h1, 27 | parameter UNKNOWN_OPCODE_RESULT = 32'h0 28 | ) 29 | ( 30 | input [31:0] op_a_i, 31 | input [31:0] op_b_i, 32 | input [1:0] opcode_i, 33 | output reg [31:0] result_o 34 | ); 35 | reg [31:0] tmp; 36 | always@(*) begin 37 | case(opcode_i) 38 | SIGNED: begin 39 | tmp = op_a_i - op_b_i; 40 | // 不同号 41 | if(op_a_i[31]^op_b_i[31]) 42 | result_o = op_a_i[31]; 43 | else 44 | result_o = (tmp[31]==1'b1)?SIGNED_LT:OTHERS; 45 | end 46 | UNSIGNED: begin 47 | result_o = (op_a_i < op_b_i)?UNSIGNED_LT:OTHERS; 48 | end 49 | default: 50 | result_o = UNKNOWN_OPCODE_RESULT; 51 | endcase 52 | end 53 | endmodule 54 | -------------------------------------------------------------------------------- /pipeline/suspend/trace/data_hazard_detect.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/16 14:16:30 7 | // Design Name: 8 | // Module Name: suspend_o 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | 22 | 23 | module data_hazard_detect( 24 | input clk_i, 25 | input rst_i, 26 | // input re1_i, 27 | // input re2_i, 28 | input [4:0] rR1_id_exe_i, 29 | input [4:0] rR2_id_exe_i, 30 | input [4:0] wr_exe_mem_i, 31 | input [4:0] wr_mem_wb_i, 32 | input [4:0] wr_wb_i, 33 | input detect_r1, 34 | input detect_r2, 35 | output suspend_o 36 | ); 37 | wire rR1_id_exe_hazard = (rR1_id_exe_i == wr_exe_mem_i)?(wr_exe_mem_i!=5'h0):1'b0; 38 | wire rR2_id_exe_hazard = (rR2_id_exe_i == wr_exe_mem_i)?(wr_exe_mem_i!=5'h0):1'b0; 39 | wire rR1_id_mem_hazard = (rR1_id_exe_i == wr_mem_wb_i)?(wr_mem_wb_i!=5'h0):1'b0; 40 | wire rR2_id_mem_hazard = (rR2_id_exe_i == wr_mem_wb_i)?(wr_mem_wb_i!=5'h0):1'b0; 41 | wire rR1_id_wb_hazard = (rR1_id_exe_i == wr_wb_i)?(wr_wb_i!=5'h0):1'b0; 42 | wire rR2_id_wb_hazard = (rR2_id_exe_i == wr_wb_i)?(wr_wb_i!=5'h0):1'b0; 43 | assign suspend_o = ((rR1_id_exe_hazard | rR1_id_mem_hazard | rR1_id_wb_hazard) & detect_r1) 44 | |((rR2_id_exe_hazard | rR2_id_mem_hazard | rR2_id_wb_hazard) & detect_r2); 45 | 46 | endmodule 47 | -------------------------------------------------------------------------------- /pipeline/suspend/trace/execute.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 17:22:25 7 | // Design Name: 8 | // Module Name: execute 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 执行模块,集成alu和alu的数据选择器 14 | // Dependencies: 15 | // aluop_selector, alu 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module execute( 22 | input reset_i, 23 | input [1:0] pc_sel_i, 24 | input [31:0] pc_i, 25 | input branch_controler_i, 26 | input op_A_sel_i, 27 | input op_B_sel_i, 28 | input [31:0] current_pc_i, 29 | input [31:0] rD1_i, 30 | input [31:0] rD2_i, 31 | input [31:0] ext_i, 32 | input [4:0] alu_opcode_i, 33 | output [31:0] alu_result_o, 34 | // output alu_branch_o, 35 | output [31:0] next_pc_o 36 | ); 37 | wire [31:0] alu_op_a; 38 | wire [31:0] alu_op_b; 39 | wire alu_branch; 40 | wire branch = branch_controler_i & alu_branch; 41 | aluop_selector u_aluop_selector( 42 | .op_A_sel_i (op_A_sel_i), 43 | .op_B_sel_i (op_B_sel_i), 44 | .current_pc_i(current_pc_i), 45 | .rD1_i (rD1_i), 46 | .rD2_i (rD2_i), 47 | .ext_i (ext_i ), 48 | .alu_op_a_o (alu_op_a), 49 | .alu_op_b_o (alu_op_b) 50 | ); 51 | alu u_alu( 52 | .alu_opcode_i (alu_opcode_i), 53 | .alu_op_a_i (alu_op_a), 54 | .alu_op_b_i (alu_op_b), 55 | .alu_result_o (alu_result_o), 56 | .branch_o (alu_branch) 57 | ); 58 | npc u_npc( 59 | .reset_i (reset_i), 60 | .pc_sel_i (pc_sel_i), 61 | .pc_i (pc_i), 62 | .offset_i (ext_i), 63 | .rD1_i (rD1_i), 64 | .branch_i (branch), 65 | .next_pc_o(next_pc_o) 66 | ); 67 | endmodule 68 | -------------------------------------------------------------------------------- /pipeline/suspend/trace/imm_gen.v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yikai-coder/HITsz_CPU_design/c1d6cea65b82fd382c3bf34725d2e8ccb11a9936/pipeline/suspend/trace/imm_gen.v -------------------------------------------------------------------------------- /pipeline/suspend/trace/instruction_decoder.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/01 17:00:09 7 | // Design Name: 8 | // Module Name: imm_gen 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 译码模块,集成寄存器堆和立即数生成模块 14 | // Dependencies: 15 | // reg_file,imm_gen 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module instruction_decoder #( 22 | parameter RETURN_PC = 2'b00, 23 | parameter ALU_RESULT = 2'b01, 24 | parameter MEM_DATA = 2'b10 25 | ) 26 | ( 27 | input reset_i, 28 | input [31:0] return_pc_i, 29 | input [31:0] ALU_result_i, 30 | input [31:0] mem_data_i, 31 | input [1:0] wd_sel_i, 32 | input [4:0] wr_i, 33 | input we_i, 34 | input clk_i, 35 | input [31:0] inst_i, 36 | input [2:0] imm_sel_i, 37 | output [31:0] wd_o, // test 38 | output [31:0] ext_o, 39 | output [31:0] rD1_o, 40 | output [31:0] rD2_o 41 | // output reg write_back // 写回阶段信号 42 | ); 43 | 44 | reg [31:0] wD; 45 | reg [4:0] wr; 46 | // 根据wd_sel选择写入数据 47 | // 写入寄存器恒为inst[11:7] 48 | always @(*) begin 49 | case(wd_sel_i) 50 | RETURN_PC: begin 51 | wD = return_pc_i; 52 | end 53 | ALU_RESULT: begin 54 | wD = ALU_result_i; 55 | end 56 | MEM_DATA: begin 57 | wD = mem_data_i; 58 | end 59 | default: begin 60 | wD = 32'h0; 61 | end 62 | endcase 63 | end 64 | assign wd_o = wD; 65 | 66 | reg_file u_reg_file( 67 | .clk_i (clk_i), 68 | .reset_i (reset_i), 69 | .rR1_i (inst_i[19:15]), 70 | .rR2_i (inst_i[24:20]), 71 | .wR_i (wr_i), 72 | .wD_i (wD), 73 | .WE_i (we_i), 74 | .rD1_o (rD1_o), 75 | .rD2_o (rD2_o) 76 | ); 77 | // assign we_o = we_i; 78 | // assign wD_o = wD; 79 | // assign wR_o = wr; 80 | 81 | imm_gen u_imm_gen( 82 | .reset_i (reset_i), 83 | .inst_i (inst_i), 84 | .imm_sel_i (imm_sel_i), 85 | .ext_o (ext_o) 86 | ); 87 | endmodule 88 | -------------------------------------------------------------------------------- /pipeline/suspend/trace/instruction_fetch.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/01 15:31:29 7 | // Design Name: 8 | // Module Name: instruction_fetch 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 取指模块 14 | // 包含pc,npc,irom三个子模块 15 | // Dependencies: 16 | // 17 | // Revision: 18 | // Revision 0.01 - File Created 19 | // Additional Comments: 20 | // 21 | ////////////////////////////////////////////////////////////////////////////////// 22 | module instruction_fetch( 23 | input clk_i, 24 | input reset_i, 25 | input [31:0] next_pc_i, 26 | input data_suspend_i, 27 | input flush_i, 28 | output [31:0] inst_o, 29 | output [31:0] return_pc_o, 30 | output [31:0] current_pc_o, // 用于auipc 31 | output [31:0] pc_o 32 | ); 33 | // wire [31:0] npc; 34 | wire [31:0] pc; 35 | assign pc_o = pc; 36 | assign current_pc_o = pc; 37 | assign return_pc_o = pc + 3'h4; 38 | pc u_pc( 39 | .npc_i (next_pc_i), 40 | .clk_i (clk_i), 41 | .reset_i (reset_i), 42 | .data_suspend_i (data_suspend_i), 43 | .flush_i (flush_i), 44 | .pc_o (pc) 45 | ); 46 | // npc模块转移到EXE中 47 | // npc u_npc( 48 | // .reset_i (reset_i), 49 | // .pc_sel_i (pc_sel_i), 50 | // .pc_i (pc), 51 | // .offset_i (offset_i), 52 | // .rD1_i (rD1_i), 53 | // .branch_i (branch_i), 54 | // .next_pc_o (npc), 55 | // .pc_plus_4_o(return_pc_o) 56 | // // ); 57 | // irom u_irom( 58 | // .pc_i (pc), 59 | // .inst_o(inst_o) 60 | // ); 61 | endmodule 62 | -------------------------------------------------------------------------------- /pipeline/suspend/trace/irom.v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yikai-coder/HITsz_CPU_design/c1d6cea65b82fd382c3bf34725d2e8ccb11a9936/pipeline/suspend/trace/irom.v -------------------------------------------------------------------------------- /pipeline/suspend/trace/jump_examine.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/16 15:03:15 7 | // Design Name: 8 | // Module Name: jump_examine 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 放置在if模块后方检测跳转指令的出现 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | 22 | 23 | module jump_examine #( 24 | parameter JALR_OPCODE = 7'b1100111, 25 | parameter B_OPCODE = 7'b1100011, 26 | parameter JAL_OPCODE = 7'b1101111 27 | ) 28 | ( 29 | input clk_i, 30 | input rst_i, 31 | input [31:0] npc_i, 32 | input [31:0] current_pc_i, 33 | output flush_o 34 | ); 35 | // reg [31:0] pc_1; 36 | // reg [31:0] pc_2; 37 | // always @(posedge clk_i or posedge rst_i) begin 38 | // if(rst_i) begin 39 | // pc_1 <= 32'hfffffffc; 40 | // pc_2 <= 32'hfffffffc; 41 | // end 42 | // else begin 43 | // pc_2 <= pc_1; 44 | // pc_1 <= current_pc_i; 45 | // end 46 | // end 47 | assign flush_o = (npc_i!=current_pc_i+3'h4); 48 | endmodule 49 | -------------------------------------------------------------------------------- /pipeline/suspend/trace/logic_unit.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 15:41:40 7 | // Design Name: 8 | // Module Name: logic_unit 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // alu下的逻辑运算单元 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module logic_unit #( 22 | parameter AND = 2'b00, 23 | parameter OR = 2'b01, 24 | parameter XOR = 2'b10, 25 | parameter UNKNOWN_OPCODE_RESULT = 32'h0 26 | ) 27 | ( 28 | input [31:0] op_a_i, 29 | input [31:0] op_b_i, 30 | input [1:0] opcode_i, 31 | output reg [31:0] result_o 32 | ); 33 | always @(*) begin 34 | case(opcode_i) 35 | AND: result_o = op_a_i & op_b_i; 36 | OR: result_o = op_a_i | op_b_i; 37 | XOR: result_o = op_a_i ^ op_b_i; 38 | default: result_o = UNKNOWN_OPCODE_RESULT; 39 | endcase 40 | end 41 | endmodule 42 | -------------------------------------------------------------------------------- /pipeline/suspend/trace/npc.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/01 14:28:45 7 | // Design Name: 8 | // Module Name: npc 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // npc数据处理,根据pc_sel输出不同指令对应的下一周期pc信号 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module npc #( 22 | parameter INTERPRETER_NPC = 32'b0 // 对应pc_sel信号异常,转入中断处理 23 | ) 24 | ( 25 | input reset_i, 26 | input [1:0] pc_sel_i, 27 | input [31:0] pc_i, 28 | input [31:0] offset_i, 29 | input [31:0] rD1_i, 30 | input branch_i, 31 | output reg [31:0] next_pc_o, 32 | output [31:0] pc_plus_4_o // 用于jal指令与jalr指令 33 | ); 34 | always @(*) begin 35 | if(reset_i == 1'b1) 36 | next_pc_o = pc_i; 37 | else begin 38 | case (pc_sel_i) 39 | 2'b00: next_pc_o = pc_i + 3'b100; // pc+4 40 | 2'b01: next_pc_o = (branch_i==1'b1)?pc_i+offset_i:pc_i+3'b100; //Branch 41 | 2'b10: next_pc_o = pc_i+offset_i; // jal 42 | 2'b11: next_pc_o = (rD1_i+offset_i)&(~1); // jalr 43 | default: 44 | next_pc_o = INTERPRETER_NPC; 45 | endcase 46 | end 47 | end 48 | assign pc_plus_4_o = pc_i+3'b100; 49 | endmodule 50 | -------------------------------------------------------------------------------- /pipeline/suspend/trace/pc.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/01 14:22:58 7 | // Design Name: 8 | // Module Name: pc 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // PC寄存器,在每个时钟上升沿将前一个周期送入的npc输出 14 | // 在复位信号送来时输出复位后首条指令的PC值 15 | // Dependencies: 16 | // 17 | // Revision: 18 | // Revision 0.01 - File Created 19 | // Additional Comments: 20 | // 21 | ////////////////////////////////////////////////////////////////////////////////// 22 | module pc#( 23 | parameter INIT_PC = 32'hfffffffc // 假设0为CPU复位后的首条指令对应地址 24 | ) 25 | ( 26 | input [31:0] npc_i, 27 | input clk_i, 28 | input reset_i, 29 | input data_suspend_i, 30 | input flush_i, 31 | output reg [31:0] pc_o 32 | ); 33 | reg first_time; // 用于防止reset失效的当个周期时间不够无法完成一条指令,将第一条指令的执行时间推迟到下一次时钟上升沿到来 34 | // always @(posedge clk_i or posedge reset_i) begin 35 | // if(reset_i) begin 36 | // pc_o <= INIT_PC; 37 | // first_time <= 1'b0; 38 | // end 39 | // else begin 40 | // first_time <= 1'b1; 41 | // if(first_time == 1'b0) 42 | // pc_o <= INIT_PC; 43 | // else 44 | // // pc_o <= npc_i; 45 | // if(data_suspend_i) 46 | // pc_o <= pc_o; 47 | // else if(flush_i) 48 | // pc_o <= npc_i; 49 | // else 50 | // pc_o <= pc_o + 3'h4; 51 | // end 52 | // end 53 | always @(posedge clk_i or posedge reset_i) begin 54 | if(reset_i) 55 | pc_o <= INIT_PC; 56 | else 57 | if(flush_i) 58 | pc_o <= npc_i; 59 | else if(data_suspend_i) 60 | pc_o <= pc_o; 61 | else 62 | pc_o <= pc_o + 3'h4; 63 | end 64 | endmodule 65 | -------------------------------------------------------------------------------- /pipeline/suspend/trace/reg_exe_mem.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ps 2 | module reg_exe_mem( 3 | input clk_i, 4 | input rst_i, 5 | input [31:0] alu_result_i, 6 | input [31:0] mem_wd_i, 7 | input mem_we_i, 8 | input [1:0] mem_data_sel_i, 9 | input [4:0] wr_i, 10 | input [1:0] wd_sel_i, 11 | input regfile_we_i, 12 | input [31:0] return_pc_i, 13 | input [31:0] current_pc_i, 14 | output reg [31:0] current_pc_o, 15 | output reg [31:0] alu_result_o, 16 | output reg [31:0] mem_wd_o, 17 | output reg mem_we_o, 18 | output reg [1:0] mem_data_sel_o, 19 | output reg [4:0] wr_o, 20 | output reg [1:0] wd_sel_o, 21 | output reg regfile_we_o, 22 | output reg [31:0] return_pc_o 23 | ); 24 | always @(posedge clk_i or posedge rst_i) begin 25 | if(rst_i) 26 | alu_result_o <= 32'h0; 27 | else 28 | alu_result_o <= alu_result_i; 29 | end 30 | always @(posedge clk_i or posedge rst_i) begin 31 | if(rst_i) 32 | mem_wd_o <= 32'h0; 33 | else 34 | mem_wd_o <= mem_wd_i; 35 | end 36 | always @(posedge clk_i or posedge rst_i) begin 37 | if(rst_i) 38 | mem_we_o <= 1'b0; 39 | else 40 | mem_we_o <= mem_we_i; 41 | end 42 | always @(posedge clk_i or posedge rst_i) begin 43 | if(rst_i) 44 | mem_data_sel_o <= 2'h0; 45 | else 46 | mem_data_sel_o <= mem_data_sel_i; 47 | end 48 | always @(posedge clk_i or posedge rst_i) begin 49 | if(rst_i) 50 | wr_o <= 4'h0; 51 | else 52 | wr_o <= wr_i; 53 | end 54 | always @(posedge clk_i or posedge rst_i) begin 55 | if(rst_i) 56 | wd_sel_o <= 2'h0; 57 | else 58 | wd_sel_o <= wd_sel_i; 59 | end 60 | always @(posedge clk_i or posedge rst_i) begin 61 | if(rst_i) 62 | regfile_we_o <= 1'b0; 63 | else 64 | regfile_we_o <= regfile_we_i; 65 | end 66 | always @(posedge clk_i or posedge rst_i) begin 67 | if(rst_i) 68 | return_pc_o <= 32'h0; 69 | else 70 | return_pc_o <= return_pc_i; 71 | end 72 | always @(posedge clk_i or posedge rst_i) begin 73 | if(rst_i) 74 | current_pc_o <= 32'h0; 75 | else 76 | current_pc_o <= current_pc_i; 77 | end 78 | 79 | endmodule -------------------------------------------------------------------------------- /pipeline/suspend/trace/reg_file_8.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/01 14:22:58 7 | // Design Name: 8 | // Module Name: pc 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 寄存器堆模块的子模块,每个模块存储8个寄存器 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module reg_file_8( 22 | input clk_i, 23 | input reset_i, 24 | input [4:0] rR1_i, 25 | input [4:0] rR2_i, 26 | input [4:0] wR_i, 27 | input [31:0] wD_i, 28 | input WE_i, 29 | output reg [31:0] rD1_o, 30 | output reg [31:0] rD2_o 31 | ); 32 | reg [31:0] reg_0; 33 | reg [31:0] reg_1; 34 | reg [31:0] reg_2; 35 | reg [31:0] reg_3; 36 | reg [31:0] reg_4; 37 | reg [31:0] reg_5; 38 | reg [31:0] reg_6; 39 | reg [31:0] reg_7; 40 | // rD1_o 41 | always @ (*) begin 42 | case(rR1_i[2:0]) 43 | 3'b000: rD1_o = (rR1_i[4:3]==2'b00)?32'h0:reg_0; // x0不可被修改 44 | 3'b001: rD1_o = reg_1; 45 | 3'b010: rD1_o = reg_2; 46 | 3'b011: rD1_o = reg_3; 47 | 3'b100: rD1_o = reg_4; 48 | 3'b101: rD1_o = reg_5; 49 | 3'b110: rD1_o = reg_6; 50 | 3'b111: rD1_o = reg_7; 51 | default: rD1_o = 32'h0; 52 | endcase 53 | end 54 | // rD2_o 55 | always @ (*) begin 56 | case(rR2_i[2:0]) 57 | 3'b000: rD2_o = (rR2_i[4:3]==2'b00)?32'h0:reg_0; 58 | 3'b001: rD2_o = reg_1; 59 | 3'b010: rD2_o = reg_2; 60 | 3'b011: rD2_o = reg_3; 61 | 3'b100: rD2_o = reg_4; 62 | 3'b101: rD2_o = reg_5; 63 | 3'b110: rD2_o = reg_6; 64 | 3'b111: rD2_o = reg_7; 65 | default: rD2_o = 32'h0; 66 | endcase 67 | end 68 | // wirte 69 | always @ (posedge clk_i or posedge reset_i) begin 70 | if(reset_i == 1'b1) begin 71 | reg_0 = 32'h0; 72 | reg_1 = 32'h0; 73 | reg_2 = 32'h0; 74 | reg_3 = 32'h0; 75 | reg_4 = 32'h0; 76 | reg_5 = 32'h0; 77 | reg_6 = 32'h0; 78 | reg_7 = 32'h0; 79 | end 80 | else 81 | if(WE_i == 1'b1) begin 82 | case(wR_i[2:0]) 83 | 3'b000: reg_0 = (wR_i[4:3]==2'b00)?32'h0:wD_i; 84 | 3'b001: reg_1 = wD_i; 85 | 3'b010: reg_2 = wD_i; 86 | 3'b011: reg_3 = wD_i; 87 | 3'b100: reg_4 = wD_i; 88 | 3'b101: reg_5 = wD_i; 89 | 3'b110: reg_6 = wD_i; 90 | 3'b111: reg_7 = wD_i; 91 | default:; 92 | endcase 93 | end 94 | else; 95 | end 96 | endmodule 97 | -------------------------------------------------------------------------------- /pipeline/suspend/trace/reg_if_id.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns/1ps 2 | // IF/ID流水线寄存器 3 | module reg_if_id #( 4 | parameter INIT_PC = 32'h0 5 | ) 6 | ( 7 | input clk_i, 8 | input rst_i, 9 | input [31:0] inst_i, 10 | input [31:0] current_pc_i, 11 | input [31:0] return_pc_i, 12 | input suspend_i, 13 | input flush_i, 14 | output reg [31:0] inst_o, 15 | output reg [31:0] current_pc_o, 16 | output reg [31:0] return_pc_o 17 | ); 18 | always @(posedge clk_i or posedge rst_i) begin 19 | if(rst_i) 20 | inst_o <= INIT_PC; 21 | else 22 | if(flush_i) 23 | inst_o <= INIT_PC; 24 | else if(suspend_i) 25 | inst_o <= inst_o; 26 | else 27 | inst_o <= inst_i; 28 | end 29 | always @(posedge clk_i or posedge rst_i) begin 30 | if(rst_i) 31 | current_pc_o <= 32'h0; 32 | else 33 | if(flush_i) 34 | current_pc_o <= 32'h0; 35 | else if(suspend_i) 36 | current_pc_o <= current_pc_o; 37 | else 38 | current_pc_o <= current_pc_i; 39 | end 40 | always @(posedge clk_i or posedge rst_i) begin 41 | if(rst_i) 42 | return_pc_o <= 32'h0; 43 | else 44 | if(flush_i) 45 | return_pc_o <= 32'h0; 46 | else if(suspend_i) 47 | return_pc_o <= return_pc_o; 48 | else 49 | return_pc_o <= return_pc_i; 50 | end 51 | endmodule -------------------------------------------------------------------------------- /pipeline/suspend/trace/reg_mem_wb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/14 09:22:34 7 | // Design Name: 8 | // Module Name: reg_mem_wb 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module reg_mem_wb( 22 | input clk_i, 23 | input rst_i, 24 | input [31:0] return_pc_i, 25 | input [31:0] alu_result_i, 26 | input [31:0] mem_rd_i, 27 | input [4:0] wr_i, 28 | input [1:0] wd_sel_i, 29 | input regfile_we_i, 30 | input [31:0] current_pc_i, 31 | output reg [31:0] current_pc_o, 32 | output reg [31:0] return_pc_o, 33 | output reg [31:0] alu_result_o, 34 | output reg [31:0] mem_rd_o, 35 | output reg [4:0] wr_o, 36 | output reg [1:0] wd_sel_o, 37 | output reg regfile_we_o 38 | ); 39 | always @(posedge clk_i or posedge rst_i) begin 40 | if(rst_i) 41 | return_pc_o <= 32'h0; 42 | else 43 | return_pc_o <= return_pc_i; 44 | end 45 | always @(posedge clk_i or posedge rst_i) begin 46 | if(rst_i) 47 | alu_result_o <= 32'h0; 48 | else 49 | alu_result_o <= alu_result_i; 50 | end 51 | always @(posedge clk_i or posedge rst_i) begin 52 | if(rst_i) 53 | mem_rd_o <= 32'h0; 54 | else 55 | mem_rd_o <= mem_rd_i; 56 | end 57 | always @(posedge clk_i or posedge rst_i) begin 58 | if(rst_i) 59 | wr_o <= 5'h0; 60 | else 61 | wr_o <= wr_i; 62 | end 63 | always @(posedge clk_i or posedge rst_i) begin 64 | if(rst_i) 65 | wd_sel_o <= 2'h0; 66 | else 67 | wd_sel_o <= wd_sel_i; 68 | end 69 | always @(posedge clk_i or posedge rst_i) begin 70 | if(rst_i) 71 | regfile_we_o <= 1'b0; 72 | else 73 | regfile_we_o <= regfile_we_i; 74 | end 75 | always @(posedge clk_i or posedge rst_i) begin 76 | if(rst_i) 77 | current_pc_o <= 32'h0; 78 | else 79 | current_pc_o <= current_pc_i; 80 | end 81 | endmodule 82 | -------------------------------------------------------------------------------- /pipeline/suspend/trace/shift_unit.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 15:41:40 7 | // Design Name: 8 | // Module Name: shift_unit 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // alu下的移位操作单元,通过桶形移位器实现 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module shift_unit #( 22 | parameter LEFT_SHIFT = 2'b00, 23 | parameter RIGHT_LOGIC_SHIFT = 2'b01, 24 | parameter RIGHT_ARITHMETIC_SHIFT = 2'b10, 25 | parameter UNKNOWN_OPCODE_RESULT = 32'h0 26 | ) 27 | ( 28 | input [31:0] op_a_i, 29 | input [31:0] op_b_i, // 实际只有低5位有效,高位是拓展而来 30 | input [1:0] opcode_i, 31 | output [31:0] result_o 32 | ); 33 | reg [31:0] tmp; 34 | always @(*) begin 35 | case(opcode_i) 36 | LEFT_SHIFT:begin 37 | tmp = (op_b_i[0]==1'b1)?{op_a_i[30:0], 1'b0} :op_a_i; 38 | tmp = (op_b_i[1]==1'b1)?{tmp[29:0], 2'b0} :tmp; 39 | tmp = (op_b_i[2]==1'b1)?{tmp[27:0], 4'b0} :tmp; 40 | tmp = (op_b_i[3]==1'b1)?{tmp[23:0], 8'b0} :tmp; 41 | tmp = (op_b_i[4]==1'b1)?{tmp[15:0], 16'b0} :tmp; 42 | end 43 | RIGHT_LOGIC_SHIFT:begin 44 | tmp = (op_b_i[0]==1'b1)?{1'b0, op_a_i[31:1]}:op_a_i; 45 | tmp = (op_b_i[1]==1'b1)?{2'b0, tmp[31:2]} :tmp; 46 | tmp = (op_b_i[2]==1'b1)?{4'b0, tmp[31:4]} :tmp; 47 | tmp = (op_b_i[3]==1'b1)?{8'b0, tmp[31:8]} :tmp; 48 | tmp = (op_b_i[4]==1'b1)?{16'b0, tmp[31:16]} :tmp; 49 | end 50 | RIGHT_ARITHMETIC_SHIFT: begin 51 | tmp = (op_b_i[0]==1'b1)?{{1{op_a_i[31]}}, op_a_i[31:1]}:op_a_i; 52 | tmp = (op_b_i[1]==1'b1)?{{2{op_a_i[31]}}, tmp[31:2]} :tmp; 53 | tmp = (op_b_i[2]==1'b1)?{{4{op_a_i[31]}}, tmp[31:4]} :tmp; 54 | tmp = (op_b_i[3]==1'b1)?{{8{op_a_i[31]}}, tmp[31:8]} :tmp; 55 | tmp = (op_b_i[4]==1'b1)?{{16{op_a_i[31]}}, tmp[31:16]} :tmp; 56 | end 57 | default: tmp = UNKNOWN_OPCODE_RESULT; 58 | endcase 59 | end 60 | assign result_o = tmp; 61 | endmodule 62 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | 哈尔滨工业大学(深圳)2021夏季学期计算机设计与实践课程代码。 2 | 3 | 课程要求设计基于MiniRV指令集的单周期CPU与流水线CPU,至少完成24条基础指令。流水线CPU还要处理数据冒险与控制冒险。 4 | 5 | 工程代码要求能够通过虚拟机当中的trace比对以及烧录到开发板上进行测试。 6 | 7 | 文件目录如下: 8 | ``` 9 | ├─pipeline 流水线CPU代码 10 | │ ├─forward 前递解决数据冒险代码 11 | │ │ ├─onBoard 开发板运行代码 12 | │ │ └─trace trace比对代码 13 | │ └─suspend 暂停解决数据冒险代码 14 | │ ├─onBoard 开发板运行代码 15 | │ └─trace trace比对代码 16 | └─single_cycle 单周期CPU代码 17 | ├─obBoard 开发板运行代码 18 | └─trace trace比对代码 19 | 20 | ``` 21 | -------------------------------------------------------------------------------- /single_cycle/obBoard/alu.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 15:34:04 7 | // Design Name: 8 | // Module Name: alu 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 集成算数单元,逻辑运算单元,比较单元,移位单元,以及专用于b型指令的运算单元 14 | // alu_opcode的【3:2】用于选择不同单元的输出结果作为最终输出 15 | // alu_opcode的【1:0】作为不同单元的操作码 16 | // alu_opcode【4】专门用于lui指令直接输出op_b 17 | // Dependencies: 18 | // arithmetic_unit, compare_unit,logic_unit,shift_unit,branch_unit 19 | // Revision: 20 | // Revision 0.01 - File Created 21 | // Additional Comments: 22 | // 23 | ////////////////////////////////////////////////////////////////////////////////// 24 | module alu #( 25 | parameter ARITHMETiC = 2'b00, 26 | parameter COMPARE = 2'b01, 27 | parameter LOGIC = 2'b10, 28 | parameter SHIFT = 2'b11 29 | ) 30 | ( 31 | input [4:0] alu_opcode_i, 32 | input [31:0] alu_op_a_i, 33 | input [31:0] alu_op_b_i, 34 | output reg [31:0] alu_result_o, 35 | output branch_o 36 | ); 37 | wire [31:0] result_arithmetic; 38 | wire [31:0] result_compare; 39 | wire [31:0] result_logic; 40 | wire [31:0] result_shift; 41 | // 算数运算单元 42 | arithmetic_unit u_arithmetic_unit( 43 | .op_a_i (alu_op_a_i), 44 | .op_b_i (alu_op_b_i), 45 | .opcode_i(alu_opcode_i[1:0]), 46 | .result_o(result_arithmetic) 47 | ); 48 | // 比较操作单元 49 | compare_unit u_compare_unit( 50 | .op_a_i (alu_op_a_i), 51 | .op_b_i (alu_op_b_i), 52 | .opcode_i(alu_opcode_i[1:0]), 53 | .result_o(result_compare) 54 | ); 55 | // 逻辑运算单元 56 | logic_unit u_logic_unit( 57 | .op_a_i (alu_op_a_i), 58 | .op_b_i (alu_op_b_i), 59 | .opcode_i(alu_opcode_i[1:0]), 60 | .result_o(result_logic) 61 | ); 62 | // 移位运算单元 63 | shift_unit u_shift_unit( 64 | .op_a_i (alu_op_a_i), 65 | .op_b_i (alu_op_b_i), 66 | .opcode_i(alu_opcode_i[1:0]), 67 | .result_o(result_shift) 68 | ); 69 | // B型指令专用branch分支运算单元 70 | branch_unit u_branch_unit( 71 | .op_a_i (alu_op_a_i), 72 | .op_b_i (alu_op_b_i), 73 | .opcode_i(alu_opcode_i[3:0]), 74 | .branch (branch_o) 75 | ); 76 | // 根据opcode选择输出哪个单元的结果 77 | always @(*) begin 78 | // lui指令 79 | if(alu_opcode_i[4]) 80 | alu_result_o = alu_op_b_i; 81 | else 82 | case(alu_opcode_i[3:2]) 83 | ARITHMETiC: alu_result_o = result_arithmetic; 84 | COMPARE: alu_result_o = result_compare; 85 | LOGIC: alu_result_o = result_logic; 86 | SHIFT: alu_result_o = result_shift; 87 | endcase 88 | end 89 | 90 | endmodule 91 | -------------------------------------------------------------------------------- /single_cycle/obBoard/aluop_selector.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 14:47:37 7 | // Design Name: 8 | // Module Name: aluop_selector 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 根据op_A_sel和op_B_sel选择送入alu的操作输 14 | // op_A:1'b0: 当前pc 15 | // 1'b1: rD1 16 | // op_B:1'b0: imm 17 | // 1'b1: rD2 18 | // Dependencies: 19 | // 20 | // Revision: 21 | // Revision 0.01 - File Created 22 | // Additional Comments: 23 | // 24 | ////////////////////////////////////////////////////////////////////////////////// 25 | module aluop_selector #( 26 | parameter CURRENTPC = 1'b0, 27 | parameter RD1 = 1'b1, 28 | parameter EXT = 1'b0, 29 | parameter RD2 = 1'b1 30 | ) 31 | ( 32 | input op_A_sel_i, 33 | input op_B_sel_i, 34 | input [31:0] current_pc_i, 35 | input [31:0] rD1_i, 36 | input [31:0] rD2_i, 37 | input [31:0] ext_i, 38 | output reg [31:0] alu_op_a_o, 39 | output reg [31:0] alu_op_b_o 40 | ); 41 | // alu_a选择 42 | always @(*) begin 43 | case(op_A_sel_i) 44 | CURRENTPC: alu_op_a_o = current_pc_i; 45 | RD1: alu_op_a_o = rD1_i; 46 | default: alu_op_a_o = 32'h0; 47 | endcase 48 | end 49 | // alu_b选择 50 | always @(*) begin 51 | case(op_B_sel_i) 52 | EXT: alu_op_b_o = ext_i; 53 | RD2: alu_op_b_o = rD2_i; 54 | default: alu_op_b_o = 32'h0; 55 | endcase 56 | end 57 | endmodule 58 | -------------------------------------------------------------------------------- /single_cycle/obBoard/arithmetic_unit.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 15:41:40 7 | // Design Name: 8 | // Module Name: arithmetic_unit 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 算数运算单元,根据传入的两个操作数和操作码进行算术运算 14 | // opcode:00:加法 15 | // 01:减法 16 | // Dependencies: 17 | // 18 | // Revision: 19 | // Revision 0.01 - File Created 20 | // Additional Comments: 21 | // 22 | ////////////////////////////////////////////////////////////////////////////////// 23 | module arithmetic_unit #( 24 | parameter PLUS = 2'b00, 25 | parameter SUB = 2'b01, 26 | parameter UNKNOWN_OPCODE_RESULT = 32'h0 27 | ) 28 | ( 29 | input [31:0] op_a_i, 30 | input [31:0] op_b_i, 31 | input [1:0] opcode_i, 32 | output reg [31:0] result_o 33 | ); 34 | always @(*) begin 35 | case(opcode_i) 36 | PLUS: result_o = op_a_i + op_b_i; 37 | SUB: result_o = op_a_i + (~op_b_i+1'b1); // 采用加补码的方式实现减法 38 | default: result_o = UNKNOWN_OPCODE_RESULT; 39 | endcase 40 | end 41 | endmodule 42 | -------------------------------------------------------------------------------- /single_cycle/obBoard/branch_unit.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 16:45:19 7 | // Design Name: 8 | // Module Name: branch_unit 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // B型指令专用branch运算单元 14 | // 15 | // Dependencies: 16 | // 17 | // Revision: 18 | // Revision 0.01 - File Created 19 | // Additional Comments: 20 | // 21 | ////////////////////////////////////////////////////////////////////////////////// 22 | module branch_unit#( 23 | parameter EQ = 4'h0, 24 | parameter NEQ = 4'h1, 25 | parameter UNSIGNED_LT = 4'h2, 26 | parameter SIGNED_LT = 4'h3, 27 | parameter UNSIGNED_GE = 4'h4, 28 | parameter SIGNED_GE = 4'h5, 29 | parameter SUCCESS = 1'b1, 30 | parameter UNSUCCESS = 1'b0, 31 | parameter UNKNOWN_OPCODE_RESULT = 1'b0 32 | ) 33 | ( 34 | input [31:0] op_a_i, 35 | input [31:0] op_b_i, 36 | input [3:0] opcode_i, 37 | output reg branch 38 | ); 39 | reg [31:0] tmp; 40 | always @(*) begin 41 | tmp = op_a_i - op_b_i; 42 | end 43 | always @(*) begin 44 | case(opcode_i) 45 | EQ: branch = (tmp == 32'h0)?SUCCESS:UNSUCCESS; 46 | NEQ: branch = (tmp == 32'h0)?UNSUCCESS:SUCCESS; 47 | UNSIGNED_LT: branch = (op_a_i < op_b_i)?SUCCESS:UNSUCCESS; 48 | SIGNED_LT: begin 49 | // 对符号不同的情况特殊处理,防止发生溢出 50 | if(op_a_i[31] ^ op_b_i[31]) 51 | branch = op_a_i[31]; 52 | else 53 | branch = (tmp[31] == 1'b1)?SUCCESS:UNSUCCESS; 54 | end 55 | UNSIGNED_GE: branch = (op_a_i < op_b_i)?UNSUCCESS:SUCCESS; 56 | SIGNED_GE: begin 57 | // 对符号不同的情况特殊处理,防止发生溢出 58 | if(op_a_i[31] ^ op_b_i[31]) 59 | branch = op_b_i[31]; 60 | else 61 | branch = (tmp[31] == 1'b1)?UNSUCCESS:SUCCESS; 62 | end 63 | default: branch = UNKNOWN_OPCODE_RESULT; 64 | endcase 65 | end 66 | endmodule 67 | -------------------------------------------------------------------------------- /single_cycle/obBoard/clock_divider.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/05/11 18:57:50 7 | // Design Name: 8 | // Module Name: time 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | // 分频器,将高频时钟信号转化为低频时钟信号用于驱动数码管 22 | // 输入:时钟信号clk 23 | // 输出:低频时钟信号out 24 | module clock_divider( 25 | input clk, 26 | output reg out 27 | ); 28 | reg [15:0] cnt = 0; 29 | reg tag = 1'b0; 30 | always @ (posedge clk) begin 31 | if(tag == 1'b0) begin 32 | out = 1'b0; 33 | tag = 1'b1; 34 | end 35 | else begin 36 | if(cnt == 16'b1010_0001_0010_0000) begin //27'b101_1111_0101_1110_0001_0000_0000 37 | out = ~out; 38 | cnt = 0; 39 | end 40 | else begin 41 | cnt = cnt+1'b1; 42 | end 43 | end 44 | end 45 | endmodule 46 | -------------------------------------------------------------------------------- /single_cycle/obBoard/compare_unit.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 15:41:40 7 | // Design Name: 8 | // Module Name: compare_unit 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 比较运算单元,用于R型与I型指令 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module compare_unit #( 22 | parameter SIGNED = 2'b00, 23 | parameter UNSIGNED = 2'b01, 24 | parameter OTHERS = 32'h0, 25 | parameter SIGNED_LT = 32'h1, 26 | parameter UNSIGNED_LT = 32'h2, 27 | parameter UNKNOWN_OPCODE_RESULT = 32'h0 28 | ) 29 | ( 30 | input [31:0] op_a_i, 31 | input [31:0] op_b_i, 32 | input [1:0] opcode_i, 33 | output reg [31:0] result_o 34 | ); 35 | reg [31:0] tmp; 36 | always@(*) begin 37 | case(opcode_i) 38 | SIGNED: begin 39 | tmp = op_a_i - op_b_i; 40 | // 不同号 41 | if(op_a_i[31]^op_b_i[31]) 42 | result_o = op_a_i[31]; 43 | else 44 | result_o = (tmp[31]==1'b1)?SIGNED_LT:OTHERS; 45 | end 46 | UNSIGNED: begin 47 | result_o = (op_a_i < op_b_i)?UNSIGNED_LT:OTHERS; 48 | end 49 | default: 50 | result_o = UNKNOWN_OPCODE_RESULT; 51 | endcase 52 | end 53 | endmodule 54 | -------------------------------------------------------------------------------- /single_cycle/obBoard/execute.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 17:22:25 7 | // Design Name: 8 | // Module Name: execute 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 执行模块,集成alu和alu的数据选择器 14 | // Dependencies: 15 | // aluop_selector, alu 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module execute( 22 | input op_A_sel_i, 23 | input op_B_sel_i, 24 | input [31:0] current_pc_i, 25 | input [31:0] rD1_i, 26 | input [31:0] rD2_i, 27 | input [31:0] ext_i, 28 | output [31:0] alu_result_o, 29 | input [4:0] alu_opcode_i, 30 | output alu_branch_o 31 | ); 32 | wire [31:0] alu_op_a; 33 | wire [31:0] alu_op_b; 34 | aluop_selector u_aluop_selector( 35 | .op_A_sel_i (op_A_sel_i), 36 | .op_B_sel_i (op_B_sel_i), 37 | .current_pc_i(current_pc_i), 38 | .rD1_i (rD1_i), 39 | .rD2_i (rD2_i), 40 | .ext_i (ext_i ), 41 | .alu_op_a_o (alu_op_a), 42 | .alu_op_b_o (alu_op_b) 43 | ); 44 | alu u_alu( 45 | .alu_opcode_i (alu_opcode_i), 46 | .alu_op_a_i (alu_op_a), 47 | .alu_op_b_i (alu_op_b), 48 | .alu_result_o (alu_result_o), 49 | .branch_o (alu_branch_o) 50 | ); 51 | endmodule 52 | -------------------------------------------------------------------------------- /single_cycle/obBoard/imm_gen.v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yikai-coder/HITsz_CPU_design/c1d6cea65b82fd382c3bf34725d2e8ccb11a9936/single_cycle/obBoard/imm_gen.v -------------------------------------------------------------------------------- /single_cycle/obBoard/instruction_decoder.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/01 17:00:09 7 | // Design Name: 8 | // Module Name: imm_gen 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 译码模块,集成寄存器堆和立即数生成模块 14 | // Dependencies: 15 | // reg_file,imm_gen 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module instruction_decoder #( 22 | parameter RETURN_PC = 2'b00, 23 | parameter ALU_RESULT = 2'b01, 24 | parameter MEM_DATA = 2'b10 25 | ) 26 | ( 27 | input reset_i, 28 | input [31:0] return_pc_i, 29 | input [31:0] ALU_result_i, 30 | input [31:0] mem_data_i, 31 | input [1:0] wd_sel_i, 32 | input we_i, 33 | input clk_i, 34 | input [31:0] inst_i, 35 | input [2:0] imm_sel_i, 36 | output [31:0] ext_o, 37 | output [31:0] rD1_o, 38 | output [31:0] rD2_o, 39 | // output we_o, // test 40 | // output [31:0] wD_o, 41 | // output [4:0] wR_o, 42 | output [31:0] rD19_o 43 | // output reg write_back // 写回阶段信号 44 | ); 45 | reg [31:0] wD; 46 | reg [4:0] wr; 47 | // 根据wd_sel选择写入数据 48 | // 写入寄存器恒为inst[11:7] 49 | always @(*) begin 50 | case(wd_sel_i) 51 | RETURN_PC: begin 52 | wr = inst_i[11:7]; 53 | wD = return_pc_i; 54 | end 55 | ALU_RESULT: begin 56 | wr = inst_i[11:7]; 57 | wD = ALU_result_i; 58 | end 59 | MEM_DATA: begin 60 | wD = mem_data_i; 61 | wr = inst_i[11:7]; 62 | end 63 | default: begin 64 | wD = 32'h0; 65 | wr = 32'h0; 66 | end 67 | endcase 68 | 69 | end 70 | reg_file u_reg_file( 71 | .clk_i (clk_i), 72 | .reset_i (reset_i), 73 | .rR1_i (inst_i[19:15]), 74 | .rR2_i (inst_i[24:20]), 75 | .wR_i (wr), 76 | .wD_i (wD), 77 | .WE_i (we_i), 78 | .rD1_o (rD1_o), 79 | .rD2_o (rD2_o), 80 | .rD19_o (rD19_o) 81 | ); 82 | assign we_o = we_i; 83 | assign wD_o = wD; 84 | assign wR_o = wr; 85 | 86 | imm_gen u_imm_gen( 87 | .reset_i (reset_i), 88 | .inst_i (inst_i), 89 | .imm_sel_i (imm_sel_i), 90 | .ext_o (ext_o) 91 | ); 92 | endmodule 93 | -------------------------------------------------------------------------------- /single_cycle/obBoard/instruction_fetch.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/01 15:31:29 7 | // Design Name: 8 | // Module Name: instruction_fetch 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 取指模块 14 | // 包含pc,npc,irom三个子模块 15 | // Dependencies: 16 | // 17 | // Revision: 18 | // Revision 0.01 - File Created 19 | // Additional Comments: 20 | // 21 | ////////////////////////////////////////////////////////////////////////////////// 22 | module instruction_fetch( 23 | input clk_i, 24 | input reset_i, 25 | input [1:0] pc_sel_i, 26 | input [31:0] offset_i, 27 | input [31:0] rD1_i, 28 | input branch_i, 29 | output [31:0] inst_o, 30 | output [31:0] return_pc_o, 31 | output [31:0] current_pc_o, // 用于auipc 32 | output [31:0] pc_o 33 | ); 34 | wire [31:0] npc; 35 | wire [31:0] pc; 36 | assign pc_o = pc; 37 | assign current_pc_o = pc; 38 | pc u_pc( 39 | .npc_i (npc), 40 | .clk_i (clk_i), 41 | .reset_i(reset_i), 42 | .pc_o (pc) 43 | ); 44 | npc u_npc( 45 | .reset_i (reset_i), 46 | .pc_sel_i (pc_sel_i), 47 | .pc_i (pc), 48 | .offset_i (offset_i), 49 | .rD1_i (rD1_i), 50 | .branch_i (branch_i), 51 | .next_pc_o (npc), 52 | .pc_plus_4_o(return_pc_o) 53 | ); 54 | irom u_irom( 55 | .pc_i (pc), 56 | .inst_o(inst_o) 57 | ); 58 | endmodule 59 | -------------------------------------------------------------------------------- /single_cycle/obBoard/irom.v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yikai-coder/HITsz_CPU_design/c1d6cea65b82fd382c3bf34725d2e8ccb11a9936/single_cycle/obBoard/irom.v -------------------------------------------------------------------------------- /single_cycle/obBoard/logic_unit.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 15:41:40 7 | // Design Name: 8 | // Module Name: logic_unit 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // alu下的逻辑运算单元 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module logic_unit #( 22 | parameter AND = 2'b00, 23 | parameter OR = 2'b01, 24 | parameter XOR = 2'b10, 25 | parameter UNKNOWN_OPCODE_RESULT = 32'h0 26 | ) 27 | ( 28 | input [31:0] op_a_i, 29 | input [31:0] op_b_i, 30 | input [1:0] opcode_i, 31 | output reg [31:0] result_o 32 | ); 33 | always @(*) begin 34 | case(opcode_i) 35 | AND: result_o = op_a_i & op_b_i; 36 | OR: result_o = op_a_i | op_b_i; 37 | XOR: result_o = op_a_i ^ op_b_i; 38 | default: result_o = UNKNOWN_OPCODE_RESULT; 39 | endcase 40 | end 41 | endmodule 42 | -------------------------------------------------------------------------------- /single_cycle/obBoard/my_cpu.v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yikai-coder/HITsz_CPU_design/c1d6cea65b82fd382c3bf34725d2e8ccb11a9936/single_cycle/obBoard/my_cpu.v -------------------------------------------------------------------------------- /single_cycle/obBoard/npc.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/01 14:28:45 7 | // Design Name: 8 | // Module Name: npc 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // npc数据处理,根据pc_sel输出不同指令对应的下一周期pc信号 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module npc #( 22 | parameter INTERPRETER_NPC = 32'b0 // 对应pc_sel信号异常,转入中断处理 23 | ) 24 | ( 25 | input reset_i, 26 | input [1:0] pc_sel_i, 27 | input [31:0] pc_i, 28 | input [31:0] offset_i, 29 | input [31:0] rD1_i, 30 | input branch_i, 31 | output reg [31:0] next_pc_o, 32 | output [31:0] pc_plus_4_o // 用于jal指令与jalr指令 33 | ); 34 | always @(*) begin 35 | if(reset_i == 1'b1) 36 | next_pc_o = pc_i; 37 | else begin 38 | case (pc_sel_i) 39 | 2'b00: next_pc_o = pc_i + 3'b100; // pc+4 40 | 2'b01: next_pc_o = (branch_i==1'b1)?pc_i+offset_i:pc_i+3'b100; //Branch 41 | 2'b10: next_pc_o = pc_i+offset_i; // jal 42 | 2'b11: next_pc_o = (rD1_i+offset_i)&(~1); // jalr 43 | default: 44 | next_pc_o = INTERPRETER_NPC; 45 | endcase 46 | end 47 | end 48 | assign pc_plus_4_o = pc_i+3'b100; 49 | endmodule 50 | -------------------------------------------------------------------------------- /single_cycle/obBoard/pc.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/01 14:22:58 7 | // Design Name: 8 | // Module Name: pc 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // PC寄存器,在每个时钟上升沿将前一个周期送入的npc输出 14 | // 在复位信号送来时输出复位后首条指令的PC值 15 | // Dependencies: 16 | // 17 | // Revision: 18 | // Revision 0.01 - File Created 19 | // Additional Comments: 20 | // 21 | ////////////////////////////////////////////////////////////////////////////////// 22 | module pc#( 23 | parameter INIT_PC = 32'b0 // 假设0为CPU复位后的首条指令对应地址 24 | ) 25 | ( 26 | input [31:0] npc_i, 27 | input clk_i, 28 | input reset_i, 29 | output reg [31:0] pc_o 30 | ); 31 | reg first_time; // 用于防止reset失效的当个周期时间不够无法完成一条指令,将第一条指令的执行时间推迟到下一次时钟上升沿到来 32 | always @(posedge clk_i or posedge reset_i) begin 33 | if(reset_i) begin 34 | pc_o <= INIT_PC; 35 | first_time <= 1'b0; 36 | end 37 | else begin 38 | first_time <= 1'b1; 39 | if(first_time == 1'b0) 40 | pc_o <= INIT_PC; 41 | else 42 | pc_o <= npc_i; 43 | end 44 | end 45 | endmodule 46 | -------------------------------------------------------------------------------- /single_cycle/obBoard/reg_file_8.v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yikai-coder/HITsz_CPU_design/c1d6cea65b82fd382c3bf34725d2e8ccb11a9936/single_cycle/obBoard/reg_file_8.v -------------------------------------------------------------------------------- /single_cycle/obBoard/shift_unit.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 15:41:40 7 | // Design Name: 8 | // Module Name: shift_unit 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // alu下的移位操作单元,通过桶形移位器实现 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module shift_unit #( 22 | parameter LEFT_SHIFT = 2'b00, 23 | parameter RIGHT_LOGIC_SHIFT = 2'b01, 24 | parameter RIGHT_ARITHMETIC_SHIFT = 2'b10, 25 | parameter UNKNOWN_OPCODE_RESULT = 32'h0 26 | ) 27 | ( 28 | input [31:0] op_a_i, 29 | input [31:0] op_b_i, // 实际只有低5位有效,高位是拓展而来 30 | input [1:0] opcode_i, 31 | output [31:0] result_o 32 | ); 33 | reg [31:0] tmp; 34 | always @(*) begin 35 | case(opcode_i) 36 | LEFT_SHIFT:begin 37 | tmp = (op_b_i[0]==1'b1)?{op_a_i[30:0], 1'b0} :op_a_i; 38 | tmp = (op_b_i[1]==1'b1)?{tmp[29:0], 2'b0} :tmp; 39 | tmp = (op_b_i[2]==1'b1)?{tmp[27:0], 4'b0} :tmp; 40 | tmp = (op_b_i[3]==1'b1)?{tmp[23:0], 8'b0} :tmp; 41 | tmp = (op_b_i[4]==1'b1)?{tmp[15:0], 16'b0} :tmp; 42 | end 43 | RIGHT_LOGIC_SHIFT:begin 44 | tmp = (op_b_i[0]==1'b1)?{1'b0, op_a_i[31:1]}:op_a_i; 45 | tmp = (op_b_i[1]==1'b1)?{2'b0, tmp[31:2]} :tmp; 46 | tmp = (op_b_i[2]==1'b1)?{4'b0, tmp[31:4]} :tmp; 47 | tmp = (op_b_i[3]==1'b1)?{8'b0, tmp[31:8]} :tmp; 48 | tmp = (op_b_i[4]==1'b1)?{16'b0, tmp[31:16]} :tmp; 49 | end 50 | RIGHT_ARITHMETIC_SHIFT: begin 51 | tmp = (op_b_i[0]==1'b1)?{{1{op_a_i[31]}}, op_a_i[31:1]}:op_a_i; 52 | tmp = (op_b_i[1]==1'b1)?{{2{op_a_i[31]}}, tmp[31:2]} :tmp; 53 | tmp = (op_b_i[2]==1'b1)?{{4{op_a_i[31]}}, tmp[31:4]} :tmp; 54 | tmp = (op_b_i[3]==1'b1)?{{8{op_a_i[31]}}, tmp[31:8]} :tmp; 55 | tmp = (op_b_i[4]==1'b1)?{{16{op_a_i[31]}}, tmp[31:16]} :tmp; 56 | end 57 | default: tmp = UNKNOWN_OPCODE_RESULT; 58 | endcase 59 | end 60 | assign result_o = tmp; 61 | endmodule 62 | -------------------------------------------------------------------------------- /single_cycle/obBoard/top.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/08 14:10:06 7 | // Design Name: 8 | // Module Name: top 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | 22 | 23 | module top( 24 | input clk_i, 25 | input rst_i, 26 | output wire led0_en, 27 | output wire led1_en, 28 | output wire led2_en, 29 | output wire led3_en, 30 | output wire led4_en, 31 | output wire led5_en, 32 | output wire led6_en, 33 | output wire led7_en, 34 | output wire led_ca , 35 | output wire led_cb , 36 | output wire led_cc , 37 | output wire led_cd , 38 | output wire led_ce , 39 | output wire led_cf , 40 | output wire led_cg , 41 | output wire led_dp 42 | ); 43 | wire [31:0] rD19; 44 | wire clk_display; 45 | wire rst_n = ~rst_i; 46 | my_cpu u_my_cpu( 47 | .sysclk_i(clk_i), 48 | .reset_i (rst_i), 49 | .rD19_o (rD19) 50 | ); 51 | clock_divider u_clock_divider( 52 | .clk(clk_i), 53 | .out(clk_display) 54 | ); 55 | display u_display( 56 | .clk (clk_display), 57 | .rst_n(rst_n), 58 | .busy (1'b0), 59 | .z1 (rD19[31:24]), 60 | .r1 (rD19[23:16]), 61 | .z2 (rD19[15:8]), 62 | .r2 (rD19[7:0]), 63 | .led0_en(led0_en), 64 | .led1_en(led1_en), 65 | .led2_en(led2_en), 66 | .led3_en(led3_en), 67 | .led4_en(led4_en), 68 | .led5_en(led5_en), 69 | .led6_en(led6_en), 70 | .led7_en(led7_en), 71 | .led_ca (led_ca), 72 | .led_cb (led_cb), 73 | .led_cc (led_cc), 74 | .led_cd (led_cd), 75 | .led_ce (led_ce), 76 | .led_cf (led_cf), 77 | .led_cg (led_cg), 78 | .led_dp (led_dp) 79 | ); 80 | 81 | endmodule 82 | -------------------------------------------------------------------------------- /single_cycle/trace/alu.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 15:34:04 7 | // Design Name: 8 | // Module Name: alu 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 集成算数单元,逻辑运算单元,比较单元,移位单元,以及专用于b型指令的运算单元 14 | // alu_opcode的【3:2】用于选择不同单元的输出结果作为最终输出 15 | // alu_opcode的【1:0】作为不同单元的操作码 16 | // alu_opcode【4】专门用于lui指令直接输出op_b 17 | // Dependencies: 18 | // arithmetic_unit, compare_unit,logic_unit,shift_unit,branch_unit 19 | // Revision: 20 | // Revision 0.01 - File Created 21 | // Additional Comments: 22 | // 23 | ////////////////////////////////////////////////////////////////////////////////// 24 | module alu #( 25 | parameter ARITHMETiC = 2'b00, 26 | parameter COMPARE = 2'b01, 27 | parameter LOGIC = 2'b10, 28 | parameter SHIFT = 2'b11 29 | ) 30 | ( 31 | input [4:0] alu_opcode_i, 32 | input [31:0] alu_op_a_i, 33 | input [31:0] alu_op_b_i, 34 | output reg [31:0] alu_result_o, 35 | output branch_o 36 | ); 37 | wire [31:0] result_arithmetic; 38 | wire [31:0] result_compare; 39 | wire [31:0] result_logic; 40 | wire [31:0] result_shift; 41 | // 算数运算单元 42 | arithmetic_unit u_arithmetic_unit( 43 | .op_a_i (alu_op_a_i), 44 | .op_b_i (alu_op_b_i), 45 | .opcode_i(alu_opcode_i[1:0]), 46 | .result_o(result_arithmetic) 47 | ); 48 | // 比较操作单元 49 | compare_unit u_compare_unit( 50 | .op_a_i (alu_op_a_i), 51 | .op_b_i (alu_op_b_i), 52 | .opcode_i(alu_opcode_i[1:0]), 53 | .result_o(result_compare) 54 | ); 55 | // 逻辑运算单元 56 | logic_unit u_logic_unit( 57 | .op_a_i (alu_op_a_i), 58 | .op_b_i (alu_op_b_i), 59 | .opcode_i(alu_opcode_i[1:0]), 60 | .result_o(result_logic) 61 | ); 62 | // 移位运算单元 63 | shift_unit u_shift_unit( 64 | .op_a_i (alu_op_a_i), 65 | .op_b_i (alu_op_b_i), 66 | .opcode_i(alu_opcode_i[1:0]), 67 | .result_o(result_shift) 68 | ); 69 | // B型指令专用branch分支运算单元 70 | branch_unit u_branch_unit( 71 | .op_a_i (alu_op_a_i), 72 | .op_b_i (alu_op_b_i), 73 | .opcode_i(alu_opcode_i[3:0]), 74 | .branch (branch_o) 75 | ); 76 | // 根据opcode选择输出哪个单元的结果 77 | always @(*) begin 78 | // lui指令 79 | if(alu_opcode_i[4]) 80 | alu_result_o = alu_op_b_i; 81 | else 82 | case(alu_opcode_i[3:2]) 83 | ARITHMETiC: alu_result_o = result_arithmetic; 84 | COMPARE: alu_result_o = result_compare; 85 | LOGIC: alu_result_o = result_logic; 86 | SHIFT: alu_result_o = result_shift; 87 | endcase 88 | end 89 | 90 | endmodule 91 | -------------------------------------------------------------------------------- /single_cycle/trace/aluop_selector.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 14:47:37 7 | // Design Name: 8 | // Module Name: aluop_selector 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 根据op_A_sel和op_B_sel选择送入alu的操作输 14 | // op_A:1'b0: 当前pc 15 | // 1'b1: rD1 16 | // op_B:1'b0: imm 17 | // 1'b1: rD2 18 | // Dependencies: 19 | // 20 | // Revision: 21 | // Revision 0.01 - File Created 22 | // Additional Comments: 23 | // 24 | ////////////////////////////////////////////////////////////////////////////////// 25 | module aluop_selector #( 26 | parameter CURRENTPC = 1'b0, 27 | parameter RD1 = 1'b1, 28 | parameter EXT = 1'b0, 29 | parameter RD2 = 1'b1 30 | ) 31 | ( 32 | input op_A_sel_i, 33 | input op_B_sel_i, 34 | input [31:0] current_pc_i, 35 | input [31:0] rD1_i, 36 | input [31:0] rD2_i, 37 | input [31:0] ext_i, 38 | output reg [31:0] alu_op_a_o, 39 | output reg [31:0] alu_op_b_o 40 | ); 41 | // alu_a选择 42 | always @(*) begin 43 | case(op_A_sel_i) 44 | CURRENTPC: alu_op_a_o = current_pc_i; 45 | RD1: alu_op_a_o = rD1_i; 46 | default: alu_op_a_o = 32'h0; 47 | endcase 48 | end 49 | // alu_b选择 50 | always @(*) begin 51 | case(op_B_sel_i) 52 | EXT: alu_op_b_o = ext_i; 53 | RD2: alu_op_b_o = rD2_i; 54 | default: alu_op_b_o = 32'h0; 55 | endcase 56 | end 57 | endmodule 58 | -------------------------------------------------------------------------------- /single_cycle/trace/arithmetic_unit.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 15:41:40 7 | // Design Name: 8 | // Module Name: arithmetic_unit 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 算数运算单元,根据传入的两个操作数和操作码进行算术运算 14 | // opcode:00:加法 15 | // 01:减法 16 | // Dependencies: 17 | // 18 | // Revision: 19 | // Revision 0.01 - File Created 20 | // Additional Comments: 21 | // 22 | ////////////////////////////////////////////////////////////////////////////////// 23 | module arithmetic_unit #( 24 | parameter PLUS = 2'b00, 25 | parameter SUB = 2'b01, 26 | parameter UNKNOWN_OPCODE_RESULT = 32'h0 27 | ) 28 | ( 29 | input [31:0] op_a_i, 30 | input [31:0] op_b_i, 31 | input [1:0] opcode_i, 32 | output reg [31:0] result_o 33 | ); 34 | always @(*) begin 35 | case(opcode_i) 36 | PLUS: result_o = op_a_i + op_b_i; 37 | SUB: result_o = op_a_i + (~op_b_i+1'b1); // 采用加补码的方式实现减法 38 | default: result_o = UNKNOWN_OPCODE_RESULT; 39 | endcase 40 | end 41 | endmodule 42 | -------------------------------------------------------------------------------- /single_cycle/trace/branch_unit.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 16:45:19 7 | // Design Name: 8 | // Module Name: branch_unit 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // B型指令专用branch运算单元 14 | // 15 | // Dependencies: 16 | // 17 | // Revision: 18 | // Revision 0.01 - File Created 19 | // Additional Comments: 20 | // 21 | ////////////////////////////////////////////////////////////////////////////////// 22 | module branch_unit#( 23 | parameter EQ = 4'h0, 24 | parameter NEQ = 4'h1, 25 | parameter UNSIGNED_LT = 4'h2, 26 | parameter SIGNED_LT = 4'h3, 27 | parameter UNSIGNED_GE = 4'h4, 28 | parameter SIGNED_GE = 4'h5, 29 | parameter SUCCESS = 1'b1, 30 | parameter UNSUCCESS = 1'b0, 31 | parameter UNKNOWN_OPCODE_RESULT = 1'b0 32 | ) 33 | ( 34 | input [31:0] op_a_i, 35 | input [31:0] op_b_i, 36 | input [3:0] opcode_i, 37 | output reg branch 38 | ); 39 | reg [31:0] tmp; 40 | always @(*) begin 41 | tmp = op_a_i - op_b_i; 42 | end 43 | always @(*) begin 44 | case(opcode_i) 45 | EQ: branch = (tmp == 32'h0)?SUCCESS:UNSUCCESS; 46 | NEQ: branch = (tmp == 32'h0)?UNSUCCESS:SUCCESS; 47 | UNSIGNED_LT: branch = (op_a_i < op_b_i)?SUCCESS:UNSUCCESS; 48 | SIGNED_LT: begin 49 | // 对符号不同的情况特殊处理,防止发生溢出 50 | if(op_a_i[31] ^ op_b_i[31]) 51 | branch = op_a_i[31]; 52 | else 53 | branch = (tmp[31] == 1'b1)?SUCCESS:UNSUCCESS; 54 | end 55 | UNSIGNED_GE: branch = (op_a_i < op_b_i)?UNSUCCESS:SUCCESS; 56 | SIGNED_GE: begin 57 | // 对符号不同的情况特殊处理,防止发生溢出 58 | if(op_a_i[31] ^ op_b_i[31]) 59 | branch = op_b_i[31]; 60 | else 61 | branch = (tmp[31] == 1'b1)?UNSUCCESS:SUCCESS; 62 | end 63 | default: branch = UNKNOWN_OPCODE_RESULT; 64 | endcase 65 | end 66 | endmodule 67 | -------------------------------------------------------------------------------- /single_cycle/trace/compare_unit.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 15:41:40 7 | // Design Name: 8 | // Module Name: compare_unit 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 比较运算单元,用于R型与I型指令 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module compare_unit #( 22 | parameter SIGNED = 2'b00, 23 | parameter UNSIGNED = 2'b01, 24 | parameter OTHERS = 32'h0, 25 | parameter SIGNED_LT = 32'h1, 26 | parameter UNSIGNED_LT = 32'h1, 27 | parameter UNKNOWN_OPCODE_RESULT = 32'h0 28 | ) 29 | ( 30 | input [31:0] op_a_i, 31 | input [31:0] op_b_i, 32 | input [1:0] opcode_i, 33 | output reg [31:0] result_o 34 | ); 35 | reg [31:0] tmp; 36 | always@(*) begin 37 | case(opcode_i) 38 | SIGNED: begin 39 | tmp = op_a_i - op_b_i; 40 | // 不同号 41 | if(op_a_i[31]^op_b_i[31]) 42 | result_o = op_a_i[31]; 43 | else 44 | result_o = (tmp[31]==1'b1)?SIGNED_LT:OTHERS; 45 | end 46 | UNSIGNED: begin 47 | result_o = (op_a_i < op_b_i)?UNSIGNED_LT:OTHERS; 48 | end 49 | default: 50 | result_o = UNKNOWN_OPCODE_RESULT; 51 | endcase 52 | end 53 | endmodule 54 | -------------------------------------------------------------------------------- /single_cycle/trace/execute.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 17:22:25 7 | // Design Name: 8 | // Module Name: execute 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 执行模块,集成alu和alu的数据选择器 14 | // Dependencies: 15 | // aluop_selector, alu 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module execute( 22 | input op_A_sel_i, 23 | input op_B_sel_i, 24 | input [31:0] current_pc_i, 25 | input [31:0] rD1_i, 26 | input [31:0] rD2_i, 27 | input [31:0] ext_i, 28 | output [31:0] alu_result_o, 29 | input [4:0] alu_opcode_i, 30 | output alu_branch_o 31 | ); 32 | wire [31:0] alu_op_a; 33 | wire [31:0] alu_op_b; 34 | aluop_selector u_aluop_selector( 35 | .op_A_sel_i (op_A_sel_i), 36 | .op_B_sel_i (op_B_sel_i), 37 | .current_pc_i(current_pc_i), 38 | .rD1_i (rD1_i), 39 | .rD2_i (rD2_i), 40 | .ext_i (ext_i ), 41 | .alu_op_a_o (alu_op_a), 42 | .alu_op_b_o (alu_op_b) 43 | ); 44 | alu u_alu( 45 | .alu_opcode_i (alu_opcode_i), 46 | .alu_op_a_i (alu_op_a), 47 | .alu_op_b_i (alu_op_b), 48 | .alu_result_o (alu_result_o), 49 | .branch_o (alu_branch_o) 50 | ); 51 | endmodule 52 | -------------------------------------------------------------------------------- /single_cycle/trace/imm_gen.v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Yikai-coder/HITsz_CPU_design/c1d6cea65b82fd382c3bf34725d2e8ccb11a9936/single_cycle/trace/imm_gen.v -------------------------------------------------------------------------------- /single_cycle/trace/instruction_decoder.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/01 17:00:09 7 | // Design Name: 8 | // Module Name: imm_gen 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 译码模块,集成寄存器堆和立即数生成模块 14 | // Dependencies: 15 | // reg_file,imm_gen 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module instruction_decoder #( 22 | parameter RETURN_PC = 2'b00, 23 | parameter ALU_RESULT = 2'b01, 24 | parameter MEM_DATA = 2'b10 25 | ) 26 | ( 27 | input reset_i, 28 | input [31:0] return_pc_i, 29 | input [31:0] ALU_result_i, 30 | input [31:0] mem_data_i, 31 | input [1:0] wd_sel_i, 32 | input we_i, 33 | input clk_i, 34 | input [31:0] inst_i, 35 | input [2:0] imm_sel_i, 36 | output [31:0] ext_o, 37 | output [31:0] rD1_o, 38 | output [31:0] rD2_o, 39 | output we_o, // test 40 | output [31:0] wD_o, 41 | output [4:0] wR_o 42 | // output reg write_back // 写回阶段信号 43 | ); 44 | reg [31:0] wD; 45 | reg [4:0] wr; 46 | // 根据wd_sel选择写入数据 47 | // 写入寄存器恒为inst[11:7] 48 | always @(*) begin 49 | case(wd_sel_i) 50 | RETURN_PC: begin 51 | wr = inst_i[11:7]; 52 | wD = return_pc_i; 53 | end 54 | ALU_RESULT: begin 55 | wr = inst_i[11:7]; 56 | wD = ALU_result_i; 57 | end 58 | MEM_DATA: begin 59 | wD = mem_data_i; 60 | wr = inst_i[11:7]; 61 | end 62 | default: begin 63 | wD = 32'h0; 64 | wr = 32'h0; 65 | end 66 | endcase 67 | 68 | end 69 | reg_file u_reg_file( 70 | .clk_i (clk_i), 71 | .reset_i (reset_i), 72 | .rR1_i (inst_i[19:15]), 73 | .rR2_i (inst_i[24:20]), 74 | .wR_i (wr), 75 | .wD_i (wD), 76 | .WE_i (we_i), 77 | .rD1_o (rD1_o), 78 | .rD2_o (rD2_o) 79 | ); 80 | assign we_o = we_i; 81 | assign wD_o = wD; 82 | assign wR_o = wr; 83 | 84 | imm_gen u_imm_gen( 85 | .reset_i (reset_i), 86 | .inst_i (inst_i), 87 | .imm_sel_i (imm_sel_i), 88 | .ext_o (ext_o) 89 | ); 90 | endmodule 91 | -------------------------------------------------------------------------------- /single_cycle/trace/instruction_fetch.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/01 15:31:29 7 | // Design Name: 8 | // Module Name: instruction_fetch 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 取指模块 14 | // 包含pc,npc,irom三个子模块 15 | // Dependencies: 16 | // 17 | // Revision: 18 | // Revision 0.01 - File Created 19 | // Additional Comments: 20 | // 21 | ////////////////////////////////////////////////////////////////////////////////// 22 | module instruction_fetch( 23 | input clk_i, 24 | input reset_i, 25 | input [1:0] pc_sel_i, 26 | input [31:0] offset_i, 27 | input [31:0] rD1_i, 28 | input branch_i, 29 | output [31:0] inst_o, 30 | output [31:0] return_pc_o, 31 | output [31:0] current_pc_o, // 用于auipc 32 | output [31:0] pc_o 33 | ); 34 | wire [31:0] npc; 35 | wire [31:0] pc; 36 | assign pc_o = pc; 37 | assign current_pc_o = pc; 38 | pc u_pc( 39 | .npc_i (npc), 40 | .clk_i (clk_i), 41 | .reset_i(reset_i), 42 | .pc_o (pc) 43 | ); 44 | npc u_npc( 45 | .reset_i (reset_i), 46 | .pc_sel_i (pc_sel_i), 47 | .pc_i (pc), 48 | .offset_i (offset_i), 49 | .rD1_i (rD1_i), 50 | .branch_i (branch_i), 51 | .next_pc_o (npc), 52 | .pc_plus_4_o(return_pc_o) 53 | ); 54 | // irom u_irom( 55 | // .pc_i (pc), 56 | // .inst_o(inst_o) 57 | // ); 58 | endmodule 59 | -------------------------------------------------------------------------------- /single_cycle/trace/irom.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/01 15:21:18 7 | // Design Name: 8 | // Module Name: irom 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // irom模块,用于调用IP核 14 | // Dependencies: 15 | // prgrom 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module irom( 22 | input [31:0] pc_i, 23 | output [31:0] inst_o 24 | ); 25 | prgrom U0_irom( 26 | .a (pc_i[15:2]), 27 | .spo (inst_o) 28 | ); 29 | endmodule 30 | -------------------------------------------------------------------------------- /single_cycle/trace/logic_unit.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 15:41:40 7 | // Design Name: 8 | // Module Name: logic_unit 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // alu下的逻辑运算单元 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module logic_unit #( 22 | parameter AND = 2'b00, 23 | parameter OR = 2'b01, 24 | parameter XOR = 2'b10, 25 | parameter UNKNOWN_OPCODE_RESULT = 32'h0 26 | ) 27 | ( 28 | input [31:0] op_a_i, 29 | input [31:0] op_b_i, 30 | input [1:0] opcode_i, 31 | output reg [31:0] result_o 32 | ); 33 | always @(*) begin 34 | case(opcode_i) 35 | AND: result_o = op_a_i & op_b_i; 36 | OR: result_o = op_a_i | op_b_i; 37 | XOR: result_o = op_a_i ^ op_b_i; 38 | default: result_o = UNKNOWN_OPCODE_RESULT; 39 | endcase 40 | end 41 | endmodule 42 | -------------------------------------------------------------------------------- /single_cycle/trace/npc.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/01 14:28:45 7 | // Design Name: 8 | // Module Name: npc 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // npc数据处理,根据pc_sel输出不同指令对应的下一周期pc信号 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module npc #( 22 | parameter INTERPRETER_NPC = 32'b0 // 对应pc_sel信号异常,转入中断处理 23 | ) 24 | ( 25 | input reset_i, 26 | input [1:0] pc_sel_i, 27 | input [31:0] pc_i, 28 | input [31:0] offset_i, 29 | input [31:0] rD1_i, 30 | input branch_i, 31 | output reg [31:0] next_pc_o, 32 | output [31:0] pc_plus_4_o // 用于jal指令与jalr指令 33 | ); 34 | always @(*) begin 35 | if(reset_i == 1'b1) 36 | next_pc_o = pc_i; 37 | else begin 38 | case (pc_sel_i) 39 | 2'b00: next_pc_o = pc_i + 3'b100; // pc+4 40 | 2'b01: next_pc_o = (branch_i==1'b1)?pc_i+offset_i:pc_i+3'b100; //Branch 41 | 2'b10: next_pc_o = pc_i+offset_i; // jal 42 | 2'b11: next_pc_o = (rD1_i+offset_i)&(~1); // jalr 43 | default: 44 | next_pc_o = INTERPRETER_NPC; 45 | endcase 46 | end 47 | end 48 | assign pc_plus_4_o = pc_i+3'b100; 49 | endmodule 50 | -------------------------------------------------------------------------------- /single_cycle/trace/pc.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/01 14:22:58 7 | // Design Name: 8 | // Module Name: pc 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // PC寄存器,在每个时钟上升沿将前一个周期送入的npc输出 14 | // 在复位信号送来时输出复位后首条指令的PC值 15 | // Dependencies: 16 | // 17 | // Revision: 18 | // Revision 0.01 - File Created 19 | // Additional Comments: 20 | // 21 | ////////////////////////////////////////////////////////////////////////////////// 22 | module pc#( 23 | parameter INIT_PC = 32'b0 // 假设0为CPU复位后的首条指令对应地址 24 | ) 25 | ( 26 | input [31:0] npc_i, 27 | input clk_i, 28 | input reset_i, 29 | output reg [31:0] pc_o 30 | ); 31 | reg first_time; // 用于防止reset失效的当个周期时间不够无法完成一条指令,将第一条指令的执行时间推迟到下一次时钟上升沿到来 32 | always @(posedge clk_i or posedge reset_i) begin 33 | if(reset_i) begin 34 | pc_o <= INIT_PC; 35 | first_time <= 1'b0; 36 | end 37 | else begin 38 | first_time <= 1'b1; 39 | if(first_time == 1'b0) 40 | pc_o <= INIT_PC; 41 | else 42 | pc_o <= npc_i; 43 | end 44 | end 45 | endmodule 46 | -------------------------------------------------------------------------------- /single_cycle/trace/reg_file_8.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/01 14:22:58 7 | // Design Name: 8 | // Module Name: pc 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // 寄存器堆模块的子模块,每个模块存储8个寄存器 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module reg_file_8( 22 | input clk_i, 23 | input reset_i, 24 | input [4:0] rR1_i, 25 | input [4:0] rR2_i, 26 | input [4:0] wR_i, 27 | input [31:0] wD_i, 28 | input WE_i, 29 | output reg [31:0] rD1_o, 30 | output reg [31:0] rD2_o 31 | ); 32 | reg [31:0] reg_0; 33 | reg [31:0] reg_1; 34 | reg [31:0] reg_2; 35 | reg [31:0] reg_3; 36 | reg [31:0] reg_4; 37 | reg [31:0] reg_5; 38 | reg [31:0] reg_6; 39 | reg [31:0] reg_7; 40 | // rD1_o 41 | always @ (*) begin 42 | case(rR1_i[2:0]) 43 | 3'b000: rD1_o = (rR1_i[4:3]==2'b00)?32'h0:reg_0; // x0不可被修改 44 | 3'b001: rD1_o = reg_1; 45 | 3'b010: rD1_o = reg_2; 46 | 3'b011: rD1_o = reg_3; 47 | 3'b100: rD1_o = reg_4; 48 | 3'b101: rD1_o = reg_5; 49 | 3'b110: rD1_o = reg_6; 50 | 3'b111: rD1_o = reg_7; 51 | default: rD1_o = 32'h0; 52 | endcase 53 | end 54 | // rD2_o 55 | always @ (*) begin 56 | case(rR2_i[2:0]) 57 | 3'b000: rD2_o = (rR2_i[4:3]==2'b00)?32'h0:reg_0; 58 | 3'b001: rD2_o = reg_1; 59 | 3'b010: rD2_o = reg_2; 60 | 3'b011: rD2_o = reg_3; 61 | 3'b100: rD2_o = reg_4; 62 | 3'b101: rD2_o = reg_5; 63 | 3'b110: rD2_o = reg_6; 64 | 3'b111: rD2_o = reg_7; 65 | default: rD2_o = 32'h0; 66 | endcase 67 | end 68 | // wirte 69 | always @ (posedge clk_i or posedge reset_i) begin 70 | if(reset_i == 1'b1) begin 71 | reg_0 = 32'h0; 72 | reg_1 = 32'h0; 73 | reg_2 = 32'h0; 74 | reg_3 = 32'h0; 75 | reg_4 = 32'h0; 76 | reg_5 = 32'h0; 77 | reg_6 = 32'h0; 78 | reg_7 = 32'h0; 79 | end 80 | else 81 | if(WE_i == 1'b1) begin 82 | case(wR_i) 83 | 3'b000: reg_0 = (wR_i[4:3]==2'b00)?32'h0:wD_i; 84 | 3'b001: reg_1 = wD_i; 85 | 3'b010: reg_2 = wD_i; 86 | 3'b011: reg_3 = wD_i; 87 | 3'b100: reg_4 = wD_i; 88 | 3'b101: reg_5 = wD_i; 89 | 3'b110: reg_6 = wD_i; 90 | 3'b111: reg_7 = wD_i; 91 | default:; 92 | endcase 93 | end 94 | else; 95 | end 96 | endmodule 97 | -------------------------------------------------------------------------------- /single_cycle/trace/shift_unit.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 2021/07/02 15:41:40 7 | // Design Name: 8 | // Module Name: shift_unit 9 | // Project Name: 10 | // Target Devices: 11 | // Tool Versions: 12 | // Description: 13 | // alu下的移位操作单元,通过桶形移位器实现 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module shift_unit #( 22 | parameter LEFT_SHIFT = 2'b00, 23 | parameter RIGHT_LOGIC_SHIFT = 2'b01, 24 | parameter RIGHT_ARITHMETIC_SHIFT = 2'b10, 25 | parameter UNKNOWN_OPCODE_RESULT = 32'h0 26 | ) 27 | ( 28 | input [31:0] op_a_i, 29 | input [31:0] op_b_i, // 实际只有低5位有效,高位是拓展而来 30 | input [1:0] opcode_i, 31 | output [31:0] result_o 32 | ); 33 | reg [31:0] tmp; 34 | always @(*) begin 35 | case(opcode_i) 36 | LEFT_SHIFT:begin 37 | tmp = (op_b_i[0]==1'b1)?{op_a_i[30:0], 1'b0} :op_a_i; 38 | tmp = (op_b_i[1]==1'b1)?{tmp[29:0], 2'b0} :tmp; 39 | tmp = (op_b_i[2]==1'b1)?{tmp[27:0], 4'b0} :tmp; 40 | tmp = (op_b_i[3]==1'b1)?{tmp[23:0], 8'b0} :tmp; 41 | tmp = (op_b_i[4]==1'b1)?{tmp[15:0], 16'b0} :tmp; 42 | end 43 | RIGHT_LOGIC_SHIFT:begin 44 | tmp = (op_b_i[0]==1'b1)?{1'b0, op_a_i[31:1]}:op_a_i; 45 | tmp = (op_b_i[1]==1'b1)?{2'b0, tmp[31:2]} :tmp; 46 | tmp = (op_b_i[2]==1'b1)?{4'b0, tmp[31:4]} :tmp; 47 | tmp = (op_b_i[3]==1'b1)?{8'b0, tmp[31:8]} :tmp; 48 | tmp = (op_b_i[4]==1'b1)?{16'b0, tmp[31:16]} :tmp; 49 | end 50 | RIGHT_ARITHMETIC_SHIFT: begin 51 | tmp = (op_b_i[0]==1'b1)?{{1{op_a_i[31]}}, op_a_i[31:1]}:op_a_i; 52 | tmp = (op_b_i[1]==1'b1)?{{2{op_a_i[31]}}, tmp[31:2]} :tmp; 53 | tmp = (op_b_i[2]==1'b1)?{{4{op_a_i[31]}}, tmp[31:4]} :tmp; 54 | tmp = (op_b_i[3]==1'b1)?{{8{op_a_i[31]}}, tmp[31:8]} :tmp; 55 | tmp = (op_b_i[4]==1'b1)?{{16{op_a_i[31]}}, tmp[31:16]} :tmp; 56 | end 57 | default: tmp = UNKNOWN_OPCODE_RESULT; 58 | endcase 59 | end 60 | assign result_o = tmp; 61 | endmodule 62 | -------------------------------------------------------------------------------- /single_cycle/trace/top.v: -------------------------------------------------------------------------------- 1 | // Add your code here, or replace this file 2 | module top( 3 | input clk, 4 | input rst_n, 5 | output debug_wb_have_inst, 6 | output [31:0] debug_wb_pc, 7 | output debug_wb_ena, 8 | output [4:0] debug_wb_reg, 9 | output reg [31:0] debug_wb_value 10 | ); 11 | 12 | wire rst = ~rst_n; 13 | wire [31:0] inst; 14 | wire [31:0] pc; 15 | wire mem_we; 16 | wire [13:0] adr; 17 | wire cpu_clk; 18 | wire [31:0] input_data; 19 | wire [31:0] output_data; 20 | wire debug_ena; 21 | wire [31:0] debug_value; 22 | wire [4:0] debug_reg; 23 | assign debug_wb_pc = pc; 24 | 25 | 26 | 27 | assign debug_wb_have_inst = ~clk & rst_n; 28 | always @(negedge clk) begin 29 | debug_wb_value <= debug_value; 30 | end 31 | 32 | 33 | my_cpu u_my_cpu( 34 | .sysclk_i (clk), 35 | .reset_i (rst), 36 | .inst_i (inst), 37 | .pc_o (pc), 38 | .npc_o (debug_wb_pc), 39 | .mem_we_o (mem_we), 40 | .adr_o (adr), 41 | .outer_inputdata_o (input_data), 42 | .outer_outputdata_i(output_data), 43 | .rf_we_o (debug_wb_ena), 44 | .rf_wd_o (debug_value), 45 | .rf_wr_o (debug_wb_reg) 46 | ); 47 | 48 | // 下面两个模块,只需要实例化并连线,不需要添加文件 49 | 50 | inst_mem imem( 51 | .a (pc[15:2]), 52 | .spo (inst) 53 | ); 54 | 55 | data_mem dmem( 56 | .clk (clk), // input wire clka 57 | .a (adr), // input wire [13:0] addra 58 | .spo (output_data), // output wire [31:0] douta 59 | .we (mem_we), // input wire [0:0] wea 60 | .d (input_data) // input wire [31:0] dina 61 | ); 62 | endmodule 63 | --------------------------------------------------------------------------------