Skip to content

Commit

Permalink
beginning the full shift to SystemVerilog: change fpga Makefile, use …
Browse files Browse the repository at this point in the history
…unique case, remember to undef macros
  • Loading branch information
stevej committed Nov 6, 2024
1 parent dcb2296 commit f0e72f1
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 49 deletions.
13 changes: 6 additions & 7 deletions src/byte_transmitter.v
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@
// Given a byte, writes out 1 bit at a time while enable is high.
// Assumes the caller is tracking when 8 bits is sent.
module byte_transmitter (
`ifdef FORMAL
(*gclk*)
`endif
input wire clk,
`ifdef FORMAL (*gclk*)
`endif
input wire clk_tck,
input wire reset,
input wire enable,
// TODO: make size configurable
Expand All @@ -29,7 +28,7 @@ module byte_transmitter (

// TDO must be written on the falling edge
// to avoid hold violations.
always @(negedge clk) begin
always @(negedge clk_tck) begin
if (reset) begin
byte_count <= 6'h20;
r_done <= 1'b0;
Expand Down Expand Up @@ -71,9 +70,9 @@ module byte_transmitter (
f_past_valid = 0;
end

always @(posedge clk) f_past_valid <= 1;
always @(posedge clk_tck) f_past_valid <= 1;

always @(posedge clk) begin
always @(posedge clk_tck) begin
assume (reset);

if (f_past_valid && enable && done) begin
Expand Down
2 changes: 1 addition & 1 deletion src/fpga/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ PACKAGE = sg48
all: $(PROJ).rpt $(PROJ).bin

%.json: %.v
yosys -g -p 'synth_ice40 -top tt_fpga_top -json $@' $<
yosys -g -f 'verilog -sv' -p 'synth_ice40 -top tt_fpga_top -json $@' $<

%.asc: $(PIN_DEF) %.json
nextpnr-ice40 --pcf-allow-unconstrained --$(DEVICE) --package $(PACKAGE) --asc $@ --pcf $< --json $*.json
Expand Down
79 changes: 44 additions & 35 deletions src/jtag.v
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,14 @@
end;

module jtag (
`ifdef FORMAL
(*gclk*)
`endif
input wire tck,
`ifdef FORMAL (*gclk*)
`endif
input wire tck,
/* verilator lint_off UNUSED */
input wire tdi,
input wire tms,
input wire trst_n, /* TRST_N */
input wire enable,
input wire tdi,
input wire tms,
input wire trst_n, /* TRST_N */
input wire enable,
output wire tdo
);

Expand Down Expand Up @@ -75,8 +74,9 @@ module jtag (
//wire r_in_reset_from_main_clk;

// for checking that the TAP state machine is in reset at the right time.
// TODO: move this behind an `ifdef FORMAL and prefix with `f_`
reg [4:0] tms_reset_check;
`ifdef FORMAL
reg [4:0] f_tms_reset_check;
`endif
reg [7:0] cycles;

// Are we done writing the idcode?
Expand All @@ -87,7 +87,7 @@ module jtag (
wire transmitter_channel; // for byte_transmitter to write to TDO

byte_transmitter id_byte_transmitter (
.clk(tck),
.clk_tck(tck),
.reset(~trst_n | reset_byte_transmitter),
.enable(byte_transmitter_enable),
.in(IdCodeDrRegister),
Expand Down Expand Up @@ -125,7 +125,9 @@ module jtag (
in_exit1_dr <= 1'b0;

current_state <= TestLogicReset; // State 0
tms_reset_check <= 5'h0;
`ifdef FORMAL
f_tms_reset_check <= 5'h0;
`endif
cycles <= 8'h0;
current_ir_instruction <= IdCode; // IDCODE is the default instruction.
r_output_selector_transmitter <= 1'b1; // by default the tap controller writes
Expand All @@ -139,49 +141,53 @@ module jtag (
in_exit1_dr <= 1'b0;

current_state <= current_state;
tms_reset_check <= tms_reset_check << 1;
tms_reset_check[0] <= tms;
`ifdef FORMAL
f_tms_reset_check <= f_tms_reset_check << 1;
f_tms_reset_check[0] <= tms;
`endif
cycles <= cycles + 1'd1;
current_ir_instruction <= current_ir_instruction;
r_output_selector_transmitter <= r_output_selector_transmitter;
byte_transmitter_enable <= byte_transmitter_enable;
reset_byte_transmitter <= reset_byte_transmitter;
// TAP state machine
case (current_state)
unique case (current_state)
TestLogicReset: begin // 0
tms_reset_check <= 5'h0;
case (tms)
`ifdef FORMAL
f_tms_reset_check <= 5'h0;
`endif
unique case (tms)
1: current_state <= TestLogicReset;
default: current_state <= RunTestOrIdle;
endcase
end
RunTestOrIdle: begin // 1
in_run_test_idle <= 1'b1;
case (tms)
unique case (tms)
1: current_state <= SelectDrScan;
default: current_state <= RunTestOrIdle;
endcase
end
SelectDrScan: begin // 2
in_select_dr_scan <= 1'b1;
case (tms)
unique case (tms)
1: current_state <= SelectIrScan;
default: current_state <= CaptureDr;
endcase
end
SelectIrScan: begin // 3
case (tms)
unique case (tms)
1: current_state <= TestLogicReset;
default: current_state <= CaptureIr;
endcase
end
CaptureDr: begin // 4
in_capture_dr <= 1'b1;
case (tms)
unique case (tms)
1: current_state <= Exit1Dr;
default: begin
current_state <= ShiftDr;
case (current_ir_instruction)
unique case (current_ir_instruction)
IdCode: begin
// place the byte transmitter with the IDCODE register and start to shift it onto TDO.
r_output_selector_transmitter <= 1'b0;
Expand All @@ -202,7 +208,7 @@ module jtag (
endcase
end
CaptureIr: begin // 5
case (tms)
unique case (tms)
1: current_state <= Exit1Ir;
default: current_state <= ShiftIr;
endcase
Expand All @@ -211,10 +217,10 @@ module jtag (
in_shift_dr <= 1'b1;
// 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)
unique case (tms)
1: current_state <= Exit1Dr;
default: begin
case (current_ir_instruction)
unique case (current_ir_instruction)
IdCode: begin
if (!idcode_out_done) begin
current_state <= ShiftDr;
Expand All @@ -234,56 +240,56 @@ module jtag (
endcase
end
ShiftIr: begin // 7
case (tms)
unique case (tms)
1: current_state <= Exit1Ir;
default: current_state <= ShiftIr;
endcase
end
Exit1Dr: begin // 8
in_exit1_dr <= 1'b1;
case (tms)
unique case (tms)
1: current_state <= UpdateDr;
default: current_state <= PauseDr;
endcase
end
Exit1Ir: begin // 9
case (tms)
unique case (tms)
1: current_state <= UpdateIr;
default: current_state <= PauseIr;
endcase
end
PauseDr: begin // 10
case (tms)
unique case (tms)
1: current_state <= Exit2Dr;
default: current_state <= PauseDr;
endcase
end
PauseIr: begin // 11
case (tms)
unique case (tms)
1: current_state <= Exit2Ir;
default: current_state <= PauseIr;
endcase
end
Exit2Dr: begin // 12
case (tms)
unique case (tms)
1: current_state <= UpdateDr;
default: current_state <= ShiftDr;
endcase
end
Exit2Ir: begin // 13
case (tms)
unique case (tms)
1: current_state <= UpdateIr;
default: current_state <= ShiftIr;
endcase
end
UpdateDr: begin // 14
case (tms)
unique case (tms)
1: current_state <= SelectDrScan;
default: current_state <= RunTestOrIdle;
endcase
end
UpdateIr: begin // 15
case (tms)
unique case (tms)
1: current_state <= SelectDrScan;
default: current_state <= RunTestOrIdle;
endcase
Expand Down Expand Up @@ -325,7 +331,7 @@ module jtag (

always @(posedge tck) begin
// Whenever TMS is high for five cycles, the design is in reset
if (f_past_valid && $past(~trst_n) && trst_n && ($past(tms_reset_check) == 5'b1_1111)) begin
if (f_past_valid && $past(~trst_n) && trst_n && ($past(f_tms_reset_check) == 5'b1_1111)) begin
assert (current_state == TestLogicReset);
end

Expand Down Expand Up @@ -391,5 +397,8 @@ module jtag (

end
`endif
`undef HAPPENS_BEFORE
`undef STATE_EXITS

endmodule
`endif
12 changes: 6 additions & 6 deletions test/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from cocotb.clock import Clock
from cocotb.triggers import ClockCycles

@cocotb.test()
#@cocotb.test()
async def test_minipit_fires_every_ten_cycles(dut):
dut._log.info("Start")
clock = Clock(dut.clk, 3, units="us")
Expand Down Expand Up @@ -46,7 +46,7 @@ async def test_minipit_fires_every_ten_cycles(dut):
# .tdi(ui_in[1]),
# .tms(ui_in[2]),
# .trst(ui_in[3]),
@cocotb.test()
#@cocotb.test()
async def test_tms_five_high_for_reset(dut):
dut._log.info("Start")
clock = Clock(dut.clk, 3, units="us")
Expand All @@ -56,7 +56,7 @@ async def test_tms_five_high_for_reset(dut):
dut.ui_in.value = 0
dut.uio_in.value = 0
dut.rst_n.value = 1

dut.ui_in.value = 0b0000_1000
await ClockCycles(dut.clk, 1)
dut.rst_n.value = 0
await ClockCycles(dut.clk, 1)
Expand Down Expand Up @@ -105,7 +105,7 @@ async def test_tms_five_high_for_reset(dut):
@cocotb.test()
async def test_idcode(dut):
dut._log.info("Start")
clock = Clock(dut.clk, 1, units="us")
clock = Clock(dut.clk, 3, units="us")
cocotb.start_soon(clock.start())
dut._log.info("Reset the part")
dut.ena.value = 1
Expand All @@ -128,7 +128,7 @@ async def test_idcode(dut):
dut.ui_in.value = 0b0000_1000
await ClockCycles(dut.clk, 1)

# Should be nothing on the output lines as there hasn't been enough
# Should be nothing on the output lines as there hasn't been enough cycles
# for an interrupt and we haven't changed out of the initial JTAG state.
assert dut.uo_out.value == 0x0

Expand All @@ -139,7 +139,7 @@ async def test_idcode(dut):
#
# Drive TCK and TMS into ShiftDr state
# TMS: 0 1 0 0 to get into ShiftDr
STATES = [0b0000_1001, 0b0000_1101, 0b0000_1001, 0b0000_1001]
STATES = [0b0000_1101, 0b0000_1001, 0b0000_1001] #, 0b0000_1001]
for state in STATES:
dut.ui_in.value = state
await ClockCycles(dut.clk, 1)
Expand Down

0 comments on commit f0e72f1

Please sign in to comment.