parent
462cc4c786
commit
ec65381ba9
19
rtl.flist
19
rtl.flist
|
@ -1,11 +1,11 @@
|
||||||
|
|
||||||
+incdir+../rtl/core
|
+incdir+../rtl/core
|
||||||
|
+incdir+../rtl/debug
|
||||||
|
|
||||||
../rtl/core/clint.sv
|
|
||||||
../rtl/core/csr_reg.sv
|
../rtl/core/csr_reg.sv
|
||||||
../rtl/core/csr.sv
|
../rtl/core/csr.sv
|
||||||
../rtl/core/defines.sv
|
../rtl/core/defines.sv
|
||||||
../rtl/core/divider.sv
|
../rtl/core/divider.sv
|
||||||
|
../rtl/core/exception.sv
|
||||||
../rtl/core/exu.sv
|
../rtl/core/exu.sv
|
||||||
../rtl/core/exu_alu_datapath.sv
|
../rtl/core/exu_alu_datapath.sv
|
||||||
../rtl/core/exu_commit.sv
|
../rtl/core/exu_commit.sv
|
||||||
|
@ -22,9 +22,15 @@
|
||||||
../rtl/core/tinyriscv_core.sv
|
../rtl/core/tinyriscv_core.sv
|
||||||
../rtl/core/tracer.sv
|
../rtl/core/tracer.sv
|
||||||
|
|
||||||
|
../rtl/debug/jtag_def.sv
|
||||||
|
../rtl/debug/jtag_tap.sv
|
||||||
|
../rtl/debug/jtag_dtm.sv
|
||||||
|
../rtl/debug/jtag_dmi.sv
|
||||||
../rtl/debug/jtag_dm.sv
|
../rtl/debug/jtag_dm.sv
|
||||||
../rtl/debug/jtag_driver.sv
|
../rtl/debug/jtag_mem.sv
|
||||||
|
../rtl/debug/jtag_sba.sv
|
||||||
../rtl/debug/jtag_top.sv
|
../rtl/debug/jtag_top.sv
|
||||||
|
../rtl/debug/debug_rom.sv
|
||||||
|
|
||||||
../rtl/perips/gpio.sv
|
../rtl/perips/gpio.sv
|
||||||
../rtl/perips/ram.sv
|
../rtl/perips/ram.sv
|
||||||
|
@ -32,18 +38,13 @@
|
||||||
../rtl/perips/timer.sv
|
../rtl/perips/timer.sv
|
||||||
../rtl/perips/uart.sv
|
../rtl/perips/uart.sv
|
||||||
|
|
||||||
../rtl/sys_bus/rib.sv
|
|
||||||
../rtl/sys_bus/obi_interconnect.sv
|
../rtl/sys_bus/obi_interconnect.sv
|
||||||
../rtl/sys_bus/obi_interconnect_master_sel.sv
|
../rtl/sys_bus/obi_interconnect_master_sel.sv
|
||||||
../rtl/sys_bus/obi_interconnect_slave_sel.sv
|
../rtl/sys_bus/obi_interconnect_slave_sel.sv
|
||||||
|
|
||||||
../rtl/top/tinyriscv_soc_top.sv
|
../rtl/top/tinyriscv_soc_top.sv
|
||||||
|
|
||||||
../rtl/utils/full_handshake_rx.sv
|
|
||||||
../rtl/utils/full_handshake_tx.sv
|
|
||||||
../rtl/utils/gen_buf.sv
|
../rtl/utils/gen_buf.sv
|
||||||
../rtl/utils/gen_dff.sv
|
../rtl/utils/gen_dff.sv
|
||||||
../rtl/utils/gen_ram.sv
|
../rtl/utils/gen_ram.sv
|
||||||
../rtl/utils/vld_rdy.sv
|
../rtl/utils/cdc_2phase.sv
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,223 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
`include "defines.sv"
|
|
||||||
|
|
||||||
// core local interruptor module
|
|
||||||
// 核心中断管理、仲裁模块
|
|
||||||
module clint(
|
|
||||||
|
|
||||||
input wire clk,
|
|
||||||
input wire rst_n,
|
|
||||||
|
|
||||||
// from core
|
|
||||||
input wire[`INT_WIDTH-1:0] int_flag_i, // 中断输入信号
|
|
||||||
|
|
||||||
// from exu
|
|
||||||
input wire inst_ecall_i, // ecall指令
|
|
||||||
input wire inst_ebreak_i, // ebreak指令
|
|
||||||
input wire inst_mret_i, // mret指令
|
|
||||||
input wire[31:0] inst_addr_i, // 指令地址
|
|
||||||
input wire jump_flag_i,
|
|
||||||
input wire mem_access_misaligned_i,
|
|
||||||
|
|
||||||
// from csr_reg
|
|
||||||
input wire[31:0] csr_mtvec_i, // mtvec寄存器
|
|
||||||
input wire[31:0] csr_mepc_i, // mepc寄存器
|
|
||||||
input wire[31:0] csr_mstatus_i, // mstatus寄存器
|
|
||||||
|
|
||||||
// to csr_reg
|
|
||||||
output reg csr_we_o, // 写CSR寄存器标志
|
|
||||||
output reg[31:0] csr_waddr_o, // 写CSR寄存器地址
|
|
||||||
output reg[31:0] csr_wdata_o, // 写CSR寄存器数据
|
|
||||||
|
|
||||||
// to pipe_ctrl
|
|
||||||
output wire stall_flag_o, // 流水线暂停标志
|
|
||||||
output wire[31:0] int_addr_o, // 中断入口地址
|
|
||||||
output wire int_assert_o // 中断标志
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
// 中断状态定义
|
|
||||||
localparam S_INT_IDLE = 4'b0001;
|
|
||||||
localparam S_INT_SYNC_ASSERT = 4'b0010;
|
|
||||||
localparam S_INT_ASYNC_ASSERT = 4'b0100;
|
|
||||||
localparam S_INT_MRET = 4'b1000;
|
|
||||||
|
|
||||||
// 写CSR寄存器状态定义
|
|
||||||
localparam S_CSR_IDLE = 5'b00001;
|
|
||||||
localparam S_CSR_MSTATUS = 5'b00010;
|
|
||||||
localparam S_CSR_MEPC = 5'b00100;
|
|
||||||
localparam S_CSR_MSTATUS_MRET = 5'b01000;
|
|
||||||
localparam S_CSR_MCAUSE = 5'b10000;
|
|
||||||
|
|
||||||
reg[3:0] int_state;
|
|
||||||
reg[4:0] csr_state;
|
|
||||||
reg[31:0] inst_addr;
|
|
||||||
reg[31:0] cause;
|
|
||||||
|
|
||||||
wire global_int_en = csr_mstatus_i[3];
|
|
||||||
|
|
||||||
assign stall_flag_o = ((int_state != S_INT_IDLE) | (csr_state != S_CSR_IDLE))? 1'b1: 1'b0;
|
|
||||||
|
|
||||||
// 将跳转标志放在流水线上传递
|
|
||||||
wire pc_state_jump_flag;
|
|
||||||
gen_rst_0_dff #(1) pc_state_dff(clk, rst_n, jump_flag_i, pc_state_jump_flag);
|
|
||||||
|
|
||||||
wire if_state_jump_flag;
|
|
||||||
gen_rst_0_dff #(1) if_state_dff(clk, rst_n, pc_state_jump_flag, if_state_jump_flag);
|
|
||||||
|
|
||||||
wire id_state_jump_flag;
|
|
||||||
gen_rst_0_dff #(1) id_state_dff(clk, rst_n, if_state_jump_flag, id_state_jump_flag);
|
|
||||||
|
|
||||||
wire ex_state_jump_flag;
|
|
||||||
gen_rst_0_dff #(1) ex_state_dff(clk, rst_n, id_state_jump_flag, ex_state_jump_flag);
|
|
||||||
|
|
||||||
wire[3:0] state_jump_flag = {pc_state_jump_flag, if_state_jump_flag, id_state_jump_flag, ex_state_jump_flag};
|
|
||||||
// 如果流水线没有冲刷完成则不响应中断
|
|
||||||
wire inst_addr_valid = (~(|state_jump_flag)) | ex_state_jump_flag;
|
|
||||||
|
|
||||||
|
|
||||||
// 中断仲裁逻辑
|
|
||||||
always @ (*) begin
|
|
||||||
// 同步中断
|
|
||||||
if (inst_ecall_i | inst_ebreak_i | mem_access_misaligned_i) begin
|
|
||||||
int_state = S_INT_SYNC_ASSERT;
|
|
||||||
// 异步中断
|
|
||||||
end else if ((int_flag_i != `INT_NONE) & global_int_en & inst_addr_valid) begin
|
|
||||||
int_state = S_INT_ASYNC_ASSERT;
|
|
||||||
// 中断返回
|
|
||||||
end else if (inst_mret_i) begin
|
|
||||||
int_state = S_INT_MRET;
|
|
||||||
// 无中断响应
|
|
||||||
end else begin
|
|
||||||
int_state = S_INT_IDLE;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
// 写CSR寄存器状态切换
|
|
||||||
always @ (posedge clk or negedge rst_n) begin
|
|
||||||
if (!rst_n) begin
|
|
||||||
csr_state <= S_CSR_IDLE;
|
|
||||||
cause <= 32'h0;
|
|
||||||
inst_addr <= 32'h0;
|
|
||||||
end else begin
|
|
||||||
case (csr_state)
|
|
||||||
S_CSR_IDLE: begin
|
|
||||||
case (int_state)
|
|
||||||
// 同步中断
|
|
||||||
S_INT_SYNC_ASSERT: begin
|
|
||||||
csr_state <= S_CSR_MEPC;
|
|
||||||
// 在中断处理函数里会将中断返回地址加4
|
|
||||||
inst_addr <= inst_addr_i;
|
|
||||||
cause <= inst_ebreak_i? 32'd3:
|
|
||||||
inst_ecall_i? 32'd11:
|
|
||||||
mem_access_misaligned_i? 32'd4:
|
|
||||||
32'd10;
|
|
||||||
end
|
|
||||||
// 异步中断
|
|
||||||
S_INT_ASYNC_ASSERT: begin
|
|
||||||
csr_state <= S_CSR_MEPC;
|
|
||||||
inst_addr <= inst_addr_i;
|
|
||||||
// 定时器中断
|
|
||||||
cause <= 32'h80000004;
|
|
||||||
end
|
|
||||||
// 中断返回
|
|
||||||
S_INT_MRET: begin
|
|
||||||
csr_state <= S_CSR_MSTATUS_MRET;
|
|
||||||
end
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
S_CSR_MEPC: begin
|
|
||||||
csr_state <= S_CSR_MSTATUS;
|
|
||||||
end
|
|
||||||
S_CSR_MSTATUS: begin
|
|
||||||
csr_state <= S_CSR_MCAUSE;
|
|
||||||
end
|
|
||||||
S_CSR_MCAUSE: begin
|
|
||||||
csr_state <= S_CSR_IDLE;
|
|
||||||
end
|
|
||||||
S_CSR_MSTATUS_MRET: begin
|
|
||||||
csr_state <= S_CSR_IDLE;
|
|
||||||
end
|
|
||||||
default: begin
|
|
||||||
csr_state <= S_CSR_IDLE;
|
|
||||||
end
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
// 发出中断信号前,先写几个CSR寄存器
|
|
||||||
always @ (posedge clk or negedge rst_n) begin
|
|
||||||
if (!rst_n) begin
|
|
||||||
csr_we_o <= 1'b0;
|
|
||||||
csr_waddr_o <= 32'h0;
|
|
||||||
csr_wdata_o <= 32'h0;
|
|
||||||
end else begin
|
|
||||||
case (csr_state)
|
|
||||||
// 将mepc寄存器的值设为当前指令地址
|
|
||||||
S_CSR_MEPC: begin
|
|
||||||
csr_we_o <= 1'b1;
|
|
||||||
csr_waddr_o <= {20'h0, `CSR_MEPC};
|
|
||||||
csr_wdata_o <= inst_addr;
|
|
||||||
end
|
|
||||||
// 写中断产生的原因
|
|
||||||
S_CSR_MCAUSE: begin
|
|
||||||
csr_we_o <= 1'b1;
|
|
||||||
csr_waddr_o <= {20'h0, `CSR_MCAUSE};
|
|
||||||
csr_wdata_o <= cause;
|
|
||||||
end
|
|
||||||
// 关闭全局中断
|
|
||||||
S_CSR_MSTATUS: begin
|
|
||||||
csr_we_o <= 1'b1;
|
|
||||||
csr_waddr_o <= {20'h0, `CSR_MSTATUS};
|
|
||||||
csr_wdata_o <= {csr_mstatus_i[31:4], 1'b0, csr_mstatus_i[2:0]};
|
|
||||||
end
|
|
||||||
// 中断返回
|
|
||||||
S_CSR_MSTATUS_MRET: begin
|
|
||||||
csr_we_o <= 1'b1;
|
|
||||||
csr_waddr_o <= {20'h0, `CSR_MSTATUS};
|
|
||||||
csr_wdata_o <= {csr_mstatus_i[31:4], csr_mstatus_i[7], csr_mstatus_i[2:0]};
|
|
||||||
end
|
|
||||||
default: begin
|
|
||||||
csr_we_o <= 1'b0;
|
|
||||||
csr_waddr_o <= 32'h0;
|
|
||||||
csr_wdata_o <= 32'h0;
|
|
||||||
end
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
reg in_int_context;
|
|
||||||
|
|
||||||
always @ (posedge clk or negedge rst_n) begin
|
|
||||||
if (!rst_n) begin
|
|
||||||
in_int_context <= 1'b0;
|
|
||||||
end else begin
|
|
||||||
if (csr_state == S_CSR_MSTATUS_MRET) begin
|
|
||||||
in_int_context <= 1'b0;
|
|
||||||
end else if (csr_state != S_CSR_IDLE) begin
|
|
||||||
in_int_context <= 1'b1;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
assign int_assert_o = (csr_state == S_CSR_MCAUSE) | (csr_state == S_CSR_MSTATUS_MRET);
|
|
||||||
assign int_addr_o = (csr_state == S_CSR_MCAUSE)? csr_mtvec_i:
|
|
||||||
(csr_state == S_CSR_MSTATUS_MRET)? csr_mepc_i:
|
|
||||||
32'h0;
|
|
||||||
|
|
||||||
endmodule
|
|
|
@ -36,7 +36,9 @@ module csr_reg(
|
||||||
|
|
||||||
output wire[31:0] mtvec_o, // mtvec寄存器值
|
output wire[31:0] mtvec_o, // mtvec寄存器值
|
||||||
output wire[31:0] mepc_o, // mepc寄存器值
|
output wire[31:0] mepc_o, // mepc寄存器值
|
||||||
output wire[31:0] mstatus_o // mstatus寄存器值
|
output wire[31:0] mstatus_o, // mstatus寄存器值
|
||||||
|
output wire[31:0] mie_o, // mie寄存器值
|
||||||
|
output wire[31:0] dpc_o // dpc寄存器值
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -67,6 +69,9 @@ module csr_reg(
|
||||||
reg[31:0] mhartid_d;
|
reg[31:0] mhartid_d;
|
||||||
wire[31:0] mhartid_q;
|
wire[31:0] mhartid_q;
|
||||||
reg mhartid_we;
|
reg mhartid_we;
|
||||||
|
reg[31:0] dpc_d;
|
||||||
|
wire[31:0] dpc_q;
|
||||||
|
reg dpc_we;
|
||||||
|
|
||||||
reg[63:0] cycle;
|
reg[63:0] cycle;
|
||||||
|
|
||||||
|
@ -83,6 +88,8 @@ module csr_reg(
|
||||||
assign mtvec_o = mtvec_q;
|
assign mtvec_o = mtvec_q;
|
||||||
assign mepc_o = mepc_q;
|
assign mepc_o = mepc_q;
|
||||||
assign mstatus_o = mstatus_q;
|
assign mstatus_o = mstatus_q;
|
||||||
|
assign mie_o = mie_q;
|
||||||
|
assign dpc_o = dpc_q;
|
||||||
|
|
||||||
reg[31:0] exu_rdata;
|
reg[31:0] exu_rdata;
|
||||||
|
|
||||||
|
@ -122,6 +129,9 @@ module csr_reg(
|
||||||
`CSR_MHARTID: begin
|
`CSR_MHARTID: begin
|
||||||
exu_rdata = mhartid_q;
|
exu_rdata = mhartid_q;
|
||||||
end
|
end
|
||||||
|
`CSR_DPC: begin
|
||||||
|
exu_rdata = dpc_q;
|
||||||
|
end
|
||||||
default: begin
|
default: begin
|
||||||
exu_rdata = 32'h0;
|
exu_rdata = 32'h0;
|
||||||
end
|
end
|
||||||
|
@ -154,6 +164,8 @@ module csr_reg(
|
||||||
dscratch1_we = 1'b0;
|
dscratch1_we = 1'b0;
|
||||||
mhartid_d = mhartid_q;
|
mhartid_d = mhartid_q;
|
||||||
mhartid_we = 1'b0;
|
mhartid_we = 1'b0;
|
||||||
|
dpc_d = dpc_q;
|
||||||
|
dpc_we = 1'b0;
|
||||||
|
|
||||||
if (we) begin
|
if (we) begin
|
||||||
case (waddr[11:0])
|
case (waddr[11:0])
|
||||||
|
@ -193,6 +205,10 @@ module csr_reg(
|
||||||
mhartid_d = wdata;
|
mhartid_d = wdata;
|
||||||
mhartid_we = 1'b1;
|
mhartid_we = 1'b1;
|
||||||
end
|
end
|
||||||
|
`CSR_DPC: begin
|
||||||
|
dpc_d = wdata;
|
||||||
|
dpc_we = 1'b1;
|
||||||
|
end
|
||||||
default:;
|
default:;
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
@ -297,4 +313,15 @@ module csr_reg(
|
||||||
.rdata_o(mhartid_q)
|
.rdata_o(mhartid_q)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// dpc
|
||||||
|
csr #(
|
||||||
|
.RESET_VAL(32'h0)
|
||||||
|
) dpc_csr (
|
||||||
|
.clk(clk),
|
||||||
|
.rst_n(rst_n),
|
||||||
|
.wdata_i(dpc_d),
|
||||||
|
.we_i(dpc_we),
|
||||||
|
.rdata_o(dpc_q)
|
||||||
|
);
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
@ -54,6 +54,7 @@
|
||||||
`define INST_MRET 32'h30200073
|
`define INST_MRET 32'h30200073
|
||||||
`define INST_ECALL 32'h00000073
|
`define INST_ECALL 32'h00000073
|
||||||
`define INST_EBREAK 32'h00100073
|
`define INST_EBREAK 32'h00100073
|
||||||
|
`define INST_DRET 32'h7b200073
|
||||||
|
|
||||||
// 指令译码信息
|
// 指令译码信息
|
||||||
`define DECINFO_GRP_BUS 2:0
|
`define DECINFO_GRP_BUS 2:0
|
||||||
|
@ -118,12 +119,13 @@
|
||||||
`define DECINFO_MEM_SH (`DECINFO_GRP_WIDTH+6)
|
`define DECINFO_MEM_SH (`DECINFO_GRP_WIDTH+6)
|
||||||
`define DECINFO_MEM_SW (`DECINFO_GRP_WIDTH+7)
|
`define DECINFO_MEM_SW (`DECINFO_GRP_WIDTH+7)
|
||||||
|
|
||||||
`define DECINFO_SYS_BUS_WIDTH (`DECINFO_GRP_WIDTH+5)
|
`define DECINFO_SYS_BUS_WIDTH (`DECINFO_GRP_WIDTH+6)
|
||||||
`define DECINFO_SYS_ECALL (`DECINFO_GRP_WIDTH+0)
|
`define DECINFO_SYS_ECALL (`DECINFO_GRP_WIDTH+0)
|
||||||
`define DECINFO_SYS_EBREAK (`DECINFO_GRP_WIDTH+1)
|
`define DECINFO_SYS_EBREAK (`DECINFO_GRP_WIDTH+1)
|
||||||
`define DECINFO_SYS_NOP (`DECINFO_GRP_WIDTH+2)
|
`define DECINFO_SYS_NOP (`DECINFO_GRP_WIDTH+2)
|
||||||
`define DECINFO_SYS_MRET (`DECINFO_GRP_WIDTH+3)
|
`define DECINFO_SYS_MRET (`DECINFO_GRP_WIDTH+3)
|
||||||
`define DECINFO_SYS_FENCE (`DECINFO_GRP_WIDTH+4)
|
`define DECINFO_SYS_FENCE (`DECINFO_GRP_WIDTH+4)
|
||||||
|
`define DECINFO_SYS_DRET (`DECINFO_GRP_WIDTH+5)
|
||||||
|
|
||||||
// 最长的那组
|
// 最长的那组
|
||||||
`define DECINFO_WIDTH `DECINFO_CSR_BUS_WIDTH
|
`define DECINFO_WIDTH `DECINFO_CSR_BUS_WIDTH
|
||||||
|
@ -137,6 +139,8 @@
|
||||||
`define CSR_MIE 12'h304
|
`define CSR_MIE 12'h304
|
||||||
`define CSR_MSTATUS 12'h300
|
`define CSR_MSTATUS 12'h300
|
||||||
`define CSR_MSCRATCH 12'h340
|
`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_DSCRATCH0 12'h7b2
|
||||||
`define CSR_DSCRATCH1 12'h7b3
|
`define CSR_DSCRATCH1 12'h7b3
|
||||||
`define CSR_MHARTID 12'hF14
|
|
||||||
|
|
|
@ -0,0 +1,262 @@
|
||||||
|
/*
|
||||||
|
Copyright 2021 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
`include "defines.sv"
|
||||||
|
|
||||||
|
`define CAUSE_IRQ_EXTERNAL_M {1'b1, 31'd11}
|
||||||
|
`define CAUSE_IRQ_SOFTWARE_M {1'b1, 31'd3}
|
||||||
|
`define CAUSE_IRQ_TIMER_M {1'b1, 31'd7}
|
||||||
|
|
||||||
|
`define CAUSE_EXCEP_ECALL_M {1'b0, 31'd11}
|
||||||
|
`define CAUSE_EXCEP_EBREAK_M {1'b0, 31'd3}
|
||||||
|
|
||||||
|
`define MIE_MTIE_BIT 7
|
||||||
|
`define MIE_MEIE_BIT 11
|
||||||
|
`define MIE_MSIE_BIT 3
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
module exception (
|
||||||
|
|
||||||
|
input wire clk,
|
||||||
|
input wire rst_n,
|
||||||
|
|
||||||
|
input wire inst_valid_i,
|
||||||
|
input wire inst_ecall_i, // ecall指令
|
||||||
|
input wire inst_ebreak_i, // ebreak指令
|
||||||
|
input wire inst_mret_i, // mret指令
|
||||||
|
input wire inst_dret_i, // dret指令
|
||||||
|
input wire[31:0] inst_addr_i, // 指令地址
|
||||||
|
|
||||||
|
input wire[31:0] mtvec_i, // mtvec寄存器
|
||||||
|
input wire[31:0] mepc_i, // mepc寄存器
|
||||||
|
input wire[31:0] mstatus_i, // mstatus寄存器
|
||||||
|
input wire[31:0] mie_i, // mie寄存器
|
||||||
|
input wire[31:0] dpc_i, // dpc寄存器
|
||||||
|
|
||||||
|
input wire irq_software_i,
|
||||||
|
input wire irq_timer_i,
|
||||||
|
input wire irq_external_i,
|
||||||
|
input wire[14:0] irq_fast_i,
|
||||||
|
|
||||||
|
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 stall_flag_o, // 流水线暂停标志
|
||||||
|
output wire[31:0] int_addr_o, // 中断入口地址
|
||||||
|
output wire int_assert_o // 中断标志
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
localparam ILLEGAL_INSTR_OFFSET = 0;
|
||||||
|
localparam INSTR_ADDR_MISA_OFFSET = 4;
|
||||||
|
localparam ECALL_OFFSET = 8;
|
||||||
|
localparam EBREAK_OFFSET = 12;
|
||||||
|
localparam LOAD_MISA_OFFSET = 16;
|
||||||
|
localparam STORE_MISA_OFFSET = 20;
|
||||||
|
localparam RESERVED1_EXCEPTION_OFFSET = 24;
|
||||||
|
localparam RESERVED2_EXCEPTION_OFFSET = 28;
|
||||||
|
|
||||||
|
localparam EXTERNAL_INT_OFFSET = 32;
|
||||||
|
localparam SOFTWARE_INT_OFFSET = 36;
|
||||||
|
localparam TIMER_INT_OFFSET = 40;
|
||||||
|
localparam FAST_INT_OFFSET = 44;
|
||||||
|
|
||||||
|
|
||||||
|
localparam S_IDLE = 3'b001;
|
||||||
|
localparam S_W_MEPC = 3'b010;
|
||||||
|
localparam S_ASSERT = 3'b100;
|
||||||
|
|
||||||
|
|
||||||
|
reg debug_mode_d, debug_mode_q;
|
||||||
|
reg[2:0] state_d, state_q;
|
||||||
|
reg[31:0] assert_addr_d, assert_addr_q;
|
||||||
|
reg[31:0] return_addr_d, return_addr_q;
|
||||||
|
reg csr_we;
|
||||||
|
reg[31:0] csr_waddr;
|
||||||
|
reg[31:0] csr_wdata;
|
||||||
|
|
||||||
|
wire global_int_en;
|
||||||
|
|
||||||
|
assign global_int_en = mstatus_i[3];
|
||||||
|
|
||||||
|
reg[3:0] fast_irq_id;
|
||||||
|
wire fast_irq_req;
|
||||||
|
|
||||||
|
always @ (*) begin
|
||||||
|
if (irq_fast_i[ 0]) fast_irq_id = 4'd0;
|
||||||
|
else if (irq_fast_i[ 1]) fast_irq_id = 4'd1;
|
||||||
|
else if (irq_fast_i[ 2]) fast_irq_id = 4'd2;
|
||||||
|
else if (irq_fast_i[ 3]) fast_irq_id = 4'd3;
|
||||||
|
else if (irq_fast_i[ 4]) fast_irq_id = 4'd4;
|
||||||
|
else if (irq_fast_i[ 5]) fast_irq_id = 4'd5;
|
||||||
|
else if (irq_fast_i[ 6]) fast_irq_id = 4'd6;
|
||||||
|
else if (irq_fast_i[ 7]) fast_irq_id = 4'd7;
|
||||||
|
else if (irq_fast_i[ 8]) fast_irq_id = 4'd8;
|
||||||
|
else if (irq_fast_i[ 9]) fast_irq_id = 4'd9;
|
||||||
|
else if (irq_fast_i[10]) fast_irq_id = 4'd10;
|
||||||
|
else if (irq_fast_i[11]) fast_irq_id = 4'd11;
|
||||||
|
else if (irq_fast_i[12]) fast_irq_id = 4'd12;
|
||||||
|
else if (irq_fast_i[13]) fast_irq_id = 4'd13;
|
||||||
|
else fast_irq_id = 4'd14;
|
||||||
|
end
|
||||||
|
|
||||||
|
assign fast_irq_req = |irq_fast_i;
|
||||||
|
|
||||||
|
reg interrupt_req_tmp;
|
||||||
|
reg[31:0] interrupt_cause;
|
||||||
|
reg[31:0] interrupt_offset;
|
||||||
|
wire interrupt_req = inst_valid_i & interrupt_req_tmp;
|
||||||
|
|
||||||
|
always @ (*) begin
|
||||||
|
if (fast_irq_req) begin
|
||||||
|
interrupt_req_tmp = 1'b1;
|
||||||
|
interrupt_cause = {1'b1, {26{1'b0}}, 1'b1, fast_irq_id};
|
||||||
|
interrupt_offset = {fast_irq_id, 2'b0} + FAST_INT_OFFSET;
|
||||||
|
end else if (irq_external_i & mie_i[`MIE_MEIE_BIT]) begin
|
||||||
|
interrupt_req_tmp = 1'b1;
|
||||||
|
interrupt_cause = `CAUSE_IRQ_EXTERNAL_M;
|
||||||
|
interrupt_offset = EXTERNAL_INT_OFFSET;
|
||||||
|
end else if (irq_software_i & mie_i[`MIE_MSIE_BIT]) begin
|
||||||
|
interrupt_req_tmp = 1'b1;
|
||||||
|
interrupt_cause = `CAUSE_IRQ_SOFTWARE_M;
|
||||||
|
interrupt_offset = SOFTWARE_INT_OFFSET;
|
||||||
|
end else if (irq_timer_i & mie_i[`MIE_MTIE_BIT]) begin
|
||||||
|
interrupt_req_tmp = 1'b1;
|
||||||
|
interrupt_cause = `CAUSE_IRQ_TIMER_M;
|
||||||
|
interrupt_offset = TIMER_INT_OFFSET;
|
||||||
|
end else begin
|
||||||
|
interrupt_req_tmp = 1'b0;
|
||||||
|
interrupt_cause = 32'h0;
|
||||||
|
interrupt_offset = 32'h0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
reg exception_req;
|
||||||
|
reg[31:0] exception_cause;
|
||||||
|
reg[31:0] exception_offset;
|
||||||
|
|
||||||
|
always @ (*) begin
|
||||||
|
if (inst_ecall_i) begin
|
||||||
|
exception_req = 1'b1;
|
||||||
|
exception_cause = `CAUSE_EXCEP_ECALL_M;
|
||||||
|
exception_offset = ECALL_OFFSET;
|
||||||
|
end else if (inst_ebreak_i) begin
|
||||||
|
exception_req = 1'b1;
|
||||||
|
exception_cause = `CAUSE_EXCEP_EBREAK_M;
|
||||||
|
exception_offset = EBREAK_OFFSET;
|
||||||
|
end else begin
|
||||||
|
exception_req = 1'b0;
|
||||||
|
exception_cause = 32'h0;
|
||||||
|
exception_offset = 32'h0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
wire int_or_exception_req;
|
||||||
|
wire[31:0] int_or_exception_cause;
|
||||||
|
wire[31:0] int_or_exception_offset;
|
||||||
|
|
||||||
|
assign int_or_exception_req = (interrupt_req & global_int_en) | exception_req;
|
||||||
|
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;
|
||||||
|
|
||||||
|
assign stall_flag_o = ((state_q != S_IDLE) & (state_q != S_ASSERT)) |
|
||||||
|
(interrupt_req & global_int_en) | exception_req |
|
||||||
|
debug_mode_req |
|
||||||
|
inst_mret_i |
|
||||||
|
inst_dret_i;
|
||||||
|
|
||||||
|
always @ (*) begin
|
||||||
|
state_d = state_q;
|
||||||
|
assert_addr_d = assert_addr_q;
|
||||||
|
debug_mode_d = debug_mode_q;
|
||||||
|
return_addr_d = return_addr_q;
|
||||||
|
csr_we = 1'b0;
|
||||||
|
csr_waddr = 32'h0;
|
||||||
|
csr_wdata = 32'h0;
|
||||||
|
|
||||||
|
case (state_q)
|
||||||
|
S_IDLE: begin
|
||||||
|
if (int_or_exception_req) begin
|
||||||
|
csr_we = 1'b1;
|
||||||
|
csr_waddr = {20'h0, `CSR_MCAUSE};
|
||||||
|
csr_wdata = int_or_exception_cause;
|
||||||
|
assert_addr_d = mtvec_i + int_or_exception_offset;
|
||||||
|
return_addr_d = inst_addr_i;
|
||||||
|
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;
|
||||||
|
assert_addr_d = debug_halt_addr_i;
|
||||||
|
state_d = S_ASSERT;
|
||||||
|
end else if (inst_mret_i) begin
|
||||||
|
assert_addr_d = mepc_i;
|
||||||
|
state_d = S_ASSERT;
|
||||||
|
end else if (inst_dret_i) begin
|
||||||
|
assert_addr_d = dpc_i;
|
||||||
|
state_d = S_ASSERT;
|
||||||
|
debug_mode_d = 1'b0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
S_W_MEPC: begin
|
||||||
|
csr_we = 1'b1;
|
||||||
|
csr_waddr = {20'h0, `CSR_MEPC};
|
||||||
|
csr_wdata = return_addr_q;
|
||||||
|
state_d = S_ASSERT;
|
||||||
|
end
|
||||||
|
|
||||||
|
S_ASSERT: begin
|
||||||
|
csr_we = 1'b0;
|
||||||
|
state_d = S_IDLE;
|
||||||
|
end
|
||||||
|
|
||||||
|
default:;
|
||||||
|
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
assign csr_we_o = csr_we;
|
||||||
|
assign csr_waddr_o = csr_waddr;
|
||||||
|
assign csr_wdata_o = csr_wdata;
|
||||||
|
|
||||||
|
assign int_assert_o = (state_q == S_ASSERT);
|
||||||
|
assign int_addr_o = assert_addr_q;
|
||||||
|
|
||||||
|
always @ (posedge clk or negedge rst_n) begin
|
||||||
|
if (!rst_n) begin
|
||||||
|
state_q <= S_IDLE;
|
||||||
|
assert_addr_q <= 32'h0;
|
||||||
|
debug_mode_q <= 1'b0;
|
||||||
|
return_addr_q <= 32'h0;
|
||||||
|
end else begin
|
||||||
|
state_q <= state_d;
|
||||||
|
assert_addr_q <= assert_addr_d;
|
||||||
|
debug_mode_q <= debug_mode_d;
|
||||||
|
return_addr_q <= return_addr_d;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
|
@ -30,6 +30,7 @@ module exu(
|
||||||
output wire inst_ecall_o, // ecall指令
|
output wire inst_ecall_o, // ecall指令
|
||||||
output wire inst_ebreak_o, // ebreak指令
|
output wire inst_ebreak_o, // ebreak指令
|
||||||
output wire inst_mret_o, // mret指令
|
output wire inst_mret_o, // mret指令
|
||||||
|
output wire inst_dret_o, // dret指令
|
||||||
|
|
||||||
// mem
|
// mem
|
||||||
input wire[31:0] mem_rdata_i, // 内存输入数据
|
input wire[31:0] mem_rdata_i, // 内存输入数据
|
||||||
|
@ -143,6 +144,7 @@ module exu(
|
||||||
wire sys_op_ecall_o;
|
wire sys_op_ecall_o;
|
||||||
wire sys_op_ebreak_o;
|
wire sys_op_ebreak_o;
|
||||||
wire sys_op_fence_o;
|
wire sys_op_fence_o;
|
||||||
|
wire sys_op_dret_o;
|
||||||
|
|
||||||
exu_dispatch u_exu_dispatch(
|
exu_dispatch u_exu_dispatch(
|
||||||
// input
|
// input
|
||||||
|
@ -219,12 +221,14 @@ module exu(
|
||||||
.sys_op_mret_o(sys_op_mret_o),
|
.sys_op_mret_o(sys_op_mret_o),
|
||||||
.sys_op_ecall_o(sys_op_ecall_o),
|
.sys_op_ecall_o(sys_op_ecall_o),
|
||||||
.sys_op_ebreak_o(sys_op_ebreak_o),
|
.sys_op_ebreak_o(sys_op_ebreak_o),
|
||||||
.sys_op_fence_o(sys_op_fence_o)
|
.sys_op_fence_o(sys_op_fence_o),
|
||||||
|
.sys_op_dret_o(sys_op_dret_o)
|
||||||
);
|
);
|
||||||
|
|
||||||
assign inst_ecall_o = sys_op_ecall_o;
|
assign inst_ecall_o = sys_op_ecall_o;
|
||||||
assign inst_ebreak_o = sys_op_ebreak_o;
|
assign inst_ebreak_o = sys_op_ebreak_o;
|
||||||
assign inst_mret_o = sys_op_mret_o;
|
assign inst_mret_o = sys_op_mret_o;
|
||||||
|
assign inst_dret_o = sys_op_dret_o;
|
||||||
|
|
||||||
wire[31:0] alu_res_o;
|
wire[31:0] alu_res_o;
|
||||||
wire[31:0] bjp_res_o;
|
wire[31:0] bjp_res_o;
|
||||||
|
|
|
@ -99,7 +99,8 @@ module exu_dispatch(
|
||||||
output wire sys_op_mret_o,
|
output wire sys_op_mret_o,
|
||||||
output wire sys_op_ecall_o,
|
output wire sys_op_ecall_o,
|
||||||
output wire sys_op_ebreak_o,
|
output wire sys_op_ebreak_o,
|
||||||
output wire sys_op_fence_o
|
output wire sys_op_fence_o,
|
||||||
|
output wire sys_op_dret_o
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -206,5 +207,6 @@ module exu_dispatch(
|
||||||
assign sys_op_ecall_o = sys_info[`DECINFO_SYS_ECALL];
|
assign sys_op_ecall_o = sys_info[`DECINFO_SYS_ECALL];
|
||||||
assign sys_op_ebreak_o = sys_info[`DECINFO_SYS_EBREAK];
|
assign sys_op_ebreak_o = sys_info[`DECINFO_SYS_EBREAK];
|
||||||
assign sys_op_fence_o = sys_info[`DECINFO_SYS_FENCE];
|
assign sys_op_fence_o = sys_info[`DECINFO_SYS_FENCE];
|
||||||
|
assign sys_op_dret_o = sys_info[`DECINFO_SYS_DRET];
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
@ -156,6 +156,7 @@ module idu(
|
||||||
wire inst_remu = opcode_0110011 & funct3_111 & funct7_0000001;
|
wire inst_remu = opcode_0110011 & funct3_111 & funct7_0000001;
|
||||||
wire inst_nop = (inst_i == `INST_NOP);
|
wire inst_nop = (inst_i == `INST_NOP);
|
||||||
wire inst_mret = (inst_i == `INST_MRET);
|
wire inst_mret = (inst_i == `INST_MRET);
|
||||||
|
wire inst_dret = (inst_i == `INST_DRET);
|
||||||
|
|
||||||
// 将指令分类
|
// 将指令分类
|
||||||
wire inst_type_load = opcode_0000011;
|
wire inst_type_load = opcode_0000011;
|
||||||
|
@ -228,6 +229,7 @@ module idu(
|
||||||
assign dec_sys_info_bus[`DECINFO_SYS_EBREAK] = inst_ebreak;
|
assign dec_sys_info_bus[`DECINFO_SYS_EBREAK] = inst_ebreak;
|
||||||
assign dec_sys_info_bus[`DECINFO_SYS_NOP] = inst_nop;
|
assign dec_sys_info_bus[`DECINFO_SYS_NOP] = inst_nop;
|
||||||
assign dec_sys_info_bus[`DECINFO_SYS_MRET] = inst_mret;
|
assign dec_sys_info_bus[`DECINFO_SYS_MRET] = inst_mret;
|
||||||
|
assign dec_sys_info_bus[`DECINFO_SYS_DRET] = inst_dret;
|
||||||
assign dec_sys_info_bus[`DECINFO_SYS_FENCE] = inst_fence | inst_fence_i;
|
assign dec_sys_info_bus[`DECINFO_SYS_FENCE] = inst_fence | inst_fence_i;
|
||||||
|
|
||||||
// 指令中的立即数
|
// 指令中的立即数
|
||||||
|
@ -259,7 +261,7 @@ module idu(
|
||||||
wire op_bjp = inst_jal | inst_jalr | inst_type_branch;
|
wire op_bjp = inst_jal | inst_jalr | inst_type_branch;
|
||||||
wire op_muldiv = inst_type_muldiv;
|
wire op_muldiv = inst_type_muldiv;
|
||||||
wire op_csr = inst_csrrw | inst_csrrwi | inst_csrrs | inst_csrrsi | inst_csrrc | inst_csrrci;
|
wire op_csr = inst_csrrw | inst_csrrwi | inst_csrrs | inst_csrrsi | inst_csrrc | inst_csrrci;
|
||||||
wire op_sys = inst_ebreak | inst_ecall | inst_nop | inst_mret | inst_fence | inst_fence_i;
|
wire op_sys = inst_ebreak | inst_ecall | inst_nop | inst_mret | inst_fence | inst_fence_i | inst_dret;
|
||||||
wire op_mem = inst_type_load | inst_type_store;
|
wire op_mem = inst_type_load | inst_type_store;
|
||||||
|
|
||||||
assign dec_info_bus_o = ({`DECINFO_WIDTH{op_alu}} & {{`DECINFO_WIDTH-`DECINFO_ALU_BUS_WIDTH{1'b0}}, dec_alu_info_bus}) |
|
assign dec_info_bus_o = ({`DECINFO_WIDTH{op_alu}} & {{`DECINFO_WIDTH-`DECINFO_ALU_BUS_WIDTH{1'b0}}, dec_alu_info_bus}) |
|
||||||
|
|
|
@ -49,7 +49,6 @@ module tinyriscv_core #(
|
||||||
input wire irq_timer_i,
|
input wire irq_timer_i,
|
||||||
input wire irq_external_i,
|
input wire irq_external_i,
|
||||||
input wire[14:0] irq_fast_i,
|
input wire[14:0] irq_fast_i,
|
||||||
input wire irq_nm_i,
|
|
||||||
|
|
||||||
// debug req signal
|
// debug req signal
|
||||||
input wire debug_req_i
|
input wire debug_req_i
|
||||||
|
@ -114,6 +113,7 @@ module tinyriscv_core #(
|
||||||
wire ex_inst_ecall_o;
|
wire ex_inst_ecall_o;
|
||||||
wire ex_inst_ebreak_o;
|
wire ex_inst_ebreak_o;
|
||||||
wire ex_inst_mret_o;
|
wire ex_inst_mret_o;
|
||||||
|
wire ex_inst_dret_o;
|
||||||
wire ex_inst_valid_o;
|
wire ex_inst_valid_o;
|
||||||
|
|
||||||
// gpr_reg模块输出信号
|
// gpr_reg模块输出信号
|
||||||
|
@ -126,6 +126,8 @@ module tinyriscv_core #(
|
||||||
wire[31:0] csr_mtvec_o;
|
wire[31:0] csr_mtvec_o;
|
||||||
wire[31:0] csr_mepc_o;
|
wire[31:0] csr_mepc_o;
|
||||||
wire[31:0] csr_mstatus_o;
|
wire[31:0] csr_mstatus_o;
|
||||||
|
wire[31:0] csr_mie_o;
|
||||||
|
wire[31:0] csr_dpc_o;
|
||||||
|
|
||||||
// pipe_ctrl模块输出信号
|
// pipe_ctrl模块输出信号
|
||||||
wire[31:0] ctrl_flush_addr_o;
|
wire[31:0] ctrl_flush_addr_o;
|
||||||
|
@ -197,7 +199,9 @@ module tinyriscv_core #(
|
||||||
.clint_wdata_i(clint_csr_wdata_o),
|
.clint_wdata_i(clint_csr_wdata_o),
|
||||||
.mtvec_o(csr_mtvec_o),
|
.mtvec_o(csr_mtvec_o),
|
||||||
.mepc_o(csr_mepc_o),
|
.mepc_o(csr_mepc_o),
|
||||||
.mstatus_o(csr_mstatus_o)
|
.mstatus_o(csr_mstatus_o),
|
||||||
|
.mie_o(csr_mie_o),
|
||||||
|
.dpc_o(csr_dpc_o)
|
||||||
);
|
);
|
||||||
|
|
||||||
ifu_idu u_ifu_idu(
|
ifu_idu u_ifu_idu(
|
||||||
|
@ -283,6 +287,7 @@ module tinyriscv_core #(
|
||||||
.inst_ecall_o(ex_inst_ecall_o),
|
.inst_ecall_o(ex_inst_ecall_o),
|
||||||
.inst_ebreak_o(ex_inst_ebreak_o),
|
.inst_ebreak_o(ex_inst_ebreak_o),
|
||||||
.inst_mret_o(ex_inst_mret_o),
|
.inst_mret_o(ex_inst_mret_o),
|
||||||
|
.inst_dret_o(ex_inst_dret_o),
|
||||||
.int_stall_i(clint_stall_flag_o),
|
.int_stall_i(clint_stall_flag_o),
|
||||||
.csr_raddr_o(ex_csr_raddr_o),
|
.csr_raddr_o(ex_csr_raddr_o),
|
||||||
.csr_rdata_i(csr_ex_data_o),
|
.csr_rdata_i(csr_ex_data_o),
|
||||||
|
@ -300,19 +305,26 @@ module tinyriscv_core #(
|
||||||
.rd_we_i(ie_rd_we_o)
|
.rd_we_i(ie_rd_we_o)
|
||||||
);
|
);
|
||||||
|
|
||||||
clint u_clint(
|
exception u_exception(
|
||||||
.clk(clk),
|
.clk(clk),
|
||||||
.rst_n(rst_n),
|
.rst_n(rst_n),
|
||||||
.int_flag_i(`INT_NONE),
|
.inst_valid_i(ex_inst_valid_o),
|
||||||
.inst_ecall_i(ex_inst_ecall_o),
|
.inst_ecall_i(ex_inst_ecall_o),
|
||||||
.inst_ebreak_i(ex_inst_ebreak_o),
|
.inst_ebreak_i(ex_inst_ebreak_o),
|
||||||
.inst_mret_i(ex_inst_mret_o),
|
.inst_mret_i(ex_inst_mret_o),
|
||||||
|
.inst_dret_i(ex_inst_dret_o),
|
||||||
.inst_addr_i(ie_dec_pc_o),
|
.inst_addr_i(ie_dec_pc_o),
|
||||||
.jump_flag_i(ex_jump_flag_o),
|
.mtvec_i(csr_mtvec_o),
|
||||||
.mem_access_misaligned_i(ex_mem_access_misaligned_o),
|
.mepc_i(csr_mepc_o),
|
||||||
.csr_mtvec_i(csr_mtvec_o),
|
.mstatus_i(csr_mstatus_o),
|
||||||
.csr_mepc_i(csr_mepc_o),
|
.mie_i(csr_mie_o),
|
||||||
.csr_mstatus_i(csr_mstatus_o),
|
.dpc_i(csr_dpc_o),
|
||||||
|
.irq_software_i(irq_software_i),
|
||||||
|
.irq_timer_i(irq_timer_i),
|
||||||
|
.irq_external_i(irq_external_i),
|
||||||
|
.irq_fast_i(irq_fast_i),
|
||||||
|
.debug_halt_addr_i(DEBUG_HALT_ADDR),
|
||||||
|
.debug_req_i(debug_req_i),
|
||||||
.csr_we_o(clint_csr_we_o),
|
.csr_we_o(clint_csr_we_o),
|
||||||
.csr_waddr_o(clint_csr_waddr_o),
|
.csr_waddr_o(clint_csr_waddr_o),
|
||||||
.csr_wdata_o(clint_csr_wdata_o),
|
.csr_wdata_o(clint_csr_wdata_o),
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
/* 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.
|
||||||
|
*
|
||||||
|
* File: $filename.v
|
||||||
|
*
|
||||||
|
* Description: Auto-generated bootrom
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Auto-generated code
|
||||||
|
module debug_rom (
|
||||||
|
input wire clk_i,
|
||||||
|
input wire req_i,
|
||||||
|
input wire [63:0] addr_i,
|
||||||
|
output wire [63:0] rdata_o
|
||||||
|
);
|
||||||
|
|
||||||
|
localparam RomSize = 19;
|
||||||
|
|
||||||
|
wire [RomSize-1:0][63:0] mem;
|
||||||
|
|
||||||
|
assign mem = {
|
||||||
|
64'h00000000_7b200073,
|
||||||
|
64'h7b202473_7b302573,
|
||||||
|
64'h10852423_f1402473,
|
||||||
|
64'ha85ff06f_7b202473,
|
||||||
|
64'h7b302573_10052223,
|
||||||
|
64'h00100073_7b202473,
|
||||||
|
64'h7b302573_10052623,
|
||||||
|
64'h00c51513_00c55513,
|
||||||
|
64'h00000517_fd5ff06f,
|
||||||
|
64'hfa041ce3_00247413,
|
||||||
|
64'h40044403_00a40433,
|
||||||
|
64'hf1402473_02041c63,
|
||||||
|
64'h00147413_40044403,
|
||||||
|
64'h00a40433_10852023,
|
||||||
|
64'hf1402473_00c51513,
|
||||||
|
64'h00c55513_00000517,
|
||||||
|
64'h7b351073_7b241073,
|
||||||
|
64'h0ff0000f_04c0006f,
|
||||||
|
64'h07c0006f_00c0006f
|
||||||
|
};
|
||||||
|
|
||||||
|
reg [4:0] addr_q;
|
||||||
|
|
||||||
|
always @ (posedge clk_i) begin
|
||||||
|
if (req_i) begin
|
||||||
|
addr_q <= addr_i[7:3];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
reg[63:0] rdata;
|
||||||
|
|
||||||
|
// this prevents spurious Xes from propagating into
|
||||||
|
// the speculative fetch stage of the core
|
||||||
|
always @ (*) begin
|
||||||
|
rdata = 64'h0;
|
||||||
|
if (addr_q < 5'd19) begin
|
||||||
|
rdata = mem[addr_q];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign rdata_o = rdata;
|
||||||
|
|
||||||
|
endmodule
|
|
@ -0,0 +1,130 @@
|
||||||
|
/*
|
||||||
|
Copyright 2021 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
`define DbgVersion013 4'h2
|
||||||
|
`define ProgBufSize 5'h8
|
||||||
|
`define DataCount 4'h2
|
||||||
|
`define HaltAddress 64'h800
|
||||||
|
`define ResumeAddress `HaltAddress + 4
|
||||||
|
`define ExceptionAddress `HaltAddress + 8
|
||||||
|
`define DataAddr 12'h380
|
||||||
|
|
||||||
|
// dmi op
|
||||||
|
`define DMI_OP_NOP 2'b00
|
||||||
|
`define DMI_OP_READ 2'b01
|
||||||
|
`define DMI_OP_WRITE 2'b10
|
||||||
|
|
||||||
|
// DM regs addr
|
||||||
|
`define Data0 6'h04
|
||||||
|
`define Data1 6'h05
|
||||||
|
`define Data2 6'h06
|
||||||
|
`define Data3 6'h07
|
||||||
|
`define DMControl 6'h10
|
||||||
|
`define DMStatus 6'h11
|
||||||
|
`define Hartinfo 6'h12
|
||||||
|
`define AbstractCS 6'h16
|
||||||
|
`define Command 6'h17
|
||||||
|
`define ProgBuf0 6'h20
|
||||||
|
`define ProgBuf1 6'h21
|
||||||
|
`define ProgBuf2 6'h22
|
||||||
|
`define ProgBuf3 6'h23
|
||||||
|
`define ProgBuf4 6'h24
|
||||||
|
`define ProgBuf5 6'h25
|
||||||
|
`define ProgBuf6 6'h26
|
||||||
|
`define ProgBuf7 6'h27
|
||||||
|
`define ProgBuf8 6'h28
|
||||||
|
`define ProgBuf9 6'h29
|
||||||
|
`define ProgBuf10 6'h2A
|
||||||
|
`define ProgBuf11 6'h2B
|
||||||
|
`define ProgBuf12 6'h2C
|
||||||
|
`define ProgBuf13 6'h2D
|
||||||
|
`define ProgBuf14 6'h2E
|
||||||
|
`define ProgBuf15 6'h2F
|
||||||
|
`define SBAddress3 6'h37
|
||||||
|
`define SBCS 6'h38
|
||||||
|
`define SBAddress0 6'h39
|
||||||
|
`define SBAddress1 6'h3A
|
||||||
|
`define SBAddress2 6'h3B
|
||||||
|
`define SBData0 6'h3C
|
||||||
|
`define SBData1 6'h3D
|
||||||
|
`define SBData2 6'h3E
|
||||||
|
`define SBData3 6'h3F
|
||||||
|
|
||||||
|
// dmstatus bit index
|
||||||
|
`define Impebreak 22
|
||||||
|
`define Allhavereset 19
|
||||||
|
`define Anyhavereset 18
|
||||||
|
`define Allresumeack 17
|
||||||
|
`define Anyresumeack 16
|
||||||
|
`define Allnonexistent 15
|
||||||
|
`define Anynonexistent 14
|
||||||
|
`define Allunavail 13
|
||||||
|
`define Anyunavail 12
|
||||||
|
`define Allrunning 11
|
||||||
|
`define Anyrunning 10
|
||||||
|
`define Allhalted 9
|
||||||
|
`define Anyhalted 8
|
||||||
|
`define Authenticated 7
|
||||||
|
`define Authbusy 6
|
||||||
|
`define Hasresethaltreq 5
|
||||||
|
`define Confstrptrvalid 4
|
||||||
|
`define Version 3:0
|
||||||
|
|
||||||
|
// dmcontrol bit index
|
||||||
|
`define Haltreq 31
|
||||||
|
`define Resumereq 30
|
||||||
|
`define Hartreset 29
|
||||||
|
`define Ackhavereset 28
|
||||||
|
`define Hasel 26
|
||||||
|
`define Hartsello 25:16
|
||||||
|
`define Hartselhi 15:6
|
||||||
|
`define Setresethaltreq 3
|
||||||
|
`define Clrresethaltreq 2
|
||||||
|
`define Ndmreset 1
|
||||||
|
`define Dmactive 0
|
||||||
|
|
||||||
|
// abstractcs bit index
|
||||||
|
`define Progbufsize 28:24
|
||||||
|
`define Busy 12
|
||||||
|
`define Cmderr 10:8
|
||||||
|
`define Datacount 3:0
|
||||||
|
|
||||||
|
// abstract command access register bit index
|
||||||
|
`define Cmdtype 31:24
|
||||||
|
`define Aarsize 22:20
|
||||||
|
`define Aarpostincrement 19
|
||||||
|
`define Postexec 18
|
||||||
|
`define Transfer 17
|
||||||
|
`define Write 16
|
||||||
|
`define Regno 15:0
|
||||||
|
|
||||||
|
// sbcs bit index
|
||||||
|
`define Sbversion 31:29
|
||||||
|
`define Sbbusyerror 22
|
||||||
|
`define Sbbusy 21
|
||||||
|
`define Sbreadonaddr 20
|
||||||
|
`define Sbaccess 19:17
|
||||||
|
`define Sbautoincrement 16
|
||||||
|
`define Sbreadondata 15
|
||||||
|
`define Sberror 14:12
|
||||||
|
`define Sbasize 11:5
|
||||||
|
`define Sbaccess128 4
|
||||||
|
`define Sbaccess64 3
|
||||||
|
`define Sbaccess32 2
|
||||||
|
`define Sbaccess16 1
|
||||||
|
`define Sbaccess8 0
|
||||||
|
|
|
@ -14,368 +14,357 @@
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
`define DTM_OP_NOP 2'b00
|
`include "jtag_def.sv"
|
||||||
`define DTM_OP_READ 2'b01
|
|
||||||
`define DTM_OP_WRITE 2'b10
|
|
||||||
|
|
||||||
|
|
||||||
module jtag_dm #(
|
module jtag_dm #(
|
||||||
parameter DMI_ADDR_BITS = 6,
|
parameter DMI_ADDR_BITS = 6,
|
||||||
parameter DMI_DATA_BITS = 32,
|
parameter DMI_DATA_BITS = 32,
|
||||||
parameter DMI_OP_BITS = 2)(
|
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
|
||||||
|
)(
|
||||||
|
|
||||||
clk,
|
input wire clk,
|
||||||
rst_n,
|
input wire rst_n,
|
||||||
|
|
||||||
// rx
|
// from DMI
|
||||||
dm_ack_o,
|
input wire [DMI_REQ_BITS-1:0] dmi_data_i,
|
||||||
dtm_req_valid_i,
|
input wire dmi_valid_i,
|
||||||
dtm_req_data_i,
|
output wire dm_ready_o,
|
||||||
|
|
||||||
// tx
|
// to DMI
|
||||||
dtm_ack_i,
|
output wire [DMI_RESP_BITS-1:0] dm_data_o,
|
||||||
dm_resp_data_o,
|
output wire dm_valid_o,
|
||||||
dm_resp_valid_o,
|
input wire dmi_ready_i,
|
||||||
|
|
||||||
dm_reg_we_o,
|
output wire debug_req_o,
|
||||||
dm_reg_addr_o,
|
output wire ndmreset_o,
|
||||||
dm_reg_wdata_o,
|
|
||||||
dm_reg_rdata_i,
|
|
||||||
dm_mem_we_o,
|
|
||||||
dm_mem_addr_o,
|
|
||||||
dm_mem_wdata_o,
|
|
||||||
dm_mem_rdata_i,
|
|
||||||
dm_mem_sel_o,
|
|
||||||
|
|
||||||
req_valid_o,
|
// jtag access mem devices(DM as master)
|
||||||
req_ready_i,
|
output wire master_req_o,
|
||||||
rsp_valid_i,
|
input wire master_gnt_i,
|
||||||
rsp_ready_o,
|
input wire master_rvalid_i,
|
||||||
|
output wire master_we_o,
|
||||||
|
output wire [3:0] master_be_o,
|
||||||
|
output wire [31:0] master_addr_o,
|
||||||
|
output wire [31:0] master_wdata_o,
|
||||||
|
input wire [31:0] master_rdata_i,
|
||||||
|
input wire master_err_i,
|
||||||
|
|
||||||
dm_halt_req_o,
|
// core fetch instr or mem(DM as slave)
|
||||||
dm_reset_req_o
|
input wire slave_req_i,
|
||||||
|
input wire slave_we_i,
|
||||||
|
input wire [31:0] slave_addr_i,
|
||||||
|
input wire [3:0] slave_be_i,
|
||||||
|
input wire [31:0] slave_wdata_i,
|
||||||
|
output wire [31:0] slave_rdata_o
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
parameter DM_RESP_BITS = DMI_ADDR_BITS + DMI_DATA_BITS + DMI_OP_BITS;
|
localparam HARTINFO = {8'h0, 4'h2, 3'b0, 1'b1, `DataCount, `DataAddr};
|
||||||
parameter DTM_REQ_BITS = DMI_ADDR_BITS + DMI_DATA_BITS + DMI_OP_BITS;
|
|
||||||
parameter SHIFT_REG_BITS = DTM_REQ_BITS;
|
|
||||||
|
|
||||||
// 输入输出信号
|
wire halted;
|
||||||
input wire clk;
|
wire resumeack;
|
||||||
input wire rst_n;
|
wire sbbusy;
|
||||||
output wire dm_ack_o;
|
wire[DMI_OP_BITS-1:0] dm_op;
|
||||||
input wire dtm_req_valid_i;
|
wire[DMI_ADDR_BITS-1:0] dm_op_addr;
|
||||||
input wire[DTM_REQ_BITS-1:0] dtm_req_data_i;
|
wire[DMI_DATA_BITS-1:0] dm_op_data;
|
||||||
input wire dtm_ack_i;
|
|
||||||
output wire[DM_RESP_BITS-1:0] dm_resp_data_o;
|
|
||||||
output wire dm_resp_valid_o;
|
|
||||||
output wire dm_reg_we_o;
|
|
||||||
output wire[4:0] dm_reg_addr_o;
|
|
||||||
output wire[31:0] dm_reg_wdata_o;
|
|
||||||
input wire[31:0] dm_reg_rdata_i;
|
|
||||||
output wire dm_mem_we_o;
|
|
||||||
output wire[31:0] dm_mem_addr_o;
|
|
||||||
output wire[31:0] dm_mem_wdata_o;
|
|
||||||
input wire[31:0] dm_mem_rdata_i;
|
|
||||||
output wire[3:0] dm_mem_sel_o;
|
|
||||||
output wire req_valid_o;
|
|
||||||
input wire req_ready_i;
|
|
||||||
input wire rsp_valid_i;
|
|
||||||
output wire rsp_ready_o;
|
|
||||||
output wire dm_halt_req_o;
|
|
||||||
output wire dm_reset_req_o;
|
|
||||||
|
|
||||||
// DM模块寄存器
|
reg havereset_d, havereset_q;
|
||||||
reg[31:0] dcsr;
|
reg clear_resumeack;
|
||||||
|
reg sbaddress_write_valid;
|
||||||
|
reg sbdata_write_valid;
|
||||||
|
reg[31:0] dm_resp_data_d, dm_resp_data_q;
|
||||||
|
wire[31:0] sba_sbaddress;
|
||||||
|
wire[31:0] dm_sbaddress;
|
||||||
|
wire resumereq;
|
||||||
|
wire cmdbusy;
|
||||||
|
|
||||||
|
// DM regs
|
||||||
reg[31:0] dmstatus;
|
reg[31:0] dmstatus;
|
||||||
reg[31:0] dmcontrol;
|
reg[31:0] dmcontrol_d, dmcontrol_q;
|
||||||
reg[31:0] hartinfo;
|
|
||||||
reg[31:0] abstractcs;
|
reg[31:0] abstractcs;
|
||||||
reg[31:0] data0;
|
reg[31:0] sbcs_d, sbcs_q;
|
||||||
reg[31:0] sbcs;
|
reg[31:0] sbdata0_d, sbdata0_q;
|
||||||
reg[31:0] sbaddress0;
|
reg[31:0] sbaddress0_d, sbaddress0_q;
|
||||||
reg[31:0] sbdata0;
|
reg[31:0] command_d, command_q;
|
||||||
reg[31:0] command;
|
reg[31:0] data0_d, data0_q;
|
||||||
|
reg[2:0] cmderr_d, cmderr_q;
|
||||||
|
|
||||||
// DM模块寄存器地址
|
assign dm_sbaddress = sbaddress0_q;
|
||||||
localparam DCSR = 16'h7b0;
|
|
||||||
localparam DMSTATUS = 6'h11;
|
|
||||||
localparam DMCONTROL = 6'h10;
|
|
||||||
localparam HARTINFO = 6'h12;
|
|
||||||
localparam ABSTRACTCS = 6'h16;
|
|
||||||
localparam DATA0 = 6'h04;
|
|
||||||
localparam SBCS = 6'h38;
|
|
||||||
localparam SBADDRESS0 = 6'h39;
|
|
||||||
localparam SBDATA0 = 6'h3C;
|
|
||||||
localparam COMMAND = 6'h17;
|
|
||||||
localparam DPC = 16'h7b1;
|
|
||||||
|
|
||||||
localparam OP_SUCC = 2'b00;
|
assign dm_op = dmi_data_i[DMI_OP_BITS-1:0];
|
||||||
|
assign dm_op_addr = dmi_data_i[DMI_REQ_BITS-1:DMI_DATA_BITS+DMI_OP_BITS];
|
||||||
|
assign dm_op_data = dmi_data_i[DMI_DATA_BITS+DMI_OP_BITS-1:DMI_OP_BITS];
|
||||||
|
|
||||||
localparam STATE_IDLE = 3'b001;
|
|
||||||
localparam STATE_EXE = 3'b010;
|
|
||||||
localparam STATE_END = 3'b100;
|
|
||||||
|
|
||||||
reg[2:0] state;
|
localparam S_REQ = 2'b01;
|
||||||
reg[31:0] read_data;
|
localparam S_RESP = 2'b10;
|
||||||
reg dm_reg_we;
|
|
||||||
reg[4:0] dm_reg_addr;
|
|
||||||
reg[31:0] dm_reg_wdata;
|
|
||||||
reg dm_mem_we;
|
|
||||||
reg[31:0] dm_mem_addr;
|
|
||||||
reg[31:0] dm_mem_wdata;
|
|
||||||
reg[31:0] dm_mem_rdata;
|
|
||||||
reg dm_halt_req;
|
|
||||||
reg dm_reset_req;
|
|
||||||
reg need_resp;
|
|
||||||
reg is_read_reg;
|
|
||||||
wire rx_valid;
|
|
||||||
wire[DTM_REQ_BITS-1:0] rx_data; // driver请求数据
|
|
||||||
reg[DTM_REQ_BITS-1:0] rx_data_r;
|
|
||||||
|
|
||||||
wire[3:0] dm_mem_sel = (sbcs[19:17] == 3'd0)? 4'b0001:
|
reg[2:0] req_state_d, req_state_q;
|
||||||
(sbcs[19:17] == 3'd1)? 4'b0011:
|
reg dm_valid_d, dm_valid_q;
|
||||||
4'b1111;
|
|
||||||
wire[2:0] address_inc_step = (sbcs[19:17] == 3'd0)? 3'd1:
|
|
||||||
(sbcs[19:17] == 3'd1)? 3'd2:
|
|
||||||
3'd4;
|
|
||||||
wire[31:0] sbaddress0_next = sbaddress0 + {29'h0, address_inc_step};
|
|
||||||
wire[DM_RESP_BITS-1:0] dm_resp_data;
|
|
||||||
|
|
||||||
wire[DMI_OP_BITS-1:0] op = rx_data_r[DMI_OP_BITS-1:0];
|
// response FSM
|
||||||
wire[DMI_DATA_BITS-1:0] data = rx_data_r[DMI_DATA_BITS+DMI_OP_BITS-1:DMI_OP_BITS];
|
always @ (*) begin
|
||||||
wire[DMI_ADDR_BITS-1:0] address = rx_data_r[DTM_REQ_BITS-1:DMI_DATA_BITS+DMI_OP_BITS];
|
req_state_d = req_state_q;
|
||||||
|
dm_valid_d = dm_valid_q;
|
||||||
|
|
||||||
wire req_sys_bus = ~(address == DMSTATUS);
|
case (req_state_q)
|
||||||
|
S_REQ: begin
|
||||||
|
if (dmi_valid_i & dm_ready_o) begin
|
||||||
|
req_state_d = S_RESP;
|
||||||
|
dm_valid_d = 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
S_RESP: begin
|
||||||
|
if (dmi_ready_i) begin
|
||||||
|
dm_valid_d = 1'b0;
|
||||||
|
req_state_d = S_REQ;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
default:;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
always @ (posedge clk or negedge rst_n) begin
|
always @ (posedge clk or negedge rst_n) begin
|
||||||
if (!rst_n) begin
|
if (!rst_n) begin
|
||||||
dm_mem_we <= 1'b0;
|
req_state_q <= S_REQ;
|
||||||
dm_reg_we <= 1'b0;
|
dm_valid_q <= 1'b0;
|
||||||
dm_halt_req <= 1'b0;
|
|
||||||
dm_reset_req <= 1'b0;
|
|
||||||
dm_mem_addr <= 32'h0;
|
|
||||||
dm_reg_addr <= 5'h0;
|
|
||||||
sbaddress0 <= 32'h0;
|
|
||||||
dcsr <= 32'h0;
|
|
||||||
hartinfo <= 32'h0;
|
|
||||||
sbcs <= 32'h20040404;
|
|
||||||
dmcontrol <= 32'h0;
|
|
||||||
abstractcs <= 32'h1000003;
|
|
||||||
data0 <= 32'h0;
|
|
||||||
sbdata0 <= 32'h0;
|
|
||||||
command <= 32'h0;
|
|
||||||
dm_reg_wdata <= 32'h0;
|
|
||||||
dm_mem_wdata <= 32'h0;
|
|
||||||
dm_mem_rdata <= 32'h0;
|
|
||||||
dmstatus <= 32'h430c82;
|
|
||||||
is_read_reg <= 1'b0;
|
|
||||||
read_data <= 32'h0;
|
|
||||||
need_resp <= 1'b0;
|
|
||||||
state <= STATE_IDLE;
|
|
||||||
end else begin
|
end else begin
|
||||||
case (state)
|
req_state_q <= req_state_d;
|
||||||
STATE_IDLE: begin
|
dm_valid_q <= dm_valid_d;
|
||||||
// 接收到driver的请求
|
|
||||||
if (rx_valid) begin
|
|
||||||
rx_data_r <= rx_data;
|
|
||||||
state <= STATE_EXE;
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
STATE_EXE: begin
|
|
||||||
state <= STATE_END;
|
|
||||||
need_resp <= 1'b1;
|
|
||||||
case (op)
|
|
||||||
`DTM_OP_READ: begin
|
|
||||||
case (address)
|
|
||||||
DMSTATUS: begin
|
|
||||||
read_data <= dmstatus;
|
|
||||||
end
|
|
||||||
DMCONTROL: begin
|
|
||||||
read_data <= dmcontrol;
|
|
||||||
end
|
|
||||||
HARTINFO: begin
|
|
||||||
read_data <= hartinfo;
|
|
||||||
end
|
|
||||||
SBCS: begin
|
|
||||||
read_data <= sbcs;
|
|
||||||
end
|
|
||||||
ABSTRACTCS: begin
|
|
||||||
read_data <= abstractcs;
|
|
||||||
end
|
|
||||||
DATA0: begin
|
|
||||||
if (is_read_reg == 1'b1) begin
|
|
||||||
read_data <= dm_reg_rdata_i;
|
|
||||||
end else begin
|
|
||||||
read_data <= data0;
|
|
||||||
end
|
|
||||||
is_read_reg <= 1'b0;
|
|
||||||
end
|
|
||||||
SBDATA0: begin
|
|
||||||
read_data <= dm_mem_rdata;
|
|
||||||
if (sbcs[16] == 1'b1) begin
|
|
||||||
sbaddress0 <= sbaddress0_next;
|
|
||||||
end
|
|
||||||
if (sbcs[15] == 1'b1) begin
|
|
||||||
dm_mem_addr <= sbaddress0_next;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
default: begin
|
|
||||||
read_data <= {(DMI_DATA_BITS){1'b0}};
|
|
||||||
end
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
|
|
||||||
`DTM_OP_WRITE: begin
|
// we always ready to receive dmi request
|
||||||
read_data <= {(DMI_DATA_BITS){1'b0}};
|
assign dm_ready_o = 1'b1;
|
||||||
case (address)
|
assign dm_valid_o = dm_valid_q;
|
||||||
DMCONTROL: begin
|
assign dm_data_o = {{DMI_ADDR_BITS{1'b0}}, dm_resp_data_q, 2'b00}; // response successfully
|
||||||
// reset DM module
|
|
||||||
if (data[0] == 1'b0) begin
|
|
||||||
dcsr <= 32'hc0;
|
// DMI read or write operation
|
||||||
dmstatus <= 32'h430c82; // not halted, all running
|
always @ (*) begin
|
||||||
hartinfo <= 32'h0;
|
// dmstatus
|
||||||
sbcs <= 32'h20040404;
|
dmstatus = 32'h0;
|
||||||
abstractcs <= 32'h1000003;
|
dmstatus[`Version] = `DbgVersion013;
|
||||||
dmcontrol <= data;
|
dmstatus[`Authenticated] = 1'b1;
|
||||||
dm_halt_req <= 1'b0;
|
dmstatus[`Allresumeack] = resumeack;
|
||||||
dm_reset_req <= 1'b0;
|
dmstatus[`Anyresumeack] = resumeack;
|
||||||
// DM is active
|
dmstatus[`Allhavereset] = havereset_q;
|
||||||
end else begin
|
dmstatus[`Anyhavereset] = havereset_q;
|
||||||
// we have only one hart
|
dmstatus[`Allhalted] = halted;
|
||||||
dmcontrol <= (data & ~(32'h3fffc0)) | 32'h10000;
|
dmstatus[`Anyhalted] = halted;
|
||||||
// halt
|
dmstatus[`Allrunning] = ~halted;
|
||||||
if (data[31] == 1'b1) begin
|
dmstatus[`Anyrunning] = ~halted;
|
||||||
dm_halt_req <= 1'b1;
|
|
||||||
// clear ALLRUNNING ANYRUNNING and set ALLHALTED
|
// abstractcs
|
||||||
dmstatus <= {dmstatus[31:12], 4'h3, dmstatus[7:0]};
|
cmderr_d = cmderr_q;
|
||||||
// reset
|
abstractcs = 32'h0;
|
||||||
end else if (data[1] == 1'b1) begin
|
abstractcs[`Datacount] = `DataCount;
|
||||||
dm_reset_req <= 1'b1;
|
abstractcs[`Progbufsize] = `ProgBufSize;
|
||||||
dm_halt_req <= 1'b0;
|
abstractcs[`Busy] = cmdbusy;
|
||||||
dmstatus <= {dmstatus[31:12], 4'hc, dmstatus[7:0]};
|
abstractcs[`Cmderr] = cmderr_q;
|
||||||
// resume
|
|
||||||
end else if (dm_halt_req == 1'b1 && data[30] == 1'b1) begin
|
havereset_d = havereset_q;
|
||||||
dm_halt_req <= 1'b0;
|
sbaddress0_d = sba_sbaddress;
|
||||||
// set ALLRUNNING ANYRUNNING and clear ALLHALTED
|
dmcontrol_d = dmcontrol_q;
|
||||||
dmstatus <= {dmstatus[31:12], 4'hc, dmstatus[7:0]};
|
clear_resumeack = 1'b0;
|
||||||
end
|
sbaddress_write_valid = 1'b0;
|
||||||
end
|
sbdata_write_valid = 1'b0;
|
||||||
end
|
|
||||||
COMMAND: begin
|
data0_d = data0_q;
|
||||||
// access reg
|
sbcs_d = sbcs_q;
|
||||||
if (data[31:24] == 8'h0) begin
|
sbdata0_d = sbdata0_q;
|
||||||
if (data[22:20] > 3'h2) begin
|
dm_resp_data_d = dm_resp_data_q;
|
||||||
abstractcs <= abstractcs | (1'b1 << 9);
|
|
||||||
end else begin
|
if (dmi_valid_i & dm_ready_o) begin
|
||||||
abstractcs <= abstractcs & (~(3'h7 << 8));
|
|
||||||
// read or write
|
|
||||||
if (data[18] == 1'b0) begin
|
|
||||||
dm_reg_addr <= data[15:0] - 16'h1000;
|
|
||||||
// read
|
// read
|
||||||
if (data[16] == 1'b0) begin
|
if (dm_op == `DMI_OP_READ) begin
|
||||||
if (data[15:0] == DCSR) begin
|
case (dm_op_addr)
|
||||||
data0 <= dcsr;
|
`DMStatus: dm_resp_data_d = dmstatus;
|
||||||
end else if (data[15:0] < 16'h1020) begin
|
`DMControl: dm_resp_data_d = dmcontrol_q;
|
||||||
is_read_reg <= 1'b1;
|
`Hartinfo: dm_resp_data_d = HARTINFO;
|
||||||
end
|
`SBCS: dm_resp_data_d = sbcs_q;
|
||||||
|
`AbstractCS:dm_resp_data_d = abstractcs;
|
||||||
|
default:;
|
||||||
|
endcase
|
||||||
|
|
||||||
// write
|
// write
|
||||||
|
end else if (dm_op == `DMI_OP_WRITE) begin
|
||||||
|
case (dm_op_addr)
|
||||||
|
`DMControl: begin
|
||||||
|
dmcontrol_d = dm_op_data;
|
||||||
|
if (dmcontrol_d[`Ackhavereset]) begin
|
||||||
|
havereset_d = 1'b0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
`Data0: begin
|
||||||
|
data0_d = dm_op_data;
|
||||||
|
end
|
||||||
|
|
||||||
|
`SBCS: begin
|
||||||
|
if (sbbusy) begin
|
||||||
|
sbcs_d[`Sbbusyerror] = 1'b1;
|
||||||
end else begin
|
end else begin
|
||||||
if (data[15:0] < 16'h1020) begin
|
sbcs_d = dm_op_data;
|
||||||
dm_reg_we <= 1'b1;
|
// write 1 to clear
|
||||||
dm_reg_wdata <= data0;
|
sbcs_d[`Sbbusyerror] = sbcs_q[`Sbbusyerror] & (~sbcs_d[`Sbbusyerror]);
|
||||||
|
sbcs_d[`Sberror] = sbcs_q[`Sberror] & (~sbcs_d[`Sberror]);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
`SBAddress0: begin
|
||||||
|
if (sbbusy | sbcs_d[`Sbbusyerror]) begin
|
||||||
|
sbcs_d[`Sbbusyerror] = 1'b1;
|
||||||
|
end else begin
|
||||||
|
sbaddress0_d = dm_op_data;
|
||||||
|
sbaddress_write_valid = (sbcs_q[`Sberror] == 3'b0);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
`SBData0: begin
|
||||||
|
if (sbbusy | sbcs_d[`Sbbusyerror]) begin
|
||||||
|
sbcs_d[`Sbbusyerror] = 1'b1;
|
||||||
|
end else begin
|
||||||
|
sbdata0_d = dm_op_data;
|
||||||
|
sbdata_write_valid = (sbcs_q[`Sberror] == 3'b0);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
DATA0: begin
|
|
||||||
data0 <= data;
|
`AbstractCS: begin
|
||||||
end
|
|
||||||
SBCS: begin
|
|
||||||
sbcs <= data;
|
|
||||||
end
|
|
||||||
SBADDRESS0: begin
|
|
||||||
sbaddress0 <= data;
|
|
||||||
if (sbcs[20] == 1'b1) begin
|
|
||||||
dm_mem_addr <= data;
|
|
||||||
end
|
|
||||||
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_next;
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
default:;
|
||||||
endcase
|
endcase
|
||||||
end
|
// nop
|
||||||
|
end else begin
|
||||||
|
|
||||||
`DTM_OP_NOP: begin
|
|
||||||
read_data <= {(DMI_DATA_BITS){1'b0}};
|
|
||||||
end
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
STATE_END: begin
|
|
||||||
state <= STATE_IDLE;
|
|
||||||
dm_mem_rdata <= dm_mem_rdata_i;
|
|
||||||
need_resp <= 1'b0;
|
|
||||||
dm_mem_we <= 1'b0;
|
|
||||||
dm_reg_we <= 1'b0;
|
|
||||||
dm_reset_req <= 1'b0;
|
|
||||||
end
|
|
||||||
endcase
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
wire jtag_req_hsked = (req_valid_o & req_ready_i);
|
// dmcontrol
|
||||||
wire jtag_rsp_hsked = (rsp_valid_i & rsp_ready_o);
|
dmcontrol_d[`Hasel] = 1'b0;
|
||||||
|
dmcontrol_d[`Hartreset] = 1'b0;
|
||||||
|
dmcontrol_d[`Setresethaltreq] = 1'b0;
|
||||||
|
dmcontrol_d[`Clrresethaltreq] = 1'b0;
|
||||||
|
dmcontrol_d[`Ackhavereset] = 1'b0;
|
||||||
|
dmcontrol_d[`Hartsello] = 10'h1;
|
||||||
|
dmcontrol_d[`Hartselhi] = 10'h0;
|
||||||
|
// 收到resume请求后清resume应答
|
||||||
|
if (!dmcontrol_q[`Resumereq] && dmcontrol_d[`Resumereq]) begin
|
||||||
|
clear_resumeack = 1'b1;
|
||||||
|
end
|
||||||
|
// 发出resume后并且收到应答
|
||||||
|
if (dmcontrol_q[`Resumereq] && resumeack) begin
|
||||||
|
// 清resume请求位
|
||||||
|
dmcontrol_d[`Resumereq] = 1'b0;
|
||||||
|
end
|
||||||
|
|
||||||
assign rsp_ready_o = (~rst_n)? 1'b0: 1'b1;
|
// sbcs
|
||||||
assign dm_mem_sel_o = dm_mem_sel;
|
sbcs_d[`Sbversion] = 3'd1;
|
||||||
|
sbcs_d[`Sbbusy] = sbbusy;
|
||||||
|
sbcs_d[`Sbasize] = 7'd32;
|
||||||
|
sbcs_d[`Sbaccess128] = 1'b0;
|
||||||
|
sbcs_d[`Sbaccess64] = 1'b0;
|
||||||
|
sbcs_d[`Sbaccess32] = 1'b1;
|
||||||
|
sbcs_d[`Sbaccess16] = 1'b0;
|
||||||
|
sbcs_d[`Sbaccess8] = 1'b0;
|
||||||
|
sbcs_d[`Sbaccess] = 3'd2;
|
||||||
|
|
||||||
|
// set the havereset flag when we did a ndmreset
|
||||||
|
if (ndmreset_o) begin
|
||||||
|
havereset_d = 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
assign dm_reg_we_o = dm_reg_we;
|
assign debug_req_o = dmcontrol_q[`Haltreq];
|
||||||
assign dm_reg_addr_o = dm_reg_addr;
|
assign ndmreset_o = dmcontrol_q[`Ndmreset];
|
||||||
assign dm_reg_wdata_o = dm_reg_wdata;
|
assign resumereq = dmcontrol_q[`Resumereq];
|
||||||
assign dm_mem_we_o = dm_mem_we;
|
|
||||||
assign dm_mem_addr_o = dm_mem_addr;
|
|
||||||
assign dm_mem_wdata_o = dm_mem_wdata;
|
|
||||||
|
|
||||||
assign req_valid_o = (state != STATE_IDLE) & req_sys_bus;
|
|
||||||
assign dm_halt_req_o = dm_halt_req;
|
|
||||||
assign dm_reset_req_o = dm_reset_req;
|
|
||||||
|
|
||||||
assign dm_resp_data = {address, read_data, OP_SUCC};
|
|
||||||
|
|
||||||
|
|
||||||
full_handshake_tx #(
|
always @ (posedge clk or negedge rst_n) begin
|
||||||
.DW(DM_RESP_BITS)
|
if (!rst_n) begin
|
||||||
) tx(
|
dmcontrol_q <= 32'h0;
|
||||||
|
havereset_q <= 1'b1;
|
||||||
|
data0_q <= 32'h0;
|
||||||
|
sbcs_q <= 32'h0;
|
||||||
|
sbaddress0_q <= 32'h0;
|
||||||
|
sbdata0_q <= 32'h0;
|
||||||
|
dm_resp_data_q <= 32'h0;
|
||||||
|
cmderr_q <= 3'h0;
|
||||||
|
end else begin
|
||||||
|
if (!dmcontrol_q[`Dmactive]) begin
|
||||||
|
dmcontrol_q[`Haltreq] <= 1'b0;
|
||||||
|
dmcontrol_q[`Resumereq] <= 1'b0;
|
||||||
|
dmcontrol_q[`Hartreset] <= 1'b0;
|
||||||
|
dmcontrol_q[`Ackhavereset] <= 1'b0;
|
||||||
|
dmcontrol_q[`Hasel] <= 1'b0;
|
||||||
|
dmcontrol_q[`Hartsello] <= 10'b0;
|
||||||
|
dmcontrol_q[`Hartselhi] <= 10'b0;
|
||||||
|
dmcontrol_q[`Setresethaltreq] <= 1'b0;
|
||||||
|
dmcontrol_q[`Clrresethaltreq] <= 1'b0;
|
||||||
|
dmcontrol_q[`Ndmreset] <= 1'b0;
|
||||||
|
dmcontrol_q[`Dmactive] <= dmcontrol_d[`Dmactive];
|
||||||
|
data0_q <= 32'h0;
|
||||||
|
sbcs_q <= 32'h0;
|
||||||
|
sbaddress0_q <= 32'h0;
|
||||||
|
sbdata0_q <= 32'h0;
|
||||||
|
dm_resp_data_q <= 32'h0;
|
||||||
|
cmderr_q <= 3'h0;
|
||||||
|
end else begin
|
||||||
|
dmcontrol_q <= dmcontrol_d;
|
||||||
|
data0_q <= data0_d;
|
||||||
|
sbcs_q <= sbcs_d;
|
||||||
|
sbaddress0_q <= sbaddress0_d;
|
||||||
|
sbdata0_q <= sbdata0_d;
|
||||||
|
dm_resp_data_q <= dm_resp_data_d;
|
||||||
|
cmderr_q <= cmderr_d;
|
||||||
|
end
|
||||||
|
havereset_q <= havereset_d;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
jtag_mem #(
|
||||||
|
|
||||||
|
) u_jtag_mem (
|
||||||
.clk(clk),
|
.clk(clk),
|
||||||
.rst_n(rst_n),
|
.rst_n(rst_n),
|
||||||
.ack_i(dtm_ack_i),
|
|
||||||
.req_i(need_resp),
|
.halted_o(halted),
|
||||||
.req_data_i(dm_resp_data),
|
.resumeack_o(resumeack),
|
||||||
.idle_o(),
|
.clear_resumeack_i(clear_resumeack),
|
||||||
.req_o(dm_resp_valid_o),
|
.resumereq_i(resumereq),
|
||||||
.req_data_o(dm_resp_data_o)
|
.haltreq_i(debug_req_o),
|
||||||
|
.cmdbusy_o(cmdbusy),
|
||||||
|
|
||||||
|
.req_i(slave_req_i),
|
||||||
|
.we_i(slave_we_i),
|
||||||
|
.addr_i(slave_addr_i),
|
||||||
|
.be_i(slave_be_i),
|
||||||
|
.wdata_i(slave_wdata_i),
|
||||||
|
.rdata_o(slave_rdata_o)
|
||||||
);
|
);
|
||||||
|
|
||||||
full_handshake_rx #(
|
jtag_sba #(
|
||||||
.DW(DTM_REQ_BITS)
|
|
||||||
) rx(
|
) u_jtag_sba (
|
||||||
.clk(clk),
|
.clk(clk),
|
||||||
.rst_n(rst_n),
|
.rst_n(rst_n),
|
||||||
.req_i(dtm_req_valid_i),
|
.sbbusy_o(sbbusy),
|
||||||
.req_data_i(dtm_req_data_i),
|
.master_req_o(master_req_o),
|
||||||
.ack_o(dm_ack_o),
|
.master_gnt_i(master_gnt_i),
|
||||||
.recv_data_o(rx_data),
|
.master_rvalid_i(master_rvalid_i),
|
||||||
.recv_rdy_o(rx_valid)
|
.master_we_o(master_we_o),
|
||||||
|
.master_be_o(master_be_o),
|
||||||
|
.master_addr_o(master_addr_o),
|
||||||
|
.master_wdata_o(master_wdata_o),
|
||||||
|
.master_rdata_i(master_rdata_i),
|
||||||
|
.master_err_i(master_err_i)
|
||||||
);
|
);
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
Copyright 2021 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_dmi #(
|
||||||
|
parameter DATA_WIDTH = 40
|
||||||
|
)(
|
||||||
|
|
||||||
|
// JTAG side(master side)
|
||||||
|
input wire jtag_tck_i,
|
||||||
|
input wire jtag_trst_ni,
|
||||||
|
|
||||||
|
input wire [DATA_WIDTH-1:0] jtag_data_i,
|
||||||
|
input wire jtag_valid_i,
|
||||||
|
output wire jtag_ready_o,
|
||||||
|
|
||||||
|
output wire [DATA_WIDTH-1:0] jtag_data_o,
|
||||||
|
output wire jtag_valid_o,
|
||||||
|
input wire jtag_ready_i,
|
||||||
|
|
||||||
|
// Core side(slave side)
|
||||||
|
input wire clk_i,
|
||||||
|
input wire rst_ni,
|
||||||
|
|
||||||
|
input wire [DATA_WIDTH-1:0] core_data_i,
|
||||||
|
input wire core_valid_i,
|
||||||
|
output wire core_ready_o,
|
||||||
|
|
||||||
|
output wire [DATA_WIDTH-1:0] core_data_o,
|
||||||
|
output wire core_valid_o,
|
||||||
|
input wire core_ready_i
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
cdc_2phase #(.DATA_WIDTH(DATA_WIDTH)) u_cdc_req (
|
||||||
|
.src_rst_ni ( jtag_trst_ni ),
|
||||||
|
.src_clk_i ( jtag_tck_i ),
|
||||||
|
.src_data_i ( jtag_data_i ),
|
||||||
|
.src_valid_i ( jtag_valid_i ),
|
||||||
|
.src_ready_o ( jtag_ready_o ),
|
||||||
|
|
||||||
|
.dst_rst_ni ( rst_ni ),
|
||||||
|
.dst_clk_i ( clk_i ),
|
||||||
|
.dst_data_o ( core_data_o ),
|
||||||
|
.dst_valid_o ( core_valid_o ),
|
||||||
|
.dst_ready_i ( core_ready_i )
|
||||||
|
);
|
||||||
|
|
||||||
|
cdc_2phase #(.DATA_WIDTH(DATA_WIDTH)) u_cdc_resp (
|
||||||
|
.src_rst_ni ( rst_ni ),
|
||||||
|
.src_clk_i ( clk_i ),
|
||||||
|
.src_data_i ( core_data_i ),
|
||||||
|
.src_valid_i ( core_valid_i ),
|
||||||
|
.src_ready_o ( core_ready_o ),
|
||||||
|
|
||||||
|
.dst_rst_ni ( jtag_trst_ni ),
|
||||||
|
.dst_clk_i ( jtag_tck_i ),
|
||||||
|
.dst_data_o ( jtag_data_o ),
|
||||||
|
.dst_valid_o ( jtag_valid_o ),
|
||||||
|
.dst_ready_i ( jtag_ready_i )
|
||||||
|
);
|
||||||
|
|
||||||
|
endmodule
|
|
@ -0,0 +1,187 @@
|
||||||
|
/*
|
||||||
|
Copyright 2021 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
`include "jtag_def.sv"
|
||||||
|
|
||||||
|
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
|
||||||
|
)(
|
||||||
|
|
||||||
|
input wire jtag_tck_i, // JTAG test clock pad
|
||||||
|
input wire jtag_trst_ni, // JTAG test reset pad
|
||||||
|
|
||||||
|
// to jtag_dmi
|
||||||
|
output wire [DTM_REQ_BITS-1:0] dtm_data_o,
|
||||||
|
output wire dtm_valid_o,
|
||||||
|
// from jtag_dmi
|
||||||
|
input wire dmi_ready_i,
|
||||||
|
|
||||||
|
// from jtag_dmi
|
||||||
|
input wire [DMI_RESP_BITS-1:0] dmi_data_i,
|
||||||
|
input wire dmi_valid_i,
|
||||||
|
// to jtag_dmi
|
||||||
|
output wire dtm_ready_o,
|
||||||
|
|
||||||
|
// from jtag_tap
|
||||||
|
input wire tap_req_i,
|
||||||
|
input wire [TAP_REQ_BITS-1:0] tap_data_i,
|
||||||
|
|
||||||
|
// to jtag_tap
|
||||||
|
output wire [DTM_RESP_BITS-1:0] data_o,
|
||||||
|
output wire [31:0] idcode_o,
|
||||||
|
output wire [31:0] dtmcs_o
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
localparam IDCODE_VERSION = 4'h1;
|
||||||
|
localparam IDCODE_PART_NUMBER = 16'he200;
|
||||||
|
localparam IDCODE_MANUFLD = 11'h537;
|
||||||
|
|
||||||
|
localparam DTM_VERSION = 4'h1;
|
||||||
|
|
||||||
|
localparam S_IDLE = 5'b00001;
|
||||||
|
localparam S_READ = 5'b00010;
|
||||||
|
localparam S_WAIT_READ = 5'b00100;
|
||||||
|
localparam S_WRITE = 5'b01000;
|
||||||
|
localparam S_WAIT_WRITE = 5'b10000;
|
||||||
|
|
||||||
|
reg[4:0] state_d;
|
||||||
|
reg[4:0] state_q;
|
||||||
|
reg dtm_valid;
|
||||||
|
reg[DTM_REQ_BITS-1:0] dtm_data_q;
|
||||||
|
reg[DTM_REQ_BITS-1:0] dtm_data_d;
|
||||||
|
reg[DTM_RESP_BITS-1:0] resp_tap_data_q;
|
||||||
|
reg is_busy;
|
||||||
|
|
||||||
|
wire[DTM_RESP_BITS-1:0] busy_response;
|
||||||
|
wire dtm_busy;
|
||||||
|
wire[DMI_OP_BITS-1:0] op;
|
||||||
|
wire[1:0] dtm_state;
|
||||||
|
wire[DMI_ADDR_BITS-1:0] addr_bits = DMI_ADDR_BITS[5:0];
|
||||||
|
|
||||||
|
assign idcode_o = {IDCODE_VERSION, IDCODE_PART_NUMBER, IDCODE_MANUFLD, 1'h1};
|
||||||
|
assign dtmcs_o = {14'b0,
|
||||||
|
1'b0, // dmihardreset
|
||||||
|
1'b0, // dmireset
|
||||||
|
1'b0,
|
||||||
|
3'h5, // idle
|
||||||
|
dtm_state, // 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 dtm_state = is_busy ? 2'b01 : 2'b00;
|
||||||
|
|
||||||
|
assign op = tap_data_i[DMI_OP_BITS-1:0];
|
||||||
|
|
||||||
|
|
||||||
|
always @ (*) begin
|
||||||
|
state_d = state_q;
|
||||||
|
dtm_valid = 1'b0;
|
||||||
|
dtm_data_d = dtm_data_q;
|
||||||
|
|
||||||
|
case (state_q)
|
||||||
|
S_IDLE: begin
|
||||||
|
if (tap_req_i) begin
|
||||||
|
if (op == `DMI_OP_READ) begin
|
||||||
|
state_d = S_READ;
|
||||||
|
dtm_data_d = tap_data_i;
|
||||||
|
end else if (op == `DMI_OP_WRITE) begin
|
||||||
|
state_d = S_WRITE;
|
||||||
|
dtm_data_d = tap_data_i;
|
||||||
|
end else begin
|
||||||
|
state_d = S_IDLE;
|
||||||
|
end
|
||||||
|
end else begin
|
||||||
|
state_d = S_IDLE;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
S_READ: begin
|
||||||
|
dtm_valid = 1'b1;
|
||||||
|
if (dmi_ready_i) begin
|
||||||
|
state_d = S_WAIT_READ;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
S_WAIT_READ: begin
|
||||||
|
if (dmi_valid_i) begin
|
||||||
|
dtm_data_d = dmi_data_i;
|
||||||
|
state_d = S_IDLE;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
S_WRITE: begin
|
||||||
|
dtm_valid = 1'b1;
|
||||||
|
if (dmi_ready_i) begin
|
||||||
|
state_d = S_WAIT_WRITE;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
S_WAIT_WRITE: begin
|
||||||
|
if (dmi_valid_i) begin
|
||||||
|
dtm_data_d = dmi_data_i;
|
||||||
|
state_d = S_IDLE;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
default: begin
|
||||||
|
dtm_data_d = {DTM_REQ_BITS{1'b0}};
|
||||||
|
state_d = S_IDLE;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
assign dtm_valid_o = dtm_valid;
|
||||||
|
assign dtm_data_o = dtm_data_q;
|
||||||
|
// we will always be ready to core request
|
||||||
|
assign dtm_ready_o = 1'b1;
|
||||||
|
|
||||||
|
always @ (posedge jtag_tck_i or negedge jtag_trst_ni) begin
|
||||||
|
if (!jtag_trst_ni) begin
|
||||||
|
state_q <= S_IDLE;
|
||||||
|
dtm_data_q <= {DTM_REQ_BITS{1'b0}};
|
||||||
|
end else begin
|
||||||
|
state_q <= state_d;
|
||||||
|
dtm_data_q <= dtm_data_d;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always @ (posedge jtag_tck_i or negedge jtag_trst_ni) begin
|
||||||
|
if (!jtag_trst_ni) begin
|
||||||
|
resp_tap_data_q <= {DTM_RESP_BITS{1'b0}};
|
||||||
|
is_busy <= 1'b0;
|
||||||
|
end else begin
|
||||||
|
if (state_q != S_IDLE) begin
|
||||||
|
resp_tap_data_q <= busy_response;
|
||||||
|
is_busy <= 1'b1;
|
||||||
|
end else begin
|
||||||
|
resp_tap_data_q <= dtm_data_q;
|
||||||
|
is_busy <= 1'b0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign data_o = resp_tap_data_q;
|
||||||
|
|
||||||
|
endmodule
|
|
@ -0,0 +1,194 @@
|
||||||
|
/*
|
||||||
|
Copyright 2021 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_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 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
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
// 16KB
|
||||||
|
localparam DbgAddressBits = 12;
|
||||||
|
// 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 WhereToAddr = 12'h300;
|
||||||
|
localparam FlagsBaseAddr = 12'h400;
|
||||||
|
localparam FlagsEndAddr = 12'h7FF;
|
||||||
|
|
||||||
|
localparam HaltedAddr = 12'h100;
|
||||||
|
localparam GoingAddr = 12'h104;
|
||||||
|
localparam ResumingAddr = 12'h108;
|
||||||
|
localparam ExceptionAddr = 12'h10C;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
wire fwd_rom_d;
|
||||||
|
wire[63:0] rom_rdata;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// word mux for 32bit and 64bit buses
|
||||||
|
wire [63:0] word_mux;
|
||||||
|
assign word_mux = fwd_rom_q ? rom_rdata : rdata_q;
|
||||||
|
assign rdata_o = (word_enable32_q) ? word_mux[32 +: 32] : word_mux[0 +: 32];
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
case (state_q)
|
||||||
|
S_IDLE: begin
|
||||||
|
if (resumereq_i && (!resuming_q) &&
|
||||||
|
halted_q && (!haltreq_i)) begin
|
||||||
|
state_d = S_RESUME;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
S_RESUME: begin
|
||||||
|
resume = 1'b1;
|
||||||
|
if (resuming_q) begin
|
||||||
|
state_d = S_IDLE;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
default:;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
always @ (*) begin
|
||||||
|
rdata_d = rdata_q;
|
||||||
|
halted_d = halted_q;
|
||||||
|
resuming_d = resuming_q;
|
||||||
|
|
||||||
|
if (clear_resumeack_i) begin
|
||||||
|
resuming_d = 1'b0;
|
||||||
|
end
|
||||||
|
|
||||||
|
// write
|
||||||
|
if (we_i) begin
|
||||||
|
case (addr_i[DbgAddressBits-1:0])
|
||||||
|
HaltedAddr: begin
|
||||||
|
halted_d = 1'b1;
|
||||||
|
end
|
||||||
|
|
||||||
|
GoingAddr: begin
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
ResumingAddr: begin
|
||||||
|
halted_d = 1'b0;
|
||||||
|
resuming_d = 1'b1;
|
||||||
|
end
|
||||||
|
|
||||||
|
ExceptionAddr: begin
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
default:;
|
||||||
|
endcase
|
||||||
|
// read
|
||||||
|
end else begin
|
||||||
|
case (addr_i[DbgAddressBits-1:0])
|
||||||
|
// harts are polling for flags here
|
||||||
|
FlagsBaseAddr: begin
|
||||||
|
rdata_d = {30'b0, resume, go};
|
||||||
|
end
|
||||||
|
|
||||||
|
default:;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
wire[63:0] rom_addr;
|
||||||
|
assign rom_addr = {32'h0, addr_i};
|
||||||
|
|
||||||
|
assign fwd_rom_d = addr_i[DbgAddressBits-1:0] >= `HaltAddress;
|
||||||
|
|
||||||
|
debug_rom u_debug_rom (
|
||||||
|
.clk_i ( clk ),
|
||||||
|
.req_i ( 1'b1 ),
|
||||||
|
.addr_i ( rom_addr ),
|
||||||
|
.rdata_o ( rom_rdata )
|
||||||
|
);
|
||||||
|
|
||||||
|
always @ (posedge clk or negedge rst_n) begin
|
||||||
|
if (!rst_n) begin
|
||||||
|
rdata_q <= 32'h0;
|
||||||
|
fwd_rom_q <= 1'b0;
|
||||||
|
word_enable32_q <= 1'b0;
|
||||||
|
halted_q <= 1'b0;
|
||||||
|
resuming_q <= 1'b0;
|
||||||
|
end else begin
|
||||||
|
rdata_q <= rdata_d;
|
||||||
|
fwd_rom_q <= fwd_rom_d;
|
||||||
|
word_enable32_q <= addr_i[2];
|
||||||
|
halted_q <= halted_d;
|
||||||
|
resuming_q <= resuming_d;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always @ (posedge clk or negedge rst_n) begin
|
||||||
|
if (!rst_n) begin
|
||||||
|
state_q <= S_IDLE;
|
||||||
|
end else begin
|
||||||
|
state_q <= state_d;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2020 Blue Liang, liangkangnan@163.com
|
Copyright 2021 Blue Liang, liangkangnan@163.com
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -15,43 +15,33 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
module vld_rdy #(
|
module jtag_sba #(
|
||||||
parameter CUT_READY = 0)(
|
|
||||||
|
)(
|
||||||
|
|
||||||
input wire clk,
|
input wire clk,
|
||||||
input wire rst_n,
|
input wire rst_n,
|
||||||
|
|
||||||
input wire vld_i,
|
output wire sbbusy_o,
|
||||||
output wire rdy_o,
|
|
||||||
input wire rdy_i,
|
output wire master_req_o,
|
||||||
output wire vld_o
|
input wire master_gnt_i,
|
||||||
|
input wire master_rvalid_i,
|
||||||
|
output wire master_we_o,
|
||||||
|
output wire [3:0] master_be_o,
|
||||||
|
output wire [31:0] master_addr_o,
|
||||||
|
output wire [31:0] master_wdata_o,
|
||||||
|
input wire [31:0] master_rdata_i,
|
||||||
|
input wire master_err_i
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
wire vld_set;
|
|
||||||
wire vld_clr;
|
|
||||||
wire vld_ena;
|
|
||||||
wire vld_r;
|
|
||||||
wire vld_nxt;
|
|
||||||
|
|
||||||
// The valid will be set when input handshaked
|
assign sbbusy_o = 1'b0;
|
||||||
assign vld_set = vld_i & rdy_o;
|
|
||||||
// The valid will be clr when output handshaked
|
|
||||||
assign vld_clr = vld_o & rdy_i;
|
|
||||||
|
|
||||||
assign vld_ena = vld_set | vld_clr;
|
assign master_req_o = 1'b0;
|
||||||
assign vld_nxt = vld_set | (~vld_clr);
|
assign master_we_o = 1'b0;
|
||||||
|
|
||||||
gen_en_dff #(1) vld_dff(clk, rst_n, vld_ena, vld_nxt, vld_r);
|
|
||||||
|
|
||||||
assign vld_o = vld_r;
|
|
||||||
|
|
||||||
if (CUT_READY == 1) begin
|
|
||||||
// If cut ready, then only accept when stage is not full
|
|
||||||
assign rdy_o = (~vld_r);
|
|
||||||
end else begin
|
|
||||||
// If not cut ready, then can accept when stage is not full or it is popping
|
|
||||||
assign rdy_o = (~vld_r) | vld_clr;
|
|
||||||
end
|
|
||||||
|
|
||||||
endmodule
|
endmodule
|
|
@ -0,0 +1,175 @@
|
||||||
|
/*
|
||||||
|
Copyright 2021 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_tap #(
|
||||||
|
parameter DMI_ADDR_BITS = 6,
|
||||||
|
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
|
||||||
|
)(
|
||||||
|
|
||||||
|
input wire jtag_tck_i, // JTAG test clock pad
|
||||||
|
input wire jtag_tdi_i, // JTAG test data input pad
|
||||||
|
input wire jtag_tms_i, // JTAG test mode select pad
|
||||||
|
input wire jtag_trst_ni, // JTAG test reset pad
|
||||||
|
output wire jtag_tdo_o, // JTAG test data output pad
|
||||||
|
|
||||||
|
output wire tap_req_o,
|
||||||
|
output wire[TAP_REQ_BITS-1:0] tap_data_o,
|
||||||
|
|
||||||
|
input wire[DTM_RESP_BITS-1:0] dtm_data_i,
|
||||||
|
input wire[31:0] idcode_i,
|
||||||
|
input wire[31:0] dtmcs_i
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
localparam SHIFT_REG_BITS = TAP_REQ_BITS;
|
||||||
|
|
||||||
|
localparam TEST_LOGIC_RESET = 16'h0001;
|
||||||
|
localparam RUN_TEST_IDLE = 16'h0002;
|
||||||
|
localparam SELECT_DR = 16'h0004;
|
||||||
|
localparam CAPTURE_DR = 16'h0008;
|
||||||
|
localparam SHIFT_DR = 16'h0010;
|
||||||
|
localparam EXIT1_DR = 16'h0020;
|
||||||
|
localparam PAUSE_DR = 16'h0040;
|
||||||
|
localparam EXIT2_DR = 16'h0080;
|
||||||
|
localparam UPDATE_DR = 16'h0100;
|
||||||
|
localparam SELECT_IR = 16'h0200;
|
||||||
|
localparam CAPTURE_IR = 16'h0400;
|
||||||
|
localparam SHIFT_IR = 16'h0800;
|
||||||
|
localparam EXIT1_IR = 16'h1000;
|
||||||
|
localparam PAUSE_IR = 16'h2000;
|
||||||
|
localparam EXIT2_IR = 16'h4000;
|
||||||
|
localparam UPDATE_IR = 16'h8000;
|
||||||
|
|
||||||
|
// DTM regs
|
||||||
|
localparam REG_BYPASS = 5'b11111;
|
||||||
|
localparam REG_IDCODE = 5'b00001;
|
||||||
|
localparam REG_DMI = 5'b10001;
|
||||||
|
localparam REG_DTMCS = 5'b10000;
|
||||||
|
|
||||||
|
reg[IR_BITS-1:0] ir_reg;
|
||||||
|
reg[SHIFT_REG_BITS-1:0] shift_reg;
|
||||||
|
|
||||||
|
reg[15:0] tap_state;
|
||||||
|
reg[15:0] next_state;
|
||||||
|
|
||||||
|
always @ (posedge jtag_tck_i or negedge jtag_trst_ni) begin
|
||||||
|
if (!jtag_trst_ni) begin
|
||||||
|
tap_state <= TEST_LOGIC_RESET;
|
||||||
|
end else begin
|
||||||
|
tap_state <= next_state;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// state switch
|
||||||
|
always @ (*) begin
|
||||||
|
case (tap_state)
|
||||||
|
TEST_LOGIC_RESET : next_state = jtag_tms_i ? TEST_LOGIC_RESET : RUN_TEST_IDLE;
|
||||||
|
RUN_TEST_IDLE : next_state = jtag_tms_i ? SELECT_DR : RUN_TEST_IDLE;
|
||||||
|
SELECT_DR : next_state = jtag_tms_i ? SELECT_IR : CAPTURE_DR;
|
||||||
|
CAPTURE_DR : next_state = jtag_tms_i ? EXIT1_DR : SHIFT_DR;
|
||||||
|
SHIFT_DR : next_state = jtag_tms_i ? EXIT1_DR : SHIFT_DR;
|
||||||
|
EXIT1_DR : next_state = jtag_tms_i ? UPDATE_DR : PAUSE_DR;
|
||||||
|
PAUSE_DR : next_state = jtag_tms_i ? EXIT2_DR : PAUSE_DR;
|
||||||
|
EXIT2_DR : next_state = jtag_tms_i ? UPDATE_DR : SHIFT_DR;
|
||||||
|
UPDATE_DR : next_state = jtag_tms_i ? SELECT_DR : RUN_TEST_IDLE;
|
||||||
|
SELECT_IR : next_state = jtag_tms_i ? TEST_LOGIC_RESET : CAPTURE_IR;
|
||||||
|
CAPTURE_IR : next_state = jtag_tms_i ? EXIT1_IR : SHIFT_IR;
|
||||||
|
SHIFT_IR : next_state = jtag_tms_i ? EXIT1_IR : SHIFT_IR;
|
||||||
|
EXIT1_IR : next_state = jtag_tms_i ? UPDATE_IR : PAUSE_IR;
|
||||||
|
PAUSE_IR : next_state = jtag_tms_i ? EXIT2_IR : PAUSE_IR;
|
||||||
|
EXIT2_IR : next_state = jtag_tms_i ? UPDATE_IR : SHIFT_IR;
|
||||||
|
UPDATE_IR : next_state = jtag_tms_i ? SELECT_DR : RUN_TEST_IDLE;
|
||||||
|
default : next_state = TEST_LOGIC_RESET;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
// IR or DR shift
|
||||||
|
always @ (posedge jtag_tck_i or negedge jtag_trst_ni) begin
|
||||||
|
if (!jtag_trst_ni) begin
|
||||||
|
shift_reg <= {SHIFT_REG_BITS{1'b0}};
|
||||||
|
end else begin
|
||||||
|
case (tap_state)
|
||||||
|
// IR
|
||||||
|
CAPTURE_IR: shift_reg <= {{(SHIFT_REG_BITS-1){1'b0}}, 1'b1}; //JTAG spec says it must be 2'b01
|
||||||
|
SHIFT_IR : shift_reg <= {{(SHIFT_REG_BITS-IR_BITS){1'b0}}, jtag_tdi_i, 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_i};
|
||||||
|
REG_DTMCS : shift_reg <= {{(SHIFT_REG_BITS-DMI_DATA_BITS){1'b0}}, dtmcs_i};
|
||||||
|
REG_DMI : shift_reg <= dtm_data_i;
|
||||||
|
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_i}; // in = out
|
||||||
|
REG_IDCODE : shift_reg <= {{(SHIFT_REG_BITS-DMI_DATA_BITS){1'b0}}, jtag_tdi_i, shift_reg[31:1]}; // right shift 1 bit
|
||||||
|
REG_DTMCS : shift_reg <= {{(SHIFT_REG_BITS-DMI_DATA_BITS){1'b0}}, jtag_tdi_i, shift_reg[31:1]}; // right shift 1 bit
|
||||||
|
REG_DMI : shift_reg <= {jtag_tdi_i, shift_reg[SHIFT_REG_BITS-1:1]}; // right shift 1 bit
|
||||||
|
default : shift_reg <= {{(SHIFT_REG_BITS-1){1'b0}} , jtag_tdi_i};
|
||||||
|
endcase
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
reg tap_req_q;
|
||||||
|
reg[TAP_REQ_BITS-1:0] tap_data_q;
|
||||||
|
|
||||||
|
// send request to DTM module
|
||||||
|
always @ (posedge jtag_tck_i or negedge jtag_trst_ni) begin
|
||||||
|
if (!jtag_trst_ni) begin
|
||||||
|
tap_req_q <= 1'b0;
|
||||||
|
tap_data_q <= {TAP_REQ_BITS{1'b0}};
|
||||||
|
end else begin
|
||||||
|
if ((tap_state == UPDATE_DR) && (ir_reg == REG_DMI)) begin
|
||||||
|
tap_req_q <= 1'b1;
|
||||||
|
tap_data_q <= shift_reg;
|
||||||
|
end else begin
|
||||||
|
tap_req_q <= 1'b0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign tap_req_o = tap_req_q;
|
||||||
|
assign tap_data_o = tap_data_q;
|
||||||
|
|
||||||
|
// ir_reg
|
||||||
|
always @ (negedge jtag_tck_i) begin
|
||||||
|
if (tap_state == TEST_LOGIC_RESET) begin
|
||||||
|
ir_reg <= REG_IDCODE;
|
||||||
|
end else if (tap_state == UPDATE_IR) begin
|
||||||
|
ir_reg <= shift_reg[IR_BITS-1:0];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
reg jtag_tdo_q;
|
||||||
|
|
||||||
|
// TDO output
|
||||||
|
always @ (negedge jtag_tck_i) begin
|
||||||
|
if ((tap_state == SHIFT_IR) || (tap_state == SHIFT_DR)) begin
|
||||||
|
jtag_tdo_q <= shift_reg[0];
|
||||||
|
end else begin
|
||||||
|
jtag_tdo_q <= 1'b0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign jtag_tdo_o = jtag_tdo_q;
|
||||||
|
|
||||||
|
endmodule
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2020 Blue Liang, liangkangnan@163.com
|
Copyright 2021 Blue Liang, liangkangnan@163.com
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -14,104 +14,148 @@
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
`include "../core/defines.sv"
|
|
||||||
|
|
||||||
// JTAG顶层模块
|
|
||||||
module jtag_top #(
|
module jtag_top #(
|
||||||
parameter DMI_ADDR_BITS = 6,
|
|
||||||
parameter DMI_DATA_BITS = 32,
|
|
||||||
parameter DMI_OP_BITS = 2)(
|
|
||||||
|
|
||||||
input wire clk,
|
)(
|
||||||
input wire jtag_rst_n,
|
|
||||||
|
|
||||||
input wire jtag_pin_TCK,
|
input wire clk_i,
|
||||||
input wire jtag_pin_TMS,
|
input wire rst_ni,
|
||||||
input wire jtag_pin_TDI,
|
|
||||||
output wire jtag_pin_TDO,
|
|
||||||
|
|
||||||
output wire reg_we_o,
|
output wire debug_req_o,
|
||||||
output wire[4:0] reg_addr_o,
|
output wire ndmreset_o,
|
||||||
output wire[31:0] reg_wdata_o,
|
|
||||||
input wire[31:0] reg_rdata_i,
|
|
||||||
|
|
||||||
output wire mem_we_o,
|
input wire jtag_tck_i, // JTAG test clock pad
|
||||||
output wire[31:0] mem_addr_o,
|
input wire jtag_tdi_i, // JTAG test data input pad
|
||||||
output wire[31:0] mem_wdata_o,
|
input wire jtag_tms_i, // JTAG test mode select pad
|
||||||
input wire[31:0] mem_rdata_i,
|
input wire jtag_trst_ni, // JTAG test reset pad
|
||||||
output wire[3:0] mem_sel_o,
|
output wire jtag_tdo_o, // JTAG test data output pad
|
||||||
|
|
||||||
output wire req_valid_o,
|
output wire master_req_o,
|
||||||
input wire req_ready_i,
|
input wire master_gnt_i,
|
||||||
input wire rsp_valid_i,
|
input wire master_rvalid_i,
|
||||||
output wire rsp_ready_o,
|
output wire master_we_o,
|
||||||
|
output wire [3:0] master_be_o,
|
||||||
|
output wire [31:0] master_addr_o,
|
||||||
|
output wire [31:0] master_wdata_o,
|
||||||
|
input wire [31:0] master_rdata_i,
|
||||||
|
input wire master_err_i,
|
||||||
|
|
||||||
output wire halt_req_o,
|
input wire slave_req_i,
|
||||||
output wire reset_req_o
|
input wire slave_we_i,
|
||||||
|
input wire [31:0] slave_addr_i,
|
||||||
|
input wire [3:0] slave_be_i,
|
||||||
|
input wire [31:0] slave_wdata_i,
|
||||||
|
output wire [31:0] slave_rdata_o
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
parameter DM_RESP_BITS = DMI_ADDR_BITS + DMI_DATA_BITS + DMI_OP_BITS;
|
// addr + data + op = 6 + 32 + 2 = 40
|
||||||
parameter DTM_REQ_BITS = DMI_ADDR_BITS + DMI_DATA_BITS + DMI_OP_BITS;
|
localparam DMI_DATA_WIDTH = 40;
|
||||||
|
|
||||||
// jtag_driver输出信号
|
|
||||||
wire dtm_ack_o;
|
|
||||||
wire dtm_req_valid_o;
|
|
||||||
wire[DTM_REQ_BITS - 1:0] dtm_req_data_o;
|
|
||||||
|
|
||||||
// jtag_dm输出信号
|
wire [DMI_DATA_WIDTH-1:0] dm_to_dmi_data;
|
||||||
wire dm_ack_o;
|
wire dm_to_dmi_valid;
|
||||||
wire[DM_RESP_BITS-1:0] dm_resp_data_o;
|
wire dm_to_dmi_ready;
|
||||||
wire dm_resp_valid_o;
|
wire [DMI_DATA_WIDTH-1:0] dmi_to_dm_data;
|
||||||
wire dm_halt_req_o;
|
wire dmi_to_dm_valid;
|
||||||
wire dm_reset_req_o;
|
wire dmi_to_dm_ready;
|
||||||
|
|
||||||
jtag_driver #(
|
|
||||||
.DMI_ADDR_BITS(DMI_ADDR_BITS),
|
|
||||||
.DMI_DATA_BITS(DMI_DATA_BITS),
|
|
||||||
.DMI_OP_BITS(DMI_OP_BITS)
|
|
||||||
) u_jtag_driver(
|
|
||||||
.rst_n(jtag_rst_n),
|
|
||||||
.jtag_TCK(jtag_pin_TCK),
|
|
||||||
.jtag_TDI(jtag_pin_TDI),
|
|
||||||
.jtag_TMS(jtag_pin_TMS),
|
|
||||||
.jtag_TDO(jtag_pin_TDO),
|
|
||||||
.dm_resp_i(dm_resp_valid_o),
|
|
||||||
.dm_resp_data_i(dm_resp_data_o),
|
|
||||||
.dtm_ack_o(dtm_ack_o),
|
|
||||||
.dm_ack_i(dm_ack_o),
|
|
||||||
.dtm_req_valid_o(dtm_req_valid_o),
|
|
||||||
.dtm_req_data_o(dtm_req_data_o)
|
|
||||||
);
|
|
||||||
|
|
||||||
jtag_dm #(
|
jtag_dm #(
|
||||||
.DMI_ADDR_BITS(DMI_ADDR_BITS),
|
|
||||||
.DMI_DATA_BITS(DMI_DATA_BITS),
|
) u_jtag_dm (
|
||||||
.DMI_OP_BITS(DMI_OP_BITS)
|
.clk (clk_i),
|
||||||
) u_jtag_dm(
|
.rst_n (rst_ni),
|
||||||
.clk(clk),
|
.dmi_data_i (dmi_to_dm_data),
|
||||||
.rst_n(jtag_rst_n),
|
.dmi_valid_i (dmi_to_dm_valid),
|
||||||
.dm_ack_o(dm_ack_o),
|
.dm_ready_o (dm_to_dmi_ready),
|
||||||
.dtm_req_valid_i(dtm_req_valid_o),
|
.dm_data_o (dm_to_dmi_data),
|
||||||
.dtm_req_data_i(dtm_req_data_o),
|
.dm_valid_o (dm_to_dmi_valid),
|
||||||
.dtm_ack_i(dtm_ack_o),
|
.dmi_ready_i (dmi_to_dm_ready),
|
||||||
.dm_resp_data_o(dm_resp_data_o),
|
.debug_req_o (debug_req_o),
|
||||||
.dm_resp_valid_o(dm_resp_valid_o),
|
.ndmreset_o (ndmreset_o),
|
||||||
.dm_reg_we_o(reg_we_o),
|
.master_req_o (master_req_o),
|
||||||
.dm_reg_addr_o(reg_addr_o),
|
.master_gnt_i (master_gnt_i),
|
||||||
.dm_reg_wdata_o(reg_wdata_o),
|
.master_rvalid_i(master_rvalid_i),
|
||||||
.dm_reg_rdata_i(reg_rdata_i),
|
.master_we_o (master_we_o),
|
||||||
.dm_mem_we_o(mem_we_o),
|
.master_be_o (master_be_o),
|
||||||
.dm_mem_addr_o(mem_addr_o),
|
.master_addr_o (master_addr_o),
|
||||||
.dm_mem_wdata_o(mem_wdata_o),
|
.master_wdata_o (master_wdata_o),
|
||||||
.dm_mem_rdata_i(mem_rdata_i),
|
.master_rdata_i (master_rdata_i),
|
||||||
.dm_mem_sel_o(mem_sel_o),
|
.master_err_i (master_err_i),
|
||||||
.req_valid_o(req_valid_o),
|
.slave_req_i (slave_req_i),
|
||||||
.req_ready_i(req_ready_i),
|
.slave_we_i (slave_we_i),
|
||||||
.rsp_valid_i(rsp_valid_i),
|
.slave_addr_i (slave_addr_i),
|
||||||
.rsp_ready_o(rsp_ready_o),
|
.slave_be_i (slave_be_i),
|
||||||
.dm_halt_req_o(halt_req_o),
|
.slave_wdata_i (slave_wdata_i),
|
||||||
.dm_reset_req_o(reset_req_o)
|
.slave_rdata_o (slave_rdata_o)
|
||||||
|
);
|
||||||
|
|
||||||
|
wire [DMI_DATA_WIDTH-1:0] dtm_to_dmi_data;
|
||||||
|
wire dtm_to_dmi_valid;
|
||||||
|
wire dtm_to_dmi_ready;
|
||||||
|
wire [DMI_DATA_WIDTH-1:0] dmi_to_dtm_data;
|
||||||
|
wire dmi_to_dtm_valid;
|
||||||
|
wire dmi_to_dtm_ready;
|
||||||
|
|
||||||
|
jtag_dmi #(
|
||||||
|
|
||||||
|
) u_jtag_dmi (
|
||||||
|
.jtag_tck_i (jtag_tck_i),
|
||||||
|
.jtag_trst_ni (jtag_trst_ni),
|
||||||
|
.jtag_data_i (dtm_to_dmi_data),
|
||||||
|
.jtag_valid_i (dtm_to_dmi_valid),
|
||||||
|
.jtag_ready_o (dmi_to_dtm_ready),
|
||||||
|
.jtag_data_o (dmi_to_dtm_data),
|
||||||
|
.jtag_valid_o (dmi_to_dtm_valid),
|
||||||
|
.jtag_ready_i (dtm_to_dmi_ready),
|
||||||
|
.clk_i (clk_i),
|
||||||
|
.rst_ni (rst_ni),
|
||||||
|
.core_data_i (dm_to_dmi_data),
|
||||||
|
.core_valid_i (dm_to_dmi_valid),
|
||||||
|
.core_ready_o (dmi_to_dm_ready),
|
||||||
|
.core_data_o (dmi_to_dm_data),
|
||||||
|
.core_valid_o (dmi_to_dm_valid),
|
||||||
|
.core_ready_i (dm_to_dmi_ready)
|
||||||
|
);
|
||||||
|
|
||||||
|
wire tap_to_dtm_req;
|
||||||
|
wire [DMI_DATA_WIDTH-1:0] tap_to_dtm_data;
|
||||||
|
wire [DMI_DATA_WIDTH-1:0] dtm_to_tap_data;
|
||||||
|
wire [31:0] idcode;
|
||||||
|
wire [31:0] dtmcs;
|
||||||
|
|
||||||
|
jtag_dtm #(
|
||||||
|
|
||||||
|
) u_jtag_dtm (
|
||||||
|
.jtag_tck_i (jtag_tck_i),
|
||||||
|
.jtag_trst_ni (jtag_trst_ni),
|
||||||
|
.dtm_data_o (dtm_to_dmi_data),
|
||||||
|
.dtm_valid_o (dtm_to_dmi_valid),
|
||||||
|
.dmi_ready_i (dmi_to_dtm_ready),
|
||||||
|
.dmi_data_i (dmi_to_dtm_data),
|
||||||
|
.dmi_valid_i (dmi_to_dtm_valid),
|
||||||
|
.dtm_ready_o (dtm_to_dmi_ready),
|
||||||
|
.tap_req_i (tap_to_dtm_req),
|
||||||
|
.tap_data_i (tap_to_dtm_data),
|
||||||
|
.data_o (dtm_to_tap_data),
|
||||||
|
.idcode_o (idcode),
|
||||||
|
.dtmcs_o (dtmcs)
|
||||||
|
);
|
||||||
|
|
||||||
|
jtag_tap #(
|
||||||
|
|
||||||
|
) u_jtag_tap (
|
||||||
|
.jtag_tck_i (jtag_tck_i),
|
||||||
|
.jtag_tdi_i (jtag_tdi_i),
|
||||||
|
.jtag_tms_i (jtag_tms_i),
|
||||||
|
.jtag_trst_ni (jtag_trst_ni),
|
||||||
|
.jtag_tdo_o (jtag_tdo_o),
|
||||||
|
.tap_req_o (tap_to_dtm_req),
|
||||||
|
.tap_data_o (tap_to_dtm_data),
|
||||||
|
.dtm_data_i (dtm_to_tap_data),
|
||||||
|
.idcode_i (idcode),
|
||||||
|
.dtmcs_i (dtmcs)
|
||||||
);
|
);
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
@ -1,373 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
// RIB总线模块
|
|
||||||
module rib #(
|
|
||||||
parameter MASTER_NUM = 3,
|
|
||||||
parameter SLAVE_NUM = 2)(
|
|
||||||
|
|
||||||
input wire clk,
|
|
||||||
input wire rst_n,
|
|
||||||
|
|
||||||
// master 0 interface
|
|
||||||
input wire[31:0] m0_addr_i,
|
|
||||||
input wire[31:0] m0_data_i,
|
|
||||||
input wire[3:0] m0_sel_i,
|
|
||||||
input wire m0_req_vld_i,
|
|
||||||
input wire m0_rsp_rdy_i,
|
|
||||||
input wire m0_we_i,
|
|
||||||
output wire m0_req_rdy_o,
|
|
||||||
output wire m0_rsp_vld_o,
|
|
||||||
output wire[31:0] m0_data_o,
|
|
||||||
|
|
||||||
// master 1 interface
|
|
||||||
input wire[31:0] m1_addr_i,
|
|
||||||
input wire[31:0] m1_data_i,
|
|
||||||
input wire[3:0] m1_sel_i,
|
|
||||||
input wire m1_req_vld_i,
|
|
||||||
input wire m1_rsp_rdy_i,
|
|
||||||
input wire m1_we_i,
|
|
||||||
output wire m1_req_rdy_o,
|
|
||||||
output wire m1_rsp_vld_o,
|
|
||||||
output wire[31:0] m1_data_o,
|
|
||||||
|
|
||||||
// master 2 interface
|
|
||||||
input wire[31:0] m2_addr_i,
|
|
||||||
input wire[31:0] m2_data_i,
|
|
||||||
input wire[3:0] m2_sel_i,
|
|
||||||
input wire m2_req_vld_i,
|
|
||||||
input wire m2_rsp_rdy_i,
|
|
||||||
input wire m2_we_i,
|
|
||||||
output wire m2_req_rdy_o,
|
|
||||||
output wire m2_rsp_vld_o,
|
|
||||||
output wire[31:0] m2_data_o,
|
|
||||||
|
|
||||||
// master 3 interface
|
|
||||||
input wire[31:0] m3_addr_i,
|
|
||||||
input wire[31:0] m3_data_i,
|
|
||||||
input wire[3:0] m3_sel_i,
|
|
||||||
input wire m3_req_vld_i,
|
|
||||||
input wire m3_rsp_rdy_i,
|
|
||||||
input wire m3_we_i,
|
|
||||||
output wire m3_req_rdy_o,
|
|
||||||
output wire m3_rsp_vld_o,
|
|
||||||
output wire[31:0] m3_data_o,
|
|
||||||
|
|
||||||
// slave 0 interface
|
|
||||||
input wire[31:0] s0_data_i,
|
|
||||||
input wire s0_req_rdy_i,
|
|
||||||
input wire s0_rsp_vld_i,
|
|
||||||
output wire[31:0] s0_addr_o,
|
|
||||||
output wire[31:0] s0_data_o,
|
|
||||||
output wire[3:0] s0_sel_o,
|
|
||||||
output wire s0_req_vld_o,
|
|
||||||
output wire s0_rsp_rdy_o,
|
|
||||||
output wire s0_we_o,
|
|
||||||
|
|
||||||
// slave 1 interface
|
|
||||||
input wire[31:0] s1_data_i,
|
|
||||||
input wire s1_req_rdy_i,
|
|
||||||
input wire s1_rsp_vld_i,
|
|
||||||
output wire[31:0] s1_addr_o,
|
|
||||||
output wire[31:0] s1_data_o,
|
|
||||||
output wire[3:0] s1_sel_o,
|
|
||||||
output wire s1_req_vld_o,
|
|
||||||
output wire s1_rsp_rdy_o,
|
|
||||||
output wire s1_we_o,
|
|
||||||
|
|
||||||
// slave 2 interface
|
|
||||||
input wire[31:0] s2_data_i,
|
|
||||||
input wire s2_req_rdy_i,
|
|
||||||
input wire s2_rsp_vld_i,
|
|
||||||
output wire[31:0] s2_addr_o,
|
|
||||||
output wire[31:0] s2_data_o,
|
|
||||||
output wire[3:0] s2_sel_o,
|
|
||||||
output wire s2_req_vld_o,
|
|
||||||
output wire s2_rsp_rdy_o,
|
|
||||||
output wire s2_we_o,
|
|
||||||
|
|
||||||
// slave 3 interface
|
|
||||||
input wire[31:0] s3_data_i,
|
|
||||||
input wire s3_req_rdy_i,
|
|
||||||
input wire s3_rsp_vld_i,
|
|
||||||
output wire[31:0] s3_addr_o,
|
|
||||||
output wire[31:0] s3_data_o,
|
|
||||||
output wire[3:0] s3_sel_o,
|
|
||||||
output wire s3_req_vld_o,
|
|
||||||
output wire s3_rsp_rdy_o,
|
|
||||||
output wire s3_we_o,
|
|
||||||
|
|
||||||
// slave 4 interface
|
|
||||||
input wire[31:0] s4_data_i,
|
|
||||||
input wire s4_req_rdy_i,
|
|
||||||
input wire s4_rsp_vld_i,
|
|
||||||
output wire[31:0] s4_addr_o,
|
|
||||||
output wire[31:0] s4_data_o,
|
|
||||||
output wire[3:0] s4_sel_o,
|
|
||||||
output wire s4_req_vld_o,
|
|
||||||
output wire s4_rsp_rdy_o,
|
|
||||||
output wire s4_we_o
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
/////////////////////////////// mux master //////////////////////////////
|
|
||||||
|
|
||||||
wire[MASTER_NUM-1:0] master_req;
|
|
||||||
wire[31:0] master_addr[MASTER_NUM-1:0];
|
|
||||||
wire[31:0] master_data[MASTER_NUM-1:0];
|
|
||||||
wire[3:0] master_sel[MASTER_NUM-1:0];
|
|
||||||
wire[MASTER_NUM-1:0] master_rsp_rdy;
|
|
||||||
wire[MASTER_NUM-1:0] master_we;
|
|
||||||
|
|
||||||
genvar i;
|
|
||||||
generate
|
|
||||||
|
|
||||||
if (MASTER_NUM == 2) begin: if_m_num_2
|
|
||||||
assign master_req = {m0_req_vld_i, m1_req_vld_i};
|
|
||||||
assign master_rsp_rdy = {m0_rsp_rdy_i, m1_rsp_rdy_i};
|
|
||||||
assign master_we = {m0_we_i, m1_we_i};
|
|
||||||
wire[32*MASTER_NUM-1:0] m_addr = {m0_addr_i, m1_addr_i};
|
|
||||||
wire[32*MASTER_NUM-1:0] m_data = {m0_data_i, m1_data_i};
|
|
||||||
wire[4*MASTER_NUM-1:0] m_sel = {m0_sel_i, m1_sel_i};
|
|
||||||
for (i = 0; i < MASTER_NUM; i = i + 1) begin: for_m_num_2
|
|
||||||
assign master_addr[i] = m_addr[(i+1)*32-1:32*i];
|
|
||||||
assign master_data[i] = m_data[(i+1)*32-1:32*i];
|
|
||||||
assign master_sel[i] = m_sel[(i+1)*4-1:4*i];
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if (MASTER_NUM == 3) begin: if_m_num_3
|
|
||||||
assign master_req = {m0_req_vld_i, m1_req_vld_i, m2_req_vld_i};
|
|
||||||
assign master_rsp_rdy = {m0_rsp_rdy_i, m1_rsp_rdy_i, m2_rsp_rdy_i};
|
|
||||||
assign master_we = {m0_we_i, m1_we_i, m2_we_i};
|
|
||||||
wire[32*MASTER_NUM-1:0] m_addr = {m0_addr_i, m1_addr_i, m2_addr_i};
|
|
||||||
wire[32*MASTER_NUM-1:0] m_data = {m0_data_i, m1_data_i, m2_data_i};
|
|
||||||
wire[4*MASTER_NUM-1:0] m_sel = {m0_sel_i, m1_sel_i, m2_sel_i};
|
|
||||||
for (i = 0; i < MASTER_NUM; i = i + 1) begin: for_m_num_3
|
|
||||||
assign master_addr[i] = m_addr[(i+1)*32-1:32*i];
|
|
||||||
assign master_data[i] = m_data[(i+1)*32-1:32*i];
|
|
||||||
assign master_sel[i] = m_sel[(i+1)*4-1:4*i];
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if (MASTER_NUM == 4) begin: if_m_num_4
|
|
||||||
assign master_req = {m0_req_vld_i, m1_req_vld_i, m2_req_vld_i, m3_req_vld_i};
|
|
||||||
assign master_rsp_rdy = {m0_rsp_rdy_i, m1_rsp_rdy_i, m2_rsp_rdy_i, m3_rsp_rdy_i};
|
|
||||||
assign master_we = {m0_we_i, m1_we_i, m2_we_i, m3_we_i};
|
|
||||||
wire[32*MASTER_NUM-1:0] m_addr = {m0_addr_i, m1_addr_i, m2_addr_i, m3_addr_i};
|
|
||||||
wire[32*MASTER_NUM-1:0] m_data = {m0_data_i, m1_data_i, m2_data_i, m3_data_i};
|
|
||||||
wire[4*MASTER_NUM-1:0] m_sel = {m0_sel_i, m1_sel_i, m2_sel_i, m3_sel_i};
|
|
||||||
for (i = 0; i < MASTER_NUM; i = i + 1) begin: for_m_num_4
|
|
||||||
assign master_addr[i] = m_addr[(i+1)*32-1:32*i];
|
|
||||||
assign master_data[i] = m_data[(i+1)*32-1:32*i];
|
|
||||||
assign master_sel[i] = m_sel[(i+1)*4-1:4*i];
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
wire[MASTER_NUM-1:0] master_req_vec;
|
|
||||||
wire[MASTER_NUM-1:0] master_sel_vec;
|
|
||||||
|
|
||||||
// 优先级仲裁机制,LSB优先级最高,MSB优先级最低
|
|
||||||
for (i = 0; i < MASTER_NUM; i = i + 1) begin: m_arb
|
|
||||||
if (i == 0) begin: m_is_0
|
|
||||||
assign master_req_vec[i] = 1'b1;
|
|
||||||
end else begin: m_is_not_0
|
|
||||||
assign master_req_vec[i] = ~(|master_req[i-1:0]);
|
|
||||||
end
|
|
||||||
assign master_sel_vec[i] = master_req_vec[i] & master_req[i];
|
|
||||||
end
|
|
||||||
|
|
||||||
reg[31:0] mux_m_addr;
|
|
||||||
reg[31:0] mux_m_data;
|
|
||||||
reg[3:0] mux_m_sel;
|
|
||||||
reg mux_m_req_vld;
|
|
||||||
reg mux_m_rsp_rdy;
|
|
||||||
reg mux_m_we;
|
|
||||||
|
|
||||||
integer j;
|
|
||||||
|
|
||||||
always @ (*) begin: m_out
|
|
||||||
mux_m_addr = 32'h0;
|
|
||||||
mux_m_data = 32'h0;
|
|
||||||
mux_m_sel = 4'h0;
|
|
||||||
mux_m_req_vld = 1'b0;
|
|
||||||
mux_m_rsp_rdy = 1'b0;
|
|
||||||
mux_m_we = 1'b0;
|
|
||||||
for (j = 0; j < MASTER_NUM; j = j + 1) begin: m_sig_out
|
|
||||||
mux_m_addr = mux_m_addr | ({32{master_sel_vec[j]}} & master_addr[j]);
|
|
||||||
mux_m_data = mux_m_data | ({32{master_sel_vec[j]}} & master_data[j]);
|
|
||||||
mux_m_sel = mux_m_sel | ({4 {master_sel_vec[j]}} & master_sel[j]);
|
|
||||||
mux_m_req_vld = mux_m_req_vld | ({1 {master_sel_vec[j]}} & master_req[j]);
|
|
||||||
mux_m_rsp_rdy = mux_m_rsp_rdy | ({1 {master_sel_vec[j]}} & master_rsp_rdy[j]);
|
|
||||||
mux_m_we = mux_m_we | ({1 {master_sel_vec[j]}} & master_we[j]);
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
/////////////////////////////// mux slave /////////////////////////////////
|
|
||||||
|
|
||||||
wire[SLAVE_NUM-1:0] slave_sel;
|
|
||||||
|
|
||||||
// 访问地址的最高4位决定要访问的是哪一个从设备
|
|
||||||
// 因此最多支持16个从设备
|
|
||||||
for (i = 0; i < SLAVE_NUM; i = i + 1) begin: s_sel
|
|
||||||
assign slave_sel[i] = (mux_m_addr[31:28] == i);
|
|
||||||
end
|
|
||||||
|
|
||||||
wire[SLAVE_NUM-1:0] slave_req_rdy;
|
|
||||||
wire[SLAVE_NUM-1:0] slave_rsp_vld;
|
|
||||||
wire[31:0] slave_data[SLAVE_NUM-1:0];
|
|
||||||
|
|
||||||
if (SLAVE_NUM == 2) begin: if_s_num_2
|
|
||||||
assign slave_req_rdy = {s1_req_rdy_i, s0_req_rdy_i};
|
|
||||||
assign slave_rsp_vld = {s1_rsp_vld_i, s0_rsp_vld_i};
|
|
||||||
wire[32*SLAVE_NUM-1:0] s_data = {s1_data_i, s0_data_i};
|
|
||||||
for (i = 0; i < SLAVE_NUM; i = i + 1) begin: for_s_num_2
|
|
||||||
assign slave_data[i] = s_data[(i+1)*32-1:32*i];
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if (SLAVE_NUM == 3) begin: if_s_num_3
|
|
||||||
assign slave_req_rdy = {s2_req_rdy_i, s1_req_rdy_i, s0_req_rdy_i};
|
|
||||||
assign slave_rsp_vld = {s2_rsp_vld_i, s1_rsp_vld_i, s0_rsp_vld_i};
|
|
||||||
wire[32*SLAVE_NUM-1:0] s_data = {s2_data_i, s1_data_i, s0_data_i};
|
|
||||||
for (i = 0; i < SLAVE_NUM; i = i + 1) begin: for_s_num_3
|
|
||||||
assign slave_data[i] = s_data[(i+1)*32-1:32*i];
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if (SLAVE_NUM == 4) begin: if_s_num_4
|
|
||||||
assign slave_req_rdy = {s3_req_rdy_i, s2_req_rdy_i, s1_req_rdy_i, s0_req_rdy_i};
|
|
||||||
assign slave_rsp_vld = {s3_rsp_vld_i, s2_rsp_vld_i, s1_rsp_vld_i, s0_rsp_vld_i};
|
|
||||||
wire[32*SLAVE_NUM-1:0] s_data = {s3_data_i, s2_data_i, s1_data_i, s0_data_i};
|
|
||||||
for (i = 0; i < SLAVE_NUM; i = i + 1) begin: for_s_num_4
|
|
||||||
assign slave_data[i] = s_data[(i+1)*32-1:32*i];
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if (SLAVE_NUM == 5) begin: if_s_num_5
|
|
||||||
assign slave_req_rdy = {s4_req_rdy_i, s3_req_rdy_i, s2_req_rdy_i, s1_req_rdy_i, s0_req_rdy_i};
|
|
||||||
assign slave_rsp_vld = {s4_rsp_vld_i, s3_rsp_vld_i, s2_rsp_vld_i, s1_rsp_vld_i, s0_rsp_vld_i};
|
|
||||||
wire[32*SLAVE_NUM-1:0] s_data = {s4_data_i, s3_data_i, s2_data_i, s1_data_i, s0_data_i};
|
|
||||||
for (i = 0; i < SLAVE_NUM; i = i + 1) begin: for_s_num_5
|
|
||||||
assign slave_data[i] = s_data[(i+1)*32-1:32*i];
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
reg[31:0] mux_s_data;
|
|
||||||
reg mux_s_req_rdy;
|
|
||||||
reg mux_s_rsp_vld;
|
|
||||||
|
|
||||||
always @ (*) begin: s_out
|
|
||||||
mux_s_data = 32'h0;
|
|
||||||
mux_s_req_rdy = 1'b0;
|
|
||||||
mux_s_rsp_vld = 1'b0;
|
|
||||||
for (j = 0; j < SLAVE_NUM; j = j + 1) begin: s_sig_out
|
|
||||||
mux_s_data = mux_s_data | ({32{slave_sel[j]}} & slave_data[j]);
|
|
||||||
mux_s_req_rdy = mux_s_req_rdy | ({1 {slave_sel[j]}} & slave_req_rdy[j]);
|
|
||||||
mux_s_rsp_vld = mux_s_rsp_vld | ({1 {slave_sel[j]}} & slave_rsp_vld[j]);
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
/////////////////////////////// demux master //////////////////////////////
|
|
||||||
|
|
||||||
wire[MASTER_NUM-1:0] demux_m_req_rdy;
|
|
||||||
wire[MASTER_NUM-1:0] demux_m_rsp_vld;
|
|
||||||
wire[32*MASTER_NUM-1:0] demux_m_data;
|
|
||||||
|
|
||||||
for (i = 0; i < MASTER_NUM; i = i + 1) begin: demux_m_sig
|
|
||||||
assign demux_m_req_rdy[i] = {1 {master_sel_vec[i]}} & mux_s_req_rdy;
|
|
||||||
assign demux_m_rsp_vld[i] = {1 {master_sel_vec[i]}} & mux_s_rsp_vld;
|
|
||||||
assign demux_m_data[(i+1)*32-1:32*i] = {32{master_sel_vec[i]}} & mux_s_data;
|
|
||||||
end
|
|
||||||
|
|
||||||
if (MASTER_NUM == 2) begin: demux_m_sig_2
|
|
||||||
assign {m0_req_rdy_o, m1_req_rdy_o} = demux_m_req_rdy;
|
|
||||||
assign {m0_rsp_vld_o, m1_rsp_vld_o} = demux_m_rsp_vld;
|
|
||||||
assign {m0_data_o, m1_data_o} = demux_m_data;
|
|
||||||
end
|
|
||||||
|
|
||||||
if (MASTER_NUM == 3) begin: demux_m_sig_3
|
|
||||||
assign {m0_req_rdy_o, m1_req_rdy_o, m2_req_rdy_o} = demux_m_req_rdy;
|
|
||||||
assign {m0_rsp_vld_o, m1_rsp_vld_o, m2_rsp_vld_o} = demux_m_rsp_vld;
|
|
||||||
assign {m0_data_o, m1_data_o, m2_data_o} = demux_m_data;
|
|
||||||
end
|
|
||||||
|
|
||||||
if (MASTER_NUM == 4) begin: demux_m_sig_4
|
|
||||||
assign {m0_req_rdy_o, m1_req_rdy_o, m2_req_rdy_o, m3_req_rdy_o} = demux_m_req_rdy;
|
|
||||||
assign {m0_rsp_vld_o, m1_rsp_vld_o, m2_rsp_vld_o, m3_rsp_vld_o} = demux_m_rsp_vld;
|
|
||||||
assign {m0_data_o, m1_data_o, m2_data_o, m3_data_o} = demux_m_data;
|
|
||||||
end
|
|
||||||
|
|
||||||
/////////////////////////////// demux slave //////////////////////////////
|
|
||||||
|
|
||||||
wire[32*SLAVE_NUM-1:0] demux_s_addr;
|
|
||||||
wire[32*SLAVE_NUM-1:0] demux_s_data;
|
|
||||||
wire[4*SLAVE_NUM-1:0] demux_s_sel;
|
|
||||||
wire[SLAVE_NUM-1:0] demux_s_req_vld;
|
|
||||||
wire[SLAVE_NUM-1:0] demux_s_rsp_rdy;
|
|
||||||
wire[SLAVE_NUM-1:0] demux_s_we;
|
|
||||||
|
|
||||||
for (i = 0; i < SLAVE_NUM; i = i + 1) begin: demux_s_sig
|
|
||||||
// 去掉外设基地址,只保留offset
|
|
||||||
assign demux_s_addr[(i+1)*32-1:32*i] = {32{slave_sel[i]}} & {4'h0, mux_m_addr[27:0]};
|
|
||||||
assign demux_s_data[(i+1)*32-1:32*i] = {32{slave_sel[i]}} & mux_m_data;
|
|
||||||
assign demux_s_sel[(i+1)*4-1:4*i] = {4 {slave_sel[i]}} & mux_m_sel;
|
|
||||||
assign demux_s_req_vld[i] = {1 {slave_sel[i]}} & mux_m_req_vld;
|
|
||||||
assign demux_s_rsp_rdy[i] = {1 {slave_sel[i]}} & mux_m_rsp_rdy;
|
|
||||||
assign demux_s_we[i] = {1 {slave_sel[i]}} & mux_m_we;
|
|
||||||
end
|
|
||||||
|
|
||||||
if (SLAVE_NUM == 2) begin: demux_s_sig_2
|
|
||||||
assign {s1_addr_o, s0_addr_o} = demux_s_addr;
|
|
||||||
assign {s1_data_o, s0_data_o} = demux_s_data;
|
|
||||||
assign {s1_sel_o, s0_sel_o} = demux_s_sel;
|
|
||||||
assign {s1_req_vld_o, s0_req_vld_o} = demux_s_req_vld;
|
|
||||||
assign {s1_rsp_rdy_o, s0_rsp_rdy_o} = demux_s_rsp_rdy;
|
|
||||||
assign {s1_we_o, s0_we_o} = demux_s_we;
|
|
||||||
end
|
|
||||||
|
|
||||||
if (SLAVE_NUM == 3) begin: demux_s_sig_3
|
|
||||||
assign {s2_addr_o, s1_addr_o, s0_addr_o} = demux_s_addr;
|
|
||||||
assign {s2_data_o, s1_data_o, s0_data_o} = demux_s_data;
|
|
||||||
assign {s2_sel_o, s1_sel_o, s0_sel_o} = demux_s_sel;
|
|
||||||
assign {s2_req_vld_o, s1_req_vld_o, s0_req_vld_o} = demux_s_req_vld;
|
|
||||||
assign {s2_rsp_rdy_o, s1_rsp_rdy_o, s0_rsp_rdy_o} = demux_s_rsp_rdy;
|
|
||||||
assign {s2_we_o, s1_we_o, s0_we_o} = demux_s_we;
|
|
||||||
end
|
|
||||||
|
|
||||||
if (SLAVE_NUM == 4) begin: demux_s_sig_4
|
|
||||||
assign {s3_addr_o, s2_addr_o, s1_addr_o, s0_addr_o} = demux_s_addr;
|
|
||||||
assign {s3_data_o, s2_data_o, s1_data_o, s0_data_o} = demux_s_data;
|
|
||||||
assign {s3_sel_o, s2_sel_o, s1_sel_o, s0_sel_o} = demux_s_sel;
|
|
||||||
assign {s3_req_vld_o, s2_req_vld_o, s1_req_vld_o, s0_req_vld_o} = demux_s_req_vld;
|
|
||||||
assign {s3_rsp_rdy_o, s2_rsp_rdy_o, s1_rsp_rdy_o, s0_rsp_rdy_o} = demux_s_rsp_rdy;
|
|
||||||
assign {s3_we_o, s2_we_o, s1_we_o, s0_we_o} = demux_s_we;
|
|
||||||
end
|
|
||||||
|
|
||||||
if (SLAVE_NUM == 5) begin: demux_s_sig_5
|
|
||||||
assign {s4_addr_o, s3_addr_o, s2_addr_o, s1_addr_o, s0_addr_o} = demux_s_addr;
|
|
||||||
assign {s4_data_o, s3_data_o, s2_data_o, s1_data_o, s0_data_o} = demux_s_data;
|
|
||||||
assign {s4_sel_o, s3_sel_o, s2_sel_o, s1_sel_o, s0_sel_o} = demux_s_sel;
|
|
||||||
assign {s4_req_vld_o, s3_req_vld_o, s2_req_vld_o, s1_req_vld_o, s0_req_vld_o} = demux_s_req_vld;
|
|
||||||
assign {s4_rsp_rdy_o, s3_rsp_rdy_o, s2_rsp_rdy_o, s1_rsp_rdy_o, s0_rsp_rdy_o} = demux_s_rsp_rdy;
|
|
||||||
assign {s4_we_o, s3_we_o, s2_we_o, s1_we_o, s0_we_o} = demux_s_we;
|
|
||||||
end
|
|
||||||
|
|
||||||
endgenerate
|
|
||||||
|
|
||||||
|
|
||||||
endmodule
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
`include "../core/defines.sv"
|
`include "../core/defines.sv"
|
||||||
|
`include "../debug/jtag_def.sv"
|
||||||
|
|
||||||
// tinyriscv soc顶层模块
|
// tinyriscv soc顶层模块
|
||||||
module tinyriscv_soc_top(
|
module tinyriscv_soc_top(
|
||||||
|
@ -38,14 +39,18 @@ module tinyriscv_soc_top(
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
localparam int MASTERS = 2; //Number of master ports
|
localparam int MASTERS = 3; // Number of master ports
|
||||||
localparam int SLAVES = 2; //Number of slave ports
|
localparam int SLAVES = 3; // Number of slave ports
|
||||||
|
|
||||||
|
// masters
|
||||||
localparam int CoreD = 0;
|
localparam int CoreD = 0;
|
||||||
localparam int CoreI = 1;
|
localparam int JtagHost = 1;
|
||||||
|
localparam int CoreI = 2;
|
||||||
|
|
||||||
|
// slaves
|
||||||
localparam int Rom = 0;
|
localparam int Rom = 0;
|
||||||
localparam int Ram = 1;
|
localparam int Ram = 1;
|
||||||
|
localparam int JtagDevice = 2;
|
||||||
|
|
||||||
|
|
||||||
wire master_req [MASTERS];
|
wire master_req [MASTERS];
|
||||||
|
@ -80,12 +85,12 @@ module tinyriscv_soc_top(
|
||||||
|
|
||||||
wire ndmreset;
|
wire ndmreset;
|
||||||
wire ndmreset_n;
|
wire ndmreset_n;
|
||||||
|
wire debug_req;
|
||||||
|
|
||||||
assign ndmreset = 1'b0;
|
|
||||||
|
|
||||||
tinyriscv_core #(
|
tinyriscv_core #(
|
||||||
.DEBUG_HALT_ADDR(`DEBUG_ADDR_BASE + 16'h800),
|
.DEBUG_HALT_ADDR(`DEBUG_ADDR_BASE + `HaltAddress),
|
||||||
.DEBUG_EXCEPTION_ADDR(`DEBUG_ADDR_BASE + 16'h808)
|
.DEBUG_EXCEPTION_ADDR(`DEBUG_ADDR_BASE + `ExceptionAddress)
|
||||||
) u_tinyriscv_core (
|
) u_tinyriscv_core (
|
||||||
.clk(clk),
|
.clk(clk),
|
||||||
.rst_n(ndmreset_n),
|
.rst_n(ndmreset_n),
|
||||||
|
@ -111,9 +116,8 @@ module tinyriscv_soc_top(
|
||||||
.irq_timer_i(1'b0),
|
.irq_timer_i(1'b0),
|
||||||
.irq_external_i(1'b0),
|
.irq_external_i(1'b0),
|
||||||
.irq_fast_i(15'b0),
|
.irq_fast_i(15'b0),
|
||||||
.irq_nm_i(1'b0),
|
|
||||||
|
|
||||||
.debug_req_i(1'b0)
|
.debug_req_i(debug_req)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
@ -182,7 +186,37 @@ module tinyriscv_soc_top(
|
||||||
.rst_no(ndmreset_n)
|
.rst_no(ndmreset_n)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
assign slave_addr_mask[JtagDevice] = `DEBUG_ADDR_MASK;
|
||||||
|
assign slave_addr_base[JtagDevice] = `DEBUG_ADDR_BASE;
|
||||||
|
// JTAG module
|
||||||
|
jtag_top #(
|
||||||
|
|
||||||
|
) u_jtag_top (
|
||||||
|
.clk_i (clk),
|
||||||
|
.rst_ni (rst_ext_ni),
|
||||||
|
.debug_req_o (debug_req),
|
||||||
|
.ndmreset_o (ndmreset),
|
||||||
|
.jtag_tck_i (sim_jtag_tck),
|
||||||
|
.jtag_tdi_i (sim_jtag_tdi),
|
||||||
|
.jtag_tms_i (sim_jtag_tms),
|
||||||
|
.jtag_trst_ni (sim_jtag_trstn),
|
||||||
|
.jtag_tdo_o (sim_jtag_tdo),
|
||||||
|
.master_req_o (master_req[JtagHost]),
|
||||||
|
.master_gnt_i (master_gnt[JtagHost]),
|
||||||
|
.master_rvalid_i (master_rvalid[JtagHost]),
|
||||||
|
.master_we_o (master_we[JtagHost]),
|
||||||
|
.master_be_o (master_be[JtagHost]),
|
||||||
|
.master_addr_o (master_addr[JtagHost]),
|
||||||
|
.master_wdata_o (master_wdata[JtagHost]),
|
||||||
|
.master_rdata_i (master_rdata[JtagHost]),
|
||||||
|
.master_err_i (1'b0),
|
||||||
|
.slave_req_i (slave_req[JtagDevice]),
|
||||||
|
.slave_we_i (slave_we[JtagDevice]),
|
||||||
|
.slave_addr_i (slave_addr[JtagDevice]),
|
||||||
|
.slave_be_i (slave_be[JtagDevice]),
|
||||||
|
.slave_wdata_i (slave_wdata[JtagDevice]),
|
||||||
|
.slave_rdata_o (slave_rdata[JtagDevice])
|
||||||
|
);
|
||||||
|
|
||||||
`ifdef VERILATOR
|
`ifdef VERILATOR
|
||||||
sim_jtag #(
|
sim_jtag #(
|
||||||
|
@ -191,7 +225,7 @@ module tinyriscv_soc_top(
|
||||||
) u_sim_jtag (
|
) u_sim_jtag (
|
||||||
.clock ( clk ),
|
.clock ( clk ),
|
||||||
.reset ( ~rst_ext_ni ),
|
.reset ( ~rst_ext_ni ),
|
||||||
.enable ( 1'b0 ),
|
.enable ( 1'b1 ),
|
||||||
.init_done ( rst_ext_ni ),
|
.init_done ( rst_ext_ni ),
|
||||||
.jtag_TCK ( sim_jtag_tck ),
|
.jtag_TCK ( sim_jtag_tck ),
|
||||||
.jtag_TMS ( sim_jtag_tms ),
|
.jtag_TMS ( sim_jtag_tms ),
|
||||||
|
|
|
@ -0,0 +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 */
|
|
@ -1,128 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// 数据接收端模块
|
|
||||||
// 跨时钟域传输,全(四次)握手协议
|
|
||||||
// req = 1
|
|
||||||
// ack_o = 1
|
|
||||||
// req = 0
|
|
||||||
// ack_o = 0
|
|
||||||
module full_handshake_rx #(
|
|
||||||
parameter DW = 32)( // RX要接收数据的位宽
|
|
||||||
|
|
||||||
input wire clk, // RX端时钟信号
|
|
||||||
input wire rst_n, // RX端复位信号
|
|
||||||
|
|
||||||
// from tx
|
|
||||||
input wire req_i, // TX端请求信号
|
|
||||||
input wire[DW-1:0] req_data_i, // TX端输入数据
|
|
||||||
|
|
||||||
// to tx
|
|
||||||
output wire ack_o, // RX端应答TX端信号
|
|
||||||
|
|
||||||
// to rx
|
|
||||||
output wire[DW-1:0] recv_data_o,// RX端接收到的数据
|
|
||||||
output wire recv_rdy_o // RX端是否接收到数据信号
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
localparam STATE_IDLE = 2'b01;
|
|
||||||
localparam STATE_DEASSERT = 2'b10;
|
|
||||||
|
|
||||||
reg[1:0] state;
|
|
||||||
reg[1:0] state_next;
|
|
||||||
|
|
||||||
always @ (posedge clk or negedge rst_n) begin
|
|
||||||
if (!rst_n) begin
|
|
||||||
state <= STATE_IDLE;
|
|
||||||
end else begin
|
|
||||||
state <= state_next;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
always @ (*) begin
|
|
||||||
case (state)
|
|
||||||
// 等待TX请求信号req=1
|
|
||||||
STATE_IDLE: begin
|
|
||||||
if (req == 1'b1) begin
|
|
||||||
state_next = STATE_DEASSERT;
|
|
||||||
end else begin
|
|
||||||
state_next = STATE_IDLE;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
// 等待req=0
|
|
||||||
STATE_DEASSERT: begin
|
|
||||||
if (req) begin
|
|
||||||
state_next = STATE_DEASSERT;
|
|
||||||
end else begin
|
|
||||||
state_next = STATE_IDLE;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
default: begin
|
|
||||||
state_next = STATE_IDLE;
|
|
||||||
end
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
|
|
||||||
reg req_d;
|
|
||||||
reg req;
|
|
||||||
|
|
||||||
// 将请求信号打两拍进行同步
|
|
||||||
always @ (posedge clk or negedge rst_n) begin
|
|
||||||
if (!rst_n) begin
|
|
||||||
req_d <= 1'b0;
|
|
||||||
req <= 1'b0;
|
|
||||||
end else begin
|
|
||||||
req_d <= req_i;
|
|
||||||
req <= req_d;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
reg[DW-1:0] recv_data;
|
|
||||||
reg recv_rdy;
|
|
||||||
reg ack;
|
|
||||||
|
|
||||||
always @ (posedge clk or negedge rst_n) begin
|
|
||||||
if (!rst_n) begin
|
|
||||||
ack <= 1'b0;
|
|
||||||
recv_rdy <= 1'b0;
|
|
||||||
recv_data <= {(DW){1'b0}};
|
|
||||||
end else begin
|
|
||||||
case (state)
|
|
||||||
STATE_IDLE: begin
|
|
||||||
if (req == 1'b1) begin
|
|
||||||
ack <= 1'b1;
|
|
||||||
recv_rdy <= 1'b1; // 这个信号只会持续一个时钟
|
|
||||||
recv_data <= req_data_i; // 这个信号只会持续一个时钟
|
|
||||||
end
|
|
||||||
end
|
|
||||||
STATE_DEASSERT: begin
|
|
||||||
recv_rdy <= 1'b0;
|
|
||||||
recv_data <= {(DW){1'b0}};
|
|
||||||
// req撤销后ack也撤销
|
|
||||||
if (req == 1'b0) begin
|
|
||||||
ack <= 1'b0;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
assign ack_o = ack;
|
|
||||||
assign recv_rdy_o = recv_rdy;
|
|
||||||
assign recv_data_o = recv_data;
|
|
||||||
|
|
||||||
endmodule
|
|
|
@ -1,147 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// 数据发送端模块
|
|
||||||
// 跨时钟域传输,全(四次)握手协议
|
|
||||||
// req_o = 1
|
|
||||||
// ack = 1
|
|
||||||
// req_o = 0
|
|
||||||
// ack = 0
|
|
||||||
module full_handshake_tx #(
|
|
||||||
parameter DW = 32)( // TX要发送数据的位宽
|
|
||||||
|
|
||||||
input wire clk, // TX端时钟信号
|
|
||||||
input wire rst_n, // TX端复位信号
|
|
||||||
|
|
||||||
// from rx
|
|
||||||
input wire ack_i, // RX端应答信号
|
|
||||||
|
|
||||||
// from tx
|
|
||||||
input wire req_i, // TX端请求信号,只需持续一个时钟
|
|
||||||
input wire[DW-1:0] req_data_i, // TX端要发送的数据,只需持续一个时钟
|
|
||||||
|
|
||||||
// to tx
|
|
||||||
output wire idle_o, // TX端是否空闲信号,空闲才能发数据
|
|
||||||
|
|
||||||
// to rx
|
|
||||||
output wire req_o, // TX端请求信号
|
|
||||||
output wire[DW-1:0] req_data_o // TX端要发送的数据
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
localparam STATE_IDLE = 3'b001;
|
|
||||||
localparam STATE_ASSERT = 3'b010;
|
|
||||||
localparam STATE_DEASSERT = 3'b100;
|
|
||||||
|
|
||||||
reg[2:0] state;
|
|
||||||
reg[2:0] state_next;
|
|
||||||
|
|
||||||
always @ (posedge clk or negedge rst_n) begin
|
|
||||||
if (!rst_n) begin
|
|
||||||
state <= STATE_IDLE;
|
|
||||||
end else begin
|
|
||||||
state <= state_next;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
always @ (*) begin
|
|
||||||
case (state)
|
|
||||||
STATE_IDLE: begin
|
|
||||||
if (req_i == 1'b1) begin
|
|
||||||
state_next = STATE_ASSERT;
|
|
||||||
end else begin
|
|
||||||
state_next = STATE_IDLE;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
// 等待ack=1
|
|
||||||
STATE_ASSERT: begin
|
|
||||||
if (!ack) begin
|
|
||||||
state_next = STATE_ASSERT;
|
|
||||||
end else begin
|
|
||||||
state_next = STATE_DEASSERT;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
// 等待ack=0
|
|
||||||
STATE_DEASSERT: begin
|
|
||||||
if (!ack) begin
|
|
||||||
state_next = STATE_IDLE;
|
|
||||||
end else begin
|
|
||||||
state_next = STATE_DEASSERT;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
default: begin
|
|
||||||
state_next = STATE_IDLE;
|
|
||||||
end
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
|
|
||||||
reg ack_d;
|
|
||||||
reg ack;
|
|
||||||
|
|
||||||
// 将应答信号打两拍进行同步
|
|
||||||
always @ (posedge clk or negedge rst_n) begin
|
|
||||||
if (!rst_n) begin
|
|
||||||
ack_d <= 1'b0;
|
|
||||||
ack <= 1'b0;
|
|
||||||
end else begin
|
|
||||||
ack_d <= ack_i;
|
|
||||||
ack <= ack_d;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
reg req;
|
|
||||||
reg[DW-1:0] req_data;
|
|
||||||
reg idle;
|
|
||||||
|
|
||||||
always @ (posedge clk or negedge rst_n) begin
|
|
||||||
if (!rst_n) begin
|
|
||||||
idle <= 1'b1;
|
|
||||||
req <= 1'b0;
|
|
||||||
req_data <= {(DW){1'b0}};
|
|
||||||
end else begin
|
|
||||||
case (state)
|
|
||||||
// 锁存TX请求数据,在收到ack之前一直保持有效
|
|
||||||
STATE_IDLE: begin
|
|
||||||
if (req_i == 1'b1) begin
|
|
||||||
idle <= 1'b0;
|
|
||||||
req <= req_i;
|
|
||||||
req_data <= req_data_i;
|
|
||||||
end else begin
|
|
||||||
idle <= 1'b1;
|
|
||||||
req <= 1'b0;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
// 收到RX的ack之后撤销TX请求
|
|
||||||
STATE_ASSERT: begin
|
|
||||||
if (ack == 1'b1) begin
|
|
||||||
req <= 1'b0;
|
|
||||||
req_data <= {(DW){1'b0}};
|
|
||||||
end
|
|
||||||
end
|
|
||||||
STATE_DEASSERT: begin
|
|
||||||
if (!ack) begin
|
|
||||||
idle <= 1'b1;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
assign idle_o = idle;
|
|
||||||
assign req_o = req;
|
|
||||||
assign req_data_o = req_data;
|
|
||||||
|
|
||||||
endmodule
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
debug_level 2
|
||||||
|
adapter_khz 10000
|
||||||
|
|
||||||
|
interface remote_bitbang
|
||||||
|
remote_bitbang_host localhost
|
||||||
|
|
||||||
|
remote_bitbang_port 9999
|
||||||
|
|
||||||
|
set _CHIPNAME riscv
|
||||||
|
jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x1e200a6f
|
||||||
|
|
||||||
|
foreach t [jtag names] {
|
||||||
|
puts [format "TAP: %s\n" $t]
|
||||||
|
}
|
||||||
|
|
||||||
|
set _TARGETNAME $_CHIPNAME.cpu
|
||||||
|
target create $_TARGETNAME riscv -chain-position $_TARGETNAME
|
||||||
|
|
||||||
|
riscv set_reset_timeout_sec 2000
|
||||||
|
riscv set_command_timeout_sec 2000
|
||||||
|
|
||||||
|
# prefer to use sba for system bus access
|
||||||
|
riscv set_prefer_sba on
|
||||||
|
|
||||||
|
# dump jtag chain
|
||||||
|
scan_chain
|
||||||
|
|
||||||
|
init
|
||||||
|
riscv test_compliance
|
||||||
|
shutdown
|
|
@ -0,0 +1,31 @@
|
||||||
|
debug_level 2
|
||||||
|
adapter_khz 10000
|
||||||
|
|
||||||
|
interface remote_bitbang
|
||||||
|
remote_bitbang_host localhost
|
||||||
|
|
||||||
|
remote_bitbang_port 9999
|
||||||
|
|
||||||
|
set _CHIPNAME riscv
|
||||||
|
jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x1e200a6f
|
||||||
|
|
||||||
|
foreach t [jtag names] {
|
||||||
|
puts [format "TAP: %s\n" $t]
|
||||||
|
}
|
||||||
|
|
||||||
|
set _TARGETNAME $_CHIPNAME.cpu
|
||||||
|
target create $_TARGETNAME riscv -chain-position $_TARGETNAME
|
||||||
|
|
||||||
|
riscv set_reset_timeout_sec 2000
|
||||||
|
riscv set_command_timeout_sec 2000
|
||||||
|
|
||||||
|
# prefer to use sba for system bus access
|
||||||
|
riscv set_prefer_sba on
|
||||||
|
|
||||||
|
# dump jtag chain
|
||||||
|
scan_chain
|
||||||
|
|
||||||
|
init
|
||||||
|
|
||||||
|
halt
|
||||||
|
echo "Ready for Remote Connections"
|
|
@ -34,7 +34,7 @@ module tb_top_verilator #(
|
||||||
$display("No firmware specified");
|
$display("No firmware specified");
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
/*
|
||||||
always @(posedge clk_i or negedge rst_ni) begin
|
always @(posedge clk_i or negedge rst_ni) begin
|
||||||
if (!rst_ni) begin
|
if (!rst_ni) begin
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ module tb_top_verilator #(
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
*/
|
||||||
tinyriscv_soc_top u_tinyriscv_soc_top(
|
tinyriscv_soc_top u_tinyriscv_soc_top(
|
||||||
.clk(clk_i),
|
.clk(clk_i),
|
||||||
.rst_ext_ni(rst_ni)
|
.rst_ext_ni(rst_ni)
|
||||||
|
|
Loading…
Reference in New Issue