aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp3/top/n3xx/dboards/rh/cpld/rh_tb.v
diff options
context:
space:
mode:
Diffstat (limited to 'fpga/usrp3/top/n3xx/dboards/rh/cpld/rh_tb.v')
-rw-r--r--fpga/usrp3/top/n3xx/dboards/rh/cpld/rh_tb.v410
1 files changed, 410 insertions, 0 deletions
diff --git a/fpga/usrp3/top/n3xx/dboards/rh/cpld/rh_tb.v b/fpga/usrp3/top/n3xx/dboards/rh/cpld/rh_tb.v
new file mode 100644
index 000000000..fb5f62328
--- /dev/null
+++ b/fpga/usrp3/top/n3xx/dboards/rh/cpld/rh_tb.v
@@ -0,0 +1,410 @@
+///////////////////////////////////////////////////////////////////
+//
+// Copyright 2018 Ettus Research, A National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+// Module: rh_tb
+// Simple testbench for rhodium_top
+// This creates a rudimentary stimulus only, to allow results to be viewed
+// in the waveform viewer
+//////////////////////////////////////////////////////////////////////
+
+`timescale 1ns/1ps
+
+
+module rh_tb;
+
+reg ADC_A_Over_Range_18, ADC_B_Over_Range_18;
+
+wire [13:0] usrpio_io; // TODO: use one of these as pl_spi_addr[3]
+
+wire CPLD_PS_SPI_LE_25, CPLD_PS_SPI_CLK_25,
+ CPLD_PS_ADDR0_25, CPLD_PS_ADDR1_25, CPLD_PS_SPI_SDI_25;
+wire CPLD_PS_SPI_SDO_25;
+
+wire CPLD_PL_SPI_SDO_18;
+wire CPLD_PL_SPI_LE_18, CPLD_PL_SPI_SCLK_18,
+ CPLD_PL_SPI_SDI_18,
+ CPLD_PL_SPI_ADDR0_18, CPLD_PL_SPI_ADDR1_18,
+ CPLD_PL_SPI_ADDR2_18,
+ CPLD_ATR_TX_18, CPLD_ATR_RX_18;
+// NOTE: TxRx front-end switches are driven direct from the motherboard, so these ATR
+// lines have no function at this time.
+
+wire ADC_SPI_CS_L_18, ADC_SPI_SCLK_18;
+wire ADC_SPI_SDIO_18;
+
+wire DAC_SPI_CS_L_18, DAC_SPI_SCLK_18;
+wire DAC_SPI_SDIO_18;
+reg DAC_Alarm_18; // TODO: drive to gpio?
+
+wire PHDAC_SPI_CS_L, PHDAC_SPI_SCLK, PHDAC_SPI_SDI;
+
+
+reg LO_SYNC;
+
+wire CLKDIST_SPI_CS_L,
+ CLKDIST_SPI_SCLK;
+wire CLKDIST_SPI_SDIO;
+
+wire Tx_DSA_C1,
+ Tx_DSA_C2,
+ Tx_DSA_C4,
+ Tx_DSA_C8,
+ Tx_DSA_C16;
+ wire Tx_DSA1_LE,
+ Tx_DSA2_LE;
+ wire Tx_Sw1_Ctrl_1,
+ Tx_Sw1_Ctrl_2,
+ Tx_Sw2_Ctrl_1,
+ Tx_Sw2_Ctrl_2,
+ Tx_Sw3_Ctrl_1,
+ Tx_Sw3_Ctrl_2,
+ Tx_Sw3_Ctrl_3,
+ Tx_Sw3_Ctrl_4,
+ Rx_LO_Input_Select,
+ Rx_LO_Filter_Sw_1,
+ Rx_LO_Filter_Sw_2,
+ Tx_LO_Input_Select,
+ Tx_LO_Filter_Sw_1,
+ Tx_LO_Filter_Sw_2;
+wire CLKDIST_Status_LD1,
+ CLKDIST_Status_LD2;
+wire LOSYNTH_RX_MUXOUT,
+ LOSYNTH_TX_MUXOUT;
+
+wire LO_SPI_SCLK,
+ LO_SPI_SDI,
+ LO_TX_CS_L,
+ LO_RX_CS_L,
+ Rx_Sw1_Ctrl_1,
+ Rx_Sw1_Ctrl_2,
+ Rx_DSA_C1,
+ Rx_DSA_C2,
+ Rx_DSA_C4,
+ Rx_DSA_C8,
+ Rx_DSA_C16;
+ wire Rx_DSA1_LE,
+ Rx_DSA2_LE;
+ wire Rx_Sw2_Ctrl,
+ Rx_Sw3_Ctrl_1,
+ Rx_Sw3_Ctrl_2,
+ Rx_Sw4_Ctrl_1,
+ Rx_Sw4_Ctrl_2,
+ Rx_Sw4_Ctrl_3,
+ Rx_Sw4_Ctrl_4,
+ Rx_Demod_ADJ_1,
+ Rx_Demod_ADJ_2;
+wire LO_DSA_C1,
+ LO_DSA_C2,
+ LO_DSA_C4,
+ LO_DSA_C8,
+ LO_DSA_C16;
+wire RxLO_DSA_LE,
+ TxLO_DSA_LE;
+wire LODIST_Bd_SPI_CS_L,
+ LODIST_Bd_SPI_SDI,
+ LODIST_Bd_SPI_SCLK,
+ Tx_Sw5_Ctrl_1,
+ Tx_Sw5_Ctrl_2,
+ Rx_Sw6_Ctrl_1,
+ Rx_Sw6_Ctrl_2;
+wire LODIST_Bd_IO1;
+wire Tx_HB_LB_Select,
+Rx_HB_LB_Select,
+Cal_iso_Sw_Ctrl;
+
+
+parameter dly = 20;
+
+integer scnt;
+integer acnt;
+integer ccnt;
+integer ccnt_max;
+
+reg ps_sck;
+reg ps_mosi;
+reg clkdis_cs_b;
+reg cpld_ps_cs_b;
+reg phdac_cs_b;
+reg adc_cs_b;
+reg dac_cs_b;
+
+reg pl_sck;
+reg pl_mosi;
+reg txlo_cs_b;
+reg rxlo_cs_b;
+reg lodis_cs_b;
+reg cpld_pl_cs_b;
+
+task ps_cpld_xfer;
+ input [1:0] tbl;
+ input [5:0] cmd;
+ input [15:0] data;
+ reg [23:0] shiftreg;
+ integer i;
+begin
+ ps_sck <= 1'b0;
+ clkdis_cs_b <= 1'b1;
+ cpld_ps_cs_b <= 1'b1;
+ phdac_cs_b <= 1'b1;
+ adc_cs_b <= 1'b1;
+ dac_cs_b <= 1'b1;
+ txlo_cs_b <= 1'b1;
+ rxlo_cs_b <= 1'b1;
+ lodis_cs_b <= 1'b1;
+ cpld_pl_cs_b <= 1'b1;
+ shiftreg <= {tbl,cmd,data};
+ #(dly);
+ cpld_ps_cs_b <= 1'b0;
+ #(dly);
+ for (i = 0; i < 24; i = i + 1) begin
+ ps_sck <= 1'b0;
+ ps_mosi <= shiftreg[23-i];
+ #(dly);
+ ps_sck <= 1'b1;
+ #(dly);
+ end
+ ps_sck <= 1'b0;
+ #(dly);
+ cpld_ps_cs_b <= 1'b1;
+ #(dly);
+end
+endtask
+
+task pl_cpld_xfer;
+ input [1:0] tbl;
+ input [5:0] cmd;
+ input [15:0] data;
+ reg [23:0] shiftreg;
+ integer i;
+begin
+ pl_sck <= 1'b0;
+ clkdis_cs_b <= 1'b1;
+ cpld_ps_cs_b <= 1'b1;
+ phdac_cs_b <= 1'b1;
+ adc_cs_b <= 1'b1;
+ dac_cs_b <= 1'b1;
+ txlo_cs_b <= 1'b1;
+ rxlo_cs_b <= 1'b1;
+ lodis_cs_b <= 1'b1;
+ cpld_pl_cs_b <= 1'b1;
+ shiftreg <= {tbl,cmd,data};
+ #(dly);
+ cpld_pl_cs_b <= 1'b0;
+ #(dly);
+ for (i = 0; i < 24; i = i + 1) begin
+ pl_sck <= 1'b0;
+ pl_mosi <= shiftreg[23-i];
+ #(dly);
+ pl_sck <= 1'b1;
+ #(dly);
+ end
+ pl_sck <= 1'b0;
+ #(dly);
+ cpld_pl_cs_b <= 1'b1;
+ #(dly);
+end
+endtask
+
+assign CPLD_PS_SPI_LE_25 = clkdis_cs_b;
+assign CPLD_PS_ADDR0_25 = cpld_ps_cs_b;
+assign CPLD_PS_ADDR1_25 = phdac_cs_b;
+assign usrpio_io[12] = adc_cs_b;
+assign usrpio_io[13] = dac_cs_b;
+assign CPLD_PS_SPI_CLK_25 = ps_sck;
+assign CPLD_PS_SPI_SDI_25 = ps_mosi;
+
+assign CPLD_PL_SPI_LE_18 = txlo_cs_b;
+assign CPLD_PL_SPI_ADDR1_18 = rxlo_cs_b;
+assign CPLD_PL_SPI_ADDR2_18 = lodis_cs_b;
+assign CPLD_PL_SPI_ADDR0_18 = cpld_pl_cs_b;
+assign CPLD_PL_SPI_SCLK_18 = pl_sck;
+assign CPLD_PL_SPI_SDI_18 = pl_mosi;
+
+assign CLKDIST_Status_LD1 = 1'b0;
+assign LOSYNTH_RX_MUXOUT = 1'b1;
+assign LOSYNTH_TX_MUXOUT = 1'b1;
+
+initial
+begin
+ $dumpfile("rh_cpld.vcd");
+ $dumpvars;
+ // Check Signature register read-back
+ #(dly) ps_cpld_xfer(2'b00, {5'b00000, 1'b1}, 16'h0000);
+ // Check Signature register is read-only
+ #(dly) ps_cpld_xfer(2'b00, {5'b00000, 1'b0}, 16'h1234);
+ #(dly) ps_cpld_xfer(2'b00, {5'b00000, 1'b1}, 16'h0000);
+
+ // Load portions of lower RX gain table with some values
+ #(dly) ps_cpld_xfer(2'b00, {5'b00110, 1'b0}, 16'h0000); /* Write GAIN_BAND_SEL for lower table */
+ #(dly) ps_cpld_xfer(2'b01, 6'd0, {2'd0, 5'd0, 5'd1, 1'b1, 3'd0});
+ #(dly) ps_cpld_xfer(2'b01, 6'd1, {2'd0, 5'd0, 5'd2, 1'b1, 3'd0});
+ #(dly) ps_cpld_xfer(2'b01, 6'd2, {2'd0, 5'd1, 5'd2, 1'b1, 3'd0});
+ #(dly) ps_cpld_xfer(2'b01, 6'd3, {2'd0, 5'd1, 5'd3, 1'b1, 3'd0});
+
+ // Load portions of upper RX gain table with some values
+ #(dly) ps_cpld_xfer(2'b00, {5'b00110, 1'b0}, 16'h0101); /* Write GAIN_BAND_SEL for upper table */
+ #(dly) ps_cpld_xfer(2'b01, 6'd4, {2'd0, 5'd2, 5'd3, 1'b1, 3'd0});
+ #(dly) ps_cpld_xfer(2'b01, 6'd5, {2'd0, 5'd2, 5'd4, 1'b1, 3'd0});
+ #(dly) ps_cpld_xfer(2'b01, 6'd6, {2'd0, 5'd3, 5'd4, 1'b1, 3'd0});
+ #(dly) ps_cpld_xfer(2'b01, 6'd7, {2'd0, 5'd3, 5'd5, 1'b1, 3'd0});
+
+ // Check RX gain table readback
+ #(dly) ps_cpld_xfer(2'b01, 6'd0, 16'h0);
+ #(dly) ps_cpld_xfer(2'b01, 6'd1, 16'h0);
+ #(dly) ps_cpld_xfer(2'b01, 6'd2, 16'h0);
+ #(dly) ps_cpld_xfer(2'b01, 6'd3, 16'h0);
+ #(dly) ps_cpld_xfer(2'b01, 6'd4, 16'h0);
+ #(dly) ps_cpld_xfer(2'b01, 6'd5, 16'h0);
+ #(dly) ps_cpld_xfer(2'b01, 6'd6, 16'h0);
+
+ // Check can write a couple registers on PL side
+ // (Also make sure we're looking at the lower gain tables)
+ #(dly) pl_cpld_xfer(2'b00, {5'd6, 1'b0}, 16'h0000);
+ #(dly) pl_cpld_xfer(2'b00, {5'd7, 1'b0}, 16'h0000);
+
+ // Check retrieval of gain values for RX table and program DSAs
+ #(dly) pl_cpld_xfer(2'b01, 6'd2, {2'b0, 1'b1, 6'b0, 1'b1, 6'b0});
+ #(dly) pl_cpld_xfer(2'b01, 6'd3, {2'b0, 1'b0, 6'b0, 1'b1, 6'b0});
+ #(dly) pl_cpld_xfer(2'b01, 6'd1, {2'b0, 1'b1, 6'b0, 1'b0, 6'b0});
+
+ // Check writes to RXBS and TXBS registers
+ #(dly) pl_cpld_xfer(2'b00, {5'd6, 1'b0}, 16'h1ABC);
+ #(dly) pl_cpld_xfer(2'b00, {5'd7, 1'b0}, 16'h1CAB);
+
+ // Check TX DSA programming is independent of RX DSA programming
+ #(dly) pl_cpld_xfer(2'b10, 6'd4, {2'b0, 1'b1, 6'b0, 1'b0, 6'b0});
+
+ // Check LO gain programming works
+ #(dly) pl_cpld_xfer(2'b11, 6'd5, {2'b0, 1'b1, 6'b0, 1'b0, 6'b0});
+ #(dly) pl_cpld_xfer(2'b11, 6'd7, {2'b0, 1'b0, 6'b0, 1'b1, 6'b0});
+ #(dly) pl_cpld_xfer(2'b11, 6'd0, {2'b0, 1'b0, 6'b0, 1'b0, 6'b0});
+
+ // More checks for PL register writes
+ #(dly) pl_cpld_xfer(2'b00, {5'd6, 1'b0}, 16'h0ABC);
+ #(dly) pl_cpld_xfer(2'b00, {5'd7, 1'b0}, 16'h0CAB);
+ #(dly) pl_cpld_xfer(2'b00, {5'd8, 1'b0}, 16'hAA5C);
+ #(dly) pl_cpld_xfer(2'b00, {5'd8, 1'b0}, 16'h5A5C);
+ #(dly) pl_cpld_xfer(2'b00, {5'd6, 1'b0}, 16'h1C42);
+
+ // Check low/high gain tables and independence of RX vs. TX
+ #(dly) pl_cpld_xfer(2'b01, 6'd0, 16'h2040);
+ #(dly) pl_cpld_xfer(2'b00, {5'd7, 1'b0}, 16'h104C);
+ #(dly) pl_cpld_xfer(2'b10, 6'd0, 16'h2040);
+ #(dly) pl_cpld_xfer(2'b00, {5'd7, 1'b0}, 16'h0C80);
+ #(dly) pl_cpld_xfer(2'b10, 6'd5, 16'h2040);
+ $finish;
+end
+
+rhodium_top toplevel_inst(usrpio_io, // bank 1A, 1B and 6
+ADC_A_Over_Range_18, ADC_B_Over_Range_18, // bank 1A
+
+// bank 6
+CPLD_PS_SPI_LE_25,
+CPLD_PS_SPI_CLK_25,
+CPLD_PS_ADDR0_25,
+CPLD_PS_ADDR1_25,
+CPLD_PS_SPI_SDI_25,
+CPLD_PS_SPI_SDO_25,
+PHDAC_SPI_CS_L, PHDAC_SPI_SCLK, PHDAC_SPI_SDI,
+LO_SYNC,
+
+// bank 2
+CPLD_PL_SPI_SDO_18,
+CPLD_PL_SPI_LE_18,
+CPLD_PL_SPI_SCLK_18,
+CPLD_PL_SPI_SDI_18,
+CPLD_PL_SPI_ADDR0_18,
+CPLD_PL_SPI_ADDR1_18,
+CPLD_PL_SPI_ADDR2_18,
+CPLD_ATR_TX_18,
+CPLD_ATR_RX_18,
+ADC_SPI_CS_L_18,
+ADC_SPI_SCLK_18,
+ADC_SPI_SDIO_18,
+DAC_SPI_CS_L_18,
+DAC_SPI_SCLK_18,
+DAC_SPI_SDIO_18,
+DAC_Alarm_18,
+
+// bank 3
+
+CLKDIST_SPI_CS_L,
+CLKDIST_SPI_SCLK,
+CLKDIST_SPI_SDIO,
+Tx_DSA_C1,
+Tx_DSA_C2,
+Tx_DSA_C4,
+Tx_DSA_C8,
+Tx_DSA_C16,
+Tx_DSA1_LE,
+Tx_DSA2_LE,
+Tx_Sw1_Ctrl_1,
+Tx_Sw1_Ctrl_2,
+Tx_Sw2_Ctrl_1,
+Tx_Sw2_Ctrl_2,
+Tx_Sw3_Ctrl_1,
+Tx_Sw3_Ctrl_2,
+Tx_Sw3_Ctrl_3,
+Tx_Sw3_Ctrl_4,
+Rx_LO_Input_Select,
+Rx_LO_Filter_Sw_1,
+Rx_LO_Filter_Sw_2,
+Tx_LO_Input_Select,
+Tx_LO_Filter_Sw_1,
+Tx_LO_Filter_Sw_2,
+CLKDIST_Status_LD1,
+CLKDIST_Status_LD2,
+LOSYNTH_RX_MUXOUT,
+LOSYNTH_TX_MUXOUT,
+
+// bank 8
+LO_SPI_SCLK, // fans out to both rx & tx synths
+LO_SPI_SDI,
+LO_TX_CS_L,
+LO_RX_CS_L,
+Rx_Sw1_Ctrl_1,
+Rx_Sw1_Ctrl_2,
+Rx_DSA_C1,
+Rx_DSA_C2,
+Rx_DSA_C4,
+Rx_DSA_C8,
+Rx_DSA_C16,
+Rx_DSA1_LE,
+Rx_DSA2_LE,
+Rx_Sw2_Ctrl,
+Rx_Sw3_Ctrl_1,
+Rx_Sw3_Ctrl_2,
+Rx_Sw4_Ctrl_1,
+Rx_Sw4_Ctrl_2,
+Rx_Sw4_Ctrl_3,
+Rx_Sw4_Ctrl_4,
+Rx_Demod_ADJ_1,
+Rx_Demod_ADJ_2,
+
+// bank 5
+LO_DSA_C1,
+LO_DSA_C2,
+LO_DSA_C4,
+LO_DSA_C8,
+LO_DSA_C16,
+RxLO_DSA_LE,
+TxLO_DSA_LE,
+LODIST_Bd_SPI_CS_L,
+LODIST_Bd_SPI_SDI,
+LODIST_Bd_SPI_SCLK,
+LODIST_Bd_IO1,
+Tx_Sw5_Ctrl_1,
+Tx_Sw5_Ctrl_2,
+Rx_Sw6_Ctrl_1,
+Rx_Sw6_Ctrl_2,
+
+Tx_HB_LB_Select,
+Rx_HB_LB_Select,
+Cal_iso_Sw_Ctrl
+
+
+);
+endmodule // rh_tb