diff --git a/rtl/debug/jtag_dm.v b/rtl/debug/jtag_dm.v index adcb21a..985e62d 100644 --- a/rtl/debug/jtag_dm.v +++ b/rtl/debug/jtag_dm.v @@ -24,70 +24,67 @@ `define DTM_OP_WRITE 2'b10 -module jtag_dm( +module jtag_dm #( + parameter DMI_ADDR_BITS = 6, + parameter DMI_DATA_BITS = 32, + parameter DMI_OP_BITS = 2)( clk, rst_n, - dtm_req_valid, - dtm_req_data, + dtm_req_valid_i, + dtm_req_data_i, - dm_is_busy, - dm_resp_data, + dm_is_busy_o, + dm_resp_data_o, + dm_resp_ready_i, - dm_reg_we, - dm_reg_addr, - dm_reg_wdata, - dm_reg_rdata, - dm_mem_we, - dm_mem_addr, - dm_mem_wdata, - dm_mem_rdata, - dm_op_req, + dm_reg_we_o, + dm_reg_addr_o, + dm_reg_wdata_o, + dm_reg_rdata_i, + dm_mem_we_o, + dm_mem_addr_o, + dm_mem_wdata_o, + dm_mem_rdata_i, + dm_op_req_o, - dm_halt_req, - dm_reset_req + dm_halt_req_o, + dm_reset_req_o ); - parameter DMI_ADDR_BITS = 6; - parameter DMI_DATA_BITS = 32; - parameter DMI_OP_BITS = 2; parameter DM_RESP_BITS = DMI_ADDR_BITS + DMI_DATA_BITS + DMI_OP_BITS; parameter DTM_REQ_BITS = DMI_ADDR_BITS + DMI_DATA_BITS + DMI_OP_BITS; parameter SHIFT_REG_BITS = DTM_REQ_BITS; - // input and output + // 输入输出信号 input wire clk; input wire rst_n; - input wire dtm_req_valid; - input wire[DTM_REQ_BITS - 1:0] dtm_req_data; - output reg dm_is_busy; - output reg[DM_RESP_BITS - 1:0] dm_resp_data; - output reg dm_reg_we; - output reg[4:0] dm_reg_addr; - output reg[31:0] dm_reg_wdata; - input wire[31:0] dm_reg_rdata; - output reg dm_mem_we; - output reg[31:0] dm_mem_addr; - output reg[31:0] dm_mem_wdata; - input wire[31:0] dm_mem_rdata; - output reg dm_op_req; - output reg dm_halt_req; - output reg dm_reset_req; + input wire dtm_req_valid_i; + input wire[DTM_REQ_BITS-1:0] dtm_req_data_i; + output wire dm_is_busy_o; + output wire[DM_RESP_BITS-1:0] dm_resp_data_o; + output wire dm_reg_we_o; + output wire[4:0] dm_reg_addr_o; + output wire[31:0] dm_reg_wdata_o; + input wire[31:0] dm_reg_rdata_i; + output wire dm_mem_we_o; + output wire[31:0] dm_mem_addr_o; + output wire[31:0] dm_mem_wdata_o; + input wire[31:0] dm_mem_rdata_i; + 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 = 2'b0; - localparam STATE_EX = 2'b1; + localparam STATE_IDLE = 3'b001; + localparam STATE_EXE = 3'b010; + localparam STATE_RESP = 3'b100; - reg[1:0] state; - reg[DMI_OP_BITS - 1:0] op; - reg[DMI_DATA_BITS - 1:0] data; - reg[DMI_ADDR_BITS - 1:0] address; - reg[DTM_REQ_BITS - 1:0] req_data; - reg is_halted; - reg is_reseted; - reg is_read_reg; + reg[2:0] state; + reg[2:0] state_next; - // DM regs + // DM模块寄存器 reg[31:0] dcsr; reg[31:0] dmstatus; reg[31:0] dmcontrol; @@ -99,6 +96,7 @@ module jtag_dm( reg[31:0] sbdata0; reg[31:0] command; + // DM模块寄存器地址 localparam DCSR = 16'h7b0; localparam DMSTATUS = 6'h11; localparam DMCONTROL = 6'h10; @@ -113,254 +111,434 @@ module jtag_dm( localparam OP_SUCC = 2'b00; - + // 当前状态切换 always @ (posedge clk or negedge rst_n) begin if (!rst_n) begin state <= STATE_IDLE; - dm_mem_we <= 1'b0; - dm_reg_we <= 1'b0; - dm_resp_data <= {(DM_RESP_BITS){1'b0}}; - dm_is_busy <= 1'b0; - dm_halt_req <= 1'b0; - dm_reset_req <= 1'b0; - dm_mem_addr <= 32'h0; - dm_reg_addr <= 5'h0; - is_halted <= 1'b0; - is_reseted <= 1'b0; - dm_op_req <= 1'b0; - op <= 2'h0; - data <= 32'h0; - sbaddress0 <= 32'h0; - dcsr <= 32'h0; - hartinfo <= 32'h0; - sbcs <= 32'h0; - dmcontrol <= 32'h0; - abstractcs <= 32'h0; - data0 <= 32'h0; - sbdata0 <= 32'h0; - command <= 32'h0; - dm_reg_wdata <= 32'h0; - dm_mem_wdata <= 32'h0; - address <= 6'h0; - dmstatus <= 32'h0; - is_read_reg <= 1'b0; end else begin - if (state == STATE_IDLE) begin - dm_mem_we <= 1'b0; - dm_reg_we <= 1'b0; - dm_reset_req <= 1'b0; - if (dtm_req_valid == `DTM_REQ_VALID) begin - state <= STATE_EX; - op <= dtm_req_data[DMI_OP_BITS - 1:0]; - data <= dtm_req_data[DMI_DATA_BITS + DMI_OP_BITS - 1:DMI_OP_BITS]; - address <= dtm_req_data[DTM_REQ_BITS - 1:DMI_DATA_BITS + DMI_OP_BITS]; - req_data <= dtm_req_data; - dm_is_busy <= 1'b1; - if ((dtm_req_data[DMI_OP_BITS - 1:0] == `DTM_OP_READ && - dtm_req_data[DTM_REQ_BITS - 1:DMI_DATA_BITS + DMI_OP_BITS] == DMSTATUS) || - (dtm_req_data[DMI_OP_BITS - 1:0] == `DTM_OP_NOP)) begin - dm_op_req <= 1'b0; - end else begin - dm_op_req <= 1'b1; - end + 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 - dm_op_req <= 1'b0; + state_next = STATE_IDLE; end - end else begin - case (op) - `DTM_OP_READ: begin - case (address) - DMSTATUS: begin - dm_is_busy <= 1'b0; - state <= STATE_IDLE; - dm_resp_data <= {address, dmstatus, OP_SUCC}; - 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 + endcase + end - DMCONTROL: begin - dm_is_busy <= 1'b0; - state <= STATE_IDLE; - dm_resp_data <= {address, dmcontrol, OP_SUCC}; - end + reg[31:0] mem_rdata; + reg[31:0] reg_rdata; - HARTINFO: begin - dm_is_busy <= 1'b0; - state <= STATE_IDLE; - dm_resp_data <= {address, hartinfo, OP_SUCC}; - end - - SBCS: begin - dm_is_busy <= 1'b0; - state <= STATE_IDLE; - dm_resp_data <= {address, sbcs, OP_SUCC}; - end - - ABSTRACTCS: begin - dm_is_busy <= 1'b0; - state <= STATE_IDLE; - dm_resp_data <= {address, abstractcs, OP_SUCC}; - end - - DATA0: begin - dm_is_busy <= 1'b0; - state <= STATE_IDLE; - if (is_read_reg == 1'b1) begin - dm_resp_data <= {address, dm_reg_rdata, OP_SUCC}; - end else begin - dm_resp_data <= {address, data0, OP_SUCC}; - end - is_read_reg <= 1'b0; - end - - SBDATA0: begin - dm_is_busy <= 1'b0; - state <= STATE_IDLE; - dm_resp_data <= {address, dm_mem_rdata, OP_SUCC}; - if (sbcs[16] == 1'b1) begin - sbaddress0 <= sbaddress0 + 4; - end - if (sbcs[15] == 1'b1) begin - dm_mem_addr <= sbaddress0 + 4; - end - end - - default: begin - dm_is_busy <= 1'b0; - state <= STATE_IDLE; - dm_resp_data <= {{address}, {(DMI_DATA_BITS){1'b0}}, OP_SUCC}; - end - endcase - end - - `DTM_OP_WRITE: begin - 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; - is_halted <= 1'b0; - is_reseted <= 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; - is_halted <= 1'b1; - // clear ALLRUNNING ANYRUNNING and set ALLHALTED - dmstatus <= {dmstatus[31:12], 4'h3, dmstatus[7:0]}; - // resume - end else if (is_halted == 1'b1 && data[30] == 1'b1) begin - dm_halt_req <= 1'b0; - is_halted <= 1'b0; - // set ALLRUNNING ANYRUNNING and clear ALLHALTED - dmstatus <= {dmstatus[31:12], 4'hc, dmstatus[7:0]}; - end - end - dm_is_busy <= 1'b0; - state <= STATE_IDLE; - dm_resp_data <= {{address}, {(DMI_DATA_BITS){1'b0}}, OP_SUCC}; - 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 - // read - if (data[16] == 1'b0) begin - if (data[15:0] == DCSR) begin - data0 <= dcsr; - end else if (data[15:0] < 16'h1020) begin - dm_reg_addr <= data[15:0] - 16'h1000; - 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; - is_halted <= 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_addr <= data[15:0] - 16'h1000; - dm_reg_wdata <= data0; - end - end - end - end - end - dm_is_busy <= 1'b0; - state <= STATE_IDLE; - dm_resp_data <= {{address}, {(DMI_DATA_BITS){1'b0}}, OP_SUCC}; - end - - DATA0: begin - data0 <= data; - dm_is_busy <= 1'b0; - state <= STATE_IDLE; - dm_resp_data <= {{address}, {(DMI_DATA_BITS){1'b0}}, OP_SUCC}; - end - - SBCS: begin - sbcs <= data; - dm_is_busy <= 1'b0; - state <= STATE_IDLE; - dm_resp_data <= {{address}, {(DMI_DATA_BITS){1'b0}}, OP_SUCC}; - end - - SBADDRESS0: begin - sbaddress0 <= data; - if (sbcs[20] == 1'b1) begin - dm_mem_addr <= data; - end - dm_is_busy <= 1'b0; - state <= STATE_IDLE; - dm_resp_data <= {{address}, {(DMI_DATA_BITS){1'b0}}, OP_SUCC}; - end - - 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 + 4; - end - dm_is_busy <= 1'b0; - state <= STATE_IDLE; - dm_resp_data <= {{address}, {(DMI_DATA_BITS){1'b0}}, OP_SUCC}; - end - - default: begin - dm_is_busy <= 1'b0; - state <= STATE_IDLE; - dm_resp_data <= {{address}, {(DMI_DATA_BITS){1'b0}}, OP_SUCC}; - end - endcase - end - - `DTM_OP_NOP: begin - dm_is_busy <= 1'b0; - state <= STATE_IDLE; - dm_resp_data <= {{address}, {(DMI_DATA_BITS){1'b0}}, OP_SUCC}; - end - endcase + 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] dm_mem_addr; + reg[31:0] dm_mem_wdata; + reg dm_mem_we; + + always @ (posedge clk or negedge rst_n) begin + if (!rst_n | dm_reset) begin + dm_mem_addr <= 32'h0; + dm_mem_wdata <= 32'h0; + dm_mem_we <= 1'b0; + end else begin + case (state) + STATE_EXE: begin + if (op_write) begin + case (address) + SBDATA0: begin + dm_mem_addr <= sbaddress0; + dm_mem_wdata <= data; + dm_mem_we <= 1'b1; + end + SBADDRESS0: begin + 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; + end + end + end + end else if (op_read & access_data0) begin + is_read_reg <= 1'b0; + end + end + STATE_IDLE: begin + dm_reg_we <= 1'b0; + end + endcase + 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_is_busy_o = (state != STATE_IDLE); + endmodule diff --git a/rtl/debug/jtag_driver.v b/rtl/debug/jtag_driver.v index cad6a41..69ca93f 100644 --- a/rtl/debug/jtag_driver.v +++ b/rtl/debug/jtag_driver.v @@ -20,7 +20,10 @@ `define DTM_REQ_INVALID 1'b0 -module jtag_driver( +module jtag_driver #( + parameter DMI_ADDR_BITS = 6, + parameter DMI_DATA_BITS = 32, + parameter DMI_OP_BITS = 2)( rst_n, @@ -43,9 +46,6 @@ module jtag_driver( parameter DTM_VERSION = 4'h1; parameter IR_BITS = 5; - parameter DMI_ADDR_BITS = 6; - parameter DMI_DATA_BITS = 32; - parameter DMI_OP_BITS = 2; parameter DM_RESP_BITS = DMI_ADDR_BITS + DMI_DATA_BITS + DMI_OP_BITS; parameter DTM_REQ_BITS = DMI_ADDR_BITS + DMI_DATA_BITS + DMI_OP_BITS; parameter SHIFT_REG_BITS = DTM_REQ_BITS; @@ -100,7 +100,7 @@ module jtag_driver( wire dtm_reset; assign dtm_reset = shift_reg[16]; - assign idcode = {IDCODE_VERSION, IDCODE_PART_NUMBER, IDCODE_MANUFLD, 1'h1}; + assign idcode = {IDCODE_VERSION, IDCODE_PART_NUMBER, IDCODE_MANUFLD, 1'h1}; assign dtmcs = {14'b0, 1'b0, // dmihardreset 1'b0, // dmireset @@ -110,7 +110,7 @@ module jtag_driver( addr_bits, // abits DTM_VERSION}; // version - assign busy_response = {{(DMI_ADDR_BITS + DMI_DATA_BITS){1'b0}}, {(DMI_OP_BITS){1'b1}}}; // op = 2'b11 + assign busy_response = {{(DMI_ADDR_BITS + DMI_DATA_BITS){1'b0}}, {(DMI_OP_BITS){1'b1}}}; // op = 2'b11 assign none_busy_response = dm_resp_data; assign is_busy = sticky_busy | dm_is_busy; assign dmi_stat = is_busy ? 2'b01 : 2'b00; @@ -171,7 +171,7 @@ module jtag_driver( always @(posedge jtag_TCK or negedge rst_n) begin if (!rst_n) begin dtm_req_valid <= `DTM_REQ_INVALID; - dtm_req_data <= 40'h0; + dtm_req_data <= {DTM_REQ_BITS{1'b0}}; end else begin if (jtag_state == UPDATE_DR) begin if (ir_reg == REG_DMI) begin @@ -227,5 +227,4 @@ module jtag_driver( end end - endmodule diff --git a/rtl/debug/jtag_top.v b/rtl/debug/jtag_top.v index 1fcb212..aaf9973 100644 --- a/rtl/debug/jtag_top.v +++ b/rtl/debug/jtag_top.v @@ -17,11 +17,12 @@ `include "../core/defines.v" // JTAG顶层模块 -// 涉及跨时钟域传输,这里采用打两拍的方式进行同步 -module jtag_top( +module jtag_top #( + parameter DMI_ADDR_BITS = 6, + parameter DMI_DATA_BITS = 32, + parameter DMI_OP_BITS = 2)( input wire clk, - input wire jtag_rst_n, input wire jtag_pin_TCK, @@ -29,24 +30,21 @@ module jtag_top( input wire jtag_pin_TDI, output wire jtag_pin_TDO, - output reg reg_we_o, + output wire reg_we_o, output wire[4:0] reg_addr_o, output wire[31:0] reg_wdata_o, input wire[31:0] reg_rdata_i, - output reg mem_we_o, + output wire mem_we_o, output wire[31:0] mem_addr_o, output wire[31:0] mem_wdata_o, input wire[31:0] mem_rdata_i, output wire op_req_o, - output reg halt_req_o, - output reg reset_req_o + output wire halt_req_o, + output wire reset_req_o ); - parameter DMI_ADDR_BITS = 6; - parameter DMI_DATA_BITS = 32; - parameter DMI_OP_BITS = 2; parameter DM_RESP_BITS = DMI_ADDR_BITS + DMI_DATA_BITS + DMI_OP_BITS; parameter DTM_REQ_BITS = DMI_ADDR_BITS + DMI_DATA_BITS + DMI_OP_BITS; @@ -63,59 +61,69 @@ module jtag_top( wire dm_mem_we_o; wire[31:0] dm_mem_addr_o; wire[31:0] dm_mem_wdata_o; - wire dm_op_req_o; + wire dm_op_req_sync; wire dm_halt_req_o; wire dm_reset_req_o; + wire dm_resp_ready; + wire halt_req_sync; + wire reset_req_sync; - reg tmp_reg_we_o; - reg[4:0] tmp_reg_addr_o; - reg[31:0] tmp_reg_wdata_o; - reg tmp_mem_we_o; - reg[31:0] tmp_mem_addr_o; - reg[31:0] tmp_mem_wdata_o; - reg tmp_op_req_o; - reg tmp_halt_req_o; - reg tmp_reset_req_o; + 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; - assign reg_addr_o = dm_reg_addr_o; - assign reg_wdata_o = dm_reg_wdata_o; - assign mem_addr_o = dm_mem_addr_o; - assign mem_wdata_o = dm_mem_wdata_o; - assign op_req_o = dm_op_req_o; + 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) + ); - // 打第一拍 - always @ (posedge clk) begin - if (!jtag_rst_n) begin - tmp_reg_we_o <= `WriteDisable; - tmp_mem_we_o <= `WriteDisable; - tmp_halt_req_o <= 1'b0; - tmp_reset_req_o <= 1'b0; - end else begin - tmp_reg_we_o <= dm_reg_we_o; - tmp_mem_we_o <= dm_mem_we_o; - tmp_halt_req_o <= dm_halt_req_o; - tmp_reset_req_o <= dm_reset_req_o; - end - end + 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) + ); - // 打第二拍 - always @ (posedge clk) begin - if (!jtag_rst_n) begin - reg_we_o <= `WriteDisable; - mem_we_o <= `WriteDisable; - halt_req_o <= 1'b0; - reset_req_o <= 1'b0; - end else begin - reg_we_o <= tmp_reg_we_o; - mem_we_o <= tmp_mem_we_o; - halt_req_o <= tmp_halt_req_o; - reset_req_o <= tmp_reset_req_o; - end - end + 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 u_jtag_driver( + jtag_driver #( + .DMI_ADDR_BITS(DMI_ADDR_BITS), + .DMI_DATA_BITS(DMI_DATA_BITS), + .DMI_OP_BITS(DMI_OP_BITS) + ) u_jtag_driver( .rst_n(jtag_rst_n), .jtag_TCK(jtag_pin_TCK), .jtag_TDI(jtag_pin_TDI), @@ -127,24 +135,29 @@ module jtag_top( .dtm_req_data(dtm_req_data) ); - jtag_dm u_jtag_dm( + jtag_dm #( + .DMI_ADDR_BITS(DMI_ADDR_BITS), + .DMI_DATA_BITS(DMI_DATA_BITS), + .DMI_OP_BITS(DMI_OP_BITS) + ) u_jtag_dm( .clk(jtag_pin_TCK), .rst_n(jtag_rst_n), - .dtm_req_valid(dtm_req_valid), - .dtm_req_data(dtm_req_data), - .dm_is_busy(dm_is_busy), - .dm_resp_data(dm_resp_data), - .dm_reg_we(dm_reg_we_o), - .dm_reg_addr(dm_reg_addr_o), - .dm_reg_wdata(dm_reg_wdata_o), - .dm_reg_rdata(reg_rdata_i), - .dm_mem_we(dm_mem_we_o), - .dm_mem_addr(dm_mem_addr_o), - .dm_mem_wdata(dm_mem_wdata_o), - .dm_mem_rdata(mem_rdata_i), - .dm_op_req(dm_op_req_o), - .dm_halt_req(dm_halt_req_o), - .dm_reset_req(dm_reset_req_o) + .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_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_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) ); endmodule diff --git a/rtl/soc/tinyriscv_soc_top.v b/rtl/soc/tinyriscv_soc_top.v index 4ed1f86..944c592 100644 --- a/rtl/soc/tinyriscv_soc_top.v +++ b/rtl/soc/tinyriscv_soc_top.v @@ -116,8 +116,6 @@ module tinyriscv_soc_top( // jtag wire jtag_halt_req_o; wire jtag_reset_req_o; - reg jtag_rst; - reg[2:0] jtag_rst_cnt; wire[`RegAddrBus] jtag_reg_addr_o; wire[`RegBus] jtag_reg_data_o; wire jtag_reg_we_o; @@ -337,25 +335,14 @@ module tinyriscv_soc_top( .mem_rdata_i(m3_data_o) ); - // jtag模块复位逻辑 - always @ (posedge clk) begin - if (rst == `RstEnable) begin - jtag_rst <= 1'b1; - jtag_rst_cnt <= 3'h0; - end else begin - if (jtag_rst_cnt < 3'h5) begin - jtag_rst <= ~jtag_rst; - jtag_rst_cnt <= jtag_rst_cnt + 1'b1; - end else begin - jtag_rst <= 1'b1; - end - end - end - // jtag模块例化 - jtag_top u_jtag_top( + jtag_top #( + .DMI_ADDR_BITS(6), + .DMI_DATA_BITS(32), + .DMI_OP_BITS(2) + ) u_jtag_top( .clk(clk), - .jtag_rst_n(jtag_rst), + .jtag_rst_n(rst), .jtag_pin_TCK(jtag_TCK), .jtag_pin_TMS(jtag_TMS), .jtag_pin_TDI(jtag_TDI),