debug: add sba module

Signed-off-by: liangkangnan <liangkangnan@163.com>
pull/4/head
liangkangnan 2021-04-26 09:48:19 +08:00
parent 65a26842c4
commit 4da79b6046
2 changed files with 201 additions and 16 deletions

View File

@ -66,6 +66,7 @@ module jtag_dm #(
wire halted;
wire resumeack;
wire sbbusy;
wire[2:0] sberror;
wire[DMI_OP_BITS-1:0] dm_op;
wire[DMI_ADDR_BITS-1:0] dm_op_addr;
wire[DMI_DATA_BITS-1:0] dm_op_data;
@ -74,11 +75,15 @@ module jtag_dm #(
reg clear_resumeack;
reg sbaddress_write_valid;
reg sbdata_write_valid;
reg sbdata_read_valid;
reg[31:0] sbcs;
reg[31:0] dm_resp_data_d, dm_resp_data_q;
wire[31:0] sba_sbaddress;
wire[31:0] dm_sbaddress;
wire resumereq;
wire cmdbusy;
wire sbdata_valid;
wire[31:0] sbdata;
// DM regs
reg[31:0] dmstatus;
@ -173,6 +178,8 @@ module jtag_dm #(
clear_resumeack = 1'b0;
sbaddress_write_valid = 1'b0;
sbdata_write_valid = 1'b0;
sbdata_read_valid = 1'b0;
sbcs = 32'h0;
data0_d = data0_q;
sbcs_d = sbcs_q;
@ -183,14 +190,22 @@ module jtag_dm #(
// read
if (dm_op == `DMI_OP_READ) begin
case (dm_op_addr)
`DMStatus: dm_resp_data_d = dmstatus;
`DMControl: dm_resp_data_d = dmcontrol_q;
`Hartinfo: dm_resp_data_d = HARTINFO;
`SBCS: dm_resp_data_d = sbcs_q;
`DMStatus :dm_resp_data_d = dmstatus;
`DMControl :dm_resp_data_d = dmcontrol_q;
`Hartinfo :dm_resp_data_d = HARTINFO;
`SBCS :dm_resp_data_d = sbcs_q;
`AbstractCS:dm_resp_data_d = abstractcs;
`SBAddress0:dm_resp_data_d = sbaddress0_q;
`SBData0 : begin
if (sbbusy || sbcs_q[`Sbbusyerror]) begin
sbcs_d[`Sbbusyerror] = 1'b1;
end else begin
sbdata_read_valid = (sbcs_q[`Sberror] == 3'b0);
dm_resp_data_d = sbdata0_q;
end
end
default:;
endcase
// write
end else if (dm_op == `DMI_OP_WRITE) begin
case (dm_op_addr)
@ -209,15 +224,16 @@ module jtag_dm #(
if (sbbusy) begin
sbcs_d[`Sbbusyerror] = 1'b1;
end else begin
sbcs = dm_op_data;
sbcs_d = dm_op_data;
// write 1 to clear
sbcs_d[`Sbbusyerror] = sbcs_q[`Sbbusyerror] & (~sbcs_d[`Sbbusyerror]);
sbcs_d[`Sberror] = sbcs_q[`Sberror] & (~sbcs_d[`Sberror]);
sbcs_d[`Sbbusyerror] = sbcs_q[`Sbbusyerror] & (~sbcs[`Sbbusyerror]);
sbcs_d[`Sberror] = sbcs_q[`Sberror] & (~sbcs[`Sberror]);
end
end
`SBAddress0: begin
if (sbbusy | sbcs_d[`Sbbusyerror]) begin
if (sbbusy | sbcs_q[`Sbbusyerror]) begin
sbcs_d[`Sbbusyerror] = 1'b1;
end else begin
sbaddress0_d = dm_op_data;
@ -226,7 +242,7 @@ module jtag_dm #(
end
`SBData0: begin
if (sbbusy | sbcs_d[`Sbbusyerror]) begin
if (sbbusy | sbcs_q[`Sbbusyerror]) begin
sbcs_d[`Sbbusyerror] = 1'b1;
end else begin
sbdata0_d = dm_op_data;
@ -241,8 +257,6 @@ module jtag_dm #(
default:;
endcase
// nop
end else begin
end
end
@ -267,6 +281,7 @@ module jtag_dm #(
// sbcs
sbcs_d[`Sbversion] = 3'd1;
sbcs_d[`Sbbusy] = sbbusy;
sbcs_d[`Sberror] = sberror;
sbcs_d[`Sbasize] = 7'd32;
sbcs_d[`Sbaccess128] = 1'b0;
sbcs_d[`Sbaccess64] = 1'b0;
@ -275,6 +290,10 @@ module jtag_dm #(
sbcs_d[`Sbaccess8] = 1'b0;
sbcs_d[`Sbaccess] = 3'd2;
if (sbdata_valid) begin
sbdata0_d = sbdata;
end
// set the havereset flag when we did a ndmreset
if (ndmreset_o) begin
havereset_d = 1'b1;
@ -355,7 +374,21 @@ module jtag_dm #(
) u_jtag_sba (
.clk(clk),
.rst_n(rst_n),
.sbaddress_i(sbaddress0_q),
.sbaddress_write_valid_i(sbaddress_write_valid),
.sbreadonaddr_i(sbcs_q[`Sbreadonaddr]),
.sbaddress_o(sba_sbaddress),
.sbautoincrement_i(sbcs_q[`Sbautoincrement]),
.sbaccess_i(sbcs_q[`Sbaccess]),
.sbreadondata_i(sbcs_q[`Sbreadondata]),
.sbdata_i(sbdata0_q),
.sbdata_read_valid_i(sbdata_read_valid),
.sbdata_write_valid_i(sbdata_write_valid),
.sbdata_o(sbdata),
.sbdata_valid_o(sbdata_valid),
.sbbusy_o(sbbusy),
.sberror_o(sberror),
.master_req_o(master_req_o),
.master_gnt_i(master_gnt_i),
.master_rvalid_i(master_rvalid_i),

View File

@ -19,10 +19,27 @@ module jtag_sba #(
)(
input wire clk,
input wire rst_n,
input wire clk,
input wire rst_n,
input wire [31:0] sbaddress_i,
input wire sbaddress_write_valid_i,
input wire sbreadonaddr_i,
output wire [31:0] sbaddress_o,
input wire sbautoincrement_i,
input wire [2:0] sbaccess_i,
input wire sbreadondata_i,
input wire [31:0] sbdata_i,
input wire sbdata_read_valid_i,
input wire sbdata_write_valid_i,
output wire [31:0] sbdata_o,
output wire sbdata_valid_o,
output wire sbbusy_o,
output wire [2:0] sberror_o,
output wire master_req_o,
input wire master_gnt_i,
@ -36,12 +53,147 @@ 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;
assign sbbusy_o = 1'b0;
reg[4:0] state_d, state_q;
reg[2:0] sberror;
reg[3:0] be_mask;
reg[1:0] be_index;
assign master_req_o = 1'b0;
assign master_we_o = 1'b0;
reg master_req;
reg master_we;
reg[3:0] master_be;
reg[31:0] master_addr;
reg[31:0] master_wdata;
reg[31:0] sbaddress;
wire[31:0] sbaddress_new;
assign sbaddress_new = sbaddress_i + (32'h1 << sbaccess_i);
assign sbbusy_o = (state_q != S_IDLE);
always @ (*) begin
be_mask = 4'b0;
be_index = sbaddress_i[1:0];
// generate byte enable mask
case (sbaccess_i)
3'b000: begin
be_mask[be_index] = 1'b1;
end
3'b001: begin
if (be_index == 2'h0) begin
be_mask[1:0] = 2'b11;
end else if (be_index == 2'h2) begin
be_mask[3:2] = 2'b11;
end
end
3'b010: begin
be_mask = 4'b1111;
end
default:;
endcase
end
always @ (*) begin
state_d = state_q;
sbaddress = sbaddress_i;
master_addr = sbaddress_i;
master_wdata = sbdata_i;
master_req = 1'b0;
master_be = 4'b0;
master_we = 1'b0;
sberror = 3'b0;
case (state_q)
S_IDLE: begin
// debugger requested a read
if (sbaddress_write_valid_i && sbreadonaddr_i) begin
state_d = S_READ;
end
// debugger requested a write
if (sbdata_write_valid_i) begin
state_d = S_WRITE;
end
// perform another read
if (sbdata_read_valid_i && sbreadondata_i) begin
state_d = S_READ;
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
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;
end
end
S_WAIT_WRITE: begin
if (master_rvalid_i) begin
state_d = S_IDLE;
if (sbautoincrement_i) begin
sbaddress = sbaddress_new;
end
end
end
default:;
endcase
if ((sbaccess_i > 3'h2) & (state_q != S_IDLE)) begin
master_req = 1'b0;
state_d = S_IDLE;
sberror = 3'h3;
end
end
assign master_req_o = master_req;
assign master_we_o = master_we;
assign master_be_o = master_be;
assign master_addr_o = master_addr;
assign master_wdata_o = master_wdata;
assign sbdata_valid_o = master_rvalid_i;
assign sbdata_o = master_rdata_i;
assign sberror_o = sberror;
assign sbaddress_o = sbaddress;
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
state_q <= S_IDLE;
end else begin
state_q <= state_d;
end
end
endmodule