parent
462cc4c786
commit
ec65381ba9
19
rtl.flist
19
rtl.flist
|
@ -1,11 +1,11 @@
|
|||
|
||||
+incdir+../rtl/core
|
||||
+incdir+../rtl/debug
|
||||
|
||||
../rtl/core/clint.sv
|
||||
../rtl/core/csr_reg.sv
|
||||
../rtl/core/csr.sv
|
||||
../rtl/core/defines.sv
|
||||
../rtl/core/divider.sv
|
||||
../rtl/core/exception.sv
|
||||
../rtl/core/exu.sv
|
||||
../rtl/core/exu_alu_datapath.sv
|
||||
../rtl/core/exu_commit.sv
|
||||
|
@ -22,9 +22,15 @@
|
|||
../rtl/core/tinyriscv_core.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_driver.sv
|
||||
../rtl/debug/jtag_mem.sv
|
||||
../rtl/debug/jtag_sba.sv
|
||||
../rtl/debug/jtag_top.sv
|
||||
../rtl/debug/debug_rom.sv
|
||||
|
||||
../rtl/perips/gpio.sv
|
||||
../rtl/perips/ram.sv
|
||||
|
@ -32,18 +38,13 @@
|
|||
../rtl/perips/timer.sv
|
||||
../rtl/perips/uart.sv
|
||||
|
||||
../rtl/sys_bus/rib.sv
|
||||
../rtl/sys_bus/obi_interconnect.sv
|
||||
../rtl/sys_bus/obi_interconnect_master_sel.sv
|
||||
../rtl/sys_bus/obi_interconnect_slave_sel.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_dff.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] 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;
|
||||
wire[31:0] mhartid_q;
|
||||
reg mhartid_we;
|
||||
reg[31:0] dpc_d;
|
||||
wire[31:0] dpc_q;
|
||||
reg dpc_we;
|
||||
|
||||
reg[63:0] cycle;
|
||||
|
||||
|
@ -83,6 +88,8 @@ module csr_reg(
|
|||
assign mtvec_o = mtvec_q;
|
||||
assign mepc_o = mepc_q;
|
||||
assign mstatus_o = mstatus_q;
|
||||
assign mie_o = mie_q;
|
||||
assign dpc_o = dpc_q;
|
||||
|
||||
reg[31:0] exu_rdata;
|
||||
|
||||
|
@ -122,6 +129,9 @@ module csr_reg(
|
|||
`CSR_MHARTID: begin
|
||||
exu_rdata = mhartid_q;
|
||||
end
|
||||
`CSR_DPC: begin
|
||||
exu_rdata = dpc_q;
|
||||
end
|
||||
default: begin
|
||||
exu_rdata = 32'h0;
|
||||
end
|
||||
|
@ -154,6 +164,8 @@ module csr_reg(
|
|||
dscratch1_we = 1'b0;
|
||||
mhartid_d = mhartid_q;
|
||||
mhartid_we = 1'b0;
|
||||
dpc_d = dpc_q;
|
||||
dpc_we = 1'b0;
|
||||
|
||||
if (we) begin
|
||||
case (waddr[11:0])
|
||||
|
@ -193,6 +205,10 @@ module csr_reg(
|
|||
mhartid_d = wdata;
|
||||
mhartid_we = 1'b1;
|
||||
end
|
||||
`CSR_DPC: begin
|
||||
dpc_d = wdata;
|
||||
dpc_we = 1'b1;
|
||||
end
|
||||
default:;
|
||||
endcase
|
||||
end
|
||||
|
@ -297,4 +313,15 @@ module csr_reg(
|
|||
.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
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
`define INST_MRET 32'h30200073
|
||||
`define INST_ECALL 32'h00000073
|
||||
`define INST_EBREAK 32'h00100073
|
||||
`define INST_DRET 32'h7b200073
|
||||
|
||||
// 指令译码信息
|
||||
`define DECINFO_GRP_BUS 2:0
|
||||
|
@ -118,12 +119,13 @@
|
|||
`define DECINFO_MEM_SH (`DECINFO_GRP_WIDTH+6)
|
||||
`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_EBREAK (`DECINFO_GRP_WIDTH+1)
|
||||
`define DECINFO_SYS_NOP (`DECINFO_GRP_WIDTH+2)
|
||||
`define DECINFO_SYS_MRET (`DECINFO_GRP_WIDTH+3)
|
||||
`define DECINFO_SYS_FENCE (`DECINFO_GRP_WIDTH+4)
|
||||
`define DECINFO_SYS_DRET (`DECINFO_GRP_WIDTH+5)
|
||||
|
||||
// 最长的那组
|
||||
`define DECINFO_WIDTH `DECINFO_CSR_BUS_WIDTH
|
||||
|
@ -137,6 +139,8 @@
|
|||
`define CSR_MIE 12'h304
|
||||
`define CSR_MSTATUS 12'h300
|
||||
`define CSR_MSCRATCH 12'h340
|
||||
`define CSR_MHARTID 12'hF14
|
||||
`define CSR_DCSR 12'h7b0
|
||||
`define CSR_DPC 12'h7b1
|
||||
`define CSR_DSCRATCH0 12'h7b2
|
||||
`define CSR_DSCRATCH1 12'h7b3
|
||||
`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_ebreak_o, // ebreak指令
|
||||
output wire inst_mret_o, // mret指令
|
||||
output wire inst_dret_o, // dret指令
|
||||
|
||||
// mem
|
||||
input wire[31:0] mem_rdata_i, // 内存输入数据
|
||||
|
@ -143,6 +144,7 @@ module exu(
|
|||
wire sys_op_ecall_o;
|
||||
wire sys_op_ebreak_o;
|
||||
wire sys_op_fence_o;
|
||||
wire sys_op_dret_o;
|
||||
|
||||
exu_dispatch u_exu_dispatch(
|
||||
// input
|
||||
|
@ -219,12 +221,14 @@ module exu(
|
|||
.sys_op_mret_o(sys_op_mret_o),
|
||||
.sys_op_ecall_o(sys_op_ecall_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_ebreak_o = sys_op_ebreak_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] bjp_res_o;
|
||||
|
|
|
@ -99,7 +99,8 @@ module exu_dispatch(
|
|||
output wire sys_op_mret_o,
|
||||
output wire sys_op_ecall_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_ebreak_o = sys_info[`DECINFO_SYS_EBREAK];
|
||||
assign sys_op_fence_o = sys_info[`DECINFO_SYS_FENCE];
|
||||
assign sys_op_dret_o = sys_info[`DECINFO_SYS_DRET];
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -156,6 +156,7 @@ module idu(
|
|||
wire inst_remu = opcode_0110011 & funct3_111 & funct7_0000001;
|
||||
wire inst_nop = (inst_i == `INST_NOP);
|
||||
wire inst_mret = (inst_i == `INST_MRET);
|
||||
wire inst_dret = (inst_i == `INST_DRET);
|
||||
|
||||
// 将指令分类
|
||||
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_NOP] = inst_nop;
|
||||
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;
|
||||
|
||||
// 指令中的立即数
|
||||
|
@ -259,7 +261,7 @@ module idu(
|
|||
wire op_bjp = inst_jal | inst_jalr | inst_type_branch;
|
||||
wire op_muldiv = inst_type_muldiv;
|
||||
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;
|
||||
|
||||
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_external_i,
|
||||
input wire[14:0] irq_fast_i,
|
||||
input wire irq_nm_i,
|
||||
|
||||
// debug req signal
|
||||
input wire debug_req_i
|
||||
|
@ -114,6 +113,7 @@ module tinyriscv_core #(
|
|||
wire ex_inst_ecall_o;
|
||||
wire ex_inst_ebreak_o;
|
||||
wire ex_inst_mret_o;
|
||||
wire ex_inst_dret_o;
|
||||
wire ex_inst_valid_o;
|
||||
|
||||
// gpr_reg模块输出信号
|
||||
|
@ -126,6 +126,8 @@ module tinyriscv_core #(
|
|||
wire[31:0] csr_mtvec_o;
|
||||
wire[31:0] csr_mepc_o;
|
||||
wire[31:0] csr_mstatus_o;
|
||||
wire[31:0] csr_mie_o;
|
||||
wire[31:0] csr_dpc_o;
|
||||
|
||||
// pipe_ctrl模块输出信号
|
||||
wire[31:0] ctrl_flush_addr_o;
|
||||
|
@ -197,7 +199,9 @@ module tinyriscv_core #(
|
|||
.clint_wdata_i(clint_csr_wdata_o),
|
||||
.mtvec_o(csr_mtvec_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(
|
||||
|
@ -283,6 +287,7 @@ module tinyriscv_core #(
|
|||
.inst_ecall_o(ex_inst_ecall_o),
|
||||
.inst_ebreak_o(ex_inst_ebreak_o),
|
||||
.inst_mret_o(ex_inst_mret_o),
|
||||
.inst_dret_o(ex_inst_dret_o),
|
||||
.int_stall_i(clint_stall_flag_o),
|
||||
.csr_raddr_o(ex_csr_raddr_o),
|
||||
.csr_rdata_i(csr_ex_data_o),
|
||||
|
@ -300,19 +305,26 @@ module tinyriscv_core #(
|
|||
.rd_we_i(ie_rd_we_o)
|
||||
);
|
||||
|
||||
clint u_clint(
|
||||
exception u_exception(
|
||||
.clk(clk),
|
||||
.rst_n(rst_n),
|
||||
.int_flag_i(`INT_NONE),
|
||||
.inst_valid_i(ex_inst_valid_o),
|
||||
.inst_ecall_i(ex_inst_ecall_o),
|
||||
.inst_ebreak_i(ex_inst_ebreak_o),
|
||||
.inst_mret_i(ex_inst_mret_o),
|
||||
.inst_dret_i(ex_inst_dret_o),
|
||||
.inst_addr_i(ie_dec_pc_o),
|
||||
.jump_flag_i(ex_jump_flag_o),
|
||||
.mem_access_misaligned_i(ex_mem_access_misaligned_o),
|
||||
.csr_mtvec_i(csr_mtvec_o),
|
||||
.csr_mepc_i(csr_mepc_o),
|
||||
.csr_mstatus_i(csr_mstatus_o),
|
||||
.mtvec_i(csr_mtvec_o),
|
||||
.mepc_i(csr_mepc_o),
|
||||
.mstatus_i(csr_mstatus_o),
|
||||
.mie_i(csr_mie_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_waddr_o(clint_csr_waddr_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
|
||||
|
|
@ -1,381 +1,370 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
`define DTM_OP_NOP 2'b00
|
||||
`define DTM_OP_READ 2'b01
|
||||
`define DTM_OP_WRITE 2'b10
|
||||
|
||||
|
||||
module jtag_dm #(
|
||||
parameter DMI_ADDR_BITS = 6,
|
||||
parameter DMI_DATA_BITS = 32,
|
||||
parameter DMI_OP_BITS = 2)(
|
||||
|
||||
clk,
|
||||
rst_n,
|
||||
|
||||
// rx
|
||||
dm_ack_o,
|
||||
dtm_req_valid_i,
|
||||
dtm_req_data_i,
|
||||
|
||||
// tx
|
||||
dtm_ack_i,
|
||||
dm_resp_data_o,
|
||||
dm_resp_valid_o,
|
||||
|
||||
dm_reg_we_o,
|
||||
dm_reg_addr_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,
|
||||
req_ready_i,
|
||||
rsp_valid_i,
|
||||
rsp_ready_o,
|
||||
|
||||
dm_halt_req_o,
|
||||
dm_reset_req_o
|
||||
|
||||
);
|
||||
|
||||
parameter DM_RESP_BITS = DMI_ADDR_BITS + DMI_DATA_BITS + DMI_OP_BITS;
|
||||
parameter DTM_REQ_BITS = DMI_ADDR_BITS + DMI_DATA_BITS + DMI_OP_BITS;
|
||||
parameter SHIFT_REG_BITS = DTM_REQ_BITS;
|
||||
|
||||
// 输入输出信号
|
||||
input wire clk;
|
||||
input wire rst_n;
|
||||
output wire dm_ack_o;
|
||||
input wire dtm_req_valid_i;
|
||||
input wire[DTM_REQ_BITS-1:0] dtm_req_data_i;
|
||||
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[31:0] dcsr;
|
||||
reg[31:0] dmstatus;
|
||||
reg[31:0] dmcontrol;
|
||||
reg[31:0] hartinfo;
|
||||
reg[31:0] abstractcs;
|
||||
reg[31:0] data0;
|
||||
reg[31:0] sbcs;
|
||||
reg[31:0] sbaddress0;
|
||||
reg[31:0] sbdata0;
|
||||
reg[31:0] command;
|
||||
|
||||
// DM模块寄存器地址
|
||||
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;
|
||||
|
||||
localparam STATE_IDLE = 3'b001;
|
||||
localparam STATE_EXE = 3'b010;
|
||||
localparam STATE_END = 3'b100;
|
||||
|
||||
reg[2:0] state;
|
||||
reg[31:0] read_data;
|
||||
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:
|
||||
(sbcs[19:17] == 3'd1)? 4'b0011:
|
||||
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];
|
||||
wire[DMI_DATA_BITS-1:0] data = rx_data_r[DMI_DATA_BITS+DMI_OP_BITS-1:DMI_OP_BITS];
|
||||
wire[DMI_ADDR_BITS-1:0] address = rx_data_r[DTM_REQ_BITS-1:DMI_DATA_BITS+DMI_OP_BITS];
|
||||
|
||||
wire req_sys_bus = ~(address == DMSTATUS);
|
||||
|
||||
always @ (posedge clk or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
dm_mem_we <= 1'b0;
|
||||
dm_reg_we <= 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
|
||||
case (state)
|
||||
STATE_IDLE: begin
|
||||
// 接收到driver的请求
|
||||
if (rx_valid) begin
|
||||
rx_data_r <= rx_data;
|
||||
state <= STATE_EXE;
|
||||
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
|
||||
read_data <= {(DMI_DATA_BITS){1'b0}};
|
||||
case (address)
|
||||
DMCONTROL: begin
|
||||
// reset DM module
|
||||
if (data[0] == 1'b0) begin
|
||||
dcsr <= 32'hc0;
|
||||
dmstatus <= 32'h430c82; // not halted, all running
|
||||
hartinfo <= 32'h0;
|
||||
sbcs <= 32'h20040404;
|
||||
abstractcs <= 32'h1000003;
|
||||
dmcontrol <= data;
|
||||
dm_halt_req <= 1'b0;
|
||||
dm_reset_req <= 1'b0;
|
||||
// DM is active
|
||||
end else begin
|
||||
// we have only one hart
|
||||
dmcontrol <= (data & ~(32'h3fffc0)) | 32'h10000;
|
||||
// halt
|
||||
if (data[31] == 1'b1) begin
|
||||
dm_halt_req <= 1'b1;
|
||||
// clear ALLRUNNING ANYRUNNING and set ALLHALTED
|
||||
dmstatus <= {dmstatus[31:12], 4'h3, dmstatus[7:0]};
|
||||
// reset
|
||||
end else if (data[1] == 1'b1) begin
|
||||
dm_reset_req <= 1'b1;
|
||||
dm_halt_req <= 1'b0;
|
||||
dmstatus <= {dmstatus[31:12], 4'hc, dmstatus[7:0]};
|
||||
// resume
|
||||
end else if (dm_halt_req == 1'b1 && data[30] == 1'b1) begin
|
||||
dm_halt_req <= 1'b0;
|
||||
// set ALLRUNNING ANYRUNNING and clear ALLHALTED
|
||||
dmstatus <= {dmstatus[31:12], 4'hc, dmstatus[7:0]};
|
||||
end
|
||||
end
|
||||
end
|
||||
COMMAND: begin
|
||||
// access reg
|
||||
if (data[31:24] == 8'h0) begin
|
||||
if (data[22:20] > 3'h2) begin
|
||||
abstractcs <= abstractcs | (1'b1 << 9);
|
||||
end else begin
|
||||
abstractcs <= abstractcs & (~(3'h7 << 8));
|
||||
// read or write
|
||||
if (data[18] == 1'b0) begin
|
||||
dm_reg_addr <= data[15:0] - 16'h1000;
|
||||
// read
|
||||
if (data[16] == 1'b0) begin
|
||||
if (data[15:0] == DCSR) begin
|
||||
data0 <= dcsr;
|
||||
end else if (data[15:0] < 16'h1020) begin
|
||||
is_read_reg <= 1'b1;
|
||||
end
|
||||
// write
|
||||
end else begin
|
||||
if (data[15:0] < 16'h1020) begin
|
||||
dm_reg_we <= 1'b1;
|
||||
dm_reg_wdata <= data0;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
DATA0: begin
|
||||
data0 <= data;
|
||||
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
|
||||
endcase
|
||||
end
|
||||
|
||||
`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
|
||||
|
||||
wire jtag_req_hsked = (req_valid_o & req_ready_i);
|
||||
wire jtag_rsp_hsked = (rsp_valid_i & rsp_ready_o);
|
||||
|
||||
assign rsp_ready_o = (~rst_n)? 1'b0: 1'b1;
|
||||
assign dm_mem_sel_o = dm_mem_sel;
|
||||
|
||||
|
||||
assign dm_reg_we_o = dm_reg_we;
|
||||
assign dm_reg_addr_o = dm_reg_addr;
|
||||
assign dm_reg_wdata_o = dm_reg_wdata;
|
||||
assign dm_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 #(
|
||||
.DW(DM_RESP_BITS)
|
||||
) tx(
|
||||
.clk(clk),
|
||||
.rst_n(rst_n),
|
||||
.ack_i(dtm_ack_i),
|
||||
.req_i(need_resp),
|
||||
.req_data_i(dm_resp_data),
|
||||
.idle_o(),
|
||||
.req_o(dm_resp_valid_o),
|
||||
.req_data_o(dm_resp_data_o)
|
||||
);
|
||||
|
||||
full_handshake_rx #(
|
||||
.DW(DTM_REQ_BITS)
|
||||
) rx(
|
||||
.clk(clk),
|
||||
.rst_n(rst_n),
|
||||
.req_i(dtm_req_valid_i),
|
||||
.req_data_i(dtm_req_data_i),
|
||||
.ack_o(dm_ack_o),
|
||||
.recv_data_o(rx_data),
|
||||
.recv_rdy_o(rx_valid)
|
||||
);
|
||||
|
||||
endmodule
|
||||
/*
|
||||
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 "jtag_def.sv"
|
||||
|
||||
module jtag_dm #(
|
||||
parameter DMI_ADDR_BITS = 6,
|
||||
parameter DMI_DATA_BITS = 32,
|
||||
parameter DMI_OP_BITS = 2,
|
||||
localparam DMI_REQ_BITS = DMI_ADDR_BITS + DMI_DATA_BITS + DMI_OP_BITS,
|
||||
localparam DMI_RESP_BITS = DMI_REQ_BITS
|
||||
)(
|
||||
|
||||
input wire clk,
|
||||
input wire rst_n,
|
||||
|
||||
// from DMI
|
||||
input wire [DMI_REQ_BITS-1:0] dmi_data_i,
|
||||
input wire dmi_valid_i,
|
||||
output wire dm_ready_o,
|
||||
|
||||
// to DMI
|
||||
output wire [DMI_RESP_BITS-1:0] dm_data_o,
|
||||
output wire dm_valid_o,
|
||||
input wire dmi_ready_i,
|
||||
|
||||
output wire debug_req_o,
|
||||
output wire ndmreset_o,
|
||||
|
||||
// jtag access mem devices(DM as master)
|
||||
output wire master_req_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,
|
||||
|
||||
// core fetch instr or mem(DM as slave)
|
||||
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
|
||||
|
||||
);
|
||||
|
||||
localparam HARTINFO = {8'h0, 4'h2, 3'b0, 1'b1, `DataCount, `DataAddr};
|
||||
|
||||
wire halted;
|
||||
wire resumeack;
|
||||
wire sbbusy;
|
||||
wire[DMI_OP_BITS-1:0] dm_op;
|
||||
wire[DMI_ADDR_BITS-1:0] dm_op_addr;
|
||||
wire[DMI_DATA_BITS-1:0] dm_op_data;
|
||||
|
||||
reg havereset_d, havereset_q;
|
||||
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] dmcontrol_d, dmcontrol_q;
|
||||
reg[31:0] abstractcs;
|
||||
reg[31:0] sbcs_d, sbcs_q;
|
||||
reg[31:0] sbdata0_d, sbdata0_q;
|
||||
reg[31:0] sbaddress0_d, sbaddress0_q;
|
||||
reg[31:0] command_d, command_q;
|
||||
reg[31:0] data0_d, data0_q;
|
||||
reg[2:0] cmderr_d, cmderr_q;
|
||||
|
||||
assign dm_sbaddress = sbaddress0_q;
|
||||
|
||||
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 S_REQ = 2'b01;
|
||||
localparam S_RESP = 2'b10;
|
||||
|
||||
reg[2:0] req_state_d, req_state_q;
|
||||
reg dm_valid_d, dm_valid_q;
|
||||
|
||||
// response FSM
|
||||
always @ (*) begin
|
||||
req_state_d = req_state_q;
|
||||
dm_valid_d = dm_valid_q;
|
||||
|
||||
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
|
||||
if (!rst_n) begin
|
||||
req_state_q <= S_REQ;
|
||||
dm_valid_q <= 1'b0;
|
||||
end else begin
|
||||
req_state_q <= req_state_d;
|
||||
dm_valid_q <= dm_valid_d;
|
||||
end
|
||||
end
|
||||
|
||||
// we always ready to receive dmi request
|
||||
assign dm_ready_o = 1'b1;
|
||||
assign dm_valid_o = dm_valid_q;
|
||||
assign dm_data_o = {{DMI_ADDR_BITS{1'b0}}, dm_resp_data_q, 2'b00}; // response successfully
|
||||
|
||||
|
||||
// DMI read or write operation
|
||||
always @ (*) begin
|
||||
// dmstatus
|
||||
dmstatus = 32'h0;
|
||||
dmstatus[`Version] = `DbgVersion013;
|
||||
dmstatus[`Authenticated] = 1'b1;
|
||||
dmstatus[`Allresumeack] = resumeack;
|
||||
dmstatus[`Anyresumeack] = resumeack;
|
||||
dmstatus[`Allhavereset] = havereset_q;
|
||||
dmstatus[`Anyhavereset] = havereset_q;
|
||||
dmstatus[`Allhalted] = halted;
|
||||
dmstatus[`Anyhalted] = halted;
|
||||
dmstatus[`Allrunning] = ~halted;
|
||||
dmstatus[`Anyrunning] = ~halted;
|
||||
|
||||
// abstractcs
|
||||
cmderr_d = cmderr_q;
|
||||
abstractcs = 32'h0;
|
||||
abstractcs[`Datacount] = `DataCount;
|
||||
abstractcs[`Progbufsize] = `ProgBufSize;
|
||||
abstractcs[`Busy] = cmdbusy;
|
||||
abstractcs[`Cmderr] = cmderr_q;
|
||||
|
||||
havereset_d = havereset_q;
|
||||
sbaddress0_d = sba_sbaddress;
|
||||
dmcontrol_d = dmcontrol_q;
|
||||
clear_resumeack = 1'b0;
|
||||
sbaddress_write_valid = 1'b0;
|
||||
sbdata_write_valid = 1'b0;
|
||||
|
||||
data0_d = data0_q;
|
||||
sbcs_d = sbcs_q;
|
||||
sbdata0_d = sbdata0_q;
|
||||
dm_resp_data_d = dm_resp_data_q;
|
||||
|
||||
if (dmi_valid_i & dm_ready_o) begin
|
||||
// read
|
||||
if (dm_op == `DMI_OP_READ) begin
|
||||
case (dm_op_addr)
|
||||
`DMStatus: dm_resp_data_d = dmstatus;
|
||||
`DMControl: dm_resp_data_d = dmcontrol_q;
|
||||
`Hartinfo: dm_resp_data_d = HARTINFO;
|
||||
`SBCS: dm_resp_data_d = sbcs_q;
|
||||
`AbstractCS:dm_resp_data_d = abstractcs;
|
||||
default:;
|
||||
endcase
|
||||
|
||||
// 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
|
||||
sbcs_d = dm_op_data;
|
||||
// write 1 to clear
|
||||
sbcs_d[`Sbbusyerror] = sbcs_q[`Sbbusyerror] & (~sbcs_d[`Sbbusyerror]);
|
||||
sbcs_d[`Sberror] = sbcs_q[`Sberror] & (~sbcs_d[`Sberror]);
|
||||
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
|
||||
|
||||
`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
|
||||
|
||||
`AbstractCS: begin
|
||||
|
||||
end
|
||||
|
||||
default:;
|
||||
endcase
|
||||
// nop
|
||||
end else begin
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
// dmcontrol
|
||||
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
|
||||
|
||||
// sbcs
|
||||
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 debug_req_o = dmcontrol_q[`Haltreq];
|
||||
assign ndmreset_o = dmcontrol_q[`Ndmreset];
|
||||
assign resumereq = dmcontrol_q[`Resumereq];
|
||||
|
||||
|
||||
always @ (posedge clk or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
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),
|
||||
.rst_n(rst_n),
|
||||
|
||||
.halted_o(halted),
|
||||
.resumeack_o(resumeack),
|
||||
.clear_resumeack_i(clear_resumeack),
|
||||
.resumereq_i(resumereq),
|
||||
.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)
|
||||
);
|
||||
|
||||
jtag_sba #(
|
||||
|
||||
) u_jtag_sba (
|
||||
.clk(clk),
|
||||
.rst_n(rst_n),
|
||||
.sbbusy_o(sbbusy),
|
||||
.master_req_o(master_req_o),
|
||||
.master_gnt_i(master_gnt_i),
|
||||
.master_rvalid_i(master_rvalid_i),
|
||||
.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
|
||||
|
|
|
@ -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
|
|
@ -1,290 +1,290 @@
|
|||
/*
|
||||
Copyright 2020 Blue Liang, liangkangnan@163.com
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
module jtag_driver #(
|
||||
parameter DMI_ADDR_BITS = 6,
|
||||
parameter DMI_DATA_BITS = 32,
|
||||
parameter DMI_OP_BITS = 2)(
|
||||
|
||||
rst_n,
|
||||
|
||||
jtag_TCK,
|
||||
jtag_TDI,
|
||||
jtag_TMS,
|
||||
jtag_TDO,
|
||||
|
||||
// rx
|
||||
dm_resp_i,
|
||||
dm_resp_data_i,
|
||||
dtm_ack_o,
|
||||
|
||||
// tx
|
||||
dm_ack_i,
|
||||
dtm_req_valid_o,
|
||||
dtm_req_data_o
|
||||
|
||||
);
|
||||
|
||||
parameter IDCODE_VERSION = 4'h1;
|
||||
parameter IDCODE_PART_NUMBER = 16'he200;
|
||||
parameter IDCODE_MANUFLD = 11'h537;
|
||||
|
||||
parameter DTM_VERSION = 4'h1;
|
||||
parameter IR_BITS = 5;
|
||||
|
||||
parameter DM_RESP_BITS = DMI_ADDR_BITS + DMI_DATA_BITS + DMI_OP_BITS;
|
||||
parameter DTM_REQ_BITS = DMI_ADDR_BITS + DMI_DATA_BITS + DMI_OP_BITS;
|
||||
parameter SHIFT_REG_BITS = DTM_REQ_BITS;
|
||||
|
||||
// input and output
|
||||
input wire rst_n;
|
||||
input wire jtag_TCK;
|
||||
input wire jtag_TDI;
|
||||
input wire jtag_TMS;
|
||||
output reg jtag_TDO;
|
||||
input wire dm_resp_i;
|
||||
input wire[DM_RESP_BITS - 1:0] dm_resp_data_i;
|
||||
output wire dtm_ack_o;
|
||||
input wire dm_ack_i;
|
||||
output wire dtm_req_valid_o;
|
||||
output wire[DTM_REQ_BITS - 1:0] dtm_req_data_o;
|
||||
|
||||
// JTAG StateMachine
|
||||
parameter TEST_LOGIC_RESET = 4'h0;
|
||||
parameter RUN_TEST_IDLE = 4'h1;
|
||||
parameter SELECT_DR = 4'h2;
|
||||
parameter CAPTURE_DR = 4'h3;
|
||||
parameter SHIFT_DR = 4'h4;
|
||||
parameter EXIT1_DR = 4'h5;
|
||||
parameter PAUSE_DR = 4'h6;
|
||||
parameter EXIT2_DR = 4'h7;
|
||||
parameter UPDATE_DR = 4'h8;
|
||||
parameter SELECT_IR = 4'h9;
|
||||
parameter CAPTURE_IR = 4'hA;
|
||||
parameter SHIFT_IR = 4'hB;
|
||||
parameter EXIT1_IR = 4'hC;
|
||||
parameter PAUSE_IR = 4'hD;
|
||||
parameter EXIT2_IR = 4'hE;
|
||||
parameter UPDATE_IR = 4'hF;
|
||||
|
||||
// DTM regs
|
||||
parameter REG_BYPASS = 5'b11111;
|
||||
parameter REG_IDCODE = 5'b00001;
|
||||
parameter REG_DMI = 5'b10001;
|
||||
parameter REG_DTMCS = 5'b10000;
|
||||
|
||||
reg[IR_BITS - 1:0] ir_reg;
|
||||
reg[SHIFT_REG_BITS - 1:0] shift_reg;
|
||||
reg[3:0] jtag_state;
|
||||
wire is_busy;
|
||||
reg sticky_busy;
|
||||
reg dtm_req_valid;
|
||||
reg[DTM_REQ_BITS - 1:0] dtm_req_data;
|
||||
reg[DM_RESP_BITS - 1:0] dm_resp_data;
|
||||
reg dm_is_busy;
|
||||
|
||||
wire[5:0] addr_bits = DMI_ADDR_BITS[5:0];
|
||||
wire [SHIFT_REG_BITS - 1:0] busy_response;
|
||||
wire [SHIFT_REG_BITS - 1:0] none_busy_response;
|
||||
wire[31:0] idcode;
|
||||
wire[31:0] dtmcs;
|
||||
wire[1:0] dmi_stat;
|
||||
wire dtm_reset;
|
||||
wire tx_idle;
|
||||
wire rx_valid;
|
||||
wire[DM_RESP_BITS - 1:0] rx_data;
|
||||
wire tx_valid;
|
||||
wire[DTM_REQ_BITS - 1:0] tx_data;
|
||||
|
||||
assign dtm_reset = shift_reg[16];
|
||||
assign idcode = {IDCODE_VERSION, IDCODE_PART_NUMBER, IDCODE_MANUFLD, 1'h1};
|
||||
assign dtmcs = {14'b0,
|
||||
1'b0, // dmihardreset
|
||||
1'b0, // dmireset
|
||||
1'b0,
|
||||
3'h5, // idle
|
||||
dmi_stat, // dmistat
|
||||
addr_bits, // abits
|
||||
DTM_VERSION}; // version
|
||||
|
||||
assign busy_response = {{(DMI_ADDR_BITS + DMI_DATA_BITS){1'b0}}, {(DMI_OP_BITS){1'b1}}}; // op = 2'b11
|
||||
assign none_busy_response = dm_resp_data;
|
||||
assign is_busy = sticky_busy | dm_is_busy;
|
||||
assign dmi_stat = is_busy ? 2'b01 : 2'b00;
|
||||
|
||||
// state switch
|
||||
always @(posedge jtag_TCK or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
jtag_state <= TEST_LOGIC_RESET;
|
||||
end else begin
|
||||
case (jtag_state)
|
||||
TEST_LOGIC_RESET : jtag_state <= jtag_TMS ? TEST_LOGIC_RESET : RUN_TEST_IDLE;
|
||||
RUN_TEST_IDLE : jtag_state <= jtag_TMS ? SELECT_DR : RUN_TEST_IDLE;
|
||||
SELECT_DR : jtag_state <= jtag_TMS ? SELECT_IR : CAPTURE_DR;
|
||||
CAPTURE_DR : jtag_state <= jtag_TMS ? EXIT1_DR : SHIFT_DR;
|
||||
SHIFT_DR : jtag_state <= jtag_TMS ? EXIT1_DR : SHIFT_DR;
|
||||
EXIT1_DR : jtag_state <= jtag_TMS ? UPDATE_DR : PAUSE_DR;
|
||||
PAUSE_DR : jtag_state <= jtag_TMS ? EXIT2_DR : PAUSE_DR;
|
||||
EXIT2_DR : jtag_state <= jtag_TMS ? UPDATE_DR : SHIFT_DR;
|
||||
UPDATE_DR : jtag_state <= jtag_TMS ? SELECT_DR : RUN_TEST_IDLE;
|
||||
SELECT_IR : jtag_state <= jtag_TMS ? TEST_LOGIC_RESET : CAPTURE_IR;
|
||||
CAPTURE_IR : jtag_state <= jtag_TMS ? EXIT1_IR : SHIFT_IR;
|
||||
SHIFT_IR : jtag_state <= jtag_TMS ? EXIT1_IR : SHIFT_IR;
|
||||
EXIT1_IR : jtag_state <= jtag_TMS ? UPDATE_IR : PAUSE_IR;
|
||||
PAUSE_IR : jtag_state <= jtag_TMS ? EXIT2_IR : PAUSE_IR;
|
||||
EXIT2_IR : jtag_state <= jtag_TMS ? UPDATE_IR : SHIFT_IR;
|
||||
UPDATE_IR : jtag_state <= jtag_TMS ? SELECT_DR : RUN_TEST_IDLE;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
// IR or DR shift
|
||||
always @(posedge jtag_TCK) begin
|
||||
case (jtag_state)
|
||||
// IR
|
||||
CAPTURE_IR: shift_reg <= {{(SHIFT_REG_BITS - 1){1'b0}}, 1'b1}; //JTAG spec says it must be b01
|
||||
SHIFT_IR : shift_reg <= {{(SHIFT_REG_BITS - IR_BITS){1'b0}}, jtag_TDI, shift_reg[IR_BITS - 1:1]}; // right shift 1 bit
|
||||
// DR
|
||||
CAPTURE_DR: case (ir_reg)
|
||||
REG_BYPASS : shift_reg <= {(SHIFT_REG_BITS){1'b0}};
|
||||
REG_IDCODE : shift_reg <= {{(SHIFT_REG_BITS - DMI_DATA_BITS){1'b0}}, idcode};
|
||||
REG_DTMCS : shift_reg <= {{(SHIFT_REG_BITS - DMI_DATA_BITS){1'b0}}, dtmcs};
|
||||
REG_DMI : shift_reg <= is_busy ? busy_response : none_busy_response;
|
||||
default:
|
||||
shift_reg <= {(SHIFT_REG_BITS){1'b0}};
|
||||
endcase
|
||||
SHIFT_DR : case (ir_reg)
|
||||
REG_BYPASS : shift_reg <= {{(SHIFT_REG_BITS - 1){1'b0}}, jtag_TDI}; // in = out
|
||||
REG_IDCODE : shift_reg <= {{(SHIFT_REG_BITS - DMI_DATA_BITS){1'b0}}, jtag_TDI, shift_reg[31:1]}; // right shift 1 bit
|
||||
REG_DTMCS : shift_reg <= {{(SHIFT_REG_BITS - DMI_DATA_BITS){1'b0}}, jtag_TDI, shift_reg[31:1]}; // right shift 1 bit
|
||||
REG_DMI : shift_reg <= {jtag_TDI, shift_reg[SHIFT_REG_BITS - 1:1]}; // right shift 1 bit
|
||||
default:
|
||||
shift_reg <= {{(SHIFT_REG_BITS - 1){1'b0}} , jtag_TDI};
|
||||
endcase
|
||||
endcase
|
||||
end
|
||||
|
||||
// start access DM module
|
||||
always @(posedge jtag_TCK or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
dtm_req_valid <= 1'b0;
|
||||
dtm_req_data <= {DTM_REQ_BITS{1'b0}};
|
||||
end else begin
|
||||
if (jtag_state == UPDATE_DR) begin
|
||||
if (ir_reg == REG_DMI) begin
|
||||
// if DM can be access
|
||||
if (!is_busy & tx_idle) begin
|
||||
dtm_req_valid <= 1'b1;
|
||||
dtm_req_data <= shift_reg;
|
||||
end
|
||||
end
|
||||
end else begin
|
||||
dtm_req_valid <= 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign tx_valid = dtm_req_valid;
|
||||
assign tx_data = dtm_req_data;
|
||||
|
||||
// DTM reset
|
||||
always @ (posedge jtag_TCK or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
sticky_busy <= 1'b0;
|
||||
end else begin
|
||||
if (jtag_state == UPDATE_DR) begin
|
||||
if (ir_reg == REG_DTMCS & dtm_reset) begin
|
||||
sticky_busy <= 1'b0;
|
||||
end
|
||||
end else if (jtag_state == CAPTURE_DR) begin
|
||||
if (ir_reg == REG_DMI) begin
|
||||
sticky_busy <= is_busy;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// receive DM response data
|
||||
always @ (posedge jtag_TCK or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
dm_resp_data <= {DM_RESP_BITS{1'b0}};
|
||||
end else begin
|
||||
if (rx_valid) begin
|
||||
dm_resp_data <= rx_data;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// tx busy
|
||||
always @ (posedge jtag_TCK or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
dm_is_busy <= 1'b0;
|
||||
end else begin
|
||||
if (dtm_req_valid) begin
|
||||
dm_is_busy <= 1'b1;
|
||||
end else if (rx_valid) begin
|
||||
dm_is_busy <= 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// TAP reset
|
||||
always @(negedge jtag_TCK) begin
|
||||
if (jtag_state == TEST_LOGIC_RESET) begin
|
||||
ir_reg <= REG_IDCODE;
|
||||
end else if (jtag_state == UPDATE_IR) begin
|
||||
ir_reg <= shift_reg[IR_BITS - 1:0];
|
||||
end
|
||||
end
|
||||
|
||||
// TDO output
|
||||
always @(negedge jtag_TCK) begin
|
||||
if (jtag_state == SHIFT_IR) begin
|
||||
jtag_TDO <= shift_reg[0];
|
||||
end else if (jtag_state == SHIFT_DR) begin
|
||||
jtag_TDO <= shift_reg[0];
|
||||
end else begin
|
||||
jtag_TDO <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
full_handshake_tx #(
|
||||
.DW(DTM_REQ_BITS)
|
||||
) tx(
|
||||
.clk(jtag_TCK),
|
||||
.rst_n(rst_n),
|
||||
.ack_i(dm_ack_i),
|
||||
.req_i(tx_valid),
|
||||
.req_data_i(tx_data),
|
||||
.idle_o(tx_idle),
|
||||
.req_o(dtm_req_valid_o),
|
||||
.req_data_o(dtm_req_data_o)
|
||||
);
|
||||
|
||||
full_handshake_rx #(
|
||||
.DW(DM_RESP_BITS)
|
||||
) rx(
|
||||
.clk(jtag_TCK),
|
||||
.rst_n(rst_n),
|
||||
.req_i(dm_resp_i),
|
||||
.req_data_i(dm_resp_data_i),
|
||||
.ack_o(dtm_ack_o),
|
||||
.recv_data_o(rx_data),
|
||||
.recv_rdy_o(rx_valid)
|
||||
);
|
||||
|
||||
endmodule
|
||||
/*
|
||||
Copyright 2020 Blue Liang, liangkangnan@163.com
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
module jtag_driver #(
|
||||
parameter DMI_ADDR_BITS = 6,
|
||||
parameter DMI_DATA_BITS = 32,
|
||||
parameter DMI_OP_BITS = 2)(
|
||||
|
||||
rst_n,
|
||||
|
||||
jtag_TCK,
|
||||
jtag_TDI,
|
||||
jtag_TMS,
|
||||
jtag_TDO,
|
||||
|
||||
// rx
|
||||
dm_resp_i,
|
||||
dm_resp_data_i,
|
||||
dtm_ack_o,
|
||||
|
||||
// tx
|
||||
dm_ack_i,
|
||||
dtm_req_valid_o,
|
||||
dtm_req_data_o
|
||||
|
||||
);
|
||||
|
||||
parameter IDCODE_VERSION = 4'h1;
|
||||
parameter IDCODE_PART_NUMBER = 16'he200;
|
||||
parameter IDCODE_MANUFLD = 11'h537;
|
||||
|
||||
parameter DTM_VERSION = 4'h1;
|
||||
parameter IR_BITS = 5;
|
||||
|
||||
parameter DM_RESP_BITS = DMI_ADDR_BITS + DMI_DATA_BITS + DMI_OP_BITS;
|
||||
parameter DTM_REQ_BITS = DMI_ADDR_BITS + DMI_DATA_BITS + DMI_OP_BITS;
|
||||
parameter SHIFT_REG_BITS = DTM_REQ_BITS;
|
||||
|
||||
// input and output
|
||||
input wire rst_n;
|
||||
input wire jtag_TCK;
|
||||
input wire jtag_TDI;
|
||||
input wire jtag_TMS;
|
||||
output reg jtag_TDO;
|
||||
input wire dm_resp_i;
|
||||
input wire[DM_RESP_BITS - 1:0] dm_resp_data_i;
|
||||
output wire dtm_ack_o;
|
||||
input wire dm_ack_i;
|
||||
output wire dtm_req_valid_o;
|
||||
output wire[DTM_REQ_BITS - 1:0] dtm_req_data_o;
|
||||
|
||||
// JTAG StateMachine
|
||||
parameter TEST_LOGIC_RESET = 4'h0;
|
||||
parameter RUN_TEST_IDLE = 4'h1;
|
||||
parameter SELECT_DR = 4'h2;
|
||||
parameter CAPTURE_DR = 4'h3;
|
||||
parameter SHIFT_DR = 4'h4;
|
||||
parameter EXIT1_DR = 4'h5;
|
||||
parameter PAUSE_DR = 4'h6;
|
||||
parameter EXIT2_DR = 4'h7;
|
||||
parameter UPDATE_DR = 4'h8;
|
||||
parameter SELECT_IR = 4'h9;
|
||||
parameter CAPTURE_IR = 4'hA;
|
||||
parameter SHIFT_IR = 4'hB;
|
||||
parameter EXIT1_IR = 4'hC;
|
||||
parameter PAUSE_IR = 4'hD;
|
||||
parameter EXIT2_IR = 4'hE;
|
||||
parameter UPDATE_IR = 4'hF;
|
||||
|
||||
// DTM regs
|
||||
parameter REG_BYPASS = 5'b11111;
|
||||
parameter REG_IDCODE = 5'b00001;
|
||||
parameter REG_DMI = 5'b10001;
|
||||
parameter REG_DTMCS = 5'b10000;
|
||||
|
||||
reg[IR_BITS - 1:0] ir_reg;
|
||||
reg[SHIFT_REG_BITS - 1:0] shift_reg;
|
||||
reg[3:0] jtag_state;
|
||||
wire is_busy;
|
||||
reg sticky_busy;
|
||||
reg dtm_req_valid;
|
||||
reg[DTM_REQ_BITS - 1:0] dtm_req_data;
|
||||
reg[DM_RESP_BITS - 1:0] dm_resp_data;
|
||||
reg dm_is_busy;
|
||||
|
||||
wire[5:0] addr_bits = DMI_ADDR_BITS[5:0];
|
||||
wire [SHIFT_REG_BITS - 1:0] busy_response;
|
||||
wire [SHIFT_REG_BITS - 1:0] none_busy_response;
|
||||
wire[31:0] idcode;
|
||||
wire[31:0] dtmcs;
|
||||
wire[1:0] dmi_stat;
|
||||
wire dtm_reset;
|
||||
wire tx_idle;
|
||||
wire rx_valid;
|
||||
wire[DM_RESP_BITS - 1:0] rx_data;
|
||||
wire tx_valid;
|
||||
wire[DTM_REQ_BITS - 1:0] tx_data;
|
||||
|
||||
assign dtm_reset = shift_reg[16];
|
||||
assign idcode = {IDCODE_VERSION, IDCODE_PART_NUMBER, IDCODE_MANUFLD, 1'h1};
|
||||
assign dtmcs = {14'b0,
|
||||
1'b0, // dmihardreset
|
||||
1'b0, // dmireset
|
||||
1'b0,
|
||||
3'h5, // idle
|
||||
dmi_stat, // dmistat
|
||||
addr_bits, // abits
|
||||
DTM_VERSION}; // version
|
||||
|
||||
assign busy_response = {{(DMI_ADDR_BITS + DMI_DATA_BITS){1'b0}}, {(DMI_OP_BITS){1'b1}}}; // op = 2'b11
|
||||
assign none_busy_response = dm_resp_data;
|
||||
assign is_busy = sticky_busy | dm_is_busy;
|
||||
assign dmi_stat = is_busy ? 2'b01 : 2'b00;
|
||||
|
||||
// state switch
|
||||
always @(posedge jtag_TCK or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
jtag_state <= TEST_LOGIC_RESET;
|
||||
end else begin
|
||||
case (jtag_state)
|
||||
TEST_LOGIC_RESET : jtag_state <= jtag_TMS ? TEST_LOGIC_RESET : RUN_TEST_IDLE;
|
||||
RUN_TEST_IDLE : jtag_state <= jtag_TMS ? SELECT_DR : RUN_TEST_IDLE;
|
||||
SELECT_DR : jtag_state <= jtag_TMS ? SELECT_IR : CAPTURE_DR;
|
||||
CAPTURE_DR : jtag_state <= jtag_TMS ? EXIT1_DR : SHIFT_DR;
|
||||
SHIFT_DR : jtag_state <= jtag_TMS ? EXIT1_DR : SHIFT_DR;
|
||||
EXIT1_DR : jtag_state <= jtag_TMS ? UPDATE_DR : PAUSE_DR;
|
||||
PAUSE_DR : jtag_state <= jtag_TMS ? EXIT2_DR : PAUSE_DR;
|
||||
EXIT2_DR : jtag_state <= jtag_TMS ? UPDATE_DR : SHIFT_DR;
|
||||
UPDATE_DR : jtag_state <= jtag_TMS ? SELECT_DR : RUN_TEST_IDLE;
|
||||
SELECT_IR : jtag_state <= jtag_TMS ? TEST_LOGIC_RESET : CAPTURE_IR;
|
||||
CAPTURE_IR : jtag_state <= jtag_TMS ? EXIT1_IR : SHIFT_IR;
|
||||
SHIFT_IR : jtag_state <= jtag_TMS ? EXIT1_IR : SHIFT_IR;
|
||||
EXIT1_IR : jtag_state <= jtag_TMS ? UPDATE_IR : PAUSE_IR;
|
||||
PAUSE_IR : jtag_state <= jtag_TMS ? EXIT2_IR : PAUSE_IR;
|
||||
EXIT2_IR : jtag_state <= jtag_TMS ? UPDATE_IR : SHIFT_IR;
|
||||
UPDATE_IR : jtag_state <= jtag_TMS ? SELECT_DR : RUN_TEST_IDLE;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
// IR or DR shift
|
||||
always @(posedge jtag_TCK) begin
|
||||
case (jtag_state)
|
||||
// IR
|
||||
CAPTURE_IR: shift_reg <= {{(SHIFT_REG_BITS - 1){1'b0}}, 1'b1}; //JTAG spec says it must be b01
|
||||
SHIFT_IR : shift_reg <= {{(SHIFT_REG_BITS - IR_BITS){1'b0}}, jtag_TDI, shift_reg[IR_BITS - 1:1]}; // right shift 1 bit
|
||||
// DR
|
||||
CAPTURE_DR: case (ir_reg)
|
||||
REG_BYPASS : shift_reg <= {(SHIFT_REG_BITS){1'b0}};
|
||||
REG_IDCODE : shift_reg <= {{(SHIFT_REG_BITS - DMI_DATA_BITS){1'b0}}, idcode};
|
||||
REG_DTMCS : shift_reg <= {{(SHIFT_REG_BITS - DMI_DATA_BITS){1'b0}}, dtmcs};
|
||||
REG_DMI : shift_reg <= is_busy ? busy_response : none_busy_response;
|
||||
default:
|
||||
shift_reg <= {(SHIFT_REG_BITS){1'b0}};
|
||||
endcase
|
||||
SHIFT_DR : case (ir_reg)
|
||||
REG_BYPASS : shift_reg <= {{(SHIFT_REG_BITS - 1){1'b0}}, jtag_TDI}; // in = out
|
||||
REG_IDCODE : shift_reg <= {{(SHIFT_REG_BITS - DMI_DATA_BITS){1'b0}}, jtag_TDI, shift_reg[31:1]}; // right shift 1 bit
|
||||
REG_DTMCS : shift_reg <= {{(SHIFT_REG_BITS - DMI_DATA_BITS){1'b0}}, jtag_TDI, shift_reg[31:1]}; // right shift 1 bit
|
||||
REG_DMI : shift_reg <= {jtag_TDI, shift_reg[SHIFT_REG_BITS - 1:1]}; // right shift 1 bit
|
||||
default:
|
||||
shift_reg <= {{(SHIFT_REG_BITS - 1){1'b0}} , jtag_TDI};
|
||||
endcase
|
||||
endcase
|
||||
end
|
||||
|
||||
// start access DM module
|
||||
always @(posedge jtag_TCK or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
dtm_req_valid <= 1'b0;
|
||||
dtm_req_data <= {DTM_REQ_BITS{1'b0}};
|
||||
end else begin
|
||||
if (jtag_state == UPDATE_DR) begin
|
||||
if (ir_reg == REG_DMI) begin
|
||||
// if DM can be access
|
||||
if (!is_busy & tx_idle) begin
|
||||
dtm_req_valid <= 1'b1;
|
||||
dtm_req_data <= shift_reg;
|
||||
end
|
||||
end
|
||||
end else begin
|
||||
dtm_req_valid <= 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign tx_valid = dtm_req_valid;
|
||||
assign tx_data = dtm_req_data;
|
||||
|
||||
// DTM reset
|
||||
always @ (posedge jtag_TCK or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
sticky_busy <= 1'b0;
|
||||
end else begin
|
||||
if (jtag_state == UPDATE_DR) begin
|
||||
if (ir_reg == REG_DTMCS & dtm_reset) begin
|
||||
sticky_busy <= 1'b0;
|
||||
end
|
||||
end else if (jtag_state == CAPTURE_DR) begin
|
||||
if (ir_reg == REG_DMI) begin
|
||||
sticky_busy <= is_busy;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// receive DM response data
|
||||
always @ (posedge jtag_TCK or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
dm_resp_data <= {DM_RESP_BITS{1'b0}};
|
||||
end else begin
|
||||
if (rx_valid) begin
|
||||
dm_resp_data <= rx_data;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// tx busy
|
||||
always @ (posedge jtag_TCK or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
dm_is_busy <= 1'b0;
|
||||
end else begin
|
||||
if (dtm_req_valid) begin
|
||||
dm_is_busy <= 1'b1;
|
||||
end else if (rx_valid) begin
|
||||
dm_is_busy <= 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// TAP reset
|
||||
always @(negedge jtag_TCK) begin
|
||||
if (jtag_state == TEST_LOGIC_RESET) begin
|
||||
ir_reg <= REG_IDCODE;
|
||||
end else if (jtag_state == UPDATE_IR) begin
|
||||
ir_reg <= shift_reg[IR_BITS - 1:0];
|
||||
end
|
||||
end
|
||||
|
||||
// TDO output
|
||||
always @(negedge jtag_TCK) begin
|
||||
if (jtag_state == SHIFT_IR) begin
|
||||
jtag_TDO <= shift_reg[0];
|
||||
end else if (jtag_state == SHIFT_DR) begin
|
||||
jtag_TDO <= shift_reg[0];
|
||||
end else begin
|
||||
jtag_TDO <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
full_handshake_tx #(
|
||||
.DW(DTM_REQ_BITS)
|
||||
) tx(
|
||||
.clk(jtag_TCK),
|
||||
.rst_n(rst_n),
|
||||
.ack_i(dm_ack_i),
|
||||
.req_i(tx_valid),
|
||||
.req_data_i(tx_data),
|
||||
.idle_o(tx_idle),
|
||||
.req_o(dtm_req_valid_o),
|
||||
.req_data_o(dtm_req_data_o)
|
||||
);
|
||||
|
||||
full_handshake_rx #(
|
||||
.DW(DM_RESP_BITS)
|
||||
) rx(
|
||||
.clk(jtag_TCK),
|
||||
.rst_n(rst_n),
|
||||
.req_i(dm_resp_i),
|
||||
.req_data_i(dm_resp_data_i),
|
||||
.ack_o(dtm_ack_o),
|
||||
.recv_data_o(rx_data),
|
||||
.recv_rdy_o(rx_valid)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -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,57 +1,47 @@
|
|||
/*
|
||||
Copyright 2020 Blue Liang, liangkangnan@163.com
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
module vld_rdy #(
|
||||
parameter CUT_READY = 0)(
|
||||
|
||||
input wire clk,
|
||||
input wire rst_n,
|
||||
|
||||
input wire vld_i,
|
||||
output wire rdy_o,
|
||||
input wire rdy_i,
|
||||
output wire vld_o
|
||||
|
||||
);
|
||||
|
||||
wire vld_set;
|
||||
wire vld_clr;
|
||||
wire vld_ena;
|
||||
wire vld_r;
|
||||
wire vld_nxt;
|
||||
|
||||
// The valid will be set when input handshaked
|
||||
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 vld_nxt = vld_set | (~vld_clr);
|
||||
|
||||
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
|
||||
/*
|
||||
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_sba #(
|
||||
|
||||
)(
|
||||
|
||||
input wire clk,
|
||||
input wire rst_n,
|
||||
|
||||
output wire sbbusy_o,
|
||||
|
||||
output wire master_req_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
|
||||
|
||||
);
|
||||
|
||||
|
||||
assign sbbusy_o = 1'b0;
|
||||
|
||||
assign master_req_o = 1'b0;
|
||||
assign master_we_o = 1'b0;
|
||||
|
||||
|
||||
|
||||
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,117 +1,161 @@
|
|||
/*
|
||||
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 "../core/defines.sv"
|
||||
|
||||
// JTAG顶层模块
|
||||
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 jtag_pin_TMS,
|
||||
input wire jtag_pin_TDI,
|
||||
output wire jtag_pin_TDO,
|
||||
|
||||
output wire reg_we_o,
|
||||
output wire[4:0] reg_addr_o,
|
||||
output wire[31:0] reg_wdata_o,
|
||||
input wire[31:0] reg_rdata_i,
|
||||
|
||||
output wire mem_we_o,
|
||||
output wire[31:0] mem_addr_o,
|
||||
output wire[31:0] mem_wdata_o,
|
||||
input wire[31:0] mem_rdata_i,
|
||||
output wire[3:0] 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 halt_req_o,
|
||||
output wire reset_req_o
|
||||
|
||||
);
|
||||
|
||||
parameter DM_RESP_BITS = DMI_ADDR_BITS + DMI_DATA_BITS + DMI_OP_BITS;
|
||||
parameter DTM_REQ_BITS = DMI_ADDR_BITS + DMI_DATA_BITS + DMI_OP_BITS;
|
||||
|
||||
// jtag_driver输出信号
|
||||
wire dtm_ack_o;
|
||||
wire dtm_req_valid_o;
|
||||
wire[DTM_REQ_BITS - 1:0] dtm_req_data_o;
|
||||
|
||||
// jtag_dm输出信号
|
||||
wire dm_ack_o;
|
||||
wire[DM_RESP_BITS-1:0] dm_resp_data_o;
|
||||
wire dm_resp_valid_o;
|
||||
wire dm_halt_req_o;
|
||||
wire dm_reset_req_o;
|
||||
|
||||
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 #(
|
||||
.DMI_ADDR_BITS(DMI_ADDR_BITS),
|
||||
.DMI_DATA_BITS(DMI_DATA_BITS),
|
||||
.DMI_OP_BITS(DMI_OP_BITS)
|
||||
) u_jtag_dm(
|
||||
.clk(clk),
|
||||
.rst_n(jtag_rst_n),
|
||||
.dm_ack_o(dm_ack_o),
|
||||
.dtm_req_valid_i(dtm_req_valid_o),
|
||||
.dtm_req_data_i(dtm_req_data_o),
|
||||
.dtm_ack_i(dtm_ack_o),
|
||||
.dm_resp_data_o(dm_resp_data_o),
|
||||
.dm_resp_valid_o(dm_resp_valid_o),
|
||||
.dm_reg_we_o(reg_we_o),
|
||||
.dm_reg_addr_o(reg_addr_o),
|
||||
.dm_reg_wdata_o(reg_wdata_o),
|
||||
.dm_reg_rdata_i(reg_rdata_i),
|
||||
.dm_mem_we_o(mem_we_o),
|
||||
.dm_mem_addr_o(mem_addr_o),
|
||||
.dm_mem_wdata_o(mem_wdata_o),
|
||||
.dm_mem_rdata_i(mem_rdata_i),
|
||||
.dm_mem_sel_o(mem_sel_o),
|
||||
.req_valid_o(req_valid_o),
|
||||
.req_ready_i(req_ready_i),
|
||||
.rsp_valid_i(rsp_valid_i),
|
||||
.rsp_ready_o(rsp_ready_o),
|
||||
.dm_halt_req_o(halt_req_o),
|
||||
.dm_reset_req_o(reset_req_o)
|
||||
);
|
||||
|
||||
endmodule
|
||||
/*
|
||||
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_top #(
|
||||
|
||||
)(
|
||||
|
||||
input wire clk_i,
|
||||
input wire rst_ni,
|
||||
|
||||
output wire debug_req_o,
|
||||
output wire ndmreset_o,
|
||||
|
||||
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 master_req_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,
|
||||
|
||||
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
|
||||
|
||||
);
|
||||
|
||||
// addr + data + op = 6 + 32 + 2 = 40
|
||||
localparam DMI_DATA_WIDTH = 40;
|
||||
|
||||
|
||||
wire [DMI_DATA_WIDTH-1:0] dm_to_dmi_data;
|
||||
wire dm_to_dmi_valid;
|
||||
wire dm_to_dmi_ready;
|
||||
wire [DMI_DATA_WIDTH-1:0] dmi_to_dm_data;
|
||||
wire dmi_to_dm_valid;
|
||||
wire dmi_to_dm_ready;
|
||||
|
||||
jtag_dm #(
|
||||
|
||||
) u_jtag_dm (
|
||||
.clk (clk_i),
|
||||
.rst_n (rst_ni),
|
||||
.dmi_data_i (dmi_to_dm_data),
|
||||
.dmi_valid_i (dmi_to_dm_valid),
|
||||
.dm_ready_o (dm_to_dmi_ready),
|
||||
.dm_data_o (dm_to_dmi_data),
|
||||
.dm_valid_o (dm_to_dmi_valid),
|
||||
.dmi_ready_i (dmi_to_dm_ready),
|
||||
.debug_req_o (debug_req_o),
|
||||
.ndmreset_o (ndmreset_o),
|
||||
.master_req_o (master_req_o),
|
||||
.master_gnt_i (master_gnt_i),
|
||||
.master_rvalid_i(master_rvalid_i),
|
||||
.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),
|
||||
.slave_req_i (slave_req_i),
|
||||
.slave_we_i (slave_we_i),
|
||||
.slave_addr_i (slave_addr_i),
|
||||
.slave_be_i (slave_be_i),
|
||||
.slave_wdata_i (slave_wdata_i),
|
||||
.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
|
||||
|
|
|
@ -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 "../debug/jtag_def.sv"
|
||||
|
||||
// tinyriscv soc顶层模块
|
||||
module tinyriscv_soc_top(
|
||||
|
@ -38,14 +39,18 @@ module tinyriscv_soc_top(
|
|||
|
||||
|
||||
|
||||
localparam int MASTERS = 2; //Number of master ports
|
||||
localparam int SLAVES = 2; //Number of slave ports
|
||||
localparam int MASTERS = 3; // Number of master ports
|
||||
localparam int SLAVES = 3; // Number of slave ports
|
||||
|
||||
localparam int CoreD = 0;
|
||||
localparam int CoreI = 1;
|
||||
// masters
|
||||
localparam int CoreD = 0;
|
||||
localparam int JtagHost = 1;
|
||||
localparam int CoreI = 2;
|
||||
|
||||
localparam int Rom = 0;
|
||||
localparam int Ram = 1;
|
||||
// slaves
|
||||
localparam int Rom = 0;
|
||||
localparam int Ram = 1;
|
||||
localparam int JtagDevice = 2;
|
||||
|
||||
|
||||
wire master_req [MASTERS];
|
||||
|
@ -80,12 +85,12 @@ module tinyriscv_soc_top(
|
|||
|
||||
wire ndmreset;
|
||||
wire ndmreset_n;
|
||||
wire debug_req;
|
||||
|
||||
assign ndmreset = 1'b0;
|
||||
|
||||
tinyriscv_core #(
|
||||
.DEBUG_HALT_ADDR(`DEBUG_ADDR_BASE + 16'h800),
|
||||
.DEBUG_EXCEPTION_ADDR(`DEBUG_ADDR_BASE + 16'h808)
|
||||
.DEBUG_HALT_ADDR(`DEBUG_ADDR_BASE + `HaltAddress),
|
||||
.DEBUG_EXCEPTION_ADDR(`DEBUG_ADDR_BASE + `ExceptionAddress)
|
||||
) u_tinyriscv_core (
|
||||
.clk(clk),
|
||||
.rst_n(ndmreset_n),
|
||||
|
@ -111,9 +116,8 @@ module tinyriscv_soc_top(
|
|||
.irq_timer_i(1'b0),
|
||||
.irq_external_i(1'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)
|
||||
);
|
||||
|
||||
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
|
||||
sim_jtag #(
|
||||
|
@ -191,7 +225,7 @@ module tinyriscv_soc_top(
|
|||
) u_sim_jtag (
|
||||
.clock ( clk ),
|
||||
.reset ( ~rst_ext_ni ),
|
||||
.enable ( 1'b0 ),
|
||||
.enable ( 1'b1 ),
|
||||
.init_done ( rst_ext_ni ),
|
||||
.jtag_TCK ( sim_jtag_tck ),
|
||||
.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
|
|
@ -1,46 +1,46 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// 将输入打DP拍后输出
|
||||
module gen_ticks_sync #(
|
||||
parameter DP = 2,
|
||||
parameter DW = 32)(
|
||||
|
||||
input wire rst_n,
|
||||
input wire clk,
|
||||
|
||||
input wire[DW-1:0] din,
|
||||
output wire[DW-1:0] dout
|
||||
|
||||
);
|
||||
|
||||
wire[DW-1:0] sync_dat[DP-1:0];
|
||||
|
||||
genvar i;
|
||||
|
||||
generate
|
||||
for (i = 0; i < DP; i = i + 1) begin: ticks_sync
|
||||
if (i == 0) begin: dp_is_0
|
||||
gen_rst_0_dff #(DW) rst_0_dff(clk, rst_n, din, sync_dat[0]);
|
||||
end else begin: dp_is_not_0
|
||||
gen_rst_0_dff #(DW) rst_0_dff(clk, rst_n, sync_dat[i-1], sync_dat[i]);
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
assign dout = sync_dat[DP-1];
|
||||
|
||||
endmodule
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// 将输入打DP拍后输出
|
||||
module gen_ticks_sync #(
|
||||
parameter DP = 2,
|
||||
parameter DW = 32)(
|
||||
|
||||
input wire rst_n,
|
||||
input wire clk,
|
||||
|
||||
input wire[DW-1:0] din,
|
||||
output wire[DW-1:0] dout
|
||||
|
||||
);
|
||||
|
||||
wire[DW-1:0] sync_dat[DP-1:0];
|
||||
|
||||
genvar i;
|
||||
|
||||
generate
|
||||
for (i = 0; i < DP; i = i + 1) begin: ticks_sync
|
||||
if (i == 0) begin: dp_is_0
|
||||
gen_rst_0_dff #(DW) rst_0_dff(clk, rst_n, din, sync_dat[0]);
|
||||
end else begin: dp_is_not_0
|
||||
gen_rst_0_dff #(DW) rst_0_dff(clk, rst_n, sync_dat[i-1], sync_dat[i]);
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
assign dout = sync_dat[DP-1];
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -1,173 +1,173 @@
|
|||
/*
|
||||
Copyright 2020 Blue Liang, liangkangnan@163.com
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// 带默认值和控制信号的流水线触发器
|
||||
module gen_pipe_dff #(
|
||||
parameter DW = 32)(
|
||||
|
||||
input wire clk,
|
||||
input wire rst_n,
|
||||
input wire hold_en,
|
||||
|
||||
input wire[DW-1:0] def_val,
|
||||
input wire[DW-1:0] din,
|
||||
output wire[DW-1:0] qout
|
||||
|
||||
);
|
||||
|
||||
reg[DW-1:0] qout_r;
|
||||
|
||||
always @ (posedge clk or negedge rst_n) begin
|
||||
if (!rst_n | hold_en) begin
|
||||
qout_r <= def_val;
|
||||
end else begin
|
||||
qout_r <= din;
|
||||
end
|
||||
end
|
||||
|
||||
assign qout = qout_r;
|
||||
|
||||
endmodule
|
||||
|
||||
// 复位后输出为0的触发器
|
||||
module gen_rst_0_dff #(
|
||||
parameter DW = 32)(
|
||||
|
||||
input wire clk,
|
||||
input wire rst_n,
|
||||
|
||||
input wire[DW-1:0] din,
|
||||
output wire[DW-1:0] qout
|
||||
|
||||
);
|
||||
|
||||
reg[DW-1:0] qout_r;
|
||||
|
||||
always @ (posedge clk or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
qout_r <= {DW{1'b0}};
|
||||
end else begin
|
||||
qout_r <= din;
|
||||
end
|
||||
end
|
||||
|
||||
assign qout = qout_r;
|
||||
|
||||
endmodule
|
||||
|
||||
// 复位后输出为1的触发器
|
||||
module gen_rst_1_dff #(
|
||||
parameter DW = 32)(
|
||||
|
||||
input wire clk,
|
||||
input wire rst_n,
|
||||
|
||||
input wire[DW-1:0] din,
|
||||
output wire[DW-1:0] qout
|
||||
|
||||
);
|
||||
|
||||
reg[DW-1:0] qout_r;
|
||||
|
||||
always @ (posedge clk or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
qout_r <= {DW{1'b1}};
|
||||
end else begin
|
||||
qout_r <= din;
|
||||
end
|
||||
end
|
||||
|
||||
assign qout = qout_r;
|
||||
|
||||
endmodule
|
||||
|
||||
// 复位后输出为默认值的触发器
|
||||
module gen_rst_def_dff #(
|
||||
parameter DW = 32)(
|
||||
|
||||
input wire clk,
|
||||
input wire rst_n,
|
||||
input wire[DW-1:0] def_val,
|
||||
|
||||
input wire[DW-1:0] din,
|
||||
output wire[DW-1:0] qout
|
||||
|
||||
);
|
||||
|
||||
reg[DW-1:0] qout_r;
|
||||
|
||||
always @ (posedge clk or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
qout_r <= def_val;
|
||||
end else begin
|
||||
qout_r <= din;
|
||||
end
|
||||
end
|
||||
|
||||
assign qout = qout_r;
|
||||
|
||||
endmodule
|
||||
|
||||
// 带使能端、复位后输出为0的触发器
|
||||
module gen_en_dff #(
|
||||
parameter DW = 32)(
|
||||
|
||||
input wire clk,
|
||||
input wire rst_n,
|
||||
|
||||
input wire en,
|
||||
input wire[DW-1:0] din,
|
||||
output wire[DW-1:0] qout
|
||||
|
||||
);
|
||||
|
||||
reg[DW-1:0] qout_r;
|
||||
|
||||
always @ (posedge clk or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
qout_r <= {DW{1'b0}};
|
||||
end else if (en == 1'b1) begin
|
||||
qout_r <= din;
|
||||
end
|
||||
end
|
||||
|
||||
assign qout = qout_r;
|
||||
|
||||
endmodule
|
||||
|
||||
// 带使能端、没有复位的触发器
|
||||
module gen_en_dffnr #(
|
||||
parameter DW = 32)(
|
||||
|
||||
input wire clk,
|
||||
|
||||
input wire en,
|
||||
input wire[DW-1:0] din,
|
||||
output wire[DW-1:0] qout
|
||||
|
||||
);
|
||||
|
||||
reg[DW-1:0] qout_r;
|
||||
|
||||
always @ (posedge clk) begin
|
||||
if (en == 1'b1) begin
|
||||
qout_r <= din;
|
||||
end
|
||||
end
|
||||
|
||||
assign qout = qout_r;
|
||||
|
||||
endmodule
|
||||
/*
|
||||
Copyright 2020 Blue Liang, liangkangnan@163.com
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// 带默认值和控制信号的流水线触发器
|
||||
module gen_pipe_dff #(
|
||||
parameter DW = 32)(
|
||||
|
||||
input wire clk,
|
||||
input wire rst_n,
|
||||
input wire hold_en,
|
||||
|
||||
input wire[DW-1:0] def_val,
|
||||
input wire[DW-1:0] din,
|
||||
output wire[DW-1:0] qout
|
||||
|
||||
);
|
||||
|
||||
reg[DW-1:0] qout_r;
|
||||
|
||||
always @ (posedge clk or negedge rst_n) begin
|
||||
if (!rst_n | hold_en) begin
|
||||
qout_r <= def_val;
|
||||
end else begin
|
||||
qout_r <= din;
|
||||
end
|
||||
end
|
||||
|
||||
assign qout = qout_r;
|
||||
|
||||
endmodule
|
||||
|
||||
// 复位后输出为0的触发器
|
||||
module gen_rst_0_dff #(
|
||||
parameter DW = 32)(
|
||||
|
||||
input wire clk,
|
||||
input wire rst_n,
|
||||
|
||||
input wire[DW-1:0] din,
|
||||
output wire[DW-1:0] qout
|
||||
|
||||
);
|
||||
|
||||
reg[DW-1:0] qout_r;
|
||||
|
||||
always @ (posedge clk or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
qout_r <= {DW{1'b0}};
|
||||
end else begin
|
||||
qout_r <= din;
|
||||
end
|
||||
end
|
||||
|
||||
assign qout = qout_r;
|
||||
|
||||
endmodule
|
||||
|
||||
// 复位后输出为1的触发器
|
||||
module gen_rst_1_dff #(
|
||||
parameter DW = 32)(
|
||||
|
||||
input wire clk,
|
||||
input wire rst_n,
|
||||
|
||||
input wire[DW-1:0] din,
|
||||
output wire[DW-1:0] qout
|
||||
|
||||
);
|
||||
|
||||
reg[DW-1:0] qout_r;
|
||||
|
||||
always @ (posedge clk or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
qout_r <= {DW{1'b1}};
|
||||
end else begin
|
||||
qout_r <= din;
|
||||
end
|
||||
end
|
||||
|
||||
assign qout = qout_r;
|
||||
|
||||
endmodule
|
||||
|
||||
// 复位后输出为默认值的触发器
|
||||
module gen_rst_def_dff #(
|
||||
parameter DW = 32)(
|
||||
|
||||
input wire clk,
|
||||
input wire rst_n,
|
||||
input wire[DW-1:0] def_val,
|
||||
|
||||
input wire[DW-1:0] din,
|
||||
output wire[DW-1:0] qout
|
||||
|
||||
);
|
||||
|
||||
reg[DW-1:0] qout_r;
|
||||
|
||||
always @ (posedge clk or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
qout_r <= def_val;
|
||||
end else begin
|
||||
qout_r <= din;
|
||||
end
|
||||
end
|
||||
|
||||
assign qout = qout_r;
|
||||
|
||||
endmodule
|
||||
|
||||
// 带使能端、复位后输出为0的触发器
|
||||
module gen_en_dff #(
|
||||
parameter DW = 32)(
|
||||
|
||||
input wire clk,
|
||||
input wire rst_n,
|
||||
|
||||
input wire en,
|
||||
input wire[DW-1:0] din,
|
||||
output wire[DW-1:0] qout
|
||||
|
||||
);
|
||||
|
||||
reg[DW-1:0] qout_r;
|
||||
|
||||
always @ (posedge clk or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
qout_r <= {DW{1'b0}};
|
||||
end else if (en == 1'b1) begin
|
||||
qout_r <= din;
|
||||
end
|
||||
end
|
||||
|
||||
assign qout = qout_r;
|
||||
|
||||
endmodule
|
||||
|
||||
// 带使能端、没有复位的触发器
|
||||
module gen_en_dffnr #(
|
||||
parameter DW = 32)(
|
||||
|
||||
input wire clk,
|
||||
|
||||
input wire en,
|
||||
input wire[DW-1:0] din,
|
||||
output wire[DW-1:0] qout
|
||||
|
||||
);
|
||||
|
||||
reg[DW-1:0] qout_r;
|
||||
|
||||
always @ (posedge clk) begin
|
||||
if (en == 1'b1) begin
|
||||
qout_r <= din;
|
||||
end
|
||||
end
|
||||
|
||||
assign qout = qout_r;
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -1,72 +1,72 @@
|
|||
/*
|
||||
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 "../core/defines.sv"
|
||||
|
||||
|
||||
module gen_ram #(
|
||||
parameter DP = 512,
|
||||
parameter DW = 32,
|
||||
parameter MW = 4,
|
||||
parameter AW = 32)(
|
||||
|
||||
input wire clk,
|
||||
input wire[AW-1:0] addr_i,
|
||||
input wire[DW-1:0] data_i,
|
||||
input wire[MW-1:0] sel_i,
|
||||
input wire we_i,
|
||||
|
||||
output wire[DW-1:0] data_o
|
||||
|
||||
);
|
||||
|
||||
reg[DW-1:0] ram [0:DP-1];
|
||||
reg[AW-1:0] addr_r;
|
||||
wire[MW-1:0] wen;
|
||||
wire ren;
|
||||
|
||||
assign ren = (~we_i);
|
||||
assign wen = ({MW{we_i}} & sel_i);
|
||||
|
||||
always @ (posedge clk) begin
|
||||
if (ren) begin
|
||||
addr_r <= addr_i;
|
||||
end
|
||||
end
|
||||
|
||||
assign data_o = ram[addr_r];
|
||||
|
||||
genvar i;
|
||||
|
||||
generate
|
||||
for (i = 0; i < MW; i = i + 1) begin: sel_width
|
||||
if ((8 * i + 8) > DW) begin: i_gt_8
|
||||
always @ (posedge clk) begin: i_gt_8_ff
|
||||
if (wen[i]) begin: gt_8_wen
|
||||
ram[addr_i][DW-1:8*i] <= data_i[DW-1:8*i];
|
||||
end
|
||||
end
|
||||
end else begin: i_lt_8
|
||||
always @ (posedge clk) begin: i_lt_8_ff
|
||||
if (wen[i]) begin: lt_8_wen
|
||||
ram[addr_i][8*i+7:8*i] <= data_i[8*i+7:8*i];
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
endmodule
|
||||
/*
|
||||
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 "../core/defines.sv"
|
||||
|
||||
|
||||
module gen_ram #(
|
||||
parameter DP = 512,
|
||||
parameter DW = 32,
|
||||
parameter MW = 4,
|
||||
parameter AW = 32)(
|
||||
|
||||
input wire clk,
|
||||
input wire[AW-1:0] addr_i,
|
||||
input wire[DW-1:0] data_i,
|
||||
input wire[MW-1:0] sel_i,
|
||||
input wire we_i,
|
||||
|
||||
output wire[DW-1:0] data_o
|
||||
|
||||
);
|
||||
|
||||
reg[DW-1:0] ram [0:DP-1];
|
||||
reg[AW-1:0] addr_r;
|
||||
wire[MW-1:0] wen;
|
||||
wire ren;
|
||||
|
||||
assign ren = (~we_i);
|
||||
assign wen = ({MW{we_i}} & sel_i);
|
||||
|
||||
always @ (posedge clk) begin
|
||||
if (ren) begin
|
||||
addr_r <= addr_i;
|
||||
end
|
||||
end
|
||||
|
||||
assign data_o = ram[addr_r];
|
||||
|
||||
genvar i;
|
||||
|
||||
generate
|
||||
for (i = 0; i < MW; i = i + 1) begin: sel_width
|
||||
if ((8 * i + 8) > DW) begin: i_gt_8
|
||||
always @ (posedge clk) begin: i_gt_8_ff
|
||||
if (wen[i]) begin: gt_8_wen
|
||||
ram[addr_i][DW-1:8*i] <= data_i[DW-1:8*i];
|
||||
end
|
||||
end
|
||||
end else begin: i_lt_8
|
||||
always @ (posedge clk) begin: i_lt_8_ff
|
||||
if (wen[i]) begin: lt_8_wen
|
||||
ram[addr_i][8*i+7:8*i] <= data_i[8*i+7:8*i];
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
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");
|
||||
end
|
||||
end
|
||||
|
||||
/*
|
||||
always @(posedge clk_i or negedge rst_ni) begin
|
||||
if (!rst_ni) begin
|
||||
|
||||
|
@ -65,7 +65,7 @@ module tb_top_verilator #(
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
*/
|
||||
tinyriscv_soc_top u_tinyriscv_soc_top(
|
||||
.clk(clk_i),
|
||||
.rst_ext_ni(rst_ni)
|
||||
|
|
Loading…
Reference in New Issue