734 lines
15 KiB
Verilog
734 lines
15 KiB
Verilog
/*
|
|
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.
|
|
*/
|
|
|
|
`timescale 1 ns / 1 ps
|
|
|
|
`include "defines.v"
|
|
|
|
|
|
`define JTAG_CLK 500 // 1MHz. This value do not less than 100
|
|
|
|
|
|
module jtag_tb;
|
|
|
|
reg clk;
|
|
reg rst_n;
|
|
|
|
reg TCK;
|
|
reg TMS;
|
|
reg TDI;
|
|
wire TDO;
|
|
|
|
reg[39:0] shift_reg;
|
|
reg in;
|
|
reg[39:0] resp_data;
|
|
|
|
|
|
always #10 clk = ~clk; // core clock = 50MHz
|
|
|
|
|
|
integer i;
|
|
integer j;
|
|
|
|
|
|
task tap_reset;
|
|
begin
|
|
for (i = 0; i < 8; i = i + 1) begin
|
|
TMS = 1;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
end
|
|
end
|
|
endtask
|
|
|
|
task select_ir;
|
|
input[39:0] ir;
|
|
|
|
begin
|
|
// IR
|
|
shift_reg = ir;
|
|
|
|
// IDLE
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// SELECT-DR
|
|
TMS = 1;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// SELECT-IR
|
|
TMS = 1;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// CAPTURE-IR
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// SHIFT-IR
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// SHIFT-IR & EXIT1-IR
|
|
for (i = 5; i > 0; i = i - 1) begin
|
|
if (shift_reg[0] == 1'b1)
|
|
TDI = 1'b1;
|
|
else
|
|
TDI = 1'b0;
|
|
|
|
if (i == 1)
|
|
TMS = 1;
|
|
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
in = TDO;
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
shift_reg = {{(35){1'b0}}, in, shift_reg[4:1]};
|
|
end
|
|
|
|
// PAUSE-IR
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// EXIT2-IR
|
|
TMS = 1;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// UPDATE-IR
|
|
TMS = 1;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// IDLE
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// IDLE
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// IDLE
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// IDLE
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// IDLE
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
end
|
|
endtask
|
|
|
|
task dmi_write;
|
|
input[5:0] addr;
|
|
input[31:0] data;
|
|
output[39:0] out;
|
|
|
|
begin
|
|
// op write
|
|
shift_reg = {addr, data, 2'b10};
|
|
|
|
// SELECT-DR
|
|
TMS = 1;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// CAPTURE-DR
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// SHIFT-DR
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// SHIFT-DR & EXIT1-DR
|
|
for (i = 40; i > 0; i = i - 1) begin
|
|
if (shift_reg[0] == 1'b1)
|
|
TDI = 1'b1;
|
|
else
|
|
TDI = 1'b0;
|
|
|
|
if (i == 1)
|
|
TMS = 1;
|
|
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
in = TDO;
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
shift_reg = {in, shift_reg[39:1]};
|
|
end
|
|
|
|
// PAUSE-DR
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// EXIT2-DR
|
|
TMS = 1;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// UPDATE-DR
|
|
TMS = 1;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// IDLE
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// IDLE
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// IDLE
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// IDLE
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// IDLE
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// op nop
|
|
shift_reg = {addr, {(32){1'b0}}, 2'b00};
|
|
|
|
// SELECT-DR
|
|
TMS = 1;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// CAPTURE-DR
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// SHIFT-DR
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// SHIFT-DR & EXIT1-DR
|
|
for (i = 40; i > 0; i = i - 1) begin
|
|
if (shift_reg[0] == 1'b1)
|
|
TDI = 1'b1;
|
|
else
|
|
TDI = 1'b0;
|
|
|
|
if (i == 1)
|
|
TMS = 1;
|
|
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
in = TDO;
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
shift_reg = {in, shift_reg[39:1]};
|
|
end
|
|
|
|
// PAUSE-DR
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// EXIT2-DR
|
|
TMS = 1;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// UPDATE-DR
|
|
TMS = 1;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// IDLE
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// IDLE
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// IDLE
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// IDLE
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// IDLE
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
out = shift_reg;
|
|
end
|
|
endtask
|
|
|
|
task dmi_read;
|
|
input[5:0] addr;
|
|
output[39:0] out;
|
|
|
|
begin
|
|
// op read
|
|
shift_reg = {addr, {(32){1'b0}}, 2'b01};
|
|
|
|
// SELECT-DR
|
|
TMS = 1;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// CAPTURE-DR
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// SHIFT-DR
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// SHIFT-DR & EXIT1-DR
|
|
for (i = 40; i > 0; i = i - 1) begin
|
|
if (shift_reg[0] == 1'b1)
|
|
TDI = 1'b1;
|
|
else
|
|
TDI = 1'b0;
|
|
|
|
if (i == 1)
|
|
TMS = 1;
|
|
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
in = TDO;
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
shift_reg = {in, shift_reg[39:1]};
|
|
end
|
|
|
|
// PAUSE-DR
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// EXIT2-DR
|
|
TMS = 1;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// UPDATE-DR
|
|
TMS = 1;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// IDLE
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// IDLE
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// IDLE
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// IDLE
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// IDLE
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// op nop
|
|
shift_reg = {addr, {(32){1'b0}}, 2'b00};
|
|
|
|
// SELECT-DR
|
|
TMS = 1;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// CAPTURE-DR
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// SHIFT-DR
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// SHIFT-DR & EXIT1-DR
|
|
for (i = 40; i > 0; i = i - 1) begin
|
|
if (shift_reg[0] == 1'b1)
|
|
TDI = 1'b1;
|
|
else
|
|
TDI = 1'b0;
|
|
|
|
if (i == 1)
|
|
TMS = 1;
|
|
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
in = TDO;
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
shift_reg = {in, shift_reg[39:1]};
|
|
end
|
|
|
|
// PAUSE-DR
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// EXIT2-DR
|
|
TMS = 1;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// UPDATE-DR
|
|
TMS = 1;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// IDLE
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// IDLE
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// IDLE
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// IDLE
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
// IDLE
|
|
TMS = 0;
|
|
TCK = 0;
|
|
#`JTAG_CLK
|
|
TCK = 1;
|
|
#`JTAG_CLK
|
|
TCK = 0;
|
|
|
|
out = shift_reg;
|
|
end
|
|
endtask
|
|
|
|
|
|
initial begin
|
|
clk = 0;
|
|
rst_n = 1'b1;
|
|
|
|
TCK = 1;
|
|
TMS = 1;
|
|
TDI = 1;
|
|
shift_reg = 40'h0;
|
|
resp_data = 40'h0;
|
|
in = 1'b0;
|
|
|
|
$display("test running...");
|
|
#100
|
|
rst_n = 1'b0;
|
|
#100
|
|
rst_n = 1'b1;
|
|
#200
|
|
|
|
/*************************** start test ***************************/
|
|
// reset TAP state machine
|
|
tap_reset();
|
|
// select dm regs
|
|
select_ir(40'b10001);
|
|
// reset dm module
|
|
dmi_write(6'h10, 32'h0, resp_data);
|
|
|
|
// read dmstatus reg
|
|
dmi_read(6'h11, resp_data);
|
|
$display("dmstatus = 0x%x", resp_data[33:2]);
|
|
|
|
// write data to memory
|
|
dmi_write(6'h38, 32'h20050404, resp_data); // write sbcs
|
|
dmi_write(6'h39, 32'h0, resp_data); // write sbaddress0
|
|
for (j = 0; j < 5; j = j + 1) begin
|
|
$display("write: addr = 0x%x, data = 0x%x", j * 4, 32'h0 + j);
|
|
dmi_write(6'h3c, 32'h0 + j, resp_data); // write sbdata0
|
|
end
|
|
|
|
// read data from memory
|
|
dmi_write(6'h38, 32'h20158404, resp_data); // write sbcs
|
|
dmi_write(6'h39, 32'h0, resp_data); // write sbaddress0
|
|
for (j = 0; j < 5; j = j + 1) begin
|
|
dmi_read(6'h3c, resp_data); // read sbdata0
|
|
$display("read: addr = 0x%x, data = 0x%x", j * 4, resp_data[33:2]);
|
|
end
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// Check whether the data read is equal to the data written.
|
|
///////////////////////////////////////////////////////////
|
|
|
|
$finish;
|
|
end
|
|
|
|
|
|
// sim timeout
|
|
initial begin
|
|
#10000000
|
|
$display("Time Out.");
|
|
$finish;
|
|
end
|
|
|
|
// generate wave file, used by gtkwave
|
|
initial begin
|
|
$dumpfile("jtag_tb.vcd");
|
|
$dumpvars(0, jtag_tb);
|
|
end
|
|
|
|
tinyriscv_soc_top tinyriscv_soc_top_0(
|
|
.clk(clk),
|
|
.rst_ext_i(rst_n),
|
|
.jtag_TCK(TCK),
|
|
.jtag_TMS(TMS),
|
|
.jtag_TDI(TDI),
|
|
.jtag_TDO(TDO)
|
|
);
|
|
|
|
endmodule
|