From 386ba909bad4ce756586d9edd6af5bd8dd75c36c Mon Sep 17 00:00:00 2001 From: liangkangnan Date: Wed, 23 Sep 2020 21:37:00 +0800 Subject: [PATCH] rtl: jtag: handle DM module in cpu clock domain Signed-off-by: liangkangnan --- rtl/debug/jtag_dm.v | 653 ++++++++++++++-------------------------- rtl/debug/jtag_driver.v | 95 +++++- rtl/debug/jtag_top.v | 113 ++----- 3 files changed, 333 insertions(+), 528 deletions(-) diff --git a/rtl/debug/jtag_dm.v b/rtl/debug/jtag_dm.v index 6463dd0..4a27ca5 100644 --- a/rtl/debug/jtag_dm.v +++ b/rtl/debug/jtag_dm.v @@ -31,12 +31,16 @@ module jtag_dm #( clk, rst_n, + + // rx + dm_ack_o, dtm_req_valid_i, dtm_req_data_i, - dm_is_busy_o, + // tx + dtm_ack_i, dm_resp_data_o, - dm_resp_ready_i, + dm_resp_valid_o, dm_reg_we_o, dm_reg_addr_o, @@ -46,8 +50,8 @@ module jtag_dm #( dm_mem_addr_o, dm_mem_wdata_o, dm_mem_rdata_i, - dm_op_req_o, + dm_op_req_o, dm_halt_req_o, dm_reset_req_o @@ -60,10 +64,12 @@ module jtag_dm #( // 输入输出信号 input wire clk; input wire rst_n; + output wire dm_ack_o; input wire dtm_req_valid_i; input wire[DTM_REQ_BITS-1:0] dtm_req_data_i; - output wire dm_is_busy_o; + input wire dtm_ack_i; output wire[DM_RESP_BITS-1:0] dm_resp_data_o; + output wire dm_resp_valid_o; output wire dm_reg_we_o; output wire[4:0] dm_reg_addr_o; output wire[31:0] dm_reg_wdata_o; @@ -75,14 +81,6 @@ module jtag_dm #( output wire dm_op_req_o; output wire dm_halt_req_o; output wire dm_reset_req_o; - input wire dm_resp_ready_i; - - localparam STATE_IDLE = 3'b001; - localparam STATE_EXE = 3'b010; - localparam STATE_RESP = 3'b100; - - reg[2:0] state; - reg[2:0] state_next; // DM模块寄存器 reg[31:0] dcsr; @@ -97,451 +95,248 @@ module jtag_dm #( reg[31:0] command; // DM模块寄存器地址 - localparam DCSR = 16'h7b0; - localparam DMSTATUS = 6'h11; - localparam DMCONTROL = 6'h10; - localparam HARTINFO = 6'h12; + localparam DCSR = 16'h7b0; + localparam DMSTATUS = 6'h11; + localparam DMCONTROL = 6'h10; + localparam HARTINFO = 6'h12; localparam ABSTRACTCS = 6'h16; - localparam DATA0 = 6'h04; - localparam SBCS = 6'h38; + localparam DATA0 = 6'h04; + localparam SBCS = 6'h38; localparam SBADDRESS0 = 6'h39; - localparam SBDATA0 = 6'h3C; - localparam COMMAND = 6'h17; - localparam DPC = 16'h7b1; + localparam SBDATA0 = 6'h3C; + localparam COMMAND = 6'h17; + localparam DPC = 16'h7b1; localparam OP_SUCC = 2'b00; - // 当前状态切换 - always @ (posedge clk or negedge rst_n) begin - if (!rst_n) begin - state <= STATE_IDLE; - end else begin - state <= state_next; - end - end - - // 下一个状态切换 - always @ (*) begin - case (state) - STATE_IDLE: begin - if (dtm_req_valid_i == `DTM_REQ_VALID) begin - state_next = STATE_EXE; - end else begin - state_next = STATE_IDLE; - end - end - STATE_EXE: begin - if (access_core) begin - state_next = STATE_RESP; - end else begin - state_next = STATE_IDLE; - end - end - STATE_RESP: begin - if (dm_resp_ready_i == 1'b1) begin - state_next = STATE_IDLE; - end else begin - state_next = STATE_RESP; - end - end - default: begin - state_next = STATE_IDLE; - end - endcase - end - - reg[31:0] mem_rdata; - reg[31:0] reg_rdata; - - always @ (posedge clk or negedge rst_n) begin - if (!rst_n) begin - mem_rdata <= 32'h0; - reg_rdata <= 32'h0; - end else begin - if (state == STATE_RESP && dm_resp_ready_i == 1'b1) begin - mem_rdata <= dm_mem_rdata_i; - reg_rdata <= dm_reg_rdata_i; - end - end - end - - reg[DTM_REQ_BITS-1:0] dtm_req_data; - - // 锁存jtag_dirver模块传过来的数据 - always @ (posedge clk or negedge rst_n) begin - if (!rst_n) begin - dtm_req_data <= {DTM_REQ_BITS{1'b0}}; - end else begin - if ((state == STATE_IDLE) && (dtm_req_valid_i == `DTM_REQ_VALID)) begin - dtm_req_data <= dtm_req_data_i; - end - end - end - - wire[DMI_OP_BITS-1:0] op = dtm_req_data[DMI_OP_BITS-1:0]; - wire[DMI_DATA_BITS-1:0] data = dtm_req_data[DMI_DATA_BITS+DMI_OP_BITS-1:DMI_OP_BITS]; - wire[DMI_ADDR_BITS-1:0] address = dtm_req_data[DTM_REQ_BITS-1:DMI_DATA_BITS+DMI_OP_BITS]; - - wire op_write = (op == `DTM_OP_WRITE); - wire op_read = (op == `DTM_OP_READ); - wire op_nop = (op == `DTM_OP_NOP); - wire access_dmstatus = (address == DMSTATUS); - wire access_dmcontrol = (address == DMCONTROL); - wire access_hartinfo = (address == HARTINFO); - wire access_abstractcs = (address == ABSTRACTCS); - wire access_data0 = (address == DATA0); - wire access_sbcs = (address == SBCS); - wire access_sbaddress0 = (address == SBADDRESS0); - wire access_sbdata0 = (address == SBDATA0); - wire access_command = (address == COMMAND); - - wire access_core = (~op_nop) & (~access_dmcontrol) & (~access_dmstatus) & (~access_hartinfo); - - reg dm_op_req; - - always @ (posedge clk or negedge rst_n) begin - if (!rst_n) begin - dm_op_req <= 1'b0; - end else begin - case (state) - STATE_EXE: begin - if (access_core) begin - dm_op_req <= 1'b1; - end - end - STATE_IDLE: begin - dm_op_req <= 1'b0; - end - endcase - end - end - - assign dm_op_req_o = dm_op_req; - - reg[31:0] rdata; - // 返回数据给jtag driver模块 - always @ (posedge clk or negedge rst_n) begin - if (!rst_n) begin - rdata <= 32'h0; - end else begin - case (state) - STATE_EXE: begin - case (op) - `DTM_OP_READ: begin - case (address) - DMSTATUS: begin - rdata <= dmstatus; - end - DMCONTROL: begin - rdata <= dmcontrol; - end - HARTINFO: begin - rdata <= 32'h0; - end - SBCS: begin - rdata <= sbcs; - end - ABSTRACTCS: begin - rdata <= abstractcs; - end - DATA0: begin - if (is_read_reg == 1'b1) begin - rdata <= reg_rdata; - end else begin - rdata <= data0; - end - end - SBDATA0: begin - rdata <= mem_rdata; - end - default: begin - rdata <= 32'h0; - end - endcase - end - default: begin - rdata <= 32'h0; - end - endcase - end - endcase - end - end - - assign dm_resp_data_o = {address, rdata, OP_SUCC}; - - wire dm_reset = (state == STATE_EXE) & op_write & (access_dmcontrol) & (data[0] == 1'b0); - - // dmcontrol - always @ (posedge clk or negedge rst_n) begin - if (!rst_n) begin - dmcontrol <= 32'h0; - end else if (dm_reset) begin - dmcontrol <= data; - end else begin - case (state) - STATE_EXE: begin - if (op_write & access_dmcontrol) begin - dmcontrol <= (data & ~(32'h3fffc0)) | 32'h10000; - end - end - default: begin - - end - endcase - end - end - - // dmstatus - always @ (posedge clk or negedge rst_n) begin - if (!rst_n | dm_reset) begin - dmstatus <= 32'h430c82; // not halted, all running - end else begin - case (state) - STATE_EXE: begin - if (op_write & access_dmcontrol) begin - // halt - if (data[31] == 1'b1) begin - // clear ALLRUNNING ANYRUNNING and set ALLHALTED - dmstatus <= {dmstatus[31:12], 4'h3, dmstatus[7:0]}; - // resume - end else if (dm_halt_req == 1'b1 && data[30] == 1'b1) begin - // set ALLRUNNING ANYRUNNING and clear ALLHALTED - dmstatus <= {dmstatus[31:12], 4'hc, dmstatus[7:0]}; - end - end else if (core_reset) begin - // set ALLRUNNING ANYRUNNING and clear ALLHALTED - dmstatus <= {dmstatus[31:12], 4'hc, dmstatus[7:0]}; - end - end - default: begin - - end - endcase - end - end - - wire access_reg = (data[31:24] == 8'h0); - - // command - always @ (posedge clk or negedge rst_n) begin - if (!rst_n | dm_reset) begin - abstractcs <= 32'h1000003; - end else begin - case (state) - STATE_EXE: begin - if (op_write & access_command & access_reg) begin - if (data[22:20] > 3'h2) begin - abstractcs <= abstractcs | 32'h200; - end else begin - abstractcs <= abstractcs & (~(3'h7 << 8)); - end - end - end - default: begin - - end - endcase - end - end - - // data0 - always @ (posedge clk or negedge rst_n) begin - if (!rst_n | dm_reset) begin - data0 <= 32'h0; - end else begin - case (state) - STATE_EXE: begin - if (op_write & access_data0) begin - data0 <= data; - end - end - default: begin - - end - endcase - end - end - - // sbcs - always @ (posedge clk or negedge rst_n) begin - if (!rst_n | dm_reset) begin - sbcs <= 32'h20040404; - end else begin - case (state) - STATE_EXE: begin - if (op_write & access_sbcs) begin - sbcs <= data; - end - end - default: begin - - end - endcase - end - end - - // sbaddress0 - always @ (posedge clk or negedge rst_n) begin - if (!rst_n | dm_reset) begin - sbaddress0 <= 32'h0; - end else begin - case (state) - STATE_EXE: begin - if (op_write & access_sbaddress0) begin - sbaddress0 <= data; - end - if ((op_write | op_read) & access_sbdata0 & (sbcs[16] == 1'b1)) begin - sbaddress0 <= sbaddress0 + 4; - end - end - default: begin - - end - endcase - end - end - - // sbdata0 - always @ (posedge clk or negedge rst_n) begin - if (!rst_n | dm_reset) begin - sbdata0 <= 32'h0; - end else begin - case (state) - STATE_EXE: begin - if (op_write & access_sbdata0) begin - sbdata0 <= data; - end - end - default: begin - - end - endcase - end - end - - reg dm_halt_req; - - // dm_halt_req - always @ (posedge clk or negedge rst_n) begin - if (!rst_n | dm_reset) begin - dm_halt_req <= 1'b0; - end else begin - case (state) - STATE_EXE: begin - if (op_write & access_dmcontrol) begin - // halt - if (data[31] == 1'b1) begin - dm_halt_req <= 1'b1; - // resume - end else if ((dm_halt_req == 1'b1) && (data[30] == 1'b1)) begin - dm_halt_req <= 1'b0; - end - end else if (core_reset) begin - dm_halt_req <= 1'b0; - end - end - default: begin - - end - endcase - end - end - - assign dm_halt_req_o = dm_halt_req; - - wire core_reset = (state == STATE_EXE) & op_write & access_command & access_reg & (data[22:20] <= 3'h2) & - (data[18] == 1'b0) & (data[16] == 1'b1) & (data[15:0] == DPC); - - assign dm_reset_req_o = core_reset; - + reg[31:0] read_data; + reg dm_reg_we; + reg[4:0] dm_reg_addr; + reg[31:0] dm_reg_wdata; + reg dm_mem_we; reg[31:0] dm_mem_addr; reg[31:0] dm_mem_wdata; - reg dm_mem_we; + reg dm_halt_req; + reg dm_reset_req; + reg need_resp; + reg is_read_reg; + wire rx_valid; + wire[DTM_REQ_BITS-1:0] rx_data; + + wire[31:0] sbaddress0_next = sbaddress0 + 4; + wire[DM_RESP_BITS-1:0] dm_resp_data; + + wire[DMI_OP_BITS-1:0] op = rx_data[DMI_OP_BITS-1:0]; + wire[DMI_DATA_BITS-1:0] data = rx_data[DMI_DATA_BITS+DMI_OP_BITS-1:DMI_OP_BITS]; + wire[DMI_ADDR_BITS-1:0] address = rx_data[DTM_REQ_BITS-1:DMI_DATA_BITS+DMI_OP_BITS]; + + wire read_dmstatus = (op == `DTM_OP_READ) & (address == DMSTATUS); always @ (posedge clk or negedge rst_n) begin - if (!rst_n | dm_reset) begin - dm_mem_addr <= 32'h0; - dm_mem_wdata <= 32'h0; + if (!rst_n) begin dm_mem_we <= 1'b0; + dm_reg_we <= 1'b0; + dm_halt_req <= 1'b0; + dm_reset_req <= 1'b0; + dm_mem_addr <= 32'h0; + dm_reg_addr <= 5'h0; + sbaddress0 <= 32'h0; + dcsr <= 32'h0; + hartinfo <= 32'h0; + sbcs <= 32'h20040404; + dmcontrol <= 32'h0; + abstractcs <= 32'h1000003; + data0 <= 32'h0; + sbdata0 <= 32'h0; + command <= 32'h0; + dm_reg_wdata <= 32'h0; + dm_mem_wdata <= 32'h0; + dmstatus <= 32'h430c82; + is_read_reg <= 1'b0; + read_data <= 32'h0; + need_resp <= 1'b0; end else begin - case (state) - STATE_EXE: begin - if (op_write) begin + if (rx_valid) begin + need_resp <= 1'b1; + case (op) + `DTM_OP_READ: begin case (address) + DMSTATUS: begin + read_data <= dmstatus; + end + DMCONTROL: begin + read_data <= dmcontrol; + end + HARTINFO: begin + read_data <= hartinfo; + end + SBCS: begin + read_data <= sbcs; + end + ABSTRACTCS: begin + read_data <= abstractcs; + end + DATA0: begin + if (is_read_reg == 1'b1) begin + read_data <= dm_reg_rdata_i; + end else begin + read_data <= data0; + end + is_read_reg <= 1'b0; + end SBDATA0: begin - dm_mem_addr <= sbaddress0; - dm_mem_wdata <= data; - dm_mem_we <= 1'b1; + read_data <= dm_mem_rdata_i; + if (sbcs[16] == 1'b1) begin + sbaddress0 <= sbaddress0_next; + end + if (sbcs[15] == 1'b1) begin + dm_mem_addr <= sbaddress0_next; + end + end + default: begin + read_data <= {(DMI_DATA_BITS){1'b0}}; + end + endcase + end + + `DTM_OP_WRITE: begin + read_data <= {(DMI_DATA_BITS){1'b0}}; + case (address) + DMCONTROL: begin + // reset DM module + if (data[0] == 1'b0) begin + dcsr <= 32'hc0; + dmstatus <= 32'h430c82; // not halted, all running + hartinfo <= 32'h0; + sbcs <= 32'h20040404; + abstractcs <= 32'h1000003; + dmcontrol <= data; + dm_halt_req <= 1'b0; + dm_reset_req <= 1'b0; + // DM is active + end else begin + // we have only one hart + dmcontrol <= (data & ~(32'h3fffc0)) | 32'h10000; + // halt + if (data[31] == 1'b1) begin + dm_halt_req <= 1'b1; + // clear ALLRUNNING ANYRUNNING and set ALLHALTED + dmstatus <= {dmstatus[31:12], 4'h3, dmstatus[7:0]}; + // resume + end else if (dm_halt_req == 1'b1 && data[30] == 1'b1) begin + dm_halt_req <= 1'b0; + // set ALLRUNNING ANYRUNNING and clear ALLHALTED + dmstatus <= {dmstatus[31:12], 4'hc, dmstatus[7:0]}; + end + end + end + COMMAND: begin + // access reg + if (data[31:24] == 8'h0) begin + if (data[22:20] > 3'h2) begin + abstractcs <= abstractcs | (1'b1 << 9); + end else begin + abstractcs <= abstractcs & (~(3'h7 << 8)); + // read or write + if (data[18] == 1'b0) begin + dm_reg_addr <= data[15:0] - 16'h1000; + // read + if (data[16] == 1'b0) begin + if (data[15:0] == DCSR) begin + data0 <= dcsr; + end else if (data[15:0] < 16'h1020) begin + is_read_reg <= 1'b1; + end + // write + end else begin + // when write dpc, we reset cpu here + if (data[15:0] == DPC) begin + dm_reset_req <= 1'b1; + dm_halt_req <= 1'b0; + dmstatus <= {dmstatus[31:12], 4'hc, dmstatus[7:0]}; + end else if (data[15:0] < 16'h1020) begin + dm_reg_we <= 1'b1; + dm_reg_wdata <= data0; + end + end + end + end + end + end + DATA0: begin + data0 <= data; + end + SBCS: begin + sbcs <= data; end SBADDRESS0: begin + sbaddress0 <= data; if (sbcs[20] == 1'b1) begin dm_mem_addr <= data; end end - endcase - end else if (op_read) begin - if (access_sbdata0 & (sbcs[15] == 1'b1)) begin - dm_mem_addr <= sbaddress0 + 4; - end - end - end - STATE_IDLE: begin - dm_mem_we <= 1'b0; - end - endcase - end - end - - assign dm_mem_addr_o = dm_mem_addr; - assign dm_mem_wdata_o = dm_mem_wdata; - assign dm_mem_we_o = dm_mem_we; - - reg dm_reg_we; - reg[4:0] dm_reg_addr; - reg[31:0] dm_reg_wdata; - reg is_read_reg; - - always @ (posedge clk or negedge rst_n) begin - if (!rst_n | dm_reset) begin - dm_reg_we <= 1'b0; - dm_reg_addr <= 5'h0; - dm_reg_wdata <= 32'h0; - is_read_reg <= 1'b0; - end else begin - case (state) - STATE_EXE: begin - if (op_write & access_command) begin - // 访问寄存器 - if (access_reg & (data[22:20] <= 3'h2)) begin - // 读或写, 目前只支持通用寄存器读写 - if ((data[18] == 1'b0) & (data[15:0] < 16'h1020) & (data[15:0] != DPC)) begin - dm_reg_addr <= data[15:0] - 16'h1000; - // 读 - if (data[16] == 1'b0) begin - is_read_reg <= 1'b1; - // 写 - end else begin - dm_reg_we <= 1'b1; - dm_reg_wdata <= data0; + SBDATA0: begin + sbdata0 <= data; + dm_mem_addr <= sbaddress0; + dm_mem_wdata <= data; + dm_mem_we <= 1'b1; + if (sbcs[16] == 1'b1) begin + sbaddress0 <= sbaddress0_next; end end - end - end else if (op_read & access_data0) begin - is_read_reg <= 1'b0; + endcase end - end - STATE_IDLE: begin - dm_reg_we <= 1'b0; - end - endcase + + `DTM_OP_NOP: begin + read_data <= {(DMI_DATA_BITS){1'b0}}; + end + endcase + end else begin + need_resp <= 1'b0; + dm_mem_we <= 1'b0; + dm_reg_we <= 1'b0; + dm_reset_req <= 1'b0; + end end end assign dm_reg_we_o = dm_reg_we; assign dm_reg_addr_o = dm_reg_addr; assign dm_reg_wdata_o = dm_reg_wdata; + assign dm_mem_we_o = dm_mem_we; + assign dm_mem_addr_o = dm_mem_addr; + assign dm_mem_wdata_o = dm_mem_wdata; - assign dm_is_busy_o = (state != STATE_IDLE); + assign dm_op_req_o = (rx_valid & (~read_dmstatus)) | need_resp; + assign dm_halt_req_o = dm_halt_req; + assign dm_reset_req_o = dm_reset_req; + + assign dm_resp_data = {address, read_data, OP_SUCC}; + + + full_handshake_tx #( + .DW(DM_RESP_BITS) + ) tx( + .clk(clk), + .rst_n(rst_n), + .ack_i(dtm_ack_i), + .req_i(need_resp), + .req_data_i(dm_resp_data), + .idle_o(tx_idle), + .req_o(dm_resp_valid_o), + .req_data_o(dm_resp_data_o) + ); + + full_handshake_rx #( + .DW(DTM_REQ_BITS) + ) rx( + .clk(clk), + .rst_n(rst_n), + .req_i(dtm_req_valid_i), + .req_data_i(dtm_req_data_i), + .ack_o(dm_ack_o), + .recv_data_o(rx_data), + .recv_rdy_o(rx_valid) + ); endmodule diff --git a/rtl/debug/jtag_driver.v b/rtl/debug/jtag_driver.v index 69ca93f..64c60a9 100644 --- a/rtl/debug/jtag_driver.v +++ b/rtl/debug/jtag_driver.v @@ -32,10 +32,15 @@ module jtag_driver #( jtag_TMS, jtag_TDO, - dm_is_busy, - dm_resp_data, - dtm_req_valid, - dtm_req_data + // rx + dm_resp_i, + dm_resp_data_i, + dtm_ack_o, + + // tx + dm_ack_i, + dtm_req_valid_o, + dtm_req_data_o ); @@ -56,10 +61,12 @@ module jtag_driver #( input wire jtag_TDI; input wire jtag_TMS; output reg jtag_TDO; - input wire dm_is_busy; - input wire[DM_RESP_BITS - 1:0] dm_resp_data; - output reg dtm_req_valid; - output reg[DTM_REQ_BITS - 1:0] dtm_req_data; + input wire dm_resp_i; + input wire[DM_RESP_BITS - 1:0] dm_resp_data_i; + output wire dtm_ack_o; + input wire dm_ack_i; + output wire dtm_req_valid_o; + output wire[DTM_REQ_BITS - 1:0] dtm_req_data_o; // JTAG StateMachine parameter TEST_LOGIC_RESET = 4'h0; @@ -90,6 +97,10 @@ module jtag_driver #( reg[3:0] jtag_state; wire is_busy; reg sticky_busy; + reg dtm_req_valid; + reg[DTM_REQ_BITS - 1:0] dtm_req_data; + reg[DM_RESP_BITS - 1:0] dm_resp_data; + reg dm_is_busy; wire[5:0] addr_bits = DMI_ADDR_BITS[5:0]; wire [SHIFT_REG_BITS - 1:0] busy_response; @@ -98,6 +109,11 @@ module jtag_driver #( wire[31:0] dtmcs; wire[1:0] dmi_stat; wire dtm_reset; + wire tx_idle; + wire rx_valid; + wire[DM_RESP_BITS - 1:0] rx_data; + wire tx_valid; + wire[DTM_REQ_BITS - 1:0] tx_data; assign dtm_reset = shift_reg[16]; assign idcode = {IDCODE_VERSION, IDCODE_PART_NUMBER, IDCODE_MANUFLD, 1'h1}; @@ -176,28 +192,28 @@ module jtag_driver #( if (jtag_state == UPDATE_DR) begin if (ir_reg == REG_DMI) begin // if DM can be access - if (!is_busy) begin + if (!is_busy & tx_idle) begin dtm_req_valid <= `DTM_REQ_VALID; dtm_req_data <= shift_reg; end end - end - if (is_busy) begin + end else begin dtm_req_valid <= `DTM_REQ_INVALID; end end end + assign tx_valid = dtm_req_valid; + assign tx_data = dtm_req_data; + // DTM reset always @ (posedge jtag_TCK or negedge rst_n) begin if (!rst_n) begin sticky_busy <= 1'b0; end else begin if (jtag_state == UPDATE_DR) begin - if (ir_reg == REG_DTMCS) begin - if (dtm_reset) begin - sticky_busy <= 1'b0; - end + if (ir_reg == REG_DTMCS & dtm_reset) begin + sticky_busy <= 1'b0; end end else if (jtag_state == CAPTURE_DR) begin if (ir_reg == REG_DMI) begin @@ -207,6 +223,30 @@ module jtag_driver #( end end + // receive DM response data + always @ (posedge jtag_TCK or negedge rst_n) begin + if (!rst_n) begin + dm_resp_data <= {DM_RESP_BITS{1'b0}}; + end else begin + if (rx_valid) begin + dm_resp_data <= rx_data; + end + end + end + + // tx busy + always @ (posedge jtag_TCK or negedge rst_n) begin + if (!rst_n) begin + dm_is_busy <= 1'b0; + end else begin + if (dtm_req_valid) begin + dm_is_busy <= 1'b1; + end else if (rx_valid) begin + dm_is_busy <= 1'b0; + end + end + end + // TAP reset always @(negedge jtag_TCK) begin if (jtag_state == TEST_LOGIC_RESET) begin @@ -227,4 +267,29 @@ module jtag_driver #( end end + full_handshake_tx #( + .DW(DTM_REQ_BITS) + ) tx( + .clk(jtag_TCK), + .rst_n(rst_n), + .ack_i(dm_ack_i), + .req_i(tx_valid), + .req_data_i(tx_data), + .idle_o(tx_idle), + .req_o(dtm_req_valid_o), + .req_data_o(dtm_req_data_o) + ); + + full_handshake_rx #( + .DW(DM_RESP_BITS) + ) rx( + .clk(jtag_TCK), + .rst_n(rst_n), + .req_i(dm_resp_i), + .req_data_i(dm_resp_data_i), + .ack_o(dtm_ack_o), + .recv_data_o(rx_data), + .recv_rdy_o(rx_valid) + ); + endmodule diff --git a/rtl/debug/jtag_top.v b/rtl/debug/jtag_top.v index aaf9973..cc6253a 100644 --- a/rtl/debug/jtag_top.v +++ b/rtl/debug/jtag_top.v @@ -49,75 +49,17 @@ module jtag_top #( parameter DTM_REQ_BITS = DMI_ADDR_BITS + DMI_DATA_BITS + DMI_OP_BITS; // jtag_driver - wire dtm_req_valid; - wire[DTM_REQ_BITS - 1:0] dtm_req_data; + wire dtm_ack_o; + wire dtm_req_valid_o; + wire[DTM_REQ_BITS - 1:0] dtm_req_data_o; // jtag_dm - wire dm_is_busy; - wire[DM_RESP_BITS - 1:0] dm_resp_data; - wire dm_reg_we_o; - wire[4:0] dm_reg_addr_o; - wire[31:0] dm_reg_wdata_o; - wire dm_mem_we_o; - wire[31:0] dm_mem_addr_o; - wire[31:0] dm_mem_wdata_o; - wire dm_op_req_sync; + wire dm_ack_o; + wire[DM_RESP_BITS-1:0] dm_resp_data_o; + wire dm_resp_valid_o; + wire dm_op_req_o; wire dm_halt_req_o; wire dm_reset_req_o; - wire dm_resp_ready; - wire halt_req_sync; - wire reset_req_sync; - - assign reg_addr_o = dm_op_req_sync? dm_reg_addr_o: 5'h0; - assign reg_wdata_o = dm_op_req_sync? dm_reg_wdata_o: 32'h0; - assign reg_we_o = dm_op_req_sync? dm_reg_we_o: 1'b0; - assign mem_addr_o = dm_op_req_sync? dm_mem_addr_o: 32'h0; - assign mem_wdata_o = dm_op_req_sync? dm_mem_wdata_o: 32'h0; - assign mem_we_o = dm_op_req_sync? dm_mem_we_o: 1'b0; - assign halt_req_o = halt_req_sync; - assign reset_req_o = reset_req_sync; - - assign op_req_o = dm_op_req_sync; - - gen_ticks_sync #( - .DW(1), - .DP(2) - ) u_halt_sync_o( - .rst(jtag_rst_n), - .clk(clk), - .din(dm_halt_req_o), - .dout(halt_req_sync) - ); - - gen_ticks_sync #( - .DW(1), - .DP(2) - ) u_reset_sync_o( - .rst(jtag_rst_n), - .clk(clk), - .din(dm_reset_req_o), - .dout(reset_req_sync) - ); - - gen_ticks_sync #( - .DW(1), - .DP(2) - ) u_jtag_sync_o( - .rst(jtag_rst_n), - .clk(clk), - .din(dm_op_req_o), - .dout(dm_op_req_sync) - ); - - gen_ticks_sync #( - .DW(1), - .DP(2) - ) u_jtag_sync_i( - .rst(jtag_rst_n), - .clk(jtag_pin_TCK), - .din(dm_op_req_sync), - .dout(dm_resp_ready) - ); jtag_driver #( .DMI_ADDR_BITS(DMI_ADDR_BITS), @@ -129,10 +71,12 @@ module jtag_top #( .jtag_TDI(jtag_pin_TDI), .jtag_TMS(jtag_pin_TMS), .jtag_TDO(jtag_pin_TDO), - .dm_is_busy(dm_is_busy), - .dm_resp_data(dm_resp_data), - .dtm_req_valid(dtm_req_valid), - .dtm_req_data(dtm_req_data) + .dm_resp_i(dm_resp_valid_o), + .dm_resp_data_i(dm_resp_data_o), + .dtm_ack_o(dtm_ack_o), + .dm_ack_i(dm_ack_o), + .dtm_req_valid_o(dtm_req_valid_o), + .dtm_req_data_o(dtm_req_data_o) ); jtag_dm #( @@ -140,24 +84,25 @@ module jtag_top #( .DMI_DATA_BITS(DMI_DATA_BITS), .DMI_OP_BITS(DMI_OP_BITS) ) u_jtag_dm( - .clk(jtag_pin_TCK), + .clk(clk), .rst_n(jtag_rst_n), - .dm_resp_ready_i(dm_resp_ready), - .dtm_req_valid_i(dtm_req_valid), - .dtm_req_data_i(dtm_req_data), - .dm_is_busy_o(dm_is_busy), - .dm_resp_data_o(dm_resp_data), - .dm_reg_we_o(dm_reg_we_o), - .dm_reg_addr_o(dm_reg_addr_o), - .dm_reg_wdata_o(dm_reg_wdata_o), + .dm_ack_o(dm_ack_o), + .dtm_req_valid_i(dtm_req_valid_o), + .dtm_req_data_i(dtm_req_data_o), + .dtm_ack_i(dtm_ack_o), + .dm_resp_data_o(dm_resp_data_o), + .dm_resp_valid_o(dm_resp_valid_o), + .dm_reg_we_o(reg_we_o), + .dm_reg_addr_o(reg_addr_o), + .dm_reg_wdata_o(reg_wdata_o), .dm_reg_rdata_i(reg_rdata_i), - .dm_mem_we_o(dm_mem_we_o), - .dm_mem_addr_o(dm_mem_addr_o), - .dm_mem_wdata_o(dm_mem_wdata_o), + .dm_mem_we_o(mem_we_o), + .dm_mem_addr_o(mem_addr_o), + .dm_mem_wdata_o(mem_wdata_o), .dm_mem_rdata_i(mem_rdata_i), - .dm_op_req_o(dm_op_req_o), - .dm_halt_req_o(dm_halt_req_o), - .dm_reset_req_o(dm_reset_req_o) + .dm_op_req_o(op_req_o), + .dm_halt_req_o(halt_req_o), + .dm_reset_req_o(reset_req_o) ); endmodule