Add interface2

This commit is contained in:
Andrew Kay
2021-03-29 16:38:00 -05:00
parent fce3b4c273
commit 925830f0a4
107 changed files with 54855 additions and 24 deletions

2
interface2/fpga/tests/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
*_tb
*.vcd

View File

@@ -0,0 +1,27 @@
IVERILOG ?= iverilog
RTL = ../rtl
TESTS = $(patsubst %.v,%,$(wildcard *_tb.v))
all: test
coax_buffer_tb: coax_buffer_tb.v $(RTL)/coax_buffer.v $(RTL)/third_party/*.v
coax_buffered_rx_tb: coax_buffered_rx_tb.v $(RTL)/coax_buffered_rx.v $(RTL)/coax_rx.v $(RTL)/coax_rx_bit_timer.v $(RTL)/coax_buffer.v $(RTL)/third_party/*.v
coax_buffered_tx_tb: coax_buffered_tx_tb.v $(RTL)/coax_buffered_tx.v $(RTL)/coax_tx.v $(RTL)/coax_tx_bit_timer.v $(RTL)/coax_buffer.v $(RTL)/third_party/*.v
coax_rx_bit_timer_tb: coax_rx_bit_timer_tb.v $(RTL)/coax_rx_bit_timer.v
coax_rx_tb: coax_rx_tb.v $(RTL)/coax_rx.v $(RTL)/coax_rx_bit_timer.v
coax_tx_bit_timer_tb: coax_tx_bit_timer_tb.v $(RTL)/coax_tx_bit_timer.v
coax_tx_distorter_tb: coax_tx_distorter_tb.v $(RTL)/coax_tx_distorter.v
coax_tx_tb: coax_tx_tb.v $(RTL)/coax_tx.v $(RTL)/coax_tx_bit_timer.v
control_tb: control_tb.v $(RTL)/control.v $(RTL)/coax_buffered_tx.v $(RTL)/coax_tx.v $(RTL)/coax_tx_bit_timer.v $(RTL)/coax_buffer.v $(RTL)/third_party/*.v
test: $(TESTS)
$(foreach tb,$(TESTS),./run_test.sh $(tb);)
clean:
rm -f *_tb *.vcd
%_tb:
$(IVERILOG) -o $@ $^
.PHONY: all, clean

View File

@@ -0,0 +1,14 @@
`define assert_equal(actual, expected, message) \
if ((actual) !== expected) \
begin \
$display("[ASSERTION FAILURE] %m (%s:%0d): %s", `__FILE__, `__LINE__, message); \
$display("\tTime: %0t", $time); \
$display("\tExpected: %x", expected); \
$display("\tActual: %x", actual); \
end
`define assert_high(actual, message) \
`assert_equal(actual, 1, message)
`define assert_low(actual, message) \
`assert_equal(actual, 0, message)

View File

@@ -0,0 +1,90 @@
`default_nettype none
`include "assert.v"
module coax_buffer_tb;
reg clk = 0;
initial
begin
forever
begin
#1 clk <= ~clk;
end
end
reg reset = 0;
reg [9:0] write_data = 0;
reg write_strobe = 0;
reg read_strobe = 0;
coax_buffer #(
.DEPTH(16),
.ALMOST_EMPTY_THRESHOLD(4),
.ALMOST_FULL_THRESHOLD(12)
) dut (
.clk(clk),
.reset(reset),
.write_data(write_data),
.write_strobe(write_strobe),
.read_strobe(read_strobe)
);
initial
begin
$dumpfile("coax_buffer_tb.vcd");
$dumpvars(0, coax_buffer_tb);
test_1;
$finish;
end
task test_1;
begin
$display("START: test_1");
write_data = 0;
write_strobe = 0;
read_strobe = 0;
dut_reset;
#16;
repeat (16)
begin
write_strobe = 1;
#2;
write_strobe = 0;
#2;
write_data = write_data + 1;
end
#16;
repeat (16)
begin
read_strobe = 1;
#2;
read_strobe = 0;
#2;
end
#64;
$display("END: test_1");
end
endtask
task dut_reset;
begin
reset = 1;
#2;
reset = 0;
end
endtask
endmodule

View File

@@ -0,0 +1,169 @@
`default_nettype none
`include "assert.v"
`include "mock_tx.v"
module coax_buffered_rx_tb;
reg clk = 0;
initial
begin
forever
begin
#1 clk <= ~clk;
end
end
wire rx;
mock_tx mock_tx (
.tx(rx)
);
reg reset = 0;
reg read_strobe = 0;
coax_buffered_rx #(
.CLOCKS_PER_BIT(8),
.DEPTH(8)
) dut (
.clk(clk),
.reset(reset),
.rx(rx),
.read_strobe(read_strobe),
.parity(1'b1)
);
initial
begin
$dumpfile("coax_buffered_rx_tb.vcd");
$dumpvars(0, coax_buffered_rx_tb);
test_1;
test_2;
test_3;
$finish;
end
task test_1;
begin
$display("START: test_1");
dut_reset;
#2;
mock_tx.tx_start_sequence;
mock_tx.tx_word(10'b0000000001, 0);
mock_tx.tx_word(10'b0000000010, 0);
mock_tx.tx_word(10'b0000000011, 1);
mock_tx.tx_word(10'b0000000100, 0);
mock_tx.tx_word(10'b0000000101, 1);
mock_tx.tx_word(10'b0000000110, 1);
mock_tx.tx_word(10'b0000000111, 0);
mock_tx.tx_word(10'b0000001000, 0);
mock_tx.tx_end_sequence;
#8;
`assert_high(dut.full, "full should be HIGH");
`assert_low(dut.empty, "empty should be LOW");
`assert_low(dut.error, "error should be LOW");
repeat (8)
begin
read_strobe = 1;
#2;
read_strobe = 0;
#8;
end
`assert_low(dut.full, "full should be LOW");
`assert_high(dut.empty, "empty should be HIGH");
#64;
$display("END: test_1");
end
endtask
task test_2;
begin
$display("START: test_2");
dut_reset;
#2;
mock_tx.tx_start_sequence;
mock_tx.tx_word(10'b0000000001, 0);
mock_tx.tx_word(10'b0000000010, 0);
mock_tx.tx_word(10'b0000000011, 1);
mock_tx.tx_word(10'b0000000100, 0);
mock_tx.tx_end_sequence;
#8;
`assert_low(dut.error, "error should be LOW");
mock_tx.tx_start_sequence;
mock_tx.tx_word(10'b0000000101, 1);
mock_tx.tx_end_sequence;
#8;
`assert_high(dut.error, "error should be HIGH");
`assert_equal(dut.data, dut.ERROR_OVERFLOW, "error should be ERROR_OVERFLOW");
#64;
$display("END: test_2");
end
endtask
task test_3;
begin
$display("START: test_3");
dut_reset;
#2;
mock_tx.tx_start_sequence;
repeat (9)
begin
mock_tx.tx_word(10'b0000000000, 1);
end
mock_tx.tx_end_sequence;
#8;
`assert_high(dut.error, "error should be HIGH");
`assert_equal(dut.data, dut.ERROR_OVERFLOW, "error should be ERROR_OVERFLOW");
`assert_high(dut.full, "full should be HIGH");
`assert_low(dut.empty, "empty should be LOW");
#64;
$display("END: test_3");
end
endtask
task dut_reset;
begin
reset = 1;
#2;
reset = 0;
end
endtask
endmodule

View File

@@ -0,0 +1,138 @@
`default_nettype none
`include "assert.v"
module coax_buffered_tx_tb;
reg clk = 0;
initial
begin
forever
begin
#1 clk <= ~clk;
end
end
reg reset = 0;
reg [9:0] data;
reg load_strobe = 0;
reg start_strobe = 0;
coax_buffered_tx #(
.CLOCKS_PER_BIT(8),
.DEPTH(8),
.START_DEPTH(4)
) dut (
.clk(clk),
.reset(reset),
.data(data),
.load_strobe(load_strobe),
.start_strobe(start_strobe),
.parity(1'b1)
);
initial
begin
$dumpfile("coax_buffered_tx_tb.vcd");
$dumpvars(0, coax_buffered_tx_tb);
test_1;
test_2;
$finish;
end
task test_1;
begin
$display("START: test_1");
dut_reset;
#8;
data = 10'b0101110101;
load_strobe = 1;
#2;
load_strobe = 0;
#8;
data = 10'b1010001110;
load_strobe = 1;
#2;
load_strobe = 0;
#8;
data = 10'b0101110101;
load_strobe = 1;
#2;
load_strobe = 0;
#8;
start_strobe = 1;
#2;
start_strobe = 0;
#1000;
$display("END: test_1");
end
endtask
task test_2;
begin
$display("START: test_2");
dut_reset;
#8;
data = 10'b0101110101;
load_strobe = 1;
#2;
load_strobe = 0;
#8;
data = 10'b1010001110;
load_strobe = 1;
#2;
load_strobe = 0;
#8;
data = 10'b0101110101;
load_strobe = 1;
#2;
load_strobe = 0;
#8;
data = 10'b1010001110;
load_strobe = 1;
#2;
load_strobe = 0;
#8;
data = 10'b0101110101;
load_strobe = 1;
#2;
load_strobe = 0;
#1200;
$display("END: test_2");
end
endtask
task dut_reset;
begin
reset = 1;
#2;
reset = 0;
end
endtask
endmodule

View File

@@ -0,0 +1,75 @@
`default_nettype none
`include "mock_tx.v"
module coax_rx_bit_timer_tb;
reg clk = 0;
initial
begin
forever
begin
#1 clk <= ~clk;
end
end
wire rx;
mock_tx mock_tx (
.tx(rx)
);
reg reset = 0;
wire sample;
wire synchronized;
coax_rx_bit_timer #(
.CLOCKS_PER_BIT(8)
) dut (
.clk(clk),
.rx(rx),
.reset(reset),
.sample(sample),
.synchronized(synchronized)
);
initial
begin
$dumpfile("coax_rx_bit_timer_tb.vcd");
$dumpvars(0, coax_rx_bit_timer_tb);
// Idle
#32;
// Perfect
mock_tx.tx_bit(1);
mock_tx.tx_bit(0);
mock_tx.tx_bit(1);
// Delayed
mock_tx.tx_bit_custom(0, 9, 8);
// Shortened
mock_tx.tx_bit_custom(0, 6, 7);
// Stuck
mock_tx.tx_bit_custom(1, 24, 8);
// Reset
dut_reset;
mock_tx.tx_bit(1);
#32;
$finish;
end
task dut_reset;
begin
reset = 1;
#2;
reset = 0;
end
endtask
endmodule

View File

@@ -0,0 +1,492 @@
`default_nettype none
`include "assert.v"
`include "mock_tx.v"
module coax_rx_tb;
reg clk = 0;
initial
begin
forever
begin
#1 clk <= ~clk;
end
end
wire rx;
mock_tx mock_tx (
.tx(rx)
);
reg reset = 0;
coax_rx #(
.CLOCKS_PER_BIT(8)
) dut (
.clk(clk),
.reset(reset),
.rx(rx),
.parity(1'b1)
);
initial
begin
$dumpfile("coax_rx_tb.vcd");
$dumpvars(0, coax_rx_tb);
test_1;
test_2;
test_3;
test_4;
test_5;
test_6;
test_7;
test_8;
test_9;
test_10;
test_11;
test_12;
test_13;
test_14;
test_15;
test_16;
$finish;
end
task test_1;
begin
$display("START: test_1");
`assert_equal(dut.state, dut.STATE_IDLE, "state should be STATE_IDLE");
dut_reset;
#8;
`assert_equal(dut.state, dut.STATE_IDLE, "state should be STATE_IDLE");
$display("END: test_1");
end
endtask
task test_2;
begin
$display("START: test_2");
`assert_equal(dut.state, dut.STATE_IDLE, "state should be STATE_IDLE");
mock_tx.tx_set(1);
#64;
`assert_equal(dut.state, dut.STATE_IDLE, "state should be STATE_IDLE");
$display("END: test_2");
end
endtask
task test_3;
begin
$display("START: test_3");
`assert_equal(dut.state, dut.STATE_IDLE, "state should be STATE_IDLE");
mock_tx.tx_set(1);
#16;
mock_tx.tx_set(0);
mock_tx.tx_bit(1);
#64;
`assert_equal(dut.state, dut.STATE_IDLE, "state should be STATE_IDLE");
$display("END: test_3");
end
endtask
task test_4;
begin
$display("START: test_4");
`assert_equal(dut.state, dut.STATE_IDLE, "state should be STATE_IDLE");
mock_tx.tx_set(1);
#16;
mock_tx.tx_set(0);
mock_tx.tx_bit(1);
mock_tx.tx_bit(1);
#64;
`assert_equal(dut.state, dut.STATE_IDLE, "state should be STATE_IDLE");
$display("END: test_4");
end
endtask
task test_5;
begin
$display("START: test_5");
`assert_equal(dut.state, dut.STATE_IDLE, "state should be STATE_IDLE");
mock_tx.tx_set(1);
#16;
mock_tx.tx_set(0);
mock_tx.tx_bit(1);
mock_tx.tx_bit(1);
mock_tx.tx_bit(1);
#64;
`assert_equal(dut.state, dut.STATE_IDLE, "state should be STATE_IDLE");
$display("END: test_5");
end
endtask
task test_6;
begin
$display("START: test_6");
`assert_equal(dut.state, dut.STATE_IDLE, "state should be STATE_IDLE");
mock_tx.tx_set(1);
#16;
mock_tx.tx_set(0);
mock_tx.tx_bit(1);
mock_tx.tx_bit(1);
mock_tx.tx_bit(1);
mock_tx.tx_bit(1);
#64;
`assert_equal(dut.state, dut.STATE_IDLE, "state should be STATE_IDLE");
$display("END: test_6");
end
endtask
task test_7;
begin
$display("START: test_7");
`assert_equal(dut.state, dut.STATE_IDLE, "state should be STATE_IDLE");
mock_tx.tx_set(1);
#16;
mock_tx.tx_set(0);
mock_tx.tx_bit(1);
mock_tx.tx_bit(1);
mock_tx.tx_bit(1);
mock_tx.tx_bit(1);
mock_tx.tx_bit(1);
#64;
`assert_equal(dut.state, dut.STATE_IDLE, "state should be STATE_IDLE");
$display("END: test_7");
end
endtask
task test_8;
begin
$display("START: test_8");
`assert_equal(dut.state, dut.STATE_IDLE, "state should be STATE_IDLE");
mock_tx.tx_set(1);
#16;
mock_tx.tx_set(0);
mock_tx.tx_bit(1);
mock_tx.tx_bit(1);
mock_tx.tx_bit(1);
mock_tx.tx_bit(1);
mock_tx.tx_bit(1);
mock_tx.tx_set(0);
#24;
mock_tx.tx_set(1);
#64;
`assert_equal(dut.state, dut.STATE_IDLE, "state should be STATE_IDLE");
mock_tx.tx_set(0);
$display("END: test_8");
end
endtask
task test_9;
begin
$display("START: test_9");
`assert_equal(dut.state, dut.STATE_IDLE, "state should be STATE_IDLE");
mock_tx.tx_start_sequence;
mock_tx.tx_set(0);
#64;
`assert_equal(dut.state, dut.STATE_IDLE, "state should be STATE_IDLE");
$display("END: test_9");
end
endtask
task test_10;
begin
$display("START: test_10");
`assert_equal(dut.state, dut.STATE_IDLE, "state should be STATE_IDLE");
mock_tx.tx_start_sequence;
mock_tx.tx_bit(1); // SYNC_BIT
#64;
`assert_equal(dut.state, dut.STATE_ERROR, "State should be STATE_ERROR");
`assert_high(dut.error, "error should be HIGH");
`assert_equal(dut.data, dut.ERROR_LOSS_OF_MID_BIT_TRANSITION, "data should be ERROR_LOSS_OF_MID_BIT_TRANSITION");
dut_reset;
#16;
`assert_equal(dut.state, dut.STATE_IDLE, "state should be STATE_IDLE");
$display("END: test_10");
end
endtask
task test_11;
begin
$display("START: test_11");
`assert_equal(dut.state, dut.STATE_IDLE, "state should be STATE_IDLE");
mock_tx.tx_start_sequence;
mock_tx.tx_bit(1); // SYNC_BIT
mock_tx.tx_bit(0); // MSB DATA_BIT
mock_tx.tx_bit(1);
mock_tx.tx_bit(1);
mock_tx.tx_bit(0);
mock_tx.tx_bit(1);
#64;
`assert_equal(dut.state, dut.STATE_ERROR, "State should be STATE_ERROR");
`assert_high(dut.error, "error should be HIGH");
`assert_equal(dut.data, dut.ERROR_LOSS_OF_MID_BIT_TRANSITION, "data should be ERROR_LOSS_OF_MID_BIT_TRANSITION");
dut_reset;
#16;
`assert_equal(dut.state, dut.STATE_IDLE, "state should be STATE_IDLE");
$display("END: test_11");
end
endtask
task test_12;
begin
$display("START: test_12");
`assert_equal(dut.state, dut.STATE_IDLE, "state should be STATE_IDLE");
mock_tx.tx_start_sequence;
mock_tx.tx_bit(1); // SYNC_BIT
mock_tx.tx_bit(0); // MSB DATA_BIT
mock_tx.tx_bit(1);
mock_tx.tx_bit(1);
mock_tx.tx_bit(0);
mock_tx.tx_bit(1);
mock_tx.tx_bit(1);
mock_tx.tx_bit(0);
mock_tx.tx_bit(0);
mock_tx.tx_bit(1);
mock_tx.tx_bit(1); // LSB DATA_BIT
#64;
`assert_equal(dut.state, dut.STATE_ERROR, "State should be STATE_ERROR");
`assert_high(dut.error, "error should be HIGH");
`assert_equal(dut.data, dut.ERROR_LOSS_OF_MID_BIT_TRANSITION, "data should be ERROR_LOSS_OF_MID_BIT_TRANSITION");
dut_reset;
#16;
`assert_equal(dut.state, dut.STATE_IDLE, "state should be STATE_IDLE");
$display("END: test_12");
end
endtask
task test_13;
begin
$display("START: test_13");
`assert_equal(dut.state, dut.STATE_IDLE, "state should be STATE_IDLE");
mock_tx.tx_start_sequence;
mock_tx.tx_bit(1); // SYNC_BIT
mock_tx.tx_bit(0); // MSB DATA_BIT
mock_tx.tx_bit(1);
mock_tx.tx_bit(1);
mock_tx.tx_bit(0);
mock_tx.tx_bit(1);
mock_tx.tx_bit(1);
mock_tx.tx_bit(0);
mock_tx.tx_bit(0);
mock_tx.tx_bit(1);
mock_tx.tx_bit(1); // LSB DATA_BIT
mock_tx.tx_bit(0); // PARITY_BIT
#64;
`assert_equal(dut.state, dut.STATE_ERROR, "State should be STATE_ERROR");
`assert_high(dut.error, "error should be HIGH");
`assert_equal(dut.data, dut.ERROR_PARITY, "data should be ERROR_PARITY");
dut_reset;
#16;
`assert_equal(dut.state, dut.STATE_IDLE, "state should be STATE_IDLE");
$display("END: test_13");
end
endtask
task test_14;
begin
$display("START: test_14");
`assert_equal(dut.state, dut.STATE_IDLE, "state should be STATE_IDLE");
mock_tx.tx_start_sequence;
mock_tx.tx_bit(1); // SYNC_BIT
mock_tx.tx_bit(0); // MSB DATA_BIT
mock_tx.tx_bit(1);
mock_tx.tx_bit(1);
mock_tx.tx_bit(0);
mock_tx.tx_bit(1);
mock_tx.tx_bit(1);
mock_tx.tx_bit(0);
mock_tx.tx_bit(0);
mock_tx.tx_bit(1);
mock_tx.tx_bit(1); // LSB DATA_BIT
mock_tx.tx_bit(1); // PARITY_BIT
#64;
`assert_equal(dut.state, dut.STATE_ERROR, "State should be STATE_ERROR");
`assert_high(dut.error, "error should be HIGH");
`assert_equal(dut.data, dut.ERROR_LOSS_OF_MID_BIT_TRANSITION, "data should be ERROR_LOSS_OF_MID_BIT_TRANSITION");
dut_reset;
#16;
`assert_equal(dut.state, dut.STATE_IDLE, "state should be STATE_IDLE");
$display("END: test_14");
end
endtask
task test_15;
begin
$display("START: test_15");
`assert_equal(dut.state, dut.STATE_IDLE, "state should be STATE_IDLE");
mock_tx.tx_start_sequence;
mock_tx.tx_bit(1); // SYNC_BIT
mock_tx.tx_bit(0); // MSB DATA_BIT
mock_tx.tx_bit(1);
mock_tx.tx_bit(1);
mock_tx.tx_bit(0);
mock_tx.tx_bit(1);
mock_tx.tx_bit(1);
mock_tx.tx_bit(0);
mock_tx.tx_bit(0);
mock_tx.tx_bit(1);
mock_tx.tx_bit(1); // LSB DATA_BIT
mock_tx.tx_bit(1); // PARITY_BIT
mock_tx.tx_bit(0);
#64;
`assert_equal(dut.state, dut.STATE_ERROR, "State should be STATE_ERROR");
`assert_high(dut.error, "error should be HIGH");
`assert_equal(dut.data, dut.ERROR_INVALID_END_SEQUENCE, "data should be INVALID_END_SEQUENCE_STATE_ERROR");
dut_reset;
#16;
`assert_equal(dut.state, dut.STATE_IDLE, "state should be STATE_IDLE");
$display("END: test_15");
end
endtask
task test_16;
begin
$display("START: test_16");
`assert_equal(dut.state, dut.STATE_IDLE, "state should be STATE_IDLE");
mock_tx.tx_start_sequence;
mock_tx.tx_bit(1); // SYNC_BIT
mock_tx.tx_bit(0); // MSB DATA_BIT
mock_tx.tx_bit(1);
mock_tx.tx_bit(1);
mock_tx.tx_bit(0);
mock_tx.tx_bit(1);
mock_tx.tx_bit(1);
mock_tx.tx_bit(0);
mock_tx.tx_bit(0);
mock_tx.tx_bit(1);
mock_tx.tx_bit(1); // LSB DATA_BIT
mock_tx.tx_bit(1); // PARITY_BIT
mock_tx.tx_end_sequence;
#64;
`assert_equal(dut.state, dut.STATE_IDLE, "state should be STATE_IDLE");
`assert_equal(dut.data, 10'b0110110011, "data not correct")
$display("END: test_16");
end
endtask
task dut_reset;
begin
reset = 1;
#2;
reset = 0;
end
endtask
endmodule

View File

@@ -0,0 +1,38 @@
`default_nettype none
module coax_tx_bit_timer_tb;
reg clk = 0;
initial
begin
forever
begin
#1 clk <= ~clk;
end
end
reg reset = 0;
wire first_half;
wire second_half;
wire last_clock;
coax_tx_bit_timer #(
.CLOCKS_PER_BIT(8)
) dut (
.clk(clk),
.reset(reset),
.first_half(first_half),
.second_half(second_half),
.last_clock(last_clock)
);
initial
begin
$dumpfile("coax_tx_bit_timer_tb.vcd");
$dumpvars(0, coax_tx_bit_timer_tb);
#64;
$finish;
end
endmodule

View File

@@ -0,0 +1,54 @@
`default_nettype none
module coax_tx_distorter_tb;
reg clk = 0;
initial
begin
forever
begin
#1 clk <= ~clk;
end
end
reg active_input = 0;
reg tx_input = 0;
coax_tx_distorter #(
.CLOCKS_PER_BIT(8)
) dut (
.clk(clk),
.active_input(active_input),
.tx_input(tx_input)
);
initial
begin
$dumpfile("coax_tx_distorter_tb.vcd");
$dumpvars(0, coax_tx_distorter_tb);
#16;
active_input = 1;
tx_input = 1;
#8;
tx_input = 0;
#8;
tx_input = 1;
#8;
tx_input = 0;
#8;
tx_input = 1;
#8;
tx_input = 0;
active_input = 0;
#32;
$finish;
end
endmodule

View File

@@ -0,0 +1,113 @@
`default_nettype none
`include "assert.v"
module coax_tx_tb;
reg clk = 0;
initial
begin
forever
begin
#1 clk <= ~clk;
end
end
reg reset = 0;
reg [9:0] data;
reg strobe = 0;
coax_tx #(
.CLOCKS_PER_BIT(8)
) dut (
.clk(clk),
.reset(reset),
.data(data),
.strobe(strobe),
.parity(1'b1)
);
initial
begin
$dumpfile("coax_tx_tb.vcd");
$dumpvars(0, coax_tx_tb);
test_1;
test_2;
test_3;
$finish;
end
task test_1;
begin
$display("START: test_1");
`assert_equal(dut.state, dut.IDLE, "state should be IDLE");
dut_reset;
#8;
`assert_equal(dut.state, dut.IDLE, "state should be IDLE");
$display("END: test_1");
end
endtask
task test_2;
begin
$display("START: test_2");
`assert_equal(dut.state, dut.IDLE, "state should be IDLE");
data = 10'b0101110101;
strobe = 1;
#2;
strobe = 0;
#400;
`assert_equal(dut.state, dut.IDLE, "state should be IDLE");
$display("END: test_2");
end
endtask
task test_3;
begin
$display("START: test_3");
`assert_equal(dut.state, dut.IDLE, "state should be IDLE");
data = 10'b0101110101;
strobe = 1;
#2;
strobe = 0;
#330;
data = 10'b1010001110;
strobe = 1;
#2;
strobe = 0;
#600;
`assert_equal(dut.state, dut.IDLE, "state should be IDLE");
$display("END: test_3");
end
endtask
task dut_reset;
begin
reset = 1;
#2;
reset = 0;
end
endtask
endmodule

View File

@@ -0,0 +1,186 @@
`default_nettype none
`include "assert.v"
module control_tb;
reg clk = 0;
initial
begin
forever
begin
#1 clk <= ~clk;
end
end
reg reset = 0;
reg spi_cs_n = 1;
reg [7:0] spi_rx_data;
reg spi_rx_strobe = 0;
wire tx_reset;
wire tx_active;
wire [9:0] tx_data;
wire tx_load_strobe;
wire tx_start_strobe;
wire tx_empty;
wire tx_full;
wire tx_ready;
coax_buffered_tx #(
.CLOCKS_PER_BIT(8),
.DEPTH(8)
) coax_buffered_tx (
.clk(clk),
.reset(reset),
.active(tx_active),
.data(tx_data),
.load_strobe(tx_load_strobe),
.start_strobe(tx_start_strobe),
.empty(tx_empty),
.full(tx_full),
.ready(tx_ready)
);
reg rx_active = 0;
reg rx_error = 0;
reg [9:0] rx_data = 0;
reg rx_empty = 1;
control dut (
.clk(clk),
.reset(reset),
.spi_cs_n(spi_cs_n),
.spi_rx_data(spi_rx_data),
.spi_rx_strobe(spi_rx_strobe),
.tx_reset(tx_reset),
.tx_active(tx_active),
.tx_data(tx_data),
.tx_load_strobe(tx_load_strobe),
.tx_start_strobe(tx_start_strobe),
.tx_empty(tx_empty),
.tx_full(tx_full),
.tx_ready(tx_ready),
.rx_active(rx_active),
.rx_error(rx_error),
.rx_data(rx_data),
.rx_empty(rx_empty)
);
initial
begin
$dumpfile("control_tb.vcd");
$dumpvars(0, control_tb);
test_1;
test_2;
$finish;
end
task test_1;
begin
$display("START: test_1");
dut_reset;
#2;
rx_data = 10'b1111111111;
rx_empty = 0;
spi_cs_n = 0;
spi_send(8'h05); // RX
#16;
spi_send(8'h00);
#16;
rx_data = 10'b0000000000;
rx_empty = 1;
spi_send(8'h00);
#16;
repeat (8)
begin
spi_send(8'h00);
#16;
spi_send(8'h00);
#16;
end
spi_cs_n = 1;
#64;
$display("END: test_1");
end
endtask
task test_2;
begin
$display("START: test_2");
dut_reset;
#2;
spi_cs_n = 0;
spi_send(8'h04); // TX
#16;
spi_send(8'b00000011);
#16;
spi_send(8'b11111111);
#16;
#16;
spi_cs_n = 1;
#500;
dut_reset;
#20;
$display("END: test_2");
end
endtask
task dut_reset;
begin
reset = 1;
#2;
reset = 0;
end
endtask
task spi_send (
input [7:0] data
);
begin
spi_rx_data = data;
spi_rx_strobe = 1;
#2;
spi_rx_strobe = 0;
end
endtask
endmodule

View File

@@ -0,0 +1,86 @@
module mock_tx (
output reg tx = 0
);
task tx_bit (
input bit
);
begin
tx_bit_custom(bit, 8, 8);
end
endtask
task tx_start_sequence;
begin
tx = 0;
#16;
tx = 1;
#16;
tx = 0;
tx_bit(1);
tx_bit(1);
tx_bit(1);
tx_bit(1);
tx_bit(1);
tx = 0;
#24;
tx = 1;
#24;
end
endtask
task tx_word (
input [9:0] data,
input parity
);
begin
tx_bit(1);
tx_bit(data[9]);
tx_bit(data[8]);
tx_bit(data[7]);
tx_bit(data[6]);
tx_bit(data[5]);
tx_bit(data[4]);
tx_bit(data[3]);
tx_bit(data[2]);
tx_bit(data[1]);
tx_bit(data[0]);
tx_bit(parity);
end
endtask
task tx_end_sequence;
begin
tx_bit(0);
tx = 1;
#16;
tx = 0;
end
endtask
task tx_bit_custom (
input bit,
input [15:0] first_half_duration,
input [15:0] second_half_duration
);
begin
tx = !bit;
#first_half_duration;
tx = bit;
#second_half_duration;
tx = 0;
end
endtask
task tx_set (
input value
);
begin
tx = value;
end
endtask
endmodule

View File

@@ -0,0 +1,7 @@
#!/bin/sh
VVP=vvp
echo "Running $1"
${VVP} -N $1