diff --git a/lacpu/rtl/cpu/cpu_top.v b/lacpu/rtl/cpu/cpu_top.v index 3fd352c..64c6333 100755 --- a/lacpu/rtl/cpu/cpu_top.v +++ b/lacpu/rtl/cpu/cpu_top.v @@ -38,6 +38,13 @@ module mycpu_top( wire [`MS_TO_WS_BUS_WD -1:0] ms_to_ws_bus; wire [`WS_TO_RF_BUS_WD -1:0] ws_to_rf_bus; wire [`BR_BUS_WD -1:0] br_bus; + wire [`DS_TO_FW_BUS_WD -1:0] ds_to_fw_bus; + wire [`ES_TO_FW_BUS_WD -1:0] es_to_fw_bus; + wire [`MS_TO_FW_BUS_WD -1:0] ms_to_fw_bus; + wire [`FW_TO_ES_BUS_WD -1:0] fw_to_es_bus; + wire [`MS_TO_ES_BUS_WD -1:0] ms_to_es_bus; + wire [`WS_TO_ES_BUS_WD -1:0] ws_to_es_bus; + // IF stage if_stage if_stage( @@ -71,7 +78,9 @@ module mycpu_top( .ds_to_es_valid (ds_to_es_valid ), .ds_to_es_bus (ds_to_es_bus ), //to rf: for write back - .ws_to_rf_bus (ws_to_rf_bus ) + .ws_to_rf_bus (ws_to_rf_bus ), + + .ds_to_fw_bus (ds_to_fw_bus ) ); // EXE stage exe_stage exe_stage( @@ -86,6 +95,14 @@ module mycpu_top( //to ms .es_to_ms_valid (es_to_ms_valid ), .es_to_ms_bus (es_to_ms_bus ), + //from fw + .fw_to_es_bus (fw_to_es_bus ), + //to fw + .es_to_fw_bus (es_to_fw_bus ), + //from ms + .ms_to_ds_bus (ms_to_es_bus ), + //from ws + .ws_to_ds_bus (ws_to_es_bus ), // data sram interface .data_sram_en (data_sram_en ), .data_sram_wen (data_sram_wen ), @@ -108,7 +125,11 @@ module mycpu_top( //to fs .br_bus (br_bus ), //from data-sram - .data_sram_rdata(data_sram_rdata) + .data_sram_rdata(data_sram_rdata), + //to fw + .ms_to_fw_bus (ms_to_fw_bus ), + //to es + .ms_to_es_bus (ms_to_es_bus ) ); // WB stage wb_stage wb_stage( @@ -121,6 +142,8 @@ module mycpu_top( .ms_to_ws_bus (ms_to_ws_bus ), //to rf: for write back .ws_to_rf_bus (ws_to_rf_bus ), + //to es + .ws_to_es_bus (ws_to_es_bus ), //trace debug interface .debug_wb_pc (debug_wb_pc ), .debug_wb_rf_wen (debug_wb_rf_wen ), @@ -128,4 +151,15 @@ module mycpu_top( .debug_wb_rf_wdata(debug_wb_rf_wdata) ); + // Forwarding + forward forward( + .clk (clk ), + .reset (reset ), + .ds_to_fw_bus (ds_to_fw_bus), + .es_to_fw_bus (es_to_fw_bus), + .ms_to_fw_bus (ms_to_fw_bus), + + .fw_to_es_bus (fw_to_es_bus) + ); + endmodule diff --git a/lacpu/rtl/cpu/exe_stage.v b/lacpu/rtl/cpu/exe_stage.v index 6c6509f..a80c55d 100755 --- a/lacpu/rtl/cpu/exe_stage.v +++ b/lacpu/rtl/cpu/exe_stage.v @@ -16,7 +16,15 @@ module exe_stage( output data_sram_en , output [ 3:0] data_sram_wen , output [31:0] data_sram_addr , - output [31:0] data_sram_wdata + output [31:0] data_sram_wdata, + //to fw + output [`ES_TO_FW_BUS_WD -1:0] es_to_fw_bus , + //from fw + input [`FW_TO_ES_BUS_WD -1:0] fw_to_es_bus , + //from ms + input [`MS_TO_ES_BUS_WD -1:0] ms_to_ds_bus , + //from ws + input [`WS_TO_ES_BUS_WD -1:0] ws_to_ds_bus ); reg es_valid ; @@ -39,6 +47,15 @@ module exe_stage( wire [31:0] es_rf_rdata2; wire [31:0] es_pc; + wire [31:0] ms_alu_result; + wire [31:0] ws_rf_wdata; + + wire es_src1_is_es_dest; + wire es_src1_is_ms_dest; + wire es_src2_is_es_dest; + wire es_src2_is_ms_dest; + wire es_data_is_rf_wdata; + assign {es_alu_op , //166:155 es_src1_is_pc , //154:154 @@ -57,6 +74,16 @@ module exe_stage( es_pc //31 :0 } = ds_to_es_bus_r; + assign {es_src1_is_es_dest , + es_src1_is_ms_dest , + es_src2_is_es_dest , + es_src2_is_ms_dest , + es_data_is_rf_wdata + } = fw_to_es_bus; + + assign ms_alu_result = ms_to_ds_bus; + assign ws_rf_wdata = ws_to_ds_bus; + wire [31:0] br_target; wire [31:0] es_alu_src1 ; @@ -81,6 +108,12 @@ module exe_stage( es_pc //31 :0 }; + assign es_to_fw_bus = {es_rf_rdata2 , + es_dest , + es_reg_we , + es_mem_we + }; + assign es_ready_go = 1'b1; assign es_allowin = !es_valid || es_ready_go && ms_allowin; assign es_to_ms_valid = es_valid && es_ready_go; @@ -97,11 +130,15 @@ module exe_stage( end end - assign es_alu_src1 = es_src1_is_pc ? es_pc : - es_rf_rdata1; - assign es_alu_src2 = es_src2_is_imm ? es_imm : - es_src2_is_4 ? 32'd4 : - es_rf_rdata2; + assign es_alu_src1 = es_src1_is_pc ? es_pc : + es_src1_is_es_dest ? ms_alu_result : + es_src1_is_ms_dest ? ws_rf_wdata : + es_rf_rdata1; + assign es_alu_src2 = es_src2_is_imm ? es_imm : + es_src2_is_4 ? 32'd4 : + es_src2_is_es_dest ? ms_alu_result : + es_src2_is_ms_dest ? ws_rf_wdata : + es_rf_rdata2; alu u_alu( .alu_op (es_alu_op ), @@ -126,10 +163,11 @@ module exe_stage( : 4'b0000; assign data_sram_addr = es_alu_result; - assign data_sram_wdata = es_store_op[0] ? {4{es_rf_rdata2[ 7:0]}} : - es_store_op[1] ? {2{es_rf_rdata2[15:0]}} : - es_store_op[2] ? es_rf_rdata2 : - 32'b0; + assign data_sram_wdata = es_data_is_rf_wdata ? ws_rf_wdata : + es_store_op[0] ? {4{es_rf_rdata2[ 7:0]}} : + es_store_op[1] ? {2{es_rf_rdata2[15:0]}} : + es_store_op[2] ? es_rf_rdata2 : + 32'b0; assign br_target = (^es_branch_op[5:0]) ? (es_pc + es_imm) : ( es_branch_op[7:6]) ? (es_pc + es_imm) : diff --git a/lacpu/rtl/cpu/forward.v b/lacpu/rtl/cpu/forward.v new file mode 100644 index 0000000..0e0c253 --- /dev/null +++ b/lacpu/rtl/cpu/forward.v @@ -0,0 +1,63 @@ +`include "mycpu.v" + +module forward( + input clk , + input reset , + input [`DS_TO_FW_BUS_WD -1:0] ds_to_fw_bus, + input [`ES_TO_FW_BUS_WD -1:0] es_to_fw_bus, + input [`MS_TO_FW_BUS_WD -1:0] ms_to_fw_bus, + + output [`FW_TO_ES_BUS_WD -1:0] fw_to_es_bus +); + + reg [`DS_TO_FW_BUS_WD -1:0] ds_to_fw_bus_r; + reg [`ES_TO_FW_BUS_WD -1:0] es_to_fw_bus_r; + reg [`MS_TO_FW_BUS_WD -1:0] ms_to_fw_bus_r; + + wire [4:0] ds_rf_raddr1; + wire [4:0] ds_rf_raddr2; + wire [4:0] es_rf_raddr2; + wire [4:0] es_dest; + wire [4:0] ms_dest; + + wire es_mem_we; + wire es_reg_we; + wire ms_reg_we; + + wire src1_is_es_dest; + wire src1_is_ms_dest; + wire src2_is_es_dest; + wire src2_is_ms_dest; + wire data_is_rf_wdata; + + assign {ds_rf_raddr1, ds_rf_raddr2 } = ds_to_fw_bus_r; + assign {es_rf_rdata2, es_dest, es_reg_we, es_mem_we} = es_to_fw_bus_r; + assign {ms_dest , ms_reg_we} = ms_to_fw_bus_r; + + assign fw_to_es_bus = {src1_is_es_dest , //4:4 + src1_is_ms_dest , //3:3 + src2_is_es_dest , //2:2 + src2_is_ms_dest , //1:1 + data_is_rf_wdata //0:0 + }; + always @(posedge clk) begin + if(reset) begin + ds_to_fw_bus_r <= 0; + es_to_fw_bus_r <= 0; + ms_to_fw_bus_r <= 0; + end + else begin + ds_to_fw_bus_r <= ds_to_fw_bus; + es_to_fw_bus_r <= es_to_fw_bus; + ms_to_fw_bus_r <= ms_to_fw_bus; + end + end + + assign src1_is_ms_dest = ms_reg_we && (ms_dest != 5'b0) && (es_dest != ds_rf_raddr1) && (ms_dest == ds_rf_raddr1); + assign src1_is_es_dest = es_reg_we && (es_dest != 5'b0) && (es_dest == ds_rf_raddr1); + assign src2_is_ms_dest = ms_reg_we && (ms_dest != 5'b0) && (es_dest != ds_rf_raddr2) && (ms_dest == ds_rf_raddr2); + assign src2_is_es_dest = es_reg_we && (es_dest != 5'b0) && (es_dest == ds_rf_raddr2); + assign data_is_rf_wdata = ms_reg_we && (ms_dest != 5'b0) && (ms_dest == es_rf_raddr2) && es_mem_we; + + +endmodule \ No newline at end of file diff --git a/lacpu/rtl/cpu/id_stage.v b/lacpu/rtl/cpu/id_stage.v index 3e0570a..6c0bc62 100755 --- a/lacpu/rtl/cpu/id_stage.v +++ b/lacpu/rtl/cpu/id_stage.v @@ -14,7 +14,10 @@ module id_stage( output ds_to_es_valid, output [`DS_TO_ES_BUS_WD -1:0] ds_to_es_bus , //to fs - input [`WS_TO_RF_BUS_WD -1:0] ws_to_rf_bus + input [`WS_TO_RF_BUS_WD -1:0] ws_to_rf_bus , + //to fw + output [`DS_TO_FW_BUS_WD -1:0] ds_to_fw_bus + ); reg ds_valid ; @@ -127,6 +130,7 @@ module id_stage( ds_pc //31 :0 }; + assign ds_to_fw_bus = {rf_raddr1 , rf_raddr2}; assign ds_ready_go = 1'b1; assign ds_allowin = !ds_valid || ds_ready_go && es_allowin; @@ -211,10 +215,10 @@ module id_stage( assign imm = {32{inst_slti | inst_sltui | inst_addiw | inst_ldb | inst_ldh | inst_ldw | inst_stb | inst_sth | inst_stw | inst_ldbu | inst_ldhu}} & {{20{ds_inst[21]}}, ds_inst[21:10]} | {32{inst_beq | inst_bne | inst_bge | inst_bgeu | inst_blt | inst_bltu | inst_jirl}} & {{14{ds_inst[25]}}, ds_inst[25:10], 2'b0} - | {32{inst_andi | inst_ori | inst_xori }} & { 20'b0 , ds_inst[21:10]} - | {32{inst_lu12iw | inst_pcaddu12i }} & {{12{ds_inst[24]}}, ds_inst[24: 5]} - | {32{inst_slliw | inst_srliw | inst_sraiw}} & { 27'b0 , rk} - | {32{inst_b | inst_bl}} & {{4{ds_inst[9]}} , ds_inst[9:0], ds_inst[25:10], 2'b0}; + | {32{inst_andi | inst_ori | inst_xori }} & { 20'b0 , ds_inst[21:10]} + | {32{inst_lu12iw | inst_pcaddu12i }} & { ds_inst[24: 5], 12'b0} + | {32{inst_slliw | inst_srliw | inst_sraiw}} & { 27'b0 , rk} + | {32{inst_b | inst_bl}} & {{4{ds_inst[9]}}, ds_inst[9:0], ds_inst[25:10], 2'b0}; assign src1_is_pc = inst_bl | inst_jirl | inst_pcaddu12i; assign src2_is_4 = inst_bl | inst_jirl; diff --git a/lacpu/rtl/cpu/mem_stage.v b/lacpu/rtl/cpu/mem_stage.v index b7682a4..03ff65d 100755 --- a/lacpu/rtl/cpu/mem_stage.v +++ b/lacpu/rtl/cpu/mem_stage.v @@ -1,21 +1,25 @@ `include "mycpu.v" module mem_stage( - input clk , - input reset , + input clk , + input reset , //allowin - input ws_allowin , - output ms_allowin , + input ws_allowin , + output ms_allowin , //from es - input es_to_ms_valid, - input [`ES_TO_MS_BUS_WD -1:0] es_to_ms_bus , + input es_to_ms_valid , + input [`ES_TO_MS_BUS_WD -1:0] es_to_ms_bus , //to ws - output ms_to_ws_valid, - output [`MS_TO_WS_BUS_WD -1:0] ms_to_ws_bus , + output ms_to_ws_valid , + output [`MS_TO_WS_BUS_WD -1:0] ms_to_ws_bus , //to fs - output [`BR_BUS_WD -1:0] br_bus , + output [`BR_BUS_WD -1:0] br_bus , //from data-sram - input [31 :0] data_sram_rdata + input [31 :0] data_sram_rdata, + //to fw + output [`MS_TO_FW_BUS_WD -1:0] ms_to_fw_bus , + //to es + output [`MS_TO_ES_BUS_WD -1:0] ms_to_es_bus ); reg ms_valid; @@ -63,6 +67,10 @@ module mem_stage( ms_pc //31:0 }; + assign ms_to_fw_bus = {ms_dest, ms_reg_we}; + + assign ms_to_es_bus = {ms_alu_result}; + assign ms_ready_go = 1'b1; assign ms_allowin = !ms_valid || ms_ready_go && ws_allowin; assign ms_to_ws_valid = ms_valid && ms_ready_go; diff --git a/lacpu/rtl/cpu/mycpu.v b/lacpu/rtl/cpu/mycpu.v index 9239be2..615e976 100644 --- a/lacpu/rtl/cpu/mycpu.v +++ b/lacpu/rtl/cpu/mycpu.v @@ -1,5 +1,5 @@ -`ifndef MYCPU_H - `define MYCPU_H +`ifndef MYCPU_VH + `define MYCPU_VH `define BR_BUS_WD 33 `define FS_TO_DS_BUS_WD 64 @@ -7,4 +7,12 @@ `define ES_TO_MS_BUS_WD 121 `define MS_TO_WS_BUS_WD 70 `define WS_TO_RF_BUS_WD 38 + + `define DS_TO_FW_BUS_WD 10 + `define ES_TO_FW_BUS_WD 12 + `define MS_TO_FW_BUS_WD 6 + `define FW_TO_ES_BUS_WD 5 + + `define MS_TO_ES_BUS_WD 32 + `define WS_TO_ES_BUS_WD 32 `endif diff --git a/lacpu/rtl/cpu/regfile.v b/lacpu/rtl/cpu/regfile.v index ae3e065..bcb3ae6 100755 --- a/lacpu/rtl/cpu/regfile.v +++ b/lacpu/rtl/cpu/regfile.v @@ -19,9 +19,13 @@ module regfile( end //READ OUT 1 - assign rdata1 = (raddr1==5'b0) ? 32'b0 : rf[raddr1]; + assign rdata1 = (raddr1==5'b0 ) ? 32'b0 : + (raddr1==waddr) ? wdata : + rf[raddr1]; //READ OUT 2 - assign rdata2 = (raddr2==5'b0) ? 32'b0 : rf[raddr2]; + assign rdata2 = (raddr2==5'b0 ) ? 32'b0 : + (raddr2==waddr) ? wdata : + rf[raddr2]; endmodule \ No newline at end of file diff --git a/lacpu/rtl/cpu/wb_stage.v b/lacpu/rtl/cpu/wb_stage.v index f47cac3..86d018c 100755 --- a/lacpu/rtl/cpu/wb_stage.v +++ b/lacpu/rtl/cpu/wb_stage.v @@ -10,6 +10,8 @@ module wb_stage( input [`MS_TO_WS_BUS_WD -1:0] ms_to_ws_bus , //to rf: for write back output [`WS_TO_RF_BUS_WD -1:0] ws_to_rf_bus , + //to es + output [`WS_TO_ES_BUS_WD -1:0] ws_to_es_bus , //trace debug interface output [31:0] debug_wb_pc , output [ 3:0] debug_wb_rf_wen , @@ -39,6 +41,8 @@ module wb_stage( rf_wdata //31:0 }; + assign ws_to_es_bus = {rf_wdata}; + assign ws_ready_go = 1'b1; assign ws_allowin = !ws_valid || ws_ready_go; always @(posedge clk) begin diff --git a/lacpu/run_vivado/la32r/la32r.xpr b/lacpu/run_vivado/la32r/la32r.xpr index 3a30709..a9eb70e 100644 --- a/lacpu/run_vivado/la32r/la32r.xpr +++ b/lacpu/run_vivado/la32r/la32r.xpr @@ -3,7 +3,7 @@ - +