Files
lowobservable.coax/interface2/fpga/tests/tx_rx_loopback_tb.v
2021-11-06 13:32:39 -05:00

324 lines
7.9 KiB
Verilog

`default_nettype none
`include "assert.v"
module tx_rx_loopback_tb;
reg clk = 0;
initial
begin
forever
begin
#1 clk <= ~clk;
end
end
reg reset = 0;
wire loopback;
wire tx_active;
reg [9:0] tx_data;
reg tx_strobe = 0;
wire tx_ready;
reg tx_protocol = 0;
reg tx_parity = 0;
wire rx_error;
wire [9:0] rx_data;
wire rx_strobe;
reg rx_protocol = 0;
reg rx_parity = 0;
coax_tx #(
.CLOCKS_PER_BIT(8)
) dut_tx (
.clk(clk),
.reset(reset),
.active(tx_active),
.tx(loopback),
.data(tx_data),
.strobe(tx_strobe),
.ready(tx_ready),
.protocol(tx_protocol),
.parity(tx_parity)
);
coax_rx #(
.CLOCKS_PER_BIT(8)
) dut_rx (
.clk(clk),
.reset(reset),
.rx(loopback),
.error(rx_error),
.data(rx_data),
.strobe(rx_strobe),
.protocol(rx_protocol),
.parity(rx_parity)
);
initial
begin
$dumpfile("tx_rx_loopback_tb.vcd");
$dumpvars(0, tx_rx_loopback_tb);
test_3270_protocol;
test_3299_protocol;
test_protocol_mismatch;
test_parity_mismatch;
$finish;
end
task test_3270_protocol;
begin
$display("START: test_3270_protocol");
tx_protocol = 0;
tx_parity = 1;
rx_protocol = 0;
rx_parity = 1;
`assert_equal(dut_tx.state, dut_tx.IDLE, "state should be IDLE");
`assert_equal(dut_rx.state, dut_rx.STATE_IDLE, "state should be IDLE");
fork: test_3270_protocol_tx_rx_fork
begin
tx_data = 10'b0101110101;
#2;
tx_strobe = 1;
#2;
tx_strobe = 0;
@(posedge tx_ready);
tx_data = 10'b1010001010;
#2;
tx_strobe = 1;
#2;
tx_strobe = 0;
end
begin
@(posedge rx_strobe);
`assert_equal(rx_data, 10'b0101110101, "RX data should be equal to TX data");
@(posedge rx_strobe);
`assert_equal(rx_data, 10'b1010001010, "RX data should be equal to TX data");
disable test_3270_protocol_tx_rx_fork;
end
begin
#1000;
$display("[TIMEOUT] %m (%s:%0d)", `__FILE__, `__LINE__);
disable test_3270_protocol_tx_rx_fork;
end
join
#100;
`assert_equal(dut_tx.state, dut_tx.IDLE, "state should be IDLE");
`assert_equal(dut_rx.state, dut_rx.STATE_IDLE, "state should be IDLE");
$display("END: test_3270_protocol");
end
endtask
task test_3299_protocol;
begin
$display("START: test_3299_protocol");
tx_protocol = 1;
tx_parity = 1;
rx_protocol = 1;
rx_parity = 1;
`assert_equal(dut_tx.state, dut_tx.IDLE, "state should be IDLE");
`assert_equal(dut_rx.state, dut_rx.STATE_IDLE, "state should be IDLE");
fork: test_3299_protocol_tx_rx_fork
begin
tx_data = 10'b0000110001;
#2;
tx_strobe = 1;
#2;
tx_strobe = 0;
@(posedge tx_ready);
tx_data = 10'b0101110101;
#2;
tx_strobe = 1;
#2;
tx_strobe = 0;
@(posedge tx_ready);
tx_data = 10'b1010001010;
#2;
tx_strobe = 1;
#2;
tx_strobe = 0;
end
begin
@(posedge rx_strobe);
`assert_equal(rx_data, 10'b0000110001, "RX data should be equal to TX data");
@(posedge rx_strobe);
`assert_equal(rx_data, 10'b0101110101, "RX data should be equal to TX data");
@(posedge rx_strobe);
`assert_equal(rx_data, 10'b1010001010, "RX data should be equal to TX data");
disable test_3299_protocol_tx_rx_fork;
end
begin
#1000;
$display("[TIMEOUT] %m (%s:%0d)", `__FILE__, `__LINE__);
disable test_3299_protocol_tx_rx_fork;
end
join
#100;
`assert_equal(dut_tx.state, dut_tx.IDLE, "state should be IDLE");
`assert_equal(dut_rx.state, dut_rx.STATE_IDLE, "state should be IDLE");
$display("END: test_3299_protocol");
end
endtask
task test_protocol_mismatch;
begin
$display("START: test_protocol_mismatch");
tx_protocol = 1;
tx_parity = 1;
rx_protocol = 0;
rx_parity = 1;
`assert_equal(dut_tx.state, dut_tx.IDLE, "state should be IDLE");
`assert_equal(dut_rx.state, dut_rx.STATE_IDLE, "state should be IDLE");
fork: test_protocol_mismatch_tx_rx_fork
begin
tx_data = 10'b0000110001;
#2;
tx_strobe = 1;
#2;
tx_strobe = 0;
@(posedge tx_ready);
tx_data = 10'b0101110101;
#2;
tx_strobe = 1;
#2;
tx_strobe = 0;
// Wait for TX to complete... we don't want to reset the RX
// to soon as it could be reactivated with the remaining
// transmission.
@(negedge tx_active);
disable test_protocol_mismatch_tx_rx_fork;
end
begin
#1000;
$display("[TIMEOUT] %m (%s:%0d)", `__FILE__, `__LINE__);
disable test_protocol_mismatch_tx_rx_fork;
end
join
// The exact error (parity or loss of mid-bit transition) may depend
// on the length of message and data.
`assert_high(rx_error, "RX error should be HIGH");
`assert_equal(rx_data, dut_rx.ERROR_LOSS_OF_MID_BIT_TRANSITION, "RX data should be ERROR_LOSS_OF_MID_BIT_TRANSITION");
#16;
dut_reset;
#100;
`assert_equal(dut_tx.state, dut_tx.IDLE, "state should be IDLE");
`assert_equal(dut_rx.state, dut_rx.STATE_IDLE, "state should be IDLE");
$display("END: test_protocol_mismatch");
end
endtask
task test_parity_mismatch;
begin
$display("START: test_parity_mismatch");
tx_protocol = 0;
tx_parity = 1;
rx_protocol = 0;
rx_parity = 0;
`assert_equal(dut_tx.state, dut_tx.IDLE, "state should be IDLE");
`assert_equal(dut_rx.state, dut_rx.STATE_IDLE, "state should be IDLE");
fork: test_parity_mismatch_tx_rx_fork
begin
tx_data = 10'b0101110101;
#2;
tx_strobe = 1;
#2;
tx_strobe = 0;
// Wait for TX to complete... we don't want to reset the RX
// to soon as it could be reactivated with the remaining
// transmission.
@(negedge tx_active);
disable test_parity_mismatch_tx_rx_fork;
end
begin
#1000;
$display("[TIMEOUT] %m (%s:%0d)", `__FILE__, `__LINE__);
disable test_parity_mismatch_tx_rx_fork;
end
join
`assert_high(rx_error, "RX error should be HIGH");
`assert_equal(rx_data, dut_rx.ERROR_PARITY, "RX data should be ERROR_PARITY");
#16;
dut_reset;
#100;
`assert_equal(dut_tx.state, dut_tx.IDLE, "state should be IDLE");
`assert_equal(dut_rx.state, dut_rx.STATE_IDLE, "state should be IDLE");
$display("END: test_parity_mismatch");
end
endtask
task dut_reset;
begin
reset = 1;
#2;
reset = 0;
end
endtask
endmodule