diff options
Diffstat (limited to 'fpga/usrp3/top/n3xx/dboards/rh')
26 files changed, 8799 insertions, 0 deletions
diff --git a/fpga/usrp3/top/n3xx/dboards/rh/Makefile.srcs b/fpga/usrp3/top/n3xx/dboards/rh/Makefile.srcs new file mode 100644 index 000000000..1296e68e6 --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/rh/Makefile.srcs @@ -0,0 +1,32 @@ +# +# Copyright 2018 Ettus Research, a National Instruments Company +# + +################################################## +# DB IFC Sources +################################################## +RHODIUM_DB_SRCS = $(abspath $(addprefix $(BASE_DIR)/n3xx/dboards/rh/db_ifc/, \ +DbCore.vhd \ +DaughterboardRegs.vhd \ +ClockingRegs.vhd \ +PkgRhPersonality.vhd \ +PkgDaughterboardRegMap.vhd \ +PkgClockingRegMap.vhd \ +PkgJesdConfig.vhd \ +PkgAdcDacInterfaceTypes.vhd \ +RadioClocking.vhd \ +Jesd204bXcvrCore.edf \ +)) + +RHODIUM_TOP_SRCS = $(abspath $(addprefix $(BASE_DIR)/n3xx/dboards/rh/, \ +n3xx.v \ +)) + +RHODIUM_DB_CLOCKS_XDC = $(abspath $(addprefix $(BASE_DIR)/n3xx/dboards/rh/, \ +db_clocks.xdc \ +)) + +RHODIUM_DB_XDC = $(abspath $(addprefix $(BASE_DIR)/n3xx/dboards/rh/, \ +db_pins.xdc \ +db_timing.xdc \ +)) diff --git a/fpga/usrp3/top/n3xx/dboards/rh/cpld/Makefile b/fpga/usrp3/top/n3xx/dboards/rh/cpld/Makefile new file mode 100644 index 000000000..ff1598894 --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/rh/cpld/Makefile @@ -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) + diff --git a/fpga/usrp3/top/n3xx/dboards/rh/cpld/rh_tb.v b/fpga/usrp3/top/n3xx/dboards/rh/cpld/rh_tb.v new file mode 100644 index 000000000..fb5f62328 --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/rh/cpld/rh_tb.v @@ -0,0 +1,410 @@ +/////////////////////////////////////////////////////////////////// +// +// Copyright 2018 Ettus Research, A National Instruments Company +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: rh_tb +// Simple testbench for rhodium_top +// This creates a rudimentary stimulus only, to allow results to be viewed +// in the waveform viewer +////////////////////////////////////////////////////////////////////// + +`timescale 1ns/1ps + + +module rh_tb; + +reg ADC_A_Over_Range_18, ADC_B_Over_Range_18; + +wire [13:0] usrpio_io; // TODO: use one of these as pl_spi_addr[3] + +wire CPLD_PS_SPI_LE_25, CPLD_PS_SPI_CLK_25, + CPLD_PS_ADDR0_25, CPLD_PS_ADDR1_25, CPLD_PS_SPI_SDI_25; +wire CPLD_PS_SPI_SDO_25; + +wire CPLD_PL_SPI_SDO_18; +wire CPLD_PL_SPI_LE_18, CPLD_PL_SPI_SCLK_18, + CPLD_PL_SPI_SDI_18, + CPLD_PL_SPI_ADDR0_18, CPLD_PL_SPI_ADDR1_18, + CPLD_PL_SPI_ADDR2_18, + CPLD_ATR_TX_18, CPLD_ATR_RX_18; +// NOTE: TxRx front-end switches are driven direct from the motherboard, so these ATR +// lines have no function at this time. + +wire ADC_SPI_CS_L_18, ADC_SPI_SCLK_18; +wire ADC_SPI_SDIO_18; + +wire DAC_SPI_CS_L_18, DAC_SPI_SCLK_18; +wire DAC_SPI_SDIO_18; +reg DAC_Alarm_18; // TODO: drive to gpio? + +wire PHDAC_SPI_CS_L, PHDAC_SPI_SCLK, PHDAC_SPI_SDI; + + +reg LO_SYNC; + +wire CLKDIST_SPI_CS_L, + CLKDIST_SPI_SCLK; +wire CLKDIST_SPI_SDIO; + +wire Tx_DSA_C1, + Tx_DSA_C2, + Tx_DSA_C4, + Tx_DSA_C8, + Tx_DSA_C16; + wire Tx_DSA1_LE, + Tx_DSA2_LE; + wire Tx_Sw1_Ctrl_1, + Tx_Sw1_Ctrl_2, + Tx_Sw2_Ctrl_1, + Tx_Sw2_Ctrl_2, + Tx_Sw3_Ctrl_1, + Tx_Sw3_Ctrl_2, + Tx_Sw3_Ctrl_3, + Tx_Sw3_Ctrl_4, + Rx_LO_Input_Select, + Rx_LO_Filter_Sw_1, + Rx_LO_Filter_Sw_2, + Tx_LO_Input_Select, + Tx_LO_Filter_Sw_1, + Tx_LO_Filter_Sw_2; +wire CLKDIST_Status_LD1, + CLKDIST_Status_LD2; +wire LOSYNTH_RX_MUXOUT, + LOSYNTH_TX_MUXOUT; + +wire LO_SPI_SCLK, + LO_SPI_SDI, + LO_TX_CS_L, + LO_RX_CS_L, + Rx_Sw1_Ctrl_1, + Rx_Sw1_Ctrl_2, + Rx_DSA_C1, + Rx_DSA_C2, + Rx_DSA_C4, + Rx_DSA_C8, + Rx_DSA_C16; + wire Rx_DSA1_LE, + Rx_DSA2_LE; + wire Rx_Sw2_Ctrl, + Rx_Sw3_Ctrl_1, + Rx_Sw3_Ctrl_2, + Rx_Sw4_Ctrl_1, + Rx_Sw4_Ctrl_2, + Rx_Sw4_Ctrl_3, + Rx_Sw4_Ctrl_4, + Rx_Demod_ADJ_1, + Rx_Demod_ADJ_2; +wire LO_DSA_C1, + LO_DSA_C2, + LO_DSA_C4, + LO_DSA_C8, + LO_DSA_C16; +wire RxLO_DSA_LE, + TxLO_DSA_LE; +wire LODIST_Bd_SPI_CS_L, + LODIST_Bd_SPI_SDI, + LODIST_Bd_SPI_SCLK, + Tx_Sw5_Ctrl_1, + Tx_Sw5_Ctrl_2, + Rx_Sw6_Ctrl_1, + Rx_Sw6_Ctrl_2; +wire LODIST_Bd_IO1; +wire Tx_HB_LB_Select, +Rx_HB_LB_Select, +Cal_iso_Sw_Ctrl; + + +parameter dly = 20; + +integer scnt; +integer acnt; +integer ccnt; +integer ccnt_max; + +reg ps_sck; +reg ps_mosi; +reg clkdis_cs_b; +reg cpld_ps_cs_b; +reg phdac_cs_b; +reg adc_cs_b; +reg dac_cs_b; + +reg pl_sck; +reg pl_mosi; +reg txlo_cs_b; +reg rxlo_cs_b; +reg lodis_cs_b; +reg cpld_pl_cs_b; + +task ps_cpld_xfer; + input [1:0] tbl; + input [5:0] cmd; + input [15:0] data; + reg [23:0] shiftreg; + integer i; +begin + ps_sck <= 1'b0; + clkdis_cs_b <= 1'b1; + cpld_ps_cs_b <= 1'b1; + phdac_cs_b <= 1'b1; + adc_cs_b <= 1'b1; + dac_cs_b <= 1'b1; + txlo_cs_b <= 1'b1; + rxlo_cs_b <= 1'b1; + lodis_cs_b <= 1'b1; + cpld_pl_cs_b <= 1'b1; + shiftreg <= {tbl,cmd,data}; + #(dly); + cpld_ps_cs_b <= 1'b0; + #(dly); + for (i = 0; i < 24; i = i + 1) begin + ps_sck <= 1'b0; + ps_mosi <= shiftreg[23-i]; + #(dly); + ps_sck <= 1'b1; + #(dly); + end + ps_sck <= 1'b0; + #(dly); + cpld_ps_cs_b <= 1'b1; + #(dly); +end +endtask + +task pl_cpld_xfer; + input [1:0] tbl; + input [5:0] cmd; + input [15:0] data; + reg [23:0] shiftreg; + integer i; +begin + pl_sck <= 1'b0; + clkdis_cs_b <= 1'b1; + cpld_ps_cs_b <= 1'b1; + phdac_cs_b <= 1'b1; + adc_cs_b <= 1'b1; + dac_cs_b <= 1'b1; + txlo_cs_b <= 1'b1; + rxlo_cs_b <= 1'b1; + lodis_cs_b <= 1'b1; + cpld_pl_cs_b <= 1'b1; + shiftreg <= {tbl,cmd,data}; + #(dly); + cpld_pl_cs_b <= 1'b0; + #(dly); + for (i = 0; i < 24; i = i + 1) begin + pl_sck <= 1'b0; + pl_mosi <= shiftreg[23-i]; + #(dly); + pl_sck <= 1'b1; + #(dly); + end + pl_sck <= 1'b0; + #(dly); + cpld_pl_cs_b <= 1'b1; + #(dly); +end +endtask + +assign CPLD_PS_SPI_LE_25 = clkdis_cs_b; +assign CPLD_PS_ADDR0_25 = cpld_ps_cs_b; +assign CPLD_PS_ADDR1_25 = phdac_cs_b; +assign usrpio_io[12] = adc_cs_b; +assign usrpio_io[13] = dac_cs_b; +assign CPLD_PS_SPI_CLK_25 = ps_sck; +assign CPLD_PS_SPI_SDI_25 = ps_mosi; + +assign CPLD_PL_SPI_LE_18 = txlo_cs_b; +assign CPLD_PL_SPI_ADDR1_18 = rxlo_cs_b; +assign CPLD_PL_SPI_ADDR2_18 = lodis_cs_b; +assign CPLD_PL_SPI_ADDR0_18 = cpld_pl_cs_b; +assign CPLD_PL_SPI_SCLK_18 = pl_sck; +assign CPLD_PL_SPI_SDI_18 = pl_mosi; + +assign CLKDIST_Status_LD1 = 1'b0; +assign LOSYNTH_RX_MUXOUT = 1'b1; +assign LOSYNTH_TX_MUXOUT = 1'b1; + +initial +begin + $dumpfile("rh_cpld.vcd"); + $dumpvars; + // Check Signature register read-back + #(dly) ps_cpld_xfer(2'b00, {5'b00000, 1'b1}, 16'h0000); + // Check Signature register is read-only + #(dly) ps_cpld_xfer(2'b00, {5'b00000, 1'b0}, 16'h1234); + #(dly) ps_cpld_xfer(2'b00, {5'b00000, 1'b1}, 16'h0000); + + // Load portions of lower RX gain table with some values + #(dly) ps_cpld_xfer(2'b00, {5'b00110, 1'b0}, 16'h0000); /* Write GAIN_BAND_SEL for lower table */ + #(dly) ps_cpld_xfer(2'b01, 6'd0, {2'd0, 5'd0, 5'd1, 1'b1, 3'd0}); + #(dly) ps_cpld_xfer(2'b01, 6'd1, {2'd0, 5'd0, 5'd2, 1'b1, 3'd0}); + #(dly) ps_cpld_xfer(2'b01, 6'd2, {2'd0, 5'd1, 5'd2, 1'b1, 3'd0}); + #(dly) ps_cpld_xfer(2'b01, 6'd3, {2'd0, 5'd1, 5'd3, 1'b1, 3'd0}); + + // Load portions of upper RX gain table with some values + #(dly) ps_cpld_xfer(2'b00, {5'b00110, 1'b0}, 16'h0101); /* Write GAIN_BAND_SEL for upper table */ + #(dly) ps_cpld_xfer(2'b01, 6'd4, {2'd0, 5'd2, 5'd3, 1'b1, 3'd0}); + #(dly) ps_cpld_xfer(2'b01, 6'd5, {2'd0, 5'd2, 5'd4, 1'b1, 3'd0}); + #(dly) ps_cpld_xfer(2'b01, 6'd6, {2'd0, 5'd3, 5'd4, 1'b1, 3'd0}); + #(dly) ps_cpld_xfer(2'b01, 6'd7, {2'd0, 5'd3, 5'd5, 1'b1, 3'd0}); + + // Check RX gain table readback + #(dly) ps_cpld_xfer(2'b01, 6'd0, 16'h0); + #(dly) ps_cpld_xfer(2'b01, 6'd1, 16'h0); + #(dly) ps_cpld_xfer(2'b01, 6'd2, 16'h0); + #(dly) ps_cpld_xfer(2'b01, 6'd3, 16'h0); + #(dly) ps_cpld_xfer(2'b01, 6'd4, 16'h0); + #(dly) ps_cpld_xfer(2'b01, 6'd5, 16'h0); + #(dly) ps_cpld_xfer(2'b01, 6'd6, 16'h0); + + // Check can write a couple registers on PL side + // (Also make sure we're looking at the lower gain tables) + #(dly) pl_cpld_xfer(2'b00, {5'd6, 1'b0}, 16'h0000); + #(dly) pl_cpld_xfer(2'b00, {5'd7, 1'b0}, 16'h0000); + + // Check retrieval of gain values for RX table and program DSAs + #(dly) pl_cpld_xfer(2'b01, 6'd2, {2'b0, 1'b1, 6'b0, 1'b1, 6'b0}); + #(dly) pl_cpld_xfer(2'b01, 6'd3, {2'b0, 1'b0, 6'b0, 1'b1, 6'b0}); + #(dly) pl_cpld_xfer(2'b01, 6'd1, {2'b0, 1'b1, 6'b0, 1'b0, 6'b0}); + + // Check writes to RXBS and TXBS registers + #(dly) pl_cpld_xfer(2'b00, {5'd6, 1'b0}, 16'h1ABC); + #(dly) pl_cpld_xfer(2'b00, {5'd7, 1'b0}, 16'h1CAB); + + // Check TX DSA programming is independent of RX DSA programming + #(dly) pl_cpld_xfer(2'b10, 6'd4, {2'b0, 1'b1, 6'b0, 1'b0, 6'b0}); + + // Check LO gain programming works + #(dly) pl_cpld_xfer(2'b11, 6'd5, {2'b0, 1'b1, 6'b0, 1'b0, 6'b0}); + #(dly) pl_cpld_xfer(2'b11, 6'd7, {2'b0, 1'b0, 6'b0, 1'b1, 6'b0}); + #(dly) pl_cpld_xfer(2'b11, 6'd0, {2'b0, 1'b0, 6'b0, 1'b0, 6'b0}); + + // More checks for PL register writes + #(dly) pl_cpld_xfer(2'b00, {5'd6, 1'b0}, 16'h0ABC); + #(dly) pl_cpld_xfer(2'b00, {5'd7, 1'b0}, 16'h0CAB); + #(dly) pl_cpld_xfer(2'b00, {5'd8, 1'b0}, 16'hAA5C); + #(dly) pl_cpld_xfer(2'b00, {5'd8, 1'b0}, 16'h5A5C); + #(dly) pl_cpld_xfer(2'b00, {5'd6, 1'b0}, 16'h1C42); + + // Check low/high gain tables and independence of RX vs. TX + #(dly) pl_cpld_xfer(2'b01, 6'd0, 16'h2040); + #(dly) pl_cpld_xfer(2'b00, {5'd7, 1'b0}, 16'h104C); + #(dly) pl_cpld_xfer(2'b10, 6'd0, 16'h2040); + #(dly) pl_cpld_xfer(2'b00, {5'd7, 1'b0}, 16'h0C80); + #(dly) pl_cpld_xfer(2'b10, 6'd5, 16'h2040); + $finish; +end + +rhodium_top toplevel_inst(usrpio_io, // bank 1A, 1B and 6 +ADC_A_Over_Range_18, ADC_B_Over_Range_18, // bank 1A + +// bank 6 +CPLD_PS_SPI_LE_25, +CPLD_PS_SPI_CLK_25, +CPLD_PS_ADDR0_25, +CPLD_PS_ADDR1_25, +CPLD_PS_SPI_SDI_25, +CPLD_PS_SPI_SDO_25, +PHDAC_SPI_CS_L, PHDAC_SPI_SCLK, PHDAC_SPI_SDI, +LO_SYNC, + +// bank 2 +CPLD_PL_SPI_SDO_18, +CPLD_PL_SPI_LE_18, +CPLD_PL_SPI_SCLK_18, +CPLD_PL_SPI_SDI_18, +CPLD_PL_SPI_ADDR0_18, +CPLD_PL_SPI_ADDR1_18, +CPLD_PL_SPI_ADDR2_18, +CPLD_ATR_TX_18, +CPLD_ATR_RX_18, +ADC_SPI_CS_L_18, +ADC_SPI_SCLK_18, +ADC_SPI_SDIO_18, +DAC_SPI_CS_L_18, +DAC_SPI_SCLK_18, +DAC_SPI_SDIO_18, +DAC_Alarm_18, + +// bank 3 + +CLKDIST_SPI_CS_L, +CLKDIST_SPI_SCLK, +CLKDIST_SPI_SDIO, +Tx_DSA_C1, +Tx_DSA_C2, +Tx_DSA_C4, +Tx_DSA_C8, +Tx_DSA_C16, +Tx_DSA1_LE, +Tx_DSA2_LE, +Tx_Sw1_Ctrl_1, +Tx_Sw1_Ctrl_2, +Tx_Sw2_Ctrl_1, +Tx_Sw2_Ctrl_2, +Tx_Sw3_Ctrl_1, +Tx_Sw3_Ctrl_2, +Tx_Sw3_Ctrl_3, +Tx_Sw3_Ctrl_4, +Rx_LO_Input_Select, +Rx_LO_Filter_Sw_1, +Rx_LO_Filter_Sw_2, +Tx_LO_Input_Select, +Tx_LO_Filter_Sw_1, +Tx_LO_Filter_Sw_2, +CLKDIST_Status_LD1, +CLKDIST_Status_LD2, +LOSYNTH_RX_MUXOUT, +LOSYNTH_TX_MUXOUT, + +// bank 8 +LO_SPI_SCLK, // fans out to both rx & tx synths +LO_SPI_SDI, +LO_TX_CS_L, +LO_RX_CS_L, +Rx_Sw1_Ctrl_1, +Rx_Sw1_Ctrl_2, +Rx_DSA_C1, +Rx_DSA_C2, +Rx_DSA_C4, +Rx_DSA_C8, +Rx_DSA_C16, +Rx_DSA1_LE, +Rx_DSA2_LE, +Rx_Sw2_Ctrl, +Rx_Sw3_Ctrl_1, +Rx_Sw3_Ctrl_2, +Rx_Sw4_Ctrl_1, +Rx_Sw4_Ctrl_2, +Rx_Sw4_Ctrl_3, +Rx_Sw4_Ctrl_4, +Rx_Demod_ADJ_1, +Rx_Demod_ADJ_2, + +// bank 5 +LO_DSA_C1, +LO_DSA_C2, +LO_DSA_C4, +LO_DSA_C8, +LO_DSA_C16, +RxLO_DSA_LE, +TxLO_DSA_LE, +LODIST_Bd_SPI_CS_L, +LODIST_Bd_SPI_SDI, +LODIST_Bd_SPI_SCLK, +LODIST_Bd_IO1, +Tx_Sw5_Ctrl_1, +Tx_Sw5_Ctrl_2, +Rx_Sw6_Ctrl_1, +Rx_Sw6_Ctrl_2, + +Tx_HB_LB_Select, +Rx_HB_LB_Select, +Cal_iso_Sw_Ctrl + + +); +endmodule // rh_tb diff --git a/fpga/usrp3/top/n3xx/dboards/rh/cpld/rhodium_gain_ctrl.v b/fpga/usrp3/top/n3xx/dboards/rh/cpld/rhodium_gain_ctrl.v new file mode 100644 index 000000000..b13eca846 --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/rh/cpld/rhodium_gain_ctrl.v @@ -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 diff --git a/fpga/usrp3/top/n3xx/dboards/rh/cpld/rhodium_gain_table.v b/fpga/usrp3/top/n3xx/dboards/rh/cpld/rhodium_gain_table.v new file mode 100644 index 000000000..abaca43ba --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/rh/cpld/rhodium_gain_table.v @@ -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 + diff --git a/fpga/usrp3/top/n3xx/dboards/rh/cpld/rhodium_lo_gain.v b/fpga/usrp3/top/n3xx/dboards/rh/cpld/rhodium_lo_gain.v new file mode 100644 index 000000000..0c4ed4c52 --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/rh/cpld/rhodium_lo_gain.v @@ -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 + diff --git a/fpga/usrp3/top/n3xx/dboards/rh/cpld/rhodium_top.qpf b/fpga/usrp3/top/n3xx/dboards/rh/cpld/rhodium_top.qpf new file mode 100644 index 000000000..5e1bf4d57 --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/rh/cpld/rhodium_top.qpf @@ -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" diff --git a/fpga/usrp3/top/n3xx/dboards/rh/cpld/rhodium_top.qsf b/fpga/usrp3/top/n3xx/dboards/rh/cpld/rhodium_top.qsf new file mode 100644 index 000000000..e94f0bbc8 --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/rh/cpld/rhodium_top.qsf @@ -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 diff --git a/fpga/usrp3/top/n3xx/dboards/rh/cpld/rhodium_top.sdc b/fpga/usrp3/top/n3xx/dboards/rh/cpld/rhodium_top.sdc new file mode 100644 index 000000000..4b00a5053 --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/rh/cpld/rhodium_top.sdc @@ -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 + diff --git a/fpga/usrp3/top/n3xx/dboards/rh/cpld/rhodium_top.v b/fpga/usrp3/top/n3xx/dboards/rh/cpld/rhodium_top.v new file mode 100644 index 000000000..1d0d640da --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/rh/cpld/rhodium_top.v @@ -0,0 +1,605 @@ +/////////////////////////////////////////////////////////////////// +// +// Copyright 2018 Ettus Research, A National Instruments Company +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: rhodium_top +////////////////////////////////////////////////////////////////////// + +`default_nettype none + +module rhodium_top( + +input [13:0] usrp_io, // bank 1A, 1B and 6 + +input ADC_A_Over_Range_18, input ADC_B_Over_Range_18, // bank 1A + +// bank 6 +input CPLD_PS_SPI_LE_25, +input CPLD_PS_SPI_CLK_25, +input CPLD_PS_ADDR0_25, +input CPLD_PS_ADDR1_25, +input CPLD_PS_SPI_SDI_25, +output reg CPLD_PS_SPI_SDO_25, +output PHDAC_SPI_CS_L, +output PHDAC_SPI_SCLK, +output PHDAC_SPI_SDI, +input LO_SYNC, + +// bank 2 +output reg CPLD_PL_SPI_SDO_18, +input CPLD_PL_SPI_LE_18, +input CPLD_PL_SPI_SCLK_18, +input CPLD_PL_SPI_SDI_18, +input CPLD_PL_SPI_ADDR0_18, +input CPLD_PL_SPI_ADDR1_18, +input CPLD_PL_SPI_ADDR2_18, +// NOTE: TxRx front-end switches are driven direct from the motherboard, so these ATR +// lines have no function at this time. +input CPLD_ATR_TX_18, +input CPLD_ATR_RX_18, +output ADC_SPI_CS_L_18, +output ADC_SPI_SCLK_18, +inout ADC_SPI_SDIO_18, +output DAC_SPI_CS_L_18, +output DAC_SPI_SCLK_18, +inout DAC_SPI_SDIO_18, +input DAC_Alarm_18, // TODO: drive to gpio? + +// bank 3 + +output CLKDIST_SPI_CS_L, +output CLKDIST_SPI_SCLK, +inout CLKDIST_SPI_SDIO, +output Tx_DSA_C1, +output Tx_DSA_C2, +output Tx_DSA_C4, +output Tx_DSA_C8, +output Tx_DSA_C16, +output Tx_DSA1_LE, +output Tx_DSA2_LE, +output Tx_Sw1_Ctrl_1, +output Tx_Sw1_Ctrl_2, +output Tx_Sw2_Ctrl_1, +output Tx_Sw2_Ctrl_2, +output Tx_Sw3_Ctrl_1, +output Tx_Sw3_Ctrl_2, +output Tx_Sw3_Ctrl_3, +output Tx_Sw3_Ctrl_4, +output Rx_LO_Input_Select, +output Rx_LO_Filter_Sw_1, +output Rx_LO_Filter_Sw_2, +output Tx_LO_Input_Select, +output Tx_LO_Filter_Sw_1, +output Tx_LO_Filter_Sw_2, +input CLKDIST_Status_LD1, +input CLKDIST_Status_LD2, +input LOSYNTH_RX_MUXOUT, +input LOSYNTH_TX_MUXOUT, + +// bank 8 +output LO_SPI_SCLK, // fans out to both rx & tx synths +output LO_SPI_SDI, +output LO_TX_CS_L, +output LO_RX_CS_L, +output Rx_Sw1_Ctrl_1, +output Rx_Sw1_Ctrl_2, +output Rx_DSA_C1, +output Rx_DSA_C2, +output Rx_DSA_C4, +output Rx_DSA_C8, +output Rx_DSA_C16, +output Rx_DSA1_LE, +output Rx_DSA2_LE, +output Rx_Sw2_Ctrl, +output Rx_Sw3_Ctrl_1, +output Rx_Sw3_Ctrl_2, +output Rx_Sw4_Ctrl_1, +output Rx_Sw4_Ctrl_2, +output Rx_Sw4_Ctrl_3, +output Rx_Sw4_Ctrl_4, +output Rx_Demod_ADJ_1, +output Rx_Demod_ADJ_2, + +// bank 5 +output LO_DSA_C1, +output LO_DSA_C2, +output LO_DSA_C4, +output LO_DSA_C8, +output LO_DSA_C16, +output RxLO_DSA_LE, +output TxLO_DSA_LE, +output LODIST_Bd_SPI_CS_L, +output LODIST_Bd_SPI_SDI, +output LODIST_Bd_SPI_SCLK, +inout LODIST_Bd_IO1, +output Tx_Sw5_Ctrl_1, +output Tx_Sw5_Ctrl_2, +output Rx_Sw6_Ctrl_1, +output Rx_Sw6_Ctrl_2, + +output Tx_HB_LB_Select, +output Rx_HB_LB_Select, +output Cal_iso_Sw_Ctrl + + +); + +/* PS SPI */ + +localparam GIT_HASH = 36'h`GIT_HASH; +localparam PROD_SIGNATURE = 16'h0045; // Product signature (Rhodium atomic number in BCD) +localparam REVISION_MINOR = 16'h0002; +localparam REVISION_MAJOR = 16'h0004; +localparam CPLD_BUILD_LSB = GIT_HASH[15:0]; // Build code LSB +localparam CPLD_BUILD_MSB = GIT_HASH[31:16]; // Build code MSB +localparam PSADDR_SIGNATURE = 3'd0; +localparam PSADDR_REV_MINOR = 3'd1; // Minor version register +localparam PSADDR_REV_MAJOR = 3'd2; // Major version register +localparam PSADDR_BUILD_LSB = 3'd3; +localparam PSADDR_BUILD_MSB = 3'd4; +localparam PSADDR_SCRATCH = 3'd5; // scratchpad register +localparam PSADDR_GAIN_SEL = 3'd6; // band select for gain table loader +localparam PSADDR_DAC_ALARM = 3'd7; // DAC alarm pin register + +// Sub-device selection for PS SPI +localparam PS_CPLD_REGS = 2'b00; +localparam GAIN_TABLE_RX = 2'b01; +localparam GAIN_TABLE_TX = 2'b10; +localparam GAIN_TABLE_LO = 2'b11; + +// Setting to put TX SW1 in isolation mode +localparam [1:0] TX_SW1_TERM = 2'b11; + +wire clkdis_cs_b = CPLD_PS_SPI_LE_25; +wire cpld_ps_cs_b = CPLD_PS_ADDR0_25; +wire phdac_cs_b = CPLD_PS_ADDR1_25; +wire adc_cs_b = usrp_io[12]; +wire dac_cs_b = usrp_io[13]; + +// CPLD PS SPI format (left-most bit first): +// {table_sel[1:0], rsvd, reg_addr[3:0], rnw, data[15:0]} +wire [1:0] cpld_ps_table_sel; +wire [6:0] cpld_ps_spi_addr; +wire cpld_ps_spi_rnw; +reg [7:0] cpld_ps_spi_cmd; +reg [15:0] cpld_ps_spi_rdata; +reg [14:0] cpld_ps_spi_wdata; +reg cpld_ps_spi_sdo; +reg [4:0] cpld_ps_cnt; + +assign {cpld_ps_spi_addr, cpld_ps_spi_rnw} = cpld_ps_spi_cmd; + +// CPLD registers +reg [15:0] spad; +reg [15:0] gain_load_sel; + +// Double sync. the DAC ALARM pin (async). +reg dac_alarm_ms, dac_alarm = 0; +always @(posedge CPLD_PS_SPI_CLK_25) begin + {dac_alarm, dac_alarm_ms} <= {dac_alarm_ms, DAC_Alarm_18}; +end + +wire rx_gain_load_tbl_sel; +wire rx_gain_load_miso; +wire rx_gain_ctrl_tbl_sel; +wire rx_gain_ctrl_miso; +wire tx_gain_load_tbl_sel; +wire tx_gain_load_miso; +wire tx_gain_ctrl_tbl_sel; +wire tx_gain_ctrl_miso; +wire lo_gain_ctrl_miso; + +assign rx_gain_load_tbl_sel = gain_load_sel[0]; +assign tx_gain_load_tbl_sel = gain_load_sel[8]; + +always @(posedge CPLD_PS_SPI_CLK_25 or posedge cpld_ps_cs_b) +begin + if (cpld_ps_cs_b) begin + cpld_ps_cnt <= 5'd0; + end else if (!cpld_ps_cs_b) begin + if (cpld_ps_cnt < 8) begin // Address / command + cpld_ps_spi_cmd <= {cpld_ps_spi_cmd[6:0], CPLD_PS_SPI_SDI_25}; + cpld_ps_cnt <= cpld_ps_cnt + 5'd1; + end else if (cpld_ps_cnt < 23) begin // Shift in write data + cpld_ps_spi_wdata <= {cpld_ps_spi_wdata[13:0], CPLD_PS_SPI_SDI_25}; + cpld_ps_cnt <= cpld_ps_cnt + 5'd1; + end else if (!cpld_ps_spi_rnw && cpld_ps_cnt == 23 && cpld_ps_spi_addr[6:5] == PS_CPLD_REGS) begin // Write + case (cpld_ps_spi_addr[2:0]) + PSADDR_SIGNATURE: ; + PSADDR_REV_MINOR: ; + PSADDR_REV_MAJOR: ; + PSADDR_BUILD_LSB: ; + PSADDR_BUILD_MSB: ; + PSADDR_SCRATCH: spad <= {cpld_ps_spi_wdata, CPLD_PS_SPI_SDI_25}; + PSADDR_GAIN_SEL: gain_load_sel <= {cpld_ps_spi_wdata, CPLD_PS_SPI_SDI_25}; + endcase + end + if (cpld_ps_cnt == 7) begin // Set up read one cycle earlier + case (cpld_ps_spi_cmd[2:0]) + + PSADDR_SIGNATURE: cpld_ps_spi_rdata <= PROD_SIGNATURE; + PSADDR_REV_MINOR: cpld_ps_spi_rdata <= REVISION_MINOR; + PSADDR_REV_MAJOR: cpld_ps_spi_rdata <= REVISION_MAJOR; + PSADDR_BUILD_LSB: cpld_ps_spi_rdata <= CPLD_BUILD_LSB; + PSADDR_BUILD_MSB: cpld_ps_spi_rdata <= CPLD_BUILD_MSB; + PSADDR_SCRATCH: cpld_ps_spi_rdata <= spad; + PSADDR_GAIN_SEL: cpld_ps_spi_rdata <= gain_load_sel; + PSADDR_DAC_ALARM: cpld_ps_spi_rdata <= {15'b0, dac_alarm}; + endcase + end else begin + cpld_ps_spi_rdata <= {cpld_ps_spi_rdata[14:0], 1'b1}; + end + end +end + +always @(negedge CPLD_PS_SPI_CLK_25) +begin + cpld_ps_spi_sdo <= cpld_ps_spi_rdata[15]; // Shift out on negative edge +end + +// CLKDIST 3-wire to 4-wire +reg [4:0] clkdis_cnt; +reg clkdis_rd_pre, clkdis_rd, clkdis_sdio_t; + +always @(posedge CPLD_PS_SPI_CLK_25 or posedge clkdis_cs_b) +begin + if (clkdis_cs_b) begin + clkdis_cnt <= 5'd0; + clkdis_rd <= 1'b0; + clkdis_rd_pre <= 1'b0; + end else if (!clkdis_cs_b) begin + if (clkdis_cnt < 23) + clkdis_cnt <= clkdis_cnt + 5'd1; + + if (clkdis_cnt == 5'd0) // Check if read + clkdis_rd_pre <= CPLD_PS_SPI_SDI_25; + + if (clkdis_cnt == 5'd15) + clkdis_rd <= clkdis_rd_pre; + end +end + +always @(negedge CPLD_PS_SPI_CLK_25 or posedge clkdis_cs_b) +begin + if (clkdis_cs_b) begin + clkdis_sdio_t <= 1'b0; + end else begin + clkdis_sdio_t <= clkdis_rd; + end +end + +// ADC 3-wire to 4-wire +reg [4:0] adc_cnt; +reg adc_rd_pre, adc_rd, adc_sdio_t; + +always @(posedge CPLD_PS_SPI_CLK_25 or posedge adc_cs_b) +begin + if (adc_cs_b) begin + adc_cnt <= 5'd0; + adc_rd <= 1'b0; + adc_rd_pre <= 1'b0; + end else if (!adc_cs_b) begin + if (adc_cnt < 23) + adc_cnt <= adc_cnt + 5'd1; + + if (adc_cnt == 5'd0) // Check if read + adc_rd_pre <= CPLD_PS_SPI_SDI_25; + + if (adc_cnt == 5'd15) + adc_rd <= adc_rd_pre; + end +end + +always @(negedge CPLD_PS_SPI_CLK_25 or posedge adc_cs_b) +begin + if (adc_cs_b) begin + adc_sdio_t <= 1'b0; + end else begin + adc_sdio_t <= adc_rd; + end +end + +// DAC 3-wire to 4-wire +reg [4:0] dac_cnt; +reg dac_rd_pre, dac_rd, dac_sdio_t; + +always @(posedge CPLD_PS_SPI_CLK_25 or posedge dac_cs_b) +begin + if (dac_cs_b) begin + dac_cnt <= 5'd0; + dac_rd <= 1'b0; + dac_rd_pre <= 1'b0; + end else if (!dac_cs_b) begin + if (dac_cnt < 23) + dac_cnt <= dac_cnt + 5'd1; + + if (dac_cnt == 5'd0) // Check if read + dac_rd_pre <= CPLD_PS_SPI_SDI_25; + + if (dac_cnt == 5'd7) + dac_rd <= dac_rd_pre; + end +end + +always @(negedge CPLD_PS_SPI_CLK_25 or posedge dac_cs_b) +begin + if (dac_cs_b) begin + dac_sdio_t <= 1'b0; + end else begin + dac_sdio_t <= dac_rd; + end +end + +// multiplexed slave device SPI ports +wire phdac_sck, phdac_sdi; +wire clkdis_sck, adc_sck, dac_sck; +assign clkdis_sck = (clkdis_cs_b == 1'b0) ? CPLD_PS_SPI_CLK_25 : 1'b0; + +assign CLKDIST_SPI_CS_L = clkdis_cs_b; +assign CLKDIST_SPI_SCLK = clkdis_sck; + +assign adc_sck = !adc_cs_b ? CPLD_PS_SPI_CLK_25 : 1'b0; +assign dac_sck = !dac_cs_b ? CPLD_PS_SPI_CLK_25 : 1'b0; + +assign ADC_SPI_CS_L_18 = adc_cs_b; +assign ADC_SPI_SCLK_18 = adc_sck; + +assign DAC_SPI_CS_L_18 = dac_cs_b; +assign DAC_SPI_SCLK_18 = dac_sck; + +assign CLKDIST_SPI_SDIO = (!clkdis_sdio_t && !clkdis_cs_b) ? CPLD_PS_SPI_SDI_25 : 1'bz ; +assign ADC_SPI_SDIO_18 = (!adc_sdio_t && !adc_cs_b) ? CPLD_PS_SPI_SDI_25 : 1'bz ; +assign DAC_SPI_SDIO_18 = (!dac_sdio_t && !dac_cs_b) ? CPLD_PS_SPI_SDI_25 : 1'bz ; + +always @(*) +begin + CPLD_PS_SPI_SDO_25 = 1'b1; + case ({cpld_ps_cs_b, clkdis_cs_b, adc_cs_b, dac_cs_b}) + 4'b0111: begin + case (cpld_ps_spi_addr[6:5]) + PS_CPLD_REGS : CPLD_PS_SPI_SDO_25 = cpld_ps_spi_sdo; + GAIN_TABLE_RX: CPLD_PS_SPI_SDO_25 = rx_gain_load_miso; + GAIN_TABLE_TX: CPLD_PS_SPI_SDO_25 = tx_gain_load_miso; + GAIN_TABLE_LO: CPLD_PS_SPI_SDO_25 = 1'b1; + endcase + end + 4'b1011: CPLD_PS_SPI_SDO_25 = CLKDIST_SPI_SDIO; + 4'b1101: CPLD_PS_SPI_SDO_25 = ADC_SPI_SDIO_18; + 4'b1110: CPLD_PS_SPI_SDO_25 = DAC_SPI_SDIO_18; + default: ; + endcase +end + +// note: no readback from PHDAC +assign phdac_sck = (phdac_cs_b == 1'b0) ? CPLD_PS_SPI_CLK_25 : 1'b0; +assign phdac_sdi = (phdac_cs_b == 1'b0) ? CPLD_PS_SPI_SDI_25 : 1'b1; + + +assign PHDAC_SPI_SCLK = phdac_sck; +assign PHDAC_SPI_CS_L = phdac_cs_b; +assign PHDAC_SPI_SDI = phdac_sdi; + + +/* PL SPI */ +// CPLD PL SPI format (left-most bit first): +// {table_sel[1:0], reg_addr[4:0], rnw, data[15:0]} + +//TXLO, RXLO, LODIS, CPLD +localparam PLADDR_SCRATCH = 4'b0101; // scratchpad register +localparam PLADDR_RXBS = 4'b0110; +localparam PLADDR_TXBS = 4'b0111; +localparam PLADDR_RFCTRL = 4'b1000; +localparam PL_CPLD_REGS = 2'b00; + +// CPLD PL registers +reg [15:0] rxbs = 'h0; +reg [15:0] txbs = 'h0; +reg [15:0] rfctrl = 'h0; + +// register address on the falling edge of chip-select +wire txlo_cs_b = CPLD_PL_SPI_LE_18; +wire rxlo_cs_b = CPLD_PL_SPI_ADDR1_18; +wire lodis_cs_b = CPLD_PL_SPI_ADDR2_18; +wire cpld_pl_cs_b = CPLD_PL_SPI_ADDR0_18; + +wire cpld_pl_spi_rnw; +wire [6:0] cpld_pl_spi_addr; +reg [7:0] cpld_pl_spi_cmd; +reg [15:0] cpld_pl_spi_rdata; +reg [14:0] cpld_pl_spi_wdata; +reg cpld_pl_spi_sdo; +reg [4:0] cpld_pl_cnt; + +assign {cpld_pl_spi_addr, cpld_pl_spi_rnw} = cpld_pl_spi_cmd; + +reg [15:0] pl_spad; + +always @(posedge CPLD_PL_SPI_SCLK_18 or posedge cpld_pl_cs_b) +begin + if (cpld_pl_cs_b) begin + cpld_pl_cnt <= 5'd0; + end else if (!cpld_pl_cs_b) begin + if (cpld_pl_cnt < 8) begin // Address / command + cpld_pl_spi_cmd <= {cpld_pl_spi_cmd[6:0], CPLD_PL_SPI_SDI_18}; + cpld_pl_cnt <= cpld_pl_cnt + 5'd1; + end else if (cpld_pl_cnt < 23) begin // Shift in write data + cpld_pl_spi_wdata <= {cpld_pl_spi_wdata[13:0], CPLD_PL_SPI_SDI_18}; + cpld_pl_cnt <= cpld_pl_cnt + 5'd1; + end else if (!cpld_pl_spi_rnw && cpld_pl_cnt == 23 && cpld_pl_spi_addr[6:5] == PL_CPLD_REGS) begin // Write + case (cpld_pl_spi_addr[3:0]) + PLADDR_SCRATCH: pl_spad <= {cpld_pl_spi_wdata, CPLD_PL_SPI_SDI_18}; + PLADDR_RXBS: rxbs <= {cpld_pl_spi_wdata, CPLD_PL_SPI_SDI_18}; + PLADDR_TXBS: txbs <= {cpld_pl_spi_wdata, CPLD_PL_SPI_SDI_18}; + PLADDR_RFCTRL: rfctrl <= {cpld_pl_spi_wdata, CPLD_PL_SPI_SDI_18}; + endcase + end + if (cpld_pl_cnt == 7) begin // Set up read one cycle earlier + case (cpld_pl_spi_cmd[3:0]) + PLADDR_SCRATCH: cpld_pl_spi_rdata <= pl_spad; + PLADDR_RXBS: cpld_pl_spi_rdata <= rxbs; + PLADDR_TXBS: cpld_pl_spi_rdata <= txbs; + PLADDR_RFCTRL: cpld_pl_spi_rdata <= rfctrl; + endcase + end else begin + cpld_pl_spi_rdata <= {cpld_pl_spi_rdata[14:0], 1'b1}; + end + end +end + +always @(negedge CPLD_PL_SPI_SCLK_18) +begin + cpld_pl_spi_sdo <= cpld_pl_spi_rdata[15]; // Shift out on negative edge +end + +// multiplexed slave device SPI ports, names aliased to protect the innocent +wire lo_sck, lodis_sck; +wire lo_sdi, lodis_sdi; +// Note: lo_sck and lo_sdi -> fan out to both rxlo and txlo synths + +assign { LO_TX_CS_L, LO_RX_CS_L } = { txlo_cs_b, rxlo_cs_b}; +assign LO_SPI_SCLK = lo_sck; +assign LO_SPI_SDI = lo_sdi; + + +assign LODIST_Bd_SPI_CS_L = lodis_cs_b; +assign LODIST_Bd_SPI_SDI = lodis_sdi; +assign LODIST_Bd_SPI_SCLK = lodis_sck; + + +assign lodis_sck = !lodis_cs_b ? CPLD_PL_SPI_SCLK_18 : 1'b0; +assign lodis_sdi = !lodis_cs_b ? CPLD_PL_SPI_SDI_18 : 1'b1; + +assign { lo_sck, lo_sdi } = (!txlo_cs_b | !rxlo_cs_b) ? {CPLD_PL_SPI_SCLK_18,CPLD_PL_SPI_SDI_18} : 2'b01; + + +always @(*) +begin + CPLD_PL_SPI_SDO_18 = 1'bz; + case ({cpld_pl_cs_b, txlo_cs_b, rxlo_cs_b}) + 3'b110: CPLD_PL_SPI_SDO_18 = LOSYNTH_RX_MUXOUT; + 3'b101: CPLD_PL_SPI_SDO_18 = LOSYNTH_TX_MUXOUT; + 3'b011: begin + case (cpld_pl_spi_addr[6:5]) + PL_CPLD_REGS : CPLD_PL_SPI_SDO_18 = cpld_pl_spi_sdo; + GAIN_TABLE_RX: CPLD_PL_SPI_SDO_18 = rx_gain_ctrl_miso; + GAIN_TABLE_TX: CPLD_PL_SPI_SDO_18 = tx_gain_ctrl_miso; + GAIN_TABLE_LO: CPLD_PL_SPI_SDO_18 = lo_gain_ctrl_miso; + endcase + end + default: ; + endcase +end + +assign rx_gain_ctrl_tbl_sel = rxbs[12]; +assign { Rx_Sw6_Ctrl_2, + Rx_Sw6_Ctrl_1, + Rx_Sw4_Ctrl_4, + Rx_Sw4_Ctrl_3, + Rx_Sw4_Ctrl_2, + Rx_Sw4_Ctrl_1, + Rx_Sw3_Ctrl_2, + Rx_Sw3_Ctrl_1, + Rx_Sw2_Ctrl, + Rx_Sw1_Ctrl_2, + Rx_Sw1_Ctrl_1 } = { rxbs[11:1] }; + +assign tx_gain_ctrl_tbl_sel = txbs[12]; +assign { Tx_Sw5_Ctrl_2, + Tx_Sw5_Ctrl_1, + Tx_Sw3_Ctrl_4, + Tx_Sw3_Ctrl_3, + Tx_Sw3_Ctrl_2, + Tx_Sw3_Ctrl_1, + Tx_Sw2_Ctrl_2, + Tx_Sw2_Ctrl_1} = { txbs[11:4] }; + +// Terminate TX when idle +assign {Tx_Sw1_Ctrl_2, Tx_Sw1_Ctrl_1} = CPLD_ATR_TX_18 ? txbs[3:2] : TX_SW1_TERM; + +assign { Rx_LO_Filter_Sw_2, + Rx_LO_Filter_Sw_1, + Tx_LO_Filter_Sw_2, + Tx_LO_Filter_Sw_1, + Rx_Demod_ADJ_1, + Rx_Demod_ADJ_2, + Rx_LO_Input_Select } = rfctrl[15:9]; + +assign { Rx_HB_LB_Select, + Tx_LO_Input_Select } = rfctrl[7:6]; + +assign { Tx_HB_LB_Select, + Cal_iso_Sw_Ctrl } + = { rfctrl[4:3] }; + + +// RX Gain Table +wire [4:0] rx_dsa; + +rhodium_gain_ctrl #( + .TABLE_NUM(GAIN_TABLE_RX) +) rx_gain_table ( + .load_table_sel(rx_gain_load_tbl_sel), + .load_sck(CPLD_PS_SPI_CLK_25), + .load_csb(cpld_ps_cs_b), + .load_mosi(CPLD_PS_SPI_SDI_25), + .load_miso(rx_gain_load_miso), + .ctrl_table_sel(rx_gain_ctrl_tbl_sel), + .ctrl_sck(CPLD_PL_SPI_SCLK_18), + .ctrl_csb(cpld_pl_cs_b), + .ctrl_mosi(CPLD_PL_SPI_SDI_18), + .ctrl_miso(rx_gain_ctrl_miso), + .dsa(rx_dsa), + .dsa1_le(Rx_DSA1_LE), + .dsa2_le(Rx_DSA2_LE) +); + +// TX Gain Table +wire [4:0] tx_dsa; + +rhodium_gain_ctrl #( + .TABLE_NUM(GAIN_TABLE_TX) +) tx_gain_table ( + .load_table_sel(tx_gain_load_tbl_sel), + .load_sck(CPLD_PS_SPI_CLK_25), + .load_csb(cpld_ps_cs_b), + .load_mosi(CPLD_PS_SPI_SDI_25), + .load_miso(tx_gain_load_miso), + .ctrl_table_sel(tx_gain_ctrl_tbl_sel), + .ctrl_sck(CPLD_PL_SPI_SCLK_18), + .ctrl_csb(cpld_pl_cs_b), + .ctrl_mosi(CPLD_PL_SPI_SDI_18), + .ctrl_miso(tx_gain_ctrl_miso), + .dsa(tx_dsa), + .dsa1_le(Tx_DSA1_LE), + .dsa2_le(Tx_DSA2_LE) +); + +// LO Gain Table +wire [4:0] lo_dsa; + +rhodium_lo_gain #( + .TABLE_NUM(GAIN_TABLE_LO) +) lo_gain_table ( + .ctrl_sck(CPLD_PL_SPI_SCLK_18), + .ctrl_csb(cpld_pl_cs_b), + .ctrl_mosi(CPLD_PL_SPI_SDI_18), + .ctrl_miso(lo_gain_ctrl_miso), + .dsa(lo_dsa), + .dsa1_le(RxLO_DSA_LE), + .dsa2_le(TxLO_DSA_LE) +); + +// Rx data shared by DSA1, DSA2 +assign { Rx_DSA_C16, Rx_DSA_C8, Rx_DSA_C4, Rx_DSA_C2, Rx_DSA_C1 } = rx_dsa; + +// Tx data shared by DSA1, DSA2 +assign { Tx_DSA_C16, Tx_DSA_C8, Tx_DSA_C4, Tx_DSA_C2, Tx_DSA_C1 } = tx_dsa; + +// data shared by both tx and rx lo DSAs +assign { LO_DSA_C16, LO_DSA_C8, LO_DSA_C4, LO_DSA_C2, LO_DSA_C1 } = lo_dsa; + +endmodule +`default_nettype wire + diff --git a/fpga/usrp3/top/n3xx/dboards/rh/db_clocks.xdc b/fpga/usrp3/top/n3xx/dboards/rh/db_clocks.xdc new file mode 100644 index 000000000..e78342849 --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/rh/db_clocks.xdc @@ -0,0 +1,118 @@ +# +# Copyright 2017 Ettus Research, A National Instruments Company +# SPDX-License-Identifier: LGPL-3.0 +# +# Timing analysis is performed in "usrp3/top/n3xx/dboards/rh/doc/rh_timing.xlsx". +# See this spreadsheet for more details and explanations. + +#******************************************************************************* +## Daughterboard Clocks +# +# 122.88, 200, 245.76 and 250 MHz Sample Rates are allowable with 2:1/1:2 DSP and +# 2 samples/cycle arriving at the FPGA: +# +# <-- 2:1/1:2 --> +# | Supported | Sample rate | FPGA Clk | +# |sample rates | at JESD core | Frequency | +# | (MSPS) | (MSPS) | (MHz) | +# |-------------|--------------|-----------| +# | 122.88 | 491.52 | 245.76 | (uses DUC/DDC) +# | 200.00 | 400.00 | 200.00 | +# | 245.76 | 491.52 | 245.76 | +# | 250.00 | 500.00 | 250.00 | +# +# Therefore, supported sample clocks are: 122.88, 200, 245.76 and 250 MHz. +# Constrain the paths to the max rate to support all rates in a single FPGA image. +set SAMPLE_CLK_PERIOD 4.00 +create_clock -name fpga_clk_a -period $SAMPLE_CLK_PERIOD [get_ports DBA_FPGA_CLK_P] +create_clock -name fpga_clk_b -period $SAMPLE_CLK_PERIOD [get_ports DBB_FPGA_CLK_P] +create_clock -name mgt_clk_dba -period $SAMPLE_CLK_PERIOD [get_ports DBA_MGTCLK_P] +create_clock -name mgt_clk_dbb -period $SAMPLE_CLK_PERIOD [get_ports DBB_MGTCLK_P] + +# The Radio Clocks coming from the DBs are synchronized together (at the converters) to +# a typical value of less than 100ps. To give ourselves and Vivado some margin, we claim +# here that the DB-B Radio Clock can arrive 500ps before or after the DB-A clock at +# the FPGA (note that the trace lengths of the Radio Clocks coming from the DBs to the +# FPGA are about 0.5" different, thereby incurring ~80ps of additional skew at the FPGA). +# There is one spot in the FPGA where we cross domains between the DB-A and +# DB-B clock, so we must ensure that Vivado can analyze that path safely. +set FPGA_CLK_EARLY -0.5 +set FPGA_CLK_LATE 0.5 +set_clock_latency -source -early $FPGA_CLK_EARLY [get_clocks fpga_clk_b] +set_clock_latency -source -late $FPGA_CLK_LATE [get_clocks fpga_clk_b] + +# Virtual clocks for constraining I/O (used below) +create_clock -name fpga_clk_a_v -period $SAMPLE_CLK_PERIOD +create_clock -name fpga_clk_b_v -period $SAMPLE_CLK_PERIOD + +# The set_clock_latency constraints set on fpga_clk_b are problematic when used with +# I/O timing, since the analyzer gives us a double-hit on the latency. One workaround +# (used here) is to simply swap the early and late times for the virtual clock so that +# it cancels out the source latency during analysis. D. Jepson tested this by setting +# the early and late numbers to zero and then their actual value, running timing reports +# on each. The slack report matches for both cases, showing that the reversed early/late +# numbers on the virtual clock zero out the latency effects on the actual clock. +# +# Note this is not a problem for the fpga_clk_a, since no latency is added. So only apply +# it to fpga_clk_b_v. +set_clock_latency -source -early $FPGA_CLK_LATE [get_clocks fpga_clk_b_v] +set_clock_latency -source -late $FPGA_CLK_EARLY [get_clocks fpga_clk_b_v] + + + +#******************************************************************************* +## Aliases for auto-generated clocks + +create_generated_clock -name radio_clk_fb [get_pins {dba_core/RadioClockingx/RadioClkMmcm/CLKFBOUT}] +create_generated_clock -name radio_clk [get_pins {dba_core/RadioClockingx/RadioClkMmcm/CLKOUT0}] +create_generated_clock -name radio_clk_2x [get_pins {dba_core/RadioClockingx/RadioClkMmcm/CLKOUT1}] + +create_generated_clock -name radio_clk_b_fb [get_pins {dbb_core/RadioClockingx/RadioClkMmcm/CLKFBOUT}] +create_generated_clock -name radio_clk_b [get_pins {dbb_core/RadioClockingx/RadioClkMmcm/CLKOUT0}] +create_generated_clock -name radio_clk_b_2x [get_pins {dbb_core/RadioClockingx/RadioClkMmcm/CLKOUT1}] + + + +#******************************************************************************* +## Generated clocks for output busses to the daughterboard +# +# These clock definitions need to come above the set_clock_groups commands below to work! + +# Define clocks on the PL SPI clock output pins for both DBs. Actual divider values are +# set by SW at run-time. Current divider value is 125 based on what radio clock +# rate is set. +# For the CPLD SPI endpoint alone, we need it to run at ~25 MHz (writes only), this means +# that at times, the PL SPI will have its divider set to 10 (radio_clock = 250 MHz) or 8 +# (radio_clock = 200 MHz). +# The readback clock is lower (~10 MHz), so create a separate clock for it. +# Use readback divide value of 24 for an even divider (and some overconstraining). +set PL_SPI_DIVIDE_VAL 10 +set PL_SPI_RB_DIVIDE_VAL 24 +set PL_SPI_CLK_A [get_ports DBA_CPLD_PL_SPI_SCLK] +create_generated_clock -name pl_spi_clk_a \ + -source [get_pins [all_fanin -flat -only_cells -startpoints_only $PL_SPI_CLK_A]/C] \ + -divide_by $PL_SPI_DIVIDE_VAL $PL_SPI_CLK_A +create_generated_clock -name pl_spi_rb_clk_a \ + -master_clock [get_clocks radio_clk] \ + -source [get_pins [all_fanin -flat -only_cells -startpoints_only $PL_SPI_CLK_A]/C] \ + -divide_by $PL_SPI_RB_DIVIDE_VAL -add $PL_SPI_CLK_A +set PL_SPI_CLK_B [get_ports DBB_CPLD_PL_SPI_SCLK] +create_generated_clock -name pl_spi_clk_b \ + -source [get_pins [all_fanin -flat -only_cells -startpoints_only $PL_SPI_CLK_B]/C] \ + -divide_by $PL_SPI_DIVIDE_VAL $PL_SPI_CLK_B +create_generated_clock -name pl_spi_rb_clk_b \ + -master_clock [get_clocks radio_clk] \ + -source [get_pins [all_fanin -flat -only_cells -startpoints_only $PL_SPI_CLK_B]/C] \ + -divide_by $PL_SPI_RB_DIVIDE_VAL -add $PL_SPI_CLK_B + +#******************************************************************************* +## JTAG +set DB_JTAG_DIVISOR 4 +create_generated_clock -name dba_jtag_tck -divide_by $DB_JTAG_DIVISOR \ + -source [get_pins {inst_n310_ps/jtag_0/U0/bitq_ctrl/bitq_state_reg[1]/C}] \ + [get_ports DBA_CPLD_JTAG_TCK] + +create_generated_clock -name dbb_jtag_tck -divide_by $DB_JTAG_DIVISOR \ + -source [get_pins {inst_n310_ps/jtag_1/U0/bitq_ctrl/bitq_state_reg[1]/C}] \ + [get_ports DBB_CPLD_JTAG_TCK] + diff --git a/fpga/usrp3/top/n3xx/dboards/rh/db_ifc/ClockingRegs.vhd b/fpga/usrp3/top/n3xx/dboards/rh/db_ifc/ClockingRegs.vhd new file mode 100644 index 000000000..52c68ab4a --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/rh/db_ifc/ClockingRegs.vhd @@ -0,0 +1,345 @@ +------------------------------------------------------------------------------- +-- +-- File: ClockingRegs.vhd +-- Author: Daniel Jepson; mods by Humberto Jimenez +-- Original Project: N310; N32x +-- Date: 17 March 2016 +-- +------------------------------------------------------------------------------- +-- Copyright 2016-2018 Ettus Research, A National Instruments Company +-- SPDX-License-Identifier: LGPL-3.0 +------------------------------------------------------------------------------- +-- +-- Purpose: +-- +-- Register access to the control/status bits and interfaces for the +-- RadioClocking module. +-- +-- XML register definition is included below the module. +-- +------------------------------------------------------------------------------- + +library ieee; + use ieee.std_logic_1164.all; + +library work; + use work.PkgClockingRegMap.all; + use work.PkgRegs.all; + + +entity ClockingRegs is + port( + -- Async reset. Can be tied low if desired. + aReset : in boolean; + -- Sync reset... used in the same places as the async one. + bReset : in boolean; + -- Register Bus Clock -- this module connects the BusClk to PsClk, so it's limited + -- to 200 MHz! + BusClk : in std_logic; + + bRegPortOut : out RegPortOut_t; + bRegPortIn : in RegPortIn_t; + + -- Phase shift interface to the RadioClkMmcm. + -- There is a reset crossing here between the MMCM reset and aReset. The outgoing + -- crossing is safe because (a) the enable signal driven to the MMCM is a strobe-only + -- signal and (b) this interface should only be used when the MMCM is not in reset + -- (SW waits for the MMCM to be out of reset and locked before using this interface). + -- The only input signal, pPsDone, is double-synced in this file before being used. + -- This is OK (even though it is a strobe signal) because there is only a reset + -- crossing and not a clock domain crossing. + pPsInc : out std_logic; + pPsEn : out std_logic; + pPsDone : in std_logic; + + -- PsClk is driven directly by BusClk, so p = b in the logic below! + PsClk : out std_logic; + + -- Sync reset strobes from the register bus to the RadioClkMmcm. + bRadioClkMmcmReset : out std_logic; + -- Status of RadioClk MMCM lock to register bus. + aRadioClksValid : in std_logic; + + bRadioClk1xEnabled : out std_logic; + bRadioClk2xEnabled : out std_logic; + bRadioClk3xEnabled : out std_logic; + + bJesdRefClkPresent : in std_logic + ); +end ClockingRegs; + + +architecture RTL of ClockingRegs is + + --vhook_sigstart + --vhook_sigend + + signal bRadioClkMmcmResetInt : std_logic := '1'; + + signal bRegPortOutLcl : RegPortOut_t := kRegPortOutZero; + + signal bPsDone, + bPsEn, + bPsInc, + pPsDoneDs_ms, + pPsDoneDs : std_logic := '0'; + + signal bRadioClk1xEnabledInt, + bRadioClk2xEnabledInt, + bRadioClk3xEnabledInt, + bRadioClksValid_ms, + bRadioClksValid : std_logic := '0'; + + attribute ASYNC_REG : string; + attribute ASYNC_REG of bRadioClksValid_ms : signal is "true"; + attribute ASYNC_REG of bRadioClksValid : signal is "true"; + attribute ASYNC_REG of pPsDoneDs_ms : signal is "true"; + attribute ASYNC_REG of pPsDoneDs : signal is "true"; + +begin + + -- Locals to outputs. + PsClk <= BusClk; + pPsInc <= bPsInc; + pPsEn <= bPsEn; + + bRadioClkMmcmReset <= bRadioClkMmcmResetInt; + + bRadioClk1xEnabled <= bRadioClk1xEnabledInt; + bRadioClk2xEnabled <= bRadioClk2xEnabledInt; + bRadioClk3xEnabled <= bRadioClk3xEnabledInt; + + + -- Write Registers : ------------------------------------------------------------------ + -- ------------------------------------------------------------------------------------ + WriteRegisters: process(aReset, BusClk) + begin + if aReset then + bRadioClkMmcmResetInt <= '1'; + bPsInc <= '0'; + bPsEn <= '0'; + bRadioClk1xEnabledInt <= '0'; + bRadioClk2xEnabledInt <= '0'; + bRadioClk3xEnabledInt <= '0'; + elsif rising_edge(BusClk) then + + if bReset then + bRadioClkMmcmResetInt <= '1'; + bPsInc <= '0'; + bPsEn <= '0'; + bRadioClk1xEnabledInt <= '0'; + bRadioClk2xEnabledInt <= '0'; + bRadioClk3xEnabledInt <= '0'; + else + -- Clear strobe + bPsEn <= '0'; + + if RegWrite(kPhaseShiftControl, bRegPortIn) then + if bRegPortIn.Data(kPsInc) = '1' then + bPsInc <= '1'; + bPsEn <= '1'; + elsif bRegPortIn.Data(kPsDec) = '1' then + bPsInc <= '0'; + bPsEn <= '1'; + end if; + end if; + + if RegWrite(kRadioClkMmcm, bRegPortIn) then + -- Set/Clear pair + if bRegPortIn.Data(kRadioClkMmcmResetSet) = '1' then + bRadioClkMmcmResetInt <= '1'; + elsif bRegPortIn.Data(kRadioClkMmcmResetClear) = '1' then + bRadioClkMmcmResetInt <= '0'; + end if; + end if; + + if RegWrite(kRadioClkEnables, bRegPortIn) then + bRadioClk1xEnabledInt <= bRegPortIn.Data(kRadioClk1xEnabled); + bRadioClk2xEnabledInt <= bRegPortIn.Data(kRadioClk2xEnabled); + bRadioClk3xEnabledInt <= bRegPortIn.Data(kRadioClk3xEnabled); + end if; + + end if; + end if; + end process WriteRegisters; + + + DoubleSyncs : process (aReset, BusClk) + begin + if aReset then + bRadioClksValid_ms <= '0'; + bRadioClksValid <= '0'; + pPsDoneDs_ms <= '0'; + pPsDoneDs <= '0'; + elsif rising_edge(BusClk) then + -- No sync reset on double-syncs (however there are default assignments above)! + bRadioClksValid_ms <= aRadioClksValid; + bRadioClksValid <= bRadioClksValid_ms; + pPsDoneDs_ms <= pPsDone; + pPsDoneDs <= pPsDoneDs_ms; + end if; + end process; + + + -- Read Registers : ------------------------------------------------------------------- + -- ------------------------------------------------------------------------------------ + ReadRegisters: process(aReset, BusClk) + begin + if aReset then + bRegPortOutLcl <= kRegPortOutZero; + bPsDone <= '0'; + elsif rising_edge(BusClk) then + + if bReset then + bRegPortOutLcl <= kRegPortOutZero; + bPsDone <= '0'; + else + -- Deassert strobes + bRegPortOutLcl.Data <= kRegPortDataZero; + + -- All of these transactions only take one clock cycle, so we do not have to + -- de-assert the Ready signal (ever). + bRegPortOutLcl.Ready <= true; + + -- Process the returned data from the phase shifter in the MMCM. Note that even + -- though the prefixes are different (p and b), we drive the PsClk from the BusClk + -- so this "crossing" is actually safe. Whenever the Done signal asserts (pPsDone - + -- pay attention to the prefix!) from the MMCM, we set a sticky bit to tell SW + -- that the shift operation is complete. + -- + -- However, if pPsDone asserts at the same time that SW tries to read the register, + -- we should accurately report that the operation is indeed complete and then NOT + -- store the sticky (since it has already been read by SW). If a read does not come + -- through at the same time pPsDone is asserted, then we store the done state as a + -- sticky, bPsDone, which is only cleared by a read to this register. + if RegRead(kPhaseShiftControl, bRegPortIn) then + -- The phase shift is always enabled for the feedback clock in RadioClocking.vhd + bRegPortOutLcl.Data(kPsEnabledForFdbClk) <= '1'; + bRegPortOutLcl.Data(kPsDone) <= bPsDone or pPsDoneDs; + bPsDone <= '0'; + elsif pPsDoneDs = '1' then + bPsDone <= '1'; + end if; + + if RegRead(kRadioClkMmcm, bRegPortIn) then + bRegPortOutLcl.Data(kRadioClkMmcmLocked) <= bRadioClksValid; + end if; + + if RegRead(kRadioClkEnables, bRegPortIn) then + bRegPortOutLcl.Data(kRadioClk1xEnabled) <= bRadioClk1xEnabledInt; + bRegPortOutLcl.Data(kRadioClk2xEnabled) <= bRadioClk2xEnabledInt; + bRegPortOutLcl.Data(kRadioClk3xEnabled) <= bRadioClk3xEnabledInt; + end if; + + if RegRead(kMgtRefClkStatus, bRegPortIn) then + bRegPortOutLcl.Data(kJesdRefClkPresent) <= bJesdRefClkPresent; + end if; + + end if; + end if; + end process ReadRegisters; + + -- Local to output + bRegPortOut <= bRegPortOutLcl; + + +end RTL; + + +--XmlParse xml_on +--<regmap name="ClockingRegMap"> +-- <group name="ClockingRegs"> +-- +-- <register name="RadioClkMmcm" size="32" offset="0x20" attributes="Readable|Writable"> +-- <info> +-- </info> +-- <bitfield name="RadioClkMmcmLocked" range="4"> +-- <info> +-- Reflects the locked status of the MMCM. '1' = locked. This bit is only valid +-- when the MMCM reset is de-asserted. Read-only. +-- </info> +-- </bitfield> +-- <bitfield name="RadioClkMmcmResetClear" range="1" attributes="Strobe"> +-- <info> +-- Controls the reset to the Radio Clock MMCM. Strobe this bit to de-assert the +-- reset to the MMCM. Default is reset asserted. Write-only. +-- </info> +-- </bitfield> +-- <bitfield name="RadioClkMmcmResetSet" range="0" attributes="Strobe"> +-- <info> +-- Controls the reset to the Radio Clock MMCM. Strobe this bit to assert the +-- reset to the MMCM. Default is reset asserted. Write-only. +-- </info> +-- </bitfield> +-- </register> +-- +-- <register name="PhaseShiftControl" size="32" offset="0x24" attributes="Readable|Writable"> +-- <info> +-- Phase Shift for RadioClkMmcm. +-- </info> +-- <bitfield name="PsDone" range="28"> +-- <info> +-- This bit should set after a shift operation successfully completes. +-- Reading this register will clear this bit. Read-only. +-- </info> +-- </bitfield> +-- <bitfield name="PsInc" range="0" attributes="Strobe"> +-- <info> +-- Strobe this bit to increment the phase. This bit is self-clearing and will +-- always return '0' when read. If PsInc and PsDec are asserted together, +-- the phase will increment. +-- </info> +-- </bitfield> +-- <bitfield name="PsDec" range="4" attributes="Strobe"> +-- <info> +-- Strobe this bit to decrement the phase. This bit is self-clearing and will +-- always return '0' when read. If PsInc and PsDec are asserted together, +-- the phase will increment. +-- </info> +-- </bitfield> +-- <bitfield name="PsEnabledForFdbClk" range="16"> +-- <info> +-- Read-only. +-- </info> +-- </bitfield> +-- </register> +-- +-- <register name="RadioClkEnables" size="32" offset="0x28" attributes="Readable|Writable"> +-- <info> +-- </info> +-- <bitfield name="RadioClk3xEnabled" range="8"> +-- <info> +-- Set to '1' to enable the clock. Default disabled = '0'. +-- Do so ONLY after the MMCM is out of reset and locked! +-- </info> +-- </bitfield> +-- <bitfield name="RadioClk2xEnabled" range="4"> +-- <info> +-- Set to '1' to enable the clock. Default disabled = '0'. +-- Do so ONLY after the MMCM is out of reset and locked! +-- </info> +-- </bitfield> +-- <bitfield name="RadioClk1xEnabled" range="0"> +-- <info> +-- Set to '1' to enable the clock. Default disabled = '0'. +-- Do so ONLY after the MMCM is out of reset and locked! +-- </info> +-- </bitfield> +-- </register> +-- +-- <register name="MgtRefClkStatus" size="32" offset="0x30" attributes="Readable"> +-- <info> +-- </info> +-- <bitfield name="JesdRefClkPresent" range="0"> +-- <info> +-- Live indicator of the MGT Reference Clock toggling and within expected +-- frequency limits. If this bit is de-asserted, then the JESD204b core will +-- not function correctly! +-- </info> +-- </bitfield> +-- </register> +-- +-- </group> +-- +--</regmap> +--XmlParse xml_off diff --git a/fpga/usrp3/top/n3xx/dboards/rh/db_ifc/DaughterboardRegs.vhd b/fpga/usrp3/top/n3xx/dboards/rh/db_ifc/DaughterboardRegs.vhd new file mode 100644 index 000000000..8a9c20372 --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/rh/db_ifc/DaughterboardRegs.vhd @@ -0,0 +1,116 @@ +------------------------------------------------------------------------------- +-- +-- File: DaughterboardRegs.vhd +-- Author: Daniel Jepson; mods by Humberto Jimenez +-- Original Project: N310; N32x +-- Date: 27 April 2016 +-- +------------------------------------------------------------------------------- +-- Copyright 2016-2018 Ettus Research, A National Instruments Company +-- SPDX-License-Identifier: LGPL-3.0 +------------------------------------------------------------------------------- +-- +-- Purpose: +-- +-- Register interface to the semi-static control lines for the Mg +-- Daughterboard. +-- +-- XML register definition is included below the module. +-- +------------------------------------------------------------------------------- + +library ieee; + use ieee.std_logic_1164.all; + +library work; + use work.PkgDaughterboardRegMap.all; + use work.PkgRegs.all; + + +entity DaughterboardRegs is + port( + -- Async reset. Can be tied low if desired. + aReset : in boolean; + -- Sync reset... used in the same places as the async one. + bReset : in boolean; + BusClk : in std_logic; + + bRegPortOut : out RegPortOut_t; + bRegPortIn : in RegPortIn_t; + + -- Slot and DB ID values. These should be tied to constants! + kDbId : in std_logic_vector(15 downto 0); + kSlotId : in std_logic + + ); +end DaughterboardRegs; + + +architecture RTL of DaughterboardRegs is + + --vhook_sigstart + --vhook_sigend + + signal bRegPortOutLcl : RegPortOut_t := kRegPortOutZero; + +begin + + + -- Read Registers : ------------------------------------------------------------------- + -- ------------------------------------------------------------------------------------ + ReadRegisters: process(aReset, BusClk) + begin + if aReset then + bRegPortOutLcl <= kRegPortOutZero; + elsif rising_edge(BusClk) then + if bReset then + bRegPortOutLcl <= kRegPortOutZero; + else + -- De-assert strobes + bRegPortOutLcl.Data <= kRegPortDataZero; + + -- All of these transactions only take one clock cycle, so we do not have to + -- de-assert the Ready signal (ever). + bRegPortOutLcl.Ready <= true; + + if RegRead(kDaughterboardId, bRegPortIn) then + bRegPortOutLcl.Data(kDbIdValMsb downto kDbIdVal) <= kDbId; + bRegPortOutLcl.Data(kSlotIdVal) <= kSlotId; + end if; + + end if; + end if; + end process ReadRegisters; + + -- Local to output + bRegPortOut <= bRegPortOutLcl; + + +end RTL; + + +--XmlParse xml_on +--<regmap name="DaughterboardRegMap"> +-- <group name="StaticControl" order="1"> +-- +-- <register name="DaughterboardId" size="32" offset="0x30" attributes="Readable"> +-- <info> +-- </info> +-- <bitfield name="DbIdVal" range="15..0"> +-- <info> +-- ID for the DB with which this file is designed to communicate. Matches the DB +-- EEPROM ID. +-- </info> +-- </bitfield> +-- <bitfield name="SlotIdVal" range="16"> +-- <info> +-- ID for the Slot this module controls. Options are 0 and 1 for the N310 MB. +-- </info> +-- </bitfield> +-- </register> +-- +-- </group> +-- +-- +--</regmap> +--XmlParse xml_off diff --git a/fpga/usrp3/top/n3xx/dboards/rh/db_ifc/DbCore.vhd b/fpga/usrp3/top/n3xx/dboards/rh/db_ifc/DbCore.vhd new file mode 100644 index 000000000..f54a976d1 --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/rh/db_ifc/DbCore.vhd @@ -0,0 +1,563 @@ +------------------------------------------------------------------------------- +-- +-- File: DbCore.vhd +-- Author: Daniel Jepson; mods by Humberto Jimenez +-- Original Project: N310; N320 +-- Date: 12 April 2017 +-- +------------------------------------------------------------------------------- +-- Copyright 2017-2018 Ettus Research, A National Instruments Company +-- SPDX-License-Identifier: LGPL-3.0 +------------------------------------------------------------------------------- +-- +-- Purpose: +-- +-- Wrapper file for Daughterboard Control. This includes the semi-static control +-- and status registers, clocking, synchronization, and JESD204B cores. +-- +-- There is no version register for the plain-text files here. +-- Version control for the Sync and JESD204B cores is internal to the netlists. +-- +-- The resets for this core are almost entirely local and/or synchronous. +-- bBusReset is a Synchronous reset on the BusClk domain that resets all of the +-- registers connected to the RegPort, as well as any other stray registers +-- connected to the BusClk. All other resets are local to the modules they touch. +-- No other reset drives all modules universally. +-- +------------------------------------------------------------------------------- + +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +library work; + use work.PkgRhPersonality.all; + use work.PkgRegs.all; + use work.PkgJesdConfig.all; + use work.PkgAdcDacInterfaceTypes.all; + + +entity DbCore is + generic( + -- Set to '1' to include the White Rabbit TDC. + kInclWhiteRabbitTdc : std_logic := '0' + ); + port( + + -- Resets -- + -- Synchronous Reset for the BusClk domain (mainly for the RegPort) + bBusReset : in std_logic; + + -- Clocks -- + -- Register Bus Clock (any frequency) + BusClk : in std_logic; + -- Always-on at 40 MHz + Clk40 : in std_logic; + -- Super secret crazy awesome measurement clock at weird frequencies. + MeasClk : in std_logic; + -- FPGA Sample Clock from DB LMK + FpgaClk_p : in std_logic; + FpgaClk_n : in std_logic; + + -- Sample Clock Sharing. The clocks generated in this module are exported out to the + -- top level so they can be shared amongst daughterboards. Therefore they must be + -- driven back into the SampleClk*x inputs at a higher level in order for this module + -- to work correctly. There are a few isolated cases where SampleClk*xOut is used + -- directly in this module, and those are documented below. + SampleClk1xOut : out std_logic; + SampleClk1x : in std_logic; + SampleClk2xOut : out std_logic; + SampleClk2x : in std_logic; + + + -- Register Ports -- + -- + -- Only synchronous resets can be used for these ports! + bRegPortInFlat : in std_logic_vector(49 downto 0); + bRegPortOutFlat : out std_logic_vector(33 downto 0); + + -- Slot ID value. This should be tied to a constant! + kSlotId : in std_logic; + + + -- SYSREF -- + -- + -- SYSREF direct from the LMK + sSysRefFpgaLvds_p, + sSysRefFpgaLvds_n : in std_logic; + -- SYNC directly to the LMK + aLmkSync : out std_logic; + + + -- JESD Signals -- + -- + -- GTX Sample Clock Reference Input. Direct connect to FPGA pins. + JesdRefClk_p, + JesdRefClk_n : in std_logic; + + -- ADC JESD PHY Interface. Direct connect to FPGA pins. + aAdcRx_p, + aAdcRx_n : in std_logic_vector(3 downto 0); + aSyncAdcOut_n : out std_logic; + + -- DAC JESD PHY Interface. Direct connect to FPGA pins. + aDacTx_p, + aDacTx_n : out std_logic_vector(3 downto 0); + aSyncDacIn_n : in std_logic; + + + -- Data Pipes to/from the DACs/ADCs -- + -- + -- - Data is presented as two samples per cycle. + -- - sAdcDataValid asserts when ADC data is valid. + -- - sDacReadyForInput asserts when DAC data is ready to be received. + -- + -- Reset Crossings: + -- The ADC data and valid outputs are synchronously cleared before the asynchronous + -- reset is asserted--preventing any reset crossing issues here between the RX + -- (internal to the core) reset and the no-reset domain of RFNoC. + -- + -- The DAC samples should be zeros on reset de-assertion due to RFI being de-asserted + -- in reset. If they are not zeros, then it is still OK because data is ignored until + -- RFI is asserted. DAC RFI is double-synchronized to protect against the reset + -- crossing. This is safe to do because it simply delays the output of RFI by two + -- cycles on the assertion edge, and as long as reset is held for more than two + -- cycles, the de-assertion edge of RFI should come long before the TX module is + -- taken out of reset. + + -- Supporting 2 samples per clk cycle. + sAdcDataValid : out std_logic; + sAdcDataSample0I : out std_logic_vector(15 downto 0); + sAdcDataSample0Q : out std_logic_vector(15 downto 0); + sAdcDataSample1I : out std_logic_vector(15 downto 0); + sAdcDataSample1Q : out std_logic_vector(15 downto 0); + -- + sDacReadyForInput : out std_logic; + sDacDataSample0I : in std_logic_vector(15 downto 0); + sDacDataSample0Q : in std_logic_vector(15 downto 0); + sDacDataSample1I : in std_logic_vector(15 downto 0); + sDacDataSample1Q : in std_logic_vector(15 downto 0); + + + -- RefClk & Timing & Sync -- + RefClk : in std_logic; + rPpsPulse : in std_logic; + rGatedPulseToPin : inout std_logic; -- straight to pin + sGatedPulseToPin : inout std_logic; -- straight to pin + sPps : out std_logic; + sPpsToIob : out std_logic; + + -- White Rabbit Timing & Sync -- + WrRefClk : in std_logic; + rWrPpsPulse : in std_logic; + rWrGatedPulseToPin : inout std_logic; -- straight to pin + sWrGatedPulseToPin : inout std_logic; -- straight to pin + aPpsSfpSel : in std_logic_vector(1 downto 0); + + -- Debug for JESD + sAdcSync : out std_logic; + sDacSync : out std_logic; + sSysRef : out std_logic; + + -- Debug for Timing & Sync + rRpTransfer : out std_logic; + sSpTransfer : out std_logic; + rWrRpTransfer : out std_logic; + sWrSpTransfer : out std_logic + ); + +end DbCore; + + +architecture RTL of DbCore is + + component Jesd204bXcvrCore + port ( + bBusReset : in STD_LOGIC; + BusClk : in STD_LOGIC; + ReliableClk40 : in STD_LOGIC; + FpgaClk1x : in STD_LOGIC; + FpgaClk2x : in STD_LOGIC; + bFpgaClksStable : in STD_LOGIC; + JesdRefClk_p : in STD_LOGIC; + JesdRefClk_n : in STD_LOGIC; + bJesdRefClkPresent : out STD_LOGIC; + aLmkSync : out STD_LOGIC; + bRegPortInFlat : in STD_LOGIC_VECTOR(49 downto 0); + bRegPortOutFlat : out STD_LOGIC_VECTOR(33 downto 0); + CaptureSysRefClk : in STD_LOGIC; + cSysRefFpgaLvds_p : in STD_LOGIC; + cSysRefFpgaLvds_n : in STD_LOGIC; + fSysRef : out STD_LOGIC; + aAdcRx_p : in STD_LOGIC_VECTOR(3 downto 0); + aAdcRx_n : in STD_LOGIC_VECTOR(3 downto 0); + aSyncAdcOut_n : out STD_LOGIC; + aDacTx_p : out STD_LOGIC_VECTOR(3 downto 0); + aDacTx_n : out STD_LOGIC_VECTOR(3 downto 0); + aSyncDacIn_n : in STD_LOGIC; + fAdcDataFlatter : out STD_LOGIC_VECTOR(63 downto 0); + fDacDataFlatter : in STD_LOGIC_VECTOR(63 downto 0); + fAdcDataValid : out STD_LOGIC; + fDacReadyForInput : out STD_LOGIC; + aDacSync : out STD_LOGIC; + aAdcSync : out STD_LOGIC); + end component; + + function to_Boolean (s : std_ulogic) return boolean is + begin + return (To_X01(s)='1'); + end to_Boolean; + + function to_StdLogic(b : boolean) return std_ulogic is + begin + if b then + return '1'; + else + return '0'; + end if; + end to_StdLogic; + + --vhook_sigstart + signal aAdcSync: STD_LOGIC; + signal aDacSync: STD_LOGIC; + signal bClockingRegPortOut: RegPortOut_t; + signal bDbRegPortOut: RegPortOut_t; + signal bFpgaClksStable: STD_LOGIC; + signal bJesdCoreRegPortInFlat: STD_LOGIC_VECTOR(49 downto 0); + signal bJesdCoreRegPortOutFlat: STD_LOGIC_VECTOR(33 downto 0); + signal bJesdRefClkPresent: STD_LOGIC; + signal bRadioClk1xEnabled: std_logic; + signal bRadioClk2xEnabled: std_logic; + signal bRadioClk3xEnabled: std_logic; + signal bRadioClkMmcmReset: std_logic; + signal bRadioClksValid: std_logic; + signal pPsDone: std_logic; + signal pPsEn: std_logic; + signal pPsInc: std_logic; + signal PsClk: std_logic; + signal sAdcDataFlatter: STD_LOGIC_VECTOR(63 downto 0); + signal SampleClk1xOutLcl: std_logic; + signal sDacDataFlatter: STD_LOGIC_VECTOR(63 downto 0); + signal sDacReadyForInputAsyncReset: STD_LOGIC; + signal sRegPps: std_logic; + signal sSysRefAsyncReset: STD_LOGIC; + signal sWrPps: std_logic; + --vhook_sigend + + signal bJesdRegPortInGrp, bSyncRegPortIn, bWrSyncRegPortIn, bRegPortIn : RegPortIn_t; + signal bJesdRegPortOut, bSyncRegPortOut, bWrSyncRegPortOut, bRegPortOut : RegPortOut_t; + + signal sDacReadyForInput_ms, sDacReadyForInputLcl, + sDacSync_ms, sDacSyncLcl, + sAdcSync_ms, sAdcSyncLcl, + sSysRef_ms, sSysRefLcl : std_logic := '0'; + + signal sAdcDataAry : AdcDataAry_t; + signal sDacDataAry : DacDataAry_t; + + signal sPpsSfpSel_ms, sPpsSfpSel : std_logic_vector(1 downto 0) := (others => '0'); + signal sUseWrTdcPps : boolean := false; + signal sPpsInt, sPpsMuxed : std_logic := '0'; + + attribute ASYNC_REG : string; + attribute ASYNC_REG of sDacReadyForInput_ms : signal is "true"; + attribute ASYNC_REG of sDacReadyForInputLcl : signal is "true"; + attribute ASYNC_REG of sDacSync_ms : signal is "true"; + attribute ASYNC_REG of sDacSyncLcl : signal is "true"; + attribute ASYNC_REG of sAdcSync_ms : signal is "true"; + attribute ASYNC_REG of sAdcSyncLcl : signal is "true"; + attribute ASYNC_REG of sSysRef_ms : signal is "true"; + attribute ASYNC_REG of sSysRefLcl : signal is "true"; + attribute ASYNC_REG of sPpsSfpSel_ms : signal is "true"; + attribute ASYNC_REG of sPpsSfpSel : signal is "true"; + +begin + + bRegPortOutFlat <= Flatten(bRegPortOut); + bRegPortIn <= Unflatten(bRegPortInFlat); + + + -- Combine return RegPorts. + bRegPortOut <= bJesdRegPortOut + + bClockingRegPortOut + + bSyncRegPortOut + bWrSyncRegPortOut + + bDbRegPortOut; + + + -- Clocking : ------------------------------------------------------------------------- + -- Automatically export the Sample Clocks and only use the incoming clocks in the + -- remainder of the logic. For a single module, the clocks must be looped back + -- in at a higher level! + -- ------------------------------------------------------------------------------------ + + --vhook_e RadioClocking + --vhook_a aReset false + --vhook_a bReset to_boolean(bBusReset) + --vhook_a RadioClk1x SampleClk1xOutLcl + --vhook_a RadioClk2x SampleClk2xOut + --vhook_a RadioClk3x open + RadioClockingx: entity work.RadioClocking (rtl) + port map ( + aReset => false, --in boolean + bReset => to_boolean(bBusReset), --in boolean + BusClk => BusClk, --in std_logic + bRadioClkMmcmReset => bRadioClkMmcmReset, --in std_logic + bRadioClksValid => bRadioClksValid, --out std_logic + bRadioClk1xEnabled => bRadioClk1xEnabled, --in std_logic + bRadioClk2xEnabled => bRadioClk2xEnabled, --in std_logic + bRadioClk3xEnabled => bRadioClk3xEnabled, --in std_logic + pPsInc => pPsInc, --in std_logic + pPsEn => pPsEn, --in std_logic + PsClk => PsClk, --in std_logic + pPsDone => pPsDone, --out std_logic + FpgaClk_n => FpgaClk_n, --in std_logic + FpgaClk_p => FpgaClk_p, --in std_logic + RadioClk1x => SampleClk1xOutLcl, --out std_logic + RadioClk2x => SampleClk2xOut, --out std_logic + RadioClk3x => open); --out std_logic + + -- We need an internal copy of SampleClk1x for the TDC, since we don't want to try + -- and align the other DB's clock accidentally. + SampleClk1xOut <= SampleClk1xOutLcl; + + --vhook_e ClockingRegs + --vhook_a aReset false + --vhook_a bReset to_boolean(bBusReset) + --vhook_a bRegPortOut bClockingRegPortOut + --vhook_a aRadioClksValid bRadioClksValid + ClockingRegsx: entity work.ClockingRegs (RTL) + port map ( + aReset => false, --in boolean + bReset => to_boolean(bBusReset), --in boolean + BusClk => BusClk, --in std_logic + bRegPortOut => bClockingRegPortOut, --out RegPortOut_t + bRegPortIn => bRegPortIn, --in RegPortIn_t + pPsInc => pPsInc, --out std_logic + pPsEn => pPsEn, --out std_logic + pPsDone => pPsDone, --in std_logic + PsClk => PsClk, --out std_logic + bRadioClkMmcmReset => bRadioClkMmcmReset, --out std_logic + aRadioClksValid => bRadioClksValid, --in std_logic + bRadioClk1xEnabled => bRadioClk1xEnabled, --out std_logic + bRadioClk2xEnabled => bRadioClk2xEnabled, --out std_logic + bRadioClk3xEnabled => bRadioClk3xEnabled, --out std_logic + bJesdRefClkPresent => bJesdRefClkPresent); --in std_logic + + + + -- JESD204B : ------------------------------------------------------------------------- + -- ------------------------------------------------------------------------------------ + + bJesdRegPortInGrp <= Mask(RegPortIn => bRegPortIn, + kRegisterOffset => kJesdRegGroupInDbRegs); -- 0x2000 to 0x3FFC + + -- Expand/compress the RegPort for moving through the netlist boundary. + bJesdRegPortOut <= Unflatten(bJesdCoreRegPortOutFlat); + bJesdCoreRegPortInFlat <= Flatten(bJesdRegPortInGrp); + + + --vhook Jesd204bXcvrCore + --vhook_a bRegPortInFlat bJesdCoreRegPortInFlat + --vhook_a bRegPortOutFlat bJesdCoreRegPortOutFlat + --vhook_a FpgaClk1x SampleClk1x + --vhook_a FpgaClk2x SampleClk2x + --vhook_a ReliableClk40 Clk40 + --vhook_a CaptureSysRefClk SampleClk1xOutLcl + --vhook_a cSysRefFpgaLvds_p sSysRefFpgaLvds_p + --vhook_a cSysRefFpgaLvds_n sSysRefFpgaLvds_n + --vhook_a fSysRef sSysRefAsyncReset + --vhook_a fDacReadyForInput sDacReadyForInputAsyncReset + --vhook_a {^f(.*)} s$1 + Jesd204bXcvrCorex: Jesd204bXcvrCore + port map ( + bBusReset => bBusReset, --in STD_LOGIC + BusClk => BusClk, --in STD_LOGIC + ReliableClk40 => Clk40, --in STD_LOGIC + FpgaClk1x => SampleClk1x, --in STD_LOGIC + FpgaClk2x => SampleClk2x, --in STD_LOGIC + bFpgaClksStable => bFpgaClksStable, --in STD_LOGIC + JesdRefClk_p => JesdRefClk_p, --in STD_LOGIC + JesdRefClk_n => JesdRefClk_n, --in STD_LOGIC + bJesdRefClkPresent => bJesdRefClkPresent, --out STD_LOGIC + aLmkSync => aLmkSync, --out STD_LOGIC + bRegPortInFlat => bJesdCoreRegPortInFlat, --in STD_LOGIC_VECTOR(49:0) + bRegPortOutFlat => bJesdCoreRegPortOutFlat, --out STD_LOGIC_VECTOR(33:0) + CaptureSysRefClk => SampleClk1xOutLcl, --in STD_LOGIC + cSysRefFpgaLvds_p => sSysRefFpgaLvds_p, --in STD_LOGIC + cSysRefFpgaLvds_n => sSysRefFpgaLvds_n, --in STD_LOGIC + fSysRef => sSysRefAsyncReset, --out STD_LOGIC + aAdcRx_p => aAdcRx_p, --in STD_LOGIC_VECTOR(3:0) + aAdcRx_n => aAdcRx_n, --in STD_LOGIC_VECTOR(3:0) + aSyncAdcOut_n => aSyncAdcOut_n, --out STD_LOGIC + aDacTx_p => aDacTx_p, --out STD_LOGIC_VECTOR(3:0) + aDacTx_n => aDacTx_n, --out STD_LOGIC_VECTOR(3:0) + aSyncDacIn_n => aSyncDacIn_n, --in STD_LOGIC + fAdcDataFlatter => sAdcDataFlatter, --out STD_LOGIC_VECTOR(63:0) + fDacDataFlatter => sDacDataFlatter, --in STD_LOGIC_VECTOR(63:0) + fAdcDataValid => sAdcDataValid, --out STD_LOGIC + fDacReadyForInput => sDacReadyForInputAsyncReset, --out STD_LOGIC + aDacSync => aDacSync, --out STD_LOGIC + aAdcSync => aAdcSync); --out STD_LOGIC + + + JesdDoubleSyncToNoResetSampleClk : process (SampleClk1x) + begin + if rising_edge(SampleClk1x) then + sDacReadyForInput_ms <= sDacReadyForInputAsyncReset; + sDacReadyForInputLcl <= sDacReadyForInput_ms; + -- No clock crossing here -- just reset, although the prefix declares otherwise... + sDacSync_ms <= aDacSync; + sDacSyncLcl <= sDacSync_ms; + sAdcSync_ms <= aAdcSync; + sAdcSyncLcl <= sAdcSync_ms; + sSysRef_ms <= sSysRefAsyncReset; + sSysRefLcl <= sSysRef_ms; + end if; + end process; + + -- Locals to outputs. + sDacReadyForInput <= sDacReadyForInputLcl; + sDacSync <= sDacSyncLcl; + sAdcSync <= sAdcSyncLcl; + sSysRef <= sSysRefLcl; + + -- Just combine the first two enables, since they're the ones that are used for JESD. + -- No reset crossing here, since bFpgaClksStable is only received by a no-reset domain + -- and the MGTs directly. + bFpgaClksStable <= bRadioClksValid and bRadioClk1xEnabled and bRadioClk2xEnabled; + + -- Compress/expand the flat data types from the netlist and route to top level. + sAdcDataAry <= Unflatten(sAdcDataFlatter); + sDacDataFlatter <= Flatten(sDacDataAry); + + -- Data mapping using the array types. + sAdcDataSample0I <= (sAdcDataAry(0).Data.I & sAdcDataAry(0).Over.I & sAdcDataAry(0).CBit1.I); + sAdcDataSample0Q <= (sAdcDataAry(0).Data.Q & sAdcDataAry(0).Over.Q & sAdcDataAry(0).CBit1.Q); + sAdcDataSample1I <= (sAdcDataAry(1).Data.I & sAdcDataAry(1).Over.I & sAdcDataAry(1).CBit1.I); + sAdcDataSample1Q <= (sAdcDataAry(1).Data.Q & sAdcDataAry(1).Over.Q & sAdcDataAry(1).CBit1.Q); + -- + sDacDataAry(0).Data.I <= sDacDataSample0I; + sDacDataAry(0).Data.Q <= sDacDataSample0Q; + sDacDataAry(1).Data.I <= sDacDataSample1I; + sDacDataAry(1).Data.Q <= sDacDataSample1Q; + + + -- Timing and Sync : ------------------------------------------------------------------ + -- ------------------------------------------------------------------------------------ + + bSyncRegPortIn <= Mask(RegPortIn => bRegPortIn, + kRegisterOffset => kTdc0OffsetsInEndpoint); -- 0x0200 + + --vhook_e TdcWrapper + --vhook_# Use the local copy of the SampleClock, since we want the TDC to measure the + --vhook_# clock offset for this daughterboard, not the global SampleClock. + --vhook_a SampleClk SampleClk1xOutLcl + --vhook_a sPpsPulse sRegPps + TdcWrapperx: entity work.TdcWrapper (struct) + port map ( + BusClk => BusClk, --in std_logic + bBusReset => bBusReset, --in std_logic + RefClk => RefClk, --in std_logic + SampleClk => SampleClk1xOutLcl, --in std_logic + MeasClk => MeasClk, --in std_logic + bSyncRegPortOut => bSyncRegPortOut, --out RegPortOut_t + bSyncRegPortIn => bSyncRegPortIn, --in RegPortIn_t + rPpsPulse => rPpsPulse, --in std_logic + sPpsPulse => sRegPps, --out std_logic + rRpTransfer => rRpTransfer, --out std_logic + sSpTransfer => sSpTransfer, --out std_logic + rGatedPulseToPin => rGatedPulseToPin, --inout std_logic + sGatedPulseToPin => sGatedPulseToPin); --inout std_logic + + WrTdcGen: if kInclWhiteRabbitTdc = '1' generate + bWrSyncRegPortIn <= Mask(RegPortIn => bRegPortIn, + kRegisterOffset => kTdc1OffsetsInEndpoint); -- 0x0400 + + --vhook_e TdcWrapper WrTdcWrapperx + --vhook_# Use the local copy of the SampleClock, since we want the TDC to measure the + --vhook_# clock offset for this daughterboard, not the global SampleClock. + --vhook_a bSyncRegPortIn bWrSyncRegPortIn + --vhook_a bSyncRegPortOut bWrSyncRegPortOut + --vhook_a SampleClk SampleClk1xOutLcl + --vhook_a RefClk WrRefClk + --vhook_a rPpsPulse rWrPpsPulse + --vhook_a sPpsPulse sWrPps + --vhook_a rRpTransfer rWrRpTransfer + --vhook_a sSpTransfer sWrSpTransfer + --vhook_a rGatedPulseToPin rWrGatedPulseToPin + --vhook_a sGatedPulseToPin sWrGatedPulseToPin + WrTdcWrapperx: entity work.TdcWrapper (struct) + port map ( + BusClk => BusClk, --in std_logic + bBusReset => bBusReset, --in std_logic + RefClk => WrRefClk, --in std_logic + SampleClk => SampleClk1xOutLcl, --in std_logic + MeasClk => MeasClk, --in std_logic + bSyncRegPortOut => bWrSyncRegPortOut, --out RegPortOut_t + bSyncRegPortIn => bWrSyncRegPortIn, --in RegPortIn_t + rPpsPulse => rWrPpsPulse, --in std_logic + sPpsPulse => sWrPps, --out std_logic + rRpTransfer => rWrRpTransfer, --out std_logic + sSpTransfer => sWrSpTransfer, --out std_logic + rGatedPulseToPin => rWrGatedPulseToPin, --inout std_logic + sGatedPulseToPin => sWrGatedPulseToPin); --inout std_logic + end generate WrTdcGen; + + WrTdcNotGen: if kInclWhiteRabbitTdc = '0' generate + bWrSyncRegPortOut <= kRegPortOutZero; + sWrPps <= '0'; + rWrRpTransfer <= '0'; + sWrSpTransfer <= '0'; + rWrGatedPulseToPin <= '0'; + sWrGatedPulseToPin <= '0'; + end generate WrTdcNotGen; + + -- Mux the output PPS based on the SFP selection bits. Encoding is one-hot, with zero + -- also a valid state. Regardless of whether the user selects SFP0 or SFP1 as the time + -- source, there is only one White Rabbit TDC, so '01' and '10' are equivalent. + -- '00': Use the PPS output from the "regular" TDC. + -- '01': Use the PPS output from the "white rabbit" TDC. + -- '10': Use the PPS output from the "white rabbit" TDC. + PpsOutputMux : process (SampleClk1xOutLcl) + begin + if rising_edge(SampleClk1xOutLcl) then + -- Double-sync the control bits to the Sample Clock domain. + sPpsSfpSel_ms <= aPpsSfpSel; + sPpsSfpSel <= sPpsSfpSel_ms; + + -- OR the control bits together to produce a single override enable for the WR TDC. + sUseWrTdcPps <= to_boolean(sPpsSfpSel(0) or sPpsSfpSel(1)); + + -- Flop the outputs. One flop for the PPS output IOB, the other for use internally. + sPpsInt <= sPpsMuxed; + end if; + end process PpsOutputMux; + + sPpsMuxed <= sWrPps when sUseWrTdcPps else sRegPps; + sPps <= sPpsInt; + sPpsToIob <= sPpsMuxed; -- No added flop here since there's an IOB outside this module. + + + -- Daughterboard Control : ------------------------------------------------------------ + -- ------------------------------------------------------------------------------------ + + --vhook_e DaughterboardRegs + --vhook_# Tying this low is safe because the sync reset is used inside DaughterboardRegs. + --vhook_a aReset false + --vhook_a bReset to_boolean(bBusReset) + --vhook_a bRegPortOut bDbRegPortOut + --vhook_a kDbId std_logic_vector(to_unsigned(kDbId,kDbIdSize)) + DaughterboardRegsx: entity work.DaughterboardRegs (RTL) + port map ( + aReset => false, --in boolean + bReset => to_boolean(bBusReset), --in boolean + BusClk => BusClk, --in std_logic + bRegPortOut => bDbRegPortOut, --out RegPortOut_t + bRegPortIn => bRegPortIn, --in RegPortIn_t + kDbId => std_logic_vector(to_unsigned(kDbId,kDbIdSize)), --in std_logic_vector(15:0) + kSlotId => kSlotId); --in std_logic + + + + +end RTL; diff --git a/fpga/usrp3/top/n3xx/dboards/rh/db_ifc/Jesd204bXcvrCore.edf b/fpga/usrp3/top/n3xx/dboards/rh/db_ifc/Jesd204bXcvrCore.edf Binary files differnew file mode 100644 index 000000000..c9df3749b --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/rh/db_ifc/Jesd204bXcvrCore.edf diff --git a/fpga/usrp3/top/n3xx/dboards/rh/db_ifc/Jesd204bXcvrCore_stub.vhd b/fpga/usrp3/top/n3xx/dboards/rh/db_ifc/Jesd204bXcvrCore_stub.vhd new file mode 100644 index 000000000..bf75e9d0d --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/rh/db_ifc/Jesd204bXcvrCore_stub.vhd @@ -0,0 +1,54 @@ +-- Copyright 1986-2017 Xilinx, Inc. All Rights Reserved. +-- -------------------------------------------------------------------------------- +-- Tool Version: Vivado v.2017.4 (win64) Build 2086221 Fri Dec 15 20:55:39 MST 2017 +-- Date : Fri Nov 9 16:19:51 2018 +-- Host : hjimenez running 64-bit major release (build 9200) +-- Command : write_vhdl -mode synth_stub -force -file ./Jesd204bXcvrCore_stub.vhd +-- Design : Jesd204bXcvrCore +-- Purpose : Stub declaration of top-level module interface +-- Device : xc7z100ffg900-2 +-- -------------------------------------------------------------------------------- +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; + +entity Jesd204bXcvrCore is + Port ( + bBusReset : in STD_LOGIC; + BusClk : in STD_LOGIC; + ReliableClk40 : in STD_LOGIC; + FpgaClk1x : in STD_LOGIC; + FpgaClk2x : in STD_LOGIC; + bFpgaClksStable : in STD_LOGIC; + JesdRefClk_p : in STD_LOGIC; + JesdRefClk_n : in STD_LOGIC; + bJesdRefClkPresent : out STD_LOGIC; + aLmkSync : out STD_LOGIC; + bRegPortInFlat : in STD_LOGIC_VECTOR ( 49 downto 0 ); + bRegPortOutFlat : out STD_LOGIC_VECTOR ( 33 downto 0 ); + CaptureSysRefClk : in STD_LOGIC; + cSysRefFpgaLvds_p : in STD_LOGIC; + cSysRefFpgaLvds_n : in STD_LOGIC; + fSysRef : out STD_LOGIC; + aAdcRx_p : in STD_LOGIC_VECTOR ( 3 downto 0 ); + aAdcRx_n : in STD_LOGIC_VECTOR ( 3 downto 0 ); + aSyncAdcOut_n : out STD_LOGIC; + aDacTx_p : out STD_LOGIC_VECTOR ( 3 downto 0 ); + aDacTx_n : out STD_LOGIC_VECTOR ( 3 downto 0 ); + aSyncDacIn_n : in STD_LOGIC; + fAdcDataFlatter : out STD_LOGIC_VECTOR ( 63 downto 0 ); + fDacDataFlatter : in STD_LOGIC_VECTOR ( 63 downto 0 ); + fAdcDataValid : out STD_LOGIC; + fDacReadyForInput : out STD_LOGIC; + aDacSync : out STD_LOGIC; + aAdcSync : out STD_LOGIC + ); + +end Jesd204bXcvrCore; + +architecture stub of Jesd204bXcvrCore is +attribute syn_black_box : boolean; +attribute black_box_pad_pin : string; +attribute syn_black_box of stub : architecture is true; +attribute black_box_pad_pin of stub : architecture is "bBusReset,BusClk,ReliableClk40,FpgaClk1x,FpgaClk2x,bFpgaClksStable,JesdRefClk_p,JesdRefClk_n,bJesdRefClkPresent,aLmkSync,bRegPortInFlat[49:0],bRegPortOutFlat[33:0],CaptureSysRefClk,cSysRefFpgaLvds_p,cSysRefFpgaLvds_n,fSysRef,aAdcRx_p[3:0],aAdcRx_n[3:0],aSyncAdcOut_n,aDacTx_p[3:0],aDacTx_n[3:0],aSyncDacIn_n,fAdcDataFlatter[63:0],fDacDataFlatter[63:0],fAdcDataValid,fDacReadyForInput,aDacSync,aAdcSync"; +begin +end; diff --git a/fpga/usrp3/top/n3xx/dboards/rh/db_ifc/PkgAdcDacInterfaceTypes.vhd b/fpga/usrp3/top/n3xx/dboards/rh/db_ifc/PkgAdcDacInterfaceTypes.vhd new file mode 100644 index 000000000..8512d133a --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/rh/db_ifc/PkgAdcDacInterfaceTypes.vhd @@ -0,0 +1,302 @@ +------------------------------------------------------------------------------- +-- +-- File: PkgAdcDacInterfaceTypes.vhd +-- Author: National Instruments +-- Original Project: USRP N32x +-- Date: 15 Dec 2017 +-- +------------------------------------------------------------------------------- +-- (c) 2018 Copyright National Instruments Corporation +-- All Rights Reserved +-- National Instruments Internal Information +------------------------------------------------------------------------------- +-- +-- Purpose: Contains types for ADC and DAC data so they can more easily be +-- passed through the design. +-- +-- vreview_group JesdCoreN32x +-- vreview_reviewers djepson wfife +------------------------------------------------------------------------------- + +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +library work; + use work.PkgJesdConfig.all; + + +package PkgAdcDacInterfaceTypes is + + -- Data type for the DACs. + type DacData_t is record + I : std_logic_vector(kDacDataWidth - 1 downto 0); + Q : std_logic_vector(kDacDataWidth - 1 downto 0); + end record; + + -- Data type for the ADCs. + type AdcData_t is record + I : std_logic_vector(kAdcDataWidth - 1 downto 0); + Q : std_logic_vector(kAdcDataWidth - 1 downto 0); + end record; + + -- Type has two bits that correspond to I and Q; example usage: overrange flags. + type IQFlags_t is record + I : std_logic; + Q : std_logic; + end record; + + -- Single data type for all information from the ADCs. + type AdcSamples_t is record + Data : AdcData_t; + Over : IQFlags_t; + CBit1 : IQFlags_t; + end record; + + -- Single data type for all information to the DACs. + type DacSamples_t is record + Data : DacData_t; + end record; + + -- To support multiple data values per clock cycle, these types + -- are arrays of the ADC and DAC data types where the size of the array + -- corresponds to the number of samples per cycle. + type AdcDataAry_t is array (kSamplesPerCycle - 1 downto 0) of AdcSamples_t; + type DacDataAry_t is array (kSamplesPerCycle - 1 downto 0) of DacSamples_t; + + -- Zero/default constant + constant kAdcDataAryZero : AdcDataAry_t := + (others => (Data => (others => (others => '0')), + Over => (others => '0'), + CBit1 => (others => '0')) + ); + + -- Zero/default constant + constant kDacDataAryZero : DacDataAry_t := + (others => (Data => (others => (others => '0'))) + ); + + -- Flattened type that converts the ADC data into std_logic_vector types. This type is + -- not suitable for use in the port maps of components that are presynthesized (into EDF + -- or NGC files) but is useful for passing data to the top level. + type AdcDataAryFlat_t is record + DataI : std_logic_vector(kSamplesPerCycle*kAdcDataWidth - 1 downto 0); + DataQ : std_logic_vector(kSamplesPerCycle*kAdcDataWidth - 1 downto 0); + OverI : std_logic_vector(kSamplesPerCycle - 1 downto 0); + OverQ : std_logic_vector(kSamplesPerCycle - 1 downto 0); + CBit1I : std_logic_vector(kSamplesPerCycle - 1 downto 0); + CBit1Q : std_logic_vector(kSamplesPerCycle - 1 downto 0); + end record; + + -- Fully flattened ADC data for passing into and out of presynthesized components. + subtype AdcDataAryFlatter_t is std_logic_vector(2*(kSamplesPerCycle*(kAdcDataWidth + 2)) - 1 downto 0); + + -- Flattened type that converts the DAC data into std_logic_vector types. This type is + -- not suitable for use in the port maps of components that are presynthesized (into EDF + -- or NGC files) but is useful for passing data from the top level. + type DacDataAryFlat_t is record + DataI : std_logic_vector(kSamplesPerCycle*kDacDataWidth - 1 downto 0); + DataQ : std_logic_vector(kSamplesPerCycle*kDacDataWidth - 1 downto 0); + end record; + + -- Fully flattened DAC data for passing into and out of presynthesized components. + subtype DacDataAryFlatter_t is std_logic_vector(2*(kSamplesPerCycle*kDacDataWidth) - 1 downto 0); + + -- Function to convert types defined above for the ADC data + function Flatten (AdcData : AdcDataAry_t) return AdcDataAryFlat_t; + function Flatten (AdcData : AdcDataAryFlat_t) return AdcDataAryFlatter_t; + function Flatten (AdcData : AdcDataAry_t) return AdcDataAryFlatter_t; + function Unflatten(AdcData : AdcDataAryFlatter_t) return AdcDataAryFlat_t; + function Unflatten(AdcData : AdcDataAryFlat_t) return AdcDataAry_t; + function Unflatten(AdcData : AdcDataAryFlatter_t) return AdcDataAry_t; + + + -- Function to convert types defined above for the DAC data + function Flatten (DacData : DacDataAry_t) return DacDataAryFlat_t; + function Flatten (DacData : DacDataAryFlat_t) return DacDataAryFlatter_t; + function Flatten (DacData : DacDataAry_t) return DacDataAryFlatter_t; + function Unflatten(DacData : DacDataAryFlatter_t) return DacDataAryFlat_t; + function UnFlatten(DacData : DacDataAryFlat_t) return DacDataAry_t; + function Unflatten(DacData : DacDataAryFlatter_t) return DacDataAry_t; + + +end package PkgAdcDacInterfaceTypes; + + +package body PkgAdcDacInterfaceTypes is + + -- Flattens AdcDataAry_t to AdcDataAryFlat_t + function Flatten(AdcData : AdcDataAry_t) return AdcDataAryFlat_t + is + variable ReturnVar : AdcDataAryFlat_t; + begin + ReturnVar := (DataI => (others => '0'), -- Note (others => (others => '0')) does not work here + DataQ => (others => '0'), -- since DataX and OverX/CBit1X are of different lengths (ModelSim error) + OverI => (others => '0'), + OverQ => (others => '0'), + CBit1I => (others => '0'), + CBit1Q => (others => '0')); + + -- The upstream logic puts the 0th element of an array in the MSBs of its data word + for i in 0 to kSamplesPerCycle - 1 loop + ReturnVar.DataI((kSamplesPerCycle - i)*kAdcDataWidth - 1 downto (kSamplesPerCycle - 1 - i)*kAdcDataWidth) := AdcData(i).Data.I; -- Input Data 0 to MSB + ReturnVar.DataQ((kSamplesPerCycle - i)*kAdcDataWidth - 1 downto (kSamplesPerCycle - 1 - i)*kAdcDataWidth) := AdcData(i).Data.Q; + ReturnVar.OverI (kSamplesPerCycle - 1 - i) := AdcData(i).Over.I; -- Input Data 0 to MSB + ReturnVar.OverQ (kSamplesPerCycle - 1 - i) := AdcData(i).Over.Q; + ReturnVar.CBit1I(kSamplesPerCycle - 1 - i) := AdcData(i).CBit1.I; + ReturnVar.CBit1Q(kSamplesPerCycle - 1 - i) := AdcData(i).CBit1.Q; + end loop; + + return ReturnVar; + end function Flatten; + + + -- UnFlattens AdcDataAryFlat_t to AdcDataAry_t + function Unflatten(AdcData : AdcDataAryFlat_t) return AdcDataAry_t + is + variable ReturnVar : AdcDataAry_t; + begin + ReturnVar := (others => (Data => (others => (others => '0')), Over => (others => '0'), CBit1 => (others => '0'))); + for i in 0 to kSamplesPerCycle - 1 loop + -- MSB of flattened word = 0th element of ADC data array - this corresponds to how TheWindow + -- expects data arrays to be transferred. + ReturnVar(kSamplesPerCycle - 1 - i).Data.I := AdcData.DataI((i+1)*kAdcDataWidth - 1 downto i*kAdcDataWidth); + ReturnVar(kSamplesPerCycle - 1 - i).Data.Q := AdcData.DataQ((i+1)*kAdcDataWidth - 1 downto i*kAdcDataWidth); + ReturnVar(kSamplesPerCycle - 1 - i).Over.I := AdcData.OverI(i); + ReturnVar(kSamplesPerCycle - 1 - i).Over.Q := AdcData.OverQ(i); + ReturnVar(kSamplesPerCycle - 1 - i).CBit1.I := AdcData.CBit1I(i); + ReturnVar(kSamplesPerCycle - 1 - i).CBit1.Q := AdcData.CBit1Q(i); + end loop; + return ReturnVar; + end function Unflatten; + + + + + -- Flattens AdcDataAryFlat_t to AdcDataAryFlatter_t + function Flatten(AdcData : AdcDataAryFlat_t) return AdcDataAryFlatter_t + is + variable ReturnVar : AdcDataAryFlatter_t; + begin + ReturnVar := AdcData.OverQ & AdcData.CBit1Q & AdcData.OverI & AdcData.CBit1I & AdcData.DataQ & AdcData.DataI; + return ReturnVar; + end function Flatten; + + -- UnFlattens AdcDataAryFlatter_t to AdcDataAryFlat_t + function Unflatten(AdcData : AdcDataAryFlatter_t) return AdcDataAryFlat_t + is + variable ReturnVar : AdcDataAryFlat_t; + begin + ReturnVar.DataI := AdcData(1*kSamplesPerCycle*kAdcDataWidth + 0*kSamplesPerCycle - 1 downto 0*kSamplesPerCycle*kAdcDataWidth + 0*kSamplesPerCycle); + ReturnVar.DataQ := AdcData(2*kSamplesPerCycle*kAdcDataWidth + 0*kSamplesPerCycle - 1 downto 1*kSamplesPerCycle*kAdcDataWidth + 0*kSamplesPerCycle); + ReturnVar.CBit1I := AdcData(2*kSamplesPerCycle*kAdcDataWidth + 1*kSamplesPerCycle - 1 downto 2*kSamplesPerCycle*kAdcDataWidth + 0*kSamplesPerCycle); + ReturnVar.OverI := AdcData(2*kSamplesPerCycle*kAdcDataWidth + 2*kSamplesPerCycle - 1 downto 2*kSamplesPerCycle*kAdcDataWidth + 1*kSamplesPerCycle); + ReturnVar.CBit1Q := AdcData(2*kSamplesPerCycle*kAdcDataWidth + 3*kSamplesPerCycle - 1 downto 2*kSamplesPerCycle*kAdcDataWidth + 2*kSamplesPerCycle); + ReturnVar.OverQ := AdcData(2*kSamplesPerCycle*kAdcDataWidth + 4*kSamplesPerCycle - 1 downto 2*kSamplesPerCycle*kAdcDataWidth + 3*kSamplesPerCycle); + return ReturnVar; + end function Unflatten; + + + -- Flattens AdcDataAry_t to AdcDataAryFlatter_t + function Flatten(AdcData : AdcDataAry_t) return AdcDataAryFlatter_t + is + variable TempVar : AdcDataAryFlat_t; + variable ReturnVar : AdcDataAryFlatter_t; + begin + TempVar := Flatten(AdcData); + ReturnVar := Flatten(TempVar); + return ReturnVar; + end function Flatten; + + -- UnFlattens AdcDataAryFlatter_t to AdcDataAry_t + function Unflatten(AdcData : AdcDataAryFlatter_t) return AdcDataAry_t + is + variable TempVar : AdcDataAryFlat_t; + variable ReturnVar : AdcDataAry_t; + begin + TempVar := Unflatten(AdcData); + ReturnVar := Unflatten(TempVar); + return ReturnVar; + end function Unflatten; + + + + -- Flattens DacDataAry_t to DacDataAryFlat_t + function Flatten(DacData : DacDataAry_t) return DacDataAryFlat_t + is + variable ReturnVar : DacDataAryFlat_t; + begin + ReturnVar := (others => (others => '0')); + for i in 0 to kSamplesPerCycle - 1 loop + -- MSB of flattened word = 0th element of ADC data array - this corresponds to how TheWindow + -- expects data arrays to be transferred. + ReturnVar.DataI((i+1)*kDacDataWidth - 1 downto i*kDacDataWidth) := DacData(kSamplesPerCycle - 1 - i).Data.I; + ReturnVar.DataQ((i+1)*kDacDataWidth - 1 downto i*kDacDataWidth) := DacData(kSamplesPerCycle - 1 - i).Data.Q; + end loop; + return ReturnVar; + end function Flatten; + + + -- UnFlattens DacDataAryFlat_t to DacDataAry_t + function UnFlatten(DacData : DacDataAryFlat_t) return DacDataAry_t + is + variable ReturnVar : DacDataAry_t; + begin + ReturnVar := (others => (Data => (others => (others => '0')))); + + -- The upstream logic puts the 0th element of an array in the MSBs of its data word + for i in 0 to kSamplesPerCycle - 1 loop + ReturnVar(kSamplesPerCycle - 1 - i).Data.I := DacData.DataI(kDacDataWidth*(i+1) - 1 downto kDacDataWidth*i); + ReturnVar(kSamplesPerCycle - 1 - i).Data.Q := DacData.DataQ(kDacDataWidth*(i+1) - 1 downto kDacDataWidth*i); + end loop; + + return ReturnVar; + end function UnFlatten; + + + + -- Flattens DacDataAryFlat_t to DacDataAryFlatter_t + function Flatten(DacData : DacDataAryFlat_t) return DacDataAryFlatter_t + is + variable ReturnVar : DacDataAryFlatter_t; + begin + ReturnVar := DacData.DataQ & DacData.DataI; + return ReturnVar; + end function Flatten; + + + -- UnFlattens DacDataAryFlatter_t to DacDataAryFlat_t + function Unflatten(DacData : DacDataAryFlatter_t) return DacDataAryFlat_t + is + variable ReturnVar : DacDataAryFlat_t; + begin + ReturnVar.DataI := DacData(1*kSamplesPerCycle*kDacDataWidth - 1 downto 0*kSamplesPerCycle*kDacDataWidth); + ReturnVar.DataQ := DacData(2*kSamplesPerCycle*kDacDataWidth - 1 downto 1*kSamplesPerCycle*kDacDataWidth); + return ReturnVar; + end function Unflatten; + + + -- Flattens DacDataAry_t to DacDataAryFlatter_t + function Flatten(DacData : DacDataAry_t) return DacDataAryFlatter_t + is + variable TempVar : DacDataAryFlat_t; + variable ReturnVar : DacDataAryFlatter_t; + begin + TempVar := Flatten(DacData); + ReturnVar := Flatten(TempVar); + return ReturnVar; + end function Flatten; + + -- UnFlattens DacDataAryFlatter_t to DacDataAry_t + function Unflatten(DacData : DacDataAryFlatter_t) return DacDataAry_t + is + variable TempVar : DacDataAryFlat_t; + variable ReturnVar : DacDataAry_t; + begin + TempVar := Unflatten(DacData); + ReturnVar := Unflatten(TempVar); + return ReturnVar; + end function Unflatten; + + +end package body; diff --git a/fpga/usrp3/top/n3xx/dboards/rh/db_ifc/PkgClockingRegMap.vhd b/fpga/usrp3/top/n3xx/dboards/rh/db_ifc/PkgClockingRegMap.vhd new file mode 100644 index 000000000..03b95c100 --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/rh/db_ifc/PkgClockingRegMap.vhd @@ -0,0 +1,107 @@ +------------------------------------------------------------------------------- +-- +-- File: PkgClockingRegMap.vhd +-- Author: Autogenerated by XmlParse +-- Original Project: -- +-- Date: -- +-- +------------------------------------------------------------------------------- +-- Copyright 2017 Ettus Research, A National Instruments Company +-- SPDX-License-Identifier: LGPL-3.0 +------------------------------------------------------------------------------- +-- +-- Purpose: +-- The constants in this file are autogenerated by XmlParse and should +-- be used by testbench code to access specific register fields. +-- +------------------------------------------------------------------------------- + +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +package PkgClockingRegMap is + +--=============================================================================== +-- A numerically ordered list of registers and their VHDL source files +--=============================================================================== + + -- RadioClkMmcm : 0x20 (ClockingRegs.vhd) + -- PhaseShiftControl : 0x24 (ClockingRegs.vhd) + -- RadioClkEnables : 0x28 (ClockingRegs.vhd) + -- MgtRefClkStatus : 0x30 (ClockingRegs.vhd) + +--=============================================================================== +-- RegTypes +--=============================================================================== + +--=============================================================================== +-- Register Group ClockingRegs +--=============================================================================== + + -- RadioClkMmcm Register (from ClockingRegs.vhd) + constant kRadioClkMmcm : integer := 16#20#; -- Register Offset + constant kRadioClkMmcmSize: integer := 32; -- register width in bits + constant kRadioClkMmcmMask : std_logic_vector(31 downto 0) := X"00000013"; + constant kRadioClkMmcmResetSetSize : integer := 1; --RadioClkMmcm:RadioClkMmcmResetSet + constant kRadioClkMmcmResetSetMsb : integer := 0; --RadioClkMmcm:RadioClkMmcmResetSet + constant kRadioClkMmcmResetSet : integer := 0; --RadioClkMmcm:RadioClkMmcmResetSet + constant kRadioClkMmcmResetClearSize : integer := 1; --RadioClkMmcm:RadioClkMmcmResetClear + constant kRadioClkMmcmResetClearMsb : integer := 1; --RadioClkMmcm:RadioClkMmcmResetClear + constant kRadioClkMmcmResetClear : integer := 1; --RadioClkMmcm:RadioClkMmcmResetClear + constant kRadioClkMmcmLockedSize : integer := 1; --RadioClkMmcm:RadioClkMmcmLocked + constant kRadioClkMmcmLockedMsb : integer := 4; --RadioClkMmcm:RadioClkMmcmLocked + constant kRadioClkMmcmLocked : integer := 4; --RadioClkMmcm:RadioClkMmcmLocked + + -- PhaseShiftControl Register (from ClockingRegs.vhd) + constant kPhaseShiftControl : integer := 16#24#; -- Register Offset + constant kPhaseShiftControlSize: integer := 32; -- register width in bits + constant kPhaseShiftControlMask : std_logic_vector(31 downto 0) := X"10010011"; + constant kPsIncSize : integer := 1; --PhaseShiftControl:PsInc + constant kPsIncMsb : integer := 0; --PhaseShiftControl:PsInc + constant kPsInc : integer := 0; --PhaseShiftControl:PsInc + constant kPsDecSize : integer := 1; --PhaseShiftControl:PsDec + constant kPsDecMsb : integer := 4; --PhaseShiftControl:PsDec + constant kPsDec : integer := 4; --PhaseShiftControl:PsDec + constant kPsEnabledForFdbClkSize : integer := 1; --PhaseShiftControl:PsEnabledForFdbClk + constant kPsEnabledForFdbClkMsb : integer := 16; --PhaseShiftControl:PsEnabledForFdbClk + constant kPsEnabledForFdbClk : integer := 16; --PhaseShiftControl:PsEnabledForFdbClk + constant kPsDoneSize : integer := 1; --PhaseShiftControl:PsDone + constant kPsDoneMsb : integer := 28; --PhaseShiftControl:PsDone + constant kPsDone : integer := 28; --PhaseShiftControl:PsDone + + -- RadioClkEnables Register (from ClockingRegs.vhd) + constant kRadioClkEnables : integer := 16#28#; -- Register Offset + constant kRadioClkEnablesSize: integer := 32; -- register width in bits + constant kRadioClkEnablesMask : std_logic_vector(31 downto 0) := X"00000111"; + constant kRadioClk1xEnabledSize : integer := 1; --RadioClkEnables:RadioClk1xEnabled + constant kRadioClk1xEnabledMsb : integer := 0; --RadioClkEnables:RadioClk1xEnabled + constant kRadioClk1xEnabled : integer := 0; --RadioClkEnables:RadioClk1xEnabled + constant kRadioClk2xEnabledSize : integer := 1; --RadioClkEnables:RadioClk2xEnabled + constant kRadioClk2xEnabledMsb : integer := 4; --RadioClkEnables:RadioClk2xEnabled + constant kRadioClk2xEnabled : integer := 4; --RadioClkEnables:RadioClk2xEnabled + constant kRadioClk3xEnabledSize : integer := 1; --RadioClkEnables:RadioClk3xEnabled + constant kRadioClk3xEnabledMsb : integer := 8; --RadioClkEnables:RadioClk3xEnabled + constant kRadioClk3xEnabled : integer := 8; --RadioClkEnables:RadioClk3xEnabled + + -- MgtRefClkStatus Register (from ClockingRegs.vhd) + constant kMgtRefClkStatus : integer := 16#30#; -- Register Offset + constant kMgtRefClkStatusSize: integer := 32; -- register width in bits + constant kMgtRefClkStatusMask : std_logic_vector(31 downto 0) := X"00000001"; + constant kJesdRefClkPresentSize : integer := 1; --MgtRefClkStatus:JesdRefClkPresent + constant kJesdRefClkPresentMsb : integer := 0; --MgtRefClkStatus:JesdRefClkPresent + constant kJesdRefClkPresent : integer := 0; --MgtRefClkStatus:JesdRefClkPresent + +end package; + +package body PkgClockingRegMap is + + -- function kRadioClkMmcmRec not implemented because PkgXReg in this project does not support XReg2_t. + + -- function kPhaseShiftControlRec not implemented because PkgXReg in this project does not support XReg2_t. + + -- function kRadioClkEnablesRec not implemented because PkgXReg in this project does not support XReg2_t. + + -- function kMgtRefClkStatusRec not implemented because PkgXReg in this project does not support XReg2_t. + +end package body; diff --git a/fpga/usrp3/top/n3xx/dboards/rh/db_ifc/PkgDaughterboardRegMap.vhd b/fpga/usrp3/top/n3xx/dboards/rh/db_ifc/PkgDaughterboardRegMap.vhd new file mode 100644 index 000000000..06708cde3 --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/rh/db_ifc/PkgDaughterboardRegMap.vhd @@ -0,0 +1,56 @@ +------------------------------------------------------------------------------- +-- +-- File: PkgDaughterboardRegMap.vhd +-- Author: Autogenerated by XmlParse +-- Original Project: -- +-- Date: -- +-- +------------------------------------------------------------------------------- +-- Copyright 2017 Ettus Research, A National Instruments Company +-- SPDX-License-Identifier: LGPL-3.0 +------------------------------------------------------------------------------- +-- +-- Purpose: +-- The constants in this file are autogenerated by XmlParse and should +-- be used by testbench code to access specific register fields. +-- +------------------------------------------------------------------------------- + +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +package PkgDaughterboardRegMap is + +--=============================================================================== +-- A numerically ordered list of registers and their VHDL source files +--=============================================================================== + + -- DaughterboardId : 0x630 (DaughterboardRegs.vhd) + +--=============================================================================== +-- RegTypes +--=============================================================================== + +--=============================================================================== +-- Register Group StaticControl +--=============================================================================== + + -- DaughterboardId Register (from DaughterboardRegs.vhd) + constant kDaughterboardId : integer := 16#630#; -- Register Offset + constant kDaughterboardIdSize: integer := 32; -- register width in bits + constant kDaughterboardIdMask : std_logic_vector(31 downto 0) := X"0001ffff"; + constant kDbIdValSize : integer := 16; --DaughterboardId:DbIdVal + constant kDbIdValMsb : integer := 15; --DaughterboardId:DbIdVal + constant kDbIdVal : integer := 0; --DaughterboardId:DbIdVal + constant kSlotIdValSize : integer := 1; --DaughterboardId:SlotIdVal + constant kSlotIdValMsb : integer := 16; --DaughterboardId:SlotIdVal + constant kSlotIdVal : integer := 16; --DaughterboardId:SlotIdVal + +end package; + +package body PkgDaughterboardRegMap is + + -- function kDaughterboardIdRec not implemented because PkgXReg in this project does not support XReg2_t. + +end package body; diff --git a/fpga/usrp3/top/n3xx/dboards/rh/db_ifc/PkgJesdConfig.vhd b/fpga/usrp3/top/n3xx/dboards/rh/db_ifc/PkgJesdConfig.vhd new file mode 100644 index 000000000..4913b03fc --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/rh/db_ifc/PkgJesdConfig.vhd @@ -0,0 +1,165 @@ +------------------------------------------------------------------------------- +-- +-- File: PkgJesdConfig.vhd +-- Author: National Instruments +-- Original Project: N32x +-- Date: 15 Dec 2017 +-- +------------------------------------------------------------------------------- +-- Copyright 2016-2018 Ettus Research, A National Instruments Company +-- SPDX-License-Identifier: LGPL-3.0 +------------------------------------------------------------------------------- +-- +-- Purpose: JESD204B setup constants and functions. These constants are shared +-- between RX and TX JESD cores. +-- +-- vreview_group JesdCoreN32x +-- vreview_reviewers djepson wfife +------------------------------------------------------------------------------- + +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +library work; + use work.PkgRegs.all; + + +package PkgJesdConfig is + + -- "JESD" in ASCII - with the core number 0 or 1 on the LSb. + constant kJesdSignature : std_logic_vector(31 downto 0) := x"4a455344"; + + -- Register endpoints + constant kJesdDrpRegsInEndpoint : RegOffset_t := (kOffset => 16#0800#, -- 0x2800 to + kWidth => 16#0800#); -- 0x2FFF + + -- Selects the UsrClk2 for the transceivers. For 64-bit wide transceivers, the + -- UsrClk = 2*UserClk2 frequency. For 32-bit wide transceivers, UsrClk = UserClk2 + -- frequency. This is a generalization, the clock ratio should be confirmed based on + -- the transceiver configuration. + -- The N310 transceivers use the single rate reference, hence = false. + constant kDoubleRateUsrClk : boolean := false; + + -- For the N32x, all lanes are in one quad and we use the QPLL. + constant kJesdUseQpll : boolean := true; + + constant kAdcDataWidth : integer := 14; -- ADC data width in bits + constant kDacDataWidth : integer := 16; -- DAC data width in bits + constant kSamplesPerCycle : integer := 2; -- Number of samples per SampleClk1x + + constant kGtxDrpAddrWidth : natural := 9; + constant kGtxAddrLsbPosition : natural := 2; + constant kQpllDrpAddrWidth : natural := 8; + constant kGtxDrpDataWidth : natural := 16; + + -- Max supported number of lanes + constant kMaxNumLanes : natural := 4; + -- Max supported number of quads (normally there is 1 quad per 4 lanes but disconnect + -- the definitions to allow quad sharing) + constant kMaxNumQuads : natural := 1; + + -- Rhodium: + -- JESD shared setup - LMFS = 4211, HD = 1 (Samples are split across multiple lanes). + constant kNumLanes : natural := 4; -- L + constant kNumConvs : positive := 2; -- M + constant kOctetsPerFrame : natural := 1; -- F + constant kDacJesdSamplesPerCycle : integer := 1; -- S + constant kOctetsPerLane : natural := 2; -- MGT data is kOctetsPerLane*8 = 16 bits wide + constant kNumQuads : natural := kNumLanes / 4; -- 4 lanes per quad + constant kHighDensity : boolean := true; -- HD + constant kConvResBits : positive := kDacDataWidth; -- Converter resolution in bits + constant kConvSampleBits : positive := 16; -- Sample Length in bits + constant kInitLaneAlignCnt : positive := 4; + constant kFramesPerMulti : natural := 24; -- K + + -- Rhodium: + -- The converters are running at 400/491.52/500 MSPS (DeviceClk), and the sampling + -- clock at the FPGA (UserClk) is 200/245.76/250 MHz; so UsrClk = (DeviceClk / 2). + -- The frame rate = DeviceClk, and the Multiframe rate = (frame rate / kFramesPerMulti) + -- Thus, kUserClksPerMulti = (UsrClk / Multiframe rate) + -- = (UsrClk / (DeviceClk / kFramesPerMulti)) + -- since UsrClk = DeviceClk / 2 then, + -- kUserClksPerMulti = ((DeviceClk / 2) / (DeviceClk / kFramesPerMulti)) + -- therefore, + -- kUserClksPerMulti = kFramesPerMulti / 2 + constant kUserClksPerMulti : integer := kFramesPerMulti / 2; + + + type NaturalVector is array ( natural range <>) of natural; + + -- The PCB connections are are passed trough, any swapping is handled somewhere else. + -- + -- Transceiver MGT Channel ADC Lane DAC Lane + -- *********** *********** ******** ******** + -- GT0: X0Y8 0 0 0 + -- GT1: X0Y9 1 1 1 + -- GT2: X0Y10 2 2 2 + -- GT3: X0Y11 3 3 3 + constant kRxLaneIndices : NaturalVector(kNumLanes - 1 downto 0) := + ( + -- MGT => ADC (in above table) + 0 => 0, + 1 => 1, + 2 => 2, + 3 => 3 + ); + + constant kTxLaneIndices : NaturalVector(kNumLanes - 1 downto 0) := + ( + -- MGT => DAC lane + 0 => 0, + 1 => 1, + 2 => 2, + 3 => 3 + ); + + constant kLaneToQuadMap : NaturalVector(kNumLanes - 1 downto 0) := + ( + -- All lanes are in one quad + 0 => 0, + 1 => 0, + 2 => 0, + 3 => 0 + ); + + + -- The master transceiver channel for channel bonding. E(kMasterBondingChannel) + -- must have the highest value decrementing to b"000" for that last channels to bond. + constant kMasterBondingChannel : integer := 1; + + -- Channel bonding occurs when a master detects a K-char sequence and aligns its + -- internal FIFO to the start of this sequence. A signal is then generated to other + -- slave transceivers that cause them to bond to the sequence - this bonding signal is + -- cascaded from master to slave to slave to slave, etc where each slave must know how + -- many levels to the master there are. The last slave to bond must be at level b"000" + -- and the master is at the highest level; the number of levels in the sequence is + -- governed by the size of the transceiver FIFO (see the Xilinx user guides for more + -- information). + type BondLevels_t is array(0 to kNumLanes - 1) of std_logic_vector(2 downto 0); + constant kBondLevel : BondLevels_t := ( + 0 => b"000", -- Control from 1 + 1 => b"001", -- Master + 2 => b"000", -- Control from 1 + 3 => b"000" -- Control from 1 + ); + + + -- User Rx Data + -- ADC Word data width: 14 sample bits + 2 tails bits + constant kAdcWordWidth : integer := 16; + subtype AdcWord_t is std_logic_vector(kAdcWordWidth - 1 downto 0); + type AdcWordArray_t is array(kSamplesPerCycle*2 - 1 downto 0) of AdcWord_t; -- The *2 is because there are two samples (I and Q) per "sample" + + -- Constants to specify the contents of the AdcWord_t vector. + constant kAdcWordDataMsb : integer := 15; + constant kAdcWordDataLsb : integer := 2; + constant kAdcWordOver : integer := 1; + constant kAdcWordCBit1 : integer := 0; + + + -- Option to pipeline stages to improve timing, if needed + constant kPipelineDetectCharsStage : boolean := false; + constant kPipelineCharReplStage : boolean := false; + +end package; diff --git a/fpga/usrp3/top/n3xx/dboards/rh/db_ifc/PkgRhPersonality.vhd b/fpga/usrp3/top/n3xx/dboards/rh/db_ifc/PkgRhPersonality.vhd new file mode 100644 index 000000000..801a46d15 --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/rh/db_ifc/PkgRhPersonality.vhd @@ -0,0 +1,62 @@ +------------------------------------------------------------------------------- +-- +-- File: PkgRhPersonality.vhd +-- Author: National Instruments +-- Original Project: N32x +-- Date: 15 Dec 2017 +-- +------------------------------------------------------------------------------- +-- Copyright 2017 Ettus Research, A National Instruments Company +-- SPDX-License-Identifier: GPL-3.0 +------------------------------------------------------------------------------- +-- +-- Purpose: This package contains constants and helpful functions that enable +-- the FPGA to be compiled with different features. +-- +------------------------------------------------------------------------------- + +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +library work; + use work.PkgRegs.all; + + +package PkgRhPersonality is + + -- Rhodium daughterboard ID definition. + constant kDbId : integer := 16#152#; + constant kDbIdSize : integer := 16; + + + -- RegPort Address Definitions : ------------------------------------------------------ + -- + -- DB Regs ... + -- + -- Clocking Offset: 0x 000 Width: 0x 200 + -- Tdco0 Offset: 0x 200 Width: 0x 200 + -- Tdco1 Offset: 0x 400 Width: 0x 200 + -- Daughterboard Ctrl Offset: 0x 600 Width: 0x 200 + -- Total: 0x2000 + -- JESD 2x - A Offset: 0x2000 Width: 0x1000 + -- JESD 2x - B Offset: 0x3000 Width: 0x1000 + -- Total: 0x4000 + -- Total: 0x8000 for two DBs + -- ------------------------------------------------------------------------------------ + + -- A single RegPort runs to the JESD204B Core. + constant kJesdRegGroupInDbRegs : RegOffset_t := (kOffset => 16#2000#, -- 0x2000 to + kWidth => 16#1000#); -- 0x2FFF + + -- DB Regs : -------------------------------------------------------------------------- + constant kClockingOffsetInEndpoint : RegOffset_t := (kOffset => 16#0000#, -- 0x0000 to + kWidth => 16#0200#); -- 0x01FF + constant kTdc0OffsetsInEndpoint : RegOffset_t := (kOffset => 16#0200#, -- 0x0200 to + kWidth => 16#0200#); -- 0x03FF + constant kTdc1OffsetsInEndpoint : RegOffset_t := (kOffset => 16#0400#, -- 0x0400 to + kWidth => 16#0200#); -- 0x05FF + constant kDaughterboardOffsetInEndpoint : RegOffset_t := (kOffset => 16#0600#, -- 0x0600 to + kWidth => 16#0200#); -- 0x07FF + +end package PkgRhPersonality; diff --git a/fpga/usrp3/top/n3xx/dboards/rh/db_ifc/RadioClocking.vhd b/fpga/usrp3/top/n3xx/dboards/rh/db_ifc/RadioClocking.vhd new file mode 100644 index 000000000..69a15d49a --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/rh/db_ifc/RadioClocking.vhd @@ -0,0 +1,305 @@ +------------------------------------------------------------------------------- +-- +-- File: RadioClocking.vhd +-- Author: Daniel Jepson +-- Original Project: N310 +-- Date: 22 February 2016 +-- +------------------------------------------------------------------------------- +-- Copyright 2016-2018 Ettus Research, A National Instruments Company +-- SPDX-License-Identifier: LGPL-3.0 +------------------------------------------------------------------------------- +-- +-- Purpose: +-- +-- Instantiates a MMCM to produce 1x, 2x, and 3x versions of the Radio Clock +-- coming from the FPGA input pin. Handles all the buffering for the input clock. +-- Additionally allows the clocks to be turned on and off, and phase shifted. +-- +-- NOTE: This module hard-codes the MMCM settings for a SPECIFIC clock rate! +-- +------------------------------------------------------------------------------- + +library ieee; + use ieee.std_logic_1164.all; + +library unisim; + use unisim.vcomponents.all; + + +entity RadioClocking is + port ( + -- Async reset. Can be tied low if desired. + aReset : in boolean; + -- Sync reset... used in the same places as the async one. + bReset : in boolean; + + -- Should be a always-on clock + BusClk : in std_logic; + + -- Sync reset to the RadioClkMmcm. + bRadioClkMmcmReset : in std_logic; + + -- Locked indication from the RadioClkMmcm in BusClk and aReset domains. + bRadioClksValid : out std_logic; + + bRadioClk1xEnabled : in std_logic; + bRadioClk2xEnabled : in std_logic; + bRadioClk3xEnabled : in std_logic; + + -- Phase shift interface for the RadioClkMmcm. PsClk must be <= 200 MHz. + pPsInc : in std_logic; + pPsEn : in std_logic; + PsClk : in std_logic; + pPsDone : out std_logic; + + -- Straight from pins. Buffer included in here. + FpgaClk_n : in std_logic; + FpgaClk_p : in std_logic; + + RadioClk1x : out std_logic; + RadioClk2x : out std_logic; + RadioClk3x : out std_logic + + ); +end RadioClocking; + + +architecture rtl of RadioClocking is + + --vhook_sigstart + signal RadioClk1xLcl: std_logic; + signal RadioClk1xPll: std_logic; + signal RadioClk2xLcl: std_logic; + signal RadioClk2xPll: std_logic; + signal RadioClk3xLcl: std_logic; + signal RadioClk3xPll: std_logic; + --vhook_sigend + + signal RadioClkMmcmFeedbackIn, + RadioClkMmcmFeedbackOut, + FpgaClkSE, + aRadioClkMmcmLocked : std_logic; + + signal bRadioClkMmcmLocked_ms, + bRadioClkMmcmLocked, + bEnableRadioClkBufgOutputs, + bEnableRadioClk1xBufgOutput, + bEnableRadioClk2xBufgOutput, + bEnableRadioClk3xBufgOutput : std_logic := '0'; + + signal aRadioClkMmcmResetInternal : std_logic := '1'; + + attribute ASYNC_REG : string; + attribute ASYNC_REG of bRadioClkMmcmLocked_ms : signal is "true"; + attribute ASYNC_REG of bRadioClkMmcmLocked : signal is "true"; + +begin + + -- Radio Clock Buffering : ------------------------------------------------------------ + -- + -- ------------------------------------------------------------------------------------ + --vhook_i IBUFDS FpgaClkIbufg hidegeneric=true + --vhook_a I FpgaClk_p + --vhook_a IB FpgaClk_n + --vhook_a O FpgaClkSE + FpgaClkIbufg: IBUFDS + port map ( + O => FpgaClkSE, --out std_ulogic + I => FpgaClk_p, --in std_ulogic + IB => FpgaClk_n); --in std_ulogic + + + ResetDelay : process(aReset, BusClk) + begin + if aReset then + aRadioClkMmcmResetInternal <= '1'; + elsif rising_edge(BusClk) then + if bReset then + aRadioClkMmcmResetInternal <= '1'; + else + -- Delay by 1 to allow the BUFGs to turn off before the MMCM is reset. + aRadioClkMmcmResetInternal <= bRadioClkMmcmReset; + end if; + end if; + end process ResetDelay; + + + RadioClkMmcm: MMCME2_ADV + generic map( + COMPENSATION => "ZHOLD", + BANDWIDTH => "OPTIMIZED", + CLKFBOUT_MULT_F => 4.000, -- Feedback + CLKOUT0_DIVIDE_F => 4.000, -- Data Clock 1x, RadioClk1xPll + CLKOUT1_DIVIDE => 2, -- Data Clock 2x, RadioClk2xPll + CLKOUT2_DIVIDE => 2, -- Data Clock 3x, RadioClk3xPll + CLKOUT3_DIVIDE => 1, -- unused + CLKOUT4_DIVIDE => 1, -- unused + CLKOUT5_DIVIDE => 1, -- unused + CLKOUT6_DIVIDE => 1, -- unused + CLKFBOUT_PHASE => 0.000, -- Feedback + CLKOUT0_PHASE => 0.000, -- Data Clock 1x + CLKOUT1_PHASE => 0.000, -- Data Clock 2x + CLKOUT2_PHASE => 0.000, -- Data Clock 3x + CLKOUT3_PHASE => 0.000, -- unused + CLKOUT4_PHASE => 0.000, -- unused + CLKOUT5_PHASE => 0.000, -- unused + CLKOUT6_PHASE => 0.000, -- unused + CLKOUT0_DUTY_CYCLE => 0.500, + CLKOUT1_DUTY_CYCLE => 0.500, + CLKOUT2_DUTY_CYCLE => 0.500, + CLKOUT3_DUTY_CYCLE => 0.500, + CLKOUT4_DUTY_CYCLE => 0.500, + CLKOUT5_DUTY_CYCLE => 0.500, + CLKOUT6_DUTY_CYCLE => 0.500, + DIVCLK_DIVIDE => 1, + REF_JITTER1 => 0.010, + CLKIN1_PERIOD => 4.069, -- 245.76 MHz max + CLKFBOUT_USE_FINE_PS => true, + CLKOUT0_USE_FINE_PS => false, + CLKOUT1_USE_FINE_PS => false, + CLKOUT2_USE_FINE_PS => false, + CLKOUT3_USE_FINE_PS => false, + CLKOUT4_USE_FINE_PS => false, + CLKOUT5_USE_FINE_PS => false, + CLKOUT6_USE_FINE_PS => false, + STARTUP_WAIT => false, + CLKOUT4_CASCADE => false) + port map ( + CLKINSEL => '1', + CLKIN1 => FpgaClkSE, + CLKIN2 => '0', + CLKFBIN => RadioClkMmcmFeedbackIn, + RST => aRadioClkMmcmResetInternal, + PWRDWN => '0', + DADDR => (others => '0'), + DI => (others => '0'), + DWE => '0', + DEN => '0', + DCLK => '0', + DO => open, + DRDY => open, + PSINCDEC => pPsInc, + PSEN => pPsEn, + PSCLK => PsClk, + PSDONE => pPsDone, + CLKOUT0 => RadioClk1xPll, + CLKOUT0B => open, + CLKOUT1 => RadioClk2xPll, + CLKOUT1B => open, + CLKOUT2 => RadioClk3xPll, + CLKOUT2B => open, + CLKOUT3 => open, + CLKOUT3B => open, + CLKOUT4 => open, + CLKOUT5 => open, + CLKOUT6 => open, + CLKFBOUT => RadioClkMmcmFeedbackOut, + CLKFBOUTB => open, + LOCKED => aRadioClkMmcmLocked, + CLKINSTOPPED => open, + CLKFBSTOPPED => open); + + RadioClkMmcmFeedbackBufg: BUFG + port map ( + I => RadioClkMmcmFeedbackOut, + O => RadioClkMmcmFeedbackIn + ); + + + -- Only enable the WRAPBUFGs when the MMCM is locked. If the MMCM is ever placed in + -- reset, we turn off the clocks one cycle before the asynchronous version + -- (aRadioClkMmcmResetInternal) reaches the MMCM inputs in order to prevent + -- output glitches. + CombineEnablesForBuffers : process(aReset, BusClk) + begin + if aReset then + bRadioClkMmcmLocked_ms <= '0'; + bRadioClkMmcmLocked <= '0'; + bEnableRadioClk1xBufgOutput <= '0'; + bEnableRadioClk2xBufgOutput <= '0'; + bEnableRadioClk3xBufgOutput <= '0'; + bEnableRadioClkBufgOutputs <= '0'; + elsif rising_edge(BusClk) then + if bReset then + bRadioClkMmcmLocked_ms <= '0'; + bRadioClkMmcmLocked <= '0'; + bEnableRadioClk1xBufgOutput <= '0'; + bEnableRadioClk2xBufgOutput <= '0'; + bEnableRadioClk3xBufgOutput <= '0'; + bEnableRadioClkBufgOutputs <= '0'; + else + bRadioClkMmcmLocked_ms <= aRadioClkMmcmLocked; + bRadioClkMmcmLocked <= bRadioClkMmcmLocked_ms; + + bEnableRadioClkBufgOutputs <= bRadioClkMmcmLocked and + not bRadioClkMmcmReset; + bEnableRadioClk1xBufgOutput <= bRadioClk1xEnabled and bEnableRadioClkBufgOutputs; + bEnableRadioClk2xBufgOutput <= bRadioClk2xEnabled and bEnableRadioClkBufgOutputs; + bEnableRadioClk3xBufgOutput <= bRadioClk3xEnabled and bEnableRadioClkBufgOutputs; + end if; + end if; + end process CombineEnablesForBuffers; + + bRadioClksValid <= bEnableRadioClkBufgOutputs; + + --vhook_e WrapBufg RadioClk1xBuf + --vhook_a kEnableByDefault false + --vhook_a kIgnore false + --vhook_a kEnableIsAsync true + --vhook_a ClkIn RadioClk1xPll + --vhook_a aCe bEnableRadioClk1xBufgOutput + --vhook_a ClkOut RadioClk1xLcl + RadioClk1xBuf: entity work.WrapBufg (rtl) + generic map ( + kEnableByDefault => false, --boolean:=false + kIgnore => false, --boolean:=false + kEnableIsAsync => true) --boolean:=false + port map ( + ClkIn => RadioClk1xPll, --in std_logic + aCe => bEnableRadioClk1xBufgOutput, --in std_logic + ClkOut => RadioClk1xLcl); --out std_logic + + --vhook_e WrapBufg RadioClk2xBuf + --vhook_a kEnableByDefault false + --vhook_a kIgnore false + --vhook_a kEnableIsAsync true + --vhook_a ClkIn RadioClk2xPll + --vhook_a aCe bEnableRadioClk2xBufgOutput + --vhook_a ClkOut RadioClk2xLcl + RadioClk2xBuf: entity work.WrapBufg (rtl) + generic map ( + kEnableByDefault => false, --boolean:=false + kIgnore => false, --boolean:=false + kEnableIsAsync => true) --boolean:=false + port map ( + ClkIn => RadioClk2xPll, --in std_logic + aCe => bEnableRadioClk2xBufgOutput, --in std_logic + ClkOut => RadioClk2xLcl); --out std_logic + + --vhook_e WrapBufg RadioClk3xBuf + --vhook_a kEnableByDefault false + --vhook_a kIgnore false + --vhook_a kEnableIsAsync true + --vhook_a ClkIn RadioClk3xPll + --vhook_a aCe bEnableRadioClk3xBufgOutput + --vhook_a ClkOut RadioClk3xLcl + RadioClk3xBuf: entity work.WrapBufg (rtl) + generic map ( + kEnableByDefault => false, --boolean:=false + kIgnore => false, --boolean:=false + kEnableIsAsync => true) --boolean:=false + port map ( + ClkIn => RadioClk3xPll, --in std_logic + aCe => bEnableRadioClk3xBufgOutput, --in std_logic + ClkOut => RadioClk3xLcl); --out std_logic + + + -- Assign outputs from locals. + RadioClk1x <= RadioClk1xLcl; + RadioClk2x <= RadioClk2xLcl; + RadioClk3x <= RadioClk3xLcl; + + + +end rtl; diff --git a/fpga/usrp3/top/n3xx/dboards/rh/db_pins.xdc b/fpga/usrp3/top/n3xx/dboards/rh/db_pins.xdc new file mode 100644 index 000000000..b67269cd9 --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/rh/db_pins.xdc @@ -0,0 +1,280 @@ +## TDC : ################################################################################ +## Bank 10, 2.5V (DB A) +######################################################################################### + +set_property PACKAGE_PIN AB15 [get_ports {UNUSED_PIN_TDCA_0}] +set_property PACKAGE_PIN AB14 [get_ports {UNUSED_PIN_TDCA_1}] +set_property PACKAGE_PIN AB16 [get_ports {UNUSED_PIN_TDCA_2}] +set_property PACKAGE_PIN AB17 [get_ports {UNUSED_PIN_TDCA_3}] +set_property IOSTANDARD LVCMOS25 [get_ports {UNUSED_PIN_TDCA_*}] +set_property IOB TRUE [get_ports {UNUSED_PIN_TDCA_*}] + + +## TDC : ################################################################################ +## Bank 11, 2.5V (DB B) +######################################################################################### + +set_property PACKAGE_PIN W21 [get_ports {UNUSED_PIN_TDCB_0}] +set_property PACKAGE_PIN Y21 [get_ports {UNUSED_PIN_TDCB_1}] +set_property PACKAGE_PIN Y22 [get_ports {UNUSED_PIN_TDCB_2}] +set_property PACKAGE_PIN Y23 [get_ports {UNUSED_PIN_TDCB_3}] +set_property IOSTANDARD LVCMOS25 [get_ports {UNUSED_PIN_TDCB_*}] +set_property IOB TRUE [get_ports {UNUSED_PIN_TDCB_*}] + + +## USRP IO A : ########################################################################## +# DBA +######################################################################################### + +set_property PACKAGE_PIN G1 [get_ports DBA_MODULE_PWR_ENABLE] +set_property PACKAGE_PIN E5 [get_ports DBA_RF_PWR_ENABLE] + +set_property PACKAGE_PIN AF14 [get_ports DBA_FPGA_CLK_P] +set_property PACKAGE_PIN AG14 [get_ports DBA_FPGA_CLK_N] + +set_property PACKAGE_PIN N8 [get_ports DBA_MGTCLK_P] +set_property PACKAGE_PIN N7 [get_ports DBA_MGTCLK_N] + +set_property PACKAGE_PIN AG17 [get_ports DBA_FPGA_SYSREF_P] +set_property PACKAGE_PIN AG16 [get_ports DBA_FPGA_SYSREF_N] +set_property IOB TRUE [get_ports DBA_FPGA_SYSREF_*] + + +# set_property PACKAGE_PIN AD10 [get_ports NET2CLK_P] +# set_property PACKAGE_PIN AD9 [get_ports NET2CLK_N] + +set_property PACKAGE_PIN C2 [get_ports DBA_CPLD_PL_SPI_SCLK] +set_property PACKAGE_PIN B1 [get_ports DBA_TXLO_SPI_CS_B]; # DBA_CPLD_PL_SPI_LE +set_property PACKAGE_PIN B2 [get_ports DBA_CPLD_PL_SPI_CS_B]; # DBA_CPLD_PL_SPI_ADDR[0] +set_property PACKAGE_PIN F4 [get_ports DBA_RXLO_SPI_CS_B]; # DBA_CPLD_PL_SPI_ADDR[1] +set_property PACKAGE_PIN F3 [get_ports DBA_LODIS_SPI_CS_B]; # DBA_CPLD_PL_SPI_ADDR[2] +set_property PACKAGE_PIN C1 [get_ports DBA_CPLD_PL_SPI_MISO] +set_property PACKAGE_PIN A3 [get_ports DBA_CPLD_PL_SPI_MOSI] + +set_property PACKAGE_PIN AC16 [get_ports DBA_CPLD_PS_SPI_SCLK]; # DBA_CPLD_PS_SPI_ADDR[0] +set_property PACKAGE_PIN AE15 [get_ports DBA_CPLD_PS_SPI_CS_B]; # DBA_CPLD_PS_SPI_ADDR[1] +set_property PACKAGE_PIN AE16 [get_ports DBA_PHDAC_SPI_CS_B]; # DBA_CPLD_PS_SPI_LE +set_property PACKAGE_PIN AF17 [get_ports DBA_CLKDIS_SPI_CS_B] +set_property PACKAGE_PIN AK16 [get_ports DBA_ADC_SPI_CS_B]; # DBA_CPLD_UNUSED[12] +set_property PACKAGE_PIN AJ16 [get_ports DBA_DAC_SPI_CS_B]; # DBA_CPLD_UNUSED[13] +set_property PACKAGE_PIN AC17 [get_ports DBA_CPLD_PS_SPI_MISO] +set_property PACKAGE_PIN AF18 [get_ports DBA_CPLD_PS_SPI_MOSI] + +set_property PACKAGE_PIN AH13 [get_ports DBA_CPLD_JTAG_TDI] +set_property PACKAGE_PIN AH14 [get_ports DBA_CPLD_JTAG_TDO] +set_property PACKAGE_PIN AE13 [get_ports DBA_CPLD_JTAG_TMS] +set_property PACKAGE_PIN AF13 [get_ports DBA_CPLD_JTAG_TCK] + +set_property PACKAGE_PIN E1 [get_ports DBA_CLKDIST_SYNC] + +set_property PACKAGE_PIN A2 [get_ports DBA_ATR_TX] +set_property PACKAGE_PIN E3 [get_ports DBA_ATR_RX] + +set_property PACKAGE_PIN E2 [get_ports DBA_TXRX_SW_CTRL_1] +set_property PACKAGE_PIN F5 [get_ports DBA_TXRX_SW_CTRL_2] + +set_property PACKAGE_PIN AE12 [get_ports DBA_ADC_SYNCB_P] +set_property PACKAGE_PIN AF12 [get_ports DBA_ADC_SYNCB_N] +set_property PACKAGE_PIN AD14 [get_ports DBA_DAC_SYNCB_P]; # Layout swapped, RTL is negated. +set_property PACKAGE_PIN AD13 [get_ports DBA_DAC_SYNCB_N]; # Layout swapped, RTL is negated. + +# This mapping uses the TX pins as the "master" and mimics RX off of them so Vivado +# places the transceivers in the correct places. The mixup in lanes is accounted for +# in the AD9695 and the DAC37J82 crossbar settings. +set_property PACKAGE_PIN V6 [get_ports DBA_RX_P[0]] +set_property PACKAGE_PIN V5 [get_ports DBA_RX_N[0]] +set_property PACKAGE_PIN U4 [get_ports DBA_RX_P[1]] +set_property PACKAGE_PIN U3 [get_ports DBA_RX_N[1]] +set_property PACKAGE_PIN T6 [get_ports DBA_RX_P[2]] +set_property PACKAGE_PIN T5 [get_ports DBA_RX_N[2]] +set_property PACKAGE_PIN P6 [get_ports DBA_RX_P[3]] +set_property PACKAGE_PIN P5 [get_ports DBA_RX_N[3]] + +set_property PACKAGE_PIN T2 [get_ports DBA_TX_P[0]] +set_property PACKAGE_PIN T1 [get_ports DBA_TX_N[0]] +set_property PACKAGE_PIN R4 [get_ports DBA_TX_P[1]] +set_property PACKAGE_PIN R3 [get_ports DBA_TX_N[1]] +set_property PACKAGE_PIN P2 [get_ports DBA_TX_P[2]] +set_property PACKAGE_PIN P1 [get_ports DBA_TX_N[2]] +set_property PACKAGE_PIN N4 [get_ports DBA_TX_P[3]] +set_property PACKAGE_PIN N3 [get_ports DBA_TX_N[3]] + +set_property PACKAGE_PIN AG12 [get_ports DBA_LED_RX] +set_property PACKAGE_PIN AH12 [get_ports DBA_LED_RX2] +set_property PACKAGE_PIN AJ13 [get_ports DBA_LED_TX] + +# Possibly need to be used. Connected to CPLD. +# set_property PACKAGE_PIN C4 [get_ports DBA_CPLD_UNUSED[0]] +# set_property PACKAGE_PIN C3 [get_ports DBA_CPLD_UNUSED[1]] +# set_property PACKAGE_PIN K1 [get_ports DBA_CPLD_UNUSED[2]] +# set_property PACKAGE_PIN L1 [get_ports DBA_CPLD_UNUSED[3]] +# set_property PACKAGE_PIN D1 [get_ports DBA_CPLD_UNUSED[4]] +# set_property PACKAGE_PIN AE17 [get_ports DBA_CPLD_UNUSED[5]] +# set_property PACKAGE_PIN AE18 [get_ports DBA_CPLD_UNUSED[6]] +# set_property PACKAGE_PIN AB12 [get_ports DBA_CPLD_UNUSED[7]] +# set_property PACKAGE_PIN AC12 [get_ports DBA_CPLD_UNUSED[8]] +# set_property PACKAGE_PIN AG17 [get_ports DBA_CPLD_UNUSED[9]] +# set_property PACKAGE_PIN AK12 [get_ports DBA_CPLD_UNUSED[10]] +# set_property PACKAGE_PIN AK13 [get_ports DBA_CPLD_UNUSED[11]] + +set UsrpIoAHpPinsSe [get_ports {DBA_MODULE_PWR_ENABLE \ + DBA_RF_PWR_ENABLE \ + DBA_CPLD_PL_SPI_* \ + DBA_TXLO_SPI_CS_B \ + DBA_RXLO_SPI_CS_B \ + DBA_LODIS_SPI_CS_B \ + DBA_CLKDIST_SYNC \ + DBA_TXRX_SW_CTRL_* \ + DBA_ATR_*}] +set_property IOSTANDARD LVCMOS18 $UsrpIoAHpPinsSe +set_property DRIVE 6 $UsrpIoAHpPinsSe +set_property SLEW SLOW $UsrpIoAHpPinsSe + +set UsrpIoAHrPinsSeDr4 [get_ports {DBA_LED_* \ + DBA_CPLD_JTAG_*}] +set_property IOSTANDARD LVCMOS25 $UsrpIoAHrPinsSeDr4 +set_property DRIVE 4 $UsrpIoAHrPinsSeDr4 +set_property SLEW SLOW $UsrpIoAHrPinsSeDr4 + +set UsrpIoAHrPinsSeDr8 [get_ports {DBA_CPLD_PS_SPI_* \ + DBA_PHDAC_SPI_CS_B \ + DBA_CLKDIS_SPI_CS_B \ + DBA_ADC_SPI_CS_B \ + DBA_DAC_SPI_CS_B}] +set_property IOSTANDARD LVCMOS25 $UsrpIoAHrPinsSeDr8 +set_property DRIVE 8 $UsrpIoAHrPinsSeDr8 +set_property SLEW SLOW $UsrpIoAHrPinsSeDr8 + +set UsrpIoAHrPinsDiff [get_ports {DBA_ADC_SYNCB_* \ + DBA_DAC_SYNCB_* \ + DBA_FPGA_CLK_* \ + DBA_FPGA_SYSREF_*}] +set_property IOSTANDARD LVDS_25 $UsrpIoAHrPinsDiff +set_property DIFF_TERM TRUE $UsrpIoAHrPinsDiff + + +## USRP IO B : ########################################################################## +# DBB +######################################################################################### + +set_property PACKAGE_PIN J4 [get_ports DBB_MODULE_PWR_ENABLE] +set_property PACKAGE_PIN G4 [get_ports DBB_RF_PWR_ENABLE] + +set_property PACKAGE_PIN AG21 [get_ports DBB_FPGA_CLK_P] +set_property PACKAGE_PIN AH21 [get_ports DBB_FPGA_CLK_N] + +set_property PACKAGE_PIN W8 [get_ports DBB_MGTCLK_P] +set_property PACKAGE_PIN W7 [get_ports DBB_MGTCLK_N] + +set_property PACKAGE_PIN AE22 [get_ports DBB_FPGA_SYSREF_P] +set_property PACKAGE_PIN AF22 [get_ports DBB_FPGA_SYSREF_N] +set_property IOB TRUE [get_ports DBB_FPGA_SYSREF_*] + +set_property PACKAGE_PIN K6 [get_ports DBB_CPLD_PL_SPI_SCLK] +set_property PACKAGE_PIN F2 [get_ports DBB_TXLO_SPI_CS_B]; # DBB_CPLD_PL_SPI_LE +set_property PACKAGE_PIN G2 [get_ports DBB_CPLD_PL_SPI_CS_B]; # DBB_CPLD_PL_SPI_ADDR[0] +set_property PACKAGE_PIN H4 [get_ports DBB_RXLO_SPI_CS_B]; # DBB_CPLD_PL_SPI_ADDR[1] +set_property PACKAGE_PIN H3 [get_ports DBB_LODIS_SPI_CS_B]; # DBB_CPLD_PL_SPI_ADDR[2] +set_property PACKAGE_PIN J6 [get_ports DBB_CPLD_PL_SPI_MISO] +set_property PACKAGE_PIN D5 [get_ports DBB_CPLD_PL_SPI_MOSI] + +set_property PACKAGE_PIN AG22 [get_ports DBB_CPLD_PS_SPI_SCLK] +set_property PACKAGE_PIN AD23 [get_ports DBB_CPLD_PS_SPI_CS_B]; # DBB_CPLD_PS_SPI_ADDR[0] +set_property PACKAGE_PIN AE23 [get_ports DBB_PHDAC_SPI_CS_B]; # DBB_CPLD_PS_SPI_ADDR[1] +set_property PACKAGE_PIN AB24 [get_ports DBB_CLKDIS_SPI_CS_B]; # DBB_CPLD_PS_SPI_LE +set_property PACKAGE_PIN AJ23 [get_ports DBB_ADC_SPI_CS_B]; # DBB_CPLD_UNUSED[12]] +set_property PACKAGE_PIN AJ24 [get_ports DBB_DAC_SPI_CS_B]; # DBB_CPLD_UNUSED[13]] +set_property PACKAGE_PIN AH22 [get_ports DBB_CPLD_PS_SPI_MISO] +set_property PACKAGE_PIN AA24 [get_ports DBB_CPLD_PS_SPI_MOSI] + +set_property PACKAGE_PIN AH19 [get_ports DBB_CPLD_JTAG_TDI] +set_property PACKAGE_PIN AJ19 [get_ports DBB_CPLD_JTAG_TDO] +set_property PACKAGE_PIN AB21 [get_ports DBB_CPLD_JTAG_TMS] +set_property PACKAGE_PIN AB22 [get_ports DBB_CPLD_JTAG_TCK] + +set_property PACKAGE_PIN D3 [get_ports DBB_CLKDIST_SYNC] + +set_property PACKAGE_PIN E6 [get_ports DBB_ATR_TX] +set_property PACKAGE_PIN J5 [get_ports DBB_ATR_RX] + +set_property PACKAGE_PIN K5 [get_ports DBB_TXRX_SW_CTRL_1] +set_property PACKAGE_PIN G5 [get_ports DBB_TXRX_SW_CTRL_2] + +set_property PACKAGE_PIN AF23 [get_ports DBB_ADC_SYNCB_P] +set_property PACKAGE_PIN AF24 [get_ports DBB_ADC_SYNCB_N] +set_property PACKAGE_PIN AD21 [get_ports DBB_DAC_SYNCB_P] +set_property PACKAGE_PIN AE21 [get_ports DBB_DAC_SYNCB_N] + +# This mapping uses the TX pins as the "master" and mimics RX off of them so Vivado +# places the transceivers in the correct places. The mixup in lanes is accounted for +# in the AD9695 and the DAC37J82 crossbar settings. +set_property PACKAGE_PIN AC4 [get_ports DBB_RX_P[0]] +set_property PACKAGE_PIN AC3 [get_ports DBB_RX_N[0]] +set_property PACKAGE_PIN AB6 [get_ports DBB_RX_P[1]] +set_property PACKAGE_PIN AB5 [get_ports DBB_RX_N[1]] +set_property PACKAGE_PIN Y6 [get_ports DBB_RX_P[2]] +set_property PACKAGE_PIN Y5 [get_ports DBB_RX_N[2]] +set_property PACKAGE_PIN AA4 [get_ports DBB_RX_P[3]] +set_property PACKAGE_PIN AA3 [get_ports DBB_RX_N[3]] + +set_property PACKAGE_PIN AB2 [get_ports DBB_TX_P[0]] +set_property PACKAGE_PIN AB1 [get_ports DBB_TX_N[0]] +set_property PACKAGE_PIN Y2 [get_ports DBB_TX_P[1]] +set_property PACKAGE_PIN Y1 [get_ports DBB_TX_N[1]] +set_property PACKAGE_PIN W4 [get_ports DBB_TX_P[2]] +set_property PACKAGE_PIN W3 [get_ports DBB_TX_N[2]] +set_property PACKAGE_PIN V2 [get_ports DBB_TX_P[3]] +set_property PACKAGE_PIN V1 [get_ports DBB_TX_N[3]] + +set_property PACKAGE_PIN AK17 [get_ports DBB_LED_RX] +set_property PACKAGE_PIN AK18 [get_ports DBB_LED_RX2] +set_property PACKAGE_PIN AK21 [get_ports DBB_LED_TX] + +# Possibly need to be used. Connected to CPLD. +# set_property PACKAGE_PIN G6 [get_ports DBB_CPLD_UNUSED[0]] +# set_property PACKAGE_PIN H6 [get_ports DBB_CPLD_UNUSED[1]] +# set_property PACKAGE_PIN L3 [get_ports DBB_CPLD_UNUSED[2]] +# set_property PACKAGE_PIN L2 [get_ports DBB_CPLD_UNUSED[3]] +# set_property PACKAGE_PIN D4 [get_ports DBB_CPLD_UNUSED[4]] +# set_property PACKAGE_PIN AC22 [get_ports DBB_CPLD_UNUSED[5]] +# set_property PACKAGE_PIN AC23 [get_ports DBB_CPLD_UNUSED[6]] +# set_property PACKAGE_PIN AC24 [get_ports DBB_CPLD_UNUSED[7]] +# set_property PACKAGE_PIN AD24 [get_ports DBB_CPLD_UNUSED[8]] +# set_property PACKAGE_PIN AE22 [get_ports DBB_CPLD_UNUSED[9]] +# set_property PACKAGE_PIN AK20 [get_ports DBB_CPLD_UNUSED[10]] +# set_property PACKAGE_PIN AJ20 [get_ports DBB_CPLD_UNUSED[11]] + +set UsrpIoBHpPinsSe [get_ports {DBB_MODULE_PWR_ENABLE \ + DBB_RF_PWR_ENABLE \ + DBB_CPLD_PL_SPI_* \ + DBB_TXLO_SPI_CS_B \ + DBB_RXLO_SPI_CS_B \ + DBB_LODIS_SPI_CS_B \ + DBB_CLKDIST_SYNC \ + DBB_TXRX_SW_CTRL_* \ + DBB_ATR_*}] +set_property IOSTANDARD LVCMOS18 $UsrpIoBHpPinsSe +set_property DRIVE 6 $UsrpIoBHpPinsSe +set_property SLEW SLOW $UsrpIoBHpPinsSe + +set UsrpIoBHrPinsSeDr4 [get_ports {DBB_LED_* \ + DBB_CPLD_JTAG_*}] +set_property IOSTANDARD LVCMOS25 $UsrpIoBHrPinsSeDr4 +set_property DRIVE 4 $UsrpIoBHrPinsSeDr4 +set_property SLEW SLOW $UsrpIoBHrPinsSeDr4 + +set UsrpIoBHrPinsSeDr8 [get_ports {DBB_CPLD_PS_SPI_* \ + DBB_PHDAC_SPI_CS_B \ + DBB_CLKDIS_SPI_CS_B \ + DBB_ADC_SPI_CS_B \ + DBB_DAC_SPI_CS_B}] +set_property IOSTANDARD LVCMOS25 $UsrpIoBHrPinsSeDr8 +set_property DRIVE 8 $UsrpIoBHrPinsSeDr8 +set_property SLEW SLOW $UsrpIoBHrPinsSeDr8 + +set UsrpIoBHrPinsDiff [get_ports {DBB_ADC_SYNCB_* \ + DBB_DAC_SYNCB_* \ + DBB_FPGA_CLK_* \ + DBB_FPGA_SYSREF_*}] +set_property IOSTANDARD LVDS_25 $UsrpIoBHrPinsDiff +set_property DIFF_TERM TRUE $UsrpIoBHrPinsDiff diff --git a/fpga/usrp3/top/n3xx/dboards/rh/db_timing.xdc b/fpga/usrp3/top/n3xx/dboards/rh/db_timing.xdc new file mode 100644 index 000000000..cffbd839a --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/rh/db_timing.xdc @@ -0,0 +1,264 @@ +# +# Copyright 2017 Ettus Research, A National Instruments Company +# SPDX-License-Identifier: LGPL-3.0 +# +# Timing analysis is performed in "usrp3/top/n3xx/dboards/rh/doc/rh_timing.xlsx". +# See this spreadsheet for more details and explanations. + +#******************************************************************************* +## Asynchronous clock groups + +# MGT reference clocks are also async to everything. +set_clock_groups -asynchronous -group [get_clocks mgt_clk_dba -include_generated_clocks] +set_clock_groups -asynchronous -group [get_clocks mgt_clk_dbb -include_generated_clocks] + +# fpga_clk_a and fpga_clk_b are related to one another after synchronization. +# However, we do need to declare that these clocks (both a and b) and their children +# are async to the remainder of the design. Use the wildcard at the end to grab the +# virtual clock as well as the real ones. +set_clock_groups -asynchronous -group [get_clocks {fpga_clk_a* fpga_clk_b*} -include_generated_clocks] + +# The SPI readback and write clocks cannot be active at the same time, as they +# originate from the same pin. +set_clock_groups -physically_exclusive \ + -group [get_clocks pl_spi_rb_clk_a] \ + -group [get_clocks pl_spi_clk_a] +set_clock_groups -physically_exclusive \ + -group [get_clocks pl_spi_rb_clk_b] \ + -group [get_clocks pl_spi_clk_b] + +#******************************************************************************* +## PS SPI: since these lines all come from the PS and I don't have access to the +# driving clock (or anything for that matter), I'm left with constraining the maximum +# and minimum delay on these lines, per a Xilinx AR: +# https://www.xilinx.com/support/answers/62122.html +set CPLD_SPI_OUTS [get_ports {DB*_CPLD_PS_SPI_SCLK \ + DB*_CPLD_PS_SPI_MOSI \ + DB*_CPLD_PS_SPI_CS_B \ + DB*_CLKDIS_SPI_CS_B \ + DB*_PHDAC_SPI_CS_B \ + DB*_ADC_SPI_CS_B \ + DB*_DAC_SPI_CS_B}] + +# The actual min and max path delays before applying constraints were (from report_timing): +# 3.332 ns (Min at Fast Process Corner) +# 10.596 ns (Max at Slow Process Corner) +# Therefore, we round those number to their immediate succesor respectively. +# After implementation, the tools were unable to meet timing when leaving a 11 ns max +# delay value, so it was incremented. +set MIN_OUT_DELAY 3.0 +set MAX_OUT_DELAY 12.0 + +set_max_delay $MAX_OUT_DELAY -to $CPLD_SPI_OUTS +set_min_delay $MIN_OUT_DELAY -to $CPLD_SPI_OUTS + +# report_timing -to $CPLD_SPI_OUTS -max_paths 20 -delay_type min_max -name CpldSpiOutTiming + +# The actual min and max path delays before applying constraints were (from report_timing): +# 2.733 ns (Min at Fast Process Corner) +# 6.071 ns (Max at Slow Process Corner) +# Therefore, we round those number to their immediate succesor respectively. +set MIN_IN_DELAY 2.0 +set MAX_IN_DELAY 10.0 + +set PS_SPI_INPUTS_0 [get_pins -hierarchical -filter {NAME =~ "*/PS7_i/EMIOSPI0MI"}] +set PS_SPI_INPUTS_1 [get_pins -hierarchical -filter {NAME =~ "*/PS7_i/EMIOSPI1MI"}] + +set_max_delay $MAX_IN_DELAY -to $PS_SPI_INPUTS_0 +set_min_delay $MIN_IN_DELAY -to $PS_SPI_INPUTS_0 +set_max_delay $MAX_IN_DELAY -to $PS_SPI_INPUTS_1 +set_min_delay $MIN_IN_DELAY -to $PS_SPI_INPUTS_1 + +# report_timing -to $PS_SPI_INPUTS_0 -max_paths 30 -delay_type min_max -nworst 30 -name Spi0InTiming +# report_timing -to $PS_SPI_INPUTS_1 -max_paths 30 -delay_type min_max -nworst 30 -name Spi1InTiming + + + +#******************************************************************************* +## PL SPI to the CPLD +# +# All of these lines are driven or received from flops in simple_spi_core. The CPLD +# calculations assume the FPGA has less than 6 ns of skew between the SCK and +# SDI/CS_n. Pretty easy constraint to write! See above for the clock definition. +# Do this for DBA and DBB independently. +set MAX_SKEW 6.0 +set SETUP_SKEW [expr {$MAX_SKEW / 2}] +set HOLD_SKEW [expr {$MAX_SKEW / 2}] +# Do not set the output delay constraint on the clock line! +set PORT_LIST_A [get_ports {DBA_CPLD_PL_SPI_CS_B \ + DBA_CPLD_PL_SPI_MOSI \ + DBA_TXLO_SPI_CS_B \ + DBA_RXLO_SPI_CS_B \ + DBA_LODIS_SPI_CS_B }] +set PORT_LIST_B [get_ports {DBB_CPLD_PL_SPI_CS_B \ + DBB_CPLD_PL_SPI_MOSI \ + DBB_TXLO_SPI_CS_B \ + DBB_RXLO_SPI_CS_B \ + DBB_LODIS_SPI_CS_B }] +# Then add the output delay on each of the ports. +set_output_delay -clock [get_clocks pl_spi_clk_a] -max -$SETUP_SKEW $PORT_LIST_A +set_output_delay -add_delay -clock_fall -clock [get_clocks pl_spi_clk_a] -max -$SETUP_SKEW $PORT_LIST_A +set_output_delay -clock [get_clocks pl_spi_clk_a] -min $HOLD_SKEW $PORT_LIST_A +set_output_delay -add_delay -clock_fall -clock [get_clocks pl_spi_clk_a] -min $HOLD_SKEW $PORT_LIST_A +set_output_delay -clock [get_clocks pl_spi_clk_b] -max -$SETUP_SKEW $PORT_LIST_B +set_output_delay -add_delay -clock_fall -clock [get_clocks pl_spi_clk_b] -max -$SETUP_SKEW $PORT_LIST_B +set_output_delay -clock [get_clocks pl_spi_clk_b] -min $HOLD_SKEW $PORT_LIST_B +set_output_delay -add_delay -clock_fall -clock [get_clocks pl_spi_clk_b] -min $HOLD_SKEW $PORT_LIST_B +# Finally, make both the setup and hold checks use the same launching and latching edges. +set_multicycle_path -setup -from [get_clocks radio_clk] -to [get_clocks pl_spi_clk_a] -start 0 +set_multicycle_path -hold -from [get_clocks radio_clk] -to [get_clocks pl_spi_clk_a] -1 +set_multicycle_path -setup -from [get_clocks radio_clk] -to [get_clocks pl_spi_clk_b] -start 0 +set_multicycle_path -hold -from [get_clocks radio_clk] -to [get_clocks pl_spi_clk_b] -1 + +# For SDO input timing (MISO), we need to look at the CPLD's constraints on turnaround +# time plus any board propagation delay. +# CPLD clk-to-q is 20 ns, then add 1.2 ns for board delay (once for clock, once for data) +# For hold time, assume zero delay (likely overconstraining here, due to board delays) +set MISO_INPUT_A [get_ports DBA_CPLD_PL_SPI_MISO] +set MISO_INPUT_B [get_ports DBB_CPLD_PL_SPI_MISO] +set_input_delay -clock [get_clocks pl_spi_rb_clk_a] -clock_fall -max 22.400 $MISO_INPUT_A +set_input_delay -clock [get_clocks pl_spi_rb_clk_a] -clock_fall -min 0.000 $MISO_INPUT_A +set_input_delay -clock [get_clocks pl_spi_rb_clk_b] -clock_fall -max 22.400 $MISO_INPUT_B +set_input_delay -clock [get_clocks pl_spi_rb_clk_b] -clock_fall -min 0.000 $MISO_INPUT_B + +# Since the input delay span is clearly more than a period of the radio_clk, we need to +# add a multicycle path here as well to define the clock divider ratio. The MISO data +# is driven on the falling edge of the SPI clock and captured on the rising edge, so we +# only have one half of a SPI clock cycle for our setup. Hold is left alone and is OK +# as-is due to the delays in the CPLD and board. +set SETUP_CYCLES [expr {$PL_SPI_RB_DIVIDE_VAL / 2}] +set HOLD_CYCLES 0 +set_multicycle_path -setup -from [get_clocks pl_spi_rb_clk_a] -through $MISO_INPUT_A \ + $SETUP_CYCLES +set_multicycle_path -hold -from [get_clocks pl_spi_rb_clk_a] -through $MISO_INPUT_A -end \ + [expr {$SETUP_CYCLES + $HOLD_CYCLES - 1}] +set_multicycle_path -setup -from [get_clocks pl_spi_rb_clk_b] -through $MISO_INPUT_B \ + $SETUP_CYCLES +set_multicycle_path -hold -from [get_clocks pl_spi_rb_clk_b] -through $MISO_INPUT_B -end \ + [expr {$SETUP_CYCLES + $HOLD_CYCLES - 1}] + +#******************************************************************************* +## SYSREF/SYNC JESD Timing +# +# SYNC is async, SYSREF is tightly timed. + +# The SYNC output (to ADC) for both DBs is governed by the JESD cores, which are solely +# driven by DB-A clock... but it is an asynchronous signal so we use the async_out_clk. +set_output_delay -clock [get_clocks async_out_clk] 0.000 [get_ports DB*_ADC_SYNCB_P] +set_max_delay -to [get_ports DB*_ADC_SYNCB_P] 50.000 +set_min_delay -to [get_ports DB*_ADC_SYNCB_P] 0.000 + +# The SYNC input (from DAC) for both DBs is received by the DB-A clock inside the JESD +# cores... but again, it is asynchronous and therefore uses the async_in_clk. +set_input_delay -clock [get_clocks async_in_clk] 0.000 [get_ports DB*_DAC_SYNCB_P] +set_max_delay -from [get_ports DB*_DAC_SYNCB_P] 50.000 +set_min_delay -from [get_ports DB*_DAC_SYNCB_P] 0.000 + +# SYSREF is driven by the LMK directly to the FPGA. Timing analysis was performed once +# for the worst-case numbers across both DBs to produce one set of numbers for both DBs. +# Since we easily meet setup and hold in Vivado, then this is an acceptable approach. +# SYSREF is captured by the local clock from each DB, so we have two sets of constraints. +set_input_delay -clock fpga_clk_a_v -min -0.479 [get_ports DBA_FPGA_SYSREF_*] +set_input_delay -clock fpga_clk_a_v -max 0.661 [get_ports DBA_FPGA_SYSREF_*] + +set_input_delay -clock fpga_clk_b_v -min -0.479 [get_ports DBB_FPGA_SYSREF_*] +set_input_delay -clock fpga_clk_b_v -max 0.661 [get_ports DBB_FPGA_SYSREF_*] + + +#******************************************************************************* +## PPS Timing + +# Due to the N3xx synchronization and clocking structure, the PPS output is driven from +# the Sample Clock domain instead of the input Reference Clock. Constrain the output as +# tightly as possible to accurately mimic the internal Sample Clock timing. +set SETUP_SKEW 2.0 +set HOLD_SKEW -0.5 +set_output_delay -clock [get_clocks fpga_clk_a_v] -max -$SETUP_SKEW [get_ports REF_1PPS_OUT] +set_output_delay -clock [get_clocks fpga_clk_a_v] -min $HOLD_SKEW [get_ports REF_1PPS_OUT] +set_multicycle_path -setup -to [get_ports REF_1PPS_OUT] -start 0 +set_multicycle_path -hold -to [get_ports REF_1PPS_OUT] -1 + +#******************************************************************************* +### Async I/Os +set DB_ASYNC_OUTPUTS [get_ports { + DB*_MODULE_PWR_ENABLE + DB*_RF_PWR_ENABLE + DB*_CLKDIST_SYNC + DB*_ATR_TX + DB*_ATR_RX + DB*_TXRX_SW_CTRL_1 + DB*_TXRX_SW_CTRL_2 + DB*_LED_RX + DB*_LED_RX2 + DB*_LED_TX + QSFP_I2C_* +}] +set_output_delay -clock [get_clocks async_out_clk] 0.000 $DB_ASYNC_OUTPUTS +set_max_delay -to $DB_ASYNC_OUTPUTS 50.000 +set_min_delay -to $DB_ASYNC_OUTPUTS 0.000 + +set_input_delay -clock [get_clocks async_in_clk] 0.000 [get_ports QSFP_I2C_*] +set_max_delay -from [get_ports QSFP_I2C_*] 50.000 +set_min_delay -from [get_ports QSFP_I2C_*] 0.000 + +#******************************************************************************* +## JTAG + +## MAX 10 JTAG TDI setup: 2 ns +## MAX 10 JTAG TMS setup: 3 ns +## MAX 10 JTAG hold: 10 ns +## MAX 10 JTAG clk-to-q: 18 ns +## Board delay: < 1.5 ns +## +## Setup time = Board delay + TMS setup = 3 ns + 1.5 ns = 4.5 ns +## Hold time = Board delay + TMS hold = 1.5 ns + 10 ns = 11.5 ns +## Overconstrain output delay and keep skew to +/- 8 ns +## +## Input delay = 2x Board delay + clk-to-q = 3 ns + 18 ns = 21 ns + +# Constrain outputs for skew, with same latch/launch edge: +set_output_delay -clock [get_clocks dba_jtag_tck] -max -4.0 \ + [get_ports {DBA_CPLD_JTAG_TDI DBA_CPLD_JTAG_TMS}] +set_output_delay -add_delay -clock_fall -clock [get_clocks dba_jtag_tck] -max -4.0 \ + [get_ports {DBA_CPLD_JTAG_TDI DBA_CPLD_JTAG_TMS}] +set_output_delay -clock [get_clocks dba_jtag_tck] -min 4.0 \ + [get_ports {DBA_CPLD_JTAG_TDI DBA_CPLD_JTAG_TMS}] +set_output_delay -add_delay -clock_fall -clock [get_clocks dba_jtag_tck] -min 4.0 \ + [get_ports {DBA_CPLD_JTAG_TDI DBA_CPLD_JTAG_TMS}] +set_output_delay -clock [get_clocks dbb_jtag_tck] -max -4.0 \ + [get_ports {DBB_CPLD_JTAG_TDI DBB_CPLD_JTAG_TMS}] +set_output_delay -add_delay -clock_fall -clock [get_clocks dbb_jtag_tck] -max -4.0 \ + [get_ports {DBB_CPLD_JTAG_TDI DBB_CPLD_JTAG_TMS}] +set_output_delay -clock [get_clocks dbb_jtag_tck] -min 4.0 \ + [get_ports {DBB_CPLD_JTAG_TDI DBB_CPLD_JTAG_TMS}] +set_output_delay -add_delay -clock_fall -clock [get_clocks dbb_jtag_tck] -min 4.0 \ + [get_ports {DBB_CPLD_JTAG_TDI DBB_CPLD_JTAG_TMS}] +# Finally, make both the setup and hold checks use the same launching and latching edges. +set_multicycle_path -setup -from [get_clocks clk40] -to [get_clocks dba_jtag_tck] -start 0 +set_multicycle_path -hold -from [get_clocks clk40] -to [get_clocks dba_jtag_tck] -1 +set_multicycle_path -setup -from [get_clocks clk40] -to [get_clocks dbb_jtag_tck] -start 0 +set_multicycle_path -hold -from [get_clocks clk40] -to [get_clocks dbb_jtag_tck] -1 + +set_input_delay -clock [get_clocks dba_jtag_tck] -clock_fall -max 21 \ + [get_ports DBA_CPLD_JTAG_TDO] +set_input_delay -clock [get_clocks dba_jtag_tck] -clock_fall -min 0 \ + [get_ports DBA_CPLD_JTAG_TDO] +set_input_delay -clock [get_clocks dbb_jtag_tck] -clock_fall -max 21 \ + [get_ports DBB_CPLD_JTAG_TDO] +set_input_delay -clock [get_clocks dbb_jtag_tck] -clock_fall -min 0 \ + [get_ports DBB_CPLD_JTAG_TDO] +# Inputs have setup checks relative to half a period of TCK (launch on fall, +# latch on rise). Actual latch clock is faster, so push back setup and hold +# checks to match. +set_multicycle_path -setup -from [get_clocks dba_jtag_tck] \ + -through [get_ports DBA_CPLD_JTAG_TDO] \ + [expr {$DB_JTAG_DIVISOR / 2}] +set_multicycle_path -end -hold -from [get_clocks dba_jtag_tck] \ + -through [get_ports DBA_CPLD_JTAG_TDO] \ + [expr {$DB_JTAG_DIVISOR - 1}] +set_multicycle_path -setup -from [get_clocks dbb_jtag_tck] \ + -through [get_ports DBB_CPLD_JTAG_TDO] \ + [expr {$DB_JTAG_DIVISOR / 2}] +set_multicycle_path -end -hold -from [get_clocks dbb_jtag_tck] \ + -through [get_ports DBB_CPLD_JTAG_TDO] \ + [expr {$DB_JTAG_DIVISOR - 1}] diff --git a/fpga/usrp3/top/n3xx/dboards/rh/doc/rh_timing.xlsx b/fpga/usrp3/top/n3xx/dboards/rh/doc/rh_timing.xlsx Binary files differnew file mode 100755 index 000000000..7782ee33c --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/rh/doc/rh_timing.xlsx diff --git a/fpga/usrp3/top/n3xx/dboards/rh/n3xx.v b/fpga/usrp3/top/n3xx/dboards/rh/n3xx.v new file mode 100644 index 000000000..e697f00d4 --- /dev/null +++ b/fpga/usrp3/top/n3xx/dboards/rh/n3xx.v @@ -0,0 +1,3855 @@ +/////////////////////////////////////////////////////////////////// +/// +// Copyright 2018-2019 Ettus Research, A National Instruments Brand +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: n3xx +// Description: +// Top Level for N320, N321 devices +// +////////////////////////////////////////////////////////////////////// + +module n3xx ( + inout [11:0] FPGA_GPIO, + + input FPGA_REFCLK_P, + input FPGA_REFCLK_N, + input REF_1PPS_IN, + input NETCLK_REF_P, + input NETCLK_REF_N, + //input REF_1PPS_IN_MGMT, + output REF_1PPS_OUT, + + //TDC + inout UNUSED_PIN_TDCA_0, + inout UNUSED_PIN_TDCA_1, + inout UNUSED_PIN_TDCA_2, + inout UNUSED_PIN_TDCA_3, + inout UNUSED_PIN_TDCB_0, + inout UNUSED_PIN_TDCB_1, + inout UNUSED_PIN_TDCB_2, + inout UNUSED_PIN_TDCB_3, + +`ifdef NPIO_LANES + input NPIO_RX0_P, + input NPIO_RX0_N, + output NPIO_TX0_P, + output NPIO_TX0_N, + input NPIO_RX1_P, + input NPIO_RX1_N, + output NPIO_TX1_P, + output NPIO_TX1_N, +`endif +`ifdef QSFP_LANES + input [`QSFP_LANES-1:0] QSFP_RX_P, + input [`QSFP_LANES-1:0] QSFP_RX_N, + output [`QSFP_LANES-1:0] QSFP_TX_P, + output [`QSFP_LANES-1:0] QSFP_TX_N, + output QSFP_RESET_B, + output QSFP_LED, + output QSFP_MODSEL_B, + output QSFP_LPMODE, + input QSFP_PRESENT_B, + input QSFP_INT_B, + inout QSFP_I2C_SCL, + inout QSFP_I2C_SDA, +`endif + //TODO: Uncomment when connected here + //input NPIO_0_RXSYNC_0_P, NPIO_0_RXSYNC_1_P, + //input NPIO_0_RXSYNC_0_N, NPIO_0_RXSYNC_1_N, + //output NPIO_0_TXSYNC_0_P, NPIO_0_TXSYNC_1_P, + //output NPIO_0_TXSYNC_0_N, NPIO_0_TXSYNC_1_N, + //input NPIO_1_RXSYNC_0_P, NPIO_1_RXSYNC_1_P, + //input NPIO_1_RXSYNC_0_N, NPIO_1_RXSYNC_1_N, + //output NPIO_1_TXSYNC_0_P, NPIO_1_TXSYNC_1_P, + //output NPIO_1_TXSYNC_0_N, NPIO_1_TXSYNC_1_N, + //input NPIO_2_RXSYNC_0_P, NPIO_2_RXSYNC_1_P, + //input NPIO_2_RXSYNC_0_N, NPIO_2_RXSYNC_1_N, + //output NPIO_2_TXSYNC_0_P, NPIO_2_TXSYNC_1_P, + //output NPIO_2_TXSYNC_0_N, NPIO_2_TXSYNC_1_N, + + //GPS + input GPS_1PPS, + //input GPS_1PPS_RAW, + + //Misc + input ENET0_CLK125, + //inout ENET0_PTP, + //output ENET0_PTP_DIR, + //inout ATSHA204_SDA, + input FPGA_PL_RESETN, // TODO: Add to reset logic + // output reg [1:0] FPGA_TEST, + //input PWR_CLK_FPGA, // TODO: check direction + input FPGA_PUDC_B, + + //White Rabbit + input WB_20MHZ_P, + input WB_20MHZ_N, + output WB_DAC_DIN, + output WB_DAC_NCLR, + output WB_DAC_NLDAC, + output WB_DAC_NSYNC, + output WB_DAC_SCLK, + + //LEDS + output PANEL_LED_GPS, + output PANEL_LED_LINK, + output PANEL_LED_PPS, + output PANEL_LED_REF, + + // ARM Connections (PS) + inout [53:0] MIO, + inout PS_SRSTB, + inout PS_CLK, + inout PS_PORB, + inout DDR_Clk, + inout DDR_Clk_n, + inout DDR_CKE, + inout DDR_CS_n, + inout DDR_RAS_n, + inout DDR_CAS_n, + inout DDR_WEB, + inout [2:0] DDR_BankAddr, + inout [14:0] DDR_Addr, + inout DDR_ODT, + inout DDR_DRSTB, + inout [31:0] DDR_DQ, + inout [3:0] DDR_DM, + inout [3:0] DDR_DQS, + inout [3:0] DDR_DQS_n, + inout DDR_VRP, + inout DDR_VRN, + + + /////////////////////////////////// + // + // High Speed SPF+ signals and clocking + // + /////////////////////////////////// + + // These clock inputs must always be enabled with a buffer regardless of the build + // target to avoid damage to the FPGA. + input NETCLK_P, + input NETCLK_N, + input MGT156MHZ_CLK1_P, + input MGT156MHZ_CLK1_N, + + input SFP_0_RX_P, input SFP_0_RX_N, + output SFP_0_TX_P, output SFP_0_TX_N, + input SFP_1_RX_P, input SFP_1_RX_N, + output SFP_1_TX_P, output SFP_1_TX_N, + + + /////////////////////////////////// + // + // DRAM Interface + // + /////////////////////////////////// + inout [31:0] ddr3_dq, // Data pins. Input for Reads, Output for Writes. + inout [3:0] ddr3_dqs_n, // Data Strobes. Input for Reads, Output for Writes. + inout [3:0] ddr3_dqs_p, + // + output [15:0] ddr3_addr, // Address + output [2:0] ddr3_ba, // Bank Address + output ddr3_ras_n, // Row Address Strobe. + output ddr3_cas_n, // Column address select + output ddr3_we_n, // Write Enable + output ddr3_reset_n, // SDRAM reset pin. + output [0:0] ddr3_ck_p, // Differential clock + output [0:0] ddr3_ck_n, + output [0:0] ddr3_cke, // Clock Enable + output [0:0] ddr3_cs_n, // Chip Select + output [3:0] ddr3_dm, // Data Mask [3] = UDM.U26, [2] = LDM.U26, ... + output [0:0] ddr3_odt, // On-Die termination enable. + // + input sys_clk_p, // Differential + input sys_clk_n, // 100MHz clock source to generate DDR3 clocking. + + + /////////////////////////////////// + // + // Supporting I/O for SPF+ interfaces + // (non high speed stuff) + // + /////////////////////////////////// + + //SFP+ 0, Slow Speed, Bank 13 3.3V + input SFP_0_I2C_NPRESENT, + output SFP_0_LED_A, + output SFP_0_LED_B, + input SFP_0_LOS, + output SFP_0_RS0, + output SFP_0_RS1, + output SFP_0_TXDISABLE, + input SFP_0_TXFAULT, + + //SFP+ 1, Slow Speed, Bank 13 3.3V + //input SFP_1_I2C_NPRESENT, + output SFP_1_LED_A, + output SFP_1_LED_B, + input SFP_1_LOS, + output SFP_1_RS0, + output SFP_1_RS1, + output SFP_1_TXDISABLE, + input SFP_1_TXFAULT, + + //USRP IO A + output DBA_MODULE_PWR_ENABLE, + output DBA_RF_PWR_ENABLE, + + output DBA_CPLD_PS_SPI_SCLK, + output DBA_CLKDIS_SPI_CS_B, + output DBA_CPLD_PS_SPI_CS_B, + output DBA_PHDAC_SPI_CS_B, + output DBA_CPLD_PS_SPI_MOSI, + input DBA_CPLD_PS_SPI_MISO, + + output DBA_ATR_RX, + output DBA_ATR_TX, + output DBA_TXRX_SW_CTRL_1, + output DBA_TXRX_SW_CTRL_2, + + output DBA_CPLD_PL_SPI_SCLK, + output DBA_ADC_SPI_CS_B, + output DBA_DAC_SPI_CS_B, + output DBA_TXLO_SPI_CS_B, + output DBA_RXLO_SPI_CS_B, + output DBA_LODIS_SPI_CS_B, + output DBA_CPLD_PL_SPI_CS_B, + output DBA_CPLD_PL_SPI_MOSI, + input DBA_CPLD_PL_SPI_MISO, + + output DBA_ADC_SYNCB_P, + output DBA_ADC_SYNCB_N, + input DBA_DAC_SYNCB_P, + input DBA_DAC_SYNCB_N, + + output DBA_CLKDIST_SYNC, + + inout DBA_CPLD_JTAG_TCK, + inout DBA_CPLD_JTAG_TMS, + inout DBA_CPLD_JTAG_TDI, + input DBA_CPLD_JTAG_TDO, + + input DBA_FPGA_CLK_P, + input DBA_FPGA_CLK_N, + + input DBA_FPGA_SYSREF_P, + input DBA_FPGA_SYSREF_N, + + input DBA_MGTCLK_P, + input DBA_MGTCLK_N, + + input [3:0] DBA_RX_P, + input [3:0] DBA_RX_N, + output [3:0] DBA_TX_P, + output [3:0] DBA_TX_N, + + output DBA_LED_RX, + output DBA_LED_RX2, + output DBA_LED_TX, + + //USRP IO B + output DBB_MODULE_PWR_ENABLE, + output DBB_RF_PWR_ENABLE, + + output DBB_CPLD_PS_SPI_SCLK, + output DBB_CLKDIS_SPI_CS_B, + output DBB_CPLD_PS_SPI_CS_B, + output DBB_PHDAC_SPI_CS_B, + output DBB_CPLD_PS_SPI_MOSI, + input DBB_CPLD_PS_SPI_MISO, + + output DBB_ATR_RX, + output DBB_ATR_TX, + output DBB_TXRX_SW_CTRL_1, + output DBB_TXRX_SW_CTRL_2, + + output DBB_CPLD_PL_SPI_SCLK, + output DBB_ADC_SPI_CS_B, + output DBB_DAC_SPI_CS_B, + output DBB_TXLO_SPI_CS_B, + output DBB_RXLO_SPI_CS_B, + output DBB_LODIS_SPI_CS_B, + output DBB_CPLD_PL_SPI_CS_B, + output DBB_CPLD_PL_SPI_MOSI, + input DBB_CPLD_PL_SPI_MISO, + + output DBB_ADC_SYNCB_P, + output DBB_ADC_SYNCB_N, + input DBB_DAC_SYNCB_P, + input DBB_DAC_SYNCB_N, + + output DBB_CLKDIST_SYNC, + + inout DBB_CPLD_JTAG_TCK, + inout DBB_CPLD_JTAG_TMS, + inout DBB_CPLD_JTAG_TDI, + input DBB_CPLD_JTAG_TDO, + + input DBB_FPGA_CLK_P, + input DBB_FPGA_CLK_N, + + input DBB_FPGA_SYSREF_P, + input DBB_FPGA_SYSREF_N, + + input DBB_MGTCLK_P, + input DBB_MGTCLK_N, + + input [3:0] DBB_RX_P, + input [3:0] DBB_RX_N, + output [3:0] DBB_TX_P, + output [3:0] DBB_TX_N, + + output DBB_LED_RX, + output DBB_LED_RX2, + output DBB_LED_TX +); + + localparam N_AXILITE_SLAVES = 4; + localparam REG_AWIDTH = 14; // log2(0x4000) + localparam QSFP_REG_AWIDTH = 17; // log2(0x20000) + localparam REG_DWIDTH = 32; + localparam FP_GPIO_OFFSET = 32; + localparam FP_GPIO_WIDTH = 12; + + localparam NUM_RADIOS = 2; + localparam NUM_CHANNELS_PER_RADIO = 1; + localparam NUM_DBOARDS = 2; + localparam NUM_CHANNELS = NUM_RADIOS * NUM_CHANNELS_PER_RADIO; + localparam CHANNEL_WIDTH = 32; + + + // Internal connections to PS + // HP0 -- High Performance port 0, FPGA is the master + wire [5:0] S_AXI_HP0_AWID; + wire [31:0] S_AXI_HP0_AWADDR; + wire [2:0] S_AXI_HP0_AWPROT; + wire S_AXI_HP0_AWVALID; + wire S_AXI_HP0_AWREADY; + wire [63:0] S_AXI_HP0_WDATA; + wire [7:0] S_AXI_HP0_WSTRB; + wire S_AXI_HP0_WVALID; + wire S_AXI_HP0_WREADY; + wire [1:0] S_AXI_HP0_BRESP; + wire S_AXI_HP0_BVALID; + wire S_AXI_HP0_BREADY; + wire [5:0] S_AXI_HP0_ARID; + wire [31:0] S_AXI_HP0_ARADDR; + wire [2:0] S_AXI_HP0_ARPROT; + wire S_AXI_HP0_ARVALID; + wire S_AXI_HP0_ARREADY; + wire [63:0] S_AXI_HP0_RDATA; + wire [1:0] S_AXI_HP0_RRESP; + wire S_AXI_HP0_RVALID; + wire S_AXI_HP0_RREADY; + wire S_AXI_HP0_RLAST; + wire [3:0] S_AXI_HP0_ARCACHE; + wire [7:0] S_AXI_HP0_AWLEN; + wire [2:0] S_AXI_HP0_AWSIZE; + wire [1:0] S_AXI_HP0_AWBURST; + wire [3:0] S_AXI_HP0_AWCACHE; + wire S_AXI_HP0_WLAST; + wire [7:0] S_AXI_HP0_ARLEN; + wire [1:0] S_AXI_HP0_ARBURST; + wire [2:0] S_AXI_HP0_ARSIZE; + + // GP0 -- General Purpose port 0, FPGA is the master + wire [4:0] S_AXI_GP0_AWID; + wire [31:0] S_AXI_GP0_AWADDR; + wire [2:0] S_AXI_GP0_AWPROT; + wire S_AXI_GP0_AWVALID; + wire S_AXI_GP0_AWREADY; + wire [31:0] S_AXI_GP0_WDATA; + wire [3:0] S_AXI_GP0_WSTRB; + wire S_AXI_GP0_WVALID; + wire S_AXI_GP0_WREADY; + wire [1:0] S_AXI_GP0_BRESP; + wire S_AXI_GP0_BVALID; + wire S_AXI_GP0_BREADY; + wire [4:0] S_AXI_GP0_ARID; + wire [31:0] S_AXI_GP0_ARADDR; + wire [2:0] S_AXI_GP0_ARPROT; + wire S_AXI_GP0_ARVALID; + wire S_AXI_GP0_ARREADY; + wire [31:0] S_AXI_GP0_RDATA; + wire [1:0] S_AXI_GP0_RRESP; + wire S_AXI_GP0_RVALID; + wire S_AXI_GP0_RREADY; + wire S_AXI_GP0_RLAST; + wire [3:0] S_AXI_GP0_ARCACHE; + wire [7:0] S_AXI_GP0_AWLEN; + wire [2:0] S_AXI_GP0_AWSIZE; + wire [1:0] S_AXI_GP0_AWBURST; + wire [3:0] S_AXI_GP0_AWCACHE; + wire S_AXI_GP0_WLAST; + wire [7:0] S_AXI_GP0_ARLEN; + wire [1:0] S_AXI_GP0_ARBURST; + wire [2:0] S_AXI_GP0_ARSIZE; + + // HP1 -- High Performance port 1, FPGA is the master + wire [5:0] S_AXI_HP1_AWID; + wire [31:0] S_AXI_HP1_AWADDR; + wire [2:0] S_AXI_HP1_AWPROT; + wire S_AXI_HP1_AWVALID; + wire S_AXI_HP1_AWREADY; + wire [63:0] S_AXI_HP1_WDATA; + wire [7:0] S_AXI_HP1_WSTRB; + wire S_AXI_HP1_WVALID; + wire S_AXI_HP1_WREADY; + wire [1:0] S_AXI_HP1_BRESP; + wire S_AXI_HP1_BVALID; + wire S_AXI_HP1_BREADY; + wire [5:0] S_AXI_HP1_ARID; + wire [31:0] S_AXI_HP1_ARADDR; + wire [2:0] S_AXI_HP1_ARPROT; + wire S_AXI_HP1_ARVALID; + wire S_AXI_HP1_ARREADY; + wire [63:0] S_AXI_HP1_RDATA; + wire [1:0] S_AXI_HP1_RRESP; + wire S_AXI_HP1_RVALID; + wire S_AXI_HP1_RREADY; + wire S_AXI_HP1_RLAST; + wire [3:0] S_AXI_HP1_ARCACHE; + wire [7:0] S_AXI_HP1_AWLEN; + wire [2:0] S_AXI_HP1_AWSIZE; + wire [1:0] S_AXI_HP1_AWBURST; + wire [3:0] S_AXI_HP1_AWCACHE; + wire S_AXI_HP1_WLAST; + wire [7:0] S_AXI_HP1_ARLEN; + wire [1:0] S_AXI_HP1_ARBURST; + wire [2:0] S_AXI_HP1_ARSIZE; + + // GP1 -- General Purpose port 1, FPGA is the master + wire [4:0] S_AXI_GP1_AWID; + wire [31:0] S_AXI_GP1_AWADDR; + wire [2:0] S_AXI_GP1_AWPROT; + wire S_AXI_GP1_AWVALID; + wire S_AXI_GP1_AWREADY; + wire [31:0] S_AXI_GP1_WDATA; + wire [3:0] S_AXI_GP1_WSTRB; + wire S_AXI_GP1_WVALID; + wire S_AXI_GP1_WREADY; + wire [1:0] S_AXI_GP1_BRESP; + wire S_AXI_GP1_BVALID; + wire S_AXI_GP1_BREADY; + wire [4:0] S_AXI_GP1_ARID; + wire [31:0] S_AXI_GP1_ARADDR; + wire [2:0] S_AXI_GP1_ARPROT; + wire S_AXI_GP1_ARVALID; + wire S_AXI_GP1_ARREADY; + wire [31:0] S_AXI_GP1_RDATA; + wire [1:0] S_AXI_GP1_RRESP; + wire S_AXI_GP1_RVALID; + wire S_AXI_GP1_RREADY; + wire S_AXI_GP1_RLAST; + wire [3:0] S_AXI_GP1_ARCACHE; + wire [7:0] S_AXI_GP1_AWLEN; + wire [2:0] S_AXI_GP1_AWSIZE; + wire [1:0] S_AXI_GP1_AWBURST; + wire [3:0] S_AXI_GP1_AWCACHE; + wire S_AXI_GP1_WLAST; + wire [7:0] S_AXI_GP1_ARLEN; + wire [1:0] S_AXI_GP1_ARBURST; + wire [2:0] S_AXI_GP1_ARSIZE; + + // GP0 -- General Purpose port 0, FPGA is the slave + wire M_AXI_GP0_ARVALID; + wire M_AXI_GP0_AWVALID; + wire M_AXI_GP0_BREADY; + wire M_AXI_GP0_RREADY; + wire M_AXI_GP0_WVALID; + wire [11:0] M_AXI_GP0_ARID; + wire [11:0] M_AXI_GP0_AWID; + wire [11:0] M_AXI_GP0_WID; + wire [31:0] M_AXI_GP0_ARADDR; + wire [31:0] M_AXI_GP0_AWADDR; + wire [31:0] M_AXI_GP0_WDATA; + wire [3:0] M_AXI_GP0_WSTRB; + wire M_AXI_GP0_ARREADY; + wire M_AXI_GP0_AWREADY; + wire M_AXI_GP0_BVALID; + wire M_AXI_GP0_RLAST; + wire M_AXI_GP0_RVALID; + wire M_AXI_GP0_WREADY; + wire [1:0] M_AXI_GP0_BRESP; + wire [1:0] M_AXI_GP0_RRESP; + wire [31:0] M_AXI_GP0_RDATA; + + wire M_AXI_ETH_DMA0_ARVALID; + wire M_AXI_ETH_DMA0_AWVALID; + wire M_AXI_ETH_DMA0_BREADY; + wire M_AXI_ETH_DMA0_RREADY; + wire M_AXI_ETH_DMA0_WVALID; + wire [11:0] M_AXI_ETH_DMA0_ARID; + wire [11:0] M_AXI_ETH_DMA0_AWID; + wire [11:0] M_AXI_ETH_DMA0_WID; + wire [31:0] M_AXI_ETH_DMA0_ARADDR; + wire [31:0] M_AXI_ETH_DMA0_AWADDR; + wire [31:0] M_AXI_ETH_DMA0_WDATA; + wire [3:0] M_AXI_ETH_DMA0_WSTRB; + wire M_AXI_ETH_DMA0_ARREADY; + wire M_AXI_ETH_DMA0_AWREADY; + wire M_AXI_ETH_DMA0_BVALID; + wire M_AXI_ETH_DMA0_RLAST; + wire M_AXI_ETH_DMA0_RVALID; + wire M_AXI_ETH_DMA0_WREADY; + wire [1:0] M_AXI_ETH_DMA0_BRESP; + wire [1:0] M_AXI_ETH_DMA0_RRESP; + wire [31:0] M_AXI_ETH_DMA0_RDATA; + + wire M_AXI_NET0_ARVALID; + wire M_AXI_NET0_AWVALID; + wire M_AXI_NET0_BREADY; + wire M_AXI_NET0_RREADY; + wire M_AXI_NET0_WVALID; + wire [11:0] M_AXI_NET0_ARID; + wire [11:0] M_AXI_NET0_AWID; + wire [11:0] M_AXI_NET0_WID; + wire [31:0] M_AXI_NET0_ARADDR; + wire [31:0] M_AXI_NET0_AWADDR; + wire [31:0] M_AXI_NET0_WDATA; + wire [3:0] M_AXI_NET0_WSTRB; + wire M_AXI_NET0_ARREADY; + wire M_AXI_NET0_AWREADY; + wire M_AXI_NET0_BVALID; + wire M_AXI_NET0_RLAST; + wire M_AXI_NET0_RVALID; + wire M_AXI_NET0_WREADY; + wire [1:0] M_AXI_NET0_BRESP; + wire [1:0] M_AXI_NET0_RRESP; + wire [31:0] M_AXI_NET0_RDATA; + + wire M_AXI_ETH_DMA1_ARVALID; + wire M_AXI_ETH_DMA1_AWVALID; + wire M_AXI_ETH_DMA1_BREADY; + wire M_AXI_ETH_DMA1_RREADY; + wire M_AXI_ETH_DMA1_WVALID; + wire [11:0] M_AXI_ETH_DMA1_ARID; + wire [11:0] M_AXI_ETH_DMA1_AWID; + wire [11:0] M_AXI_ETH_DMA1_WID; + wire [31:0] M_AXI_ETH_DMA1_ARADDR; + wire [31:0] M_AXI_ETH_DMA1_AWADDR; + wire [31:0] M_AXI_ETH_DMA1_WDATA; + wire [3:0] M_AXI_ETH_DMA1_WSTRB; + wire M_AXI_ETH_DMA1_ARREADY; + wire M_AXI_ETH_DMA1_AWREADY; + wire M_AXI_ETH_DMA1_BVALID; + wire M_AXI_ETH_DMA1_RLAST; + wire M_AXI_ETH_DMA1_RVALID; + wire M_AXI_ETH_DMA1_WREADY; + wire [1:0] M_AXI_ETH_DMA1_BRESP; + wire [1:0] M_AXI_ETH_DMA1_RRESP; + wire [31:0] M_AXI_ETH_DMA1_RDATA; + + wire M_AXI_NET1_ARVALID; + wire M_AXI_NET1_AWVALID; + wire M_AXI_NET1_BREADY; + wire M_AXI_NET1_RREADY; + wire M_AXI_NET1_WVALID; + wire [11:0] M_AXI_NET1_ARID; + wire [11:0] M_AXI_NET1_AWID; + wire [11:0] M_AXI_NET1_WID; + wire [31:0] M_AXI_NET1_ARADDR; + wire [31:0] M_AXI_NET1_AWADDR; + wire [31:0] M_AXI_NET1_WDATA; + wire [3:0] M_AXI_NET1_WSTRB; + wire M_AXI_NET1_ARREADY; + wire M_AXI_NET1_AWREADY; + wire M_AXI_NET1_BVALID; + wire M_AXI_NET1_RLAST; + wire M_AXI_NET1_RVALID; + wire M_AXI_NET1_WREADY; + wire [1:0] M_AXI_NET1_BRESP; + wire [1:0] M_AXI_NET1_RRESP; + wire [31:0] M_AXI_NET1_RDATA; + + wire M_AXI_NET2_ARVALID; + wire M_AXI_NET2_AWVALID; + wire M_AXI_NET2_BREADY; + wire M_AXI_NET2_RREADY; + wire M_AXI_NET2_WVALID; + wire [11:0] M_AXI_NET2_ARID; + wire [11:0] M_AXI_NET2_AWID; + wire [11:0] M_AXI_NET2_WID; + wire [31:0] M_AXI_NET2_ARADDR; + wire [31:0] M_AXI_NET2_AWADDR; + wire [31:0] M_AXI_NET2_WDATA; + wire [3:0] M_AXI_NET2_WSTRB; + wire M_AXI_NET2_ARREADY; + wire M_AXI_NET2_AWREADY; + wire M_AXI_NET2_BVALID; + wire M_AXI_NET2_RLAST; + wire M_AXI_NET2_RVALID; + wire M_AXI_NET2_WREADY; + wire [1:0] M_AXI_NET2_BRESP; + wire [1:0] M_AXI_NET2_RRESP; + wire [31:0] M_AXI_NET2_RDATA; + + wire M_AXI_XBAR_ARVALID; + wire M_AXI_XBAR_AWVALID; + wire M_AXI_XBAR_BREADY; + wire M_AXI_XBAR_RREADY; + wire M_AXI_XBAR_WVALID; + wire [11:0] M_AXI_XBAR_ARID; + wire [11:0] M_AXI_XBAR_AWID; + wire [11:0] M_AXI_XBAR_WID; + wire [31:0] M_AXI_XBAR_ARADDR; + wire [31:0] M_AXI_XBAR_AWADDR; + wire [31:0] M_AXI_XBAR_WDATA; + wire [3:0] M_AXI_XBAR_WSTRB; + wire M_AXI_XBAR_ARREADY; + wire M_AXI_XBAR_AWREADY; + wire M_AXI_XBAR_BVALID; + wire M_AXI_XBAR_RLAST; + wire M_AXI_XBAR_RVALID; + wire M_AXI_XBAR_WREADY; + wire [1:0] M_AXI_XBAR_BRESP; + wire [1:0] M_AXI_XBAR_RRESP; + wire [31:0] M_AXI_XBAR_RDATA; + + wire M_AXI_JESD0_ARVALID; + wire M_AXI_JESD0_AWVALID; + wire M_AXI_JESD0_BREADY; + wire M_AXI_JESD0_RREADY; + wire M_AXI_JESD0_WVALID; + wire [11:0] M_AXI_JESD0_ARID; + wire [11:0] M_AXI_JESD0_AWID; + wire [11:0] M_AXI_JESD0_WID; + wire [31:0] M_AXI_JESD0_ARADDR; + wire [31:0] M_AXI_JESD0_AWADDR; + wire [31:0] M_AXI_JESD0_WDATA; + wire [3:0] M_AXI_JESD0_WSTRB; + wire M_AXI_JESD0_ARREADY; + wire M_AXI_JESD0_AWREADY; + wire M_AXI_JESD0_BVALID; + wire M_AXI_JESD0_RLAST; + wire M_AXI_JESD0_RVALID; + wire M_AXI_JESD0_WREADY; + wire [1:0] M_AXI_JESD0_BRESP; + wire [1:0] M_AXI_JESD0_RRESP; + wire [31:0] M_AXI_JESD0_RDATA; + + wire M_AXI_JESD1_ARVALID; + wire M_AXI_JESD1_AWVALID; + wire M_AXI_JESD1_BREADY; + wire M_AXI_JESD1_RREADY; + wire M_AXI_JESD1_WVALID; + wire [11:0] M_AXI_JESD1_ARID; + wire [11:0] M_AXI_JESD1_AWID; + wire [11:0] M_AXI_JESD1_WID; + wire [31:0] M_AXI_JESD1_ARADDR; + wire [31:0] M_AXI_JESD1_AWADDR; + wire [31:0] M_AXI_JESD1_WDATA; + wire [3:0] M_AXI_JESD1_WSTRB; + wire M_AXI_JESD1_ARREADY; + wire M_AXI_JESD1_AWREADY; + wire M_AXI_JESD1_BVALID; + wire M_AXI_JESD1_RLAST; + wire M_AXI_JESD1_RVALID; + wire M_AXI_JESD1_WREADY; + wire [1:0] M_AXI_JESD1_BRESP; + wire [1:0] M_AXI_JESD1_RRESP; + wire [31:0] M_AXI_JESD1_RDATA; + + // White Rabbit + wire wr_uart_txd; + wire wr_uart_rxd; + wire pps_wr_refclk; + wire wr_ref_clk; + + // AXI bus from PS to WR Core + wire m_axi_wr_clk; + wire [31:0] m_axi_wr_araddr; + wire [0:0] m_axi_wr_arready; + wire [0:0] m_axi_wr_arvalid; + wire [31:0] m_axi_wr_awaddr; + wire [0:0] m_axi_wr_awready; + wire [0:0] m_axi_wr_awvalid; + wire [0:0] m_axi_wr_bready; + wire [1:0] m_axi_wr_bresp; + wire [0:0] m_axi_wr_bvalid; + wire [31:0] m_axi_wr_rdata; + wire [0:0] m_axi_wr_rready; + wire [1:0] m_axi_wr_rresp; + wire [0:0] m_axi_wr_rvalid; + wire [31:0] m_axi_wr_wdata; + wire [0:0] m_axi_wr_wready; + wire [3:0] m_axi_wr_wstrb; + wire [0:0] m_axi_wr_wvalid; + + wire [63:0] ps_gpio_out; + wire [63:0] ps_gpio_in; + wire [63:0] ps_gpio_tri; + + wire [15:0] IRQ_F2P; + wire FCLK_CLK0; + wire FCLK_CLK1; + wire FCLK_CLK2; + wire FCLK_CLK3; + wire clk100; + wire clk40; + wire meas_clk_ref; + wire bus_clk; + wire gige_refclk; + wire gige_refclk_bufg; + wire xgige_refclk; + wire xgige_clk156; + wire xgige_dclk; + + wire global_rst; + wire radio_rst; + wire bus_rst; + wire FCLK_RESET0_N; + wire clk40_rst; + wire clk40_rstn; + + wire [1:0] USB0_PORT_INDCTL; + wire USB0_VBUS_PWRSELECT; + wire USB0_VBUS_PWRFAULT; + + wire ref_clk; + wire wr_refclk_buf; + wire netclk_buf; + wire meas_clk; + wire ddr3_dma_clk; + wire meas_clk_reset; + wire meas_clk_locked; + wire enable_ref_clk_async; + wire pps_radioclk1x_iob; + wire pps_radioclk1x; + wire [3:0] pps_select; + wire pps_out_enb; + wire [1:0] pps_select_sfp; + wire pps_refclk; + wire export_pps_radioclk; + wire radio_clk; + wire radio_clkB; + wire radio_clk_2x; + wire radio_clk_2xB; + + wire qsfp_sda_i; + wire qsfp_sda_o; + wire qsfp_sda_t; + wire qsfp_scl_i; + wire qsfp_scl_o; + wire qsfp_scl_t; + + ///////////////////////////////////////////////////////////////////// + // + // Resets + // + ////////////////////////////////////////////////////////////////////// + + // Global synchronous reset, on the bus_clk domain. De-asserts after 85 + // bus_clk cycles. Asserted by default. + por_gen por_gen(.clk(bus_clk), .reset_out(global_rst)); + + // Synchronous reset for the radio_clk domain, based on the global_rst. + reset_sync radio_reset_gen ( + .clk(radio_clk), + .reset_in(global_rst), + .reset_out(radio_rst) + ); + + // Synchronous reset for the bus_clk domain, based on the global_rst. + reset_sync bus_reset_gen ( + .clk(bus_clk), + .reset_in(global_rst), + .reset_out(bus_rst) + ); + + + // PS-based Resets // + // + // Synchronous reset for the clk40 domain. This is derived from the PS reset 0. + reset_sync clk40_reset_gen ( + .clk(clk40), + .reset_in(~FCLK_RESET0_N), + .reset_out(clk40_rst) + ); + // Invert for various modules. + assign clk40_rstn = ~clk40_rst; + + + ///////////////////////////////////////////////////////////////////// + // + // Timing + // + ////////////////////////////////////////////////////////////////////// + + // Clocks from the PS + // + // These clocks appear to have BUFGs already instantiated by the ip generator. + // Simply rename them here for clarity. + // FCLK_CLK0 : 100 MHz + // FCLK_CLK1 : 40 MHz + // FCLK_CLK2 : 166.6667 MHz + // FCLK_CLK3 : 200 MHz + assign clk100 = FCLK_CLK0; + assign clk40 = FCLK_CLK1; + assign meas_clk_ref = FCLK_CLK2; + assign bus_clk = FCLK_CLK3; + + //If bus_clk freq ever changes, update this paramter accordingly. + localparam BUS_CLK_RATE = 32'd200000000; //200 MHz bus_clk rate. + + n3xx_clocking n3xx_clocking_i ( + .enable_ref_clk_async(enable_ref_clk_async), + .FPGA_REFCLK_P(FPGA_REFCLK_P), + .FPGA_REFCLK_N(FPGA_REFCLK_N), + .ref_clk(ref_clk), + .WB_20MHz_P(WB_20MHZ_P), + .WB_20MHz_N(WB_20MHZ_N), + .wr_refclk_buf(wr_refclk_buf), + .NETCLK_REF_P(NETCLK_REF_P), + .NETCLK_REF_N(NETCLK_REF_N), + .netclk_buf(netclk_buf), + .NETCLK_P(NETCLK_P), + .NETCLK_N(NETCLK_N), + .gige_refclk_buf(gige_refclk), + .MGT156MHZ_CLK1_P(MGT156MHZ_CLK1_P), + .MGT156MHZ_CLK1_N(MGT156MHZ_CLK1_N), + .xgige_refclk_buf(xgige_refclk), + .misc_clks_ref(meas_clk_ref), + .meas_clk(meas_clk), + .ddr3_dma_clk(ddr3_dma_clk), + .misc_clks_reset(meas_clk_reset), + .misc_clks_locked(meas_clk_locked), + .ext_pps_from_pin(REF_1PPS_IN), + .gps_pps_from_pin(GPS_1PPS), + .pps_select(pps_select), + .pps_refclk(pps_refclk) + ); + + // Drive the rear panel connector with another controllable copy of the post-TDC PPS + // that SW can enable/disable. The user is free to hack this to be whatever + // they desire. Flop the PPS signal one more time in order that it can be packed into + // an IOB. This extra flop stage matches the additional flop inside DbCore to allow + // pps_radioclk1x and pps_out_radioclk to be in sync with one another. + synchronizer #( + .FALSE_PATH_TO_IN(0) + ) pps_export_dsync ( + .clk(radio_clk), .rst(1'b0), .in(pps_out_enb), .out(export_pps_radioclk) + ); + + // The radio_clk rate is between [122.88M, 250M] for all known N3xx variants, + // resulting in approximately [8ns, 4ns] periods. To pulse-extend the PPS output, + // we create a 25 bit-wide counter, creating ~[.262s, .131s] long output high pulses, + // variable depending on our radio_clk rate. Create two of the same output signal + // in order that the PPS_OUT gets packed into an IOB for tight timing. + reg [24:0] pps_out_count = 'b0; + reg pps_out_radioclk = 1'b0; + reg pps_led_radioclk = 1'b0; + + always @(posedge radio_clk) begin + if (export_pps_radioclk) begin + if (pps_radioclk1x_iob) begin + pps_out_radioclk <= 1'b1; + pps_led_radioclk <= 1'b1; + pps_out_count <= {25{1'b1}}; + end else begin + if (pps_out_count > 0) begin + pps_out_count <= pps_out_count - 1'b1; + end else begin + pps_out_radioclk <= 1'b0; + pps_led_radioclk <= 1'b0; + end + end + end else begin + pps_out_radioclk <= 1'b0; + pps_led_radioclk <= 1'b0; + end + end + // Local to output. + assign REF_1PPS_OUT = pps_out_radioclk; + assign PANEL_LED_PPS = pps_led_radioclk; + + ///////////////////////////////////////////////////////////////////// + // + // SFP, QSFP and NPIO MGT Connections + // + ////////////////////////////////////////////////////////////////////// + wire reg_wr_req_npio; + wire [REG_AWIDTH-1:0] reg_wr_addr_npio; + wire [REG_DWIDTH-1:0] reg_wr_data_npio; + wire reg_rd_req_npio; + wire [REG_AWIDTH-1:0] reg_rd_addr_npio; + wire reg_rd_resp_npio, reg_rd_resp_npio0, reg_rd_resp_npio1; + wire [REG_DWIDTH-1:0] reg_rd_data_npio, reg_rd_data_npio0, reg_rd_data_npio1; + + localparam NPIO_REG_BASE = 14'h0200; + + regport_resp_mux #( + .WIDTH (REG_DWIDTH), + .NUM_SLAVES (2) + ) npio_resp_mux_i( + .clk(bus_clk), .reset(bus_rst), + .sla_rd_resp({reg_rd_resp_npio0, reg_rd_resp_npio1}), + .sla_rd_data({reg_rd_data_npio0, reg_rd_data_npio1}), + .mst_rd_resp(reg_rd_resp_npio), .mst_rd_data(reg_rd_data_npio) + ); + + //-------------------------------------------------------------- + // SFP/MGT Reference Clocks + //-------------------------------------------------------------- + + // We support the HG, XG, XA, AA targets, all of which require + // the 156.25MHz reference clock. Instantiate it here. + ten_gige_phy_clk_gen xgige_clk_gen_i ( + .refclk_ibuf(xgige_refclk), + .clk156(xgige_clk156), + .dclk(xgige_dclk) + ); + + wire qpllreset; + wire qpllreset_sfp0, qpllreset_sfp1, qpllreset_npio0, qpllreset_npio1; + wire qplllock; + wire qplloutclk; + wire qplloutrefclk; + + // We reuse this GT_COMMON wrapper for both ethernet and Aurora because + // the behavior is identical + ten_gig_eth_pcs_pma_gt_common # ( + .WRAPPER_SIM_GTRESET_SPEEDUP("TRUE") //Does not affect hardware + ) ten_gig_eth_pcs_pma_gt_common_block ( + .refclk(xgige_refclk), + .qpllreset(qpllreset), //from 2nd sfp + .qplllock(qplllock), + .qplloutclk(qplloutclk), + .qplloutrefclk(qplloutrefclk), + .qpllrefclksel(3'b101 /*GTSOUTHREFCLK0*/) + ); + + // The quad's QPLL should reset if any of the channels request it + // This should never really happen because we are not changing the reference clock + // source for the QPLL. + assign qpllreset = qpllreset_sfp0 | qpllreset_sfp1 | qpllreset_npio0 | qpllreset_npio1; + + // Use the 156.25MHz reference clock for Aurora + wire aurora_refclk = xgige_refclk; + wire aurora_clk156 = xgige_clk156; + wire aurora_init_clk = xgige_dclk; + + // White Rabbit and 1GbE both use the same clocking +`ifdef SFP0_1GBE + `define SFP0_WR_1GBE +`endif +`ifdef SFP0_WR + `define SFP0_WR_1GBE +`endif + +`ifdef SFP0_WR_1GBE + // HG and WX targets require the 1GbE clock support + BUFG bufg_gige_refclk_i ( + .I(gige_refclk), + .O(gige_refclk_bufg) + ); + assign SFP_0_RS0 = 1'b0; + assign SFP_0_RS1 = 1'b0; +`else + assign SFP_0_RS0 = 1'b1; + assign SFP_0_RS1 = 1'b1; +`endif + + // SFP 1 is always set to run at ~10Gbps rates. + assign SFP_1_RS0 = 1'b1; + assign SFP_1_RS1 = 1'b1; + + // SFP port specific reference clocks + wire sfp0_gt_refclk, sfp1_gt_refclk; + wire sfp0_gb_refclk, sfp1_gb_refclk; + wire sfp0_misc_clk, sfp1_misc_clk; + +`ifdef SFP0_10GBE + assign sfp0_gt_refclk = xgige_refclk; + assign sfp0_gb_refclk = xgige_clk156; + assign sfp0_misc_clk = xgige_dclk; +`endif +`ifdef SFP0_WR_1GBE + assign sfp0_gt_refclk = gige_refclk; + assign sfp0_gb_refclk = gige_refclk_bufg; + assign sfp0_misc_clk = gige_refclk_bufg; +`endif +`ifdef SFP0_AURORA + assign sfp0_gt_refclk = aurora_refclk; + assign sfp0_gb_refclk = aurora_clk156; + assign sfp0_misc_clk = aurora_init_clk; +`endif + +`ifdef SFP1_10GBE + assign sfp1_gt_refclk = xgige_refclk; + assign sfp1_gb_refclk = xgige_clk156; + assign sfp1_misc_clk = xgige_dclk; +`endif +`ifdef SFP1_1GBE + assign sfp1_gt_refclk = gige_refclk; + assign sfp1_gb_refclk = gige_refclk_bufg; + assign sfp1_misc_clk = gige_refclk_bufg; +`endif +`ifdef SFP1_AURORA + assign sfp1_gt_refclk = aurora_refclk; + assign sfp1_gb_refclk = aurora_clk156; + assign sfp1_misc_clk = aurora_init_clk; +`endif + + // Instantiate Aurora MMCM if either of the SFPs + // or NPIOs are Aurora + wire au_tx_clk; + wire au_mmcm_reset; + wire au_user_clk; + wire au_sync_clk; + wire au_mmcm_locked; + wire sfp0_tx_out_clk, sfp1_tx_out_clk; + wire sfp0_gt_pll_lock, sfp1_gt_pll_lock; + wire npio0_tx_out_clk, npio1_tx_out_clk; + wire npio0_gt_pll_lock, npio1_gt_pll_lock; + + //NOTE: need to declare one of these defines in order to enable Aurora on + //any SFP or NPIO lane. +`ifdef SFP1_AURORA + `define SFP_AU_MMCM + assign au_tx_clk = sfp1_tx_out_clk; + assign au_mmcm_reset = ~sfp1_gt_pll_lock; +`elsif NPIO0 + `define SFP_AU_MMCM + assign au_tx_clk = npio0_tx_out_clk; + assign au_mmcm_reset = ~npio0_gt_pll_lock; +`elsif NPIO1 + `define SFP_AU_MMCM + assign au_tx_clk = npio1_tx_out_clk; + assign au_mmcm_reset = ~npio1_gt_pll_lock; +`endif + + +`ifdef SFP_AU_MMCM + aurora_phy_mmcm au_phy_mmcm_i ( + .aurora_tx_clk_unbuf(au_tx_clk), + .mmcm_reset(au_mmcm_reset), + .user_clk(au_user_clk), + .sync_clk(au_sync_clk), + .mmcm_locked(au_mmcm_locked) + ); +`else + assign au_user_clk = 1'b0; + assign au_sync_clk = 1'b0; + assign au_mmcm_locked = 1'b0; +`endif + + //-------------------------------------------------------------- + // NPIO-QSFP MGT Lanes (Example loopback config) + //-------------------------------------------------------------- + +`ifdef QSFP_LANES + localparam NUM_QSFP_LANES = `QSFP_LANES; + + // QSFP wires to the ARM core and the crossbar + // These will only be connected if QSFP is 2x10 GbE + wire [NUM_QSFP_LANES*64-1:0] arm_eth_qsfp_tx_tdata_b; + wire [NUM_QSFP_LANES-1:0] arm_eth_qsfp_tx_tvalid_b; + wire [NUM_QSFP_LANES-1:0] arm_eth_qsfp_tx_tlast_b; + wire [NUM_QSFP_LANES-1:0] arm_eth_qsfp_tx_tready_b; + wire [NUM_QSFP_LANES*4-1:0] arm_eth_qsfp_tx_tuser_b; + wire [NUM_QSFP_LANES*8-1:0] arm_eth_qsfp_tx_tkeep_b; + + wire [NUM_QSFP_LANES*64-1:0] arm_eth_qsfp_rx_tdata_b; + wire [NUM_QSFP_LANES-1:0] arm_eth_qsfp_rx_tvalid_b; + wire [NUM_QSFP_LANES-1:0] arm_eth_qsfp_rx_tlast_b; + wire [NUM_QSFP_LANES-1:0] arm_eth_qsfp_rx_tready_b; + wire [NUM_QSFP_LANES*4-1:0] arm_eth_qsfp_rx_tuser_b; + wire [NUM_QSFP_LANES*8-1:0] arm_eth_qsfp_rx_tkeep_b; + + wire [NUM_QSFP_LANES*64-1:0] v2e_qsfp_tdata; + wire [NUM_QSFP_LANES-1:0] v2e_qsfp_tlast; + wire [NUM_QSFP_LANES-1:0] v2e_qsfp_tvalid; + wire [NUM_QSFP_LANES-1:0] v2e_qsfp_tready; + + wire [NUM_QSFP_LANES*64-1:0] e2v_qsfp_tdata; + wire [NUM_QSFP_LANES-1:0] e2v_qsfp_tlast; + wire [NUM_QSFP_LANES-1:0] e2v_qsfp_tvalid; + wire [NUM_QSFP_LANES-1:0] e2v_qsfp_tready; + + wire [NUM_QSFP_LANES-1:0] qsfp_link_up; + + // QSFP quad's specific reference clocks + wire qsfp_gt_refclk; + wire qsfp_gb_refclk; + wire qsfp_misc_clk; + + wire qsfp_qplloutclk; + wire qsfp_qplloutrefclk; + wire qsfp_qplllock; + wire qsfp_qpllreset; + + wire qsfp_gt_tx_out_clk; + wire qsfp_gt_pll_lock; + + wire qsfp_au_user_clk; + wire qsfp_au_sync_clk; + wire qsfp_au_mmcm_locked; + + +`ifdef QSFP_10GBE + assign qsfp_gt_refclk = xgige_refclk; + assign qsfp_gb_refclk = xgige_clk156; + assign qsfp_misc_clk = xgige_dclk; +`endif +`ifdef QSFP_AURORA + assign qsfp_gt_refclk = aurora_refclk; + assign qsfp_gb_refclk = aurora_clk156; + assign qsfp_misc_clk = aurora_init_clk; +`endif + + // We reuse this GT_COMMON wrapper for both ethernet and Aurora because + // the behavior is identical + ten_gig_eth_pcs_pma_gt_common # ( + .WRAPPER_SIM_GTRESET_SPEEDUP("TRUE") //Does not affect hardware + ) qsfp_gt_common_block ( + .refclk(xgige_refclk), + .qpllreset(qsfp_qpllreset), + .qplllock(qsfp_qplllock), + .qplloutclk(qsfp_qplloutclk), + .qplloutrefclk(qsfp_qplloutrefclk), + .qpllrefclksel(3'b001 /*GTREFCLK0*/) + ); + + `ifdef QSFP_AURORA + aurora_phy_mmcm aurora_phy_mmcm ( + .aurora_tx_clk_unbuf(qsfp_gt_tx_out_clk), + .mmcm_reset(~qsfp_gt_pll_lock), + .user_clk(qsfp_au_user_clk), + .sync_clk(qsfp_au_sync_clk), + .mmcm_locked(qsfp_au_mmcm_locked) + ); + `else + assign qsfp_au_user_clk = 1'b0; + assign qsfp_au_sync_clk = 1'b0; + assign qsfp_au_mmcm_locked = 1'b0; + `endif + + n3xx_mgt_channel_wrapper #( + `ifdef QSFP_10GBE + .PROTOCOL ("10GbE"), + .MDIO_EN (1'b1), + .MDIO_PHYADDR (5'd4), + `elsif QSFP_AURORA + .PROTOCOL ("Aurora"), + .MDIO_EN (1'b0), + `endif + .LANES (NUM_QSFP_LANES), + .GT_COMMON (1), + .PORTNUM_BASE (4), + .REG_DWIDTH (REG_DWIDTH), + .REG_AWIDTH (QSFP_REG_AWIDTH) + ) qsfp_wrapper_i ( + .areset (global_rst), + .gt_refclk (qsfp_gt_refclk), + .gb_refclk (qsfp_gb_refclk), + .misc_clk (qsfp_misc_clk), + .user_clk (qsfp_au_user_clk), + .sync_clk (qsfp_au_sync_clk), + .gt_tx_out_clk_unbuf(qsfp_gt_tx_out_clk), + + .bus_clk (bus_clk), + .bus_rst (bus_rst), + + // GT Common + .qpllrefclklost (), + .qplllock (qsfp_qplllock), + .qplloutclk (qsfp_qplloutclk), + .qplloutrefclk (qsfp_qplloutrefclk), + .qpllreset (qsfp_qpllreset), + + // Aurora MMCM + .mmcm_locked (qsfp_au_mmcm_locked), + .gt_pll_lock (qsfp_gt_pll_lock), + + .txp (QSFP_TX_P), + .txn (QSFP_TX_N), + .rxp (QSFP_RX_P), + .rxn (QSFP_RX_N), + + .mod_present_n (QSFP_PRESENT_B), + .mod_rxlos (1'b0), + .mod_tx_fault (1'b0), + .mod_tx_disable (), + .mod_int_n (QSFP_INT_B), + .mod_reset_n (QSFP_RESET_B), + .mod_lpmode (QSFP_LPMODE), + .mod_sel_n (QSFP_MODSEL_B), + + // Clock and reset + .s_axi_aclk (clk40), + .s_axi_aresetn (clk40_rstn), + // AXI4-Lite: Write address port (domain: s_axi_aclk) + .s_axi_awaddr (M_AXI_NET2_AWADDR[QSFP_REG_AWIDTH-1:0]), + .s_axi_awvalid (M_AXI_NET2_AWVALID), + .s_axi_awready (M_AXI_NET2_AWREADY), + // AXI4-Lite: Write data port (domain: s_axi_aclk) + .s_axi_wdata (M_AXI_NET2_WDATA), + .s_axi_wstrb (M_AXI_NET2_WSTRB), + .s_axi_wvalid (M_AXI_NET2_WVALID), + .s_axi_wready (M_AXI_NET2_WREADY), + // AXI4-Lite: Write response port (domain: s_axi_aclk) + .s_axi_bresp (M_AXI_NET2_BRESP), + .s_axi_bvalid (M_AXI_NET2_BVALID), + .s_axi_bready (M_AXI_NET2_BREADY), + // AXI4-Lite: Read address port (domain: s_axi_aclk) + .s_axi_araddr (M_AXI_NET2_ARADDR[QSFP_REG_AWIDTH-1:0]), + .s_axi_arvalid (M_AXI_NET2_ARVALID), + .s_axi_arready (M_AXI_NET2_ARREADY), + // AXI4-Lite: Read data port (domain: s_axi_aclk) + .s_axi_rdata (M_AXI_NET2_RDATA), + .s_axi_rresp (M_AXI_NET2_RRESP), + .s_axi_rvalid (M_AXI_NET2_RVALID), + .s_axi_rready (M_AXI_NET2_RREADY), + + // Ethernet to Vita + .e2v_tdata (e2v_qsfp_tdata), + .e2v_tlast (e2v_qsfp_tlast), + .e2v_tvalid (e2v_qsfp_tvalid), + .e2v_tready (e2v_qsfp_tready), + + // Vita to Ethernet + .v2e_tdata (v2e_qsfp_tdata), + .v2e_tlast (v2e_qsfp_tlast), + .v2e_tvalid (v2e_qsfp_tvalid), + .v2e_tready (v2e_qsfp_tready), + + // Ethernet to CPU + .e2c_tdata (arm_eth_qsfp_rx_tdata_b), + .e2c_tkeep (arm_eth_qsfp_rx_tkeep_b), + .e2c_tlast (arm_eth_qsfp_rx_tlast_b), + .e2c_tvalid (arm_eth_qsfp_rx_tvalid_b), + .e2c_tready (arm_eth_qsfp_rx_tready_b), + + // CPU to Ethernet + .c2e_tdata (arm_eth_qsfp_tx_tdata_b), + .c2e_tkeep (arm_eth_qsfp_tx_tkeep_b), + .c2e_tlast (arm_eth_qsfp_tx_tlast_b), + .c2e_tvalid (arm_eth_qsfp_tx_tvalid_b), + .c2e_tready (arm_eth_qsfp_tx_tready_b), + + // Sideband White Rabbit Control + .wr_reset_n (1'b1), + .wr_refclk (1'b0), + + .wr_dac_sclk (), + .wr_dac_din (), + .wr_dac_clr_n (), + .wr_dac_cs_n (), + .wr_dac_ldac_n (), + + .wr_eeprom_scl_o(), + .wr_eeprom_scl_i(1'b0), + .wr_eeprom_sda_o(), + .wr_eeprom_sda_i(1'b0), + + .wr_uart_rx (1'b0), + .wr_uart_tx (), + + .mod_pps (), + .mod_refclk (), + + // WR AXI Control + .wr_axi_aclk (), + .wr_axi_aresetn (1'b1), + .wr_axi_awaddr (), + .wr_axi_awvalid (), + .wr_axi_awready (), + .wr_axi_wdata (), + .wr_axi_wstrb (), + .wr_axi_wvalid (), + .wr_axi_wready (), + .wr_axi_bresp (), + .wr_axi_bvalid (), + .wr_axi_bready (), + .wr_axi_araddr (), + .wr_axi_arvalid (), + .wr_axi_arready (), + .wr_axi_rdata (), + .wr_axi_rresp (), + .wr_axi_rvalid (), + .wr_axi_rready (), + .wr_axi_rlast (), + + .port_info (), + .device_id (device_id), + + .link_up (qsfp_link_up), + .activity () + ); + + assign QSFP_I2C_SCL = qsfp_scl_t ? 1'bz : qsfp_scl_o; + assign qsfp_scl_i = QSFP_I2C_SCL; + assign QSFP_I2C_SDA = qsfp_sda_t ? 1'bz : qsfp_sda_o; + assign qsfp_sda_i = QSFP_I2C_SDA; + + assign QSFP_LED = |qsfp_link_up; +`else + + axi_dummy #( + .DEC_ERR(1'b0) + ) inst_axi_dummy_qsfp ( + .s_axi_aclk(bus_clk), + .s_axi_areset(bus_rst), + + .s_axi_awaddr(M_AXI_NET2_AWADDR), + .s_axi_awvalid(M_AXI_NET2_AWVALID), + .s_axi_awready(M_AXI_NET2_AWREADY), + + .s_axi_wdata(M_AXI_NET2_WDATA), + .s_axi_wvalid(M_AXI_NET2_WVALID), + .s_axi_wready(M_AXI_NET2_WREADY), + + .s_axi_bresp(M_AXI_NET2_BRESP), + .s_axi_bvalid(M_AXI_NET2_BVALID), + .s_axi_bready(M_AXI_NET2_BREADY), + + .s_axi_araddr(M_AXI_NET2_ARADDR), + .s_axi_arvalid(M_AXI_NET2_ARVALID), + .s_axi_arready(M_AXI_NET2_ARREADY), + + .s_axi_rdata(M_AXI_NET2_RDATA), + .s_axi_rresp(M_AXI_NET2_RRESP), + .s_axi_rvalid(M_AXI_NET2_RVALID), + .s_axi_rready(M_AXI_NET2_RREADY) + + ); + + assign qsfp_scl_i = qsfp_scl_t ? 1'b1 : qsfp_scl_o; + assign qsfp_sda_i = qsfp_sda_t ? 1'b1 : qsfp_sda_o; + +`endif + + //-------------------------------------------------------------- + // NPIO MGT Lanes (Example loopback config) + //-------------------------------------------------------------- + +`ifdef NPIO_LANES + + wire [127:0] npio_loopback_tdata; + wire [1:0] npio_loopback_tvalid; + wire [1:0] npio_loopback_tready; + wire [1:0] npio_loopback_tlast; + + n3xx_mgt_io_core #( + .PROTOCOL ("Aurora"), + .REG_BASE (NPIO_REG_BASE + 14'h00), + .REG_DWIDTH (REG_DWIDTH), // Width of the AXI4-Lite data bus (must be 32 or 64) + .REG_AWIDTH (REG_AWIDTH), // Width of the address bus + .PORTNUM (8'd2), + .MDIO_EN (0) + ) npio_ln_0_i ( + .areset (global_rst), + .gt_refclk (aurora_refclk), + .gb_refclk (aurora_clk156), + .misc_clk (aurora_init_clk), + .user_clk (au_user_clk), + .sync_clk (au_sync_clk), + .gt_tx_out_clk_unbuf(npio0_tx_out_clk), + + .bus_clk (bus_clk),//clk for status reg reads to mdio interface + .bus_rst (bus_rst), + .qpllreset (qpllreset_npio0), + .qplloutclk (qplloutclk), + .qplloutrefclk (qplloutrefclk), + .qplllock (qplllock), + .qpllrefclklost (), + + .rxp (NPIO_RX0_P), + .rxn (NPIO_RX0_N), + .txp (NPIO_TX0_P), + .txn (NPIO_TX0_N), + + .sfpp_rxlos (1'b0), + .sfpp_tx_fault (1'b0), + + //RegPort + .reg_wr_req (reg_wr_req_npio), + .reg_wr_addr (reg_wr_addr_npio), + .reg_wr_data (reg_wr_data_npio), + .reg_rd_req (reg_rd_req_npio), + .reg_rd_addr (reg_rd_addr_npio), + .reg_rd_resp (reg_rd_resp_npio0), + .reg_rd_data (reg_rd_data_npio0), + + //DATA (loopback mode) + .s_axis_tdata (npio_loopback_tdata[63:0]), //Data to aurora core + .s_axis_tuser (4'b0), + .s_axis_tvalid (npio_loopback_tvalid[0]), + .s_axis_tlast (npio_loopback_tlast[0]), + .s_axis_tready (npio_loopback_tready[0]), + .m_axis_tdata (npio_loopback_tdata[63:0]), //Data from aurora core + .m_axis_tuser (), + .m_axis_tvalid (npio_loopback_tvalid[0]), + .m_axis_tlast (npio_loopback_tlast[0]), + .m_axis_tready (npio_loopback_tready[0]), + + .mmcm_locked (au_mmcm_locked), + .gt_pll_lock (npio0_gt_pll_lock) + ); + + n3xx_mgt_io_core #( + .PROTOCOL ("Aurora"), + .REG_BASE (NPIO_REG_BASE + 14'h40), + .REG_DWIDTH (REG_DWIDTH), // Width of the AXI4-Lite data bus (must be 32 or 64) + .REG_AWIDTH (REG_AWIDTH), // Width of the address bus + .PORTNUM (8'd3), + .MDIO_EN (0) + ) npio_ln_1_i ( + .areset (global_rst), + .gt_refclk (aurora_refclk), + .gb_refclk (aurora_clk156), + .misc_clk (aurora_init_clk), + .user_clk (au_user_clk), + .sync_clk (au_sync_clk), + .gt_tx_out_clk_unbuf(npio1_tx_out_clk), + + .bus_clk (bus_clk),//clk for status reg reads to mdio interface + .bus_rst (bus_rst), + .qpllreset (qpllreset_npio1), + .qplloutclk (qplloutclk), + .qplloutrefclk (qplloutrefclk), + .qplllock (qplllock), + .qpllrefclklost (), + + .rxp (NPIO_RX1_P), + .rxn (NPIO_RX1_N), + .txp (NPIO_TX1_P), + .txn (NPIO_TX1_N), + + .sfpp_rxlos (1'b0), + .sfpp_tx_fault (1'b0), + + //RegPort + .reg_wr_req (reg_wr_req_npio), + .reg_wr_addr (reg_wr_addr_npio), + .reg_wr_data (reg_wr_data_npio), + .reg_rd_req (reg_rd_req_npio), + .reg_rd_addr (reg_rd_addr_npio), + .reg_rd_resp (reg_rd_resp_npio1), + .reg_rd_data (reg_rd_data_npio1), + + //DATA (loopback mode) + .s_axis_tdata (npio_loopback_tdata[127:64]), //Data to aurora core + .s_axis_tuser (4'b0), + .s_axis_tvalid (npio_loopback_tvalid[1]), + .s_axis_tlast (npio_loopback_tlast[1]), + .s_axis_tready (npio_loopback_tready[1]), + .m_axis_tdata (npio_loopback_tdata[127:64]), //Data from aurora core + .m_axis_tuser (), + .m_axis_tvalid (npio_loopback_tvalid[1]), + .m_axis_tlast (npio_loopback_tlast[1]), + .m_axis_tready (npio_loopback_tready[1]), + + .mmcm_locked (au_mmcm_locked), + .gt_pll_lock (npio1_gt_pll_lock) + ); + +`else + + assign reg_rd_resp_npio0 = 1'b0; + assign reg_rd_data_npio0 = 'h0; + assign reg_rd_resp_npio1 = 1'b0; + assign reg_rd_data_npio1 = 'h0; + assign npio0_gt_pll_lock = 1'b1; + assign npio1_gt_pll_lock = 1'b1; + assign qpllreset_npio0 = 1'b0; + assign qpllreset_npio1 = 1'b0; + +`endif + + + // ARM ethernet 0 bridge signals + wire [63:0] arm_eth0_tx_tdata; + wire arm_eth0_tx_tvalid; + wire arm_eth0_tx_tlast; + wire arm_eth0_tx_tready; + wire [3:0] arm_eth0_tx_tuser; + wire [7:0] arm_eth0_tx_tkeep; + + wire [63:0] arm_eth0_tx_tdata_b; + wire arm_eth0_tx_tvalid_b; + wire arm_eth0_tx_tlast_b; + wire arm_eth0_tx_tready_b; + wire [3:0] arm_eth0_tx_tuser_b; + wire [7:0] arm_eth0_tx_tkeep_b; + + wire [63:0] arm_eth_sfp0_tx_tdata_b; + wire arm_eth_sfp0_tx_tvalid_b; + wire arm_eth_sfp0_tx_tlast_b; + wire arm_eth_sfp0_tx_tready_b; + wire [3:0] arm_eth_sfp0_tx_tuser_b; + wire [7:0] arm_eth_sfp0_tx_tkeep_b; + + wire [63:0] arm_eth0_rx_tdata; + wire arm_eth0_rx_tvalid; + wire arm_eth0_rx_tlast; + wire arm_eth0_rx_tready; + wire [3:0] arm_eth0_rx_tuser; + wire [7:0] arm_eth0_rx_tkeep; + + wire [63:0] arm_eth0_rx_tdata_b; + wire arm_eth0_rx_tvalid_b; + wire arm_eth0_rx_tlast_b; + wire arm_eth0_rx_tready_b; + wire [3:0] arm_eth0_rx_tuser_b; + wire [7:0] arm_eth0_rx_tkeep_b; + + wire [63:0] arm_eth_sfp0_rx_tdata_b; + wire arm_eth_sfp0_rx_tvalid_b; + wire arm_eth_sfp0_rx_tlast_b; + wire arm_eth_sfp0_rx_tready_b; + wire [3:0] arm_eth_sfp0_rx_tuser_b; + wire [7:0] arm_eth_sfp0_rx_tkeep_b; + + wire arm_eth0_rx_irq; + wire arm_eth0_tx_irq; + + // ARM ethernet 1 bridge signals + wire [63:0] arm_eth1_tx_tdata; + wire arm_eth1_tx_tvalid; + wire arm_eth1_tx_tlast; + wire arm_eth1_tx_tready; + wire [3:0] arm_eth1_tx_tuser; + wire [7:0] arm_eth1_tx_tkeep; + + wire [63:0] arm_eth1_tx_tdata_b; + wire arm_eth1_tx_tvalid_b; + wire arm_eth1_tx_tlast_b; + wire arm_eth1_tx_tready_b; + wire [3:0] arm_eth1_tx_tuser_b; + wire [7:0] arm_eth1_tx_tkeep_b; + + wire [63:0] arm_eth_sfp1_tx_tdata_b; + wire arm_eth_sfp1_tx_tvalid_b; + wire arm_eth_sfp1_tx_tlast_b; + wire arm_eth_sfp1_tx_tready_b; + wire [3:0] arm_eth_sfp1_tx_tuser_b; + wire [7:0] arm_eth_sfp1_tx_tkeep_b; + + wire [63:0] arm_eth1_rx_tdata; + wire arm_eth1_rx_tvalid; + wire arm_eth1_rx_tlast; + wire arm_eth1_rx_tready; + wire [3:0] arm_eth1_rx_tuser; + wire [7:0] arm_eth1_rx_tkeep; + + wire [63:0] arm_eth1_rx_tdata_b; + wire arm_eth1_rx_tvalid_b; + wire arm_eth1_rx_tlast_b; + wire arm_eth1_rx_tready_b; + wire [3:0] arm_eth1_rx_tuser_b; + wire [7:0] arm_eth1_rx_tkeep_b; + + wire [63:0] arm_eth_sfp1_rx_tdata_b; + wire arm_eth_sfp1_rx_tvalid_b; + wire arm_eth_sfp1_rx_tlast_b; + wire arm_eth_sfp1_rx_tready_b; + wire [3:0] arm_eth_sfp1_rx_tuser_b; + wire [7:0] arm_eth_sfp1_rx_tkeep_b; + + wire arm_eth1_tx_irq; + wire arm_eth1_rx_irq; + + // Vita to Ethernet + wire [63:0] v2e0_tdata; + wire v2e0_tlast; + wire v2e0_tvalid; + wire v2e0_tready; + + wire [63:0] v2e1_tdata; + wire v2e1_tlast; + wire v2e1_tvalid; + wire v2e1_tready; + + wire [63:0] v2e_sfp0_tdata; + wire v2e_sfp0_tlast; + wire v2e_sfp0_tvalid; + wire v2e_sfp0_tready; + + wire [63:0] v2e_sfp1_tdata; + wire v2e_sfp1_tlast; + wire v2e_sfp1_tvalid; + wire v2e_sfp1_tready; + + // Ethernet to Vita + wire [63:0] e2v0_tdata; + wire e2v0_tlast; + wire e2v0_tvalid; + wire e2v0_tready; + + wire [63:0] e2v1_tdata; + wire e2v1_tlast; + wire e2v1_tvalid; + wire e2v1_tready; + + wire [63:0] e2v_sfp0_tdata; + wire e2v_sfp0_tlast; + wire e2v_sfp0_tvalid; + wire e2v_sfp0_tready; + + wire [63:0] e2v_sfp1_tdata; + wire e2v_sfp1_tlast; + wire e2v_sfp1_tvalid; + wire e2v_sfp1_tready; + + // Ethernet crossover + wire [63:0] e01_tdata, e10_tdata; + wire [3:0] e01_tuser, e10_tuser; + wire e01_tlast, e01_tvalid, e01_tready; + wire e10_tlast, e10_tvalid, e10_tready; + + + // DMA xport adapter to PS + wire [63:0] m_axis_dma_tdata; + wire [3:0] m_axis_dma_tuser; + wire m_axis_dma_tlast; + wire m_axis_dma_tready; + wire m_axis_dma_tvalid; + + wire [63:0] s_axis_dma_tdata; + wire [3:0] s_axis_dma_tdest; + wire s_axis_dma_tlast; + wire s_axis_dma_tready; + wire s_axis_dma_tvalid; + + // Misc + wire [31:0] sfp_port0_info; + wire [31:0] sfp_port1_info; + wire sfp0_link_up, sfp1_link_up; + wire [15:0] device_id; + + ///////////////////////////////////////////////////////////////////// + // + // SFP Wrapper 0: Network Interface (1/10G or Aurora) + // + ////////////////////////////////////////////////////////////////////// + + n3xx_mgt_channel_wrapper #( + .LANES(1), + `ifdef SFP0_10GBE + .PROTOCOL("10GbE"), + .MDIO_EN(1'b1), + .MDIO_PHYADDR(5'd4), // PHYADDR must match the "reg" property for PHY in DTS file + `elsif SFP0_AURORA + .PROTOCOL("Aurora"), + .MDIO_EN(1'b0), + `elsif SFP0_1GBE + .PROTOCOL("1GbE"), + .MDIO_EN(1'b1), + .MDIO_PHYADDR(5'd4), // PHYADDR must match the "reg" property for PHY in DTS file + `elsif SFP0_WR + .PROTOCOL("WhiteRabbit"), + .MDIO_EN(1'b0), + `endif + .REG_DWIDTH(REG_DWIDTH), // Width of the AXI4-Lite data bus (must be 32 or 64) + .REG_AWIDTH(REG_AWIDTH), // Width of the address bus + .GT_COMMON(1), + .PORTNUM_BASE(8'd0) + ) sfp_wrapper_0 ( + .areset(global_rst), + .gt_refclk(sfp0_gt_refclk), + .gb_refclk(sfp0_gb_refclk), + .misc_clk(sfp0_misc_clk), + .user_clk(au_user_clk), + .sync_clk(au_sync_clk), + .gt_tx_out_clk_unbuf(sfp0_tx_out_clk), + + .bus_rst(bus_rst), + .bus_clk(bus_clk), + + .qpllreset(qpllreset_sfp0), + .qplllock(qplllock), + .qplloutclk(qplloutclk), + .qplloutrefclk(qplloutrefclk), + .qpllrefclklost(), + + .mmcm_locked(au_mmcm_locked), + .gt_pll_lock(sfp0_gt_pll_lock), + + .txp(SFP_0_TX_P), + .txn(SFP_0_TX_N), + .rxp(SFP_0_RX_P), + .rxn(SFP_0_RX_N), + + .mod_present_n(SFP_0_I2C_NPRESENT), + .mod_rxlos(SFP_0_LOS), + .mod_tx_fault(SFP_0_TXFAULT), + .mod_tx_disable(SFP_0_TXDISABLE), + + // Clock and reset + .s_axi_aclk(clk40), + .s_axi_aresetn(clk40_rstn), + // AXI4-Lite: Write address port (domain: s_axi_aclk) + .s_axi_awaddr(M_AXI_NET0_AWADDR[REG_AWIDTH-1:0]), + .s_axi_awvalid(M_AXI_NET0_AWVALID), + .s_axi_awready(M_AXI_NET0_AWREADY), + // AXI4-Lite: Write data port (domain: s_axi_aclk) + .s_axi_wdata(M_AXI_NET0_WDATA), + .s_axi_wstrb(M_AXI_NET0_WSTRB), + .s_axi_wvalid(M_AXI_NET0_WVALID), + .s_axi_wready(M_AXI_NET0_WREADY), + // AXI4-Lite: Write response port (domain: s_axi_aclk) + .s_axi_bresp(M_AXI_NET0_BRESP), + .s_axi_bvalid(M_AXI_NET0_BVALID), + .s_axi_bready(M_AXI_NET0_BREADY), + // AXI4-Lite: Read address port (domain: s_axi_aclk) + .s_axi_araddr(M_AXI_NET0_ARADDR[REG_AWIDTH-1:0]), + .s_axi_arvalid(M_AXI_NET0_ARVALID), + .s_axi_arready(M_AXI_NET0_ARREADY), + // AXI4-Lite: Read data port (domain: s_axi_aclk) + .s_axi_rdata(M_AXI_NET0_RDATA), + .s_axi_rresp(M_AXI_NET0_RRESP), + .s_axi_rvalid(M_AXI_NET0_RVALID), + .s_axi_rready(M_AXI_NET0_RREADY), + + // Ethernet to Vita + .e2v_tdata(e2v_sfp0_tdata), + .e2v_tlast(e2v_sfp0_tlast), + .e2v_tvalid(e2v_sfp0_tvalid), + .e2v_tready(e2v_sfp0_tready), + + // Vita to Ethernet + .v2e_tdata(v2e_sfp0_tdata), + .v2e_tlast(v2e_sfp0_tlast), + .v2e_tvalid(v2e_sfp0_tvalid), + .v2e_tready(v2e_sfp0_tready), + + // Ethernet to CPU + .e2c_tdata(arm_eth_sfp0_rx_tdata_b), + .e2c_tkeep(arm_eth_sfp0_rx_tkeep_b), + .e2c_tlast(arm_eth_sfp0_rx_tlast_b), + .e2c_tvalid(arm_eth_sfp0_rx_tvalid_b), + .e2c_tready(arm_eth_sfp0_rx_tready_b), + + // CPU to Ethernet + .c2e_tdata(arm_eth_sfp0_tx_tdata_b), + .c2e_tkeep(arm_eth_sfp0_tx_tkeep_b), + .c2e_tlast(arm_eth_sfp0_tx_tlast_b), + .c2e_tvalid(arm_eth_sfp0_tx_tvalid_b), + .c2e_tready(arm_eth_sfp0_tx_tready_b), + + // White Rabbit Specific +`ifdef SFP0_WR + .wr_reset_n (~ps_gpio_out[48]), // reset for WR only + .wr_refclk (wr_refclk_buf), + .wr_dac_sclk (WB_DAC_SCLK), + .wr_dac_din (WB_DAC_DIN), + .wr_dac_clr_n (WB_DAC_NCLR), + .wr_dac_cs_n (WB_DAC_NSYNC), + .wr_dac_ldac_n(WB_DAC_NLDAC), + .wr_eeprom_scl_o(), // storage for delay characterization + .wr_eeprom_scl_i(1'b0), // temp + .wr_eeprom_sda_o(), + .wr_eeprom_sda_i(1'b0), // temp + .wr_uart_rx(wr_uart_rxd), // to/from PS + .wr_uart_tx(wr_uart_txd), + .mod_pps(pps_wr_refclk), // out, reference clock and pps + .mod_refclk(wr_ref_clk), + // WR Slave Port to PS + .wr_axi_aclk(m_axi_wr_clk), // out to PS + .wr_axi_aresetn(1'b1), // in + .wr_axi_awaddr(m_axi_wr_awaddr), + .wr_axi_awvalid(m_axi_wr_awvalid), + .wr_axi_awready(m_axi_wr_awready), + .wr_axi_wdata(m_axi_wr_wdata), + .wr_axi_wstrb(m_axi_wr_wstrb), + .wr_axi_wvalid(m_axi_wr_wvalid), + .wr_axi_wready(m_axi_wr_wready), + .wr_axi_bresp(m_axi_wr_bresp), + .wr_axi_bvalid(m_axi_wr_bvalid), + .wr_axi_bready(m_axi_wr_bready), + .wr_axi_araddr(m_axi_wr_araddr), + .wr_axi_arvalid(m_axi_wr_arvalid), + .wr_axi_arready(m_axi_wr_arready), + .wr_axi_rdata(m_axi_wr_rdata), + .wr_axi_rresp(m_axi_wr_rresp), + .wr_axi_rvalid(m_axi_wr_rvalid), + .wr_axi_rready(m_axi_wr_rready), + .wr_axi_rlast(), +`else + .wr_reset_n(1'b1), + .wr_refclk(1'b0), + .wr_eeprom_scl_i(1'b0), + .wr_eeprom_sda_i(1'b0), + .wr_uart_rx(1'b0), +`endif + + // Misc + .port_info(sfp_port0_info), + .device_id(device_id), + + // LED + .link_up(sfp0_link_up), + .activity(SFP_0_LED_A) + ); + + assign ps_gpio_in[60] = ps_gpio_tri[60] ? sfp0_link_up : ps_gpio_out[60]; + assign SFP_0_LED_B = sfp0_link_up; + +`ifndef SFP0_WR + assign WB_DAC_SCLK = 1'b0; + assign WB_DAC_DIN = 1'b0; + assign WB_DAC_NCLR = 1'b1; + assign WB_DAC_NSYNC = 1'b1; + assign WB_DAC_NLDAC = 1'b1; + assign pps_wr_refclk = 1'b0; + assign wr_ref_clk = 1'b0; +`endif + + ///////////////////////////////////////////////////////////////////// + // + // SFP Wrapper 1: Network Interface (1/10G or Aurora) + // + ////////////////////////////////////////////////////////////////////// + + n3xx_mgt_channel_wrapper #( + .LANES(1), + `ifdef SFP1_10GBE + .PROTOCOL("10GbE"), + .MDIO_EN(1'b1), + .MDIO_PHYADDR(5'd4), // PHYADDR must match the "reg" property for PHY in DTS file + `elsif SFP1_AURORA + .PROTOCOL("Aurora"), + .MDIO_EN(1'b0), + `endif + .REG_DWIDTH(REG_DWIDTH), // Width of the AXI4-Lite data bus (must be 32 or 64) + .REG_AWIDTH(REG_AWIDTH), // Width of the address bus + .GT_COMMON(1), + .PORTNUM_BASE(8'd1) + ) sfp_wrapper_1 ( + .areset(global_rst), + + .gt_refclk(sfp1_gt_refclk), + .gb_refclk(sfp1_gb_refclk), + .misc_clk(sfp1_misc_clk), + .user_clk(au_user_clk), + .sync_clk(au_sync_clk), + .gt_tx_out_clk_unbuf(sfp1_tx_out_clk), + + .bus_rst(bus_rst), + .bus_clk(bus_clk), + + .qpllreset(qpllreset_sfp1), + .qplllock(qplllock), + .qplloutclk(qplloutclk), + .qplloutrefclk(qplloutrefclk), + .qpllrefclklost(), + + .mmcm_locked(au_mmcm_locked), + .gt_pll_lock(sfp1_gt_pll_lock), + + .txp(SFP_1_TX_P), + .txn(SFP_1_TX_N), + .rxp(SFP_1_RX_P), + .rxn(SFP_1_RX_N), + + .mod_rxlos(SFP_1_LOS), + .mod_tx_fault(SFP_1_TXFAULT), + .mod_tx_disable(SFP_1_TXDISABLE), + + // Clock and reset + .s_axi_aclk(clk40), + .s_axi_aresetn(clk40_rstn), + // AXI4-Lite: Write address port (domain: s_axi_aclk) + .s_axi_awaddr(M_AXI_NET1_AWADDR[REG_AWIDTH-1:0]), + .s_axi_awvalid(M_AXI_NET1_AWVALID), + .s_axi_awready(M_AXI_NET1_AWREADY), + // AXI4-Lite: Write data port (domain: s_axi_aclk) + .s_axi_wdata(M_AXI_NET1_WDATA), + .s_axi_wstrb(M_AXI_NET1_WSTRB), + .s_axi_wvalid(M_AXI_NET1_WVALID), + .s_axi_wready(M_AXI_NET1_WREADY), + // AXI4-Lite: Write response port (domain: s_axi_aclk) + .s_axi_bresp(M_AXI_NET1_BRESP), + .s_axi_bvalid(M_AXI_NET1_BVALID), + .s_axi_bready(M_AXI_NET1_BREADY), + // AXI4-Lite: Read address port (domain: s_axi_aclk) + .s_axi_araddr(M_AXI_NET1_ARADDR[REG_AWIDTH-1:0]), + .s_axi_arvalid(M_AXI_NET1_ARVALID), + .s_axi_arready(M_AXI_NET1_ARREADY), + // AXI4-Lite: Read data port (domain: s_axi_aclk) + .s_axi_rdata(M_AXI_NET1_RDATA), + .s_axi_rresp(M_AXI_NET1_RRESP), + .s_axi_rvalid(M_AXI_NET1_RVALID), + .s_axi_rready(M_AXI_NET1_RREADY), + + // Ethernet to Vita + .e2v_tdata(e2v_sfp1_tdata), + .e2v_tlast(e2v_sfp1_tlast), + .e2v_tvalid(e2v_sfp1_tvalid), + .e2v_tready(e2v_sfp1_tready), + + // Vita to Ethernet + .v2e_tdata(v2e_sfp1_tdata), + .v2e_tlast(v2e_sfp1_tlast), + .v2e_tvalid(v2e_sfp1_tvalid), + .v2e_tready(v2e_sfp1_tready), + + // Ethernet to CPU + .e2c_tdata(arm_eth_sfp1_rx_tdata_b), + .e2c_tkeep(arm_eth_sfp1_rx_tkeep_b), + .e2c_tlast(arm_eth_sfp1_rx_tlast_b), + .e2c_tvalid(arm_eth_sfp1_rx_tvalid_b), + .e2c_tready(arm_eth_sfp1_rx_tready_b), + + // CPU to Ethernet + .c2e_tdata(arm_eth_sfp1_tx_tdata_b), + .c2e_tkeep(arm_eth_sfp1_tx_tkeep_b), + .c2e_tlast(arm_eth_sfp1_tx_tlast_b), + .c2e_tvalid(arm_eth_sfp1_tx_tvalid_b), + .c2e_tready(arm_eth_sfp1_tx_tready_b), + + // Misc + .port_info(sfp_port1_info), + .device_id(device_id), + + // LED + .link_up(sfp1_link_up), + .activity(SFP_1_LED_A) + ); + + assign ps_gpio_in[61] = ps_gpio_tri[61] ? sfp1_link_up : ps_gpio_out[61]; + assign SFP_1_LED_B = sfp1_link_up; + + ///////////////////////////////////////////////////////////////////// + // + // Ethernet DMA 0 + // + ////////////////////////////////////////////////////////////////////// + + assign IRQ_F2P[0] = arm_eth0_rx_irq; + assign IRQ_F2P[1] = arm_eth0_tx_irq; + + assign {S_AXI_HP0_AWID, S_AXI_HP0_ARID} = 12'd0; + assign {S_AXI_GP0_AWID, S_AXI_GP0_ARID} = 10'd0; + +`ifdef QSFP_10GBE + // QSFP+ lanes connect to DMA engines and crossbar + // Connect first QSFP+ 10 GbE port to a DMA engine (and the PS/ARM) + assign arm_eth_qsfp_tx_tdata_b[0*64 +: 64] = arm_eth0_tx_tdata_b; + assign arm_eth_qsfp_tx_tvalid_b[0] = arm_eth0_tx_tvalid_b; + assign arm_eth_qsfp_tx_tlast_b[0] = arm_eth0_tx_tlast_b; + assign arm_eth0_tx_tready_b = arm_eth_qsfp_tx_tready_b[0]; + assign arm_eth_qsfp_tx_tuser_b[0*4 +: 4] = arm_eth0_tx_tuser_b; + assign arm_eth_qsfp_tx_tkeep_b[0*8 +: 8] = arm_eth0_tx_tkeep_b; + + assign arm_eth0_rx_tdata_b = arm_eth_qsfp_rx_tdata_b[0*64 +: 64]; + assign arm_eth0_rx_tvalid_b = arm_eth_qsfp_rx_tvalid_b[0]; + assign arm_eth0_rx_tlast_b = arm_eth_qsfp_rx_tlast_b[0]; + assign arm_eth_qsfp_rx_tready_b[0] = arm_eth0_rx_tready_b; + assign arm_eth0_rx_tuser_b = arm_eth_qsfp_rx_tuser_b[0*4 +: 4]; + assign arm_eth0_rx_tkeep_b = arm_eth_qsfp_rx_tkeep_b[0*8 +: 8]; + + // Connect first QSFP+ 10 GbE port to the crossbar + assign v2e_qsfp_tdata[0*64 +: 64] = v2e0_tdata; + assign v2e_qsfp_tlast[0] = v2e0_tlast; + assign v2e_qsfp_tvalid[0] = v2e0_tvalid; + assign v2e0_tready = v2e_qsfp_tready[0]; + + assign e2v0_tdata = e2v_qsfp_tdata[0*64 +: 64]; + assign e2v0_tlast = e2v_qsfp_tlast[0]; + assign e2v0_tvalid = e2v_qsfp_tvalid[0]; + assign e2v_qsfp_tready[0] = e2v0_tready; + + // Connect second QSFP+ 10 GbE port to a DMA engine (and the PS/ARM) + assign arm_eth_qsfp_tx_tdata_b[1*64 +: 64] = arm_eth1_tx_tdata_b; + assign arm_eth_qsfp_tx_tvalid_b[1] = arm_eth1_tx_tvalid_b; + assign arm_eth_qsfp_tx_tlast_b[1] = arm_eth1_tx_tlast_b; + assign arm_eth1_tx_tready_b = arm_eth_qsfp_tx_tready_b[1]; + assign arm_eth_qsfp_tx_tuser_b[1*4 +: 4] = arm_eth1_tx_tuser_b; + assign arm_eth_qsfp_tx_tkeep_b[1*8 +: 8] = arm_eth1_tx_tkeep_b; + + assign arm_eth1_rx_tdata_b = arm_eth_qsfp_rx_tdata_b[1*64 +: 64]; + assign arm_eth1_rx_tvalid_b = arm_eth_qsfp_rx_tvalid_b[1]; + assign arm_eth1_rx_tlast_b = arm_eth_qsfp_rx_tlast_b[1]; + assign arm_eth_qsfp_rx_tready_b[1] = arm_eth1_rx_tready_b; + assign arm_eth1_rx_tuser_b = arm_eth_qsfp_rx_tuser_b[1*4 +: 4]; + assign arm_eth1_rx_tkeep_b = arm_eth_qsfp_rx_tkeep_b[1*8 +: 8]; + + // Connect second QSFP+ 10 GbE port to the crossbar + assign v2e_qsfp_tdata[1*64 +: 64] = v2e1_tdata; + assign v2e_qsfp_tlast[1] = v2e1_tlast; + assign v2e_qsfp_tvalid[1] = v2e1_tvalid; + assign v2e1_tready = v2e_qsfp_tready[1]; + + assign e2v1_tdata = e2v_qsfp_tdata[1*64 +: 64]; + assign e2v1_tlast = e2v_qsfp_tlast[1]; + assign e2v1_tvalid = e2v_qsfp_tvalid[1]; + assign e2v_qsfp_tready[1] = e2v1_tready; +`else + // SFP+ ports connects to DMA engines and crossbar + // Connect first SFP+ 10 GbE port to a DMA engine (and the PS/ARM) + assign arm_eth_sfp0_tx_tdata_b = arm_eth0_tx_tdata_b; + assign arm_eth_sfp0_tx_tvalid_b = arm_eth0_tx_tvalid_b; + assign arm_eth_sfp0_tx_tlast_b = arm_eth0_tx_tlast_b; + assign arm_eth0_tx_tready_b = arm_eth_sfp0_tx_tready_b; + assign arm_eth_sfp0_tx_tuser_b = arm_eth0_tx_tuser_b; + assign arm_eth_sfp0_tx_tkeep_b = arm_eth0_tx_tkeep_b; + + assign arm_eth0_rx_tdata_b = arm_eth_sfp0_rx_tdata_b; + assign arm_eth0_rx_tvalid_b = arm_eth_sfp0_rx_tvalid_b; + assign arm_eth0_rx_tlast_b = arm_eth_sfp0_rx_tlast_b; + assign arm_eth_sfp0_rx_tready_b = arm_eth0_rx_tready_b; + assign arm_eth0_rx_tuser_b = arm_eth_sfp0_rx_tuser_b; + assign arm_eth0_rx_tkeep_b = arm_eth_sfp0_rx_tkeep_b; + + // Connect first SFP+ 10 GbE port to the crossbar + assign v2e_sfp0_tdata = v2e0_tdata; + assign v2e_sfp0_tlast = v2e0_tlast; + assign v2e_sfp0_tvalid = v2e0_tvalid; + assign v2e0_tready = v2e_sfp0_tready; + + assign e2v0_tdata = e2v_sfp0_tdata; + assign e2v0_tlast = e2v_sfp0_tlast; + assign e2v0_tvalid = e2v_sfp0_tvalid; + assign e2v_sfp0_tready = e2v0_tready; + + // Connect second SFP+ 10 GbE port to a DMA engine (and the PS/ARM) + assign arm_eth_sfp1_tx_tdata_b = arm_eth1_tx_tdata_b; + assign arm_eth_sfp1_tx_tvalid_b = arm_eth1_tx_tvalid_b; + assign arm_eth_sfp1_tx_tlast_b = arm_eth1_tx_tlast_b; + assign arm_eth1_tx_tready_b = arm_eth_sfp1_tx_tready_b; + assign arm_eth_sfp1_tx_tuser_b = arm_eth1_tx_tuser_b; + assign arm_eth_sfp1_tx_tkeep_b = arm_eth1_tx_tkeep_b; + + assign arm_eth1_rx_tdata_b = arm_eth_sfp1_rx_tdata_b; + assign arm_eth1_rx_tvalid_b = arm_eth_sfp1_rx_tvalid_b; + assign arm_eth1_rx_tlast_b = arm_eth_sfp1_rx_tlast_b; + assign arm_eth_sfp1_rx_tready_b = arm_eth1_rx_tready_b; + assign arm_eth1_rx_tuser_b = arm_eth_sfp1_rx_tuser_b; + assign arm_eth1_rx_tkeep_b = arm_eth_sfp1_rx_tkeep_b; + + // Connect first SFP+ 10 GbE port to the crossbar + assign v2e_sfp1_tdata = v2e1_tdata; + assign v2e_sfp1_tlast = v2e1_tlast; + assign v2e_sfp1_tvalid = v2e1_tvalid; + assign v2e1_tready = v2e_sfp1_tready; + + assign e2v1_tdata = e2v_sfp1_tdata; + assign e2v1_tlast = e2v_sfp1_tlast; + assign e2v1_tvalid = e2v_sfp1_tvalid; + assign e2v_sfp1_tready = e2v1_tready; + + // Don't actually instantiate DMA engines if protocols can't use them + `ifdef SFP0_AURORA + `define NO_ETH_DMA_0 + `elsif SFP0_WR + `define NO_ETH_DMA_0 + `endif + + `ifdef SFP1_AURORA + `define NO_ETH_DMA_1 + `endif +`endif + +`ifdef NO_ETH_DMA_0 + //If inst Aurora, tie off each axi/axi-lite interface + axi_dummy #( + .DEC_ERR(1'b0) + ) inst_axi_dummy_sfp0_eth_dma ( + .s_axi_aclk(bus_clk), + .s_axi_areset(bus_rst), + + .s_axi_awaddr(M_AXI_ETH_DMA0_AWADDR), + .s_axi_awvalid(M_AXI_ETH_DMA0_AWVALID), + .s_axi_awready(M_AXI_ETH_DMA0_AWREADY), + + .s_axi_wdata(M_AXI_ETH_DMA0_WDATA), + .s_axi_wvalid(M_AXI_ETH_DMA0_WVALID), + .s_axi_wready(M_AXI_ETH_DMA0_WREADY), + + .s_axi_bresp(M_AXI_ETH_DMA0_BRESP), + .s_axi_bvalid(M_AXI_ETH_DMA0_BVALID), + .s_axi_bready(M_AXI_ETH_DMA0_BREADY), + + .s_axi_araddr(M_AXI_ETH_DMA0_ARADDR), + .s_axi_arvalid(M_AXI_ETH_DMA0_ARVALID), + .s_axi_arready(M_AXI_ETH_DMA0_ARREADY), + + .s_axi_rdata(M_AXI_ETH_DMA0_RDATA), + .s_axi_rresp(M_AXI_ETH_DMA0_RRESP), + .s_axi_rvalid(M_AXI_ETH_DMA0_RVALID), + .s_axi_rready(M_AXI_ETH_DMA0_RREADY) + + ); + //S_AXI_GP0 outputs from axi_eth_dma, so needs some sort of controller/tie off + assign S_AXI_GP0_AWADDR = 32'h0; + assign S_AXI_GP0_AWLEN = 8'h0; + assign S_AXI_GP0_AWSIZE = 4'h0; + assign S_AXI_GP0_AWBURST = 3'h0; + assign S_AXI_GP0_AWPROT = 3'h0; + assign S_AXI_GP0_AWCACHE = 4'h0; + assign S_AXI_GP0_AWVALID = 1'b0; + //S_AXI_GP0_AWREADY output from PS + assign S_AXI_GP0_WDATA = 32'h0; + assign S_AXI_GP0_WSTRB = 4'h0; + assign S_AXI_GP0_WLAST = 1'b0; + assign S_AXI_GP0_WVALID = 1'b0; + //S_AXI_GP0_WREADY output from PS + //S_AXI_GP0_BRESP + //S_AXI_GP0_BVALID + assign S_AXI_GP0_BREADY = 1'b1; + assign S_AXI_GP0_ARADDR = 32'h0; + assign S_AXI_GP0_ARLEN = 8'h0; + assign S_AXI_GP0_ARSIZE = 3'h0; + assign S_AXI_GP0_ARBURST = 2'h0; + assign S_AXI_GP0_ARPROT = 3'h0; + assign S_AXI_GP0_ARCACHE = 4'h0; + assign S_AXI_GP0_ARVALID = 1'b0; + //S_AXI_GP0_ARREADY + //S_AXI_GP0_RDATA + //S_AXI_GP0_RRESP + //S_AXI_GP0_RLAST + //S_AXI_GP0_RVALID + assign S_AXI_GP0_RREADY = 1'b1; + + //S_AXI_HP0 from axi_eth_dma + assign S_AXI_HP0_ARADDR = 32'h0; + assign S_AXI_HP0_ARLEN = 8'h0; + assign S_AXI_HP0_ARSIZE = 3'h0; + assign S_AXI_HP0_ARBURST = 2'h0; + assign S_AXI_HP0_ARPROT = 3'h0; + assign S_AXI_HP0_ARCACHE = 4'h0; + assign S_AXI_HP0_ARVALID = 1'b0; + //S_AXI_HP0_ARREADY + //S_AXI_HP0_RDATA + //S_AXI_HP0_RRESP + //S_AXI_HP0_RLAST + //S_AXI_HP0_RVALID + assign S_AXI_HP0_RREADY = 1'b1; + assign S_AXI_HP0_AWADDR = 32'h0; + assign S_AXI_HP0_AWLEN = 8'h0; + assign S_AXI_HP0_AWSIZE = 3'h0; + assign S_AXI_HP0_AWBURST = 2'h0; + assign S_AXI_HP0_AWPROT = 3'h0; + assign S_AXI_HP0_AWCACHE = 4'h0; + assign S_AXI_HP0_AWVALID = 1'b0; + //S_AXI_HP0_AWREADY + assign S_AXI_HP0_WDATA = 64'h0; + assign S_AXI_HP0_WSTRB = 8'h0; + assign S_AXI_HP0_WLAST = 1'b0; + assign S_AXI_HP0_WVALID = 1'b0; + //S_AXI_HP0_WREADY + //S_AXI_HP0_BRESP + //S_AXI_HP0_BVALID + assign S_AXI_HP0_BREADY = 1'b1; + +`else + + axi_eth_dma inst_axi_eth_dma0 ( + .s_axi_lite_aclk(clk40), + .m_axi_sg_aclk(clk40), + .m_axi_mm2s_aclk(clk40), + .m_axi_s2mm_aclk(clk40), + .axi_resetn(clk40_rstn), + + .s_axi_lite_awaddr(M_AXI_ETH_DMA0_AWADDR), + .s_axi_lite_awvalid(M_AXI_ETH_DMA0_AWVALID), + .s_axi_lite_awready(M_AXI_ETH_DMA0_AWREADY), + + .s_axi_lite_wdata(M_AXI_ETH_DMA0_WDATA), + .s_axi_lite_wvalid(M_AXI_ETH_DMA0_WVALID), + .s_axi_lite_wready(M_AXI_ETH_DMA0_WREADY), + + .s_axi_lite_bresp(M_AXI_ETH_DMA0_BRESP), + .s_axi_lite_bvalid(M_AXI_ETH_DMA0_BVALID), + .s_axi_lite_bready(M_AXI_ETH_DMA0_BREADY), + + .s_axi_lite_araddr(M_AXI_ETH_DMA0_ARADDR), + .s_axi_lite_arvalid(M_AXI_ETH_DMA0_ARVALID), + .s_axi_lite_arready(M_AXI_ETH_DMA0_ARREADY), + + .s_axi_lite_rdata(M_AXI_ETH_DMA0_RDATA), + .s_axi_lite_rresp(M_AXI_ETH_DMA0_RRESP), + .s_axi_lite_rvalid(M_AXI_ETH_DMA0_RVALID), + .s_axi_lite_rready(M_AXI_ETH_DMA0_RREADY), + + .m_axi_sg_awaddr(S_AXI_GP0_AWADDR), + .m_axi_sg_awlen(S_AXI_GP0_AWLEN), + .m_axi_sg_awsize(S_AXI_GP0_AWSIZE), + .m_axi_sg_awburst(S_AXI_GP0_AWBURST), + .m_axi_sg_awprot(S_AXI_GP0_AWPROT), + .m_axi_sg_awcache(S_AXI_GP0_AWCACHE), + .m_axi_sg_awvalid(S_AXI_GP0_AWVALID), + .m_axi_sg_awready(S_AXI_GP0_AWREADY), + .m_axi_sg_wdata(S_AXI_GP0_WDATA), + .m_axi_sg_wstrb(S_AXI_GP0_WSTRB), + .m_axi_sg_wlast(S_AXI_GP0_WLAST), + .m_axi_sg_wvalid(S_AXI_GP0_WVALID), + .m_axi_sg_wready(S_AXI_GP0_WREADY), + .m_axi_sg_bresp(S_AXI_GP0_BRESP), + .m_axi_sg_bvalid(S_AXI_GP0_BVALID), + .m_axi_sg_bready(S_AXI_GP0_BREADY), + .m_axi_sg_araddr(S_AXI_GP0_ARADDR), + .m_axi_sg_arlen(S_AXI_GP0_ARLEN), + .m_axi_sg_arsize(S_AXI_GP0_ARSIZE), + .m_axi_sg_arburst(S_AXI_GP0_ARBURST), + .m_axi_sg_arprot(S_AXI_GP0_ARPROT), + .m_axi_sg_arcache(S_AXI_GP0_ARCACHE), + .m_axi_sg_arvalid(S_AXI_GP0_ARVALID), + .m_axi_sg_arready(S_AXI_GP0_ARREADY), + .m_axi_sg_rdata(S_AXI_GP0_RDATA), + .m_axi_sg_rresp(S_AXI_GP0_RRESP), + .m_axi_sg_rlast(S_AXI_GP0_RLAST), + .m_axi_sg_rvalid(S_AXI_GP0_RVALID), + .m_axi_sg_rready(S_AXI_GP0_RREADY), + + .m_axi_mm2s_araddr(S_AXI_HP0_ARADDR), + .m_axi_mm2s_arlen(S_AXI_HP0_ARLEN), + .m_axi_mm2s_arsize(S_AXI_HP0_ARSIZE), + .m_axi_mm2s_arburst(S_AXI_HP0_ARBURST), + .m_axi_mm2s_arprot(S_AXI_HP0_ARPROT), + .m_axi_mm2s_arcache(S_AXI_HP0_ARCACHE), + .m_axi_mm2s_arvalid(S_AXI_HP0_ARVALID), + .m_axi_mm2s_arready(S_AXI_HP0_ARREADY), + .m_axi_mm2s_rdata(S_AXI_HP0_RDATA), + .m_axi_mm2s_rresp(S_AXI_HP0_RRESP), + .m_axi_mm2s_rlast(S_AXI_HP0_RLAST), + .m_axi_mm2s_rvalid(S_AXI_HP0_RVALID), + .m_axi_mm2s_rready(S_AXI_HP0_RREADY), + + .mm2s_prmry_reset_out_n(), + .m_axis_mm2s_tdata(arm_eth0_tx_tdata), + .m_axis_mm2s_tkeep(arm_eth0_tx_tkeep), + .m_axis_mm2s_tvalid(arm_eth0_tx_tvalid), + .m_axis_mm2s_tready(arm_eth0_tx_tready), + .m_axis_mm2s_tlast(arm_eth0_tx_tlast), + + .m_axi_s2mm_awaddr(S_AXI_HP0_AWADDR), + .m_axi_s2mm_awlen(S_AXI_HP0_AWLEN), + .m_axi_s2mm_awsize(S_AXI_HP0_AWSIZE), + .m_axi_s2mm_awburst(S_AXI_HP0_AWBURST), + .m_axi_s2mm_awprot(S_AXI_HP0_AWPROT), + .m_axi_s2mm_awcache(S_AXI_HP0_AWCACHE), + .m_axi_s2mm_awvalid(S_AXI_HP0_AWVALID), + .m_axi_s2mm_awready(S_AXI_HP0_AWREADY), + .m_axi_s2mm_wdata(S_AXI_HP0_WDATA), + .m_axi_s2mm_wstrb(S_AXI_HP0_WSTRB), + .m_axi_s2mm_wlast(S_AXI_HP0_WLAST), + .m_axi_s2mm_wvalid(S_AXI_HP0_WVALID), + .m_axi_s2mm_wready(S_AXI_HP0_WREADY), + .m_axi_s2mm_bresp(S_AXI_HP0_BRESP), + .m_axi_s2mm_bvalid(S_AXI_HP0_BVALID), + .m_axi_s2mm_bready(S_AXI_HP0_BREADY), + + .s2mm_prmry_reset_out_n(), + .s_axis_s2mm_tdata(arm_eth0_rx_tdata), + .s_axis_s2mm_tkeep(arm_eth0_rx_tkeep), + .s_axis_s2mm_tvalid(arm_eth0_rx_tvalid), + .s_axis_s2mm_tready(arm_eth0_rx_tready), + .s_axis_s2mm_tlast(arm_eth0_rx_tlast), + + .mm2s_introut(arm_eth0_tx_irq), + .s2mm_introut(arm_eth0_rx_irq), + .axi_dma_tstvec() + ); + + axi_fifo_2clk #( + .WIDTH(1+8+64), + .SIZE(5) + ) eth_tx_0_fifo_2clk_i ( + .reset(clk40_rst), + .i_aclk(clk40), + .i_tdata({arm_eth0_tx_tlast, arm_eth0_tx_tkeep, arm_eth0_tx_tdata}), + .i_tvalid(arm_eth0_tx_tvalid), + .i_tready(arm_eth0_tx_tready), + .o_aclk(bus_clk), + .o_tdata({arm_eth0_tx_tlast_b, arm_eth0_tx_tkeep_b, arm_eth0_tx_tdata_b}), + .o_tvalid(arm_eth0_tx_tvalid_b), + .o_tready(arm_eth0_tx_tready_b) + ); + + axi_fifo_2clk #( + .WIDTH(1+8+64), + .SIZE(5) + ) eth_rx_0_fifo_2clk_i ( + .reset(bus_rst), + .i_aclk(bus_clk), + .i_tdata({arm_eth0_rx_tlast_b, arm_eth0_rx_tkeep_b, arm_eth0_rx_tdata_b}), + .i_tvalid(arm_eth0_rx_tvalid_b), + .i_tready(arm_eth0_rx_tready_b), + .o_aclk(clk40), + .o_tdata({arm_eth0_rx_tlast, arm_eth0_rx_tkeep, arm_eth0_rx_tdata}), + .o_tvalid(arm_eth0_rx_tvalid), + .o_tready(arm_eth0_rx_tready) + ); + +`endif + + ///////////////////////////////////////////////////////////////////// + // + // Ethernet DMA 1 + // + ////////////////////////////////////////////////////////////////////// + + assign IRQ_F2P[2] = arm_eth1_rx_irq; + assign IRQ_F2P[3] = arm_eth1_tx_irq; + + assign {S_AXI_HP1_AWID, S_AXI_HP1_ARID} = 12'd0; + assign {S_AXI_GP1_AWID, S_AXI_GP1_ARID} = 10'd0; + +`ifdef NO_ETH_DMA_1 + //If inst Aurora, tie off each axi/axi-lite interface + axi_dummy #(.DEC_ERR(1'b0)) inst_axi_dummy_sfp1_eth_dma + ( + .s_axi_aclk(bus_clk), + .s_axi_areset(bus_rst), + + .s_axi_awaddr(M_AXI_ETH_DMA1_AWADDR), + .s_axi_awvalid(M_AXI_ETH_DMA1_AWVALID), + .s_axi_awready(M_AXI_ETH_DMA1_AWREADY), + + .s_axi_wdata(M_AXI_ETH_DMA1_WDATA), + .s_axi_wvalid(M_AXI_ETH_DMA1_WVALID), + .s_axi_wready(M_AXI_ETH_DMA1_WREADY), + + .s_axi_bresp(M_AXI_ETH_DMA1_BRESP), + .s_axi_bvalid(M_AXI_ETH_DMA1_BVALID), + .s_axi_bready(M_AXI_ETH_DMA1_BREADY), + + .s_axi_araddr(M_AXI_ETH_DMA1_ARADDR), + .s_axi_arvalid(M_AXI_ETH_DMA1_ARVALID), + .s_axi_arready(M_AXI_ETH_DMA1_ARREADY), + + .s_axi_rdata(M_AXI_ETH_DMA1_RDATA), + .s_axi_rresp(M_AXI_ETH_DMA1_RRESP), + .s_axi_rvalid(M_AXI_ETH_DMA1_RVALID), + .s_axi_rready(M_AXI_ETH_DMA1_RREADY) + + ); + //S_AXI_GP0 outputs from axi_eth_dma, so needs some sort of controller/tie off + assign S_AXI_GP1_AWADDR = 32'h0; + assign S_AXI_GP1_AWLEN = 8'h0; + assign S_AXI_GP1_AWSIZE = 4'h0; + assign S_AXI_GP1_AWBURST = 3'h0; + assign S_AXI_GP1_AWPROT = 3'h0; + assign S_AXI_GP1_AWCACHE = 4'h0; + assign S_AXI_GP1_AWVALID = 1'b0; + //S_AXI_GP1_AWREADY output from PS + assign S_AXI_GP1_WDATA = 32'h0; + assign S_AXI_GP1_WSTRB = 4'h0; + assign S_AXI_GP1_WLAST = 1'b0; + assign S_AXI_GP1_WVALID = 1'b0; + //S_AXI_GP1_WREADY output from PS + //S_AXI_GP1_BRESP + //S_AXI_GP1_BVALID + assign S_AXI_GP1_BREADY = 1'b1; + assign S_AXI_GP1_ARADDR = 32'h0; + assign S_AXI_GP1_ARLEN = 8'h0; + assign S_AXI_GP1_ARSIZE = 3'h0; + assign S_AXI_GP1_ARBURST = 2'h0; + assign S_AXI_GP1_ARPROT = 3'h0; + assign S_AXI_GP1_ARCACHE = 4'h0; + assign S_AXI_GP1_ARVALID = 1'b0; + //S_AXI_GP1_ARREADY + //S_AXI_GP1_RDATA + //S_AXI_GP1_RRESP + //S_AXI_GP1_RLAST + //S_AXI_GP1_RVALID + assign S_AXI_GP1_RREADY = 1'b1; + + //S_AXI_HP0 from axi_eth_dma + assign S_AXI_HP1_ARADDR = 32'h0; + assign S_AXI_HP1_ARLEN = 8'h0; + assign S_AXI_HP1_ARSIZE = 3'h0; + assign S_AXI_HP1_ARBURST = 2'h0; + assign S_AXI_HP1_ARPROT = 3'h0; + assign S_AXI_HP1_ARCACHE = 4'h0; + assign S_AXI_HP1_ARVALID = 1'b0; + //S_AXI_HP1_ARREADY + //S_AXI_HP1_RDATA + //S_AXI_HP1_RRESP + //S_AXI_HP1_RLAST + //S_AXI_HP1_RVALID + assign S_AXI_HP1_RREADY = 1'b1; + assign S_AXI_HP1_AWADDR = 32'h0; + assign S_AXI_HP1_AWLEN = 8'h0; + assign S_AXI_HP1_AWSIZE = 3'h0; + assign S_AXI_HP1_AWBURST = 2'h0; + assign S_AXI_HP1_AWPROT = 3'h0; + assign S_AXI_HP1_AWCACHE = 4'h0; + assign S_AXI_HP1_AWVALID = 1'b0; + //S_AXI_HP1_AWREADY + assign S_AXI_HP1_WDATA = 64'h0; + assign S_AXI_HP1_WSTRB = 8'h0; + assign S_AXI_HP1_WLAST = 1'b0; + assign S_AXI_HP1_WVALID = 1'b0; + //S_AXI_HP1_WREADY + //S_AXI_HP1_BRESP + //S_AXI_HP1_BVALID + assign S_AXI_HP1_BREADY = 1'b1; + +`else + + axi_eth_dma inst_axi_eth_dma1 ( + .s_axi_lite_aclk(clk40), + .m_axi_sg_aclk(clk40), + .m_axi_mm2s_aclk(clk40), + .m_axi_s2mm_aclk(clk40), + .axi_resetn(clk40_rstn), + + .s_axi_lite_awaddr(M_AXI_ETH_DMA1_AWADDR), + .s_axi_lite_awvalid(M_AXI_ETH_DMA1_AWVALID), + .s_axi_lite_awready(M_AXI_ETH_DMA1_AWREADY), + + .s_axi_lite_wdata(M_AXI_ETH_DMA1_WDATA), + .s_axi_lite_wvalid(M_AXI_ETH_DMA1_WVALID), + .s_axi_lite_wready(M_AXI_ETH_DMA1_WREADY), + + .s_axi_lite_bresp(M_AXI_ETH_DMA1_BRESP), + .s_axi_lite_bvalid(M_AXI_ETH_DMA1_BVALID), + .s_axi_lite_bready(M_AXI_ETH_DMA1_BREADY), + + .s_axi_lite_araddr(M_AXI_ETH_DMA1_ARADDR), + .s_axi_lite_arvalid(M_AXI_ETH_DMA1_ARVALID), + .s_axi_lite_arready(M_AXI_ETH_DMA1_ARREADY), + + .s_axi_lite_rdata(M_AXI_ETH_DMA1_RDATA), + .s_axi_lite_rresp(M_AXI_ETH_DMA1_RRESP), + .s_axi_lite_rvalid(M_AXI_ETH_DMA1_RVALID), + .s_axi_lite_rready(M_AXI_ETH_DMA1_RREADY), + + .m_axi_sg_awaddr(S_AXI_GP1_AWADDR), + .m_axi_sg_awlen(S_AXI_GP1_AWLEN), + .m_axi_sg_awsize(S_AXI_GP1_AWSIZE), + .m_axi_sg_awburst(S_AXI_GP1_AWBURST), + .m_axi_sg_awprot(S_AXI_GP1_AWPROT), + .m_axi_sg_awcache(S_AXI_GP1_AWCACHE), + .m_axi_sg_awvalid(S_AXI_GP1_AWVALID), + .m_axi_sg_awready(S_AXI_GP1_AWREADY), + .m_axi_sg_wdata(S_AXI_GP1_WDATA), + .m_axi_sg_wstrb(S_AXI_GP1_WSTRB), + .m_axi_sg_wlast(S_AXI_GP1_WLAST), + .m_axi_sg_wvalid(S_AXI_GP1_WVALID), + .m_axi_sg_wready(S_AXI_GP1_WREADY), + .m_axi_sg_bresp(S_AXI_GP1_BRESP), + .m_axi_sg_bvalid(S_AXI_GP1_BVALID), + .m_axi_sg_bready(S_AXI_GP1_BREADY), + .m_axi_sg_araddr(S_AXI_GP1_ARADDR), + .m_axi_sg_arlen(S_AXI_GP1_ARLEN), + .m_axi_sg_arsize(S_AXI_GP1_ARSIZE), + .m_axi_sg_arburst(S_AXI_GP1_ARBURST), + .m_axi_sg_arprot(S_AXI_GP1_ARPROT), + .m_axi_sg_arcache(S_AXI_GP1_ARCACHE), + .m_axi_sg_arvalid(S_AXI_GP1_ARVALID), + .m_axi_sg_arready(S_AXI_GP1_ARREADY), + .m_axi_sg_rdata(S_AXI_GP1_RDATA), + .m_axi_sg_rresp(S_AXI_GP1_RRESP), + .m_axi_sg_rlast(S_AXI_GP1_RLAST), + .m_axi_sg_rvalid(S_AXI_GP1_RVALID), + .m_axi_sg_rready(S_AXI_GP1_RREADY), + + .m_axi_mm2s_araddr(S_AXI_HP1_ARADDR), + .m_axi_mm2s_arlen(S_AXI_HP1_ARLEN), + .m_axi_mm2s_arsize(S_AXI_HP1_ARSIZE), + .m_axi_mm2s_arburst(S_AXI_HP1_ARBURST), + .m_axi_mm2s_arprot(S_AXI_HP1_ARPROT), + .m_axi_mm2s_arcache(S_AXI_HP1_ARCACHE), + .m_axi_mm2s_arvalid(S_AXI_HP1_ARVALID), + .m_axi_mm2s_arready(S_AXI_HP1_ARREADY), + .m_axi_mm2s_rdata(S_AXI_HP1_RDATA), + .m_axi_mm2s_rresp(S_AXI_HP1_RRESP), + .m_axi_mm2s_rlast(S_AXI_HP1_RLAST), + .m_axi_mm2s_rvalid(S_AXI_HP1_RVALID), + .m_axi_mm2s_rready(S_AXI_HP1_RREADY), + + .mm2s_prmry_reset_out_n(), + .m_axis_mm2s_tdata(arm_eth1_tx_tdata), + .m_axis_mm2s_tkeep(arm_eth1_tx_tkeep), + .m_axis_mm2s_tvalid(arm_eth1_tx_tvalid), + .m_axis_mm2s_tready(arm_eth1_tx_tready), + .m_axis_mm2s_tlast(arm_eth1_tx_tlast), + + .m_axi_s2mm_awaddr(S_AXI_HP1_AWADDR), + .m_axi_s2mm_awlen(S_AXI_HP1_AWLEN), + .m_axi_s2mm_awsize(S_AXI_HP1_AWSIZE), + .m_axi_s2mm_awburst(S_AXI_HP1_AWBURST), + .m_axi_s2mm_awprot(S_AXI_HP1_AWPROT), + .m_axi_s2mm_awcache(S_AXI_HP1_AWCACHE), + .m_axi_s2mm_awvalid(S_AXI_HP1_AWVALID), + .m_axi_s2mm_awready(S_AXI_HP1_AWREADY), + .m_axi_s2mm_wdata(S_AXI_HP1_WDATA), + .m_axi_s2mm_wstrb(S_AXI_HP1_WSTRB), + .m_axi_s2mm_wlast(S_AXI_HP1_WLAST), + .m_axi_s2mm_wvalid(S_AXI_HP1_WVALID), + .m_axi_s2mm_wready(S_AXI_HP1_WREADY), + .m_axi_s2mm_bresp(S_AXI_HP1_BRESP), + .m_axi_s2mm_bvalid(S_AXI_HP1_BVALID), + .m_axi_s2mm_bready(S_AXI_HP1_BREADY), + + .s2mm_prmry_reset_out_n(), + .s_axis_s2mm_tdata(arm_eth1_rx_tdata), + .s_axis_s2mm_tkeep(arm_eth1_rx_tkeep), + .s_axis_s2mm_tvalid(arm_eth1_rx_tvalid), + .s_axis_s2mm_tready(arm_eth1_rx_tready), + .s_axis_s2mm_tlast(arm_eth1_rx_tlast), + + .mm2s_introut(arm_eth1_tx_irq), + .s2mm_introut(arm_eth1_rx_irq), + .axi_dma_tstvec() + ); + + axi_fifo_2clk #( + .WIDTH(1+8+64), + .SIZE(5) + ) eth_tx_1_fifo_2clk_i ( + .reset(clk40_rst), + .i_aclk(clk40), + .i_tdata({arm_eth1_tx_tlast, arm_eth1_tx_tkeep, arm_eth1_tx_tdata}), + .i_tvalid(arm_eth1_tx_tvalid), + .i_tready(arm_eth1_tx_tready), + .o_aclk(bus_clk), + .o_tdata({arm_eth1_tx_tlast_b, arm_eth1_tx_tkeep_b, arm_eth1_tx_tdata_b}), + .o_tvalid(arm_eth1_tx_tvalid_b), + .o_tready(arm_eth1_tx_tready_b) + ); + + axi_fifo_2clk #( + .WIDTH(1+8+64), + .SIZE(5) + ) eth_rx_1_fifo_2clk_i ( + .reset(bus_rst), + .i_aclk(bus_clk), + .i_tdata({arm_eth1_rx_tlast_b, arm_eth1_rx_tkeep_b, arm_eth1_rx_tdata_b}), + .i_tvalid(arm_eth1_rx_tvalid_b), + .i_tready(arm_eth1_rx_tready_b), + .o_aclk(clk40), + .o_tdata({arm_eth1_rx_tlast, arm_eth1_rx_tkeep, arm_eth1_rx_tdata}), + .o_tvalid(arm_eth1_rx_tvalid), + .o_tready(arm_eth1_rx_tready) + ); +`endif + + ///////////////////////////////////////////////////////////////////// + // + // Processing System + // + ////////////////////////////////////////////////////////////////////// + + wire spi0_sclk; + wire spi0_mosi; + wire spi0_miso; + wire spi0_ss0; + wire spi0_ss1; + wire spi0_ss2; + wire spi1_sclk; + wire spi1_mosi; + wire spi1_miso; + wire spi1_ss0; + wire spi1_ss1; + wire spi1_ss2; + + assign DBA_MODULE_PWR_ENABLE = ps_gpio_out[8]; + assign DBA_RF_PWR_ENABLE = ps_gpio_out[9]; + assign DBB_MODULE_PWR_ENABLE = ps_gpio_out[10]; + assign DBB_RF_PWR_ENABLE = ps_gpio_out[11]; + assign ps_gpio_in[8] = DBA_MODULE_PWR_ENABLE; + assign ps_gpio_in[9] = DBA_RF_PWR_ENABLE; + assign ps_gpio_in[10] = DBB_MODULE_PWR_ENABLE; + assign ps_gpio_in[11] = DBB_RF_PWR_ENABLE; + + // Processing System + n310_ps_bd inst_n310_ps ( + .SPI0_SCLK_I(1'b0), + .SPI0_SCLK_O(spi0_sclk), + .SPI0_SCLK_T(), + .SPI0_MOSI_I(1'b0), + .SPI0_MOSI_O(spi0_mosi), + .SPI0_MOSI_T(), + .SPI0_MISO_I(spi0_miso), + .SPI0_MISO_O(), + .SPI0_MISO_T(), + .SPI0_SS_I(1'b1), + .SPI0_SS_O(spi0_ss0), + .SPI0_SS1_O(spi0_ss1), + .SPI0_SS2_O(spi0_ss2), + .SPI0_SS_T(), + + .SPI1_SCLK_I(1'b0), + .SPI1_SCLK_O(spi1_sclk), + .SPI1_SCLK_T(), + .SPI1_MOSI_I(1'b0), + .SPI1_MOSI_O(spi1_mosi), + .SPI1_MOSI_T(), + .SPI1_MISO_I(spi1_miso), + .SPI1_MISO_O(), + .SPI1_MISO_T(), + .SPI1_SS_I(1'b1), + .SPI1_SS_O(spi1_ss0), + .SPI1_SS1_O(spi1_ss1), + .SPI1_SS2_O(spi1_ss2), + .SPI1_SS_T(), + + .bus_clk(bus_clk), + .bus_rstn(~bus_rst), + .clk40(clk40), + .clk40_rstn(clk40_rstn), + + .M_AXI_ETH_DMA0_araddr(M_AXI_ETH_DMA0_ARADDR), + .M_AXI_ETH_DMA0_arprot(), + .M_AXI_ETH_DMA0_arready(M_AXI_ETH_DMA0_ARREADY), + .M_AXI_ETH_DMA0_arvalid(M_AXI_ETH_DMA0_ARVALID), + + .M_AXI_ETH_DMA0_awaddr(M_AXI_ETH_DMA0_AWADDR), + .M_AXI_ETH_DMA0_awprot(), + .M_AXI_ETH_DMA0_awready(M_AXI_ETH_DMA0_AWREADY), + .M_AXI_ETH_DMA0_awvalid(M_AXI_ETH_DMA0_AWVALID), + + .M_AXI_ETH_DMA0_wdata(M_AXI_ETH_DMA0_WDATA), + .M_AXI_ETH_DMA0_wready(M_AXI_ETH_DMA0_WREADY), + .M_AXI_ETH_DMA0_wstrb(M_AXI_ETH_DMA0_WSTRB), + .M_AXI_ETH_DMA0_wvalid(M_AXI_ETH_DMA0_WVALID), + + .M_AXI_ETH_DMA0_rdata(M_AXI_ETH_DMA0_RDATA), + .M_AXI_ETH_DMA0_rready(M_AXI_ETH_DMA0_RREADY), + .M_AXI_ETH_DMA0_rresp(M_AXI_ETH_DMA0_RRESP), + .M_AXI_ETH_DMA0_rvalid(M_AXI_ETH_DMA0_RVALID), + + .M_AXI_ETH_DMA0_bready(M_AXI_ETH_DMA0_BREADY), + .M_AXI_ETH_DMA0_bresp(M_AXI_ETH_DMA0_BRESP), + .M_AXI_ETH_DMA0_bvalid(M_AXI_ETH_DMA0_BVALID), + + .M_AXI_ETH_DMA1_araddr(M_AXI_ETH_DMA1_ARADDR), + .M_AXI_ETH_DMA1_arprot(), + .M_AXI_ETH_DMA1_arready(M_AXI_ETH_DMA1_ARREADY), + .M_AXI_ETH_DMA1_arvalid(M_AXI_ETH_DMA1_ARVALID), + + .M_AXI_ETH_DMA1_awaddr(M_AXI_ETH_DMA1_AWADDR), + .M_AXI_ETH_DMA1_awprot(), + .M_AXI_ETH_DMA1_awready(M_AXI_ETH_DMA1_AWREADY), + .M_AXI_ETH_DMA1_awvalid(M_AXI_ETH_DMA1_AWVALID), + + .M_AXI_ETH_DMA1_bready(M_AXI_ETH_DMA1_BREADY), + .M_AXI_ETH_DMA1_bresp(M_AXI_ETH_DMA1_BRESP), + .M_AXI_ETH_DMA1_bvalid(M_AXI_ETH_DMA1_BVALID), + + .M_AXI_ETH_DMA1_rdata(M_AXI_ETH_DMA1_RDATA), + .M_AXI_ETH_DMA1_rready(M_AXI_ETH_DMA1_RREADY), + .M_AXI_ETH_DMA1_rresp(M_AXI_ETH_DMA1_RRESP), + .M_AXI_ETH_DMA1_rvalid(M_AXI_ETH_DMA1_RVALID), + + .M_AXI_ETH_DMA1_wdata(M_AXI_ETH_DMA1_WDATA), + .M_AXI_ETH_DMA1_wready(M_AXI_ETH_DMA1_WREADY), + .M_AXI_ETH_DMA1_wstrb(M_AXI_ETH_DMA1_WSTRB), + .M_AXI_ETH_DMA1_wvalid(M_AXI_ETH_DMA1_WVALID), + + .M_AXI_JESD0_araddr(M_AXI_JESD0_ARADDR), + .M_AXI_JESD0_arprot(), + .M_AXI_JESD0_arready(M_AXI_JESD0_ARREADY), + .M_AXI_JESD0_arvalid(M_AXI_JESD0_ARVALID), + + .M_AXI_JESD0_awaddr(M_AXI_JESD0_AWADDR), + .M_AXI_JESD0_awprot(), + .M_AXI_JESD0_awready(M_AXI_JESD0_AWREADY), + .M_AXI_JESD0_awvalid(M_AXI_JESD0_AWVALID), + + .M_AXI_JESD0_bready(M_AXI_JESD0_BREADY), + .M_AXI_JESD0_bresp(M_AXI_JESD0_BRESP), + .M_AXI_JESD0_bvalid(M_AXI_JESD0_BVALID), + + .M_AXI_JESD0_rdata(M_AXI_JESD0_RDATA), + .M_AXI_JESD0_rready(M_AXI_JESD0_RREADY), + .M_AXI_JESD0_rresp(M_AXI_JESD0_RRESP), + .M_AXI_JESD0_rvalid(M_AXI_JESD0_RVALID), + + .M_AXI_JESD0_wdata(M_AXI_JESD0_WDATA), + .M_AXI_JESD0_wready(M_AXI_JESD0_WREADY), + .M_AXI_JESD0_wstrb(M_AXI_JESD0_WSTRB), + .M_AXI_JESD0_wvalid(M_AXI_JESD0_WVALID), + + .M_AXI_JESD1_araddr(M_AXI_JESD1_ARADDR), + .M_AXI_JESD1_arprot(), + .M_AXI_JESD1_arready(M_AXI_JESD1_ARREADY), + .M_AXI_JESD1_arvalid(M_AXI_JESD1_ARVALID), + + .M_AXI_JESD1_awaddr(M_AXI_JESD1_AWADDR), + .M_AXI_JESD1_awprot(), + .M_AXI_JESD1_awready(M_AXI_JESD1_AWREADY), + .M_AXI_JESD1_awvalid(M_AXI_JESD1_AWVALID), + + .M_AXI_JESD1_bready(M_AXI_JESD1_BREADY), + .M_AXI_JESD1_bresp(M_AXI_JESD1_BRESP), + .M_AXI_JESD1_bvalid(M_AXI_JESD1_BVALID), + + .M_AXI_JESD1_rdata(M_AXI_JESD1_RDATA), + .M_AXI_JESD1_rready(M_AXI_JESD1_RREADY), + .M_AXI_JESD1_rresp(M_AXI_JESD1_RRESP), + .M_AXI_JESD1_rvalid(M_AXI_JESD1_RVALID), + + .M_AXI_JESD1_wdata(M_AXI_JESD1_WDATA), + .M_AXI_JESD1_wready(M_AXI_JESD1_WREADY), + .M_AXI_JESD1_wstrb(M_AXI_JESD1_WSTRB), + .M_AXI_JESD1_wvalid(M_AXI_JESD1_WVALID), + + .M_AXI_NET0_araddr(M_AXI_NET0_ARADDR), + .M_AXI_NET0_arprot(), + .M_AXI_NET0_arready(M_AXI_NET0_ARREADY), + .M_AXI_NET0_arvalid(M_AXI_NET0_ARVALID), + + .M_AXI_NET0_awaddr(M_AXI_NET0_AWADDR), + .M_AXI_NET0_awprot(), + .M_AXI_NET0_awready(M_AXI_NET0_AWREADY), + .M_AXI_NET0_awvalid(M_AXI_NET0_AWVALID), + + .M_AXI_NET0_bready(M_AXI_NET0_BREADY), + .M_AXI_NET0_bresp(M_AXI_NET0_BRESP), + .M_AXI_NET0_bvalid(M_AXI_NET0_BVALID), + + .M_AXI_NET0_rdata(M_AXI_NET0_RDATA), + .M_AXI_NET0_rready(M_AXI_NET0_RREADY), + .M_AXI_NET0_rresp(M_AXI_NET0_RRESP), + .M_AXI_NET0_rvalid(M_AXI_NET0_RVALID), + + .M_AXI_NET0_wdata(M_AXI_NET0_WDATA), + .M_AXI_NET0_wready(M_AXI_NET0_WREADY), + .M_AXI_NET0_wstrb(M_AXI_NET0_WSTRB), + .M_AXI_NET0_wvalid(M_AXI_NET0_WVALID), + + .M_AXI_NET1_araddr(M_AXI_NET1_ARADDR), + .M_AXI_NET1_arprot(), + .M_AXI_NET1_arready(M_AXI_NET1_ARREADY), + .M_AXI_NET1_arvalid(M_AXI_NET1_ARVALID), + + .M_AXI_NET1_awaddr(M_AXI_NET1_AWADDR), + .M_AXI_NET1_awprot(), + .M_AXI_NET1_awready(M_AXI_NET1_AWREADY), + .M_AXI_NET1_awvalid(M_AXI_NET1_AWVALID), + + .M_AXI_NET1_bready(M_AXI_NET1_BREADY), + .M_AXI_NET1_bresp(M_AXI_NET1_BRESP), + .M_AXI_NET1_bvalid(M_AXI_NET1_BVALID), + + .M_AXI_NET1_rdata(M_AXI_NET1_RDATA), + .M_AXI_NET1_rready(M_AXI_NET1_RREADY), + .M_AXI_NET1_rresp(M_AXI_NET1_RRESP), + .M_AXI_NET1_rvalid(M_AXI_NET1_RVALID), + + .M_AXI_NET1_wdata(M_AXI_NET1_WDATA), + .M_AXI_NET1_wready(M_AXI_NET1_WREADY), + .M_AXI_NET1_wstrb(M_AXI_NET1_WSTRB), + .M_AXI_NET1_wvalid(M_AXI_NET1_WVALID), + + .M_AXI_NET2_araddr(M_AXI_NET2_ARADDR), + .M_AXI_NET2_arprot(), + .M_AXI_NET2_arready(M_AXI_NET2_ARREADY), + .M_AXI_NET2_arvalid(M_AXI_NET2_ARVALID), + + .M_AXI_NET2_awaddr(M_AXI_NET2_AWADDR), + .M_AXI_NET2_awprot(), + .M_AXI_NET2_awready(M_AXI_NET2_AWREADY), + .M_AXI_NET2_awvalid(M_AXI_NET2_AWVALID), + + .M_AXI_NET2_bready(M_AXI_NET2_BREADY), + .M_AXI_NET2_bresp(M_AXI_NET2_BRESP), + .M_AXI_NET2_bvalid(M_AXI_NET2_BVALID), + + .M_AXI_NET2_rdata(M_AXI_NET2_RDATA), + .M_AXI_NET2_rready(M_AXI_NET2_RREADY), + .M_AXI_NET2_rresp(M_AXI_NET2_RRESP), + .M_AXI_NET2_rvalid(M_AXI_NET2_RVALID), + + .M_AXI_NET2_wdata(M_AXI_NET2_WDATA), + .M_AXI_NET2_wready(M_AXI_NET2_WREADY), + .M_AXI_NET2_wstrb(M_AXI_NET2_WSTRB), + .M_AXI_NET2_wvalid(M_AXI_NET2_WVALID), + + .M_AXI_WR_CLK(m_axi_wr_clk), + .M_AXI_WR_RSTn(1'b1), + .M_AXI_WR_araddr(m_axi_wr_araddr), + .M_AXI_WR_arready(m_axi_wr_arready), + .M_AXI_WR_arvalid(m_axi_wr_arvalid), + .M_AXI_WR_arprot(), + .M_AXI_WR_awaddr(m_axi_wr_awaddr), + .M_AXI_WR_awready(m_axi_wr_awready), + .M_AXI_WR_awvalid(m_axi_wr_awvalid), + .M_AXI_WR_awprot(), + .M_AXI_WR_bready(m_axi_wr_bready), + .M_AXI_WR_bresp(m_axi_wr_bresp), + .M_AXI_WR_bvalid(m_axi_wr_bvalid), + .M_AXI_WR_rdata(m_axi_wr_rdata), + .M_AXI_WR_rready(m_axi_wr_rready), + .M_AXI_WR_rresp(m_axi_wr_rresp), + .M_AXI_WR_rvalid(m_axi_wr_rvalid), + .M_AXI_WR_wdata(m_axi_wr_wdata), + .M_AXI_WR_wready(m_axi_wr_wready), + .M_AXI_WR_wstrb(m_axi_wr_wstrb), + .M_AXI_WR_wvalid(m_axi_wr_wvalid), + + .M_AXI_XBAR_araddr(M_AXI_XBAR_ARADDR), + .M_AXI_XBAR_arprot(), + .M_AXI_XBAR_arready(M_AXI_XBAR_ARREADY), + .M_AXI_XBAR_arvalid(M_AXI_XBAR_ARVALID), + + .M_AXI_XBAR_awaddr(M_AXI_XBAR_AWADDR), + .M_AXI_XBAR_awprot(), + .M_AXI_XBAR_awready(M_AXI_XBAR_AWREADY), + .M_AXI_XBAR_awvalid(M_AXI_XBAR_AWVALID), + + .M_AXI_XBAR_bready(M_AXI_XBAR_BREADY), + .M_AXI_XBAR_bresp(M_AXI_XBAR_BRESP), + .M_AXI_XBAR_bvalid(M_AXI_XBAR_BVALID), + + .M_AXI_XBAR_rdata(M_AXI_XBAR_RDATA), + .M_AXI_XBAR_rready(M_AXI_XBAR_RREADY), + .M_AXI_XBAR_rresp(M_AXI_XBAR_RRESP), + .M_AXI_XBAR_rvalid(M_AXI_XBAR_RVALID), + + .M_AXI_XBAR_wdata(M_AXI_XBAR_WDATA), + .M_AXI_XBAR_wready(M_AXI_XBAR_WREADY), + .M_AXI_XBAR_wstrb(M_AXI_XBAR_WSTRB), + .M_AXI_XBAR_wvalid(M_AXI_XBAR_WVALID), + + .S_AXI_GP0_ACLK(clk40), + .S_AXI_GP0_ARESETN(clk40_rstn), + .S_AXI_GP0_araddr(S_AXI_GP0_ARADDR), + .S_AXI_GP0_arburst(S_AXI_GP0_ARBURST), + .S_AXI_GP0_arcache(S_AXI_GP0_ARCACHE), + .S_AXI_GP0_arid(S_AXI_GP0_ARID), + .S_AXI_GP0_arlen(S_AXI_GP0_ARLEN), + .S_AXI_GP0_arlock(1'b0), + .S_AXI_GP0_arprot(S_AXI_GP0_ARPROT), + .S_AXI_GP0_arqos(4'b0000), + .S_AXI_GP0_arready(S_AXI_GP0_ARREADY), + .S_AXI_GP0_arregion(4'b0000), + .S_AXI_GP0_arsize(S_AXI_GP0_ARSIZE), + .S_AXI_GP0_arvalid(S_AXI_GP0_ARVALID), + .S_AXI_GP0_awaddr(S_AXI_GP0_AWADDR), + .S_AXI_GP0_awburst(S_AXI_GP0_AWBURST), + .S_AXI_GP0_awcache(S_AXI_GP0_AWCACHE), + .S_AXI_GP0_awid(S_AXI_GP0_AWID), + .S_AXI_GP0_awlen(S_AXI_GP0_AWLEN), + .S_AXI_GP0_awlock(1'b0), + .S_AXI_GP0_awprot(S_AXI_GP0_AWPROT), + .S_AXI_GP0_awqos(4'b0000), + .S_AXI_GP0_awregion(4'b0000), + .S_AXI_GP0_awready(S_AXI_GP0_AWREADY), + .S_AXI_GP0_awsize(S_AXI_GP0_AWSIZE), + .S_AXI_GP0_awvalid(S_AXI_GP0_AWVALID), + .S_AXI_GP0_bid(), + .S_AXI_GP0_bready(S_AXI_GP0_BREADY), + .S_AXI_GP0_bresp(S_AXI_GP0_BRESP), + .S_AXI_GP0_bvalid(S_AXI_GP0_BVALID), + .S_AXI_GP0_rdata(S_AXI_GP0_RDATA), + .S_AXI_GP0_rid(), + .S_AXI_GP0_rlast(S_AXI_GP0_RLAST), + .S_AXI_GP0_rready(S_AXI_GP0_RREADY), + .S_AXI_GP0_rresp(S_AXI_GP0_RRESP), + .S_AXI_GP0_rvalid(S_AXI_GP0_RVALID), + .S_AXI_GP0_wdata(S_AXI_GP0_WDATA), + .S_AXI_GP0_wlast(S_AXI_GP0_WLAST), + .S_AXI_GP0_wready(S_AXI_GP0_WREADY), + .S_AXI_GP0_wstrb(S_AXI_GP0_WSTRB), + .S_AXI_GP0_wvalid(S_AXI_GP0_WVALID), + + .S_AXI_GP1_ACLK(clk40), + .S_AXI_GP1_ARESETN(clk40_rstn), + .S_AXI_GP1_araddr(S_AXI_GP1_ARADDR), + .S_AXI_GP1_arburst(S_AXI_GP1_ARBURST), + .S_AXI_GP1_arcache(S_AXI_GP1_ARCACHE), + .S_AXI_GP1_arid(S_AXI_GP1_ARID), + .S_AXI_GP1_arlen(S_AXI_GP1_ARLEN), + .S_AXI_GP1_arlock(1'b0), + .S_AXI_GP1_arprot(S_AXI_GP1_ARPROT), + .S_AXI_GP1_arqos(4'b000), + .S_AXI_GP1_arregion(4'b0000), + .S_AXI_GP1_arready(S_AXI_GP1_ARREADY), + .S_AXI_GP1_arsize(S_AXI_GP1_ARSIZE), + .S_AXI_GP1_arvalid(S_AXI_GP1_ARVALID), + .S_AXI_GP1_awaddr(S_AXI_GP1_AWADDR), + .S_AXI_GP1_awburst(S_AXI_GP1_AWBURST), + .S_AXI_GP1_awcache(S_AXI_GP1_AWCACHE), + .S_AXI_GP1_awid(S_AXI_GP1_AWID), + .S_AXI_GP1_awlen(S_AXI_GP1_AWLEN), + .S_AXI_GP1_awlock(1'b0), + .S_AXI_GP1_awprot(S_AXI_GP1_AWPROT), + .S_AXI_GP1_awqos(4'b0000), + .S_AXI_GP1_awregion(4'b0000), + .S_AXI_GP1_awready(S_AXI_GP1_AWREADY), + .S_AXI_GP1_awsize(S_AXI_GP1_AWSIZE), + .S_AXI_GP1_awvalid(S_AXI_GP1_AWVALID), + .S_AXI_GP1_bid(), + .S_AXI_GP1_bready(S_AXI_GP1_BREADY), + .S_AXI_GP1_bresp(S_AXI_GP1_BRESP), + .S_AXI_GP1_bvalid(S_AXI_GP1_BVALID), + .S_AXI_GP1_rdata(S_AXI_GP1_RDATA), + .S_AXI_GP1_rid(), + .S_AXI_GP1_rlast(S_AXI_GP1_RLAST), + .S_AXI_GP1_rready(S_AXI_GP1_RREADY), + .S_AXI_GP1_rresp(S_AXI_GP1_RRESP), + .S_AXI_GP1_rvalid(S_AXI_GP1_RVALID), + .S_AXI_GP1_wdata(S_AXI_GP1_WDATA), + .S_AXI_GP1_wlast(S_AXI_GP1_WLAST), + .S_AXI_GP1_wready(S_AXI_GP1_WREADY), + .S_AXI_GP1_wstrb(S_AXI_GP1_WSTRB), + .S_AXI_GP1_wvalid(S_AXI_GP1_WVALID), + + .S_AXI_HP0_ACLK(clk40), + .S_AXI_HP0_ARESETN(clk40_rstn), + .S_AXI_HP0_araddr(S_AXI_HP0_ARADDR), + .S_AXI_HP0_arburst(S_AXI_HP0_ARBURST), + .S_AXI_HP0_arcache(S_AXI_HP0_ARCACHE), + .S_AXI_HP0_arid(S_AXI_HP0_ARID), + .S_AXI_HP0_arlen(S_AXI_HP0_ARLEN), + .S_AXI_HP0_arlock(1'b0), + .S_AXI_HP0_arprot(S_AXI_HP0_ARPROT), + .S_AXI_HP0_arqos(4'b0000), + .S_AXI_HP0_arready(S_AXI_HP0_ARREADY), + .S_AXI_HP0_arsize(S_AXI_HP0_ARSIZE), + .S_AXI_HP0_arvalid(S_AXI_HP0_ARVALID), + .S_AXI_HP0_awaddr(S_AXI_HP0_AWADDR), + .S_AXI_HP0_awburst(S_AXI_HP0_AWBURST), + .S_AXI_HP0_awcache(S_AXI_HP0_AWCACHE), + .S_AXI_HP0_awid(S_AXI_HP0_AWID), + .S_AXI_HP0_awlen(S_AXI_HP0_AWLEN), + .S_AXI_HP0_awlock(1'b0), + .S_AXI_HP0_awprot(S_AXI_HP0_AWPROT), + .S_AXI_HP0_awqos(4'b0000), + .S_AXI_HP0_awready(S_AXI_HP0_AWREADY), + .S_AXI_HP0_awsize(S_AXI_HP0_AWSIZE), + .S_AXI_HP0_awvalid(S_AXI_HP0_AWVALID), + .S_AXI_HP0_bid(), + .S_AXI_HP0_bready(S_AXI_HP0_BREADY), + .S_AXI_HP0_bresp(S_AXI_HP0_BRESP), + .S_AXI_HP0_bvalid(S_AXI_HP0_BVALID), + .S_AXI_HP0_rdata(S_AXI_HP0_RDATA), + .S_AXI_HP0_rid(), + .S_AXI_HP0_rlast(S_AXI_HP0_RLAST), + .S_AXI_HP0_rready(S_AXI_HP0_RREADY), + .S_AXI_HP0_rresp(S_AXI_HP0_RRESP), + .S_AXI_HP0_rvalid(S_AXI_HP0_RVALID), + .S_AXI_HP0_wdata(S_AXI_HP0_WDATA), + .S_AXI_HP0_wlast(S_AXI_HP0_WLAST), + .S_AXI_HP0_wready(S_AXI_HP0_WREADY), + .S_AXI_HP0_wstrb(S_AXI_HP0_WSTRB), + .S_AXI_HP0_wvalid(S_AXI_HP0_WVALID), + + .S_AXI_HP1_ACLK(clk40), + .S_AXI_HP1_ARESETN(clk40_rstn), + .S_AXI_HP1_araddr(S_AXI_HP1_ARADDR), + .S_AXI_HP1_arburst(S_AXI_HP1_ARBURST), + .S_AXI_HP1_arcache(S_AXI_HP1_ARCACHE), + .S_AXI_HP1_arid(S_AXI_HP1_ARID), + .S_AXI_HP1_arlen(S_AXI_HP1_ARLEN), + .S_AXI_HP1_arlock(1'b0), + .S_AXI_HP1_arprot(S_AXI_HP1_ARPROT), + .S_AXI_HP1_arqos(4'b0000), + .S_AXI_HP1_arready(S_AXI_HP1_ARREADY), + .S_AXI_HP1_arsize(S_AXI_HP1_ARSIZE), + .S_AXI_HP1_arvalid(S_AXI_HP1_ARVALID), + .S_AXI_HP1_awaddr(S_AXI_HP1_AWADDR), + .S_AXI_HP1_awburst(S_AXI_HP1_AWBURST), + .S_AXI_HP1_awcache(S_AXI_HP1_AWCACHE), + .S_AXI_HP1_awid(S_AXI_HP1_AWID), + .S_AXI_HP1_awlen(S_AXI_HP1_AWLEN), + .S_AXI_HP1_awlock(1'b0), + .S_AXI_HP1_awprot(S_AXI_HP1_AWPROT), + .S_AXI_HP1_awqos(4'b0000), + .S_AXI_HP1_awready(S_AXI_HP1_AWREADY), + .S_AXI_HP1_awsize(S_AXI_HP1_AWSIZE), + .S_AXI_HP1_awvalid(S_AXI_HP1_AWVALID), + .S_AXI_HP1_bid(), + .S_AXI_HP1_bready(S_AXI_HP1_BREADY), + .S_AXI_HP1_bresp(S_AXI_HP1_BRESP), + .S_AXI_HP1_bvalid(S_AXI_HP1_BVALID), + .S_AXI_HP1_rdata(S_AXI_HP1_RDATA), + .S_AXI_HP1_rid(), + .S_AXI_HP1_rlast(S_AXI_HP1_RLAST), + .S_AXI_HP1_rready(S_AXI_HP1_RREADY), + .S_AXI_HP1_rresp(S_AXI_HP1_RRESP), + .S_AXI_HP1_rvalid(S_AXI_HP1_RVALID), + .S_AXI_HP1_wdata(S_AXI_HP1_WDATA), + .S_AXI_HP1_wlast(S_AXI_HP1_WLAST), + .S_AXI_HP1_wready(S_AXI_HP1_WREADY), + .S_AXI_HP1_wstrb(S_AXI_HP1_WSTRB), + .S_AXI_HP1_wvalid(S_AXI_HP1_WVALID), + + // ARM DMA + .s_axis_dma_tdata(s_axis_dma_tdata), + .s_axis_dma_tdest(s_axis_dma_tdest), + .s_axis_dma_tlast(s_axis_dma_tlast), + .s_axis_dma_tready(s_axis_dma_tready), + .s_axis_dma_tvalid(s_axis_dma_tvalid), + .m_axis_dma_tdata(m_axis_dma_tdata), + .m_axis_dma_tuser(m_axis_dma_tuser), + .m_axis_dma_tlast(m_axis_dma_tlast), + .m_axis_dma_tready(m_axis_dma_tready), + .m_axis_dma_tvalid(m_axis_dma_tvalid), + + // Misc Interrupts, GPIO, clk + .IRQ_F2P(IRQ_F2P), + + .GPIO_0_tri_i(ps_gpio_in), + .GPIO_0_tri_o(ps_gpio_out), + .GPIO_0_tri_t(ps_gpio_tri), + + .JTAG0_TCK(DBA_CPLD_JTAG_TCK), + .JTAG0_TMS(DBA_CPLD_JTAG_TMS), + .JTAG0_TDI(DBA_CPLD_JTAG_TDI), + .JTAG0_TDO(DBA_CPLD_JTAG_TDO), + + .JTAG1_TCK(DBB_CPLD_JTAG_TCK), + .JTAG1_TMS(DBB_CPLD_JTAG_TMS), + .JTAG1_TDI(DBB_CPLD_JTAG_TDI), + .JTAG1_TDO(DBB_CPLD_JTAG_TDO), + + .FCLK_CLK0(FCLK_CLK0), + .FCLK_RESET0_N(FCLK_RESET0_N), + .FCLK_CLK1(FCLK_CLK1), + .FCLK_RESET1_N(), + .FCLK_CLK2(FCLK_CLK2), + .FCLK_RESET2_N(), + .FCLK_CLK3(FCLK_CLK3), + .FCLK_RESET3_N(), + + .WR_UART_txd(wr_uart_rxd), // rx <-> tx + .WR_UART_rxd(wr_uart_txd), // rx <-> tx + + .qsfp_sda_i(qsfp_sda_i), + .qsfp_sda_o(qsfp_sda_o), + .qsfp_sda_t(qsfp_sda_t), + .qsfp_scl_i(qsfp_scl_i), + .qsfp_scl_o(qsfp_scl_o), + .qsfp_scl_t(qsfp_scl_t), + + .USBIND_0_port_indctl(), + .USBIND_0_vbus_pwrfault(), + .USBIND_0_vbus_pwrselect(), + + // Outward connections to the pins + .MIO(MIO), + .DDR_cas_n(DDR_CAS_n), + .DDR_cke(DDR_CKE), + .DDR_ck_n(DDR_Clk_n), + .DDR_ck_p(DDR_Clk), + .DDR_cs_n(DDR_CS_n), + .DDR_reset_n(DDR_DRSTB), + .DDR_odt(DDR_ODT), + .DDR_ras_n(DDR_RAS_n), + .DDR_we_n(DDR_WEB), + .DDR_ba(DDR_BankAddr), + .DDR_addr(DDR_Addr), + .DDR_VRN(DDR_VRN), + .DDR_VRP(DDR_VRP), + .DDR_dm(DDR_DM), + .DDR_dq(DDR_DQ), + .DDR_dqs_n(DDR_DQS_n), + .DDR_dqs_p(DDR_DQS), + .PS_SRSTB(PS_SRSTB), + .PS_CLK(PS_CLK), + .PS_PORB(PS_PORB) + ); + + /////////////////////////////////////////////////////////////////////////////////// + // + // Xilinx DDR3 Controller and PHY. + // + /////////////////////////////////////////////////////////////////////////////////// + + wire ddr3_axi_clk; // 1/4 DDR external clock rate (200MHz) + wire ddr3_axi_rst; // Synchronized to ddr_sys_clk + wire ddr3_running; // DRAM calibration complete. + wire [11:0] device_temp; + + // Slave Interface Write Address Ports + wire [3:0] ddr3_axi_awid; + wire [31:0] ddr3_axi_awaddr; + wire [7:0] ddr3_axi_awlen; + wire [2:0] ddr3_axi_awsize; + wire [1:0] ddr3_axi_awburst; + wire [0:0] ddr3_axi_awlock; + wire [3:0] ddr3_axi_awcache; + wire [2:0] ddr3_axi_awprot; + wire [3:0] ddr3_axi_awqos; + wire ddr3_axi_awvalid; + wire ddr3_axi_awready; + // Slave Interface Write Data Ports + wire [255:0] ddr3_axi_wdata; + wire [31:0] ddr3_axi_wstrb; + wire ddr3_axi_wlast; + wire ddr3_axi_wvalid; + wire ddr3_axi_wready; + // Slave Interface Write Response Ports + wire ddr3_axi_bready; + wire [3:0] ddr3_axi_bid; + wire [1:0] ddr3_axi_bresp; + wire ddr3_axi_bvalid; + // Slave Interface Read Address Ports + wire [3:0] ddr3_axi_arid; + wire [31:0] ddr3_axi_araddr; + wire [7:0] ddr3_axi_arlen; + wire [2:0] ddr3_axi_arsize; + wire [1:0] ddr3_axi_arburst; + wire [0:0] ddr3_axi_arlock; + wire [3:0] ddr3_axi_arcache; + wire [2:0] ddr3_axi_arprot; + wire [3:0] ddr3_axi_arqos; + wire ddr3_axi_arvalid; + wire ddr3_axi_arready; + // Slave Interface Read Data Ports + wire ddr3_axi_rready; + wire [3:0] ddr3_axi_rid; + wire [255:0] ddr3_axi_rdata; + wire [1:0] ddr3_axi_rresp; + wire ddr3_axi_rlast; + wire ddr3_axi_rvalid; + + reg ddr3_axi_rst_reg_n; + + // Copied this reset circuit from example design. + always @(posedge ddr3_axi_clk) + ddr3_axi_rst_reg_n <= ~ddr3_axi_rst; + + + // Instantiate the DDR3 MIG core + // + // The top-level IP block has no parameters defined for some reason. + // Most of configurable parameters are hard-coded in the mig so get + // some additional knobs we pull those out into verilog headers. + // + // Synthesis params: ip/ddr3_32bit/ddr3_32bit_mig_parameters.vh + // Simulation params: ip/ddr3_32bit/ddr3_32bit_mig_sim_parameters.vh + + ddr3_32bit u_ddr3_32bit ( + // Memory interface ports + .ddr3_addr (ddr3_addr), + .ddr3_ba (ddr3_ba), + .ddr3_cas_n (ddr3_cas_n), + .ddr3_ck_n (ddr3_ck_n), + .ddr3_ck_p (ddr3_ck_p), + .ddr3_cke (ddr3_cke), + .ddr3_ras_n (ddr3_ras_n), + .ddr3_reset_n (ddr3_reset_n), + .ddr3_we_n (ddr3_we_n), + .ddr3_dq (ddr3_dq), + .ddr3_dqs_n (ddr3_dqs_n), + .ddr3_dqs_p (ddr3_dqs_p), + .init_calib_complete (ddr3_running), + .device_temp_i (device_temp), + + .ddr3_cs_n (ddr3_cs_n), + .ddr3_dm (ddr3_dm), + .ddr3_odt (ddr3_odt), + // Application interface ports + .ui_clk (ddr3_axi_clk), // 200Hz clock out + .ui_clk_sync_rst (ddr3_axi_rst), // Active high Reset signal synchronised to 200 MHz. + .aresetn (ddr3_axi_rst_reg_n), + .app_sr_req (1'b0), + .app_sr_active (), + .app_ref_req (1'b0), + .app_ref_ack (), + .app_zq_req (1'b0), + .app_zq_ack (), + // Slave Interface Write Address Ports + .s_axi_awid (ddr3_axi_awid), + .s_axi_awaddr (ddr3_axi_awaddr), + .s_axi_awlen (ddr3_axi_awlen), + .s_axi_awsize (ddr3_axi_awsize), + .s_axi_awburst (ddr3_axi_awburst), + .s_axi_awlock (ddr3_axi_awlock), + .s_axi_awcache (ddr3_axi_awcache), + .s_axi_awprot (ddr3_axi_awprot), + .s_axi_awqos (ddr3_axi_awqos), + .s_axi_awvalid (ddr3_axi_awvalid), + .s_axi_awready (ddr3_axi_awready), + // Slave Interface Write Data Ports + .s_axi_wdata (ddr3_axi_wdata), + .s_axi_wstrb (ddr3_axi_wstrb), + .s_axi_wlast (ddr3_axi_wlast), + .s_axi_wvalid (ddr3_axi_wvalid), + .s_axi_wready (ddr3_axi_wready), + // Slave Interface Write Response Ports + .s_axi_bid (ddr3_axi_bid), + .s_axi_bresp (ddr3_axi_bresp), + .s_axi_bvalid (ddr3_axi_bvalid), + .s_axi_bready (ddr3_axi_bready), + // Slave Interface Read Address Ports + .s_axi_arid (ddr3_axi_arid), + .s_axi_araddr (ddr3_axi_araddr), + .s_axi_arlen (ddr3_axi_arlen), + .s_axi_arsize (ddr3_axi_arsize), + .s_axi_arburst (ddr3_axi_arburst), + .s_axi_arlock (ddr3_axi_arlock), + .s_axi_arcache (ddr3_axi_arcache), + .s_axi_arprot (ddr3_axi_arprot), + .s_axi_arqos (ddr3_axi_arqos), + .s_axi_arvalid (ddr3_axi_arvalid), + .s_axi_arready (ddr3_axi_arready), + // Slave Interface Read Data Ports + .s_axi_rid (ddr3_axi_rid), + .s_axi_rdata (ddr3_axi_rdata), + .s_axi_rresp (ddr3_axi_rresp), + .s_axi_rlast (ddr3_axi_rlast), + .s_axi_rvalid (ddr3_axi_rvalid), + .s_axi_rready (ddr3_axi_rready), + // System Clock Ports + .sys_clk_p (sys_clk_p), + .sys_clk_n (sys_clk_n), + .clk_ref_i (bus_clk), + + .sys_rst (~global_rst) // IJB. Poorly named active low. Should change RST_ACT_LOW. + ); + + // Temperature monitor module + mig_7series_v4_2_tempmon #( + .TEMP_MON_CONTROL("INTERNAL"), + .XADC_CLK_PERIOD(5000 /* 200MHz clock period in ps */) + ) tempmon_i ( + .clk(bus_clk), .xadc_clk(bus_clk), .rst(bus_rst), + .device_temp_i(12'd0 /* ignored */), .device_temp(device_temp) + ); + + /////////////////////////////////////////////////////// + // + // DB PS SPI Connections + // + /////////////////////////////////////////////////////// + wire [NUM_CHANNELS-1:0] rx_atr; + wire [NUM_CHANNELS-1:0] tx_atr; + (* IOB = "true" *) reg [NUM_CHANNELS-1:0] rx_atr_reg; + (* IOB = "true" *) reg [NUM_CHANNELS-1:0] tx_atr_reg; + + // Radio GPIO control for DSA + wire [16*NUM_CHANNELS-1:0] db_gpio_out; + wire [16*NUM_CHANNELS-1:0] db_gpio_ddr; + wire [16*NUM_CHANNELS-1:0] db_gpio_in; + wire [16*NUM_CHANNELS-1:0] db_gpio_fab; + + // DB A SPI Connections + assign DBA_CPLD_PS_SPI_SCLK = spi0_sclk; + assign DBA_CPLD_PS_SPI_MOSI = spi0_mosi; + + // Assign individual chip selects from PS SPI MASTER 0. + assign DBA_CPLD_PS_SPI_CS_B = spi0_ss0; + assign DBA_CLKDIS_SPI_CS_B = spi0_ss1; + assign DBA_PHDAC_SPI_CS_B = spi0_ss2; + assign DBA_ADC_SPI_CS_B = ps_gpio_out[13]; + assign DBA_DAC_SPI_CS_B = ps_gpio_out[14]; + + // Returned data mux from the SPI interfaces. + assign spi0_miso = DBA_CPLD_PS_SPI_MISO; + + // TODO: How to control? + assign DBA_ATR_RX = rx_atr_reg[0]; + assign DBA_ATR_TX = tx_atr_reg[0]; + assign DBA_TXRX_SW_CTRL_1 = db_gpio_out[16*0+0]; + assign DBA_TXRX_SW_CTRL_2 = db_gpio_out[16*0+1]; + assign DBA_LED_RX = db_gpio_out[16*0+2]; + assign DBA_LED_RX2 = db_gpio_out[16*0+3]; + assign DBA_LED_TX = db_gpio_out[16*0+4]; + + // DB B SPI Connections + assign DBB_CPLD_PS_SPI_SCLK = spi1_sclk; + assign DBB_CPLD_PS_SPI_MOSI = spi1_mosi; + + // Assign individual chip selects from PS SPI MASTER 1. + assign DBB_CPLD_PS_SPI_CS_B = spi1_ss0; + assign DBB_CLKDIS_SPI_CS_B = spi1_ss1; + assign DBB_PHDAC_SPI_CS_B = spi1_ss2; + assign DBB_ADC_SPI_CS_B = ps_gpio_out[15]; + assign DBB_DAC_SPI_CS_B = ps_gpio_out[16]; + + // Returned data mux from the SPI interfaces. + assign spi1_miso = DBB_CPLD_PS_SPI_MISO; + + + // TODO: How to control? + assign DBB_ATR_RX = rx_atr_reg[1]; + assign DBB_ATR_TX = tx_atr_reg[1]; + assign DBB_TXRX_SW_CTRL_1 = db_gpio_out[16*1+0]; + assign DBB_TXRX_SW_CTRL_2 = db_gpio_out[16*1+1]; + assign DBB_LED_RX = db_gpio_out[16*1+2]; + assign DBB_LED_RX2 = db_gpio_out[16*1+3]; + assign DBB_LED_TX = db_gpio_out[16*1+4]; + + + /////////////////////////////////////////////////////// + // + // N320 CORE + // + /////////////////////////////////////////////////////// + + wire [CHANNEL_WIDTH-1:0] rx_db[2*NUM_CHANNELS-1:0]; + wire [CHANNEL_WIDTH-1:0] tx_db[2*NUM_CHANNELS-1:0]; + wire [CHANNEL_WIDTH-1:0] rx[NUM_CHANNELS-1:0]; + wire [CHANNEL_WIDTH-1:0] tx[NUM_CHANNELS-1:0]; + wire [CHANNEL_WIDTH*NUM_CHANNELS-1:0] rx_flat; + wire [CHANNEL_WIDTH*NUM_CHANNELS-1:0] tx_flat; + wire [47:0] rx_hb[NUM_CHANNELS-1:0]; + wire [95:0] tx_hb[NUM_CHANNELS-1:0]; + + wire [NUM_CHANNELS-1:0] rx_stb; + wire [NUM_CHANNELS-1:0] tx_stb; + + wire [31:0] build_datestamp; + + /* 2:1 and 1:2 filters to bring sample rates down + */ + genvar i; + generate for (i = 0; i < NUM_CHANNELS; i = i + 1) begin + hb47_1to2 tx_1to2 ( + .aresetn(!radio_rst), + .aclk(radio_clk), + .s_axis_data_tvalid(tx_stb[i]), + .s_axis_data_tready(), + .s_axis_data_tdata(tx[i]), + .m_axis_data_tvalid(), + .m_axis_data_tready(tx_stb[i]), + .m_axis_data_tdata(tx_hb[i]) + ); + + assign tx_db[2*i] = {tx_hb[i][39:24], tx_hb[i][15:0]}; + assign tx_db[2*i+1] = {tx_hb[i][87:72], tx_hb[i][63:48]}; + + hb47_2to1 rx_2to1 ( + .aresetn(!radio_rst), + .aclk(radio_clk), + .s_axis_data_tvalid(rx_stb[i]), + .s_axis_data_tready(), + .s_axis_data_tdata({rx_db[2*i+1], rx_db[2*i]}), + .m_axis_data_tvalid(), + .m_axis_data_tdata(rx_hb[i]) + ); + + assign rx[i] = {rx_hb[i][39:24], rx_hb[i][15:0]}; + end endgenerate + + generate + for (i = 0; i < NUM_CHANNELS; i = i + 1) begin + // Radio Data + assign rx_flat[CHANNEL_WIDTH*i +: CHANNEL_WIDTH] = rx[i]; + assign tx[i] = tx_flat[CHANNEL_WIDTH*i +: CHANNEL_WIDTH]; + end + endgenerate + + USR_ACCESSE2 usr_access_i ( + .DATA(build_datestamp), .CFGCLK(), .DATAVALID() + ); + + n3xx_core #( + .REG_AWIDTH(14), + .BUS_CLK_RATE(BUS_CLK_RATE), + .FP_GPIO_WIDTH(FP_GPIO_WIDTH), + .CHANNEL_WIDTH(CHANNEL_WIDTH), + .NUM_CHANNELS_PER_RADIO(NUM_CHANNELS_PER_RADIO), + .NUM_CHANNELS(NUM_CHANNELS), + .NUM_DBOARDS(NUM_DBOARDS), + .NUM_SPI_PER_DBOARD(4), + .USE_CORRECTION(1), + `ifdef USE_REPLAY + .USE_REPLAY(1) + `else + .USE_REPLAY(0) + `endif + ) n3xx_core( + // Clocks and resets +`ifdef NO_DB + .radio_clk(bus_clk), + .radio_rst(bus_rst), +`else + .radio_clk(radio_clk), + .radio_rst(radio_rst), +`endif + .bus_clk(bus_clk), + .bus_rst(bus_rst), + .ddr3_dma_clk(ddr3_dma_clk), + .clk40(clk40), + + // Clocking and PPS Controls/Indicators + .pps(pps_radioclk1x), + .pps_select(pps_select), + .pps_out_enb(pps_out_enb), + .pps_select_sfp(pps_select_sfp), + .ref_clk_reset(), + .meas_clk_reset(meas_clk_reset), + .ref_clk_locked(1'b1), + .meas_clk_locked(meas_clk_locked), + .enable_ref_clk_async(enable_ref_clk_async), + + .s_axi_aclk(clk40), + .s_axi_aresetn(clk40_rstn), + // AXI4-Lite: Write address port (domain: s_axi_aclk) + .s_axi_awaddr(M_AXI_XBAR_AWADDR), + .s_axi_awvalid(M_AXI_XBAR_AWVALID), + .s_axi_awready(M_AXI_XBAR_AWREADY), + // AXI4-Lite: Write data port (domain: s_axi_aclk) + .s_axi_wdata(M_AXI_XBAR_WDATA), + .s_axi_wstrb(M_AXI_XBAR_WSTRB), + .s_axi_wvalid(M_AXI_XBAR_WVALID), + .s_axi_wready(M_AXI_XBAR_WREADY), + // AXI4-Lite: Write response port (domain: s_axi_aclk) + .s_axi_bresp(M_AXI_XBAR_BRESP), + .s_axi_bvalid(M_AXI_XBAR_BVALID), + .s_axi_bready(M_AXI_XBAR_BREADY), + // AXI4-Lite: Read address port (domain: s_axi_aclk) + .s_axi_araddr(M_AXI_XBAR_ARADDR), + .s_axi_arvalid(M_AXI_XBAR_ARVALID), + .s_axi_arready(M_AXI_XBAR_ARREADY), + // AXI4-Lite: Read data port (domain: s_axi_aclk) + .s_axi_rdata(M_AXI_XBAR_RDATA), + .s_axi_rresp(M_AXI_XBAR_RRESP), + .s_axi_rvalid(M_AXI_XBAR_RVALID), + .s_axi_rready(M_AXI_XBAR_RREADY), + // ps gpio source + .ps_gpio_tri(ps_gpio_tri[FP_GPIO_WIDTH+FP_GPIO_OFFSET-1:FP_GPIO_OFFSET]), + .ps_gpio_out(ps_gpio_out[FP_GPIO_WIDTH+FP_GPIO_OFFSET-1:FP_GPIO_OFFSET]), + .ps_gpio_in(ps_gpio_in[FP_GPIO_WIDTH+FP_GPIO_OFFSET-1:FP_GPIO_OFFSET]), + // FP_GPIO + .fp_gpio_inout(FPGA_GPIO), + // Radio ATR + .rx_atr(rx_atr), + .tx_atr(tx_atr), + // Radio GPIO DSA + .db_gpio_out_flat(db_gpio_out), + .db_gpio_in_flat(db_gpio_in), + .db_gpio_ddr_flat(db_gpio_ddr), + .db_gpio_fab_flat(db_gpio_fab), + // Radio Strobes + .rx_stb(rx_stb), + .tx_stb(tx_stb), + // Radio Data + .rx(rx_flat), + .tx(tx_flat), + //cpld rx_lo tx_lo spi + .sclk_flat({DBB_CPLD_PL_SPI_SCLK, + DBA_CPLD_PL_SPI_SCLK}), + .sen_flat({DBB_CPLD_PL_SPI_CS_B,DBB_LODIS_SPI_CS_B,DBB_RXLO_SPI_CS_B,DBB_TXLO_SPI_CS_B, + DBA_CPLD_PL_SPI_CS_B,DBA_LODIS_SPI_CS_B,DBA_RXLO_SPI_CS_B,DBA_TXLO_SPI_CS_B}), + .mosi_flat({DBB_CPLD_PL_SPI_MOSI, + DBA_CPLD_PL_SPI_MOSI}), + .miso_flat({DBB_CPLD_PL_SPI_MISO, + DBA_CPLD_PL_SPI_MISO}), + // DRAM signals. + .ddr3_axi_clk (ddr3_axi_clk), + .ddr3_axi_rst (ddr3_axi_rst), + .ddr3_running (ddr3_running), + // Slave Interface Write Address Ports + .ddr3_axi_awid (ddr3_axi_awid), + .ddr3_axi_awaddr (ddr3_axi_awaddr), + .ddr3_axi_awlen (ddr3_axi_awlen), + .ddr3_axi_awsize (ddr3_axi_awsize), + .ddr3_axi_awburst (ddr3_axi_awburst), + .ddr3_axi_awlock (ddr3_axi_awlock), + .ddr3_axi_awcache (ddr3_axi_awcache), + .ddr3_axi_awprot (ddr3_axi_awprot), + .ddr3_axi_awqos (ddr3_axi_awqos), + .ddr3_axi_awvalid (ddr3_axi_awvalid), + .ddr3_axi_awready (ddr3_axi_awready), + // Slave Interface Write Data Ports + .ddr3_axi_wdata (ddr3_axi_wdata), + .ddr3_axi_wstrb (ddr3_axi_wstrb), + .ddr3_axi_wlast (ddr3_axi_wlast), + .ddr3_axi_wvalid (ddr3_axi_wvalid), + .ddr3_axi_wready (ddr3_axi_wready), + // Slave Interface Write Response Ports + .ddr3_axi_bid (ddr3_axi_bid), + .ddr3_axi_bresp (ddr3_axi_bresp), + .ddr3_axi_bvalid (ddr3_axi_bvalid), + .ddr3_axi_bready (ddr3_axi_bready), + // Slave Interface Read Address Ports + .ddr3_axi_arid (ddr3_axi_arid), + .ddr3_axi_araddr (ddr3_axi_araddr), + .ddr3_axi_arlen (ddr3_axi_arlen), + .ddr3_axi_arsize (ddr3_axi_arsize), + .ddr3_axi_arburst (ddr3_axi_arburst), + .ddr3_axi_arlock (ddr3_axi_arlock), + .ddr3_axi_arcache (ddr3_axi_arcache), + .ddr3_axi_arprot (ddr3_axi_arprot), + .ddr3_axi_arqos (ddr3_axi_arqos), + .ddr3_axi_arvalid (ddr3_axi_arvalid), + .ddr3_axi_arready (ddr3_axi_arready), + // Slave Interface Read Data Ports + .ddr3_axi_rid (ddr3_axi_rid), + .ddr3_axi_rdata (ddr3_axi_rdata), + .ddr3_axi_rresp (ddr3_axi_rresp), + .ddr3_axi_rlast (ddr3_axi_rlast), + .ddr3_axi_rvalid (ddr3_axi_rvalid), + .ddr3_axi_rready (ddr3_axi_rready), + + // DMA to PS + .m_dma_tdata(s_axis_dma_tdata), + .m_dma_tdest(s_axis_dma_tdest), + .m_dma_tlast(s_axis_dma_tlast), + .m_dma_tready(s_axis_dma_tready), + .m_dma_tvalid(s_axis_dma_tvalid), + + .s_dma_tdata(m_axis_dma_tdata), + .s_dma_tuser(m_axis_dma_tuser), + .s_dma_tlast(m_axis_dma_tlast), + .s_dma_tready(m_axis_dma_tready), + .s_dma_tvalid(m_axis_dma_tvalid), + + // VITA to Ethernet + .v2e0_tdata(v2e0_tdata), + .v2e0_tvalid(v2e0_tvalid), + .v2e0_tlast(v2e0_tlast), + .v2e0_tready(v2e0_tready), + + .v2e1_tdata(v2e1_tdata), + .v2e1_tlast(v2e1_tlast), + .v2e1_tvalid(v2e1_tvalid), + .v2e1_tready(v2e1_tready), + + // Ethernet to VITA + .e2v0_tdata(e2v0_tdata), + .e2v0_tlast(e2v0_tlast), + .e2v0_tvalid(e2v0_tvalid), + .e2v0_tready(e2v0_tready), + + .e2v1_tdata(e2v1_tdata), + .e2v1_tlast(e2v1_tlast), + .e2v1_tvalid(e2v1_tvalid), + .e2v1_tready(e2v1_tready), + + //regport interface to npio + .reg_wr_req_npio(reg_wr_req_npio), + .reg_wr_addr_npio(reg_wr_addr_npio), + .reg_wr_data_npio(reg_wr_data_npio), + .reg_rd_req_npio(reg_rd_req_npio), + .reg_rd_addr_npio(reg_rd_addr_npio), + .reg_rd_resp_npio(reg_rd_resp_npio), + .reg_rd_data_npio(reg_rd_data_npio), + + .build_datestamp(build_datestamp), + .xadc_readback({20'h0, device_temp}), + .sfp_ports_info({sfp_port1_info, sfp_port0_info}), + .device_id(device_id) + ); + + // Register the ATR bits once between sending them out to the CPLD to avoid + // glitches on the outputs! + always @(posedge radio_clk) begin + rx_atr_reg <= rx_atr; + tx_atr_reg <= tx_atr; + end + + // ////////////////////////////////////////////////////////////////////// + // + // Daughterboard Cores + // + // ////////////////////////////////////////////////////////////////////// + + wire sAdcSyncUnusedA; + wire sAdcSyncUnusedB; + wire sDacSyncUnusedA; + wire sDacSyncUnusedB; + wire sSysrefUnusedA; + wire sSysrefUnusedB; + wire rRpTransferUnusedA; + wire rRpTransferUnusedB; + wire sSpTransferUnusedA; + wire sSpTransferUnusedB; + wire rWrRpTransferUnusedA; + wire rWrRpTransferUnusedB; + wire sWrSpTransferUnusedA; + wire sWrSpTransferUnusedB; + wire sPpsUnusedB; + wire sPpsToIobUnusedB; + + wire dba_adc_sync_b; + wire dba_dac_sync_b; + wire dba_dac_sync_b_n; // This is the swapped version coming from the IBUFDS. + wire dbb_adc_sync_b; + wire dbb_dac_sync_b; + + wire [49:0] bRegPortInFlatA; + wire [49:0] bRegPortInFlatB; + wire [33:0] bRegPortOutFlatA; + wire [33:0] bRegPortOutFlatB; + + wire rx_a_valid; + wire rx_b_valid; + wire tx_a_rfi; + wire tx_b_rfi; + +`ifdef BUILD_WR + localparam INCL_WR_TDC = 1'b1; +`else + localparam INCL_WR_TDC = 1'b0; +`endif + + wire reg_portA_rd; + wire reg_portA_wr; + wire [14-1:0] reg_portA_addr; + wire [32-1:0] reg_portA_wr_data; + wire [32-1:0] reg_portA_rd_data; + wire reg_portA_ready; + wire validA_unused; + + OBUFDS dba_adc_sync_buf( + .O(DBA_ADC_SYNCB_P), + .OB(DBA_ADC_SYNCB_N), + .I(dba_adc_sync_b) + ); + + IBUFDS dba_dac_sync_buf( + .I(DBA_DAC_SYNCB_P), + .IB(DBA_DAC_SYNCB_N), + .O(dba_dac_sync_b_n) + ); + + // The differential signals are swapped in the pins, so the SYNC signal + // must be negated after the IBUFDS. + assign dba_dac_sync_b = ~ dba_dac_sync_b_n; + + OBUFDS dbb_adc_sync_buf( + .O(DBB_ADC_SYNCB_P), + .OB(DBB_ADC_SYNCB_N), + .I(dbb_adc_sync_b) + ); + + IBUFDS dbb_dac_sync_buf( + .I(DBB_DAC_SYNCB_P), + .IB(DBB_DAC_SYNCB_N), + .O(dbb_dac_sync_b) + ); + + + assign bRegPortInFlatA = {2'b0, reg_portA_addr, reg_portA_wr_data, reg_portA_rd, reg_portA_wr}; + assign {reg_portA_rd_data, validA_unused, reg_portA_ready} = bRegPortOutFlatA; + + DbCore + # (.kInclWhiteRabbitTdc(INCL_WR_TDC)) //std_logic:='0' + dba_core ( + .bBusReset(clk40_rst), //in std_logic + .BusClk(clk40), //in std_logic + .Clk40(clk40), //in std_logic + .MeasClk(meas_clk), //in std_logic + .FpgaClk_p(DBA_FPGA_CLK_P), //in std_logic + .FpgaClk_n(DBA_FPGA_CLK_N), //in std_logic + .SampleClk1xOut(radio_clk), //out std_logic + .SampleClk1x(radio_clk), //in std_logic + .SampleClk2xOut(radio_clk_2x), //out std_logic + .SampleClk2x(radio_clk_2x), //in std_logic + .bRegPortInFlat(bRegPortInFlatA), //in std_logic_vector(49:0) + .bRegPortOutFlat(bRegPortOutFlatA), //out std_logic_vector(33:0) + .kSlotId(1'b0), //in std_logic + .sSysRefFpgaLvds_p(DBA_FPGA_SYSREF_P), //in std_logic + .sSysRefFpgaLvds_n(DBA_FPGA_SYSREF_N), //in std_logic + .aLmkSync(DBA_CLKDIST_SYNC), //out std_logic + .JesdRefClk_p(DBA_MGTCLK_P), //in std_logic + .JesdRefClk_n(DBA_MGTCLK_N), //in std_logic + .aAdcRx_p(DBA_RX_P), //in std_logic_vector(3:0) + .aAdcRx_n(DBA_RX_N), //in std_logic_vector(3:0) + .aSyncAdcOut_n(dba_adc_sync_b), //out std_logic + .aDacTx_p(DBA_TX_P), //out std_logic_vector(3:0) + .aDacTx_n(DBA_TX_N), //out std_logic_vector(3:0) + .aSyncDacIn_n(dba_dac_sync_b), //in std_logic + .sAdcDataValid(rx_a_valid), //out std_logic + .sAdcDataSample0I(rx_db[0][31:16]), //out std_logic_vector(15:0) + .sAdcDataSample0Q(rx_db[0][15: 0]), //out std_logic_vector(15:0) + .sAdcDataSample1I(rx_db[1][31:16]), //out std_logic_vector(15:0) + .sAdcDataSample1Q(rx_db[1][15: 0]), //out std_logic_vector(15:0) + .sDacReadyForInput(tx_a_rfi), //out std_logic + .sDacDataSample0I(tx_db[0][31:16]), //in std_logic_vector(15:0) + .sDacDataSample0Q(tx_db[0][15: 0]), //in std_logic_vector(15:0) + .sDacDataSample1I(tx_db[1][31:16]), //in std_logic_vector(15:0) + .sDacDataSample1Q(tx_db[1][15: 0]), //in std_logic_vector(15:0) + .RefClk(ref_clk), //in std_logic + .rPpsPulse(pps_refclk), //in std_logic + .rGatedPulseToPin(UNUSED_PIN_TDCA_0), //inout std_logic + .sGatedPulseToPin(UNUSED_PIN_TDCA_1), //inout std_logic + .sPps(pps_radioclk1x), //out std_logic + .sPpsToIob(pps_radioclk1x_iob), //out std_logic + .WrRefClk(wr_ref_clk), //in std_logic + .rWrPpsPulse(pps_wr_refclk), //in std_logic + .rWrGatedPulseToPin(UNUSED_PIN_TDCA_2), //inout std_logic + .sWrGatedPulseToPin(UNUSED_PIN_TDCA_3), //inout std_logic + .aPpsSfpSel(pps_select_sfp), //in std_logic_vector(1:0) + .sAdcSync(sAdcSyncUnusedA), //out std_logic + .sDacSync(sDacSyncUnusedA), //out std_logic + .sSysRef(sSysrefUnusedA), //out std_logic + .rRpTransfer(rRpTransferUnusedA), //out std_logic + .sSpTransfer(sSpTransferUnusedA), //out std_logic + .rWrRpTransfer(rWrRpTransferUnusedA), //out std_logic + .sWrSpTransfer(sWrSpTransferUnusedA)); //out std_logic + + + + assign rx_stb[0] = rx_a_valid; + assign tx_stb[0] = tx_a_rfi; + + axil_to_ni_regport #( + .RP_DWIDTH (32), + .RP_AWIDTH (14), + .TIMEOUT (512) + ) ni_regportA_inst ( + // Clock and reset + .s_axi_aclk (clk40), + .s_axi_areset (clk40_rst), + // AXI4-Lite: Write address port (domain: s_axi_aclk) + .s_axi_awaddr(M_AXI_JESD0_AWADDR), + .s_axi_awvalid(M_AXI_JESD0_AWVALID), + .s_axi_awready(M_AXI_JESD0_AWREADY), + // AXI4-Lite: Write data port (domain: s_axi_aclk) + .s_axi_wdata(M_AXI_JESD0_WDATA), + .s_axi_wstrb(M_AXI_JESD0_WSTRB), + .s_axi_wvalid(M_AXI_JESD0_WVALID), + .s_axi_wready(M_AXI_JESD0_WREADY), + // AXI4-Lite: Write response port (domain: s_axi_aclk) + .s_axi_bresp(M_AXI_JESD0_BRESP), + .s_axi_bvalid(M_AXI_JESD0_BVALID), + .s_axi_bready(M_AXI_JESD0_BREADY), + // AXI4-Lite: Read address port (domain: s_axi_aclk) + .s_axi_araddr(M_AXI_JESD0_ARADDR), + .s_axi_arvalid(M_AXI_JESD0_ARVALID), + .s_axi_arready(M_AXI_JESD0_ARREADY), + // AXI4-Lite: Read data port (domain: s_axi_aclk) + .s_axi_rdata(M_AXI_JESD0_RDATA), + .s_axi_rresp(M_AXI_JESD0_RRESP), + .s_axi_rvalid(M_AXI_JESD0_RVALID), + .s_axi_rready(M_AXI_JESD0_RREADY), + // Register port + .reg_port_in_rd (reg_portA_rd), + .reg_port_in_wt (reg_portA_wr), + .reg_port_in_addr (reg_portA_addr), + .reg_port_in_data (reg_portA_wr_data), + .reg_port_out_data (reg_portA_rd_data), + .reg_port_out_ready(reg_portA_ready) + ); + + wire reg_portB_rd; + wire reg_portB_wr; + wire [14-1:0] reg_portB_addr; + wire [32-1:0] reg_portB_wr_data; + wire [32-1:0] reg_portB_rd_data; + wire reg_portB_ready; + wire validB_unused; + + assign bRegPortInFlatB = {2'b0, reg_portB_addr, reg_portB_wr_data, reg_portB_rd, reg_portB_wr}; + assign {reg_portB_rd_data, validB_unused, reg_portB_ready} = bRegPortOutFlatB; + + DbCore + # (.kInclWhiteRabbitTdc(INCL_WR_TDC)) //std_logic:='0' + dbb_core ( + .bBusReset(clk40_rst), //in std_logic + .BusClk(clk40), //in std_logic + .Clk40(clk40), //in std_logic + .MeasClk(meas_clk), //in std_logic + .FpgaClk_p(DBB_FPGA_CLK_P), //in std_logic + .FpgaClk_n(DBB_FPGA_CLK_N), //in std_logic + .SampleClk1xOut(radio_clkB), //out std_logic + .SampleClk1x(radio_clk), //in std_logic + .SampleClk2xOut(radio_clk_2xB), //out std_logic + .SampleClk2x(radio_clk_2x), //in std_logic + .bRegPortInFlat(bRegPortInFlatB), //in std_logic_vector(49:0) + .bRegPortOutFlat(bRegPortOutFlatB), //out std_logic_vector(33:0) + .kSlotId(1'b1), //in std_logic + .sSysRefFpgaLvds_p(DBB_FPGA_SYSREF_P), //in std_logic + .sSysRefFpgaLvds_n(DBB_FPGA_SYSREF_N), //in std_logic + .aLmkSync(DBB_CLKDIST_SYNC), //out std_logic + .JesdRefClk_p(DBB_MGTCLK_P), //in std_logic + .JesdRefClk_n(DBB_MGTCLK_N), //in std_logic + .aAdcRx_p(DBB_RX_P), //in std_logic_vector(3:0) + .aAdcRx_n(DBB_RX_N), //in std_logic_vector(3:0) + .aSyncAdcOut_n(dbb_adc_sync_b), //out std_logic + .aDacTx_p(DBB_TX_P), //out std_logic_vector(3:0) + .aDacTx_n(DBB_TX_N), //out std_logic_vector(3:0) + .aSyncDacIn_n(dbb_dac_sync_b), //in std_logic + .sAdcDataValid(rx_b_valid), //out std_logic + .sAdcDataSample0I(rx_db[2][31:16]), //out std_logic_vector(15:0) + .sAdcDataSample0Q(rx_db[2][15: 0]), //out std_logic_vector(15:0) + .sAdcDataSample1I(rx_db[3][31:16]), //out std_logic_vector(15:0) + .sAdcDataSample1Q(rx_db[3][15: 0]), //out std_logic_vector(15:0) + .sDacReadyForInput(tx_b_rfi), //out std_logic + .sDacDataSample0I(tx_db[2][31:16]), //in std_logic_vector(15:0) + .sDacDataSample0Q(tx_db[2][15: 0]), //in std_logic_vector(15:0) + .sDacDataSample1I(tx_db[3][31:16]), //in std_logic_vector(15:0) + .sDacDataSample1Q(tx_db[3][15: 0]), //in std_logic_vector(15:0) + .RefClk(ref_clk), //in std_logic + .rPpsPulse(pps_refclk), //in std_logic + .rGatedPulseToPin(UNUSED_PIN_TDCB_0), //inout std_logic + .sGatedPulseToPin(UNUSED_PIN_TDCB_1), //inout std_logic + .sPps(sPpsUnusedB), //out std_logic + .sPpsToIob(sPpsToIobUnusedB), //out std_logic + .WrRefClk(wr_ref_clk), //in std_logic + .rWrPpsPulse(pps_wr_refclk), //in std_logic + .rWrGatedPulseToPin(UNUSED_PIN_TDCB_2), //inout std_logic + .sWrGatedPulseToPin(UNUSED_PIN_TDCB_3), //inout std_logic + .aPpsSfpSel(2'd0), //in std_logic_vector(1:0) + .sAdcSync(sAdcSyncUnusedB), //out std_logic + .sDacSync(sDacSyncUnusedB), //out std_logic + .sSysRef(sSysrefUnusedB), //out std_logic + .rRpTransfer(rRpTransferUnusedB), //out std_logic + .sSpTransfer(sSpTransferUnusedB), //out std_logic + .rWrRpTransfer(rWrRpTransferUnusedB), //out std_logic + .sWrSpTransfer(sWrSpTransferUnusedB)); //out std_logic + + + + assign rx_stb[1] = rx_b_valid; + assign tx_stb[1] = tx_b_rfi; + + axil_to_ni_regport #( + .RP_DWIDTH (32), + .RP_AWIDTH (14), + .TIMEOUT (512) + ) ni_regportB_inst ( + // Clock and reset + .s_axi_aclk (clk40), + .s_axi_areset (clk40_rst), + // AXI4-Lite: Write address port (domain: s_axi_aclk) + .s_axi_awaddr(M_AXI_JESD1_AWADDR), + .s_axi_awvalid(M_AXI_JESD1_AWVALID), + .s_axi_awready(M_AXI_JESD1_AWREADY), + // AXI4-Lite: Write data port (domain: s_axi_aclk) + .s_axi_wdata(M_AXI_JESD1_WDATA), + .s_axi_wstrb(M_AXI_JESD1_WSTRB), + .s_axi_wvalid(M_AXI_JESD1_WVALID), + .s_axi_wready(M_AXI_JESD1_WREADY), + // AXI4-Lite: Write response port (domain: s_axi_aclk) + .s_axi_bresp(M_AXI_JESD1_BRESP), + .s_axi_bvalid(M_AXI_JESD1_BVALID), + .s_axi_bready(M_AXI_JESD1_BREADY), + // AXI4-Lite: Read address port (domain: s_axi_aclk) + .s_axi_araddr(M_AXI_JESD1_ARADDR), + .s_axi_arvalid(M_AXI_JESD1_ARVALID), + .s_axi_arready(M_AXI_JESD1_ARREADY), + // AXI4-Lite: Read data port (domain: s_axi_aclk) + .s_axi_rdata (M_AXI_JESD1_RDATA), + .s_axi_rresp (M_AXI_JESD1_RRESP), + .s_axi_rvalid (M_AXI_JESD1_RVALID), + .s_axi_rready (M_AXI_JESD1_RREADY), + // Register port + .reg_port_in_rd (reg_portB_rd), + .reg_port_in_wt (reg_portB_wr), + .reg_port_in_addr (reg_portB_addr), + .reg_port_in_data (reg_portB_wr_data), + .reg_port_out_data (reg_portB_rd_data), + .reg_port_out_ready(reg_portB_ready) + ); + + + // ////////////////////////////////////////////////////////////////////// + // + // LEDS + // + // ////////////////////////////////////////////////////////////////////// + + assign PANEL_LED_LINK = ps_gpio_out[45]; + assign PANEL_LED_REF = ps_gpio_out[46]; + assign PANEL_LED_GPS = ps_gpio_out[47]; + + + ///////////////////////////////////////////////////////////////////// + // + // PUDC Workaround + // + ////////////////////////////////////////////////////////////////////// + // This is a workaround for a silicon bug in Series 7 FPGA where a + // race condition with the reading of PUDC during the erase of the FPGA + // image cause glitches on output IO pins. + // + // Workaround: + // - Define the PUDC pin in the XDC file with a pullup. + // - Implements an IBUF on the PUDC input and make sure that it does + // not get optimized out. + (* dont_touch = "true" *) wire fpga_pudc_b_buf; + IBUF pudc_ibuf_i ( + .I(FPGA_PUDC_B), + .O(fpga_pudc_b_buf)); + +endmodule |