diff options
Diffstat (limited to 'fpga/usrp3/top/e31x/sim/e310_io_tb')
-rw-r--r-- | fpga/usrp3/top/e31x/sim/e310_io_tb/Makefile | 40 | ||||
-rw-r--r-- | fpga/usrp3/top/e31x/sim/e310_io_tb/e310_io_tb.sv | 230 |
2 files changed, 270 insertions, 0 deletions
diff --git a/fpga/usrp3/top/e31x/sim/e310_io_tb/Makefile b/fpga/usrp3/top/e31x/sim/e310_io_tb/Makefile new file mode 100644 index 000000000..bf4922c21 --- /dev/null +++ b/fpga/usrp3/top/e31x/sim/e310_io_tb/Makefile @@ -0,0 +1,40 @@ +# +# Copyright 2015 Ettus Research LLC +# + +#------------------------------------------------- +# Top-of-Makefile +#------------------------------------------------- +# Define BASE_DIR to point to the "top" dir +BASE_DIR = $(abspath ../../..) +# Include viv_sim_preample after defining BASE_DIR +include $(BASE_DIR)/../tools/make/viv_sim_preamble.mak + +#------------------------------------------------- +# Design Specific +#------------------------------------------------- +# Define part using PART_ID (<device>/<package>/<speedgrade>) +ARCH = zynq +PART_ID= xc7z020/clg484/-1 + +DESIGN_SRCS = $(abspath ../../e310_io.v) \ + $(abspath $(addprefix $(BASE_DIR)/../lib/control/, \ + synchronizer.v \ + synchronizer_impl.v)) + +#------------------------------------------------- +# Testbench Specific +#------------------------------------------------- +# Define only one toplevel module +SIM_TOP = e310_io_tb + +SIM_SRCS = \ +$(abspath e310_io_tb.sv) + +#------------------------------------------------- +# Bottom-of-Makefile +#------------------------------------------------- +# Include all simulator specific makefiles here +# Each should define a unique target to simulate +# e.g. xsim, vsim, etc and a common "clean" target +include $(BASE_DIR)/../tools/make/viv_simulator.mak diff --git a/fpga/usrp3/top/e31x/sim/e310_io_tb/e310_io_tb.sv b/fpga/usrp3/top/e31x/sim/e310_io_tb/e310_io_tb.sv new file mode 100644 index 000000000..66e086644 --- /dev/null +++ b/fpga/usrp3/top/e31x/sim/e310_io_tb/e310_io_tb.sv @@ -0,0 +1,230 @@ +// +// Copyright 2015 Ettus Research +// +// Test bench for E310 I/O interface to AD9361. + +`timescale 1ns/1ps +`define SIM_TIMEOUT_US 20 +`define NS_PER_TICK 1 +`define NUM_TEST_CASES 6 + +`include "sim_clks_rsts.vh" +`include "sim_exec_report.vh" + +module e310_io_tb(); + `TEST_BENCH_INIT("e310_io_tb",`NUM_TEST_CASES,`NS_PER_TICK) + + // Define all clocks and resets + `DEFINE_CLK(rx_clk, 16.27, 50) // ~61.44 MHz clock from AD9361 + `DEFINE_RESET(areset, 0, 100) // 100ns reset + + reg mimo; + wire radio_clk, radio_rst; + wire [11:0] rx_i0, rx_i1, rx_q0, rx_q1; + wire rx_stb; + reg [11:0] tx_i0, tx_i1, tx_q0, tx_q1; + wire tx_stb; + reg rx_frame; + reg [11:0] rx_data; + wire tx_clk; + wire tx_frame; + wire [11:0] tx_data; + e310_io e310_io ( + .areset(areset), + .mimo(mimo), + .radio_clk(radio_clk), + .radio_rst(radio_rst), + .rx_i0(rx_i0), + .rx_q0(rx_q0), + .rx_i1(rx_i1), + .rx_q1(rx_q1), + .rx_stb(rx_stb), + .tx_i0(tx_i0), + .tx_q0(tx_q0), + .tx_i1(tx_i1), + .tx_q1(tx_q1), + .tx_stb(tx_stb), + .rx_clk(rx_clk), + .rx_frame(rx_frame), + .rx_data(rx_data), + .tx_clk(tx_clk), + .tx_frame(tx_frame), + .tx_data(tx_data)); + + /******************************************************** + ** Test Bench + ********************************************************/ + initial begin : tb_main + mimo <= 1'b0; + tx_i0 <= 'd0; + tx_q0 <= 'd0; + tx_i1 <= 'd0; + tx_q1 <= 'd0; + rx_data <= 'd0; + rx_frame <= 1'b0; + `TEST_CASE_START("Wait for reset"); + while (areset) @(posedge radio_clk); + `TEST_CASE_DONE((~areset)); + + repeat (10) @(posedge radio_clk); + + `TEST_CASE_START("Test RX channel 0,1"); + mimo <= 1'b0; + rx_data <= 'd0; + repeat (10) @(posedge radio_clk); + fork + begin + for (int i = 1; i < 64; i = i + 2) begin + @(posedge radio_clk); + rx_frame <= 1'b1; + rx_data <= i; + @(negedge radio_clk); + rx_frame <= 1'b0; + rx_data <= i+1; + end + end + begin + while ({rx_i0, rx_q0} == 24'd0) @(posedge radio_clk); + for (int i = 1; i < 64; i = i + 2) begin + // RX should be replicated across both ports + `ASSERT_ERROR(rx_i0 == i, "RX0 I incorrect!"); + `ASSERT_ERROR(rx_q0 == i+1, "RX0 Q incorrect!"); + `ASSERT_ERROR(rx_i1 == i, "RX1 I incorrect!"); + `ASSERT_ERROR(rx_q1 == i+1, "RX1 Q incorrect!"); + @(posedge radio_clk); + end + end + join + `TEST_CASE_DONE(1); + + `TEST_CASE_START("Test RX channels 0 & 1 (MIMO mode)"); + mimo <= 1'b1; + rx_frame <= 1'b0; + rx_data <= 'd0; + repeat (10) @(posedge radio_clk); + fork + begin + for (int i = 1; i < 64; i = i + 2) begin + @(posedge radio_clk); + rx_frame <= ~rx_frame; + rx_data <= i; + @(negedge radio_clk); + rx_data <= i+1; + end + end + begin + while ({rx_i0, rx_q0} == 24'd0) @(posedge radio_clk); + for (int i = 1; i < 32; i = i + 4) begin + // RX should be replicated across both ports + `ASSERT_ERROR(rx_i0 == i, "RX0 I incorrect!"); + `ASSERT_ERROR(rx_q0 == i+1, "RX0 Q incorrect!"); + @(posedge radio_clk); + `ASSERT_ERROR(rx_i1 == i+2, "RX1 I incorrect!"); + `ASSERT_ERROR(rx_q1 == i+3, "RX1 Q incorrect!"); + @(posedge radio_clk); + end + end + join + `TEST_CASE_DONE(1); + + `TEST_CASE_START("Test TX channel 0"); + mimo <= 1'b0; + tx_i0 <= 'd0; + tx_q0 <= 'd0; + tx_i1 <= 'd0; + tx_q1 <= 'd0; + repeat (10) @(posedge radio_clk); + // TX0 + fork + begin + for (int i = 1; i < 64; i = i + 2) begin + tx_i0 <= i; + tx_q0 <= i+1; + @(posedge radio_clk); + end + end + begin + while (tx_data == 12'd0) @(posedge tx_clk); + for (int i = 1; i < 64; i = i + 2) begin + // RX should be replicated across both ports + `ASSERT_ERROR(tx_data == i, "TX0 I data incorrect!"); + `ASSERT_ERROR(tx_frame == 1'b1, "TX frame incorrect"); + @(negedge tx_clk); + `ASSERT_ERROR(tx_data == i+1, "TX0 Q data incorrect!"); + `ASSERT_ERROR(tx_frame == 1'b0, "TX frame incorrect"); + @(posedge tx_clk); + end + end + join + `TEST_CASE_DONE(1); + + `TEST_CASE_START("Test TX channel 1"); + mimo <= 1'b0; + tx_i0 <= 'd0; + tx_q0 <= 'd0; + tx_i1 <= 'd0; + tx_q1 <= 'd0; + repeat (10) @(posedge radio_clk); + fork + begin + for (int i = 1; i < 64; i = i + 2) begin + tx_i1 <= i; + tx_q1 <= i+1; + @(posedge radio_clk); + end + end + begin + while (tx_data == 12'd0) @(posedge tx_clk); + for (int i = 1; i < 64; i = i + 2) begin + `ASSERT_ERROR(tx_data == i, "TX1 I data incorrect!"); + `ASSERT_ERROR(tx_frame == 1'b1, "TX frame incorrect"); + @(negedge tx_clk); + `ASSERT_ERROR(tx_data == i+1, "TX1 Q data incorrect!"); + `ASSERT_ERROR(tx_frame == 1'b0, "TX frame incorrect"); + @(posedge tx_clk); + end + end + join + `TEST_CASE_DONE(1); + + `TEST_CASE_START("Test TX channel 0 & 1 (MIMO)"); + mimo <= 1'b1; + tx_i0 <= 'd0; + tx_q0 <= 'd0; + tx_i1 <= 'd0; + tx_q1 <= 'd0; + repeat (10) @(posedge radio_clk); + fork + begin + for (int i = 1; i < 32; i = i + 4) begin + tx_i0 <= i; + tx_q0 <= i+1; + tx_i1 <= i+2; + tx_q1 <= i+3; + @(posedge radio_clk); + while (tx_stb) @(posedge radio_clk); + end + end + begin + while (tx_data == 12'd0) @(posedge tx_clk); + for (int i = 1; i < 32; i = i + 4) begin + `ASSERT_ERROR(tx_data == i, "TX0 I data incorrect!"); + `ASSERT_ERROR(tx_frame == 1'b1, "TX frame incorrect"); + @(negedge tx_clk); + `ASSERT_ERROR(tx_data == i+1, "TX0 Q data incorrect!"); + `ASSERT_ERROR(tx_frame == 1'b1, "TX frame incorrect"); + @(posedge tx_clk); + `ASSERT_ERROR(tx_data == i+2, "TX1 I data incorrect!"); + `ASSERT_ERROR(tx_frame == 1'b0, "TX frame incorrect"); + @(negedge tx_clk); + `ASSERT_ERROR(tx_data == i+3, "TX1 Q data incorrect!"); + `ASSERT_ERROR(tx_frame == 1'b0, "TX frame incorrect"); + @(posedge tx_clk); + end + end + join + `TEST_CASE_DONE(1); + `TEST_BENCH_DONE; + end + +endmodule |