Skip to content

Commit

Permalink
test for bare minipit, more assertions, enable wire
Browse files Browse the repository at this point in the history
  • Loading branch information
stevej committed Oct 31, 2024
1 parent 55c39be commit 13a8565
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 63 deletions.
10 changes: 8 additions & 2 deletions src/byte_transmitter.v
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,16 @@ module byte_transmitter (
f_total_written <= f_total_written + 1;
assert (r_out != 1'bX);
assert (byte_count != 5'bX_XXXX);
assert (in[byte_count-1] != 1'bX);
assert (byte_count[0] != 1'bX);
assert (byte_count[1] != 1'bX);
assert (byte_count[2] != 1'bX);
assert (byte_count[3] != 1'bX);
assert (byte_count[4] != 1'bX);

assert (in[byte_count:(byte_count-1)] != 1'bX);
`endif
r_out <= in[byte_count-1];
byte_count <= byte_count - 1;
byte_count <= (byte_count - 6'd1);
end else begin
byte_count <= 6'h20;
r_done <= 1;
Expand Down
96 changes: 62 additions & 34 deletions src/jtag.v
Original file line number Diff line number Diff line change
Expand Up @@ -19,42 +19,42 @@ module jtag (
input wire tdi,
input wire tms,
input wire trst_n,
input wire enable,
output wire tdo
);

wire trst;
assign trst = ~trst_n;

// TAP controller state
localparam [4:0] TestLogicReset = 5'h0;
localparam [4:0] RunTestOrIdle = 5'h1;
localparam [4:0] SelectDrScan = 5'h2;
localparam [4:0] SelectIrScan = 5'h3;
localparam [4:0] CaptureDr = 5'h4;
localparam [4:0] CaptureIr = 5'h5;
localparam [4:0] ShiftDr = 5'h6;
localparam [4:0] ShiftIr = 5'h7;
localparam [4:0] Exit1Dr = 5'h8;
localparam [4:0] Exit1Ir = 5'h9;
localparam [4:0] PauseDr = 5'h10;
localparam [4:0] PauseIr = 5'h11;
localparam [4:0] Exit2Dr = 5'h12;
localparam [4:0] Exit2Ir = 5'h13;
localparam [4:0] UpdateDr = 5'h14;
localparam [4:0] UpdateIr = 5'h15;
localparam bit [4:0] TestLogicReset = 5'h0;
localparam bit [4:0] RunTestOrIdle = 5'h1;
localparam bit [4:0] SelectDrScan = 5'h2;
localparam bit [4:0] SelectIrScan = 5'h3;
localparam bit [4:0] CaptureDr = 5'h4;
localparam bit [4:0] CaptureIr = 5'h5;
localparam bit [4:0] ShiftDr = 5'h6;
localparam bit [4:0] ShiftIr = 5'h7;
localparam bit [4:0] Exit1Dr = 5'h8;
localparam bit [4:0] Exit1Ir = 5'h9;
localparam bit [4:0] PauseDr = 5'h10;
localparam bit [4:0] PauseIr = 5'h11;
localparam bit [4:0] Exit2Dr = 5'h12;
localparam bit [4:0] Exit2Ir = 5'h13;
localparam bit [4:0] UpdateDr = 5'h14;
localparam bit [4:0] UpdateIr = 5'h15;

reg [4:0] current_state;

// IR Instruction values
localparam [3:0] Abort = 4'b1000;
localparam [3:0] IdCode = 4'b1110;
localparam [3:0] Bypass = 4'b1111;
localparam bit [3:0] Abort = 4'b1000;
localparam bit [3:0] IdCode = 4'b1110;
localparam bit [3:0] Bypass = 4'b1111;

reg [3:0] current_ir_instruction;
reg current_ir_instruction_broken;

// DR Register containing the IDCODE of our jtag device.
localparam [31:0] IdCodeDrRegister = 32'hFAF01;
localparam bit [31:0] IdCodeDrRegister = 32'hFAF01;

// whether a reset in the main design has been seen.
wire r_in_reset_from_main_clk;
Expand All @@ -64,7 +64,7 @@ module jtag (
reg [4:0] tms_reset_check;
reg [7:0] cycles;

wire idcode_out_done;
reg idcode_out_done;

reg byte_transmitter_enable;
reg reset_byte_transmitter;
Expand Down Expand Up @@ -103,18 +103,17 @@ module jtag (
always @(posedge tck) begin
if (trst) begin
current_state <= TestLogicReset; // State 0
current_ir_instruction_broken <= 0;
tms_reset_check <= 5'b0_0000;
cycles <= 0;
current_ir_instruction <= 4'b1110; // IDCODE is the default instruction.
cycles <= 8'b0000_0000;
current_ir_instruction <= IdCode; // IDCODE is the default instruction.
r_output_selector_transmitter <= 1; // by default the tap controller writes
tap_channel <= 0; // How can an X sneak in here?
byte_transmitter_enable <= 0;
reset_byte_transmitter <= 0;
end else begin
end else if (enable) begin
tms_reset_check <= tms_reset_check << 1;
tms_reset_check[0] <= tms;
cycles <= cycles + 1;
cycles <= cycles + 1'd1;
// TAP state machine
case (current_state)
TestLogicReset: begin // 0
Expand Down Expand Up @@ -161,7 +160,7 @@ module jtag (
endcase
end
ShiftDr: begin // 6
if (~byte_transmitter_enable) tap_channel <= 0;
if (!byte_transmitter_enable) tap_channel <= 0;
// in the Shift-DR state, this data is shifted out, least significant bit first
// Pretty sure this means connect a shift register to TDO and drain it
case (tms)
Expand All @@ -175,12 +174,12 @@ module jtag (
if (~idcode_out_done) begin
current_state <= ShiftDr;
end else begin
reset_byte_transmitter <= 1;
byte_transmitter_enable <= 0;
current_state <= Exit1Dr; // Not sure if this is correct.
end
end
default: begin
current_ir_instruction_broken <= 1;
current_state <= ShiftDr;
end
endcase
Expand Down Expand Up @@ -255,6 +254,8 @@ module jtag (
current_state <= TestLogicReset;
end
endcase
end else begin
current_state <= TestLogicReset;
end
end

Expand All @@ -269,7 +270,10 @@ module jtag (
always @(posedge tck) f_past_valid <= 1;

always_comb begin
if (!f_past_valid) assume (trst);
if (!f_past_valid) begin
assume (trst);
assume (enable);
end
end

always @(posedge tck) begin
Expand All @@ -279,12 +283,36 @@ module jtag (
cover (current_state <= UpdateIr);
end

if (f_past_valid && $past(trst_n)) begin
if (f_past_valid && $past(trst)) begin
assume (trst);
assume (enable);
assert (current_state == 5'b0_0000);
/*
assert (current_state != 5'bX_XXXX);
assert (r_output_selector_transmitter != 1'bX);
assert (transmitter_channel != 1'bX);
assert (tdo != 1'bX);
// TODO: the next 16 lines are a horrible crime.
assert (current_state[0] != 1'bX);
assert (current_state[1] != 1'bX);
assert (current_state[2] != 1'bX);
assert (current_state[3] != 1'bX);
assert (current_state[4] != 1'bX);
assert (current_state[5] != 1'bX);
assert (current_state[6] != 1'bX);
assert (current_state[7] != 1'bX);
assert (current_state[8] != 1'bX);
assert (current_state[9] != 1'bX);
assert (current_state[10] != 1'bX);
assert (current_state[11] != 1'bX);
assert (current_state[12] != 1'bX);
assert (current_state[13] != 1'bX);
assert (current_state[14] != 1'bX);
assert (current_state[15] != 1'bX);
*/

assert (r_output_selector_transmitter == 1'b1);
assert (transmitter_channel == 1'b0);
assert (tdo == 1'b0);
assert (byte_transmitter_enable == 1'b0);
//assert ( != 1'bX);
end
end

Expand Down
28 changes: 6 additions & 22 deletions src/minipit.v
Original file line number Diff line number Diff line change
Expand Up @@ -6,51 +6,39 @@
module minipit (
input clk,
input rst_n,
input enable,
input write_enable,
input repeating,
input [7:0] counter_high,
input [7:0] counter_low,
input divider_on,
output wire interrupting
);

wire reset = !rst_n;

reg r_interrupting;
wire counter_set;
reg r_counter_set;
assign counter_set = r_counter_set;
assign counter_set = r_counter_set;

reg r_interrupting;
assign interrupting = r_interrupting;

// counter derived from config byte 1 concatenated with config byte 0
reg [15:0] counter;
reg [15:0] current_count;

// A counter to use when the divider is enabled
reg [ 7:0] divider_count;

always @(posedge clk) begin
if (reset) begin
if (!rst_n) begin
counter <= 16'd10; // TODO: don't auto-set a counter
current_count <= 16'd0;
r_counter_set <= 1; // TODO: don't auto-enable a default counter
divider_count <= 0;
r_interrupting <= 0;
end else begin
end else if (enable) begin
if (write_enable) begin
counter <= {counter_high, counter_low};
end else begin
r_counter_set <= 1;
end

if (counter_set && divider_on) begin
divider_count <= divider_count + 1;
if (divider_count == 10) begin
divider_count <= 0; // reset
current_count <= current_count + 1;
end
end else if (counter_set) begin
if (counter_set) begin
current_count <= current_count + 1;
end else begin
current_count <= current_count;
Expand All @@ -63,10 +51,6 @@ module minipit (
current_count <= 0;
end

// on a rollover of divider_count, reset the interrupt
if (divider_on && (divider_count > 0)) begin
r_interrupting <= 0;
end
end else begin
r_interrupting <= 0;
end
Expand Down
7 changes: 4 additions & 3 deletions src/project.v
Original file line number Diff line number Diff line change
Expand Up @@ -42,23 +42,24 @@ module tt_um_jtag_example_stevej (
.tdi(ui_in[1]),
.tms(ui_in[2]),
.trst_n(ui_in[3]),
.enable(ena),
.tdo(tdo)
);

// A hard configured interrupt rising high every 10 cycles for 1 cycle.
minipit minipit0 (
.clk(clk),
.rst_n(rst_n),
.enable(ena),
.write_enable(1'b1),
.repeating(1'b1),
.counter_high(8'b0),
.counter_high(8'b0), // 0x0 + 0xA == 10 decimal
.counter_low(8'hA),
.divider_on(1'b0),
.interrupting(interrupting)
);

// Set unused wires
//assign uio_out[7:1] = 7'b000_0000;
assign uio_out[7:1] = 7'b000_0000;

// List all unused inputs to prevent warnings
wire _unused = &{ena, ui_in, uio_in};
Expand Down
30 changes: 28 additions & 2 deletions test/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,34 @@
from cocotb.clock import Clock
from cocotb.triggers import ClockCycles

@cocotb.test()
async def test_minipit_fires_every_ten_cycles(dut):
dut._log.info("Start")
clock = Clock(dut.clk, 3, units="us")
cocotb.start_soon(clock.start())
dut._log.info("Reset the interrupt timer")
dut.ena.value = 1
dut.ui_in.value = 0
dut.uio_in.value = 0
dut.rst_n.value = 1
# We start with TRST being high per the spec.
dut.ui_in.value = 0b0000_1000

await ClockCycles(dut.clk, 1)
dut.rst_n.value = 0
await ClockCycles(dut.clk, 1)
dut.rst_n.value = 1
# We need one cycle for interrupt setup
await ClockCycles(dut.clk, 1)
# TODO: fix uo_out[7] being X
#assert dut.uo_out.value == 0x0
assert dut.uo_out.value[0] == 0x0
# After 10 clock cycles, minipit fires
for i in range(5):
await ClockCycles(dut.clk, 10)
assert dut.uo_out.value[0] == 0x1


# For reference, the pinout is:
# .tck(ui_in[0]),
# .tdi(ui_in[1]),
Expand All @@ -27,8 +55,6 @@ async def test_tms_five_high_for_reset(dut):
dut.rst_n.value = 0
await ClockCycles(dut.clk, 1)
dut.rst_n.value = 1
#dut.ui_in.value = 0b0000_1000
#await ClockCycles(dut.clk, 1)

# Drive TRST low and TCK high then low to reset tap controller
dut._log.info("Reset the jtag tap controller")
Expand Down

0 comments on commit 13a8565

Please sign in to comment.