parent
77812d60df
commit
f9412fca3c
|
@ -38,7 +38,8 @@ module csr_reg(
|
|||
output wire[31:0] mepc_o, // mepc寄存器值
|
||||
output wire[31:0] mstatus_o, // mstatus寄存器值
|
||||
output wire[31:0] mie_o, // mie寄存器值
|
||||
output wire[31:0] dpc_o // dpc寄存器值
|
||||
output wire[31:0] dpc_o, // dpc寄存器值
|
||||
output wire[31:0] dcsr_o // dcsr寄存器值
|
||||
|
||||
);
|
||||
|
||||
|
@ -72,6 +73,9 @@ module csr_reg(
|
|||
reg[31:0] dpc_d;
|
||||
wire[31:0] dpc_q;
|
||||
reg dpc_we;
|
||||
reg[31:0] dcsr_d;
|
||||
wire[31:0] dcsr_q;
|
||||
reg dcsr_we;
|
||||
|
||||
reg[63:0] cycle;
|
||||
|
||||
|
@ -90,6 +94,7 @@ module csr_reg(
|
|||
assign mstatus_o = mstatus_q;
|
||||
assign mie_o = mie_q;
|
||||
assign dpc_o = dpc_q;
|
||||
assign dcsr_o = dcsr_q;
|
||||
|
||||
reg[31:0] exu_rdata;
|
||||
|
||||
|
@ -132,6 +137,9 @@ module csr_reg(
|
|||
`CSR_DPC: begin
|
||||
exu_rdata = dpc_q;
|
||||
end
|
||||
`CSR_DCSR: begin
|
||||
exu_rdata = dcsr_q;
|
||||
end
|
||||
default: begin
|
||||
exu_rdata = 32'h0;
|
||||
end
|
||||
|
@ -166,6 +174,8 @@ module csr_reg(
|
|||
mhartid_we = 1'b0;
|
||||
dpc_d = dpc_q;
|
||||
dpc_we = 1'b0;
|
||||
dcsr_d = dcsr_q;
|
||||
dcsr_we = 1'b0;
|
||||
|
||||
if (we) begin
|
||||
case (waddr[11:0])
|
||||
|
@ -209,6 +219,10 @@ module csr_reg(
|
|||
dpc_d = wdata;
|
||||
dpc_we = 1'b1;
|
||||
end
|
||||
`CSR_DCSR: begin
|
||||
dcsr_d = wdata;
|
||||
dcsr_we = 1'b1;
|
||||
end
|
||||
default:;
|
||||
endcase
|
||||
end
|
||||
|
@ -324,4 +338,15 @@ module csr_reg(
|
|||
.rdata_o(dpc_q)
|
||||
);
|
||||
|
||||
// dcsr
|
||||
csr #(
|
||||
.RESET_VAL(32'h0)
|
||||
) dcsr_csr (
|
||||
.clk(clk),
|
||||
.rst_n(rst_n),
|
||||
.wdata_i(dcsr_d),
|
||||
.we_i(dcsr_we),
|
||||
.rdata_o(dcsr_q)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -46,6 +46,7 @@ module exception (
|
|||
input wire[31:0] mstatus_i, // mstatus寄存器
|
||||
input wire[31:0] mie_i, // mie寄存器
|
||||
input wire[31:0] dpc_i, // dpc寄存器
|
||||
input wire[31:0] dcsr_i, // dcsr寄存器
|
||||
|
||||
input wire irq_software_i,
|
||||
input wire irq_timer_i,
|
||||
|
@ -159,7 +160,7 @@ module exception (
|
|||
exception_req = 1'b1;
|
||||
exception_cause = `CAUSE_EXCEP_ECALL_M;
|
||||
exception_offset = ECALL_OFFSET;
|
||||
end else if (inst_ebreak_i) begin
|
||||
end else if (inst_ebreak_i & (!dcsr_i[15])) begin
|
||||
exception_req = 1'b1;
|
||||
exception_cause = `CAUSE_EXCEP_EBREAK_M;
|
||||
exception_offset = EBREAK_OFFSET;
|
||||
|
@ -178,7 +179,7 @@ module exception (
|
|||
assign int_or_exception_cause = exception_req ? exception_cause : interrupt_cause;
|
||||
assign int_or_exception_offset = exception_req ? exception_offset : interrupt_offset;
|
||||
|
||||
wire debug_mode_req = (~debug_mode_q) & debug_req_i & inst_valid_i;
|
||||
wire debug_mode_req = ((~debug_mode_q) & debug_req_i & inst_valid_i) | (inst_ebreak_i & dcsr_i[15]);
|
||||
|
||||
assign stall_flag_o = ((state_q != S_IDLE) & (state_q != S_ASSERT)) |
|
||||
(interrupt_req & global_int_en) | exception_req |
|
||||
|
@ -206,9 +207,11 @@ module exception (
|
|||
state_d = S_W_MEPC;
|
||||
end else if (debug_mode_req) begin
|
||||
debug_mode_d = 1'b1;
|
||||
if (!inst_ebreak_i) begin
|
||||
csr_we = 1'b1;
|
||||
csr_waddr = {20'h0, `CSR_DPC};
|
||||
csr_wdata = inst_addr_i;
|
||||
end
|
||||
assert_addr_d = debug_halt_addr_i;
|
||||
state_d = S_ASSERT;
|
||||
end else if (inst_mret_i) begin
|
||||
|
|
|
@ -128,6 +128,7 @@ module tinyriscv_core #(
|
|||
wire[31:0] csr_mstatus_o;
|
||||
wire[31:0] csr_mie_o;
|
||||
wire[31:0] csr_dpc_o;
|
||||
wire[31:0] csr_dcsr_o;
|
||||
|
||||
// pipe_ctrl模块输出信号
|
||||
wire[31:0] ctrl_flush_addr_o;
|
||||
|
@ -201,7 +202,8 @@ module tinyriscv_core #(
|
|||
.mepc_o(csr_mepc_o),
|
||||
.mstatus_o(csr_mstatus_o),
|
||||
.mie_o(csr_mie_o),
|
||||
.dpc_o(csr_dpc_o)
|
||||
.dpc_o(csr_dpc_o),
|
||||
.dcsr_o(csr_dcsr_o)
|
||||
);
|
||||
|
||||
ifu_idu u_ifu_idu(
|
||||
|
@ -319,6 +321,7 @@ module tinyriscv_core #(
|
|||
.mstatus_i(csr_mstatus_o),
|
||||
.mie_i(csr_mie_o),
|
||||
.dpc_i(csr_dpc_o),
|
||||
.dcsr_i(csr_dcsr_o),
|
||||
.irq_software_i(irq_software_i),
|
||||
.irq_timer_i(irq_timer_i),
|
||||
.irq_external_i(irq_external_i),
|
||||
|
|
|
@ -17,11 +17,14 @@
|
|||
|
||||
`define DbgVersion013 4'h2
|
||||
`define ProgBufSize 5'h8
|
||||
`define DataCount 4'h2
|
||||
`define DataCount 4'h1
|
||||
`define HaltAddress 64'h800
|
||||
`define ResumeAddress `HaltAddress + 4
|
||||
`define ExceptionAddress `HaltAddress + 8
|
||||
`define DataAddr 12'h380
|
||||
`define DataBaseAddr 12'h380
|
||||
`define AbstCmdBaseAddr 12'h338
|
||||
`define AbstCmdCount 12'd10
|
||||
`define ProgbufBaseAddr `AbstCmdBaseAddr + (4 * `AbstCmdCount)
|
||||
|
||||
// dmi op
|
||||
`define DMI_OP_NOP 2'b00
|
||||
|
@ -33,11 +36,13 @@
|
|||
`define Data1 6'h05
|
||||
`define Data2 6'h06
|
||||
`define Data3 6'h07
|
||||
`define Data4 6'h08
|
||||
`define DMControl 6'h10
|
||||
`define DMStatus 6'h11
|
||||
`define Hartinfo 6'h12
|
||||
`define AbstractCS 6'h16
|
||||
`define Command 6'h17
|
||||
`define AbstractAuto 8'h18
|
||||
`define ProgBuf0 6'h20
|
||||
`define ProgBuf1 6'h21
|
||||
`define ProgBuf2 6'h22
|
||||
|
@ -128,3 +133,21 @@
|
|||
`define Sbaccess16 1
|
||||
`define Sbaccess8 0
|
||||
|
||||
// abstractauto
|
||||
`define AutoexecData 11:0
|
||||
`define AutoexecProgbuf 31:16
|
||||
|
||||
`define CSR_CYCLE 12'hc00
|
||||
`define CSR_CYCLEH 12'hc80
|
||||
`define CSR_MTVEC 12'h305
|
||||
`define CSR_MCAUSE 12'h342
|
||||
`define CSR_MEPC 12'h341
|
||||
`define CSR_MIE 12'h304
|
||||
`define CSR_MSTATUS 12'h300
|
||||
`define CSR_MSCRATCH 12'h340
|
||||
`define CSR_MHARTID 12'hF14
|
||||
`define CSR_DCSR 12'h7b0
|
||||
`define CSR_DPC 12'h7b1
|
||||
`define CSR_DSCRATCH0 12'h7b2
|
||||
`define CSR_DSCRATCH1 12'h7b3
|
||||
|
||||
|
|
|
@ -20,8 +20,8 @@ module jtag_dm #(
|
|||
parameter DMI_ADDR_BITS = 6,
|
||||
parameter DMI_DATA_BITS = 32,
|
||||
parameter DMI_OP_BITS = 2,
|
||||
localparam DMI_REQ_BITS = DMI_ADDR_BITS + DMI_DATA_BITS + DMI_OP_BITS,
|
||||
localparam DMI_RESP_BITS = DMI_REQ_BITS
|
||||
parameter DMI_REQ_BITS = DMI_ADDR_BITS + DMI_DATA_BITS + DMI_OP_BITS,
|
||||
parameter DMI_RESP_BITS = DMI_REQ_BITS
|
||||
)(
|
||||
|
||||
input wire clk,
|
||||
|
@ -39,6 +39,7 @@ module jtag_dm #(
|
|||
|
||||
output wire debug_req_o,
|
||||
output wire ndmreset_o,
|
||||
output wire halted_o,
|
||||
|
||||
// jtag access mem devices(DM as master)
|
||||
output wire master_req_o,
|
||||
|
@ -61,7 +62,10 @@ module jtag_dm #(
|
|||
|
||||
);
|
||||
|
||||
localparam HARTINFO = {8'h0, 4'h2, 3'b0, 1'b1, `DataCount, `DataAddr};
|
||||
localparam HARTINFO = {8'h0, 4'h2, 3'b0, 1'b1, `DataCount, `DataBaseAddr};
|
||||
|
||||
localparam CmdErrorNone = 3'h0;
|
||||
localparam CmdErrorBusy = 3'h1;
|
||||
|
||||
wire halted;
|
||||
wire resumeack;
|
||||
|
@ -77,7 +81,11 @@ module jtag_dm #(
|
|||
reg sbdata_write_valid;
|
||||
reg sbdata_read_valid;
|
||||
reg[31:0] sbcs;
|
||||
reg[31:0] a_abstractcs;
|
||||
reg[31:0] dm_resp_data_d, dm_resp_data_q;
|
||||
reg cmd_valid_d, cmd_valid_q;
|
||||
reg[15:0] abstractautoprogbuf;
|
||||
reg[3:0] progbuf_index;
|
||||
wire[31:0] sba_sbaddress;
|
||||
wire[31:0] dm_sbaddress;
|
||||
wire resumereq;
|
||||
|
@ -85,17 +93,23 @@ module jtag_dm #(
|
|||
wire sbdata_valid;
|
||||
wire[31:0] sbdata;
|
||||
wire[19:0] hartsel;
|
||||
wire data_valid;
|
||||
wire[31:0] data0;
|
||||
wire cmderror_valid;
|
||||
wire[2:0] cmderror;
|
||||
|
||||
// DM regs
|
||||
reg[31:0] dmstatus;
|
||||
reg[31:0] dmcontrol_d, dmcontrol_q;
|
||||
reg[31:0] abstractcs;
|
||||
reg[31:0] abstractauto_d, abstractauto_q;
|
||||
reg[31:0] sbcs_d, sbcs_q;
|
||||
reg[31:0] sbdata0_d, sbdata0_q;
|
||||
reg[31:0] sbaddress0_d, sbaddress0_q;
|
||||
reg[31:0] command_d, command_q;
|
||||
reg[31:0] data0_d, data0_q;
|
||||
reg[2:0] cmderr_d, cmderr_q;
|
||||
reg[`ProgBufSize-1:0][31:0] progbuf_d, progbuf_q;
|
||||
|
||||
assign dm_sbaddress = sbaddress0_q;
|
||||
|
||||
|
@ -176,6 +190,8 @@ module jtag_dm #(
|
|||
abstractcs[`Progbufsize] = `ProgBufSize;
|
||||
abstractcs[`Busy] = cmdbusy;
|
||||
abstractcs[`Cmderr] = cmderr_q;
|
||||
a_abstractcs = 32'h0;
|
||||
abstractauto_d = abstractauto_q;
|
||||
|
||||
havereset_d = havereset_q;
|
||||
sbaddress0_d = sba_sbaddress;
|
||||
|
@ -185,6 +201,12 @@ module jtag_dm #(
|
|||
sbdata_write_valid = 1'b0;
|
||||
sbdata_read_valid = 1'b0;
|
||||
sbcs = 32'h0;
|
||||
command_d = command_q;
|
||||
cmd_valid_d = 1'b0;
|
||||
|
||||
progbuf_index = 4'h0;
|
||||
progbuf_d = progbuf_q;
|
||||
abstractautoprogbuf = abstractauto_q[`AutoexecProgbuf];
|
||||
|
||||
data0_d = data0_q;
|
||||
sbcs_d = sbcs_q;
|
||||
|
@ -200,6 +222,8 @@ module jtag_dm #(
|
|||
`Hartinfo :dm_resp_data_d = HARTINFO;
|
||||
`SBCS :dm_resp_data_d = sbcs_q;
|
||||
`AbstractCS:dm_resp_data_d = abstractcs;
|
||||
`AbstractAuto: dm_resp_data_d = abstractauto_q;
|
||||
`Command :dm_resp_data_d = 32'h0;
|
||||
`SBAddress0:dm_resp_data_d = sbaddress0_q;
|
||||
`SBData0 : begin
|
||||
if (sbbusy || sbcs_q[`Sbbusyerror]) begin
|
||||
|
@ -209,7 +233,26 @@ module jtag_dm #(
|
|||
dm_resp_data_d = sbdata0_q;
|
||||
end
|
||||
end
|
||||
default:;
|
||||
`Data0: begin
|
||||
dm_resp_data_d = data0_q;
|
||||
if (!cmdbusy) begin
|
||||
cmd_valid_d = abstractauto_q[0];
|
||||
end else if (cmderr_q == CmdErrorNone) begin
|
||||
cmderr_d = CmdErrorBusy;
|
||||
end
|
||||
end
|
||||
`ProgBuf0, `ProgBuf1, `ProgBuf2, `ProgBuf3,
|
||||
`ProgBuf4, `ProgBuf5, `ProgBuf6, `ProgBuf7,
|
||||
`ProgBuf8, `ProgBuf9: begin
|
||||
progbuf_index = dm_op_addr[3:0];
|
||||
dm_resp_data_d = progbuf_q[progbuf_index];
|
||||
if (!cmdbusy) begin
|
||||
cmd_valid_d = abstractautoprogbuf[progbuf_index];
|
||||
end else if (cmderr_q == CmdErrorNone) begin
|
||||
cmderr_d = CmdErrorBusy;
|
||||
end
|
||||
end
|
||||
default: dm_resp_data_d = 32'h0;
|
||||
endcase
|
||||
// write
|
||||
end else if (dm_op == `DMI_OP_WRITE) begin
|
||||
|
@ -222,7 +265,12 @@ module jtag_dm #(
|
|||
end
|
||||
|
||||
`Data0: begin
|
||||
if (!cmdbusy) begin
|
||||
data0_d = dm_op_data;
|
||||
cmd_valid_d = abstractauto_q[0];
|
||||
end else if (cmderr_q == CmdErrorNone) begin
|
||||
cmderr_d = CmdErrorBusy;
|
||||
end
|
||||
end
|
||||
|
||||
`SBCS: begin
|
||||
|
@ -255,8 +303,44 @@ module jtag_dm #(
|
|||
end
|
||||
end
|
||||
|
||||
`AbstractCS: begin
|
||||
`Command: begin
|
||||
if (!cmdbusy) begin
|
||||
cmd_valid_d = 1'b1;
|
||||
command_d = dm_op_data;
|
||||
end else if (cmderr_q == CmdErrorNone) begin
|
||||
cmderr_d = CmdErrorBusy;
|
||||
end
|
||||
end
|
||||
|
||||
`AbstractCS: begin
|
||||
a_abstractcs = dm_op_data;
|
||||
if (!cmdbusy) begin
|
||||
cmderr_d = (~a_abstractcs[`Cmderr]) & cmderr_q;
|
||||
end else if (cmderr_q == CmdErrorNone) begin
|
||||
cmderr_d = CmdErrorBusy;
|
||||
end
|
||||
end
|
||||
|
||||
`AbstractAuto: begin
|
||||
if (!cmdbusy) begin
|
||||
abstractauto_d = 32'h0;
|
||||
abstractauto_d[`AutoexecData] = {11'h0, dm_op_data[0]};
|
||||
abstractauto_d[`AutoexecProgbuf] = dm_op_data[`ProgBufSize-1+16:16];
|
||||
end else if (cmderr_q == CmdErrorNone) begin
|
||||
cmderr_d = CmdErrorBusy;
|
||||
end
|
||||
end
|
||||
|
||||
`ProgBuf0, `ProgBuf1, `ProgBuf2, `ProgBuf3,
|
||||
`ProgBuf4, `ProgBuf5, `ProgBuf6, `ProgBuf7,
|
||||
`ProgBuf8, `ProgBuf9: begin
|
||||
if (!cmdbusy) begin
|
||||
progbuf_index = dm_op_addr[3:0];
|
||||
progbuf_d[progbuf_index] = dm_op_data;
|
||||
cmd_valid_d = abstractautoprogbuf[progbuf_index];
|
||||
end else if (cmderr_q == CmdErrorNone) begin
|
||||
cmderr_d = CmdErrorBusy;
|
||||
end
|
||||
end
|
||||
|
||||
default:;
|
||||
|
@ -297,17 +381,42 @@ module jtag_dm #(
|
|||
sbdata0_d = sbdata;
|
||||
end
|
||||
|
||||
if (cmderror_valid) begin
|
||||
cmderr_d = cmderror;
|
||||
end
|
||||
|
||||
if (data_valid) begin
|
||||
data0_d = data0;
|
||||
end
|
||||
|
||||
// set the havereset flag when we did a ndmreset
|
||||
if (ndmreset_o) begin
|
||||
havereset_d = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
assign debug_req_o = dmcontrol_q[`Haltreq];
|
||||
assign ndmreset_o = dmcontrol_q[`Ndmreset];
|
||||
assign resumereq = dmcontrol_q[`Resumereq];
|
||||
assign halted_o = halted;
|
||||
|
||||
genvar i;
|
||||
|
||||
generate
|
||||
for (i = 0; i < `ProgBufSize; i = i + 1) begin: gen_progbuf
|
||||
always @ (posedge clk or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
progbuf_q[i] <= 32'h0;
|
||||
end else begin
|
||||
if (!dmcontrol_q[`Dmactive]) begin
|
||||
progbuf_q[i] <= 32'h0;
|
||||
end else begin
|
||||
progbuf_q[i] <= progbuf_d[i];
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
always @ (posedge clk or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
|
@ -319,6 +428,9 @@ module jtag_dm #(
|
|||
sbdata0_q <= 32'h0;
|
||||
dm_resp_data_q <= 32'h0;
|
||||
cmderr_q <= 3'h0;
|
||||
command_q <= 32'h0;
|
||||
abstractauto_q <= 32'h0;
|
||||
cmd_valid_q <= 1'b0;
|
||||
end else begin
|
||||
if (!dmcontrol_q[`Dmactive]) begin
|
||||
dmcontrol_q[`Haltreq] <= 1'b0;
|
||||
|
@ -338,6 +450,9 @@ module jtag_dm #(
|
|||
sbdata0_q <= 32'h0;
|
||||
dm_resp_data_q <= 32'h0;
|
||||
cmderr_q <= 3'h0;
|
||||
command_q <= 32'h0;
|
||||
abstractauto_q <= 32'h0;
|
||||
cmd_valid_q <= 1'b0;
|
||||
end else begin
|
||||
dmcontrol_q <= dmcontrol_d;
|
||||
data0_q <= data0_d;
|
||||
|
@ -346,14 +461,15 @@ module jtag_dm #(
|
|||
sbdata0_q <= sbdata0_d;
|
||||
dm_resp_data_q <= dm_resp_data_d;
|
||||
cmderr_q <= cmderr_d;
|
||||
command_q <= command_d;
|
||||
abstractauto_q <= abstractauto_d;
|
||||
cmd_valid_q <= cmd_valid_d;
|
||||
end
|
||||
havereset_q <= havereset_d;
|
||||
end
|
||||
end
|
||||
|
||||
jtag_mem #(
|
||||
|
||||
) u_jtag_mem (
|
||||
jtag_mem u_jtag_mem (
|
||||
.clk(clk),
|
||||
.rst_n(rst_n),
|
||||
|
||||
|
@ -362,6 +478,15 @@ module jtag_dm #(
|
|||
.clear_resumeack_i(clear_resumeack),
|
||||
.resumereq_i(resumereq),
|
||||
.haltreq_i(debug_req_o),
|
||||
|
||||
.progbuf_i(),
|
||||
.data_i(data0_q),
|
||||
.data_o(data0),
|
||||
.data_valid_o(data_valid),
|
||||
.cmd_valid_i(cmd_valid_q),
|
||||
.cmd_i(command_q),
|
||||
.cmderror_valid_o(cmderror_valid),
|
||||
.cmderror_o(cmderror),
|
||||
.cmdbusy_o(cmdbusy),
|
||||
|
||||
.req_i(slave_req_i),
|
||||
|
@ -372,9 +497,7 @@ module jtag_dm #(
|
|||
.rdata_o(slave_rdata_o)
|
||||
);
|
||||
|
||||
jtag_sba #(
|
||||
|
||||
) u_jtag_sba (
|
||||
jtag_sba u_jtag_sba (
|
||||
.clk(clk),
|
||||
.rst_n(rst_n),
|
||||
.sbaddress_i(sbaddress0_q),
|
||||
|
|
|
@ -1,290 +0,0 @@
|
|||
/*
|
||||
Copyright 2020 Blue Liang, liangkangnan@163.com
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
module jtag_driver #(
|
||||
parameter DMI_ADDR_BITS = 6,
|
||||
parameter DMI_DATA_BITS = 32,
|
||||
parameter DMI_OP_BITS = 2)(
|
||||
|
||||
rst_n,
|
||||
|
||||
jtag_TCK,
|
||||
jtag_TDI,
|
||||
jtag_TMS,
|
||||
jtag_TDO,
|
||||
|
||||
// rx
|
||||
dm_resp_i,
|
||||
dm_resp_data_i,
|
||||
dtm_ack_o,
|
||||
|
||||
// tx
|
||||
dm_ack_i,
|
||||
dtm_req_valid_o,
|
||||
dtm_req_data_o
|
||||
|
||||
);
|
||||
|
||||
parameter IDCODE_VERSION = 4'h1;
|
||||
parameter IDCODE_PART_NUMBER = 16'he200;
|
||||
parameter IDCODE_MANUFLD = 11'h537;
|
||||
|
||||
parameter DTM_VERSION = 4'h1;
|
||||
parameter IR_BITS = 5;
|
||||
|
||||
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 rst_n;
|
||||
input wire jtag_TCK;
|
||||
input wire jtag_TDI;
|
||||
input wire jtag_TMS;
|
||||
output reg jtag_TDO;
|
||||
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;
|
||||
parameter RUN_TEST_IDLE = 4'h1;
|
||||
parameter SELECT_DR = 4'h2;
|
||||
parameter CAPTURE_DR = 4'h3;
|
||||
parameter SHIFT_DR = 4'h4;
|
||||
parameter EXIT1_DR = 4'h5;
|
||||
parameter PAUSE_DR = 4'h6;
|
||||
parameter EXIT2_DR = 4'h7;
|
||||
parameter UPDATE_DR = 4'h8;
|
||||
parameter SELECT_IR = 4'h9;
|
||||
parameter CAPTURE_IR = 4'hA;
|
||||
parameter SHIFT_IR = 4'hB;
|
||||
parameter EXIT1_IR = 4'hC;
|
||||
parameter PAUSE_IR = 4'hD;
|
||||
parameter EXIT2_IR = 4'hE;
|
||||
parameter UPDATE_IR = 4'hF;
|
||||
|
||||
// DTM regs
|
||||
parameter REG_BYPASS = 5'b11111;
|
||||
parameter REG_IDCODE = 5'b00001;
|
||||
parameter REG_DMI = 5'b10001;
|
||||
parameter REG_DTMCS = 5'b10000;
|
||||
|
||||
reg[IR_BITS - 1:0] ir_reg;
|
||||
reg[SHIFT_REG_BITS - 1:0] shift_reg;
|
||||
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;
|
||||
wire [SHIFT_REG_BITS - 1:0] none_busy_response;
|
||||
wire[31:0] idcode;
|
||||
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};
|
||||
assign dtmcs = {14'b0,
|
||||
1'b0, // dmihardreset
|
||||
1'b0, // dmireset
|
||||
1'b0,
|
||||
3'h5, // idle
|
||||
dmi_stat, // dmistat
|
||||
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 none_busy_response = dm_resp_data;
|
||||
assign is_busy = sticky_busy | dm_is_busy;
|
||||
assign dmi_stat = is_busy ? 2'b01 : 2'b00;
|
||||
|
||||
// state switch
|
||||
always @(posedge jtag_TCK or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
jtag_state <= TEST_LOGIC_RESET;
|
||||
end else begin
|
||||
case (jtag_state)
|
||||
TEST_LOGIC_RESET : jtag_state <= jtag_TMS ? TEST_LOGIC_RESET : RUN_TEST_IDLE;
|
||||
RUN_TEST_IDLE : jtag_state <= jtag_TMS ? SELECT_DR : RUN_TEST_IDLE;
|
||||
SELECT_DR : jtag_state <= jtag_TMS ? SELECT_IR : CAPTURE_DR;
|
||||
CAPTURE_DR : jtag_state <= jtag_TMS ? EXIT1_DR : SHIFT_DR;
|
||||
SHIFT_DR : jtag_state <= jtag_TMS ? EXIT1_DR : SHIFT_DR;
|
||||
EXIT1_DR : jtag_state <= jtag_TMS ? UPDATE_DR : PAUSE_DR;
|
||||
PAUSE_DR : jtag_state <= jtag_TMS ? EXIT2_DR : PAUSE_DR;
|
||||
EXIT2_DR : jtag_state <= jtag_TMS ? UPDATE_DR : SHIFT_DR;
|
||||
UPDATE_DR : jtag_state <= jtag_TMS ? SELECT_DR : RUN_TEST_IDLE;
|
||||
SELECT_IR : jtag_state <= jtag_TMS ? TEST_LOGIC_RESET : CAPTURE_IR;
|
||||
CAPTURE_IR : jtag_state <= jtag_TMS ? EXIT1_IR : SHIFT_IR;
|
||||
SHIFT_IR : jtag_state <= jtag_TMS ? EXIT1_IR : SHIFT_IR;
|
||||
EXIT1_IR : jtag_state <= jtag_TMS ? UPDATE_IR : PAUSE_IR;
|
||||
PAUSE_IR : jtag_state <= jtag_TMS ? EXIT2_IR : PAUSE_IR;
|
||||
EXIT2_IR : jtag_state <= jtag_TMS ? UPDATE_IR : SHIFT_IR;
|
||||
UPDATE_IR : jtag_state <= jtag_TMS ? SELECT_DR : RUN_TEST_IDLE;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
// IR or DR shift
|
||||
always @(posedge jtag_TCK) begin
|
||||
case (jtag_state)
|
||||
// IR
|
||||
CAPTURE_IR: shift_reg <= {{(SHIFT_REG_BITS - 1){1'b0}}, 1'b1}; //JTAG spec says it must be b01
|
||||
SHIFT_IR : shift_reg <= {{(SHIFT_REG_BITS - IR_BITS){1'b0}}, jtag_TDI, shift_reg[IR_BITS - 1:1]}; // right shift 1 bit
|
||||
// DR
|
||||
CAPTURE_DR: case (ir_reg)
|
||||
REG_BYPASS : shift_reg <= {(SHIFT_REG_BITS){1'b0}};
|
||||
REG_IDCODE : shift_reg <= {{(SHIFT_REG_BITS - DMI_DATA_BITS){1'b0}}, idcode};
|
||||
REG_DTMCS : shift_reg <= {{(SHIFT_REG_BITS - DMI_DATA_BITS){1'b0}}, dtmcs};
|
||||
REG_DMI : shift_reg <= is_busy ? busy_response : none_busy_response;
|
||||
default:
|
||||
shift_reg <= {(SHIFT_REG_BITS){1'b0}};
|
||||
endcase
|
||||
SHIFT_DR : case (ir_reg)
|
||||
REG_BYPASS : shift_reg <= {{(SHIFT_REG_BITS - 1){1'b0}}, jtag_TDI}; // in = out
|
||||
REG_IDCODE : shift_reg <= {{(SHIFT_REG_BITS - DMI_DATA_BITS){1'b0}}, jtag_TDI, shift_reg[31:1]}; // right shift 1 bit
|
||||
REG_DTMCS : shift_reg <= {{(SHIFT_REG_BITS - DMI_DATA_BITS){1'b0}}, jtag_TDI, shift_reg[31:1]}; // right shift 1 bit
|
||||
REG_DMI : shift_reg <= {jtag_TDI, shift_reg[SHIFT_REG_BITS - 1:1]}; // right shift 1 bit
|
||||
default:
|
||||
shift_reg <= {{(SHIFT_REG_BITS - 1){1'b0}} , jtag_TDI};
|
||||
endcase
|
||||
endcase
|
||||
end
|
||||
|
||||
// start access DM module
|
||||
always @(posedge jtag_TCK or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
dtm_req_valid <= 1'b0;
|
||||
dtm_req_data <= {DTM_REQ_BITS{1'b0}};
|
||||
end else begin
|
||||
if (jtag_state == UPDATE_DR) begin
|
||||
if (ir_reg == REG_DMI) begin
|
||||
// if DM can be access
|
||||
if (!is_busy & tx_idle) begin
|
||||
dtm_req_valid <= 1'b1;
|
||||
dtm_req_data <= shift_reg;
|
||||
end
|
||||
end
|
||||
end else begin
|
||||
dtm_req_valid <= 1'b0;
|
||||
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 & dtm_reset) begin
|
||||
sticky_busy <= 1'b0;
|
||||
end
|
||||
end else if (jtag_state == CAPTURE_DR) begin
|
||||
if (ir_reg == REG_DMI) begin
|
||||
sticky_busy <= is_busy;
|
||||
end
|
||||
end
|
||||
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
|
||||
ir_reg <= REG_IDCODE;
|
||||
end else if (jtag_state == UPDATE_IR) begin
|
||||
ir_reg <= shift_reg[IR_BITS - 1:0];
|
||||
end
|
||||
end
|
||||
|
||||
// TDO output
|
||||
always @(negedge jtag_TCK) begin
|
||||
if (jtag_state == SHIFT_IR) begin
|
||||
jtag_TDO <= shift_reg[0];
|
||||
end else if (jtag_state == SHIFT_DR) begin
|
||||
jtag_TDO <= shift_reg[0];
|
||||
end else begin
|
||||
jtag_TDO <= 1'b0;
|
||||
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
|
|
@ -20,10 +20,10 @@ module jtag_dtm #(
|
|||
parameter DMI_ADDR_BITS = 6,
|
||||
parameter DMI_DATA_BITS = 32,
|
||||
parameter DMI_OP_BITS = 2,
|
||||
localparam TAP_REQ_BITS = DMI_ADDR_BITS + DMI_DATA_BITS + DMI_OP_BITS,
|
||||
localparam DTM_RESP_BITS = TAP_REQ_BITS,
|
||||
localparam DTM_REQ_BITS = DTM_RESP_BITS,
|
||||
localparam DMI_RESP_BITS = DTM_REQ_BITS
|
||||
parameter TAP_REQ_BITS = DMI_ADDR_BITS + DMI_DATA_BITS + DMI_OP_BITS,
|
||||
parameter DTM_RESP_BITS = TAP_REQ_BITS,
|
||||
parameter DTM_REQ_BITS = DTM_RESP_BITS,
|
||||
parameter DMI_RESP_BITS = DTM_REQ_BITS
|
||||
)(
|
||||
|
||||
input wire jtag_tck_i, // JTAG test clock pad
|
||||
|
|
|
@ -14,21 +14,29 @@
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
`include "jtag_def.sv"
|
||||
|
||||
|
||||
module jtag_mem #(
|
||||
)(
|
||||
module jtag_mem(
|
||||
|
||||
input wire clk,
|
||||
input wire rst_n,
|
||||
|
||||
output wire halted_o,
|
||||
output wire resumeack_o,
|
||||
output wire cmdbusy_o,
|
||||
input wire clear_resumeack_i,
|
||||
input wire resumereq_i,
|
||||
input wire haltreq_i,
|
||||
|
||||
input wire [`ProgBufSize-1:0][31:0] progbuf_i,
|
||||
input wire [31:0] data_i,
|
||||
output wire [31:0] data_o,
|
||||
output wire data_valid_o,
|
||||
input wire cmd_valid_i,
|
||||
input wire [31:0] cmd_i,
|
||||
output wire cmderror_valid_o,
|
||||
output wire [2:0] cmderror_o,
|
||||
output wire cmdbusy_o,
|
||||
|
||||
input wire req_i,
|
||||
input wire we_i,
|
||||
input wire [31:0] addr_i,
|
||||
|
@ -43,12 +51,33 @@ module jtag_mem #(
|
|||
// x10/a0
|
||||
localparam LoadBaseAddr = 5'd10;
|
||||
|
||||
localparam DataBaseAddr = `DataAddr;
|
||||
localparam DataEndAddr = (`DataAddr + 4 * `DataCount - 1);
|
||||
localparam ProgBufBaseAddr = (`DataAddr - 4 * `ProgBufSize);
|
||||
localparam ProgBufEndAddr = (`DataAddr - 1);
|
||||
localparam AbstractCmdBaseAddr = (ProgBufBaseAddr - 4 * 10);
|
||||
localparam AbstractCmdEndAddr = (ProgBufBaseAddr - 1);
|
||||
localparam Data0Addr = `DataBaseAddr;
|
||||
localparam Data1Addr = `DataBaseAddr + 4;
|
||||
localparam Data2Addr = `DataBaseAddr + 8;
|
||||
localparam Data3Addr = `DataBaseAddr + 12;
|
||||
localparam Data4Addr = `DataBaseAddr + 16;
|
||||
|
||||
localparam Progbuf0Addr = `ProgbufBaseAddr;
|
||||
localparam Progbuf1Addr = `ProgbufBaseAddr + 4;
|
||||
localparam Progbuf2Addr = `ProgbufBaseAddr + 8;
|
||||
localparam Progbuf3Addr = `ProgbufBaseAddr + 12;
|
||||
localparam Progbuf4Addr = `ProgbufBaseAddr + 16;
|
||||
localparam Progbuf5Addr = `ProgbufBaseAddr + 20;
|
||||
localparam Progbuf6Addr = `ProgbufBaseAddr + 24;
|
||||
localparam Progbuf7Addr = `ProgbufBaseAddr + 28;
|
||||
localparam Progbuf8Addr = `ProgbufBaseAddr + 32;
|
||||
localparam Progbuf9Addr = `ProgbufBaseAddr + 36;
|
||||
|
||||
localparam AbstractCmd0Addr = `AbstCmdBaseAddr;
|
||||
localparam AbstractCmd1Addr = `AbstCmdBaseAddr + 4;
|
||||
localparam AbstractCmd2Addr = `AbstCmdBaseAddr + 8;
|
||||
localparam AbstractCmd3Addr = `AbstCmdBaseAddr + 12;
|
||||
localparam AbstractCmd4Addr = `AbstCmdBaseAddr + 16;
|
||||
localparam AbstractCmd5Addr = `AbstCmdBaseAddr + 20;
|
||||
localparam AbstractCmd6Addr = `AbstCmdBaseAddr + 24;
|
||||
localparam AbstractCmd7Addr = `AbstCmdBaseAddr + 28;
|
||||
localparam AbstractCmd8Addr = `AbstCmdBaseAddr + 32;
|
||||
localparam AbstractCmd9Addr = `AbstCmdBaseAddr + 36;
|
||||
|
||||
localparam WhereToAddr = 12'h300;
|
||||
localparam FlagsBaseAddr = 12'h400;
|
||||
|
@ -59,23 +88,114 @@ module jtag_mem #(
|
|||
localparam ResumingAddr = 12'h108;
|
||||
localparam ExceptionAddr = 12'h10C;
|
||||
|
||||
localparam CmdAccessRegister = 8'h0;
|
||||
localparam CmdQuickAccess = 8'h1;
|
||||
localparam CmdAccessMemory = 8'h2;
|
||||
|
||||
localparam CmdErrorNone = 3'h0;
|
||||
localparam CmdErrorHaltResume = 3'h4;
|
||||
localparam CmdErrorNotSupport = 3'h2;
|
||||
localparam CmdErrorException = 3'h3;
|
||||
|
||||
localparam illegal = 32'h00000000;
|
||||
localparam nop = 32'h00000013;
|
||||
localparam ebreak = 32'h00100073;
|
||||
|
||||
localparam S_IDLE = 4'b0001;
|
||||
localparam S_RESUME = 4'b0010;
|
||||
localparam S_GO = 4'b0100;
|
||||
localparam S_CMD_EXECUTING = 4'b1000;
|
||||
|
||||
reg[3:0] state_d, state_q;
|
||||
|
||||
function automatic [31:0] jal;
|
||||
input [4:0] rd;
|
||||
input [20:0] imm;
|
||||
|
||||
jal = {imm[20], imm[10:1], imm[11], imm[19:12], rd, 7'h6f};
|
||||
endfunction
|
||||
|
||||
function automatic [31:0] slli;
|
||||
input [4:0] rd;
|
||||
input [4:0] rs1;
|
||||
input [5:0] shamt;
|
||||
|
||||
slli = {6'b0, shamt[5:0], rs1, 3'h1, rd, 7'h13};
|
||||
endfunction
|
||||
|
||||
function automatic [31:0] srli;
|
||||
input [4:0] rd;
|
||||
input [4:0] rs1;
|
||||
input [5:0] shamt;
|
||||
|
||||
srli = {6'b0, shamt[5:0], rs1, 3'h5, rd, 7'h13};
|
||||
endfunction
|
||||
|
||||
function automatic [31:0] load;
|
||||
input [2:0] size;
|
||||
input [4:0] dest;
|
||||
input [4:0] base;
|
||||
input [11:0] offset;
|
||||
|
||||
load = {offset[11:0], base, size, dest, 7'h03};
|
||||
endfunction
|
||||
|
||||
function automatic [31:0] auipc;
|
||||
input [4:0] rd;
|
||||
input [20:0] imm;
|
||||
|
||||
auipc = {imm[20], imm[10:1], imm[11], imm[19:12], rd, 7'h17};
|
||||
endfunction
|
||||
|
||||
function automatic [31:0] store;
|
||||
input [2:0] size;
|
||||
input [4:0] src;
|
||||
input [4:0] base;
|
||||
input [11:0] offset;
|
||||
|
||||
store = {offset[11:5], src, base, size, offset[4:0], 7'h23};
|
||||
endfunction
|
||||
|
||||
function automatic [31:0] csrw;
|
||||
input [11:0] csr;
|
||||
input [4:0] rs1;
|
||||
|
||||
csrw = {csr, rs1, 3'h1, 5'h0, 7'h73};
|
||||
endfunction
|
||||
|
||||
function automatic [31:0] csrr;
|
||||
input [11:0] csr;
|
||||
input [4:0] dest;
|
||||
|
||||
csrr = {csr, 5'h0, 3'h2, dest, 7'h73};
|
||||
endfunction
|
||||
|
||||
|
||||
reg[3:0] state_d, state_q;
|
||||
reg[31:0] rdata_d, rdata_q;
|
||||
reg halted_d, halted_q;
|
||||
reg resuming_d, resuming_q;
|
||||
reg resume, go, going;
|
||||
reg fwd_rom_q;
|
||||
reg word_enable32_q;
|
||||
reg data_valid;
|
||||
reg cmdbusy;
|
||||
wire fwd_rom_d;
|
||||
wire[63:0] rom_rdata;
|
||||
|
||||
|
||||
reg[31:0] data_bits;
|
||||
reg[9:0][31:0] abstract_cmd;
|
||||
reg unsupported_command;
|
||||
reg cmderror_valid;
|
||||
reg[2:0] cmderror;
|
||||
reg exception;
|
||||
wire[11:0] progbuf_baseaddr = Progbuf0Addr;
|
||||
wire[11:0] abstractcmd_baseaddr = AbstractCmd0Addr;
|
||||
wire[7:0] cmd_type = cmd_i[31:24];
|
||||
wire cmd_postexec = cmd_i[18];
|
||||
wire cmd_transfer = cmd_i[17];
|
||||
wire cmd_write = cmd_i[16];
|
||||
wire[15:0] cmd_regno = cmd_i[15:0];
|
||||
wire[2:0] cmd_aarsize = cmd_i[22:20];
|
||||
wire cmd_aarpostincrement = cmd_i[19];
|
||||
|
||||
// word mux for 32bit and 64bit buses
|
||||
wire [63:0] word_mux;
|
||||
|
@ -84,38 +204,84 @@ module jtag_mem #(
|
|||
|
||||
assign halted_o = halted_q;
|
||||
assign resumeack_o = resuming_q;
|
||||
assign cmdbusy_o = 1'b0;
|
||||
|
||||
|
||||
always @ (*) begin
|
||||
state_d = state_q;
|
||||
resume = 1'b0;
|
||||
go = 1'b0;
|
||||
cmdbusy = 1'b1;
|
||||
cmderror_valid = 1'b0;
|
||||
cmderror = CmdErrorNone;
|
||||
|
||||
case (state_q)
|
||||
S_IDLE: begin
|
||||
cmdbusy = 1'b0;
|
||||
if (resumereq_i && (!resuming_q) &&
|
||||
halted_q && (!haltreq_i)) begin
|
||||
state_d = S_RESUME;
|
||||
end
|
||||
if (cmd_valid_i) begin
|
||||
if (!halted_q) begin
|
||||
cmderror_valid = 1'b1;
|
||||
cmderror = CmdErrorHaltResume;
|
||||
end else if (unsupported_command) begin
|
||||
cmderror_valid = 1'b1;
|
||||
cmderror = CmdErrorNotSupport;
|
||||
end else begin
|
||||
state_d = S_GO;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
S_GO: begin
|
||||
cmdbusy = 1'b1;
|
||||
go = 1'b1;
|
||||
if (going) begin
|
||||
state_d = S_CMD_EXECUTING;
|
||||
end
|
||||
end
|
||||
|
||||
S_RESUME: begin
|
||||
resume = 1'b1;
|
||||
cmdbusy = 1'b1;
|
||||
if (resuming_q) begin
|
||||
state_d = S_IDLE;
|
||||
end
|
||||
end
|
||||
|
||||
S_CMD_EXECUTING: begin
|
||||
cmdbusy = 1'b1;
|
||||
go = 1'b0;
|
||||
if (halted_q) begin
|
||||
state_d = S_IDLE;
|
||||
end
|
||||
end
|
||||
|
||||
default:;
|
||||
endcase
|
||||
|
||||
if (exception) begin
|
||||
cmderror_valid = 1'b1;
|
||||
cmderror = CmdErrorException;
|
||||
end
|
||||
end
|
||||
|
||||
assign cmderror_valid_o = cmderror_valid;
|
||||
assign cmderror_o = cmderror;
|
||||
assign cmdbusy_o = cmdbusy;
|
||||
|
||||
always @ (*) begin
|
||||
rdata_d = rdata_q;
|
||||
halted_d = halted_q;
|
||||
resuming_d = resuming_q;
|
||||
|
||||
going = 1'b0;
|
||||
exception = 1'b0;
|
||||
|
||||
data_valid = 1'b0;
|
||||
data_bits = data_i;
|
||||
|
||||
if (clear_resumeack_i) begin
|
||||
resuming_d = 1'b0;
|
||||
end
|
||||
|
@ -128,7 +294,7 @@ module jtag_mem #(
|
|||
end
|
||||
|
||||
GoingAddr: begin
|
||||
|
||||
going = 1'b1;
|
||||
end
|
||||
|
||||
ResumingAddr: begin
|
||||
|
@ -137,7 +303,20 @@ module jtag_mem #(
|
|||
end
|
||||
|
||||
ExceptionAddr: begin
|
||||
exception = 1'b1;
|
||||
end
|
||||
|
||||
Data0Addr, Data1Addr, Data2Addr,
|
||||
Data3Addr, Data4Addr: begin
|
||||
data_valid = 1'b1;
|
||||
if (be_i[0])
|
||||
data_bits[7:0] = wdata_i[7:0];
|
||||
if (be_i[1])
|
||||
data_bits[15:8] = wdata_i[15:8];
|
||||
if (be_i[2])
|
||||
data_bits[23:16] = wdata_i[23:16];
|
||||
if (be_i[3])
|
||||
data_bits[31:24] = wdata_i[31:24];
|
||||
end
|
||||
|
||||
default:;
|
||||
|
@ -145,14 +324,144 @@ module jtag_mem #(
|
|||
// read
|
||||
end else begin
|
||||
case (addr_i[DbgAddressBits-1:0])
|
||||
WhereToAddr: begin
|
||||
if (cmdbusy & (cmd_type == CmdAccessRegister)) begin
|
||||
// execute program buf
|
||||
if (cmd_postexec) begin
|
||||
rdata_d = jal(5'h0, {9'h0, progbuf_baseaddr-WhereToAddr});
|
||||
// execute command
|
||||
end else begin
|
||||
rdata_d = jal(5'h0, {9'h0, abstractcmd_baseaddr-WhereToAddr});
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// harts are polling for flags here
|
||||
FlagsBaseAddr: begin
|
||||
rdata_d = {30'b0, resume, go};
|
||||
end
|
||||
|
||||
Data0Addr, Data1Addr, Data2Addr, Data3Addr,
|
||||
Data4Addr: begin
|
||||
rdata_d = data_i;
|
||||
end
|
||||
|
||||
Progbuf0Addr, Progbuf1Addr, Progbuf2Addr, Progbuf3Addr,
|
||||
Progbuf4Addr, Progbuf5Addr, Progbuf6Addr, Progbuf7Addr,
|
||||
Progbuf8Addr, Progbuf9Addr: begin
|
||||
rdata_d = progbuf_i[addr_i[DbgAddressBits-1:3] -
|
||||
progbuf_baseaddr[DbgAddressBits-1:3]];
|
||||
end
|
||||
|
||||
AbstractCmd0Addr, AbstractCmd1Addr, AbstractCmd2Addr, AbstractCmd3Addr,
|
||||
AbstractCmd4Addr, AbstractCmd5Addr, AbstractCmd6Addr, AbstractCmd7Addr,
|
||||
AbstractCmd8Addr, AbstractCmd9Addr: begin
|
||||
rdata_d = abstract_cmd[addr_i[DbgAddressBits-1:3] -
|
||||
abstractcmd_baseaddr[DbgAddressBits-1:3]];
|
||||
end
|
||||
|
||||
default:;
|
||||
endcase
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
assign data_valid_o = data_valid;
|
||||
assign data_o = data_bits;
|
||||
|
||||
always @ (*) begin
|
||||
unsupported_command = 1'b0;
|
||||
|
||||
abstract_cmd[0] = illegal;
|
||||
abstract_cmd[1] = auipc(5'd10, 21'd0); // auipc a0, 0
|
||||
abstract_cmd[2] = srli(5'd10, 5'd10, 6'd12); // srli a0, a0, 12
|
||||
abstract_cmd[3] = slli(5'd10, 5'd10, 6'd12); // slli a0, a0, 12
|
||||
abstract_cmd[4] = nop;
|
||||
abstract_cmd[5] = nop;
|
||||
abstract_cmd[6] = nop;
|
||||
abstract_cmd[7] = nop;
|
||||
abstract_cmd[8] = csrr(`CSR_DSCRATCH1, 5'd10); // csrr dscratch1, a0 恢复a0寄存器的值
|
||||
abstract_cmd[9] = ebreak;
|
||||
|
||||
case (cmd_type)
|
||||
CmdAccessRegister: begin
|
||||
// unsupported reg size
|
||||
if (cmd_aarsize > 3'h2 || cmd_aarpostincrement || cmd_regno >= 16'h1020) begin
|
||||
abstract_cmd[0] = ebreak;
|
||||
unsupported_command = 1'b1;
|
||||
end else begin
|
||||
// store a0 in dscratch1
|
||||
abstract_cmd[0] = csrw(`CSR_DSCRATCH1, 5'd10); // csrw dscratch1, a0 保存a0寄存器的值
|
||||
// write regs
|
||||
if (cmd_transfer && cmd_write) begin
|
||||
// a0
|
||||
if (cmd_regno[12] && (cmd_regno[4:0] == 5'd10)) begin
|
||||
// store s0 in dscratch
|
||||
abstract_cmd[4] = csrw(`CSR_DSCRATCH0, 5'd8);
|
||||
// load from data register
|
||||
abstract_cmd[5] = load(cmd_aarsize, 5'd8, LoadBaseAddr, `DataBaseAddr);
|
||||
// and store it in the corresponding CSR
|
||||
abstract_cmd[6] = csrw(`CSR_DSCRATCH1, 5'd8);
|
||||
// restore s0 again from dscratch
|
||||
abstract_cmd[7] = csrr(`CSR_DSCRATCH0, 5'd8);
|
||||
// GPR access
|
||||
end else if (cmd_regno[12]) begin
|
||||
abstract_cmd[4] = load(cmd_aarsize, cmd_regno[4:0], LoadBaseAddr, `DataBaseAddr);
|
||||
// CSR access
|
||||
end else begin
|
||||
// data register to CSR
|
||||
// store s0 in dscratch
|
||||
abstract_cmd[4] = csrw(`CSR_DSCRATCH0, 5'd8);
|
||||
// load from data register
|
||||
abstract_cmd[5] = load(cmd_aarsize, 5'd8, LoadBaseAddr, `DataBaseAddr);
|
||||
// and store it in the corresponding CSR
|
||||
abstract_cmd[6] = csrw(cmd_regno[11:0], 5'd8);
|
||||
// restore s0 again from dscratch
|
||||
abstract_cmd[7] = csrr(`CSR_DSCRATCH0, 5'd8);
|
||||
end
|
||||
// read regs
|
||||
end else if (cmd_transfer && (!cmd_write)) begin
|
||||
// a0
|
||||
if (cmd_regno[12] && (cmd_regno[4:0] == 5'd10)) begin
|
||||
// store s0 in dscratch
|
||||
abstract_cmd[4] = csrw(`CSR_DSCRATCH0, 5'd8);
|
||||
// read value from CSR into s0
|
||||
abstract_cmd[5] = csrr(`CSR_DSCRATCH1, 5'd8);
|
||||
// and store s0 into data section
|
||||
abstract_cmd[6] = store(cmd_aarsize, 5'd8, LoadBaseAddr, `DataBaseAddr);
|
||||
// restore s0 again from dscratch
|
||||
abstract_cmd[7] = csrr(`CSR_DSCRATCH0, 5'd8);
|
||||
// GPR access
|
||||
end else if (cmd_regno[12]) begin
|
||||
abstract_cmd[4] = store(cmd_aarsize, cmd_regno[4:0], LoadBaseAddr, `DataBaseAddr);
|
||||
// CSR access
|
||||
end else begin
|
||||
// CSR register to data
|
||||
// store s0 in dscratch
|
||||
abstract_cmd[4] = csrw(`CSR_DSCRATCH0, 5'd8);
|
||||
// read value from CSR into s0
|
||||
abstract_cmd[5] = csrr(cmd_regno[11:0], 5'd8);
|
||||
// and store s0 into data section
|
||||
abstract_cmd[6] = store(cmd_aarsize, 5'd8, LoadBaseAddr, `DataBaseAddr);
|
||||
// restore s0 again from dscratch
|
||||
abstract_cmd[7] = csrr(`CSR_DSCRATCH0, 5'd8);
|
||||
end
|
||||
end
|
||||
end
|
||||
if (cmd_postexec && (!unsupported_command)) begin
|
||||
// issue a nop, we will automatically run into the program buffer
|
||||
abstract_cmd[9] = nop;
|
||||
end
|
||||
end
|
||||
|
||||
// not supported at the moment:
|
||||
// CmdQuickAccess:;
|
||||
// CmdAccessMemory:;
|
||||
default: begin
|
||||
unsupported_command = 1'b1;
|
||||
abstract_cmd[0] = ebreak;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
wire[63:0] rom_addr;
|
||||
|
|
|
@ -15,9 +15,7 @@
|
|||
*/
|
||||
|
||||
|
||||
module jtag_sba #(
|
||||
|
||||
)(
|
||||
module jtag_sba(
|
||||
|
||||
input wire clk,
|
||||
input wire rst_n,
|
||||
|
|
|
@ -20,8 +20,8 @@ module jtag_tap #(
|
|||
parameter DMI_DATA_BITS = 32,
|
||||
parameter DMI_OP_BITS = 2,
|
||||
parameter IR_BITS = 5,
|
||||
localparam TAP_REQ_BITS = DMI_ADDR_BITS + DMI_DATA_BITS + DMI_OP_BITS,
|
||||
localparam DTM_RESP_BITS = TAP_REQ_BITS
|
||||
parameter TAP_REQ_BITS = DMI_ADDR_BITS + DMI_DATA_BITS + DMI_OP_BITS,
|
||||
parameter DTM_RESP_BITS = TAP_REQ_BITS
|
||||
)(
|
||||
|
||||
input wire jtag_tck_i, // JTAG test clock pad
|
||||
|
|
|
@ -15,15 +15,14 @@
|
|||
*/
|
||||
|
||||
|
||||
module jtag_top #(
|
||||
|
||||
)(
|
||||
module jtag_top(
|
||||
|
||||
input wire clk_i,
|
||||
input wire rst_ni,
|
||||
|
||||
output wire debug_req_o,
|
||||
output wire ndmreset_o,
|
||||
output wire halted_o,
|
||||
|
||||
input wire jtag_tck_i, // JTAG test clock pad
|
||||
input wire jtag_tdi_i, // JTAG test data input pad
|
||||
|
@ -74,6 +73,7 @@ module jtag_top #(
|
|||
.dmi_ready_i (dmi_to_dm_ready),
|
||||
.debug_req_o (debug_req_o),
|
||||
.ndmreset_o (ndmreset_o),
|
||||
.halted_o (halted_o),
|
||||
.master_req_o (master_req_o),
|
||||
.master_gnt_i (master_gnt_i),
|
||||
.master_rvalid_i(master_rvalid_i),
|
||||
|
|
|
@ -79,8 +79,8 @@ module obi_interconnect #(
|
|||
// slave信号赋值
|
||||
generate
|
||||
for (s = 0; s < SLAVES; s = s + 1) begin: slave_signal
|
||||
assign slave_req_o[s] = master_req_i[master_sel_int[s]];
|
||||
assign slave_we_o[s] = master_we_i[master_sel_int[s]];
|
||||
assign slave_req_o[s] = master_req_i[master_sel_int[s]] & granted_master[s];
|
||||
assign slave_we_o[s] = master_we_i[master_sel_int[s]] & granted_master[s];
|
||||
assign slave_be_o[s] = master_be_i[master_sel_int[s]];
|
||||
assign slave_addr_o[s] = master_addr_i[master_sel_int[s]];
|
||||
assign slave_wdata_o[s] = master_wdata_i[master_sel_int[s]];
|
||||
|
|
|
@ -37,8 +37,6 @@ module tinyriscv_soc_top(
|
|||
|
||||
);
|
||||
|
||||
|
||||
|
||||
localparam int MASTERS = 3; // Number of master ports
|
||||
localparam int SLAVES = 3; // Number of slave ports
|
||||
|
||||
|
@ -86,7 +84,9 @@ module tinyriscv_soc_top(
|
|||
wire ndmreset;
|
||||
wire ndmreset_n;
|
||||
wire debug_req;
|
||||
wire core_halted;
|
||||
|
||||
assign halted_ind_pin = core_halted;
|
||||
|
||||
tinyriscv_core #(
|
||||
.DEBUG_HALT_ADDR(`DEBUG_ADDR_BASE + `HaltAddress),
|
||||
|
@ -120,7 +120,6 @@ module tinyriscv_soc_top(
|
|||
.debug_req_i (debug_req)
|
||||
);
|
||||
|
||||
|
||||
assign slave_addr_mask[Rom] = `ROM_ADDR_MASK;
|
||||
assign slave_addr_base[Rom] = `ROM_ADDR_BASE;
|
||||
// 指令存储器
|
||||
|
@ -177,7 +176,6 @@ module tinyriscv_soc_top(
|
|||
.slave_rdata_i (slave_rdata)
|
||||
);
|
||||
|
||||
|
||||
rst_gen #(
|
||||
.RESET_FIFO_DEPTH(5)
|
||||
) u_rst (
|
||||
|
@ -196,6 +194,7 @@ module tinyriscv_soc_top(
|
|||
.rst_ni (rst_ext_ni),
|
||||
.debug_req_o (debug_req),
|
||||
.ndmreset_o (ndmreset),
|
||||
.halted_o (core_halted),
|
||||
.jtag_tck_i (sim_jtag_tck),
|
||||
.jtag_tdi_i (sim_jtag_tdi),
|
||||
.jtag_tms_i (sim_jtag_tms),
|
||||
|
|
|
@ -34,11 +34,14 @@ module tb_top_verilator #(
|
|||
$display("No firmware specified");
|
||||
end
|
||||
end
|
||||
/*
|
||||
|
||||
reg result_printed;
|
||||
|
||||
always @(posedge clk_i or negedge rst_ni) begin
|
||||
if (!rst_ni) begin
|
||||
|
||||
result_printed <= 1'b0;
|
||||
end else begin
|
||||
if (!result_printed) begin
|
||||
if (x26 == 32'b1) begin
|
||||
if (x27 == 32'b1) begin
|
||||
$display("~~~~~~~~~~~~~~~~~~~ TEST_PASS ~~~~~~~~~~~~~~~~~~~");
|
||||
|
@ -61,11 +64,12 @@ module tb_top_verilator #(
|
|||
$display("~~~~~~~~~~# # # # ######~~~~~~~~~~");
|
||||
$display("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
|
||||
end
|
||||
$finish;
|
||||
result_printed <= 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
*/
|
||||
end
|
||||
|
||||
tinyriscv_soc_top u_tinyriscv_soc_top(
|
||||
.clk(clk_i),
|
||||
.rst_ext_ni(rst_ni)
|
||||
|
|
Loading…
Reference in New Issue