Added JTAG interface with testbench
This commit is contained in:
131
rtl/toplevel/top_jtag.v
Normal file
131
rtl/toplevel/top_jtag.v
Normal 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
|
||||
Reference in New Issue
Block a user