rtl: optimized for instr fetch and mem access

Signed-off-by: liangkangnan <liangkangnan@163.com>
verilator
liangkangnan 2023-03-28 10:19:07 +08:00
parent 7993b97612
commit d6a14415c9
5 changed files with 82 additions and 161 deletions

View File

@ -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,22 +164,32 @@ 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;
mem_stall_d = 1'b0;
end
end
// 写内存
S_WAIT_WRITE: begin
if (mem_rvalid_i) begin
mem_stall_d = 1'b0;
state_d = S_IDLE;
end else 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
@ -183,7 +197,9 @@ module exu_mem(
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;
// 暂停流水线

View File

@ -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:
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

View File

@ -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

View File

@ -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;
@ -155,8 +159,7 @@ module jtag_dtm #(
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_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

View File

@ -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;