rtl: jtag: optimization

Signed-off-by: liangkangnan <liangkangnan@163.com>
pull/1/head
liangkangnan 2020-09-13 17:47:18 +08:00
parent 442e9e8f5c
commit 045f482fe1
4 changed files with 558 additions and 381 deletions

View File

@ -24,70 +24,67 @@
`define DTM_OP_WRITE 2'b10 `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, clk,
rst_n, rst_n,
dtm_req_valid, dtm_req_valid_i,
dtm_req_data, dtm_req_data_i,
dm_is_busy, dm_is_busy_o,
dm_resp_data, dm_resp_data_o,
dm_resp_ready_i,
dm_reg_we, dm_reg_we_o,
dm_reg_addr, dm_reg_addr_o,
dm_reg_wdata, dm_reg_wdata_o,
dm_reg_rdata, dm_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, dm_mem_rdata_i,
dm_op_req, dm_op_req_o,
dm_halt_req, dm_halt_req_o,
dm_reset_req 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 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 DTM_REQ_BITS = DMI_ADDR_BITS + DMI_DATA_BITS + DMI_OP_BITS;
parameter SHIFT_REG_BITS = DTM_REQ_BITS; parameter SHIFT_REG_BITS = DTM_REQ_BITS;
// input and output //
input wire clk; input wire clk;
input wire rst_n; input wire rst_n;
input wire dtm_req_valid; input wire dtm_req_valid_i;
input wire[DTM_REQ_BITS - 1:0] dtm_req_data; input wire[DTM_REQ_BITS-1:0] dtm_req_data_i;
output reg dm_is_busy; output wire dm_is_busy_o;
output reg[DM_RESP_BITS - 1:0] dm_resp_data; output wire[DM_RESP_BITS-1:0] dm_resp_data_o;
output reg dm_reg_we; output wire dm_reg_we_o;
output reg[4:0] dm_reg_addr; output wire[4:0] dm_reg_addr_o;
output reg[31:0] dm_reg_wdata; output wire[31:0] dm_reg_wdata_o;
input wire[31:0] dm_reg_rdata; input wire[31:0] dm_reg_rdata_i;
output reg dm_mem_we; output wire dm_mem_we_o;
output reg[31:0] dm_mem_addr; output wire[31:0] dm_mem_addr_o;
output reg[31:0] dm_mem_wdata; output wire[31:0] dm_mem_wdata_o;
input wire[31:0] dm_mem_rdata; input wire[31:0] dm_mem_rdata_i;
output reg dm_op_req; output wire dm_op_req_o;
output reg dm_halt_req; output wire dm_halt_req_o;
output reg dm_reset_req; output wire dm_reset_req_o;
input wire dm_resp_ready_i;
localparam STATE_IDLE = 2'b0; localparam STATE_IDLE = 3'b001;
localparam STATE_EX = 2'b1; localparam STATE_EXE = 3'b010;
localparam STATE_RESP = 3'b100;
reg[1:0] state; reg[2:0] state;
reg[DMI_OP_BITS - 1:0] op; reg[2:0] state_next;
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;
// DM regs // DM
reg[31:0] dcsr; reg[31:0] dcsr;
reg[31:0] dmstatus; reg[31:0] dmstatus;
reg[31:0] dmcontrol; reg[31:0] dmcontrol;
@ -99,6 +96,7 @@ module jtag_dm(
reg[31:0] sbdata0; reg[31:0] sbdata0;
reg[31:0] command; reg[31:0] command;
// DM
localparam DCSR = 16'h7b0; localparam DCSR = 16'h7b0;
localparam DMSTATUS = 6'h11; localparam DMSTATUS = 6'h11;
localparam DMCONTROL = 6'h10; localparam DMCONTROL = 6'h10;
@ -113,254 +111,434 @@ module jtag_dm(
localparam OP_SUCC = 2'b00; localparam OP_SUCC = 2'b00;
//
always @ (posedge clk or negedge rst_n) begin always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin if (!rst_n) begin
state <= STATE_IDLE; 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 end else begin
if (state == STATE_IDLE) begin state <= state_next;
dm_mem_we <= 1'b0; end
dm_reg_we <= 1'b0; end
dm_reset_req <= 1'b0;
if (dtm_req_valid == `DTM_REQ_VALID) begin //
state <= STATE_EX; always @ (*) begin
op <= dtm_req_data[DMI_OP_BITS - 1:0]; case (state)
data <= dtm_req_data[DMI_DATA_BITS + DMI_OP_BITS - 1:DMI_OP_BITS]; STATE_IDLE: begin
address <= dtm_req_data[DTM_REQ_BITS - 1:DMI_DATA_BITS + DMI_OP_BITS]; if (dtm_req_valid_i == `DTM_REQ_VALID) begin
req_data <= dtm_req_data; state_next = STATE_EXE;
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
end else begin end else begin
dm_op_req <= 1'b0; state_next = STATE_IDLE;
end end
end else begin end
case (op) STATE_EXE: begin
`DTM_OP_READ: begin if (access_core) begin
case (address) state_next = STATE_RESP;
DMSTATUS: begin end else begin
dm_is_busy <= 1'b0; state_next = STATE_IDLE;
state <= STATE_IDLE; end
dm_resp_data <= {address, dmstatus, OP_SUCC}; 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 reg[31:0] mem_rdata;
dm_is_busy <= 1'b0; reg[31:0] reg_rdata;
state <= STATE_IDLE;
dm_resp_data <= {address, dmcontrol, OP_SUCC};
end
HARTINFO: begin always @ (posedge clk or negedge rst_n) begin
dm_is_busy <= 1'b0; if (!rst_n) begin
state <= STATE_IDLE; mem_rdata <= 32'h0;
dm_resp_data <= {address, hartinfo, OP_SUCC}; reg_rdata <= 32'h0;
end end else begin
if (state == STATE_RESP && dm_resp_ready_i == 1'b1) begin
SBCS: begin mem_rdata <= dm_mem_rdata_i;
dm_is_busy <= 1'b0; reg_rdata <= dm_reg_rdata_i;
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
end end
end 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 endmodule

View File

@ -20,7 +20,10 @@
`define DTM_REQ_INVALID 1'b0 `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, rst_n,
@ -43,9 +46,6 @@ module jtag_driver(
parameter DTM_VERSION = 4'h1; parameter DTM_VERSION = 4'h1;
parameter IR_BITS = 5; 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 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 DTM_REQ_BITS = DMI_ADDR_BITS + DMI_DATA_BITS + DMI_OP_BITS;
parameter SHIFT_REG_BITS = DTM_REQ_BITS; parameter SHIFT_REG_BITS = DTM_REQ_BITS;
@ -100,7 +100,7 @@ module jtag_driver(
wire dtm_reset; wire dtm_reset;
assign dtm_reset = shift_reg[16]; 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, assign dtmcs = {14'b0,
1'b0, // dmihardreset 1'b0, // dmihardreset
1'b0, // dmireset 1'b0, // dmireset
@ -110,7 +110,7 @@ module jtag_driver(
addr_bits, // abits addr_bits, // abits
DTM_VERSION}; // version 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 none_busy_response = dm_resp_data;
assign is_busy = sticky_busy | dm_is_busy; assign is_busy = sticky_busy | dm_is_busy;
assign dmi_stat = is_busy ? 2'b01 : 2'b00; 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 always @(posedge jtag_TCK or negedge rst_n) begin
if (!rst_n) begin if (!rst_n) begin
dtm_req_valid <= `DTM_REQ_INVALID; dtm_req_valid <= `DTM_REQ_INVALID;
dtm_req_data <= 40'h0; dtm_req_data <= {DTM_REQ_BITS{1'b0}};
end else begin end else begin
if (jtag_state == UPDATE_DR) begin if (jtag_state == UPDATE_DR) begin
if (ir_reg == REG_DMI) begin if (ir_reg == REG_DMI) begin
@ -227,5 +227,4 @@ module jtag_driver(
end end
end end
endmodule endmodule

View File

@ -17,11 +17,12 @@
`include "../core/defines.v" `include "../core/defines.v"
// JTAG // 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 clk,
input wire jtag_rst_n, input wire jtag_rst_n,
input wire jtag_pin_TCK, input wire jtag_pin_TCK,
@ -29,24 +30,21 @@ module jtag_top(
input wire jtag_pin_TDI, input wire jtag_pin_TDI,
output wire jtag_pin_TDO, output wire jtag_pin_TDO,
output reg reg_we_o, output wire reg_we_o,
output wire[4:0] reg_addr_o, output wire[4:0] reg_addr_o,
output wire[31:0] reg_wdata_o, output wire[31:0] reg_wdata_o,
input wire[31:0] reg_rdata_i, 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_addr_o,
output wire[31:0] mem_wdata_o, output wire[31:0] mem_wdata_o,
input wire[31:0] mem_rdata_i, input wire[31:0] mem_rdata_i,
output wire op_req_o, output wire op_req_o,
output reg halt_req_o, output wire halt_req_o,
output reg reset_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 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 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 dm_mem_we_o;
wire[31:0] dm_mem_addr_o; wire[31:0] dm_mem_addr_o;
wire[31:0] dm_mem_wdata_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_halt_req_o;
wire dm_reset_req_o; wire dm_reset_req_o;
wire dm_resp_ready;
wire halt_req_sync;
wire reset_req_sync;
reg tmp_reg_we_o; assign reg_addr_o = dm_op_req_sync? dm_reg_addr_o: 5'h0;
reg[4:0] tmp_reg_addr_o; assign reg_wdata_o = dm_op_req_sync? dm_reg_wdata_o: 32'h0;
reg[31:0] tmp_reg_wdata_o; assign reg_we_o = dm_op_req_sync? dm_reg_we_o: 1'b0;
reg tmp_mem_we_o; assign mem_addr_o = dm_op_req_sync? dm_mem_addr_o: 32'h0;
reg[31:0] tmp_mem_addr_o; assign mem_wdata_o = dm_op_req_sync? dm_mem_wdata_o: 32'h0;
reg[31:0] tmp_mem_wdata_o; assign mem_we_o = dm_op_req_sync? dm_mem_we_o: 1'b0;
reg tmp_op_req_o; assign halt_req_o = halt_req_sync;
reg tmp_halt_req_o; assign reset_req_o = reset_req_sync;
reg tmp_reset_req_o;
assign op_req_o = dm_op_req_sync;
assign reg_addr_o = dm_reg_addr_o; gen_ticks_sync #(
assign reg_wdata_o = dm_reg_wdata_o; .DW(1),
assign mem_addr_o = dm_mem_addr_o; .DP(2)
assign mem_wdata_o = dm_mem_wdata_o; ) u_halt_sync_o(
assign op_req_o = dm_op_req_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 #(
always @ (posedge clk) begin .DW(1),
if (!jtag_rst_n) begin .DP(2)
tmp_reg_we_o <= `WriteDisable; ) u_jtag_sync_o(
tmp_mem_we_o <= `WriteDisable; .rst(jtag_rst_n),
tmp_halt_req_o <= 1'b0; .clk(clk),
tmp_reset_req_o <= 1'b0; .din(dm_op_req_o),
end else begin .dout(dm_op_req_sync)
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 #(
always @ (posedge clk) begin .DW(1),
if (!jtag_rst_n) begin .DP(2)
reg_we_o <= `WriteDisable; ) u_jtag_sync_i(
mem_we_o <= `WriteDisable; .rst(jtag_rst_n),
halt_req_o <= 1'b0; .clk(jtag_pin_TCK),
reset_req_o <= 1'b0; .din(dm_op_req_sync),
end else begin .dout(dm_resp_ready)
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
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), .rst_n(jtag_rst_n),
.jtag_TCK(jtag_pin_TCK), .jtag_TCK(jtag_pin_TCK),
.jtag_TDI(jtag_pin_TDI), .jtag_TDI(jtag_pin_TDI),
@ -127,24 +135,29 @@ module jtag_top(
.dtm_req_data(dtm_req_data) .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), .clk(jtag_pin_TCK),
.rst_n(jtag_rst_n), .rst_n(jtag_rst_n),
.dtm_req_valid(dtm_req_valid), .dm_resp_ready_i(dm_resp_ready),
.dtm_req_data(dtm_req_data), .dtm_req_valid_i(dtm_req_valid),
.dm_is_busy(dm_is_busy), .dtm_req_data_i(dtm_req_data),
.dm_resp_data(dm_resp_data), .dm_is_busy_o(dm_is_busy),
.dm_reg_we(dm_reg_we_o), .dm_resp_data_o(dm_resp_data),
.dm_reg_addr(dm_reg_addr_o), .dm_reg_we_o(dm_reg_we_o),
.dm_reg_wdata(dm_reg_wdata_o), .dm_reg_addr_o(dm_reg_addr_o),
.dm_reg_rdata(reg_rdata_i), .dm_reg_wdata_o(dm_reg_wdata_o),
.dm_mem_we(dm_mem_we_o), .dm_reg_rdata_i(reg_rdata_i),
.dm_mem_addr(dm_mem_addr_o), .dm_mem_we_o(dm_mem_we_o),
.dm_mem_wdata(dm_mem_wdata_o), .dm_mem_addr_o(dm_mem_addr_o),
.dm_mem_rdata(mem_rdata_i), .dm_mem_wdata_o(dm_mem_wdata_o),
.dm_op_req(dm_op_req_o), .dm_mem_rdata_i(mem_rdata_i),
.dm_halt_req(dm_halt_req_o), .dm_op_req_o(dm_op_req_o),
.dm_reset_req(dm_reset_req_o) .dm_halt_req_o(dm_halt_req_o),
.dm_reset_req_o(dm_reset_req_o)
); );
endmodule endmodule

View File

@ -116,8 +116,6 @@ module tinyriscv_soc_top(
// jtag // jtag
wire jtag_halt_req_o; wire jtag_halt_req_o;
wire jtag_reset_req_o; wire jtag_reset_req_o;
reg jtag_rst;
reg[2:0] jtag_rst_cnt;
wire[`RegAddrBus] jtag_reg_addr_o; wire[`RegAddrBus] jtag_reg_addr_o;
wire[`RegBus] jtag_reg_data_o; wire[`RegBus] jtag_reg_data_o;
wire jtag_reg_we_o; wire jtag_reg_we_o;
@ -337,25 +335,14 @@ module tinyriscv_soc_top(
.mem_rdata_i(m3_data_o) .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
jtag_top u_jtag_top( jtag_top #(
.DMI_ADDR_BITS(6),
.DMI_DATA_BITS(32),
.DMI_OP_BITS(2)
) u_jtag_top(
.clk(clk), .clk(clk),
.jtag_rst_n(jtag_rst), .jtag_rst_n(rst),
.jtag_pin_TCK(jtag_TCK), .jtag_pin_TCK(jtag_TCK),
.jtag_pin_TMS(jtag_TMS), .jtag_pin_TMS(jtag_TMS),
.jtag_pin_TDI(jtag_TDI), .jtag_pin_TDI(jtag_TDI),