From 4da79b604615ec5867c1f4858f0df75cc174cfe1 Mon Sep 17 00:00:00 2001 From: liangkangnan Date: Mon, 26 Apr 2021 09:48:19 +0800 Subject: [PATCH] debug: add sba module Signed-off-by: liangkangnan --- rtl/debug/jtag_dm.sv | 55 +++++++++++--- rtl/debug/jtag_sba.sv | 162 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 201 insertions(+), 16 deletions(-) diff --git a/rtl/debug/jtag_dm.sv b/rtl/debug/jtag_dm.sv index 9de7be8..daad6c1 100644 --- a/rtl/debug/jtag_dm.sv +++ b/rtl/debug/jtag_dm.sv @@ -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), diff --git a/rtl/debug/jtag_sba.sv b/rtl/debug/jtag_sba.sv index bc97911..be7a3d9 100644 --- a/rtl/debug/jtag_sba.sv +++ b/rtl/debug/jtag_sba.sv @@ -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