Merge FPGA repository back into UHD repository

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
This commit is contained in:
Martin Braun
2020-01-28 09:35:36 -08:00
co-authored by 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
parent 74893643ca
commit 6b67702ad7
2157 changed files with 1282567 additions and 0 deletions
+27
View File
@@ -0,0 +1,27 @@
#
# Copyright 2018 Ettus Research, a National Instruments Company
#
.PHONY: all clean
SRCS=rhodium_top.qpf rhodium_top.qsf rhodium_top.sdc rhodium_top.v rhodium_gain_ctrl.v rhodium_gain_table.v rhodium_lo_gain.v
SIM_SRCS=rh_tb.v rhodium_top.v rhodium_gain_ctrl.v rhodium_gain_table.v rhodium_lo_gain.v
SHORT_HASH=$(addprefix GIT_HASH=,$(shell ../../../../../tools/scripts/git-hash.sh))
all: cpld-rhodium-revb.svf
output_files/rhodium_top.pof: $(SRCS)
quartus_map rhodium_top --verilog_macro="$(SHORT_HASH)"
quartus_fit rhodium_top
quartus_asm rhodium_top
quartus_sta rhodium_top
cpld-rhodium-revb.svf: output_files/rhodium_top.pof
quartus_cpf --convert --frequency 10.0MHz --voltage 2.5 --operation p $? $@
clean:
rm -rf db incremental_db output_files simulation cpld-rhodium-revb.svf
a.out: $(SIM_SRCS)
iverilog -tvvp -D$(SHORT_HASH) -s rh_tb $(SIM_SRCS)
+410
View File
@@ -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
@@ -0,0 +1,203 @@
///////////////////////////////////////////////////////////////////
//
// Copyright 2018 Ettus Research, A National Instruments Company
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// Module: rhodium_gain_ctrl
// Description:
// Gain controller for Rhodium
// Provides 2 SPI slaves:
// The "load" slave is used to load the gain table with DSA settings for
// each index.
// The "ctrl" slave takes in a gain index and drives the DSAs with the
// setting found in the gain table.
// The SPI formats are provided below.
//////////////////////////////////////////////////////////////////////
`default_nettype none
/**
* SPI DATA FORMAT
* LOADER
* M {table_sel[1:0], gain_index[5:0], rsvd[1:0], dsa1[4:0], dsa2[4:0], wr_en, rsvd[2:0]}
* S {-------------------------------, rsvd[1:0], dsa1[4:0], dsa2[4:0], -------rsvd[3:0]}
* CTRL
* M {table_sel[1:0], gain_index[5:0], rsvd[1:0], wr_dsa1, -rsvd[5:0], wr_dsa2, rsvd[5:0]}
* S {-------------------------------, ---------rsvd[2:0], gain1[5:0], ---rsvd, gain2[5:0]}
*/
module rhodium_gain_ctrl
#(
parameter TABLE_NUM = 2'b01
) (
input wire load_table_sel,
input wire load_sck,
input wire load_csb,
input wire load_mosi,
output wire load_miso,
input wire ctrl_table_sel,
input wire ctrl_sck,
input wire ctrl_csb,
input wire ctrl_mosi,
output reg ctrl_miso,
output wire [4:0] dsa,
output reg dsa1_le,
output reg dsa2_le
);
localparam CNT_GAIN1_DRIVE = 10,
CNT_DSA1_LE_RISE = 11,
CNT_DSA1_LE_FALL = 14,
CNT_GAIN1_RELEASE = 17;
localparam CNT_GAIN2_DRIVE = 17,
CNT_DSA2_LE_RISE = 18,
CNT_DSA2_LE_FALL = 21,
CNT_GAIN2_RELEASE = 24;
/******************
* Gain table loader
*******************/
reg [4:0] load_bit_cnt;
reg [1:0] load_tbl;
reg [5:0] load_index;
reg [15:0] load_rd_data;
reg [4:0] load_dsa1;
reg [4:0] load_dsa2;
wire [4:0] load_dsa1_prev;
wire [4:0] load_dsa2_prev;
assign load_miso = load_rd_data[15]; // Shift out on neg edge
wire wr_en;
assign wr_en = (!load_csb) && (load_tbl == TABLE_NUM) && (load_bit_cnt == 20) && (load_mosi);
// Cycle counter for where we are in protocol and shift register for input
always @ (posedge load_sck or posedge load_csb)
begin
if (load_csb) begin
load_bit_cnt <= 5'd0;
end else if (!load_csb) begin
{load_dsa1, load_dsa2} <= {load_dsa1[3:0], load_dsa2, load_mosi};
if (load_bit_cnt < 23) begin
load_bit_cnt <= load_bit_cnt + 5'd1;
end
if (load_bit_cnt < 8) begin
{load_tbl, load_index} <= {load_tbl[0], load_index, load_mosi};
end
end
end
// Readback shift register
always @ (negedge load_sck)
begin
if (load_bit_cnt == 9) begin
load_rd_data <= {load_dsa1_prev, load_dsa2_prev, 5'b000};
end else begin
load_rd_data <= {load_rd_data[14:0], 1'b0};
end
end
/******************
* Gain table RAM
*******************/
wire [4:0] ctrl_dsa1;
wire [4:0] ctrl_dsa2;
/* Use half of table for low band, other half for high band
* Software decides address mapping
*/
rhodium_gain_table gain_table(
.wr_clk(load_sck),
.wr_en(wr_en),
.wr_addr({load_table_sel, load_index}),
.wr_data({load_dsa1, load_dsa2}),
.wr_data_prev({load_dsa1_prev, load_dsa2_prev}),
.rd_clk(ctrl_sck),
.rd_addr({ctrl_table_sel, ctrl_index}),
.rd_data({ctrl_dsa1, ctrl_dsa2})
);
/******************
* Gain control
*******************/
reg [4:0] ctrl_bit_cnt;
reg [1:0] ctrl_tbl;
reg [5:0] ctrl_index;
reg [5:0] gain1;
reg [5:0] gain2;
reg gain1_t;
reg gain2_t;
assign dsa = !gain1_t ? ctrl_dsa1 :
(!gain2_t ? ctrl_dsa2 :
5'b11111);
// Cycle counter for where we are in protocol and shift register for input
// Also controls timing of DSAs' latch enable signals
always @ (posedge ctrl_sck or posedge ctrl_csb)
begin
if (ctrl_csb) begin
ctrl_bit_cnt <= 5'd0;
dsa1_le <= 1'b0;
dsa2_le <= 1'b0;
gain1_t <= 1'b1;
gain2_t <= 1'b1;
end else if (!ctrl_csb) begin
if (ctrl_bit_cnt < 23) begin
ctrl_bit_cnt <= ctrl_bit_cnt + 5'd1;
end
if (ctrl_bit_cnt < 8) begin
{ctrl_tbl, ctrl_index} <= {ctrl_tbl[0], ctrl_index, ctrl_mosi};
end
if (ctrl_tbl == TABLE_NUM) begin
if ((ctrl_bit_cnt == CNT_GAIN1_DRIVE) && (ctrl_mosi)) begin
gain1 <= ctrl_index;
gain1_t <= 1'b0;
end else if ((gain1_t == 1'b0) && (ctrl_bit_cnt == CNT_DSA1_LE_RISE)) begin
dsa1_le <= 1'b1;
end else if ((gain1_t == 1'b0) && (ctrl_bit_cnt == CNT_DSA1_LE_FALL)) begin
dsa1_le <= 1'b0;
end else if ((gain1_t == 1'b0) && (ctrl_bit_cnt == CNT_GAIN1_RELEASE)) begin
gain1_t <= 1'b1;
end
if ((ctrl_bit_cnt == CNT_GAIN2_DRIVE) && (ctrl_mosi)) begin
gain2 <= ctrl_index;
gain2_t <= 1'b0;
end else if ((gain2_t == 1'b0) && (ctrl_bit_cnt == CNT_DSA2_LE_RISE)) begin
dsa2_le <= 1'b1;
end else if ((gain2_t == 1'b0) && (ctrl_bit_cnt == CNT_DSA2_LE_FALL)) begin
dsa2_le <= 1'b0;
end else if ((gain2_t == 1'b0) && (ctrl_bit_cnt == CNT_GAIN2_RELEASE)) begin
gain2_t <= 1'b1;
end
end
end
end
// SPI readback for ctrl bus, based on current bit count
always @ (negedge ctrl_sck)
begin
case (ctrl_bit_cnt) // Shift out on neg edge
11: ctrl_miso <= gain1[5];
12: ctrl_miso <= gain1[4];
13: ctrl_miso <= gain1[3];
14: ctrl_miso <= gain1[2];
15: ctrl_miso <= gain1[1];
16: ctrl_miso <= gain1[0];
18: ctrl_miso <= gain2[5];
19: ctrl_miso <= gain2[4];
20: ctrl_miso <= gain2[3];
21: ctrl_miso <= gain2[2];
22: ctrl_miso <= gain2[1];
23: ctrl_miso <= gain2[0];
default: ctrl_miso <= 1'b0;
endcase
end
endmodule // rhodium_gain_ctrl
`default_nettype wire
@@ -0,0 +1,54 @@
///////////////////////////////////////////////////////////////////
//
// Copyright 2018 Ettus Research, A National Instruments Company
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// Module: rhodium_gain_table
// Description:
// Simple dual port memory for use as gain table
// Implements a 128 x 16 bit dual-port RAM for storing 10-bit gain values.
// Write and read domains are independent. Data takes 1 cycle to become valid
// on the output of the RAM once written.
//////////////////////////////////////////////////////////////////////
`default_nettype none
module rhodium_gain_table
(
input wire wr_clk,
input wire wr_en,
input wire [6:0] wr_addr,
input wire [9:0] wr_data,
// Read data for wr_addr (read-first/read-before-write): One cycle latency
output wire [9:0] wr_data_prev,
input wire rd_clk,
input wire [6:0] rd_addr,
output wire [9:0] rd_data // Read data for rd_addr: One cycle latency
);
reg [15:0] gain_table[127:0];
reg [15:0] wr_data_prev_r;
reg [15:0] rd_data_r;
assign wr_data_prev = wr_data_prev_r[15:6];
assign rd_data = rd_data_r[15:6];
always @ (posedge wr_clk)
begin
if (wr_en)
gain_table[wr_addr] <= {wr_data, 6'b0};
wr_data_prev_r <= gain_table[wr_addr];
end
always @ (posedge rd_clk)
begin
rd_data_r <= gain_table[rd_addr];
end
endmodule // rhodium_gain_table
`default_nettype wire
+124
View File
@@ -0,0 +1,124 @@
///////////////////////////////////////////////////////////////////
//
// Copyright 2018 Ettus Research, A National Instruments Company
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// Module: rhodium_lo_gain
// Description:
// LO Gain controller for Rhodium
// Implements a gain index register (not a table)
//
// Provides 1 SPI slave:
// The "ctrl" slave takes in a gain index and drives the DSA with that
// value.
// The SPI formats are provided below.
//////////////////////////////////////////////////////////////////////
`default_nettype none
/**
* SPI DATA FORMAT (left-most bit is first)
* CTRL
* M {table_sel[1:0], rsvd, gain[4:0], rsvd[1:0], wr_dsa1, ------rsvd[5:0], wr_dsa2, ----rsvd[5:0]
* S {-------------------------------, --------------rsvd[3:0], gain1[4:0], -rsvd[1:0], gain2[4:0]}
*/
module rhodium_lo_gain #(
parameter TABLE_NUM = 2'b01
) (
input wire ctrl_sck,
input wire ctrl_csb,
input wire ctrl_mosi,
output reg ctrl_miso,
output wire [4:0] dsa,
output reg dsa1_le,
output reg dsa2_le
);
localparam CNT_GAIN1_DRIVE = 10,
CNT_DSA1_LE_RISE = 11,
CNT_DSA1_LE_FALL = 14,
CNT_GAIN1_RELEASE = 17;
localparam CNT_GAIN2_DRIVE = 17,
CNT_DSA2_LE_RISE = 18,
CNT_DSA2_LE_FALL = 21,
CNT_GAIN2_RELEASE = 24;
reg [4:0] ctrl_bit_cnt;
reg [1:0] ctrl_tbl;
reg [5:0] ctrl_index;
reg [5:0] gain1, gain2;
reg gain1_t;
reg gain2_t;
assign dsa = (!gain1_t | !gain2_t) ? ctrl_index[4:0] : 5'b11111;
// Cycle counter for where we are in protocol and shift register for input
// Also controls timing of DSAs' latch enable signals
always @ (posedge ctrl_sck or posedge ctrl_csb)
begin
if (ctrl_csb) begin
ctrl_bit_cnt <= 5'd0;
dsa1_le <= 1'b0;
dsa2_le <= 1'b0;
gain1_t <= 1'b1;
gain2_t <= 1'b1;
end else if (!ctrl_csb) begin
if (ctrl_bit_cnt < 23) begin
ctrl_bit_cnt <= ctrl_bit_cnt + 5'd1;
end
if (ctrl_bit_cnt < 8) begin
{ctrl_tbl, ctrl_index} <= {ctrl_tbl[0], ctrl_index, ctrl_mosi};
end
if (ctrl_tbl == TABLE_NUM) begin
if ((ctrl_bit_cnt == CNT_GAIN1_DRIVE) && (ctrl_mosi)) begin
gain1 <= ctrl_index;
gain1_t <= 1'b0;
end else if ((gain1_t == 1'b0) && (ctrl_bit_cnt == CNT_DSA1_LE_RISE)) begin
dsa1_le <= 1'b1;
end else if ((gain1_t == 1'b0) && (ctrl_bit_cnt == CNT_DSA1_LE_FALL)) begin
dsa1_le <= 1'b0;
end else if ((gain1_t == 1'b0) && (ctrl_bit_cnt == CNT_GAIN1_RELEASE)) begin
gain1_t <= 1'b1;
end
if ((ctrl_bit_cnt == CNT_GAIN2_DRIVE) && (ctrl_mosi)) begin
gain2 <= ctrl_index;
gain2_t <= 1'b0;
end else if ((gain2_t == 1'b0) && (ctrl_bit_cnt == CNT_DSA2_LE_RISE)) begin
dsa2_le <= 1'b1;
end else if ((gain2_t == 1'b0) && (ctrl_bit_cnt == CNT_DSA2_LE_FALL)) begin
dsa2_le <= 1'b0;
end else if ((gain2_t == 1'b0) && (ctrl_bit_cnt == CNT_GAIN2_RELEASE)) begin
gain2_t <= 1'b1;
end
end
end
end
// SPI readback for ctrl bus, based on current bit count
always @ (negedge ctrl_sck)
begin
case (ctrl_bit_cnt) // Shift out on neg edge
11: ctrl_miso <= gain1[5];
12: ctrl_miso <= gain1[4];
13: ctrl_miso <= gain1[3];
14: ctrl_miso <= gain1[2];
15: ctrl_miso <= gain1[1];
16: ctrl_miso <= gain1[0];
18: ctrl_miso <= gain2[5];
19: ctrl_miso <= gain2[4];
20: ctrl_miso <= gain2[3];
21: ctrl_miso <= gain2[2];
22: ctrl_miso <= gain2[1];
23: ctrl_miso <= gain2[0];
default: ctrl_miso <= 1'b0;
endcase
end
endmodule // rhodium_lo_gain
`default_nettype wire
+31
View File
@@ -0,0 +1,31 @@
# -------------------------------------------------------------------------- #
#
# Copyright (C) 2017 Intel Corporation. All rights reserved.
# Your use of Intel Corporation's design tools, logic functions
# and other software and tools, and its AMPP partner logic
# functions, and any output files from any of the foregoing
# (including device programming or simulation files), and any
# associated documentation or information are expressly subject
# to the terms and conditions of the Intel Program License
# Subscription Agreement, the Intel Quartus Prime License Agreement,
# the Intel MegaCore Function License Agreement, or other
# applicable license agreement, including, without limitation,
# that your use is for the sole purpose of programming logic
# devices manufactured by Intel and sold by Intel or its
# authorized distributors. Please refer to the applicable
# agreement for further details.
#
# -------------------------------------------------------------------------- #
#
# Quartus Prime
# Version 17.0.2 Build 602 07/19/2017 SJ Lite Edition
# Date created = 08:22:34 September 13, 2017
#
# -------------------------------------------------------------------------- #
QUARTUS_VERSION = "17.0"
DATE = "08:22:34 September 13, 2017"
# Revisions
PROJECT_REVISION = "rhodium_top"
+306
View File
@@ -0,0 +1,306 @@
# -------------------------------------------------------------------------- #
#
# Copyright (C) 2017 Intel Corporation. All rights reserved.
# Your use of Intel Corporation's design tools, logic functions
# and other software and tools, and its AMPP partner logic
# functions, and any output files from any of the foregoing
# (including device programming or simulation files), and any
# associated documentation or information are expressly subject
# to the terms and conditions of the Intel Program License
# Subscription Agreement, the Intel Quartus Prime License Agreement,
# the Intel MegaCore Function License Agreement, or other
# applicable license agreement, including, without limitation,
# that your use is for the sole purpose of programming logic
# devices manufactured by Intel and sold by Intel or its
# authorized distributors. Please refer to the applicable
# agreement for further details.
#
# -------------------------------------------------------------------------- #
#
# Quartus Prime
# Version 17.0.2 Build 602 07/19/2017 SJ Lite Edition
# Date created = 08:22:34 September 13, 2017
#
# -------------------------------------------------------------------------- #
#
# Notes:
#
# 1) The default values for assignments are stored in the file:
# rhodium_top_assignment_defaults.qdf
# If this file doesn't exist, see file:
# assignment_defaults.qdf
#
# 2) Altera recommends that you do not modify this file. This
# file is updated automatically by the Quartus Prime software
# and any changes you make may be lost or overwritten.
#
# -------------------------------------------------------------------------- #
set_global_assignment -name FAMILY "MAX 10"
set_global_assignment -name DEVICE 10M04SAU169I7G
set_global_assignment -name TOP_LEVEL_ENTITY rhodium_top
set_global_assignment -name ORIGINAL_QUARTUS_VERSION 17.0.2
set_global_assignment -name PROJECT_CREATION_TIME_DATE "08:22:34 SEPTEMBER 13, 2017"
set_global_assignment -name LAST_QUARTUS_VERSION "18.1.0 Lite Edition"
set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
set_global_assignment -name MIN_CORE_JUNCTION_TEMP "-40"
set_global_assignment -name MAX_CORE_JUNCTION_TEMP 100
set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR 256
set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
set_location_assignment PIN_D11 -to CPLD_PS_SPI_LE_25
set_location_assignment PIN_F13 -to CPLD_PS_SPI_CLK_25
set_location_assignment PIN_E10 -to CPLD_PS_ADDR0_25
set_location_assignment PIN_A12 -to CPLD_PS_ADDR1_25
set_location_assignment PIN_F12 -to CPLD_PS_SPI_SDI_25
set_location_assignment PIN_F10 -to CPLD_PS_SPI_SDO_25
set_location_assignment PIN_B1 -to ADC_A_Over_Range_18
set_location_assignment PIN_D1 -to ADC_B_Over_Range_18
set_instance_assignment -name IO_STANDARD "1.8 V" -to ADC_A_Over_Range_18
set_instance_assignment -name IO_STANDARD "1.8 V" -to ADC_B_Over_Range_18
set_instance_assignment -name IO_STANDARD LVDS -to LO_SYNC
set_location_assignment PIN_G9 -to LO_SYNC
set_location_assignment PIN_G10 -to "LO_SYNC(n)"
set_instance_assignment -name IO_STANDARD "1.8 V" -to ADC_SPI_CS_L_18
set_location_assignment PIN_C2 -to ADC_SPI_CS_L_18
set_location_assignment PIN_C1 -to ADC_SPI_SCLK_18
set_location_assignment PIN_E3 -to ADC_SPI_SDIO_18
set_location_assignment PIN_M5 -to CLKDIST_SPI_CS_L
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to CLKDIST_SPI_CS_L
set_instance_assignment -name IO_STANDARD "1.8 V" -to ADC_SPI_SCLK_18
set_instance_assignment -name IO_STANDARD "1.8 V" -to ADC_SPI_SDIO_18
set_location_assignment PIN_L5 -to CLKDIST_SPI_SCLK
set_location_assignment PIN_N5 -to CLKDIST_SPI_SDIO
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to CLKDIST_SPI_SCLK
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to CLKDIST_SPI_SDIO
set_location_assignment PIN_K6 -to CLKDIST_Status_LD1
set_location_assignment PIN_J6 -to CLKDIST_Status_LD2
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to CLKDIST_Status_LD1
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to CLKDIST_Status_LD2
set_location_assignment PIN_M1 -to CPLD_ATR_TX_18
set_location_assignment PIN_L1 -to CPLD_ATR_RX_18
set_instance_assignment -name IO_STANDARD "1.8 V" -to CPLD_ATR_RX_18
set_instance_assignment -name IO_STANDARD "1.8 V" -to CPLD_ATR_TX_18
set_location_assignment PIN_H6 -to CPLD_PL_SPI_ADDR0_18
set_location_assignment PIN_K2 -to CPLD_PL_SPI_ADDR1_18
set_location_assignment PIN_J2 -to CPLD_PL_SPI_ADDR2_18
set_instance_assignment -name IO_STANDARD "1.8 V" -to CPLD_PL_SPI_ADDR0_18
set_instance_assignment -name IO_STANDARD "1.8 V" -to CPLD_PL_SPI_ADDR1_18
set_instance_assignment -name IO_STANDARD "1.8 V" -to CPLD_PL_SPI_ADDR2_18
set_location_assignment PIN_K1 -to CPLD_PL_SPI_LE_18
set_location_assignment PIN_H5 -to CPLD_PL_SPI_SCLK_18
set_location_assignment PIN_L3 -to CPLD_PL_SPI_SDI_18
set_location_assignment PIN_L2 -to CPLD_PL_SPI_SDO_18
set_instance_assignment -name IO_STANDARD "1.8 V" -to CPLD_PL_SPI_LE_18
set_instance_assignment -name IO_STANDARD "1.8 V" -to CPLD_PL_SPI_SCLK_18
set_instance_assignment -name IO_STANDARD "1.8 V" -to CPLD_PL_SPI_SDI_18
set_instance_assignment -name IO_STANDARD "1.8 V" -to CPLD_PL_SPI_SDO_18
set_location_assignment PIN_M2 -to DAC_Alarm_18
set_instance_assignment -name IO_STANDARD "1.8 V" -to DAC_Alarm_18
set_location_assignment PIN_N3 -to DAC_SPI_SDIO_18
set_location_assignment PIN_N2 -to DAC_SPI_SCLK_18
set_location_assignment PIN_M3 -to DAC_SPI_CS_L_18
set_instance_assignment -name IO_STANDARD "1.8 V" -to DAC_SPI_CS_L_18
set_instance_assignment -name IO_STANDARD "1.8 V" -to DAC_SPI_SCLK_18
set_instance_assignment -name IO_STANDARD "1.8 V" -to DAC_SPI_SDIO_18
set_location_assignment PIN_M7 -to LOSYNTH_RX_MUXOUT
set_location_assignment PIN_N7 -to LOSYNTH_TX_MUXOUT
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to LOSYNTH_RX_MUXOUT
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to LOSYNTH_TX_MUXOUT
set_location_assignment PIN_E6 -to LO_RX_CS_L
set_location_assignment PIN_B2 -to LO_SPI_SCLK
set_location_assignment PIN_M4 -to LO_SPI_SDI
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to LO_RX_CS_L
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to LO_SPI_SCLK
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to LO_SPI_SDI
set_location_assignment PIN_K5 -to LO_TX_CS_L
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to LO_TX_CS_L
set_location_assignment PIN_B6 -to Rx_DSA1_LE
set_location_assignment PIN_A9 -to Rx_DSA2_LE
set_location_assignment PIN_D8 -to Rx_DSA_C1
set_location_assignment PIN_D6 -to Rx_DSA_C2
set_location_assignment PIN_A11 -to Rx_DSA_C4
set_location_assignment PIN_B10 -to Rx_DSA_C8
set_location_assignment PIN_A10 -to Rx_DSA_C16
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Rx_DSA1_LE
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Rx_DSA2_LE
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Rx_DSA_C1
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Rx_DSA_C2
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Rx_DSA_C4
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Rx_DSA_C8
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Rx_DSA_C16
set_location_assignment PIN_B3 -to Rx_Demod_ADJ_1
set_location_assignment PIN_N4 -to Rx_Demod_ADJ_2
set_location_assignment PIN_J5 -to Rx_LO_Filter_Sw_1
set_location_assignment PIN_J7 -to Rx_LO_Filter_Sw_2
set_location_assignment PIN_L4 -to Rx_LO_Input_Select
set_location_assignment PIN_A6 -to Rx_Sw1_Ctrl_1
set_location_assignment PIN_A7 -to Rx_Sw1_Ctrl_2
set_location_assignment PIN_A5 -to Rx_Sw2_Ctrl
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Rx_Demod_ADJ_1
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Rx_Demod_ADJ_2
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Rx_Sw1_Ctrl_1
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Rx_Sw1_Ctrl_2
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Rx_Sw2_Ctrl
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Rx_LO_Filter_Sw_1
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Rx_LO_Filter_Sw_2
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Rx_LO_Input_Select
set_location_assignment PIN_A4 -to Rx_Sw3_Ctrl_1
set_location_assignment PIN_A3 -to Rx_Sw3_Ctrl_2
set_location_assignment PIN_C10 -to Rx_Sw4_Ctrl_1
set_location_assignment PIN_A8 -to Rx_Sw4_Ctrl_2
set_location_assignment PIN_B9 -to Rx_Sw4_Ctrl_3
set_location_assignment PIN_C9 -to Rx_Sw4_Ctrl_4
set_location_assignment PIN_K13 -to Tx_DSA1_LE
set_location_assignment PIN_K12 -to Tx_DSA2_LE
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Rx_Sw3_Ctrl_1
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Rx_Sw3_Ctrl_2
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Rx_Sw4_Ctrl_1
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Rx_Sw4_Ctrl_2
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Rx_Sw4_Ctrl_3
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Rx_Sw4_Ctrl_4
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Tx_DSA1_LE
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Tx_DSA2_LE
set_location_assignment PIN_H13 -to Tx_DSA_C1
set_location_assignment PIN_H8 -to Tx_DSA_C2
set_location_assignment PIN_J13 -to Tx_DSA_C4
set_location_assignment PIN_H10 -to Tx_DSA_C8
set_location_assignment PIN_J12 -to Tx_DSA_C16
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Tx_DSA_C1
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Tx_DSA_C2
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Tx_DSA_C4
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Tx_DSA_C8
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Tx_DSA_C16
set_location_assignment PIN_N6 -to Tx_LO_Filter_Sw_1
set_location_assignment PIN_N12 -to Tx_LO_Filter_Sw_2
set_location_assignment PIN_N8 -to Tx_LO_Input_Select
set_location_assignment PIN_L10 -to Tx_Sw1_Ctrl_1
set_location_assignment PIN_N10 -to Tx_Sw1_Ctrl_2
set_location_assignment PIN_N11 -to Tx_Sw2_Ctrl_1
set_location_assignment PIN_L11 -to Tx_Sw2_Ctrl_2
set_location_assignment PIN_L12 -to Tx_Sw3_Ctrl_1
set_location_assignment PIN_M13 -to Tx_Sw3_Ctrl_2
set_location_assignment PIN_K11 -to Tx_Sw3_Ctrl_3
set_location_assignment PIN_J9 -to Tx_Sw3_Ctrl_4
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Tx_LO_Filter_Sw_1
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Tx_LO_Filter_Sw_2
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Tx_LO_Input_Select
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Tx_Sw1_Ctrl_1
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Tx_Sw1_Ctrl_2
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Tx_Sw2_Ctrl_1
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Tx_Sw2_Ctrl_2
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Tx_Sw3_Ctrl_1
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Tx_Sw3_Ctrl_2
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Tx_Sw3_Ctrl_3
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Tx_Sw3_Ctrl_4
set_location_assignment PIN_B11 -to PHDAC_SPI_CS_L
set_location_assignment PIN_C11 -to PHDAC_SPI_SCLK
set_location_assignment PIN_D9 -to PHDAC_SPI_SDI
set_location_assignment PIN_N9 -to LODIST_Bd_SPI_CS_L
set_location_assignment PIN_J8 -to LODIST_Bd_SPI_SCLK
set_location_assignment PIN_M9 -to LODIST_Bd_SPI_SDI
set_location_assignment PIN_L13 -to LO_DSA_C1
set_location_assignment PIN_K10 -to LO_DSA_C2
set_location_assignment PIN_H9 -to LO_DSA_C4
set_location_assignment PIN_G12 -to LO_DSA_C8
set_location_assignment PIN_G13 -to LO_DSA_C16
set_location_assignment PIN_J10 -to RxLO_DSA_LE
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to LODIST_Bd_SPI_CS_L
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to LODIST_Bd_SPI_SCLK
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to LODIST_Bd_SPI_SDI
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to LO_DSA_C1
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to LO_DSA_C2
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to LO_DSA_C4
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to LO_DSA_C8
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to LO_DSA_C16
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to RxLO_DSA_LE
set_location_assignment PIN_B4 -to Rx_Sw6_Ctrl_1
set_location_assignment PIN_B5 -to Rx_Sw6_Ctrl_2
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Rx_Sw6_Ctrl_1
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Rx_Sw6_Ctrl_2
set_location_assignment PIN_M8 -to TxLO_DSA_LE
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to TxLO_DSA_LE
set_location_assignment PIN_M11 -to Tx_Sw5_Ctrl_1
set_location_assignment PIN_M12 -to Tx_Sw5_Ctrl_2
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Tx_Sw5_Ctrl_1
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Tx_Sw5_Ctrl_2
set_location_assignment PIN_D12 -to Cal_iso_Sw_Ctrl
set_location_assignment PIN_K8 -to LODIST_Bd_IO1
set_location_assignment PIN_M10 -to Tx_HB_LB_Select
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Tx_HB_LB_Select
set_location_assignment PIN_E8 -to Rx_HB_LB_Select
set_instance_assignment -name IO_STANDARD "3.3-V LVCMOS" -to Rx_HB_LB_Select
set_instance_assignment -name IO_STANDARD "2.5 V" -to PHDAC_SPI_CS_L
set_instance_assignment -name IO_STANDARD "2.5 V" -to PHDAC_SPI_SCLK
set_instance_assignment -name IO_STANDARD "2.5 V" -to PHDAC_SPI_SDI
set_instance_assignment -name IO_STANDARD "2.5 V" -to CPLD_PS_ADDR0_25
set_instance_assignment -name IO_STANDARD "2.5 V" -to CPLD_PS_ADDR1_25
set_instance_assignment -name IO_STANDARD "2.5 V" -to CPLD_PS_SPI_CLK_25
set_instance_assignment -name IO_STANDARD "2.5 V" -to CPLD_PS_SPI_LE_25
set_instance_assignment -name IO_STANDARD "2.5 V" -to CPLD_PS_SPI_SDI_25
set_instance_assignment -name IO_STANDARD "2.5 V" -to CPLD_PS_SPI_SDO_25
set_instance_assignment -name IO_STANDARD "2.5 V" -to Cal_iso_Sw_Ctrl
set_instance_assignment -name IO_STANDARD "3.3 V SCHMITT TRIGGER" -to LODIST_Bd_IO1
set_global_assignment -name EDA_SIMULATION_TOOL "ModelSim-Altera (Verilog)"
set_global_assignment -name EDA_OUTPUT_DATA_FORMAT "VERILOG HDL" -section_id eda_simulation
set_location_assignment PIN_E4 -to usrp_io[0]
set_location_assignment PIN_G5 -to usrp_io[1]
set_location_assignment PIN_H4 -to usrp_io[2]
set_location_assignment PIN_J1 -to usrp_io[3]
set_location_assignment PIN_F1 -to usrp_io[4]
set_location_assignment PIN_C12 -to usrp_io[5]
set_location_assignment PIN_C13 -to usrp_io[6]
set_location_assignment PIN_E12 -to usrp_io[7]
set_location_assignment PIN_E13 -to usrp_io[8]
set_location_assignment PIN_B13 -to usrp_io[9]
set_location_assignment PIN_F9 -to usrp_io[10]
set_location_assignment PIN_B12 -to usrp_io[11]
set_location_assignment PIN_E9 -to usrp_io[12]
set_location_assignment PIN_F8 -to usrp_io[13]
set_instance_assignment -name IO_STANDARD "1.8 V" -to usrp_io[0]
set_instance_assignment -name IO_STANDARD "1.8 V" -to usrp_io[1]
set_instance_assignment -name IO_STANDARD "1.8 V" -to usrp_io[2]
set_instance_assignment -name IO_STANDARD "1.8 V" -to usrp_io[3]
set_instance_assignment -name IO_STANDARD "1.8 V" -to usrp_io[4]
set_instance_assignment -name IO_STANDARD "2.5 V" -to usrp_io[5]
set_instance_assignment -name IO_STANDARD "2.5 V" -to usrp_io[6]
set_instance_assignment -name IO_STANDARD "2.5 V" -to usrp_io[7]
set_instance_assignment -name IO_STANDARD "2.5 V" -to usrp_io[8]
set_instance_assignment -name IO_STANDARD "2.5 V" -to usrp_io[9]
set_instance_assignment -name IO_STANDARD "2.5 V" -to usrp_io[10]
set_instance_assignment -name IO_STANDARD "2.5 V" -to usrp_io[11]
set_instance_assignment -name IO_STANDARD "2.5 V" -to usrp_io[12]
set_instance_assignment -name IO_STANDARD "2.5 V" -to usrp_io[13]
set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW"
set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)"
set_global_assignment -name EDA_TIME_SCALE "1 ps" -section_id eda_simulation
set_global_assignment -name EDA_TEST_BENCH_ENABLE_STATUS TEST_BENCH_MODE -section_id eda_simulation
set_global_assignment -name EDA_NATIVELINK_SIMULATION_TEST_BENCH rh_tb -section_id eda_simulation
set_global_assignment -name EDA_TEST_BENCH_NAME rh_tb -section_id eda_simulation
set_global_assignment -name EDA_DESIGN_INSTANCE_NAME NA -section_id rh_tb
set_global_assignment -name EDA_TEST_BENCH_RUN_SIM_FOR "9000 ns" -section_id rh_tb
set_global_assignment -name EDA_TEST_BENCH_MODULE_NAME rh_tb -section_id rh_tb
set_global_assignment -name FLOW_ENABLE_POWER_ANALYZER ON
set_global_assignment -name POWER_DEFAULT_INPUT_IO_TOGGLE_RATE "12.5 %"
set_global_assignment -name EDA_RUN_TOOL_AUTOMATICALLY OFF -section_id eda_simulation
set_global_assignment -name OPTIMIZATION_MODE "HIGH PERFORMANCE EFFORT"
set_global_assignment -name VERILOG_FILE rhodium_top.v
set_global_assignment -name VERILOG_FILE rhodium_gain_ctrl.v
set_global_assignment -name VERILOG_FILE rhodium_gain_table.v
set_global_assignment -name VERILOG_FILE rhodium_lo_gain.v
set_global_assignment -name VERILOG_FILE rh_tb.v
set_global_assignment -name EDA_TEST_BENCH_FILE rh_tb.v -section_id rh_tb
set_global_assignment -name ENABLE_OCT_DONE OFF
set_global_assignment -name STRATIXV_CONFIGURATION_SCHEME "PASSIVE SERIAL"
set_global_assignment -name USE_CONFIGURATION_DEVICE ON
set_global_assignment -name CRC_ERROR_OPEN_DRAIN OFF
set_global_assignment -name GENERATE_SVF_FILE ON
set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -rise
set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -fall
set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -rise
set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -fall
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
+415
View File
@@ -0,0 +1,415 @@
# SPDX-License-Identifier: LGPL-3.0-or-later
#
# Copyright 2019 Ettus Research, A National Instruments Company
#
# Timing constraints for Rhodium's MAX 10 board controller
set_time_format -unit ns -decimal_places 3
# Some constants for constraining the design with the FPGA-centric method:
# Maximum trace propagation delay is assumed to be 0.6 ns on any traces
# to on-dboard slaves
set board_delay 0.600
set clk_uncertainty 0.150
###############################################################################
# Clocks
###############################################################################
# The PS SPI clock is maximum 10 MHz. It is driven from another source and
# provided with the data.
# CPLD_PS_SPI_CLK_25: 8 MHz
set sclk_ps_period 125.000
# Create clock for the PS's SPI interface
create_clock -name sclk_ps -period $sclk_ps_period \
[get_ports CPLD_PS_SPI_CLK_25]
# The PL SPI clock is split into two pieces. For the normal case, the clock
# frequency is 10 MHz. This is for any read operations.
#
# CPLD_PL_SPI_SCLK_18 pass through / read back ONLY: 10 MHz
set sclk_pl_period 100.000
create_clock -name sclk_pl -period $sclk_pl_period \
[get_ports CPLD_PL_SPI_SCLK_18]
# We can go faster for the PL writes to the internal registers and LOs.
# This rate is not supported for readback, but it helps with getting the DSA
# settings and LO settings in faster.
# CPLD_PL_SPI_SCLK_18 internal ONLY: 25 MHz
set sclk_pl_wr_period 40.000
create_clock -name sclk_pl_wr -period $sclk_pl_wr_period \
[get_ports CPLD_PL_SPI_SCLK_18] -add
# Output clocks for the MAX 10's SPI master interfaces (1 for each slave IC)
create_generated_clock -source [get_ports CPLD_PS_SPI_CLK_25] \
-name clkdist_clk [get_ports CLKDIST_SPI_SCLK]
create_generated_clock -source [get_ports CPLD_PS_SPI_CLK_25] \
-name adc_clk [get_ports ADC_SPI_SCLK_18]
create_generated_clock -source [get_ports CPLD_PS_SPI_CLK_25] \
-name dac_clk [get_ports DAC_SPI_SCLK_18]
create_generated_clock -source [get_ports CPLD_PS_SPI_CLK_25] \
-name phdac_clk [get_ports PHDAC_SPI_SCLK]
create_generated_clock -source [get_ports CPLD_PL_SPI_SCLK_18] \
-master_clock [get_clocks sclk_pl] \
-name lo_clk [get_ports LO_SPI_SCLK]
create_generated_clock -source [get_ports CPLD_PL_SPI_SCLK_18] \
-master_clock [get_clocks sclk_pl_wr] \
-name lo_wr_clk [get_ports LO_SPI_SCLK] -add
create_generated_clock -source [get_ports CPLD_PL_SPI_SCLK_18] \
-master_clock [get_clocks sclk_pl] \
-name lodist_clk [get_ports LODIST_Bd_SPI_SCLK]
# Virtual clock for DSA writes for skew calculations
#create_generated_clock -source [get_pins lo_gain_table\|dsa1_le\|clk]
create_generated_clock -source [get_ports CPLD_PL_SPI_SCLK_18] \
-master_clock [get_clocks sclk_pl_wr] \
-name dsa_reg_clk [get_pins lo_gain_table\|dsa1_le\|q]
create_generated_clock -source [get_pins lo_gain_table\|dsa1_le\|q] \
-name dsa_clk [get_ports RxLO_DSA_LE]
# PL's pass through clock doesn't interact with internal clock
set_clock_groups -physically_exclusive \
-group [get_clocks {sclk_pl_wr lo_wr_clk dsa_reg_clk dsa_clk}] \
-group [get_clocks {sclk_pl lo_clk lodist_clk}]
set_clock_groups -asynchronous \
-group [get_clocks {sclk_ps clkdist_clk adc_clk dac_clk phdac_clk}] \
-group [get_clocks {sclk_pl sclk_pl_wr lo_clk lodist_clk}]
set_clock_uncertainty -to [get_clocks {sclk_ps sclk_pl sclk_pl_wr clkdist_clk
adc_clk dac_clk phdac_clk lo_clk lo_wr_clk lodist_clk dsa_reg_clk dsa_clk}] \
$clk_uncertainty
###############################################################################
# Timing Budget Calculations
###############################################################################
# Here we carve out some timing budget for the master's SPI interfaces.
# The master will use these values to time its SPI interface.
# The PL's write-only values are smaller because there are no external chip
# dependencies.
set setup_ps 25
set hold_ps 30
# PL SPI is constrained on the master with an allowed skew value of +/- 3 ns
# relative to the launch clock
# Increase to 5 ns here for more margin
set pl_skew 5
# Clocks are nominally a 50% duty cycle, so difference between latch and
# launch is half a period, so subtract allowed skew from that for setup/hold
# specification. The half period is due to launch being the falling edge and
# latch being the rising edge.
set setup_pl [expr {$sclk_pl_period / 2 - $pl_skew}]
set hold_pl [expr {$sclk_pl_period / 2 - $pl_skew}]
set setup_pl_wr [expr {$sclk_pl_wr_period / 2 - $pl_skew}]
set hold_pl_wr [expr {$sclk_pl_wr_period / 2 - $pl_skew}]
# Calculate input delays relative to falling edge (launch)
# Min is hold time after previous rising edge (previous latch)
# Max is setup time before next rising edge (next latch)
set input_delay_min_ps [expr {-$sclk_ps_period / 2 + $hold_ps}]
set input_delay_max_ps [expr {$sclk_ps_period / 2 - $setup_ps}]
set input_delay_min_pl [expr {-$sclk_pl_period / 2 + $hold_pl}]
set input_delay_max_pl [expr {$sclk_pl_period / 2 - $setup_pl}]
set input_delay_min_pl_wr [expr {-$sclk_pl_wr_period / 2 + $hold_pl_wr}]
set input_delay_max_pl_wr [expr {$sclk_pl_wr_period / 2 - $setup_pl_wr}]
# Again, carve out timing budget for master's SPI interface
# Readback on the master will depend on clk-to-q of our slave.
# These values will need to be at least as large as the worst slave.
# Clock arrival at the slave will be delayed by propagation through the MAX 10
# Data to the MAX 10's input port will be further delayed by slave's clk-to-q
# On top of that, we then need budget for the data to cross the MAX 10, head
# out the I/O, and propagate to the master's pin. Then the master will need
# some budget for setup time.
#
# Here is what we'll budget:
# Clk propagation to I/O: 7 ns
# Clk trace delay: 1 ns
# Worst-case chip clk-to-q: 10 ns
# Data trace delay: 1 ns
# Data propagation delay from input pin to output pin: 8 ns
# Total clk-to-q from MAX 10 sclk input to MAX 10 output: 27 ns
#
# Then master's budget is 23 ns for clock delay + data delay + setup time
set clk_q_max_ps 27.000
# For the PL, the worst-case chip changes to 2 ns, so there is more budget
set clk_q_max_pl 20.000
# clk-to-q determines one side of the data invalid window
# The maximum output delay is simply latch edge - clk-to-q
# Launch is falling edge, and latch is rising edge, so...
set output_delay_max_ps [expr {$sclk_ps_period / 2 - $clk_q_max_ps}]
set output_delay_max_pl [expr {$sclk_pl_period / 2 - $clk_q_max_pl}]
# The minimum output delay represents the other edge of the data invalid
# window. Our clock is likely quite delayed already, but add a little more
# margin for hold time.
set output_delay_min_ps -5.000
set output_delay_min_pl -5.000
###############################################################################
# I/O groups (for reference later)
###############################################################################
# Chip selects
set ps_csb [get_ports {
CPLD_PS_ADDR0_25
CPLD_PS_ADDR1_25
CPLD_PS_SPI_LE_25
usrp_io[12]
usrp_io[13]
}]
set pl_csb [get_ports {
CPLD_PL_SPI_ADDR0_18
CPLD_PL_SPI_ADDR1_18
CPLD_PL_SPI_ADDR2_18
CPLD_PL_SPI_LE_18
}]
# Data for internal PL SPI
set pl_src [get_ports {
CPLD_PL_SPI_SDI_18
}]
# Passthrough inputs (forward direction)
# CPLD_PS_SPI_CLK_25 and CPLD_PL_SPI_SCLK_18 are special
set ps_pt_src [get_ports {CPLD_PS_SPI_LE_25
usrp_io[12]
usrp_io[13]
CPLD_PS_ADDR1_25
CPLD_PS_SPI_SDI_25
}]
set pl_pt_src [get_ports {CPLD_PL_SPI_LE_18
CPLD_PL_SPI_ADDR1_18
CPLD_PL_SPI_ADDR2_18
CPLD_PL_SPI_SDI_18
}]
# Passthrough outputs (forward direction)
# And inputs from the SPI slaves (readback direction)
set clkdist_spi_out [get_ports {
CLKDIST_SPI_CS_L
CLKDIST_SPI_SDIO
}]
set clkdist_spi_in [get_ports {
CLKDIST_SPI_SDIO
}]
set phdac_spi [get_ports {
PHDAC_SPI_CS_L
PHDAC_SPI_SDI
}]
set dac_spi_out [get_ports {
DAC_SPI_CS_L_18
DAC_SPI_SDIO_18
}]
set dac_spi_in [get_ports {
DAC_SPI_SDIO_18
}]
set adc_spi_out [get_ports {
ADC_SPI_CS_L_18
ADC_SPI_SDIO_18
}]
set adc_spi_in [get_ports {
ADC_SPI_SDIO_18
}]
set lo_spi_out [get_ports {
LO_TX_CS_L
LO_RX_CS_L
LO_SPI_SDI
}]
set lo_spi_in [get_ports {
LOSYNTH_RX_MUXOUT
LOSYNTH_TX_MUXOUT
}]
set lodist_spi_out [get_ports {
LODIST_Bd_SPI_CS_L
LODIST_Bd_SPI_SDI
}]
# Readback outputs
set ps_rb_out [get_ports CPLD_PS_SPI_SDO_25]
set pl_rb_out [get_ports CPLD_PL_SPI_SDO_18]
##############################################################################
# Chip-selects provide async resets
##############################################################################
set_false_path -from $ps_csb -to [get_pins *|clrn]
set_false_path -from $pl_csb -to [get_pins *|clrn]
# Also ignore setup/hold analysis for chip-selects affecting readback path
# These are available many cycles before readback begins and have
# combinatorial paths to the output
set_false_path -from $ps_csb -to $ps_rb_out
set_false_path -from $pl_csb -to $pl_rb_out
set_input_delay -clock sclk_ps -clock_fall -max $input_delay_max_ps \
[get_ports CPLD_PS_ADDR0_25]
set_input_delay -clock sclk_ps -clock_fall -min $input_delay_min_ps \
[get_ports CPLD_PS_ADDR0_25]
set_input_delay -clock sclk_pl -clock_fall -max $input_delay_max_pl \
[get_ports CPLD_PL_SPI_ADDR0_18]
set_input_delay -clock sclk_pl -clock_fall -min $input_delay_min_pl \
[get_ports CPLD_PL_SPI_ADDR0_18]
set_input_delay -clock sclk_pl_wr -clock_fall -max $input_delay_max_pl_wr \
[get_ports CPLD_PL_SPI_ADDR0_18] -add
set_input_delay -clock sclk_pl_wr -clock_fall -min $input_delay_min_pl_wr \
[get_ports CPLD_PL_SPI_ADDR0_18] -add
##############################################################################
# Input delays from SPI master
##############################################################################
set_input_delay -clock sclk_ps -clock_fall -max $input_delay_max_ps $ps_pt_src
set_input_delay -clock sclk_ps -clock_fall -min $input_delay_min_ps $ps_pt_src
set_input_delay -clock sclk_pl -clock_fall -max $input_delay_max_pl $pl_pt_src
set_input_delay -clock sclk_pl -clock_fall -min $input_delay_min_pl $pl_pt_src
set_input_delay -clock sclk_pl_wr -clock_fall -max $input_delay_max_pl_wr $pl_src -add
set_input_delay -clock sclk_pl_wr -clock_fall -min $input_delay_min_pl_wr $pl_src -add
##############################################################################
# Output delays to each SPI slave (uses setup/hold times from data sheet)
##############################################################################
set adc_setup 4
set adc_hold 2
set_output_delay -clock adc_clk -max [expr {$adc_setup + $board_delay}] \
$adc_spi_out
set_output_delay -clock adc_clk -min [expr {-$adc_hold - $board_delay}] \
$adc_spi_out
set dac_setup 10
set dac_hold 5
set_output_delay -clock dac_clk -max [expr {$dac_setup + $board_delay}] \
$dac_spi_out
set_output_delay -clock dac_clk -min [expr {-$dac_hold - $board_delay}] \
$dac_spi_out
set phdac_setup 5
set phdac_hold 5
set_output_delay -clock phdac_clk -max [expr {$phdac_setup + $board_delay}] \
$phdac_spi
set_output_delay -clock phdac_clk -min [expr {-$phdac_hold - $board_delay}] \
$phdac_spi
set clkdist_setup 10
set clkdist_hold 10
set_output_delay -clock clkdist_clk -max [expr {$clkdist_setup + $board_delay}] \
$clkdist_spi_out
set_output_delay -clock clkdist_clk -min [expr {-$clkdist_hold - $board_delay}] \
$clkdist_spi_out
set lo_setup 2
set lo_hold 2
set_output_delay -clock lo_wr_clk -max [expr {$lo_setup + $board_delay}] \
$lo_spi_out
set_output_delay -clock lo_wr_clk -min [expr {-$lo_hold - $board_delay}] \
$lo_spi_out
##############################################################################
# Input delays from each SPI slave (uses clk-to-q times from data sheet)
# One board delay for clock, another for data
##############################################################################
set lo_clk_q 2
set_input_delay -clock lo_clk -clock_fall -max [expr {$lo_clk_q + $board_delay + $board_delay}] \
$lo_spi_in
set_input_delay -clock lo_clk -clock_fall -min 0 \
$lo_spi_in
set adc_clk_q 10
set dac_clk_q 10
set clkdist_clk_q 10
set_input_delay -clock adc_clk -clock_fall -max [expr {$adc_clk_q + $board_delay + $board_delay}] \
$adc_spi_in
set_input_delay -clock adc_clk -clock_fall -min 0 \
$adc_spi_in
set_input_delay -clock dac_clk -clock_fall -max [expr {$dac_clk_q + $board_delay + $board_delay}] \
$dac_spi_in
set_input_delay -clock dac_clk -clock_fall -min 0 \
$dac_spi_in
set_input_delay -clock clkdist_clk -clock_fall -max [expr {$clkdist_clk_q + $board_delay + $board_delay}] \
$clkdist_spi_in
set_input_delay -clock clkdist_clk -clock_fall -min 0 \
$clkdist_spi_in
##############################################################################
# Output delays for readback path
##############################################################################
set_output_delay -clock sclk_ps -max $output_delay_max_ps $ps_rb_out
set_output_delay -clock sclk_ps -min $output_delay_min_ps $ps_rb_out
set_output_delay -clock sclk_pl -max $output_delay_max_pl $pl_rb_out
set_output_delay -clock sclk_pl -min $output_delay_min_pl $pl_rb_out
##############################################################################
# GPIOs and DSAs
# Outputs that aren't timing-critical
##############################################################################
set gpos [get_ports {Tx_Sw*
Rx_LO_*
Tx_LO_*
Rx_Sw*
Rx_Demod_*
Tx_HB_LB_Select
Rx_HB_LB_Select
Cal_iso_Sw_Ctrl
LODIST_Bd_IO1
}]
# Inputs that aren't timing-critical
set gpis [get_ports {LO_SYNC
CPLD_ATR_TX_18
CPLD_ATR_RX_18
DAC_Alarm_18
CLKDIST_Status*
LODIST_Bd_IO1
}]
# DSAs (special skew needs)
# RxLO_DSA_LE used for skew basis
set dsas [get_ports {Tx_DSA*
Rx_DSA*
TxLO_DSA*
LO_DSA*
}]
# Just do false paths for gpios
set_false_path -to $gpos
set_false_path -from $gpis
# Unused
set_false_path -to $lodist_spi_out
# DSA skew timing
# Earlier, we created a "clock" for one of the DSA latch enable signals
# Use set_output_delay to constrain skew around the latch enable
# set_multicycle_path is used to make latch clock = launch clock for setup
# Constrain skew to 8 ns -- controller nominally does 120 ns minimum between
# edges, and 100 ns is the DSA's requirement for setup/hold
set dsa_skew 8.0
set_output_delay -clock dsa_clk -max -$dsa_skew $dsas
set_output_delay -clock dsa_clk -min $dsa_skew $dsas
set_multicycle_path -start -setup 0 -to $dsas
set_max_delay -from [get_ports CPLD_ATR_TX_18] \
-to [get_ports {Tx_Sw1_Ctrl_1 Tx_Sw1_Ctrl_2}] 10.0
+605
View File
@@ -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