fpga: lib: Add rx_front_end_gen3 testbench

Original-commit: 532f8d0949c1d534b1a64600f2d32aadf2c7e202
This commit is contained in:
Wade Fife
2021-04-09 17:26:59 -05:00
parent 776860727e
commit bababc79eb
2 changed files with 247 additions and 0 deletions
@@ -0,0 +1,38 @@
#
# Copyright 2021 Ettus Research, a National Instruments Brand
#
# SPDX-License-Identifier: LGPL-3.0-or-later
#
#-------------------------------------------------
# Top-of-Makefile
#-------------------------------------------------
# Define BASE_DIR to point to the "top" dir.
BASE_DIR = $(abspath ../../../../../top)
# Include viv_sim_preample after defining BASE_DIR
include $(BASE_DIR)/../tools/make/viv_sim_preamble.mak
#-------------------------------------------------
# Design Specific
#-------------------------------------------------
DESIGN_SRCS += $(abspath \
$(abspath ../rx_frontend_gen3.v) \
$(abspath ../quarter_rate_downconverter.v) \
)
#-------------------------------------------------
# Testbench Specific
#-------------------------------------------------
SIM_TOP = rx_frontend_gen3_tb glbl
SIM_SRCS = \
$(abspath rx_frontend_gen3_tb.sv) \
$(VIVADO_PATH)/data/verilog/src/glbl.v \
#-------------------------------------------------
# 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
@@ -0,0 +1,209 @@
//
// Copyright 2021 Ettus Research, a National Instruments Brand
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// Module: rx_frontend_gen3_tb
//
// Description: Testbench for rx_frontend_gen3.
//
`default_nettype none
module rx_frontend_gen3_tb;
`include "test_exec.svh"
import PkgTestExec::*;
localparam real CLK_FREQUENCY = 100e6;
localparam real CLK_PERIOD_NS = 1.0e9 / CLK_FREQUENCY;
localparam real PI = 2.0 * $acos(0.0);
// Register offsets
localparam SR_MAG_CORRECTION = 0;
localparam SR_PHASE_CORRECTION = 1;
localparam SR_OFFSET_I = 2;
localparam SR_OFFSET_Q = 3;
localparam SR_IQ_MAPPING = 4;
localparam SR_HET_PHASE_INCR = 5;
// SR_IQ_MAPPING bit positions
localparam SWAP_IQ = 1 << 0;
localparam REAL_MODE = 1 << 1;
localparam INVERT_Q = 1 << 2;
localparam INVERT_I = 1 << 3;
localparam DOWNCONVERT = 1 << 4;
localparam BYPASS_ALL = 1 << 7;
// SR_OFFSET_* bit position
localparam OFFSET_FIXED = 1 << 31; // Fixed bit for SR_OFFSET register
localparam OFFSET_SET = 1 << 30; // Set bit for SR_OFFSET register
//---------------------------------------------------------------------------
// Clocks and Resets
//---------------------------------------------------------------------------
bit clk, rst;
sim_clock_gen #(.PERIOD(CLK_PERIOD_NS)) clk_gen (.clk(clk), .rst(rst));
//---------------------------------------------------------------------------
// Device Under Test (DUT)
//---------------------------------------------------------------------------
localparam BYPASS_DC_OFFSET_CORR = 0;
localparam BYPASS_IQ_COMP = 0;
localparam BYPASS_REALMODE_DSP = 0;
localparam DEVICE = "7SERIES";
logic sync_in;
logic set_stb = 0;
logic [ 7:0] set_addr = 0;
logic [31:0] set_data = 0;
logic adc_stb;
logic signed [15:0] adc_i = 0;
logic signed [15:0] adc_q = 0;
logic rx_stb;
logic signed [15:0] rx_i;
logic signed [15:0] rx_q;
rx_frontend_gen3 #(
.SR_MAG_CORRECTION (SR_MAG_CORRECTION),
.SR_PHASE_CORRECTION (SR_PHASE_CORRECTION),
.SR_OFFSET_I (SR_OFFSET_I),
.SR_OFFSET_Q (SR_OFFSET_Q),
.SR_IQ_MAPPING (SR_IQ_MAPPING),
.SR_HET_PHASE_INCR (SR_HET_PHASE_INCR),
.BYPASS_DC_OFFSET_CORR (BYPASS_DC_OFFSET_CORR),
.BYPASS_IQ_COMP (BYPASS_IQ_COMP),
.BYPASS_REALMODE_DSP (BYPASS_REALMODE_DSP),
.DEVICE (DEVICE)
) rx_frontend_gen3_i (
.clk (clk),
.reset (rst),
.sync_in (sync_in),
.set_stb (set_stb),
.set_addr (set_addr),
.set_data (set_data),
.adc_stb (adc_stb),
.adc_i (adc_i),
.adc_q (adc_q),
.rx_stb (rx_stb),
.rx_i (rx_i),
.rx_q (rx_q)
);
//---------------------------------------------------------------------------
// Input Generator
//---------------------------------------------------------------------------
real amplitude = 0.4375; // Pick your favorite amplitude < 1.0
real test_freq = CLK_FREQUENCY / 80.0; // Pick a frequency < CLK_FREQUENCY
real fp_amp = amplitude * (2**15); // Scale amplitude to signed 16-bit
real f_norm = test_freq / CLK_FREQUENCY; // Normalized frequency
longint count;
assign adc_stb = 1;
initial begin : gen_input
count = 0;
forever begin
clk_gen.clk_wait_r();
if (rst) begin
count = 0;
continue;
end
adc_i <= fp_amp * $cos(2.0*PI*f_norm*count);
adc_q <= fp_amp * $sin(2.0*PI*f_norm*count);
count++;
end
end : gen_input
//---------------------------------------------------------------------------
// Helper Functions
//---------------------------------------------------------------------------
task automatic sr_write(logic [7:0] addr, logic [31:0] data);
@clk;
set_data <= data;
set_addr <= addr;
set_stb <= 1;
@clk;
set_stb <= 0;
endtask : sr_write
//---------------------------------------------------------------------------
// Main Test Process
//---------------------------------------------------------------------------
initial begin : tb_main
string tb_name;
// Initialize the test exec object for this testbench
test.start_tb("rx_frontend_gen3_tb");
//--------------------------------
// Reset
//--------------------------------
// Reset long enough for the FIR filter to flush. This isn't required for
// synthesized code, but avoids getting 'X stuck in the round_sd module in
// simulation.
test.start_test("Reset", 10us);
clk_gen.reset(50);
@rst;
test.end_test();
//--------------------------------
// Initialize Registers
//--------------------------------
test.start_test("Initialize registers", 10us);
// Set IQ mapping (Enable down-conversion)
sr_write(SR_IQ_MAPPING, DOWNCONVERT);
// Set IQ compensation (no compensation)
sr_write(SR_MAG_CORRECTION, 'h0);
sr_write(SR_PHASE_CORRECTION, 'h0);
// Set DC offset correction (fixed offset of 0)
sr_write(SR_OFFSET_I, OFFSET_FIXED | OFFSET_SET | 'h00000000);
sr_write(SR_OFFSET_Q, OFFSET_FIXED | OFFSET_SET | 'h00000000);
// Set down-converter direction (+pi/2 per clock cycle)
sr_write(SR_HET_PHASE_INCR, 'b0);
test.end_test();
//--------------------------------
// Test Waveforms
//--------------------------------
test.start_test("Test Waveforms", 100us);
clk_gen.clk_wait_r(2000);
$display("Done! Check the waveforms in the GUI. :-)");
test.end_test();
//--------------------------------
// End TB
//--------------------------------
test.end_tb();
end : tb_main
endmodule : rx_frontend_gen3_tb
`default_nettype wire