parent
36147d9391
commit
b02b38bddc
|
@ -225,7 +225,12 @@ module csr_reg(
|
||||||
dpc_we = 1'b1;
|
dpc_we = 1'b1;
|
||||||
end
|
end
|
||||||
`CSR_DCSR: begin
|
`CSR_DCSR: begin
|
||||||
dcsr_d = wdata;
|
// Not all bits in DCSR are writable by exu
|
||||||
|
if (exu_we_i) begin
|
||||||
|
dcsr_d = {dcsr_q[31:28], wdata[27:9], dcsr_q[8:6], wdata[5:4], dcsr_q[3], wdata[2:0]};
|
||||||
|
end else begin
|
||||||
|
dcsr_d = wdata;
|
||||||
|
end
|
||||||
dcsr_we = 1'b1;
|
dcsr_we = 1'b1;
|
||||||
end
|
end
|
||||||
default:;
|
default:;
|
||||||
|
@ -345,7 +350,7 @@ module csr_reg(
|
||||||
|
|
||||||
// dcsr
|
// dcsr
|
||||||
csr #(
|
csr #(
|
||||||
.RESET_VAL(32'h0)
|
.RESET_VAL(32'h40000000)
|
||||||
) dcsr_csr (
|
) dcsr_csr (
|
||||||
.clk(clk),
|
.clk(clk),
|
||||||
.rst_n(rst_n),
|
.rst_n(rst_n),
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
`define DCSR_CAUSE_STEP 3'h4
|
`define DCSR_CAUSE_STEP 3'h4
|
||||||
`define DCSR_CAUSE_DBGREQ 3'h3
|
`define DCSR_CAUSE_DBGREQ 3'h3
|
||||||
`define DCSR_CAUSE_EBREAK 3'h1
|
`define DCSR_CAUSE_EBREAK 3'h1
|
||||||
|
`define DCSR_CAUSE_HALT 3'h5
|
||||||
|
|
||||||
|
|
||||||
module exception (
|
module exception (
|
||||||
|
@ -187,21 +188,26 @@ module exception (
|
||||||
reg enter_debug_cause_debugger_req;
|
reg enter_debug_cause_debugger_req;
|
||||||
reg enter_debug_cause_single_step;
|
reg enter_debug_cause_single_step;
|
||||||
reg enter_debug_cause_ebreak;
|
reg enter_debug_cause_ebreak;
|
||||||
|
reg enter_debug_cause_reset_halt;
|
||||||
reg[2:0] dcsr_cause_d, dcsr_cause_q;
|
reg[2:0] dcsr_cause_d, dcsr_cause_q;
|
||||||
|
|
||||||
always @ (*) begin
|
always @ (*) begin
|
||||||
enter_debug_cause_debugger_req = 1'b0;
|
enter_debug_cause_debugger_req = 1'b0;
|
||||||
enter_debug_cause_single_step = 1'b0;
|
enter_debug_cause_single_step = 1'b0;
|
||||||
enter_debug_cause_ebreak = 1'b0;
|
enter_debug_cause_ebreak = 1'b0;
|
||||||
|
enter_debug_cause_reset_halt = 1'b0;
|
||||||
dcsr_cause_d = `DCSR_CAUSE_NONE;
|
dcsr_cause_d = `DCSR_CAUSE_NONE;
|
||||||
|
|
||||||
if (inst_ebreak_i & debug_mode_q) begin
|
if (inst_ebreak_i & debug_mode_q) begin
|
||||||
enter_debug_cause_ebreak = 1'b1;
|
enter_debug_cause_ebreak = 1'b1;
|
||||||
dcsr_cause_d = `DCSR_CAUSE_EBREAK;
|
dcsr_cause_d = `DCSR_CAUSE_EBREAK;
|
||||||
|
end else if ((inst_addr_i == `CPU_RESET_ADDR) & inst_valid_i & debug_req_i) begin
|
||||||
|
enter_debug_cause_reset_halt = 1'b1;
|
||||||
|
dcsr_cause_d = `DCSR_CAUSE_HALT;
|
||||||
end else if ((~debug_mode_q) & debug_req_i & inst_valid_i) begin
|
end else if ((~debug_mode_q) & debug_req_i & inst_valid_i) begin
|
||||||
enter_debug_cause_debugger_req = 1'b1;
|
enter_debug_cause_debugger_req = 1'b1;
|
||||||
dcsr_cause_d = `DCSR_CAUSE_DBGREQ;
|
dcsr_cause_d = `DCSR_CAUSE_DBGREQ;
|
||||||
end else if (inst_ebreak_i & dcsr_i[15]) begin
|
end else if ((~debug_mode_q) & dcsr_i[2] & (state_q == S_IDLE)) begin
|
||||||
enter_debug_cause_single_step = 1'b1;
|
enter_debug_cause_single_step = 1'b1;
|
||||||
dcsr_cause_d = `DCSR_CAUSE_STEP;
|
dcsr_cause_d = `DCSR_CAUSE_STEP;
|
||||||
end
|
end
|
||||||
|
@ -209,6 +215,7 @@ module exception (
|
||||||
|
|
||||||
wire debug_mode_req = enter_debug_cause_debugger_req |
|
wire debug_mode_req = enter_debug_cause_debugger_req |
|
||||||
enter_debug_cause_single_step |
|
enter_debug_cause_single_step |
|
||||||
|
enter_debug_cause_reset_halt |
|
||||||
enter_debug_cause_ebreak;
|
enter_debug_cause_ebreak;
|
||||||
|
|
||||||
assign stall_flag_o = ((state_q != S_IDLE) & (state_q != S_ASSERT)) |
|
assign stall_flag_o = ((state_q != S_IDLE) & (state_q != S_ASSERT)) |
|
||||||
|
@ -237,13 +244,23 @@ module exception (
|
||||||
state_d = S_W_MEPC;
|
state_d = S_W_MEPC;
|
||||||
end else if (debug_mode_req) begin
|
end else if (debug_mode_req) begin
|
||||||
debug_mode_d = 1'b1;
|
debug_mode_d = 1'b1;
|
||||||
if (enter_debug_cause_debugger_req) begin
|
if (enter_debug_cause_debugger_req |
|
||||||
|
enter_debug_cause_single_step |
|
||||||
|
enter_debug_cause_reset_halt) begin
|
||||||
csr_we = 1'b1;
|
csr_we = 1'b1;
|
||||||
csr_waddr = {20'h0, `CSR_DPC};
|
csr_waddr = {20'h0, `CSR_DPC};
|
||||||
csr_wdata = inst_addr_i;
|
csr_wdata = enter_debug_cause_reset_halt ? (`CPU_RESET_ADDR) : inst_addr_i;
|
||||||
|
// when run openocd compliance test, use it.
|
||||||
|
// openocd compliance test bug: It report test fail when the reset address is 0x0:
|
||||||
|
// "NDMRESET should move DPC to reset value."
|
||||||
|
//csr_wdata = enter_debug_cause_reset_halt ? (`CPU_RESET_ADDR + 4'h4) : inst_addr_i;
|
||||||
end
|
end
|
||||||
assert_addr_d = debug_halt_addr_i;
|
assert_addr_d = debug_halt_addr_i;
|
||||||
state_d = S_W_DCSR;
|
if (enter_debug_cause_ebreak) begin
|
||||||
|
state_d = S_ASSERT;
|
||||||
|
end else begin
|
||||||
|
state_d = S_W_DCSR;
|
||||||
|
end
|
||||||
end else if (inst_mret_i) begin
|
end else if (inst_mret_i) begin
|
||||||
assert_addr_d = mepc_i;
|
assert_addr_d = mepc_i;
|
||||||
state_d = S_ASSERT;
|
state_d = S_ASSERT;
|
||||||
|
|
Loading…
Reference in New Issue