rtl: optimized for instr fetch and mem access
Signed-off-by: liangkangnan <liangkangnan@163.com>verilator
parent
7993b97612
commit
d6a14415c9
|
@ -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;
|
||||
|
||||
// 暂停流水线
|
||||
|
|
125
rtl/core/ifu.sv
125
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:
|
||||
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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue