rtl: jtag: optimization
Signed-off-by: liangkangnan <liangkangnan@163.com>pull/1/head
parent
442e9e8f5c
commit
045f482fe1
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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),
|
||||||
|
|
Loading…
Reference in New Issue