From d6a14415c94f616076e6cda0f898a89d1b7ec2af Mon Sep 17 00:00:00 2001 From: liangkangnan Date: Tue, 28 Mar 2023 10:19:07 +0800 Subject: [PATCH] rtl: optimized for instr fetch and mem access Signed-off-by: liangkangnan --- rtl/core/exu_mem.sv | 46 ++++++++++----- rtl/core/ifu.sv | 131 ++++++------------------------------------ rtl/debug/jtag_dm.sv | 11 ++-- rtl/debug/jtag_dtm.sv | 17 +++--- rtl/debug/jtag_sba.sv | 38 ++++++------ 5 files changed, 82 insertions(+), 161 deletions(-) diff --git a/rtl/core/exu_mem.sv b/rtl/core/exu_mem.sv index 8042319..1896d18 100644 --- a/rtl/core/exu_mem.sv +++ b/rtl/core/exu_mem.sv @@ -137,18 +137,22 @@ module exu_mem( reg mem_stall_d; reg mem_reg_we_d; reg mem_mem_we_d; + reg req_mem_d; + // 访存状态机 always @ (*) begin state_d = state_q; mem_stall_d = 1'b0; mem_reg_we_d = 1'b0; mem_mem_we_d = 1'b0; + req_mem_d = 1'b0; case (state_q) S_IDLE: begin - if (mem_req_o) begin + if (req_mem_i) begin mem_stall_d = 1'b1; + req_mem_d = 1'b1; if (mem_gnt_i) begin if (op_load) begin state_d = S_WAIT_READ; @@ -160,34 +164,46 @@ module exu_mem( end end + // 读内存 S_WAIT_READ: begin + req_mem_d = 1'b1; + mem_stall_d = 1'b1; + if (~mem_gnt_i) begin + state_d = S_IDLE; + end if (mem_rvalid_i) begin - mem_stall_d = 1'b0; + req_mem_d = 1'b0; state_d = S_IDLE; mem_reg_we_d = 1'b1; - end else begin - mem_stall_d = 1'b1; - end - end - - S_WAIT_WRITE: begin - if (mem_rvalid_i) begin mem_stall_d = 1'b0; - state_d = S_IDLE; - end else begin - mem_stall_d = 1'b1; end end - default:; + // 写内存 + S_WAIT_WRITE: begin + req_mem_d = 1'b1; + mem_stall_d = 1'b1; + if (~mem_gnt_i) begin + state_d = S_IDLE; + end + if (mem_rvalid_i) begin + req_mem_d = 1'b0; + state_d = S_IDLE; + mem_stall_d = 1'b0; + end + end + + default: ; endcase end - assign mem_req_o = req_mem_i && (state_q == S_IDLE); + // 访存请求 + assign mem_req_o = req_mem_d; + // 访存地址 assign mem_addr_o = mem_addr_i; // 暂停流水线 - assign mem_stall_o = mem_stall_d; + assign mem_stall_o = mem_stall_d; // 写寄存器使能 assign mem_reg_we_o = mem_reg_we_d; // 写内存使能 diff --git a/rtl/core/ifu.sv b/rtl/core/ifu.sv index 8cad501..a5cdb58 100644 --- a/rtl/core/ifu.sv +++ b/rtl/core/ifu.sv @@ -44,102 +44,6 @@ module ifu #( ); -// 从(Nor)Flash启动(非易失) -`ifdef FLASH_BOOT - - localparam S_RESET = 3'b001; - localparam S_FETCH = 3'b010; - localparam S_VALID = 3'b100; - - reg[2:0] state_d, state_q; - - wire inst_valid; - wire[31:0] fetch_addr_n; - reg[31:0] fetch_addr_q; - - wire prdt_taken; - wire[31:0] prdt_addr; - - - always @ (*) begin - state_d = state_q; - - case (state_q) - // 复位 - S_RESET: begin - // 复位撤销后转到取指状态 - if (rst_n) begin - state_d = S_FETCH; - end - end - - // 取指 - S_FETCH: begin - // 取指有效 - if (instr_gnt_i & (~stall_i[`STALL_IF]) & (~flush_i)) begin - state_d = S_VALID; - end - end - - // 指令有效 - S_VALID: begin - // 回到取指状态 - if (stall_i[`STALL_IF] || instr_rvalid_i || flush_i) begin - state_d = S_FETCH; - end - end - - default: ; - endcase - end - - // 指令有效 - assign inst_valid = (state_q == S_VALID) & instr_rvalid_i & id_ready_i; - assign inst_valid_o = inst_valid; - // 指令无效时有nop指令代替 - assign inst_o = inst_valid ? instr_rdata_i: `INST_NOP; - assign pc_o = fetch_addr_q; - - // 更新取指地址 - assign fetch_addr_n = flush_i ? flush_addr_i: - prdt_taken ? prdt_addr: - inst_valid ? fetch_addr_q + 4'h4: - fetch_addr_q; - - // 取指请求 - assign instr_req_o = (~stall_i[`STALL_IF]) & (state_q == S_FETCH) & (~flush_i); - // 取指地址(4字节对齐) - assign instr_addr_o = {fetch_addr_q[31:2], 2'b00}; - - always @ (posedge clk or negedge rst_n) begin - if (!rst_n) begin - state_q <= S_RESET; - fetch_addr_q <= `CPU_RESET_ADDR; - end else begin - state_q <= state_d; - fetch_addr_q <= fetch_addr_n; - end - end - - // 分支预测 - if (BranchPredictor) begin: g_branch_predictor - bpu u_bpu( - .clk(clk), - .rst_n(rst_n), - .inst_i(instr_rdata_i), - .inst_valid_i(inst_valid), - .pc_i(fetch_addr_q), - .prdt_taken_o(prdt_taken), - .prdt_addr_o(prdt_addr) - ); - end else begin: g_no_branch_predictor - assign prdt_taken = 1'b0; - assign prdt_addr = 32'h0; - end - -// 从Rom启动(易失) -`else - localparam S_RESET = 3'b001; localparam S_FETCH = 3'b010; localparam S_VALID = 3'b100; @@ -150,18 +54,19 @@ module ifu #( wire req_valid; wire[31:0] fetch_addr_n; reg[31:0] fetch_addr_q; + reg inst_valid_d; wire prdt_taken; wire[31:0] prdt_addr; // 取指请求有效 - assign req_valid = instr_gnt_i & (~stall_i[`STALL_IF]); + assign req_valid = instr_gnt_i; // 状态切换 - // 取指模块需要实现连续不断地取指,因此 - // 在S_FETCH和S_VALID这两个状态都要进行取指操作 + // 取指模块需要实现连续不断地取指 always @ (*) begin state_d = state_q; + inst_valid_d = 0; case (state_q) // 复位 @@ -171,6 +76,7 @@ module ifu #( state_d = S_FETCH; end end + // 取指 S_FETCH: begin // 取指有效 @@ -178,12 +84,16 @@ module ifu #( state_d = S_VALID; end end + // 指令有效 S_VALID: begin // 取指无效 if (~req_valid) begin state_d = S_FETCH; end + if (instr_rvalid_i) begin + inst_valid_d = 1'b1; + end end default: ; @@ -191,21 +101,20 @@ module ifu #( end // 指令有效 - assign inst_valid = (state_q == S_VALID) & instr_rvalid_i & id_ready_i; + assign inst_valid = inst_valid_d & id_ready_i; assign inst_valid_o = inst_valid; - // 指令无效时有nop指令代替 + // 指令无效时用nop指令代替 assign inst_o = inst_valid ? instr_rdata_i: `INST_NOP; assign pc_o = fetch_addr_q; // 更新取指地址 - assign fetch_addr_n = flush_i ? flush_addr_i: - prdt_taken ? prdt_addr: - //stall_i[`STALL_IF] ? fetch_addr_q: - inst_valid ? fetch_addr_q + 4'h4: + assign fetch_addr_n = flush_i ? flush_addr_i: + prdt_taken ? prdt_addr: + inst_valid ? fetch_addr_q + 4'h4: fetch_addr_q; - // 取指请求 - assign instr_req_o = (~stall_i[`STALL_IF]) & (state_q != S_RESET); + // 取指请求(连续不断地取指) + assign instr_req_o = (state_q != S_RESET); // 取指地址(4字节对齐) assign instr_addr_o = {fetch_addr_n[31:2], 2'b00}; @@ -227,9 +136,9 @@ module ifu #( bpu u_bpu( .clk(clk), .rst_n(rst_n), - .inst_i(instr_rdata_i), - .inst_valid_i(inst_valid), - .pc_i(fetch_addr_q), + .inst_i(inst_o), + .inst_valid_i(inst_valid_o), + .pc_i(pc_o), .prdt_taken_o(prdt_taken), .prdt_addr_o(prdt_addr) ); @@ -238,6 +147,4 @@ module ifu #( assign prdt_addr = 32'h0; end -`endif - endmodule diff --git a/rtl/debug/jtag_dm.sv b/rtl/debug/jtag_dm.sv index a7c007b..e5d7c5f 100644 --- a/rtl/debug/jtag_dm.sv +++ b/rtl/debug/jtag_dm.sv @@ -126,24 +126,23 @@ module jtag_dm #( localparam S_RESP = 2'b10; reg[2:0] req_state_d, req_state_q; - reg dm_valid_d, dm_valid_q; + reg dm_valid_d; // response FSM always @ (*) begin req_state_d = req_state_q; - dm_valid_d = dm_valid_q; + dm_valid_d = 1'b0; case (req_state_q) S_REQ: begin if (dmi_valid_i & dm_ready_o) begin req_state_d = S_RESP; - dm_valid_d = 1'b1; end end S_RESP: begin if (dmi_ready_i) begin - dm_valid_d = 1'b0; + dm_valid_d = 1'b1; req_state_d = S_REQ; end end @@ -155,16 +154,14 @@ module jtag_dm #( always @ (posedge clk or negedge rst_n) begin if (!rst_n) begin req_state_q <= S_REQ; - dm_valid_q <= 1'b0; end else begin req_state_q <= req_state_d; - dm_valid_q <= dm_valid_d; end end // we always ready to receive dmi request assign dm_ready_o = ~sbbusy; - assign dm_valid_o = dm_valid_q; + assign dm_valid_o = dm_valid_d; assign dm_data_o = {{DMI_ADDR_BITS{1'b0}}, dm_resp_data_q, 2'b00}; // response successfully diff --git a/rtl/debug/jtag_dtm.sv b/rtl/debug/jtag_dtm.sv index 3a11130..49d6106 100644 --- a/rtl/debug/jtag_dtm.sv +++ b/rtl/debug/jtag_dtm.sv @@ -68,6 +68,7 @@ module jtag_dtm #( reg[4:0] state_d; reg[4:0] state_q; reg dtm_valid; + reg dtm_ready; reg[DTM_REQ_BITS-1:0] dtm_data_q; reg[DTM_REQ_BITS-1:0] dtm_data_d; reg[DTM_RESP_BITS-1:0] resp_tap_data_q; @@ -99,6 +100,7 @@ module jtag_dtm #( always @ (*) begin state_d = state_q; dtm_valid = 1'b0; + dtm_ready = 1'b0; dtm_data_d = dtm_data_q; case (state_q) @@ -119,13 +121,14 @@ module jtag_dtm #( end S_READ: begin - dtm_valid = 1'b1; if (dmi_ready_i) begin + dtm_valid = 1'b1; state_d = S_WAIT_READ; end end S_WAIT_READ: begin + dtm_ready = 1'b1; if (dmi_valid_i) begin dtm_data_d = dmi_data_i; state_d = S_IDLE; @@ -133,13 +136,14 @@ module jtag_dtm #( end S_WRITE: begin - dtm_valid = 1'b1; if (dmi_ready_i) begin + dtm_valid = 1'b1; state_d = S_WAIT_WRITE; end end S_WAIT_WRITE: begin + dtm_ready = 1'b1; if (dmi_valid_i) begin dtm_data_d = dmi_data_i; state_d = S_IDLE; @@ -154,9 +158,8 @@ module jtag_dtm #( end assign dtm_valid_o = dtm_valid; - assign dtm_data_o = dtm_data_q; - // we will always be ready to core request - assign dtm_ready_o = 1'b1; + assign dtm_data_o = dtm_data_q; + assign dtm_ready_o = dtm_ready; always @ (posedge jtag_tck_i or negedge jtag_trst_ni) begin if (!jtag_trst_ni) begin @@ -178,7 +181,7 @@ module jtag_dtm #( end else if ((state_q != S_IDLE) && tap_req_i) begin stick_busy <= 1'b1; end - if (state_q != S_IDLE) begin + if ((state_q != S_IDLE) | tap_req_i) begin is_busy <= 1'b1; end else begin is_busy <= 1'b0; @@ -186,6 +189,6 @@ module jtag_dtm #( end end - assign data_o = (stick_busy | is_busy) ? busy_response : dtm_data_q; + assign data_o = (stick_busy | is_busy | tap_req_i) ? busy_response : dtm_data_q; endmodule diff --git a/rtl/debug/jtag_sba.sv b/rtl/debug/jtag_sba.sv index e933d51..59ef4af 100644 --- a/rtl/debug/jtag_sba.sv +++ b/rtl/debug/jtag_sba.sv @@ -51,13 +51,12 @@ module jtag_sba( ); - localparam S_IDLE = 5'b00001; - localparam S_READ = 5'b00010; - localparam S_WAIT_READ = 5'b00100; - localparam S_WRITE = 5'b01000; - localparam S_WAIT_WRITE = 5'b10000; + localparam S_IDLE = 4'b0001; + localparam S_READ = 4'b0010; + localparam S_WAIT = 4'b0100; + localparam S_WRITE = 4'b1000; - reg[4:0] state_d, state_q; + reg[3:0] state_d, state_q; reg[2:0] sberror; reg[3:0] be_mask; reg[1:0] be_index; @@ -101,6 +100,7 @@ module jtag_sba( endcase end + // 访存状态机 always @ (*) begin state_d = state_q; @@ -130,34 +130,33 @@ module jtag_sba( end end + // 读内存 S_READ: begin master_req = 1'b1; master_be = 4'b1111; if (master_gnt_i) begin - state_d = S_WAIT_READ; - end - end - - S_WAIT_READ: begin - if (master_rvalid_i) begin - state_d = S_IDLE; - if (sbautoincrement_i) begin - sbaddress = sbaddress_new; - end + state_d = S_WAIT; end end + // 写内存 S_WRITE: begin master_req = 1'b1; master_be = be_mask; master_we = 1'b1; if (master_gnt_i) begin - state_d = S_WAIT_WRITE; + state_d = S_WAIT; end end - S_WAIT_WRITE: begin + // 等待读写完成 + S_WAIT: begin + master_req = 1'b1; + if (~master_gnt_i) begin + state_d = S_IDLE; + end if (master_rvalid_i) begin + master_req = 1'b0; state_d = S_IDLE; if (sbautoincrement_i) begin sbaddress = sbaddress_new; @@ -181,8 +180,7 @@ module jtag_sba( assign master_addr_o = master_addr; assign master_wdata_o = master_wdata; - assign sbdata_valid_o = master_rvalid_i & - ((state_q == S_WAIT_READ) || (state_q == S_WAIT_WRITE)); + assign sbdata_valid_o = master_rvalid_i & (state_q == S_WAIT); assign sbdata_o = master_rdata_i; assign sberror_o = sberror; assign sbaddress_o = sbaddress;