fpga: e320: Improve timing on LVDS interface
Original-commit: c6578eda2ba482b87583ebd989cdf5cbd5c3f672
This commit is contained in:
@@ -37,7 +37,6 @@ module cat_io_lvds_dual_mode #(
|
|||||||
parameter OUTPUT_CLOCK_DELAY = 16,
|
parameter OUTPUT_CLOCK_DELAY = 16,
|
||||||
parameter OUTPUT_DATA_DELAY = 0
|
parameter OUTPUT_DATA_DELAY = 0
|
||||||
) (
|
) (
|
||||||
input rst,
|
|
||||||
input clk200,
|
input clk200,
|
||||||
|
|
||||||
// Data and frame timing (asynchronous, glitch free)
|
// Data and frame timing (asynchronous, glitch free)
|
||||||
@@ -56,13 +55,14 @@ module cat_io_lvds_dual_mode #(
|
|||||||
input ctrl_ld_out_clk_delay,
|
input ctrl_ld_out_clk_delay,
|
||||||
|
|
||||||
// Baseband sample interface
|
// Baseband sample interface
|
||||||
|
input radio_rst, // Glitch-free, synchronous to radio_clk
|
||||||
output radio_clk,
|
output radio_clk,
|
||||||
//
|
//
|
||||||
output reg rx_aligned,
|
output reg rx_aligned,
|
||||||
output reg [11:0] rx_i0,
|
output [11:0] rx_i0,
|
||||||
output reg [11:0] rx_q0,
|
output [11:0] rx_q0,
|
||||||
output reg [11:0] rx_i1,
|
output [11:0] rx_i1,
|
||||||
output reg [11:0] rx_q1,
|
output [11:0] rx_q1,
|
||||||
//
|
//
|
||||||
input [11:0] tx_i0,
|
input [11:0] tx_i0,
|
||||||
input [11:0] tx_q0,
|
input [11:0] tx_q0,
|
||||||
@@ -115,7 +115,8 @@ module cat_io_lvds_dual_mode #(
|
|||||||
// Clock Mux
|
// Clock Mux
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
// Use radio_clk_1x when MIMO = 1, radio_clk_2x when MIMO = 0
|
// Select the source for radio_clk. Use radio_clk_1x when MIMO = 1 or
|
||||||
|
// radio_clk_2x when MIMO = 0.
|
||||||
BUFGCTRL BUFGCTRL_radio_clk (
|
BUFGCTRL BUFGCTRL_radio_clk (
|
||||||
.I0 (radio_clk_1x),
|
.I0 (radio_clk_1x),
|
||||||
.I1 (radio_clk_2x),
|
.I1 (radio_clk_2x),
|
||||||
@@ -177,6 +178,14 @@ module cat_io_lvds_dual_mode #(
|
|||||||
//
|
//
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
wire rx_aligned_t;
|
||||||
|
reg rx_aligned_reg;
|
||||||
|
|
||||||
|
wire [11:0] rx_i0_t;
|
||||||
|
wire [11:0] rx_q0_t;
|
||||||
|
wire [11:0] rx_i1_t;
|
||||||
|
wire [11:0] rx_q1_t;
|
||||||
|
|
||||||
reg [11:0] rx_i0_ser;
|
reg [11:0] rx_i0_ser;
|
||||||
reg [11:0] rx_q0_ser;
|
reg [11:0] rx_q0_ser;
|
||||||
reg [11:0] rx_i1_ser;
|
reg [11:0] rx_i1_ser;
|
||||||
@@ -187,9 +196,11 @@ module cat_io_lvds_dual_mode #(
|
|||||||
reg [11:0] rx_i1_out;
|
reg [11:0] rx_i1_out;
|
||||||
reg [11:0] rx_q1_out;
|
reg [11:0] rx_q1_out;
|
||||||
|
|
||||||
|
reg rx_out_val;
|
||||||
|
|
||||||
always @(posedge radio_clk_2x)
|
always @(posedge radio_clk_2x)
|
||||||
begin
|
begin
|
||||||
rx_aligned <= rx_aligned_t;
|
rx_aligned_reg <= rx_aligned_t;
|
||||||
|
|
||||||
if (align_1x ^ align_2x) begin
|
if (align_1x ^ align_2x) begin
|
||||||
// This clock cycle corresponds to the first 1x cycle in which two
|
// This clock cycle corresponds to the first 1x cycle in which two
|
||||||
@@ -209,11 +220,17 @@ module cat_io_lvds_dual_mode #(
|
|||||||
|
|
||||||
// Select the correct Rx output based on MIMO setting
|
// Select the correct Rx output based on MIMO setting
|
||||||
if (r_mimo) begin
|
if (r_mimo) begin
|
||||||
|
// In MIMO mode, we get new data for both channels every other
|
||||||
|
// radio_clk_2x clock cycle.
|
||||||
|
rx_out_val <= ~rx_out_val;
|
||||||
rx_i0_out <= rx_i0_t;
|
rx_i0_out <= rx_i0_t;
|
||||||
rx_q0_out <= rx_q0_t;
|
rx_q0_out <= rx_q0_t;
|
||||||
rx_i1_out <= rx_i1_t;
|
rx_i1_out <= rx_i1_t;
|
||||||
rx_q1_out <= rx_q1_t;
|
rx_q1_out <= rx_q1_t;
|
||||||
end else begin
|
end else begin
|
||||||
|
// In SISO mode, we get new data for one channel on every radio_clk_2x
|
||||||
|
// cock cycle.
|
||||||
|
rx_out_val <= 1'b1;
|
||||||
rx_i0_out <= rx_i0_ser;
|
rx_i0_out <= rx_i0_ser;
|
||||||
rx_q0_out <= rx_q0_ser;
|
rx_q0_out <= rx_q0_ser;
|
||||||
rx_i1_out <= rx_i1_ser;
|
rx_i1_out <= rx_i1_ser;
|
||||||
@@ -223,35 +240,106 @@ module cat_io_lvds_dual_mode #(
|
|||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
// Synchronize Rx to radio_clk Domain
|
// Cross RX Data from radio_clk_2x to radio_clk Domain
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// This crosses the radio data from the radio_clk_1x domain to the radio_clk
|
// The clocks are synchronous and the data input rate matches the data
|
||||||
// domain. We use the falling edge of radio_clk to allow for the BUFG
|
// output rate, so this FIFO should never overflow or underflow once it is
|
||||||
// insertion delay.
|
// primed and starts being read.
|
||||||
//
|
//
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
reg [11:0] rx_i0_fall;
|
wire rx_fifo_full;
|
||||||
reg [11:0] rx_q0_fall;
|
wire rx_fifo_empty;
|
||||||
reg [11:0] rx_i1_fall;
|
reg rx_fifo_rd_en;
|
||||||
reg [11:0] rx_q1_fall;
|
|
||||||
|
|
||||||
always @(negedge radio_clk)
|
fifo_short_2clk fifo_short_2clk_rx (
|
||||||
begin
|
.rst (radio_rst), // Asynchronous reset input
|
||||||
rx_i0_fall <= rx_i0_out;
|
.wr_clk (radio_clk_2x),
|
||||||
rx_q0_fall <= rx_q0_out;
|
.rd_clk (radio_clk),
|
||||||
rx_i1_fall <= rx_i1_out;
|
.din ({rx_i1_out, rx_q1_out, rx_i0_out, rx_q0_out}),
|
||||||
rx_q1_fall <= rx_q1_out;
|
.wr_en (rx_out_val & ~rx_fifo_full & rx_aligned_reg),
|
||||||
|
.rd_en (rx_fifo_rd_en & ~rx_fifo_empty),
|
||||||
|
.dout ({rx_i1, rx_q1, rx_i0, rx_q0 }),
|
||||||
|
.full (rx_fifo_full),
|
||||||
|
.empty (rx_fifo_empty),
|
||||||
|
.rd_data_count (),
|
||||||
|
.wr_data_count ()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Wait until the FIFO is partially filled before we start reading out data.
|
||||||
|
// Go back to waiting if the FIFO empties.
|
||||||
|
always @(posedge radio_clk) begin
|
||||||
|
if (radio_rst) begin
|
||||||
|
rx_fifo_rd_en <= 1'b0;
|
||||||
|
rx_aligned <= 1'b0;
|
||||||
|
end else begin
|
||||||
|
if (!rx_fifo_empty) begin
|
||||||
|
rx_fifo_rd_en <= 1'b1;
|
||||||
|
rx_aligned <= 1'b1;
|
||||||
|
end else if (rx_fifo_empty) begin
|
||||||
|
rx_fifo_rd_en <= 1'b0;
|
||||||
|
rx_aligned <= 1'b0;
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
// Re-clock data on the rising edge to present the whole period to external IP
|
|
||||||
always @(posedge radio_clk)
|
//---------------------------------------------------------------------------
|
||||||
begin
|
// Cross TX Data from radio_clk domain to radio_clk_2x Domain
|
||||||
rx_i0 <= rx_i0_fall;
|
//---------------------------------------------------------------------------
|
||||||
rx_q0 <= rx_q0_fall;
|
//
|
||||||
rx_i1 <= rx_i1_fall;
|
// The clocks are synchronous and the data input rate matches the data
|
||||||
rx_q1 <= rx_q1_fall;
|
// output rate, so this FIFO should never overflow or underflow once it is
|
||||||
|
// primed and starts being read.
|
||||||
|
//
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Cross the radio_rst to radio_clk_2x
|
||||||
|
synchronizer #(
|
||||||
|
.INITIAL_VAL (1'b1)
|
||||||
|
) synchronizer_radio_rst_2x (
|
||||||
|
.clk (radio_clk_2x),
|
||||||
|
.rst (1'b0),
|
||||||
|
.in (radio_rst),
|
||||||
|
.out (radio_rst_2x)
|
||||||
|
);
|
||||||
|
|
||||||
|
wire [11:0] tx_i0_del0;
|
||||||
|
wire [11:0] tx_q0_del0;
|
||||||
|
wire [11:0] tx_i1_del0;
|
||||||
|
wire [11:0] tx_q1_del0;
|
||||||
|
|
||||||
|
wire tx_fifo_full;
|
||||||
|
wire tx_fifo_empty;
|
||||||
|
reg tx_fifo_rd_en;
|
||||||
|
|
||||||
|
fifo_short_2clk fifo_short_2clk_tx (
|
||||||
|
.rst (radio_rst), // Asynchronous reset input
|
||||||
|
.wr_clk (radio_clk),
|
||||||
|
.rd_clk (radio_clk_2x),
|
||||||
|
.din ({tx_i1, tx_q1, tx_i0, tx_q0}),
|
||||||
|
.wr_en (~tx_fifo_full),
|
||||||
|
.rd_en (tx_fifo_rd_en & ~tx_fifo_empty),
|
||||||
|
.dout ({tx_i1_del0, tx_q1_del0, tx_i0_del0, tx_q0_del0}),
|
||||||
|
.full (tx_fifo_full),
|
||||||
|
.empty (tx_fifo_empty),
|
||||||
|
.rd_data_count (),
|
||||||
|
.wr_data_count ()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Wait until the FIFO is partially filled before we start reading out data.
|
||||||
|
// Go back to waiting if the FIFO empties.
|
||||||
|
always @(posedge radio_clk_2x) begin
|
||||||
|
if (radio_rst_2x) begin
|
||||||
|
tx_fifo_rd_en <= 1'b0;
|
||||||
|
end else begin
|
||||||
|
if (!tx_fifo_empty) begin
|
||||||
|
tx_fifo_rd_en <= 1'b1;
|
||||||
|
end else if (tx_fifo_empty) begin
|
||||||
|
tx_fifo_rd_en <= 1'b0;
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -266,18 +354,23 @@ module cat_io_lvds_dual_mode #(
|
|||||||
//
|
//
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
reg [11:0] tx_i0_del;
|
reg [11:0] tx_i0_del1;
|
||||||
reg [11:0] tx_q0_del;
|
reg [11:0] tx_q0_del1;
|
||||||
reg [11:0] tx_i1_del;
|
reg [11:0] tx_i1_del1;
|
||||||
reg [11:0] tx_q1_del;
|
reg [11:0] tx_q1_del1;
|
||||||
|
|
||||||
|
reg [11:0] tx_i0_t;
|
||||||
|
reg [11:0] tx_q0_t;
|
||||||
|
reg [11:0] tx_i1_t;
|
||||||
|
reg [11:0] tx_q1_t;
|
||||||
|
|
||||||
always @(posedge radio_clk_2x)
|
always @(posedge radio_clk_2x)
|
||||||
begin
|
begin
|
||||||
// Capture copy of the data delayed by one radio_clk_2c cycle.
|
// Capture copy of the data delayed by one radio_clk_2x cycle.
|
||||||
tx_i0_del <= tx_i0;
|
tx_i0_del1 <= tx_i0_del0;
|
||||||
tx_q0_del <= tx_q0;
|
tx_q0_del1 <= tx_q0_del0;
|
||||||
tx_i1_del <= tx_i1;
|
tx_i1_del1 <= tx_i1_del0;
|
||||||
tx_q1_del <= tx_q1;
|
tx_q1_del1 <= tx_q1_del0;
|
||||||
end
|
end
|
||||||
|
|
||||||
always @(posedge radio_clk_1x)
|
always @(posedge radio_clk_1x)
|
||||||
@@ -285,25 +378,25 @@ module cat_io_lvds_dual_mode #(
|
|||||||
if (r_mimo) begin
|
if (r_mimo) begin
|
||||||
// In MIMO mode, radio_clk is radio_clk_1x, so we just capture the same
|
// In MIMO mode, radio_clk is radio_clk_1x, so we just capture the same
|
||||||
// data for each radio_clk_1x cycle.
|
// data for each radio_clk_1x cycle.
|
||||||
tx_i0_t <= tx_i0;
|
tx_i0_t <= tx_i0_del0;
|
||||||
tx_q0_t <= tx_q0;
|
tx_q0_t <= tx_q0_del0;
|
||||||
tx_i1_t <= tx_i1;
|
tx_i1_t <= tx_i1_del0;
|
||||||
tx_q1_t <= tx_q1;
|
tx_q1_t <= tx_q1_del0;
|
||||||
end else begin
|
end else begin
|
||||||
// In SISO mode, data is updated every radio_clk_2x cycle, so we output
|
// In SISO mode, data is updated every radio_clk_2x cycle, so we output
|
||||||
// the data from the previous radio_clk_2x cycle onto channel 0 and the
|
// the data from the previous radio_clk_2x cycle onto channel 0 and the
|
||||||
// data from the current radio_clk_2x cycle onto channel 1. This puts the
|
// data from the current radio_clk_2x cycle onto channel 1. This puts the
|
||||||
// data in the correct order when in 1R1T mode.
|
// data in the correct order when in 1R1T mode.
|
||||||
if (r_tx_ch == 0) begin
|
if (r_tx_ch == 0) begin
|
||||||
tx_i0_t <= tx_i0_del;
|
tx_i0_t <= tx_i0_del1;
|
||||||
tx_q0_t <= tx_q0_del;
|
tx_q0_t <= tx_q0_del1;
|
||||||
tx_i1_t <= tx_i0;
|
tx_i1_t <= tx_i0_del0;
|
||||||
tx_q1_t <= tx_q0;
|
tx_q1_t <= tx_q0_del0;
|
||||||
end else begin
|
end else begin
|
||||||
tx_i0_t <= tx_i1_del;
|
tx_i0_t <= tx_i1_del1;
|
||||||
tx_q0_t <= tx_q1_del;
|
tx_q0_t <= tx_q1_del1;
|
||||||
tx_i1_t <= tx_i1;
|
tx_i1_t <= tx_i1_del0;
|
||||||
tx_q1_t <= tx_q1;
|
tx_q1_t <= tx_q1_del0;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -313,17 +406,6 @@ module cat_io_lvds_dual_mode #(
|
|||||||
// Catalina TX/RX Interface
|
// Catalina TX/RX Interface
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
wire rx_aligned_t;
|
|
||||||
wire [11:0] rx_i0_t;
|
|
||||||
wire [11:0] rx_q0_t;
|
|
||||||
wire [11:0] rx_i1_t;
|
|
||||||
wire [11:0] rx_q1_t;
|
|
||||||
|
|
||||||
reg [11:0] tx_i0_t;
|
|
||||||
reg [11:0] tx_q0_t;
|
|
||||||
reg [11:0] tx_i1_t;
|
|
||||||
reg [11:0] tx_q1_t;
|
|
||||||
|
|
||||||
cat_io_lvds #(
|
cat_io_lvds #(
|
||||||
.INVERT_FRAME_RX (0),
|
.INVERT_FRAME_RX (0),
|
||||||
.INVERT_DATA_RX (6'b00_0000),
|
.INVERT_DATA_RX (6'b00_0000),
|
||||||
@@ -343,7 +425,7 @@ module cat_io_lvds_dual_mode #(
|
|||||||
.OUTPUT_DATA_DELAY (OUTPUT_DATA_DELAY),
|
.OUTPUT_DATA_DELAY (OUTPUT_DATA_DELAY),
|
||||||
.USE_BUFG (0)
|
.USE_BUFG (0)
|
||||||
) cat_io_lvds_i0 (
|
) cat_io_lvds_i0 (
|
||||||
.rst (rst),
|
.rst (radio_rst),
|
||||||
.clk200 (clk200),
|
.clk200 (clk200),
|
||||||
|
|
||||||
// Data and frame timing
|
// Data and frame timing
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
#
|
||||||
|
# Copyright 2020 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
|
||||||
|
#-------------------------------------------------
|
||||||
|
# Define part using PART_ID (<device>/<package>/<speedgrade>)
|
||||||
|
ARCH = kintex7
|
||||||
|
PART_ID = xc7k410t/ffg900/-2
|
||||||
|
|
||||||
|
# Include makefiles and sources for the DUT and its dependencies
|
||||||
|
include $(BASE_DIR)/../lib/fifo/Makefile.srcs
|
||||||
|
include $(BASE_DIR)/../lib/axi/Makefile.srcs
|
||||||
|
include $(BASE_DIR)/../lib/control/Makefile.srcs
|
||||||
|
include $(BASE_DIR)/../lib/io_cap_gen/Makefile.srcs
|
||||||
|
|
||||||
|
DESIGN_SRCS += $(abspath \
|
||||||
|
$(FIFO_SRCS) \
|
||||||
|
$(AXI_SRCS) \
|
||||||
|
$(CONTROL_LIB_SRCS) \
|
||||||
|
$(CAT_CAP_GEN_SRCS) \
|
||||||
|
)
|
||||||
|
|
||||||
|
#-------------------------------------------------
|
||||||
|
# IP Specific
|
||||||
|
#-------------------------------------------------
|
||||||
|
# If simulation contains IP, define the IP_DIR and point
|
||||||
|
# it to the base level IP directory
|
||||||
|
IP_DIR = $(BASE_DIR)/e320/ip
|
||||||
|
LIB_IP_DIR = $(BASE_DIR)/../lib/ip
|
||||||
|
|
||||||
|
# Include makefiles and sources for all IP components
|
||||||
|
# *after* defining the IP_DIR
|
||||||
|
include $(IP_DIR)/fifo_short_2clk/Makefile.inc
|
||||||
|
|
||||||
|
DESIGN_SRCS += $(abspath \
|
||||||
|
$(IP_FIFO_SHORT_2CLK_SRCS) \
|
||||||
|
)
|
||||||
|
|
||||||
|
#-------------------------------------------------
|
||||||
|
# Testbench Specific
|
||||||
|
#-------------------------------------------------
|
||||||
|
include $(BASE_DIR)/../sim/general/Makefile.srcs
|
||||||
|
include $(BASE_DIR)/../sim/axi/Makefile.srcs
|
||||||
|
|
||||||
|
MODELSIM_LIBS += unisims_ver secureip fifo_generator_v13_2_4
|
||||||
|
|
||||||
|
# Define only one top-level module
|
||||||
|
SIM_TOP = cat_io_lvds_dual_mode_tb glbl
|
||||||
|
|
||||||
|
# Simulation runtime in microseconds
|
||||||
|
SIM_RUNTIME_US = 1000
|
||||||
|
|
||||||
|
SIM_SRCS = \
|
||||||
|
$(IP_BUILD_DIR)/fifo_short_2clk/simulation/fifo_generator_vlog_beh.v \
|
||||||
|
$(IP_BUILD_DIR)/fifo_short_2clk/sim/fifo_short_2clk.v \
|
||||||
|
$(abspath cat_io_lvds_dual_mode_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
|
||||||
+133
-108
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// Copyright 2016 Ettus Research, A National Instruments Company
|
// Copyright 2020 Ettus Research, A National Instruments Company
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
//
|
//
|
||||||
@@ -12,6 +12,9 @@
|
|||||||
|
|
||||||
module cat_io_lvds_dual_mode_tb();
|
module cat_io_lvds_dual_mode_tb();
|
||||||
|
|
||||||
|
`include "test_exec.svh"
|
||||||
|
import PkgTestExec::*;
|
||||||
|
|
||||||
localparam CLK_PERIOD = 10;
|
localparam CLK_PERIOD = 10;
|
||||||
localparam CLK200_PERIOD = 2.5;
|
localparam CLK200_PERIOD = 2.5;
|
||||||
|
|
||||||
@@ -28,7 +31,6 @@ module cat_io_lvds_dual_mode_tb();
|
|||||||
localparam OUTPUT_CLOCK_DELAY = 31;
|
localparam OUTPUT_CLOCK_DELAY = 31;
|
||||||
localparam OUTPUT_DATA_DELAY = 0;
|
localparam OUTPUT_DATA_DELAY = 0;
|
||||||
|
|
||||||
reg [8*19:0] test_status;
|
|
||||||
reg check_enabled; // Controls when output checking is performed
|
reg check_enabled; // Controls when output checking is performed
|
||||||
|
|
||||||
reg clk = 0;
|
reg clk = 0;
|
||||||
@@ -99,10 +101,7 @@ module cat_io_lvds_dual_mode_tb();
|
|||||||
// Output a single burst of 2*len samples. In MIMO mode, this consists of len
|
// Output a single burst of 2*len samples. In MIMO mode, this consists of len
|
||||||
// samples on each channel. In SISO mode, this consists of 2*len samples on
|
// samples on each channel. In SISO mode, this consists of 2*len samples on
|
||||||
// the same channel.
|
// the same channel.
|
||||||
task Burst;
|
task Burst(int len, logic do_mimo);
|
||||||
input [31:0] len;
|
|
||||||
input do_mimo;
|
|
||||||
begin
|
|
||||||
repeat(len)
|
repeat(len)
|
||||||
begin
|
begin
|
||||||
mimo <= do_mimo;
|
mimo <= do_mimo;
|
||||||
@@ -137,8 +136,24 @@ module cat_io_lvds_dual_mode_tb();
|
|||||||
|
|
||||||
rx_count <= rx_count + 1;
|
rx_count <= rx_count + 1;
|
||||||
end
|
end
|
||||||
end
|
endtask : Burst
|
||||||
endtask // Burst
|
|
||||||
|
|
||||||
|
// Output zeros for len clk cycles (model what happens when the RFDC stops
|
||||||
|
// giving us data).
|
||||||
|
task Idle(int len = 100);
|
||||||
|
rx_d <= 0;
|
||||||
|
rx_frame <= 0;
|
||||||
|
repeat (len) @(posedge clk);
|
||||||
|
endtask : Idle
|
||||||
|
|
||||||
|
|
||||||
|
task Reset(int num_cycles = 20);
|
||||||
|
reset <= 1;
|
||||||
|
repeat(num_cycles) @(negedge rx_clk);
|
||||||
|
reset <= 0;
|
||||||
|
repeat(2) @(negedge rx_clk);
|
||||||
|
endtask : Reset
|
||||||
|
|
||||||
|
|
||||||
// Test receiving/transmitting 2*len samples, checking len-2 for correctness.
|
// Test receiving/transmitting 2*len samples, checking len-2 for correctness.
|
||||||
@@ -151,8 +166,7 @@ module cat_io_lvds_dual_mode_tb();
|
|||||||
input do_mimo;
|
input do_mimo;
|
||||||
begin
|
begin
|
||||||
if (len <= 2) begin
|
if (len <= 2) begin
|
||||||
$display("ERROR @%0t in %m: In TestBurst, len must be > 2", $time);
|
$fatal(1, "ERROR @%0t in %m: In TestBurst, len must be > 2", $time);
|
||||||
$finish;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
// Input several bursts, to fill the pipeline and cause results on the
|
// Input several bursts, to fill the pipeline and cause results on the
|
||||||
@@ -178,11 +192,12 @@ module cat_io_lvds_dual_mode_tb();
|
|||||||
// Test Procedure
|
// Test Procedure
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
initial
|
initial begin : main
|
||||||
begin
|
|
||||||
|
test.start_tb("cat_io_lvds_dual_mode_tb");
|
||||||
|
|
||||||
// Initial values
|
// Initial values
|
||||||
check_enabled <= 1'b0;
|
check_enabled <= 1'b0;
|
||||||
test_status <= "Reset";
|
|
||||||
reset = 1;
|
reset = 1;
|
||||||
mimo = 1;
|
mimo = 1;
|
||||||
ctrl_in_clk_delay = INPUT_CLOCK_DELAY;
|
ctrl_in_clk_delay = INPUT_CLOCK_DELAY;
|
||||||
@@ -193,14 +208,13 @@ module cat_io_lvds_dual_mode_tb();
|
|||||||
ctrl_out_data_delay = OUTPUT_DATA_DELAY;
|
ctrl_out_data_delay = OUTPUT_DATA_DELAY;
|
||||||
ctrl_ld_out_data_delay = 1'b0;
|
ctrl_ld_out_data_delay = 1'b0;
|
||||||
ctrl_ld_out_clk_delay = 1'b0;
|
ctrl_ld_out_clk_delay = 1'b0;
|
||||||
repeat(10) @(negedge rx_clk);
|
|
||||||
reset = 0;
|
Reset();
|
||||||
@(negedge rx_clk);
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
// Test Changing Delays
|
// Test Changing Delays
|
||||||
|
|
||||||
test_status <= "Load IO delays";
|
test.start_test("Load IO delays");
|
||||||
|
|
||||||
if (CLOCK_IDELAY_MODE == "VAR_LOAD") begin
|
if (CLOCK_IDELAY_MODE == "VAR_LOAD") begin
|
||||||
ctrl_ld_in_clk_delay = 1'b1;
|
ctrl_ld_in_clk_delay = 1'b1;
|
||||||
@@ -230,130 +244,159 @@ module cat_io_lvds_dual_mode_tb();
|
|||||||
@(negedge rx_clk);
|
@(negedge rx_clk);
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test.end_test();
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
// Startup
|
// Startup
|
||||||
|
|
||||||
test_status <= "Startup";
|
test.start_test("Load IO delays");
|
||||||
|
|
||||||
// Pump a few clock cycles to get things started (flush out X values)
|
// Pump a few clock cycles to get things started (flush out X values)
|
||||||
Burst(2,1);
|
Burst(2,1);
|
||||||
|
|
||||||
|
test.end_test();
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
// Test MIMO
|
// Test MIMO
|
||||||
|
|
||||||
|
test.start_test("Test MIMO");
|
||||||
|
|
||||||
// Input data until the Rx circuit aligns
|
// Input data until the Rx circuit aligns
|
||||||
test_status <= "Wait align 1";
|
$display("Wait align 1");
|
||||||
while (!rx_aligned) begin
|
while (!rx_aligned) begin
|
||||||
Burst(1,1);
|
Burst(1,1);
|
||||||
end
|
end
|
||||||
|
|
||||||
// Input some new samples
|
// Input some new samples
|
||||||
test_status <= "Burst 1 (MIMO)";
|
$display("Burst 1 (MIMO)");
|
||||||
TestBurst(30, 1);
|
TestBurst(30, 1);
|
||||||
|
|
||||||
// Reset and do another burst
|
// Reset and do another burst
|
||||||
test_status <= "Reset 2";
|
$display("Reset 2");
|
||||||
reset = 1;
|
Reset();
|
||||||
repeat(20) @(negedge rx_clk);
|
|
||||||
reset = 0;
|
|
||||||
repeat(2) @(negedge rx_clk);
|
|
||||||
|
|
||||||
// Input data until the Rx circuit aligns
|
// Input data until the Rx circuit aligns
|
||||||
test_status <= "Wait align 2";
|
$display("Wait align 2");
|
||||||
while (!rx_aligned) begin
|
while (!rx_aligned) begin
|
||||||
Burst(1,1);
|
Burst(1,1);
|
||||||
end
|
end
|
||||||
|
|
||||||
// Input some new samples
|
// Input some new samples
|
||||||
test_status <= "Burst 2 (MIMO)";
|
$display("Burst 2 (MIMO)");
|
||||||
TestBurst(23, 1);
|
TestBurst(23, 1);
|
||||||
|
|
||||||
|
test.end_test();
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
// Test SISO (transmit channel 0)
|
// Test SISO (transmit channel 0)
|
||||||
|
|
||||||
|
test.start_test("Test SISO (transmit channel 0)");
|
||||||
|
|
||||||
tx_ch <= 1'b0;
|
tx_ch <= 1'b0;
|
||||||
|
|
||||||
// Reset and do another burst
|
// Reset and do another burst
|
||||||
test_status <= "Reset 3";
|
$display("Reset 3");
|
||||||
reset = 1;
|
Reset();
|
||||||
repeat(20) @(negedge rx_clk);
|
|
||||||
reset = 0;
|
|
||||||
repeat(2) @(negedge rx_clk);
|
|
||||||
|
|
||||||
// Input data until the Rx circuit aligns in SISO mode
|
// Input data until the Rx circuit aligns in SISO mode
|
||||||
test_status <= "Wait align 3";
|
$display("Wait align 3");
|
||||||
while (!rx_aligned) begin
|
while (!rx_aligned) Burst(1,0);
|
||||||
Burst(1,0);
|
|
||||||
end
|
|
||||||
|
|
||||||
// Test SISO mode
|
// Test SISO mode
|
||||||
test_status <= "Burst 3 (SISO, Ch 0)";
|
$display("Burst 3 (SISO, Ch 0)");
|
||||||
TestBurst(25, 0);
|
TestBurst(25, 0);
|
||||||
|
|
||||||
// Reset and do another burst
|
// Reset and do another burst
|
||||||
test_status <= "Reset 4";
|
$display("Reset 4");
|
||||||
reset = 1;
|
Reset();
|
||||||
repeat(20) @(negedge rx_clk);
|
|
||||||
reset = 0;
|
|
||||||
repeat(2) @(negedge rx_clk);
|
|
||||||
|
|
||||||
// Input data until the Rx circuit aligns in SISO mode
|
// Input data until the Rx circuit aligns in SISO mode
|
||||||
test_status <= "Wait align 4";
|
$display("Wait align 4");
|
||||||
while (!rx_aligned) begin
|
while (!rx_aligned) Burst(1,0);
|
||||||
Burst(1,0);
|
|
||||||
end
|
|
||||||
|
|
||||||
// Test SISO mode
|
// Test SISO mode
|
||||||
test_status <= "Burst 4 (SISO, Ch 0)";
|
$display("Burst 4 (SISO, Ch 0)");
|
||||||
TestBurst(27, 0);
|
TestBurst(27, 0);
|
||||||
|
|
||||||
|
test.end_test();
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
// Test SISO (transmit channel 1)
|
// Test SISO (transmit channel 1)
|
||||||
|
|
||||||
|
test.start_test("Test SISO (transmit channel 1)");
|
||||||
|
|
||||||
tx_ch <= 1'b1;
|
tx_ch <= 1'b1;
|
||||||
|
|
||||||
// Reset and do another burst
|
// Reset and do another burst
|
||||||
test_status <= "Reset 5";
|
$display("Reset 5");
|
||||||
reset = 1;
|
Reset();
|
||||||
repeat(20) @(negedge rx_clk);
|
|
||||||
reset = 0;
|
|
||||||
repeat(2) @(negedge rx_clk);
|
|
||||||
|
|
||||||
// Input data until the Rx circuit aligns in SISO mode
|
// Input data until the Rx circuit aligns in SISO mode
|
||||||
test_status <= "Wait align 5";
|
$display("Wait align 5");
|
||||||
while (!rx_aligned) begin
|
while (!rx_aligned) Burst(1,0);
|
||||||
Burst(1,0);
|
|
||||||
end
|
|
||||||
|
|
||||||
// Test SISO mode
|
// Test SISO mode
|
||||||
test_status <= "Burst 5 (SISO, Ch 1)";
|
$display("Burst 5 (SISO, Ch 1)");
|
||||||
TestBurst(25, 0);
|
TestBurst(25, 0);
|
||||||
|
|
||||||
// Reset and do another burst
|
// Reset and do another burst
|
||||||
test_status <= "Reset 6";
|
$display("Reset 6");
|
||||||
reset = 1;
|
Reset();
|
||||||
repeat(20) @(negedge rx_clk);
|
|
||||||
reset = 0;
|
|
||||||
repeat(2) @(negedge rx_clk);
|
|
||||||
|
|
||||||
// Input data until the Rx circuit aligns in SISO mode
|
// Input data until the Rx circuit aligns in SISO mode
|
||||||
test_status <= "Wait align 6";
|
$display("Wait align 6");
|
||||||
|
while (!rx_aligned) Burst(1,0);
|
||||||
|
|
||||||
|
// Test SISO mode
|
||||||
|
$display("Burst 6 (SISO, Ch 1)");
|
||||||
|
TestBurst(27, 0);
|
||||||
|
|
||||||
|
test.end_test();
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
// Test going Idle then starting SISO, without reset
|
||||||
|
|
||||||
|
test.start_test("Test Idle then SISO");
|
||||||
|
|
||||||
|
tx_ch <= 1'b1;
|
||||||
|
|
||||||
|
$display("Wait idle flush 6");
|
||||||
|
while (rx_aligned) Idle(1);
|
||||||
|
$display("Wait align 6");
|
||||||
|
while (!rx_aligned) Burst(1,0);
|
||||||
|
|
||||||
|
// Test SISO mode
|
||||||
|
$display("Burst 6 (SISO, Ch 1)");
|
||||||
|
TestBurst(25, 0);
|
||||||
|
|
||||||
|
test.end_test();
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
// Test going Idle then starting MIMO, without reset
|
||||||
|
|
||||||
|
test.start_test("Test Idle then MIMO");
|
||||||
|
|
||||||
|
tx_ch <= 1'b1;
|
||||||
|
|
||||||
|
$display("Wait idle flush 7");
|
||||||
|
while (rx_aligned) Idle(1);
|
||||||
|
$display("Wait align 7");
|
||||||
while (!rx_aligned) begin
|
while (!rx_aligned) begin
|
||||||
Burst(1,0);
|
Burst(1,1);
|
||||||
end
|
end
|
||||||
|
|
||||||
// Test SISO mode
|
// Test SISO mode
|
||||||
test_status <= "Burst 6 (SISO, Ch 1)";
|
$display("Burst 7 (SISO, Ch 1)");
|
||||||
TestBurst(27, 0);
|
TestBurst(25, 1);
|
||||||
|
|
||||||
|
test.end_test();
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
// Done
|
// Done
|
||||||
|
|
||||||
test_status <= "Finished";
|
test.end_tb();
|
||||||
repeat(50) @(negedge rx_clk);
|
end : main
|
||||||
|
|
||||||
$finish;
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -391,45 +434,39 @@ module cat_io_lvds_dual_mode_tb();
|
|||||||
|
|
||||||
// Check prefix for channel 0
|
// Check prefix for channel 0
|
||||||
if (rx_i0[11:8] != 4'hA || rx_q0[11:8] != 4'hB) begin
|
if (rx_i0[11:8] != 4'hA || rx_q0[11:8] != 4'hB) begin
|
||||||
$display("ERROR @%0t in %m: Rx channel 0 didn't have expected A/B prefix in MIMO mode", $time);
|
$fatal(1, "ERROR in %m: Rx channel 0 didn't have expected A/B prefix in MIMO mode");
|
||||||
$finish;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
// Check prefix for channel 1
|
// Check prefix for channel 1
|
||||||
if (rx_i1[11:8] != 4'hC || rx_q1[11:8] != 4'hD) begin
|
if (rx_i1[11:8] != 4'hC || rx_q1[11:8] != 4'hD) begin
|
||||||
$display("ERROR @%0t in %m: Rx channel 1 didn't have expected C/D in MIMO mode", $time);
|
$fatal(1, "ERROR in %m: Rx channel 1 didn't have expected C/D in MIMO mode");
|
||||||
$finish;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
// All outputs should have the same count in MIMO mode
|
// All outputs should have the same count in MIMO mode
|
||||||
if (! (rx_i0[7:0] == rx_q0[7:0] &&
|
if (! (rx_i0[7:0] == rx_q0[7:0] &&
|
||||||
rx_i0[7:0] == rx_i1[7:0] &&
|
rx_i0[7:0] == rx_i1[7:0] &&
|
||||||
rx_i0[7:0] == rx_q1[7:0]) ) begin
|
rx_i0[7:0] == rx_q1[7:0]) ) begin
|
||||||
$display("ERROR @%0t in %m: Rx data counts didn't match on all outputs in MIMO mode", $time);
|
$fatal(1, "ERROR in %m: Rx data counts didn't match on all outputs in MIMO mode");
|
||||||
$finish;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
// Make sure the count increments
|
// Make sure the count increments
|
||||||
if (rx_i0[7:0] != rx_i0_del1[7:0] + 8'd1 || rx_q0[7:0] != rx_q0_del1[7:0] + 8'd1 ||
|
if (rx_i0[7:0] != rx_i0_del1[7:0] + 8'd1 || rx_q0[7:0] != rx_q0_del1[7:0] + 8'd1 ||
|
||||||
rx_i1[7:0] != rx_i1_del1[7:0] + 8'd1 || rx_q1[7:0] != rx_q1_del1[7:0] + 8'd1) begin
|
rx_i1[7:0] != rx_i1_del1[7:0] + 8'd1 || rx_q1[7:0] != rx_q1_del1[7:0] + 8'd1) begin
|
||||||
$display("ERROR @%0t in %m: Rx data count didn't increment as expected", $time);
|
$fatal(1, "ERROR in %m: Rx data count didn't increment as expected");
|
||||||
$finish;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end else begin // if (mimo)
|
end else begin // if (mimo)
|
||||||
|
|
||||||
// In SISO mode, both outputs should be the same
|
// In SISO mode, both outputs should be the same
|
||||||
if (rx_i0 != rx_i1 || rx_q0 != rx_q1) begin
|
if (rx_i0 != rx_i1 || rx_q0 != rx_q1) begin
|
||||||
$display("ERROR @%0t in %m: Rx channel 0 and 1 don't match in SISO mode", $time);
|
$fatal(1, "ERROR in %m: Rx channel 0 and 1 don't match in SISO mode");
|
||||||
$finish;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
// Check channel 0 prefix. No need to check channel 1, since we
|
// Check channel 0 prefix. No need to check channel 1, since we
|
||||||
// already checked that the channels match.
|
// already checked that the channels match.
|
||||||
if (!((rx_i0[11:8] == 4'hA && rx_q0[11:8] == 4'hB) ||
|
if (!((rx_i0[11:8] == 4'hA && rx_q0[11:8] == 4'hB) ||
|
||||||
(rx_i0[11:8] == 4'hC && rx_q0[11:8] == 4'hD))) begin
|
(rx_i0[11:8] == 4'hC && rx_q0[11:8] == 4'hD))) begin
|
||||||
$display("ERROR @%0t in %m: Rx data didn't have expected A/B or C/D prefix in SISO mode", $time);
|
$fatal(1, "ERROR in %m: Rx data didn't have expected A/B or C/D prefix in SISO mode");
|
||||||
$finish;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
// Make sure we're alternating between channel data. No need to check
|
// Make sure we're alternating between channel data. No need to check
|
||||||
@@ -438,15 +475,13 @@ module cat_io_lvds_dual_mode_tb();
|
|||||||
(rx_i0[11:8] == 4'hC && rx_i0_del1[11:8] == 4'hA) ||
|
(rx_i0[11:8] == 4'hC && rx_i0_del1[11:8] == 4'hA) ||
|
||||||
(rx_q0[11:8] == 4'hB && rx_q0_del1[11:8] == 4'hD) ||
|
(rx_q0[11:8] == 4'hB && rx_q0_del1[11:8] == 4'hD) ||
|
||||||
(rx_q0[11:8] == 4'hD && rx_q0_del1[11:8] == 4'hB))) begin
|
(rx_q0[11:8] == 4'hD && rx_q0_del1[11:8] == 4'hB))) begin
|
||||||
$display("ERROR @%0t in %m: Rx data not toggling between channel data in SISO mode", $time);
|
$fatal(1, "ERROR in %m: Rx data not toggling between channel data in SISO mode");
|
||||||
$finish;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
// Make sure the counts are the same for both I and Q. No need to
|
// Make sure the counts are the same for both I and Q. No need to
|
||||||
// check channel 1, since we already checked that the channels match.
|
// check channel 1, since we already checked that the channels match.
|
||||||
if (rx_i0[7:0] != rx_q0[7:0]) begin
|
if (rx_i0[7:0] != rx_q0[7:0]) begin
|
||||||
$display("ERROR @%0t in %m: Rx data counts didn't match on all outputs in SISO mode", $time);
|
$fatal(1, "ERROR in %m: Rx data counts didn't match on all outputs in SISO mode");
|
||||||
$finish;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
// Make sure the count increments every other clock cycle. No need to
|
// Make sure the count increments every other clock cycle. No need to
|
||||||
@@ -455,8 +490,7 @@ module cat_io_lvds_dual_mode_tb();
|
|||||||
rx_i0[7:0] != rx_i0_del2[7:0] + 8'd1 && (rx_i0[7:0] == rx_i0_del1[7:0] || rx_i0[7:0] == rx_i0_del1[7:0] + 8'd1) &&
|
rx_i0[7:0] != rx_i0_del2[7:0] + 8'd1 && (rx_i0[7:0] == rx_i0_del1[7:0] || rx_i0[7:0] == rx_i0_del1[7:0] + 8'd1) &&
|
||||||
rx_q0[7:0] != rx_q0_del2[7:0] + 8'd1 && (rx_q0[7:0] == rx_q0_del1[7:0] || rx_q0[7:0] == rx_q0_del1[7:0] + 8'd1)
|
rx_q0[7:0] != rx_q0_del2[7:0] + 8'd1 && (rx_q0[7:0] == rx_q0_del1[7:0] || rx_q0[7:0] == rx_q0_del1[7:0] + 8'd1)
|
||||||
)) begin
|
)) begin
|
||||||
$display("ERROR @%0t in %m: Rx data count didn't increment as expected", $time);
|
$fatal(1, "ERROR in %m: Rx data count didn't increment as expected");
|
||||||
$finish;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end // if (mimo)
|
end // if (mimo)
|
||||||
@@ -557,35 +591,30 @@ module cat_io_lvds_dual_mode_tb();
|
|||||||
|
|
||||||
// Check that the frame signal is correct
|
// Check that the frame signal is correct
|
||||||
if (tx_frame_check != 8'b11110000) begin
|
if (tx_frame_check != 8'b11110000) begin
|
||||||
$display("ERROR @%0t in %m: Tx frame was not correct in MIMO mode", $time);
|
$fatal(1, "ERROR @%0t in %m: Tx frame was not correct in MIMO mode", $time);
|
||||||
$finish;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
// Check prefix for channel 0
|
// Check prefix for channel 0
|
||||||
if (tx_i0_check[11:8] != 4'hA || tx_q0_check[11:8] != 4'hB) begin
|
if (tx_i0_check[11:8] != 4'hA || tx_q0_check[11:8] != 4'hB) begin
|
||||||
$display("ERROR @%0t in %m: Tx channel 0 didn't have expected A/B prefix in MIMO mode", $time);
|
$fatal(1, "ERROR @%0t in %m: Tx channel 0 didn't have expected A/B prefix in MIMO mode", $time);
|
||||||
$finish;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
// Check prefix for channel 1
|
// Check prefix for channel 1
|
||||||
if (tx_i1_check[11:8] != 4'hC || tx_q1_check[11:8] != 4'hD) begin
|
if (tx_i1_check[11:8] != 4'hC || tx_q1_check[11:8] != 4'hD) begin
|
||||||
$display("ERROR @%0t in %m: Tx channel 1 didn't have expected C/D in MIMO mode", $time);
|
$fatal(1, "ERROR @%0t in %m: Tx channel 1 didn't have expected C/D in MIMO mode", $time);
|
||||||
$finish;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
// All outputs should have the same count in MIMO mode
|
// All outputs should have the same count in MIMO mode
|
||||||
if (! (tx_i0_check[7:0] == tx_q0_check[7:0] &&
|
if (! (tx_i0_check[7:0] == tx_q0_check[7:0] &&
|
||||||
tx_i0_check[7:0] == tx_i1_check[7:0] &&
|
tx_i0_check[7:0] == tx_i1_check[7:0] &&
|
||||||
tx_i0_check[7:0] == tx_q1_check[7:0]) ) begin
|
tx_i0_check[7:0] == tx_q1_check[7:0]) ) begin
|
||||||
$display("ERROR @%0t in %m: Rx data counts didn't match on all outputs in MIMO mode", $time);
|
$fatal(1, "ERROR @%0t in %m: Rx data counts didn't match on all outputs in MIMO mode", $time);
|
||||||
$finish;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
// Make sure the count increments
|
// Make sure the count increments
|
||||||
if (tx_i0_check[7:0] != tx_i0_del1[7:0] + 8'd1 || tx_q0_check[7:0] != tx_q0_del1[7:0] + 8'd1 ||
|
if (tx_i0_check[7:0] != tx_i0_del1[7:0] + 8'd1 || tx_q0_check[7:0] != tx_q0_del1[7:0] + 8'd1 ||
|
||||||
tx_i1_check[7:0] != tx_i1_del1[7:0] + 8'd1 || tx_q1_check[7:0] != tx_q1_del1[7:0] + 8'd1) begin
|
tx_i1_check[7:0] != tx_i1_del1[7:0] + 8'd1 || tx_q1_check[7:0] != tx_q1_del1[7:0] + 8'd1) begin
|
||||||
$display("ERROR @%0t in %m: Rx data count didn't increment as expected", $time);
|
$fatal(1, "ERROR @%0t in %m: Rx data count didn't increment as expected", $time);
|
||||||
$finish;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end else begin
|
end else begin
|
||||||
@@ -595,8 +624,7 @@ module cat_io_lvds_dual_mode_tb();
|
|||||||
|
|
||||||
// Check that the frame signal is correct
|
// Check that the frame signal is correct
|
||||||
if (tx_frame_check != 8'b11001100) begin
|
if (tx_frame_check != 8'b11001100) begin
|
||||||
$display("ERROR @%0t in %m: Tx frame was not correct in SISO mode", $time);
|
$fatal(1, "ERROR @%0t in %m: Tx frame was not correct in SISO mode", $time);
|
||||||
$finish;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -633,8 +661,7 @@ module cat_io_lvds_dual_mode_tb();
|
|||||||
(tx_i0_check[11:8] == tx_i1_check[11:8] &&
|
(tx_i0_check[11:8] == tx_i1_check[11:8] &&
|
||||||
tx_q0_check[11:8] == tx_q1_check[11:8])
|
tx_q0_check[11:8] == tx_q1_check[11:8])
|
||||||
)) begin
|
)) begin
|
||||||
$display("ERROR @%0t in %m: Tx channel didn't have expected prefixes in SISO mode", $time);
|
$fatal(1, "ERROR @%0t in %m: Tx channel didn't have expected prefixes in SISO mode", $time);
|
||||||
$finish;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
// Check that the data count matches between samples
|
// Check that the data count matches between samples
|
||||||
@@ -643,8 +670,7 @@ module cat_io_lvds_dual_mode_tb();
|
|||||||
tx_i1_check[7:0] == tx_q1_check[7:0] &&
|
tx_i1_check[7:0] == tx_q1_check[7:0] &&
|
||||||
tx_i0_check[7:0] == tx_i1_check[7:0] - 8'd1
|
tx_i0_check[7:0] == tx_i1_check[7:0] - 8'd1
|
||||||
)) begin
|
)) begin
|
||||||
$display("ERROR @%0t in %m: Tx channel data counts didn't correlate in SISO mode", $time);
|
$fatal(1, "ERROR @%0t in %m: Tx channel data counts didn't correlate in SISO mode", $time);
|
||||||
$finish;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
// Make sure the count increments form one burst to the next
|
// Make sure the count increments form one burst to the next
|
||||||
@@ -652,8 +678,7 @@ module cat_io_lvds_dual_mode_tb();
|
|||||||
tx_q0_check[7:0] != tx_q0_del1[7:0] + 8'd2 ||
|
tx_q0_check[7:0] != tx_q0_del1[7:0] + 8'd2 ||
|
||||||
tx_i1_check[7:0] != tx_i1_del1[7:0] + 8'd2 ||
|
tx_i1_check[7:0] != tx_i1_del1[7:0] + 8'd2 ||
|
||||||
tx_q1_check[7:0] != tx_q1_del1[7:0] + 8'd2) begin
|
tx_q1_check[7:0] != tx_q1_del1[7:0] + 8'd2) begin
|
||||||
$display("ERROR @%0t in %m: Tx data count didn't increment as expected", $time);
|
$fatal(1, "ERROR @%0t in %m: Tx data count didn't increment as expected", $time);
|
||||||
$finish;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@@ -727,7 +752,6 @@ module cat_io_lvds_dual_mode_tb();
|
|||||||
.OUTPUT_CLOCK_DELAY (OUTPUT_CLOCK_DELAY),
|
.OUTPUT_CLOCK_DELAY (OUTPUT_CLOCK_DELAY),
|
||||||
.OUTPUT_DATA_DELAY (OUTPUT_DATA_DELAY)
|
.OUTPUT_DATA_DELAY (OUTPUT_DATA_DELAY)
|
||||||
) cat_io_lvds_dual_mode_dut (
|
) cat_io_lvds_dual_mode_dut (
|
||||||
.rst (reset),
|
|
||||||
.clk200 (clk200),
|
.clk200 (clk200),
|
||||||
|
|
||||||
// Data and frame timing
|
// Data and frame timing
|
||||||
@@ -748,6 +772,7 @@ module cat_io_lvds_dual_mode_tb();
|
|||||||
.ctrl_ld_out_clk_delay (ctrl_ld_out_clk_delay),
|
.ctrl_ld_out_clk_delay (ctrl_ld_out_clk_delay),
|
||||||
|
|
||||||
// Baseband sample interface
|
// Baseband sample interface
|
||||||
|
.radio_rst (reset),
|
||||||
.radio_clk (radio_clk),
|
.radio_clk (radio_clk),
|
||||||
.rx_aligned (rx_aligned),
|
.rx_aligned (rx_aligned),
|
||||||
//
|
//
|
||||||
+2
-3
@@ -818,7 +818,6 @@ module e320 (
|
|||||||
wire [REG_DWIDTH-1:0] dboard_status;
|
wire [REG_DWIDTH-1:0] dboard_status;
|
||||||
wire mimo_busclk, mimo_radioclk;
|
wire mimo_busclk, mimo_radioclk;
|
||||||
wire tx_chan_sel_busclk, tx_chan_sel_radioclk;
|
wire tx_chan_sel_busclk, tx_chan_sel_radioclk;
|
||||||
wire rx_aligned;
|
|
||||||
|
|
||||||
wire tx_pll_lock_busclk, rx_pll_lock_busclk;
|
wire tx_pll_lock_busclk, rx_pll_lock_busclk;
|
||||||
|
|
||||||
@@ -890,7 +889,6 @@ module e320 (
|
|||||||
.OUTPUT_CLOCK_DELAY (0),
|
.OUTPUT_CLOCK_DELAY (0),
|
||||||
.OUTPUT_DATA_DELAY (OUTPUT_DATA_DELAY)
|
.OUTPUT_DATA_DELAY (OUTPUT_DATA_DELAY)
|
||||||
) cat_io_lvds_dual_mode_i0 (
|
) cat_io_lvds_dual_mode_i0 (
|
||||||
.rst (radio_rst),
|
|
||||||
.clk200 (bus_clk), // 200 MHz clock
|
.clk200 (bus_clk), // 200 MHz clock
|
||||||
|
|
||||||
// Data and frame timing
|
// Data and frame timing
|
||||||
@@ -911,9 +909,10 @@ module e320 (
|
|||||||
.ctrl_ld_out_clk_delay (1'b0),
|
.ctrl_ld_out_clk_delay (1'b0),
|
||||||
|
|
||||||
// Sample interface
|
// Sample interface
|
||||||
|
.radio_rst (radio_rst),
|
||||||
.radio_clk (radio_clk),
|
.radio_clk (radio_clk),
|
||||||
.rx_aligned (rx_aligned),
|
|
||||||
//
|
//
|
||||||
|
.rx_aligned (),
|
||||||
.rx_i0 (rx_i0),
|
.rx_i0 (rx_i0),
|
||||||
.rx_q0 (rx_q0),
|
.rx_q0 (rx_q0),
|
||||||
.rx_i1 (rx_i1),
|
.rx_i1 (rx_i1),
|
||||||
|
|||||||
Reference in New Issue
Block a user