Added JTAG interface with testbench

This commit is contained in:
2026-02-23 15:37:49 +01:00
parent 20cfece6e3
commit 8f4e887b9d
12 changed files with 731 additions and 24 deletions

131
rtl/toplevel/top_jtag.v Normal file
View File

@@ -0,0 +1,131 @@
module top_jtag(
input wire aclk,
input wire aresetn,
output wire led_green,
output wire led_red,
output wire [7:0] LED,
output wire [5:0] r2r
);
// Clocking
wire clk_100;
wire clk_15;
assign clk_100 = aclk;
clk_gen clocking(
.clk_in(clk_100),
.clk_out_15(clk_15)
);
localparam integer JTAG_DATA_BITS = 8;
wire [JTAG_DATA_BITS-1:0] jtag_data;
jtag_write_reg #(
.DATA_BITS(JTAG_DATA_BITS),
.CHAIN(1)
) jtag_writer (
.clk_i(clk_15),
.rst_n_i(aresetn),
.data_o(jtag_data)
);
assign LED = jtag_data[7:0];
assign led_green = jtag_data[0];
assign led_red = jtag_data[7];
assign r2r = jtag_data[5:0];
endmodule
module jtag_write_reg #(
parameter integer DATA_BITS = 8,
parameter integer CHAIN = 1
)(
input wire clk_i,
input wire rst_n_i,
output reg [DATA_BITS-1:0] data_o
);
wire jtag_tck;
wire jtag_tdi;
wire jtag_drck;
wire jtag_capture;
wire jtag_shift;
wire jtag_update;
wire jtag_runtest;
wire jtag_reset;
wire jtag_sel;
reg [DATA_BITS-1:0] shift_q;
reg [DATA_BITS-1:0] data_jtag_q;
reg update_toggle_jtag_q;
reg update_toggle_meta_q;
reg update_toggle_sync_q;
reg update_toggle_sync_d_q;
reg [DATA_BITS-1:0] data_meta_q;
reg [DATA_BITS-1:0] data_sync_q;
jtag_if #(
.chain(CHAIN)
) jtag (
.i_tdo(shift_q[0]),
.o_tck(jtag_tck),
.o_tdi(jtag_tdi),
.o_drck(jtag_drck),
.o_capture(jtag_capture),
.o_shift(jtag_shift),
.o_update(jtag_update),
.o_runtest(jtag_runtest),
.o_reset(jtag_reset),
.o_sel(jtag_sel)
);
always @(posedge jtag_drck or posedge jtag_reset or negedge rst_n_i) begin
if (!rst_n_i || jtag_reset) begin
shift_q <= {DATA_BITS{1'b0}};
end else if (jtag_sel && jtag_capture) begin
shift_q <= data_jtag_q;
end else if (jtag_sel && jtag_shift) begin
if (DATA_BITS == 1) begin
shift_q <= jtag_tdi;
end else begin
shift_q <= {jtag_tdi, shift_q[DATA_BITS-1:1]};
end
end
end
always @(posedge jtag_update or posedge jtag_reset or negedge rst_n_i) begin
if (!rst_n_i || jtag_reset) begin
data_jtag_q <= {DATA_BITS{1'b0}};
update_toggle_jtag_q <= 1'b0;
end else if (jtag_sel) begin
data_jtag_q <= shift_q;
update_toggle_jtag_q <= ~update_toggle_jtag_q;
end
end
// CDC into clk_i domain: toggle synchronize + stable data sampling.
always @(posedge clk_i or negedge rst_n_i) begin
if (!rst_n_i) begin
update_toggle_meta_q <= 1'b0;
update_toggle_sync_q <= 1'b0;
update_toggle_sync_d_q <= 1'b0;
data_meta_q <= {DATA_BITS{1'b0}};
data_sync_q <= {DATA_BITS{1'b0}};
data_o <= {DATA_BITS{1'b0}};
end else begin
update_toggle_meta_q <= update_toggle_jtag_q;
update_toggle_sync_q <= update_toggle_meta_q;
update_toggle_sync_d_q <= update_toggle_sync_q;
data_meta_q <= data_jtag_q;
data_sync_q <= data_meta_q;
if (update_toggle_sync_q ^ update_toggle_sync_d_q) begin
data_o <= data_sync_q;
end
end
end
// Not used for this simple write-register, but kept for completeness.
wire _unused_tck;
wire _unused_runtest;
assign _unused_tck = jtag_tck;
assign _unused_runtest = jtag_runtest;
endmodule