aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp3/top/n3xx/dboards/rh/cpld/rhodium_top.v
diff options
context:
space:
mode:
Diffstat (limited to 'fpga/usrp3/top/n3xx/dboards/rh/cpld/rhodium_top.v')
-rw-r--r--fpga/usrp3/top/n3xx/dboards/rh/cpld/rhodium_top.v605
1 files changed, 605 insertions, 0 deletions
diff --git a/fpga/usrp3/top/n3xx/dboards/rh/cpld/rhodium_top.v b/fpga/usrp3/top/n3xx/dboards/rh/cpld/rhodium_top.v
new file mode 100644
index 000000000..1d0d640da
--- /dev/null
+++ b/fpga/usrp3/top/n3xx/dboards/rh/cpld/rhodium_top.v
@@ -0,0 +1,605 @@
+///////////////////////////////////////////////////////////////////
+//
+// Copyright 2018 Ettus Research, A National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+// Module: rhodium_top
+//////////////////////////////////////////////////////////////////////
+
+`default_nettype none
+
+module rhodium_top(
+
+input [13:0] usrp_io, // bank 1A, 1B and 6
+
+input ADC_A_Over_Range_18, input ADC_B_Over_Range_18, // bank 1A
+
+// bank 6
+input CPLD_PS_SPI_LE_25,
+input CPLD_PS_SPI_CLK_25,
+input CPLD_PS_ADDR0_25,
+input CPLD_PS_ADDR1_25,
+input CPLD_PS_SPI_SDI_25,
+output reg CPLD_PS_SPI_SDO_25,
+output PHDAC_SPI_CS_L,
+output PHDAC_SPI_SCLK,
+output PHDAC_SPI_SDI,
+input LO_SYNC,
+
+// bank 2
+output reg CPLD_PL_SPI_SDO_18,
+input CPLD_PL_SPI_LE_18,
+input CPLD_PL_SPI_SCLK_18,
+input CPLD_PL_SPI_SDI_18,
+input CPLD_PL_SPI_ADDR0_18,
+input CPLD_PL_SPI_ADDR1_18,
+input CPLD_PL_SPI_ADDR2_18,
+// NOTE: TxRx front-end switches are driven direct from the motherboard, so these ATR
+// lines have no function at this time.
+input CPLD_ATR_TX_18,
+input CPLD_ATR_RX_18,
+output ADC_SPI_CS_L_18,
+output ADC_SPI_SCLK_18,
+inout ADC_SPI_SDIO_18,
+output DAC_SPI_CS_L_18,
+output DAC_SPI_SCLK_18,
+inout DAC_SPI_SDIO_18,
+input DAC_Alarm_18, // TODO: drive to gpio?
+
+// bank 3
+
+output CLKDIST_SPI_CS_L,
+output CLKDIST_SPI_SCLK,
+inout CLKDIST_SPI_SDIO,
+output Tx_DSA_C1,
+output Tx_DSA_C2,
+output Tx_DSA_C4,
+output Tx_DSA_C8,
+output Tx_DSA_C16,
+output Tx_DSA1_LE,
+output Tx_DSA2_LE,
+output Tx_Sw1_Ctrl_1,
+output Tx_Sw1_Ctrl_2,
+output Tx_Sw2_Ctrl_1,
+output Tx_Sw2_Ctrl_2,
+output Tx_Sw3_Ctrl_1,
+output Tx_Sw3_Ctrl_2,
+output Tx_Sw3_Ctrl_3,
+output Tx_Sw3_Ctrl_4,
+output Rx_LO_Input_Select,
+output Rx_LO_Filter_Sw_1,
+output Rx_LO_Filter_Sw_2,
+output Tx_LO_Input_Select,
+output Tx_LO_Filter_Sw_1,
+output Tx_LO_Filter_Sw_2,
+input CLKDIST_Status_LD1,
+input CLKDIST_Status_LD2,
+input LOSYNTH_RX_MUXOUT,
+input LOSYNTH_TX_MUXOUT,
+
+// bank 8
+output LO_SPI_SCLK, // fans out to both rx & tx synths
+output LO_SPI_SDI,
+output LO_TX_CS_L,
+output LO_RX_CS_L,
+output Rx_Sw1_Ctrl_1,
+output Rx_Sw1_Ctrl_2,
+output Rx_DSA_C1,
+output Rx_DSA_C2,
+output Rx_DSA_C4,
+output Rx_DSA_C8,
+output Rx_DSA_C16,
+output Rx_DSA1_LE,
+output Rx_DSA2_LE,
+output Rx_Sw2_Ctrl,
+output Rx_Sw3_Ctrl_1,
+output Rx_Sw3_Ctrl_2,
+output Rx_Sw4_Ctrl_1,
+output Rx_Sw4_Ctrl_2,
+output Rx_Sw4_Ctrl_3,
+output Rx_Sw4_Ctrl_4,
+output Rx_Demod_ADJ_1,
+output Rx_Demod_ADJ_2,
+
+// bank 5
+output LO_DSA_C1,
+output LO_DSA_C2,
+output LO_DSA_C4,
+output LO_DSA_C8,
+output LO_DSA_C16,
+output RxLO_DSA_LE,
+output TxLO_DSA_LE,
+output LODIST_Bd_SPI_CS_L,
+output LODIST_Bd_SPI_SDI,
+output LODIST_Bd_SPI_SCLK,
+inout LODIST_Bd_IO1,
+output Tx_Sw5_Ctrl_1,
+output Tx_Sw5_Ctrl_2,
+output Rx_Sw6_Ctrl_1,
+output Rx_Sw6_Ctrl_2,
+
+output Tx_HB_LB_Select,
+output Rx_HB_LB_Select,
+output Cal_iso_Sw_Ctrl
+
+
+);
+
+/* PS SPI */
+
+localparam GIT_HASH = 36'h`GIT_HASH;
+localparam PROD_SIGNATURE = 16'h0045; // Product signature (Rhodium atomic number in BCD)
+localparam REVISION_MINOR = 16'h0002;
+localparam REVISION_MAJOR = 16'h0004;
+localparam CPLD_BUILD_LSB = GIT_HASH[15:0]; // Build code LSB
+localparam CPLD_BUILD_MSB = GIT_HASH[31:16]; // Build code MSB
+localparam PSADDR_SIGNATURE = 3'd0;
+localparam PSADDR_REV_MINOR = 3'd1; // Minor version register
+localparam PSADDR_REV_MAJOR = 3'd2; // Major version register
+localparam PSADDR_BUILD_LSB = 3'd3;
+localparam PSADDR_BUILD_MSB = 3'd4;
+localparam PSADDR_SCRATCH = 3'd5; // scratchpad register
+localparam PSADDR_GAIN_SEL = 3'd6; // band select for gain table loader
+localparam PSADDR_DAC_ALARM = 3'd7; // DAC alarm pin register
+
+// Sub-device selection for PS SPI
+localparam PS_CPLD_REGS = 2'b00;
+localparam GAIN_TABLE_RX = 2'b01;
+localparam GAIN_TABLE_TX = 2'b10;
+localparam GAIN_TABLE_LO = 2'b11;
+
+// Setting to put TX SW1 in isolation mode
+localparam [1:0] TX_SW1_TERM = 2'b11;
+
+wire clkdis_cs_b = CPLD_PS_SPI_LE_25;
+wire cpld_ps_cs_b = CPLD_PS_ADDR0_25;
+wire phdac_cs_b = CPLD_PS_ADDR1_25;
+wire adc_cs_b = usrp_io[12];
+wire dac_cs_b = usrp_io[13];
+
+// CPLD PS SPI format (left-most bit first):
+// {table_sel[1:0], rsvd, reg_addr[3:0], rnw, data[15:0]}
+wire [1:0] cpld_ps_table_sel;
+wire [6:0] cpld_ps_spi_addr;
+wire cpld_ps_spi_rnw;
+reg [7:0] cpld_ps_spi_cmd;
+reg [15:0] cpld_ps_spi_rdata;
+reg [14:0] cpld_ps_spi_wdata;
+reg cpld_ps_spi_sdo;
+reg [4:0] cpld_ps_cnt;
+
+assign {cpld_ps_spi_addr, cpld_ps_spi_rnw} = cpld_ps_spi_cmd;
+
+// CPLD registers
+reg [15:0] spad;
+reg [15:0] gain_load_sel;
+
+// Double sync. the DAC ALARM pin (async).
+reg dac_alarm_ms, dac_alarm = 0;
+always @(posedge CPLD_PS_SPI_CLK_25) begin
+ {dac_alarm, dac_alarm_ms} <= {dac_alarm_ms, DAC_Alarm_18};
+end
+
+wire rx_gain_load_tbl_sel;
+wire rx_gain_load_miso;
+wire rx_gain_ctrl_tbl_sel;
+wire rx_gain_ctrl_miso;
+wire tx_gain_load_tbl_sel;
+wire tx_gain_load_miso;
+wire tx_gain_ctrl_tbl_sel;
+wire tx_gain_ctrl_miso;
+wire lo_gain_ctrl_miso;
+
+assign rx_gain_load_tbl_sel = gain_load_sel[0];
+assign tx_gain_load_tbl_sel = gain_load_sel[8];
+
+always @(posedge CPLD_PS_SPI_CLK_25 or posedge cpld_ps_cs_b)
+begin
+ if (cpld_ps_cs_b) begin
+ cpld_ps_cnt <= 5'd0;
+ end else if (!cpld_ps_cs_b) begin
+ if (cpld_ps_cnt < 8) begin // Address / command
+ cpld_ps_spi_cmd <= {cpld_ps_spi_cmd[6:0], CPLD_PS_SPI_SDI_25};
+ cpld_ps_cnt <= cpld_ps_cnt + 5'd1;
+ end else if (cpld_ps_cnt < 23) begin // Shift in write data
+ cpld_ps_spi_wdata <= {cpld_ps_spi_wdata[13:0], CPLD_PS_SPI_SDI_25};
+ cpld_ps_cnt <= cpld_ps_cnt + 5'd1;
+ end else if (!cpld_ps_spi_rnw && cpld_ps_cnt == 23 && cpld_ps_spi_addr[6:5] == PS_CPLD_REGS) begin // Write
+ case (cpld_ps_spi_addr[2:0])
+ PSADDR_SIGNATURE: ;
+ PSADDR_REV_MINOR: ;
+ PSADDR_REV_MAJOR: ;
+ PSADDR_BUILD_LSB: ;
+ PSADDR_BUILD_MSB: ;
+ PSADDR_SCRATCH: spad <= {cpld_ps_spi_wdata, CPLD_PS_SPI_SDI_25};
+ PSADDR_GAIN_SEL: gain_load_sel <= {cpld_ps_spi_wdata, CPLD_PS_SPI_SDI_25};
+ endcase
+ end
+ if (cpld_ps_cnt == 7) begin // Set up read one cycle earlier
+ case (cpld_ps_spi_cmd[2:0])
+
+ PSADDR_SIGNATURE: cpld_ps_spi_rdata <= PROD_SIGNATURE;
+ PSADDR_REV_MINOR: cpld_ps_spi_rdata <= REVISION_MINOR;
+ PSADDR_REV_MAJOR: cpld_ps_spi_rdata <= REVISION_MAJOR;
+ PSADDR_BUILD_LSB: cpld_ps_spi_rdata <= CPLD_BUILD_LSB;
+ PSADDR_BUILD_MSB: cpld_ps_spi_rdata <= CPLD_BUILD_MSB;
+ PSADDR_SCRATCH: cpld_ps_spi_rdata <= spad;
+ PSADDR_GAIN_SEL: cpld_ps_spi_rdata <= gain_load_sel;
+ PSADDR_DAC_ALARM: cpld_ps_spi_rdata <= {15'b0, dac_alarm};
+ endcase
+ end else begin
+ cpld_ps_spi_rdata <= {cpld_ps_spi_rdata[14:0], 1'b1};
+ end
+ end
+end
+
+always @(negedge CPLD_PS_SPI_CLK_25)
+begin
+ cpld_ps_spi_sdo <= cpld_ps_spi_rdata[15]; // Shift out on negative edge
+end
+
+// CLKDIST 3-wire to 4-wire
+reg [4:0] clkdis_cnt;
+reg clkdis_rd_pre, clkdis_rd, clkdis_sdio_t;
+
+always @(posedge CPLD_PS_SPI_CLK_25 or posedge clkdis_cs_b)
+begin
+ if (clkdis_cs_b) begin
+ clkdis_cnt <= 5'd0;
+ clkdis_rd <= 1'b0;
+ clkdis_rd_pre <= 1'b0;
+ end else if (!clkdis_cs_b) begin
+ if (clkdis_cnt < 23)
+ clkdis_cnt <= clkdis_cnt + 5'd1;
+
+ if (clkdis_cnt == 5'd0) // Check if read
+ clkdis_rd_pre <= CPLD_PS_SPI_SDI_25;
+
+ if (clkdis_cnt == 5'd15)
+ clkdis_rd <= clkdis_rd_pre;
+ end
+end
+
+always @(negedge CPLD_PS_SPI_CLK_25 or posedge clkdis_cs_b)
+begin
+ if (clkdis_cs_b) begin
+ clkdis_sdio_t <= 1'b0;
+ end else begin
+ clkdis_sdio_t <= clkdis_rd;
+ end
+end
+
+// ADC 3-wire to 4-wire
+reg [4:0] adc_cnt;
+reg adc_rd_pre, adc_rd, adc_sdio_t;
+
+always @(posedge CPLD_PS_SPI_CLK_25 or posedge adc_cs_b)
+begin
+ if (adc_cs_b) begin
+ adc_cnt <= 5'd0;
+ adc_rd <= 1'b0;
+ adc_rd_pre <= 1'b0;
+ end else if (!adc_cs_b) begin
+ if (adc_cnt < 23)
+ adc_cnt <= adc_cnt + 5'd1;
+
+ if (adc_cnt == 5'd0) // Check if read
+ adc_rd_pre <= CPLD_PS_SPI_SDI_25;
+
+ if (adc_cnt == 5'd15)
+ adc_rd <= adc_rd_pre;
+ end
+end
+
+always @(negedge CPLD_PS_SPI_CLK_25 or posedge adc_cs_b)
+begin
+ if (adc_cs_b) begin
+ adc_sdio_t <= 1'b0;
+ end else begin
+ adc_sdio_t <= adc_rd;
+ end
+end
+
+// DAC 3-wire to 4-wire
+reg [4:0] dac_cnt;
+reg dac_rd_pre, dac_rd, dac_sdio_t;
+
+always @(posedge CPLD_PS_SPI_CLK_25 or posedge dac_cs_b)
+begin
+ if (dac_cs_b) begin
+ dac_cnt <= 5'd0;
+ dac_rd <= 1'b0;
+ dac_rd_pre <= 1'b0;
+ end else if (!dac_cs_b) begin
+ if (dac_cnt < 23)
+ dac_cnt <= dac_cnt + 5'd1;
+
+ if (dac_cnt == 5'd0) // Check if read
+ dac_rd_pre <= CPLD_PS_SPI_SDI_25;
+
+ if (dac_cnt == 5'd7)
+ dac_rd <= dac_rd_pre;
+ end
+end
+
+always @(negedge CPLD_PS_SPI_CLK_25 or posedge dac_cs_b)
+begin
+ if (dac_cs_b) begin
+ dac_sdio_t <= 1'b0;
+ end else begin
+ dac_sdio_t <= dac_rd;
+ end
+end
+
+// multiplexed slave device SPI ports
+wire phdac_sck, phdac_sdi;
+wire clkdis_sck, adc_sck, dac_sck;
+assign clkdis_sck = (clkdis_cs_b == 1'b0) ? CPLD_PS_SPI_CLK_25 : 1'b0;
+
+assign CLKDIST_SPI_CS_L = clkdis_cs_b;
+assign CLKDIST_SPI_SCLK = clkdis_sck;
+
+assign adc_sck = !adc_cs_b ? CPLD_PS_SPI_CLK_25 : 1'b0;
+assign dac_sck = !dac_cs_b ? CPLD_PS_SPI_CLK_25 : 1'b0;
+
+assign ADC_SPI_CS_L_18 = adc_cs_b;
+assign ADC_SPI_SCLK_18 = adc_sck;
+
+assign DAC_SPI_CS_L_18 = dac_cs_b;
+assign DAC_SPI_SCLK_18 = dac_sck;
+
+assign CLKDIST_SPI_SDIO = (!clkdis_sdio_t && !clkdis_cs_b) ? CPLD_PS_SPI_SDI_25 : 1'bz ;
+assign ADC_SPI_SDIO_18 = (!adc_sdio_t && !adc_cs_b) ? CPLD_PS_SPI_SDI_25 : 1'bz ;
+assign DAC_SPI_SDIO_18 = (!dac_sdio_t && !dac_cs_b) ? CPLD_PS_SPI_SDI_25 : 1'bz ;
+
+always @(*)
+begin
+ CPLD_PS_SPI_SDO_25 = 1'b1;
+ case ({cpld_ps_cs_b, clkdis_cs_b, adc_cs_b, dac_cs_b})
+ 4'b0111: begin
+ case (cpld_ps_spi_addr[6:5])
+ PS_CPLD_REGS : CPLD_PS_SPI_SDO_25 = cpld_ps_spi_sdo;
+ GAIN_TABLE_RX: CPLD_PS_SPI_SDO_25 = rx_gain_load_miso;
+ GAIN_TABLE_TX: CPLD_PS_SPI_SDO_25 = tx_gain_load_miso;
+ GAIN_TABLE_LO: CPLD_PS_SPI_SDO_25 = 1'b1;
+ endcase
+ end
+ 4'b1011: CPLD_PS_SPI_SDO_25 = CLKDIST_SPI_SDIO;
+ 4'b1101: CPLD_PS_SPI_SDO_25 = ADC_SPI_SDIO_18;
+ 4'b1110: CPLD_PS_SPI_SDO_25 = DAC_SPI_SDIO_18;
+ default: ;
+ endcase
+end
+
+// note: no readback from PHDAC
+assign phdac_sck = (phdac_cs_b == 1'b0) ? CPLD_PS_SPI_CLK_25 : 1'b0;
+assign phdac_sdi = (phdac_cs_b == 1'b0) ? CPLD_PS_SPI_SDI_25 : 1'b1;
+
+
+assign PHDAC_SPI_SCLK = phdac_sck;
+assign PHDAC_SPI_CS_L = phdac_cs_b;
+assign PHDAC_SPI_SDI = phdac_sdi;
+
+
+/* PL SPI */
+// CPLD PL SPI format (left-most bit first):
+// {table_sel[1:0], reg_addr[4:0], rnw, data[15:0]}
+
+//TXLO, RXLO, LODIS, CPLD
+localparam PLADDR_SCRATCH = 4'b0101; // scratchpad register
+localparam PLADDR_RXBS = 4'b0110;
+localparam PLADDR_TXBS = 4'b0111;
+localparam PLADDR_RFCTRL = 4'b1000;
+localparam PL_CPLD_REGS = 2'b00;
+
+// CPLD PL registers
+reg [15:0] rxbs = 'h0;
+reg [15:0] txbs = 'h0;
+reg [15:0] rfctrl = 'h0;
+
+// register address on the falling edge of chip-select
+wire txlo_cs_b = CPLD_PL_SPI_LE_18;
+wire rxlo_cs_b = CPLD_PL_SPI_ADDR1_18;
+wire lodis_cs_b = CPLD_PL_SPI_ADDR2_18;
+wire cpld_pl_cs_b = CPLD_PL_SPI_ADDR0_18;
+
+wire cpld_pl_spi_rnw;
+wire [6:0] cpld_pl_spi_addr;
+reg [7:0] cpld_pl_spi_cmd;
+reg [15:0] cpld_pl_spi_rdata;
+reg [14:0] cpld_pl_spi_wdata;
+reg cpld_pl_spi_sdo;
+reg [4:0] cpld_pl_cnt;
+
+assign {cpld_pl_spi_addr, cpld_pl_spi_rnw} = cpld_pl_spi_cmd;
+
+reg [15:0] pl_spad;
+
+always @(posedge CPLD_PL_SPI_SCLK_18 or posedge cpld_pl_cs_b)
+begin
+ if (cpld_pl_cs_b) begin
+ cpld_pl_cnt <= 5'd0;
+ end else if (!cpld_pl_cs_b) begin
+ if (cpld_pl_cnt < 8) begin // Address / command
+ cpld_pl_spi_cmd <= {cpld_pl_spi_cmd[6:0], CPLD_PL_SPI_SDI_18};
+ cpld_pl_cnt <= cpld_pl_cnt + 5'd1;
+ end else if (cpld_pl_cnt < 23) begin // Shift in write data
+ cpld_pl_spi_wdata <= {cpld_pl_spi_wdata[13:0], CPLD_PL_SPI_SDI_18};
+ cpld_pl_cnt <= cpld_pl_cnt + 5'd1;
+ end else if (!cpld_pl_spi_rnw && cpld_pl_cnt == 23 && cpld_pl_spi_addr[6:5] == PL_CPLD_REGS) begin // Write
+ case (cpld_pl_spi_addr[3:0])
+ PLADDR_SCRATCH: pl_spad <= {cpld_pl_spi_wdata, CPLD_PL_SPI_SDI_18};
+ PLADDR_RXBS: rxbs <= {cpld_pl_spi_wdata, CPLD_PL_SPI_SDI_18};
+ PLADDR_TXBS: txbs <= {cpld_pl_spi_wdata, CPLD_PL_SPI_SDI_18};
+ PLADDR_RFCTRL: rfctrl <= {cpld_pl_spi_wdata, CPLD_PL_SPI_SDI_18};
+ endcase
+ end
+ if (cpld_pl_cnt == 7) begin // Set up read one cycle earlier
+ case (cpld_pl_spi_cmd[3:0])
+ PLADDR_SCRATCH: cpld_pl_spi_rdata <= pl_spad;
+ PLADDR_RXBS: cpld_pl_spi_rdata <= rxbs;
+ PLADDR_TXBS: cpld_pl_spi_rdata <= txbs;
+ PLADDR_RFCTRL: cpld_pl_spi_rdata <= rfctrl;
+ endcase
+ end else begin
+ cpld_pl_spi_rdata <= {cpld_pl_spi_rdata[14:0], 1'b1};
+ end
+ end
+end
+
+always @(negedge CPLD_PL_SPI_SCLK_18)
+begin
+ cpld_pl_spi_sdo <= cpld_pl_spi_rdata[15]; // Shift out on negative edge
+end
+
+// multiplexed slave device SPI ports, names aliased to protect the innocent
+wire lo_sck, lodis_sck;
+wire lo_sdi, lodis_sdi;
+// Note: lo_sck and lo_sdi -> fan out to both rxlo and txlo synths
+
+assign { LO_TX_CS_L, LO_RX_CS_L } = { txlo_cs_b, rxlo_cs_b};
+assign LO_SPI_SCLK = lo_sck;
+assign LO_SPI_SDI = lo_sdi;
+
+
+assign LODIST_Bd_SPI_CS_L = lodis_cs_b;
+assign LODIST_Bd_SPI_SDI = lodis_sdi;
+assign LODIST_Bd_SPI_SCLK = lodis_sck;
+
+
+assign lodis_sck = !lodis_cs_b ? CPLD_PL_SPI_SCLK_18 : 1'b0;
+assign lodis_sdi = !lodis_cs_b ? CPLD_PL_SPI_SDI_18 : 1'b1;
+
+assign { lo_sck, lo_sdi } = (!txlo_cs_b | !rxlo_cs_b) ? {CPLD_PL_SPI_SCLK_18,CPLD_PL_SPI_SDI_18} : 2'b01;
+
+
+always @(*)
+begin
+ CPLD_PL_SPI_SDO_18 = 1'bz;
+ case ({cpld_pl_cs_b, txlo_cs_b, rxlo_cs_b})
+ 3'b110: CPLD_PL_SPI_SDO_18 = LOSYNTH_RX_MUXOUT;
+ 3'b101: CPLD_PL_SPI_SDO_18 = LOSYNTH_TX_MUXOUT;
+ 3'b011: begin
+ case (cpld_pl_spi_addr[6:5])
+ PL_CPLD_REGS : CPLD_PL_SPI_SDO_18 = cpld_pl_spi_sdo;
+ GAIN_TABLE_RX: CPLD_PL_SPI_SDO_18 = rx_gain_ctrl_miso;
+ GAIN_TABLE_TX: CPLD_PL_SPI_SDO_18 = tx_gain_ctrl_miso;
+ GAIN_TABLE_LO: CPLD_PL_SPI_SDO_18 = lo_gain_ctrl_miso;
+ endcase
+ end
+ default: ;
+ endcase
+end
+
+assign rx_gain_ctrl_tbl_sel = rxbs[12];
+assign { Rx_Sw6_Ctrl_2,
+ Rx_Sw6_Ctrl_1,
+ Rx_Sw4_Ctrl_4,
+ Rx_Sw4_Ctrl_3,
+ Rx_Sw4_Ctrl_2,
+ Rx_Sw4_Ctrl_1,
+ Rx_Sw3_Ctrl_2,
+ Rx_Sw3_Ctrl_1,
+ Rx_Sw2_Ctrl,
+ Rx_Sw1_Ctrl_2,
+ Rx_Sw1_Ctrl_1 } = { rxbs[11:1] };
+
+assign tx_gain_ctrl_tbl_sel = txbs[12];
+assign { Tx_Sw5_Ctrl_2,
+ Tx_Sw5_Ctrl_1,
+ Tx_Sw3_Ctrl_4,
+ Tx_Sw3_Ctrl_3,
+ Tx_Sw3_Ctrl_2,
+ Tx_Sw3_Ctrl_1,
+ Tx_Sw2_Ctrl_2,
+ Tx_Sw2_Ctrl_1} = { txbs[11:4] };
+
+// Terminate TX when idle
+assign {Tx_Sw1_Ctrl_2, Tx_Sw1_Ctrl_1} = CPLD_ATR_TX_18 ? txbs[3:2] : TX_SW1_TERM;
+
+assign { Rx_LO_Filter_Sw_2,
+ Rx_LO_Filter_Sw_1,
+ Tx_LO_Filter_Sw_2,
+ Tx_LO_Filter_Sw_1,
+ Rx_Demod_ADJ_1,
+ Rx_Demod_ADJ_2,
+ Rx_LO_Input_Select } = rfctrl[15:9];
+
+assign { Rx_HB_LB_Select,
+ Tx_LO_Input_Select } = rfctrl[7:6];
+
+assign { Tx_HB_LB_Select,
+ Cal_iso_Sw_Ctrl }
+ = { rfctrl[4:3] };
+
+
+// RX Gain Table
+wire [4:0] rx_dsa;
+
+rhodium_gain_ctrl #(
+ .TABLE_NUM(GAIN_TABLE_RX)
+) rx_gain_table (
+ .load_table_sel(rx_gain_load_tbl_sel),
+ .load_sck(CPLD_PS_SPI_CLK_25),
+ .load_csb(cpld_ps_cs_b),
+ .load_mosi(CPLD_PS_SPI_SDI_25),
+ .load_miso(rx_gain_load_miso),
+ .ctrl_table_sel(rx_gain_ctrl_tbl_sel),
+ .ctrl_sck(CPLD_PL_SPI_SCLK_18),
+ .ctrl_csb(cpld_pl_cs_b),
+ .ctrl_mosi(CPLD_PL_SPI_SDI_18),
+ .ctrl_miso(rx_gain_ctrl_miso),
+ .dsa(rx_dsa),
+ .dsa1_le(Rx_DSA1_LE),
+ .dsa2_le(Rx_DSA2_LE)
+);
+
+// TX Gain Table
+wire [4:0] tx_dsa;
+
+rhodium_gain_ctrl #(
+ .TABLE_NUM(GAIN_TABLE_TX)
+) tx_gain_table (
+ .load_table_sel(tx_gain_load_tbl_sel),
+ .load_sck(CPLD_PS_SPI_CLK_25),
+ .load_csb(cpld_ps_cs_b),
+ .load_mosi(CPLD_PS_SPI_SDI_25),
+ .load_miso(tx_gain_load_miso),
+ .ctrl_table_sel(tx_gain_ctrl_tbl_sel),
+ .ctrl_sck(CPLD_PL_SPI_SCLK_18),
+ .ctrl_csb(cpld_pl_cs_b),
+ .ctrl_mosi(CPLD_PL_SPI_SDI_18),
+ .ctrl_miso(tx_gain_ctrl_miso),
+ .dsa(tx_dsa),
+ .dsa1_le(Tx_DSA1_LE),
+ .dsa2_le(Tx_DSA2_LE)
+);
+
+// LO Gain Table
+wire [4:0] lo_dsa;
+
+rhodium_lo_gain #(
+ .TABLE_NUM(GAIN_TABLE_LO)
+) lo_gain_table (
+ .ctrl_sck(CPLD_PL_SPI_SCLK_18),
+ .ctrl_csb(cpld_pl_cs_b),
+ .ctrl_mosi(CPLD_PL_SPI_SDI_18),
+ .ctrl_miso(lo_gain_ctrl_miso),
+ .dsa(lo_dsa),
+ .dsa1_le(RxLO_DSA_LE),
+ .dsa2_le(TxLO_DSA_LE)
+);
+
+// Rx data shared by DSA1, DSA2
+assign { Rx_DSA_C16, Rx_DSA_C8, Rx_DSA_C4, Rx_DSA_C2, Rx_DSA_C1 } = rx_dsa;
+
+// Tx data shared by DSA1, DSA2
+assign { Tx_DSA_C16, Tx_DSA_C8, Tx_DSA_C4, Tx_DSA_C2, Tx_DSA_C1 } = tx_dsa;
+
+// data shared by both tx and rx lo DSAs
+assign { LO_DSA_C16, LO_DSA_C8, LO_DSA_C4, LO_DSA_C2, LO_DSA_C1 } = lo_dsa;
+
+endmodule
+`default_nettype wire
+