temp commit

Signed-off-by: liangkangnan <liangkangnan@163.com>
pull/4/head
liangkangnan 2021-04-29 19:27:25 +08:00
parent 77812d60df
commit f9412fca3c
15 changed files with 823 additions and 626 deletions

View File

@ -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

View File

@ -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,
@ -55,9 +56,9 @@ module exception (
input wire[31:0] debug_halt_addr_i,
input wire debug_req_i,
output wire csr_we_o, // 写CSR寄存器标志
output wire[31:0] csr_waddr_o, // 写CSR寄存器地址
output wire[31:0] csr_wdata_o, // 写CSR寄存器数据
output wire csr_we_o, // 写CSR寄存器标志
output wire[31:0] csr_waddr_o, // 写CSR寄存器地址
output wire[31:0] csr_wdata_o, // 写CSR寄存器数据
output wire stall_flag_o, // 流水线暂停标志
output wire[31:0] int_addr_o, // 中断入口地址
@ -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;
csr_we = 1'b1;
csr_waddr = {20'h0, `CSR_DPC};
csr_wdata = inst_addr_i;
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

View File

@ -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),

View File

@ -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

View File

@ -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
data0_d = dm_op_data;
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
`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),

View File

@ -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

View File

@ -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

View File

@ -14,27 +14,35 @@
limitations under the License.
*/
`include "jtag_def.sv"
module jtag_mem(
module jtag_mem #(
)(
input wire clk,
input wire rst_n,
input wire clk,
input wire rst_n,
output wire halted_o,
output wire resumeack_o,
input wire clear_resumeack_i,
input wire resumereq_i,
input wire haltreq_i,
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,
input wire [3:0] be_i,
input wire [31:0] wdata_i,
output wire [31:0] rdata_o
input wire req_i,
input wire we_i,
input wire [31:0] addr_i,
input wire [3:0] be_i,
input wire [31:0] wdata_i,
output wire [31:0] rdata_o
);
@ -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;

View File

@ -15,9 +15,7 @@
*/
module jtag_sba #(
)(
module jtag_sba(
input wire clk,
input wire rst_n,

View File

@ -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

View File

@ -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),

View File

@ -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]];

View File

@ -37,15 +37,13 @@ module tinyriscv_soc_top(
);
localparam int MASTERS = 3; // Number of master ports
localparam int SLAVES = 3; // Number of slave ports
localparam int MASTERS = 3; // Number of master ports
localparam int SLAVES = 3; // Number of slave ports
// masters
localparam int CoreD = 0;
localparam int JtagHost = 1;
localparam int CoreI = 2;
localparam int CoreD = 0;
localparam int JtagHost = 1;
localparam int CoreI = 2;
// slaves
localparam int Rom = 0;
@ -86,54 +84,55 @@ 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),
.DEBUG_EXCEPTION_ADDR(`DEBUG_ADDR_BASE + `ExceptionAddress)
) u_tinyriscv_core (
.clk(clk),
.rst_n(ndmreset_n),
.clk (clk),
.rst_n (ndmreset_n),
.instr_req_o(master_req[CoreI]),
.instr_gnt_i(master_gnt[CoreI]),
.instr_rvalid_i(master_rvalid[CoreI]),
.instr_addr_o(master_addr[CoreI]),
.instr_rdata_i(master_rdata[CoreI]),
.instr_err_i(1'b0),
.instr_req_o (master_req[CoreI]),
.instr_gnt_i (master_gnt[CoreI]),
.instr_rvalid_i (master_rvalid[CoreI]),
.instr_addr_o (master_addr[CoreI]),
.instr_rdata_i (master_rdata[CoreI]),
.instr_err_i (1'b0),
.data_req_o(master_req[CoreD]),
.data_gnt_i(master_gnt[CoreD]),
.data_rvalid_i(master_rvalid[CoreD]),
.data_we_o(master_we[CoreD]),
.data_be_o(master_be[CoreD]),
.data_addr_o(master_addr[CoreD]),
.data_wdata_o(master_wdata[CoreD]),
.data_rdata_i(master_rdata[CoreD]),
.data_err_i(1'b0),
.data_req_o (master_req[CoreD]),
.data_gnt_i (master_gnt[CoreD]),
.data_rvalid_i (master_rvalid[CoreD]),
.data_we_o (master_we[CoreD]),
.data_be_o (master_be[CoreD]),
.data_addr_o (master_addr[CoreD]),
.data_wdata_o (master_wdata[CoreD]),
.data_rdata_i (master_rdata[CoreD]),
.data_err_i (1'b0),
.irq_software_i(1'b0),
.irq_timer_i(1'b0),
.irq_external_i(1'b0),
.irq_fast_i(15'b0),
.irq_software_i (1'b0),
.irq_timer_i (1'b0),
.irq_external_i (1'b0),
.irq_fast_i (15'b0),
.debug_req_i(debug_req)
.debug_req_i (debug_req)
);
assign slave_addr_mask[Rom] = `ROM_ADDR_MASK;
assign slave_addr_base[Rom] = `ROM_ADDR_BASE;
// 指令存储器
rom #(
.DP(`ROM_DEPTH)
) u_rom(
.clk(clk),
.rst_n(ndmreset_n),
.addr_i(slave_addr[Rom]),
.data_i(slave_wdata[Rom]),
.sel_i(slave_be[Rom]),
.we_i(slave_we[Rom]),
.data_o(slave_rdata[Rom])
) u_rom (
.clk (clk),
.rst_n (ndmreset_n),
.addr_i (slave_addr[Rom]),
.data_i (slave_wdata[Rom]),
.sel_i (slave_be[Rom]),
.we_i (slave_we[Rom]),
.data_o (slave_rdata[Rom])
);
assign slave_addr_mask[Ram] = `RAM_ADDR_MASK;
@ -141,49 +140,48 @@ module tinyriscv_soc_top(
// 数据存储器
ram #(
.DP(`RAM_DEPTH)
) u_ram(
.clk(clk),
.rst_n(ndmreset_n),
.addr_i(slave_addr[Ram]),
.data_i(slave_wdata[Ram]),
.sel_i(slave_be[Ram]),
.we_i(slave_we[Ram]),
.data_o(slave_rdata[Ram])
) u_ram (
.clk (clk),
.rst_n (ndmreset_n),
.addr_i (slave_addr[Ram]),
.data_i (slave_wdata[Ram]),
.sel_i (slave_be[Ram]),
.we_i (slave_we[Ram]),
.data_o (slave_rdata[Ram])
);
obi_interconnect #(
.MASTERS(MASTERS),
.SLAVES(SLAVES)
) bus (
.clk_i(clk),
.rst_ni(ndmreset_n),
.master_req_i(master_req),
.master_gnt_o(master_gnt),
.master_rvalid_o(master_rvalid),
.master_we_i(master_we),
.master_be_i(master_be),
.master_addr_i(master_addr),
.master_wdata_i(master_wdata),
.master_rdata_o(master_rdata),
.slave_addr_mask_i(slave_addr_mask),
.slave_addr_base_i(slave_addr_base),
.slave_req_o(slave_req),
.slave_gnt_i(slave_gnt),
.slave_rvalid_i(slave_rvalid),
.slave_we_o(slave_we),
.slave_be_o(slave_be),
.slave_addr_o(slave_addr),
.slave_wdata_o(slave_wdata),
.slave_rdata_i(slave_rdata)
.clk_i (clk),
.rst_ni (ndmreset_n),
.master_req_i (master_req),
.master_gnt_o (master_gnt),
.master_rvalid_o (master_rvalid),
.master_we_i (master_we),
.master_be_i (master_be),
.master_addr_i (master_addr),
.master_wdata_i (master_wdata),
.master_rdata_o (master_rdata),
.slave_addr_mask_i (slave_addr_mask),
.slave_addr_base_i (slave_addr_base),
.slave_req_o (slave_req),
.slave_gnt_i (slave_gnt),
.slave_rvalid_i (slave_rvalid),
.slave_we_o (slave_we),
.slave_be_o (slave_be),
.slave_addr_o (slave_addr),
.slave_wdata_o (slave_wdata),
.slave_rdata_i (slave_rdata)
);
rst_gen #(
.RESET_FIFO_DEPTH(5)
) u_rst (
.clk(clk),
.rst_ni(rst_ext_ni & (~ndmreset)),
.rst_no(ndmreset_n)
.clk (clk),
.rst_ni (rst_ext_ni & (~ndmreset)),
.rst_no (ndmreset_n)
);
assign slave_addr_mask[JtagDevice] = `DEBUG_ADDR_MASK;
@ -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),

View File

@ -1,175 +1,175 @@
// Copyright 2018 ETH Zurich and University of Bologna.
//
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this 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.
//
// Fabian Schuiki <fschuiki@iis.ee.ethz.ch>
/// A two-phase clock domain crossing.
///
/// CONSTRAINT: Requires max_delay of min_period(src_clk_i, dst_clk_i) through
/// the paths async_req, async_ack, async_data.
/* verilator lint_off DECLFILENAME */
module cdc_2phase #(
parameter DATA_WIDTH = 32
)(
input wire src_rst_ni,
input wire src_clk_i,
input wire [DATA_WIDTH-1:0] src_data_i,
input wire src_valid_i,
output wire src_ready_o,
input wire dst_rst_ni,
input wire dst_clk_i,
output wire [DATA_WIDTH-1:0] dst_data_o,
output wire dst_valid_o,
input wire dst_ready_i
);
// Asynchronous handshake signals.
(* dont_touch = "true" *) wire async_req;
(* dont_touch = "true" *) wire async_ack;
(* dont_touch = "true" *) wire[DATA_WIDTH-1:0] async_data;
// The sender in the source domain.
cdc_2phase_src #(.DATA_WIDTH(DATA_WIDTH)) i_src (
.rst_ni ( src_rst_ni ),
.clk_i ( src_clk_i ),
.data_i ( src_data_i ),
.valid_i ( src_valid_i ),
.ready_o ( src_ready_o ),
.async_req_o ( async_req ),
.async_ack_i ( async_ack ),
.async_data_o ( async_data )
);
// The receiver in the destination domain.
cdc_2phase_dst #(.DATA_WIDTH(DATA_WIDTH)) i_dst (
.rst_ni ( dst_rst_ni ),
.clk_i ( dst_clk_i ),
.data_o ( dst_data_o ),
.valid_o ( dst_valid_o ),
.ready_i ( dst_ready_i ),
.async_req_i ( async_req ),
.async_ack_o ( async_ack ),
.async_data_i ( async_data )
);
endmodule
/// Half of the two-phase clock domain crossing located in the source domain.
module cdc_2phase_src #(
parameter DATA_WIDTH = 32
)(
input wire rst_ni,
input wire clk_i,
input wire [DATA_WIDTH-1:0] data_i,
input wire valid_i,
output wire ready_o,
output wire async_req_o,
input wire async_ack_i,
output wire [DATA_WIDTH-1:0] async_data_o
);
(* dont_touch = "true" *)
reg req_src_q, ack_src_q, ack_q;
(* dont_touch = "true" *)
reg[DATA_WIDTH-1:0] data_src_q;
// The req_src and data_src registers change when a new data item is accepted.
always @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
req_src_q <= 0;
data_src_q <= {DATA_WIDTH{1'b0}};
end else if (valid_i && ready_o) begin
req_src_q <= ~req_src_q;
data_src_q <= data_i;
end
end
// The ack_src and ack registers act as synchronization stages.
always @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
ack_src_q <= 0;
ack_q <= 0;
end else begin
ack_src_q <= async_ack_i;
ack_q <= ack_src_q;
end
end
// Output assignments.
assign ready_o = (req_src_q == ack_q);
assign async_req_o = req_src_q;
assign async_data_o = data_src_q;
endmodule
/// Half of the two-phase clock domain crossing located in the destination
/// domain.
module cdc_2phase_dst #(
parameter DATA_WIDTH = 32
)(
input wire rst_ni,
input wire clk_i,
output wire [DATA_WIDTH-1:0] data_o,
output wire valid_o,
input wire ready_i,
input wire async_req_i,
output wire async_ack_o,
input wire [DATA_WIDTH-1:0] async_data_i
);
(* dont_touch = "true" *)
(* async_reg = "true" *)
reg req_dst_q, req_q0, req_q1, ack_dst_q;
(* dont_touch = "true" *)
reg[DATA_WIDTH-1:0] data_dst_q;
// The ack_dst register changes when a new data item is accepted.
always @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
ack_dst_q <= 0;
end else if (valid_o && ready_i) begin
ack_dst_q <= ~ack_dst_q;
end
end
// The data_dst register changes when a new data item is presented. This is
// indicated by the async_req line changing levels.
always @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
data_dst_q <= '0;
end else if (req_q0 != req_q1 && !valid_o) begin
data_dst_q <= async_data_i;
end
end
// The req_dst and req registers act as synchronization stages.
always @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
req_dst_q <= 0;
req_q0 <= 0;
req_q1 <= 0;
end else begin
req_dst_q <= async_req_i;
req_q0 <= req_dst_q;
req_q1 <= req_q0;
end
end
// Output assignments.
assign valid_o = (ack_dst_q != req_q1);
assign data_o = data_dst_q;
assign async_ack_o = ack_dst_q;
endmodule
/* verilator lint_on DECLFILENAME */
// Copyright 2018 ETH Zurich and University of Bologna.
//
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this 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.
//
// Fabian Schuiki <fschuiki@iis.ee.ethz.ch>
/// A two-phase clock domain crossing.
///
/// CONSTRAINT: Requires max_delay of min_period(src_clk_i, dst_clk_i) through
/// the paths async_req, async_ack, async_data.
/* verilator lint_off DECLFILENAME */
module cdc_2phase #(
parameter DATA_WIDTH = 32
)(
input wire src_rst_ni,
input wire src_clk_i,
input wire [DATA_WIDTH-1:0] src_data_i,
input wire src_valid_i,
output wire src_ready_o,
input wire dst_rst_ni,
input wire dst_clk_i,
output wire [DATA_WIDTH-1:0] dst_data_o,
output wire dst_valid_o,
input wire dst_ready_i
);
// Asynchronous handshake signals.
(* dont_touch = "true" *) wire async_req;
(* dont_touch = "true" *) wire async_ack;
(* dont_touch = "true" *) wire[DATA_WIDTH-1:0] async_data;
// The sender in the source domain.
cdc_2phase_src #(.DATA_WIDTH(DATA_WIDTH)) i_src (
.rst_ni ( src_rst_ni ),
.clk_i ( src_clk_i ),
.data_i ( src_data_i ),
.valid_i ( src_valid_i ),
.ready_o ( src_ready_o ),
.async_req_o ( async_req ),
.async_ack_i ( async_ack ),
.async_data_o ( async_data )
);
// The receiver in the destination domain.
cdc_2phase_dst #(.DATA_WIDTH(DATA_WIDTH)) i_dst (
.rst_ni ( dst_rst_ni ),
.clk_i ( dst_clk_i ),
.data_o ( dst_data_o ),
.valid_o ( dst_valid_o ),
.ready_i ( dst_ready_i ),
.async_req_i ( async_req ),
.async_ack_o ( async_ack ),
.async_data_i ( async_data )
);
endmodule
/// Half of the two-phase clock domain crossing located in the source domain.
module cdc_2phase_src #(
parameter DATA_WIDTH = 32
)(
input wire rst_ni,
input wire clk_i,
input wire [DATA_WIDTH-1:0] data_i,
input wire valid_i,
output wire ready_o,
output wire async_req_o,
input wire async_ack_i,
output wire [DATA_WIDTH-1:0] async_data_o
);
(* dont_touch = "true" *)
reg req_src_q, ack_src_q, ack_q;
(* dont_touch = "true" *)
reg[DATA_WIDTH-1:0] data_src_q;
// The req_src and data_src registers change when a new data item is accepted.
always @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
req_src_q <= 0;
data_src_q <= {DATA_WIDTH{1'b0}};
end else if (valid_i && ready_o) begin
req_src_q <= ~req_src_q;
data_src_q <= data_i;
end
end
// The ack_src and ack registers act as synchronization stages.
always @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
ack_src_q <= 0;
ack_q <= 0;
end else begin
ack_src_q <= async_ack_i;
ack_q <= ack_src_q;
end
end
// Output assignments.
assign ready_o = (req_src_q == ack_q);
assign async_req_o = req_src_q;
assign async_data_o = data_src_q;
endmodule
/// Half of the two-phase clock domain crossing located in the destination
/// domain.
module cdc_2phase_dst #(
parameter DATA_WIDTH = 32
)(
input wire rst_ni,
input wire clk_i,
output wire [DATA_WIDTH-1:0] data_o,
output wire valid_o,
input wire ready_i,
input wire async_req_i,
output wire async_ack_o,
input wire [DATA_WIDTH-1:0] async_data_i
);
(* dont_touch = "true" *)
(* async_reg = "true" *)
reg req_dst_q, req_q0, req_q1, ack_dst_q;
(* dont_touch = "true" *)
reg[DATA_WIDTH-1:0] data_dst_q;
// The ack_dst register changes when a new data item is accepted.
always @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
ack_dst_q <= 0;
end else if (valid_o && ready_i) begin
ack_dst_q <= ~ack_dst_q;
end
end
// The data_dst register changes when a new data item is presented. This is
// indicated by the async_req line changing levels.
always @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
data_dst_q <= '0;
end else if (req_q0 != req_q1 && !valid_o) begin
data_dst_q <= async_data_i;
end
end
// The req_dst and req registers act as synchronization stages.
always @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
req_dst_q <= 0;
req_q0 <= 0;
req_q1 <= 0;
end else begin
req_dst_q <= async_req_i;
req_q0 <= req_dst_q;
req_q1 <= req_q0;
end
end
// Output assignments.
assign valid_o = (ack_dst_q != req_q1);
assign data_o = data_dst_q;
assign async_ack_o = ack_dst_q;
endmodule
/* verilator lint_on DECLFILENAME */

View File

@ -34,38 +34,42 @@ 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 (x26 == 32'b1) begin
if (x27 == 32'b1) begin
$display("~~~~~~~~~~~~~~~~~~~ TEST_PASS ~~~~~~~~~~~~~~~~~~~");
$display("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
$display("~~~~~~~~~ ##### ## #### #### ~~~~~~~~~");
$display("~~~~~~~~~ # # # # # # ~~~~~~~~~");
$display("~~~~~~~~~ # # # # #### #### ~~~~~~~~~");
$display("~~~~~~~~~ ##### ###### # #~~~~~~~~~");
$display("~~~~~~~~~ # # # # # # #~~~~~~~~~");
$display("~~~~~~~~~ # # # #### #### ~~~~~~~~~");
$display("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
end else begin
$display("~~~~~~~~~~~~~~~~~~~ TEST_FAIL ~~~~~~~~~~~~~~~~~~~~");
$display("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
$display("~~~~~~~~~~###### ## # # ~~~~~~~~~~");
$display("~~~~~~~~~~# # # # # ~~~~~~~~~~");
$display("~~~~~~~~~~##### # # # # ~~~~~~~~~~");
$display("~~~~~~~~~~# ###### # # ~~~~~~~~~~");
$display("~~~~~~~~~~# # # # # ~~~~~~~~~~");
$display("~~~~~~~~~~# # # # ######~~~~~~~~~~");
$display("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
if (!result_printed) begin
if (x26 == 32'b1) begin
if (x27 == 32'b1) begin
$display("~~~~~~~~~~~~~~~~~~~ TEST_PASS ~~~~~~~~~~~~~~~~~~~");
$display("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
$display("~~~~~~~~~ ##### ## #### #### ~~~~~~~~~");
$display("~~~~~~~~~ # # # # # # ~~~~~~~~~");
$display("~~~~~~~~~ # # # # #### #### ~~~~~~~~~");
$display("~~~~~~~~~ ##### ###### # #~~~~~~~~~");
$display("~~~~~~~~~ # # # # # # #~~~~~~~~~");
$display("~~~~~~~~~ # # # #### #### ~~~~~~~~~");
$display("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
end else begin
$display("~~~~~~~~~~~~~~~~~~~ TEST_FAIL ~~~~~~~~~~~~~~~~~~~~");
$display("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
$display("~~~~~~~~~~###### ## # # ~~~~~~~~~~");
$display("~~~~~~~~~~# # # # # ~~~~~~~~~~");
$display("~~~~~~~~~~##### # # # # ~~~~~~~~~~");
$display("~~~~~~~~~~# ###### # # ~~~~~~~~~~");
$display("~~~~~~~~~~# # # # # ~~~~~~~~~~");
$display("~~~~~~~~~~# # # # ######~~~~~~~~~~");
$display("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
end
result_printed <= 1'b1;
end
$finish;
end
end
end
*/
tinyriscv_soc_top u_tinyriscv_soc_top(
.clk(clk_i),
.rst_ext_ni(rst_ni)