+18









Martin Braun
Alex Williams
Andrej Rode
Ashish Chaudhari
Ben Hilburn
Ciro Nishiguchi
Daniel Jepson
Derek Kozel
EJ Kreinar
Humberto Jimenez
Ian Buckley
Jörg Hofrichter
Jon Kiser
Josh Blum
Jonathon Pendlum
Matt Ettus
Michael West
Moritz Fischer
Nick Foster
Nicolas Cuervo
Paul Butler
Paul David
Ryan Marlow
Sugandha Gupta
Sylvain Munaut
Trung Tran
Vidush Vishwanath
Wade Fife
6b67702ad7
The FPGA codebase was removed from the UHD repository in 2014 to reduce the size of the repository. However, over the last half-decade, the split between the repositories has proven more burdensome than it has been helpful. By merging the FPGA code back, it will be possible to create atomic commits that touch both FPGA and UHD codebases. Continuous integration testing is also simplified by merging the repositories, because it was previously difficult to automatically derive the correct UHD branch when testing a feature branch on the FPGA repository. This commit also updates the license files and paths therein. We are therefore merging the repositories again. Future development for FPGA code will happen in the same repository as the UHD host code and MPM code. == Original Codebase and Rebasing == The original FPGA repository will be hosted for the foreseeable future at its original local location: https://github.com/EttusResearch/fpga/ It can be used for bisecting, reference, and a more detailed history. The final commit from said repository to be merged here is 05003794e2da61cabf64dd278c45685a7abad7ec. This commit is tagged as v4.0.0.0-pre-uhd-merge. If you have changes in the FPGA repository that you want to rebase onto the UHD repository, simply run the following commands: - Create a directory to store patches (this should be an empty directory): mkdir ~/patches - Now make sure that your FPGA codebase is based on the same state as the code that was merged: cd src/fpga # Or wherever your FPGA code is stored git rebase v4.0.0.0-pre-uhd-merge Note: The rebase command may look slightly different depending on what exactly you're trying to rebase. - Create a patch set for your changes versus v4.0.0.0-pre-uhd-merge: git format-patch v4.0.0.0-pre-uhd-merge -o ~/patches Note: Make sure that only patches are stored in your output directory. It should otherwise be empty. Make sure that you picked the correct range of commits, and only commits you wanted to rebase were exported as patch files. - Go to the UHD repository and apply the patches: cd src/uhd # Or wherever your UHD repository is stored git am --directory fpga ~/patches/* rm -rf ~/patches # This is for cleanup == Contributors == The following people have contributed mainly to these files (this list is not complete): Co-authored-by: Alex Williams <alex.williams@ni.com> Co-authored-by: Andrej Rode <andrej.rode@ettus.com> Co-authored-by: Ashish Chaudhari <ashish@ettus.com> Co-authored-by: Ben Hilburn <ben.hilburn@ettus.com> Co-authored-by: Ciro Nishiguchi <ciro.nishiguchi@ni.com> Co-authored-by: Daniel Jepson <daniel.jepson@ni.com> Co-authored-by: Derek Kozel <derek.kozel@ettus.com> Co-authored-by: EJ Kreinar <ej@he360.com> Co-authored-by: Humberto Jimenez <humberto.jimenez@ni.com> Co-authored-by: Ian Buckley <ian.buckley@gmail.com> Co-authored-by: Jörg Hofrichter <joerg.hofrichter@ni.com> Co-authored-by: Jon Kiser <jon.kiser@ni.com> Co-authored-by: Josh Blum <josh@joshknows.com> Co-authored-by: Jonathon Pendlum <jonathan.pendlum@ettus.com> Co-authored-by: Martin Braun <martin.braun@ettus.com> Co-authored-by: Matt Ettus <matt@ettus.com> Co-authored-by: Michael West <michael.west@ettus.com> Co-authored-by: Moritz Fischer <moritz.fischer@ettus.com> Co-authored-by: Nick Foster <nick@ettus.com> Co-authored-by: Nicolas Cuervo <nicolas.cuervo@ettus.com> Co-authored-by: Paul Butler <paul.butler@ni.com> Co-authored-by: Paul David <paul.david@ettus.com> Co-authored-by: Ryan Marlow <ryan.marlow@ettus.com> Co-authored-by: Sugandha Gupta <sugandha.gupta@ettus.com> Co-authored-by: Sylvain Munaut <tnt@246tNt.com> Co-authored-by: Trung Tran <trung.tran@ettus.com> Co-authored-by: Vidush Vishwanath <vidush.vishwanath@ettus.com> Co-authored-by: Wade Fife <wade.fife@ettus.com> Original-commit: bafa9d95453387814ef25e6b6256ba8db2df612f
606 lines
17 KiB
Verilog
606 lines
17 KiB
Verilog
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// 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
|
|
|