//---------------------------------------------------------------------------- // user_logic.v - module //---------------------------------------------------------------------------- // // *************************************************************************** // ** Copyright (c) 1995-2012 Xilinx, Inc. All rights reserved. ** // ** ** // ** Xilinx, Inc. ** // ** XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" ** // ** AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND ** // ** SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE, ** // ** OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, ** // ** APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION ** // ** THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT, ** // ** AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE ** // ** FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY ** // ** WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE ** // ** IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR ** // ** REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF ** // ** INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ** // ** FOR A PARTICULAR PURPOSE. ** // ** ** // *************************************************************************** // //---------------------------------------------------------------------------- // Filename: user_logic.v // Version: 3.01.a // Description: User logic module. // Date: Tue Feb 26 12:57:13 2013 (by Create and Import Peripheral Wizard) // Verilog Standard: Verilog-2001 //---------------------------------------------------------------------------- // Naming Conventions: // active low signals: "*_n" // clock signals: "clk", "clk_div#", "clk_#x" // reset signals: "rst", "rst_n" // generics: "C_*" // user defined types: "*_TYPE" // state machine next state: "*_ns" // state machine current state: "*_cs" // combinatorial signals: "*_com" // pipelined or register delay signals: "*_d#" // counter signals: "*cnt*" // clock enable signals: "*_ce" // internal version of output port: "*_i" // device pins: "*_pin" // ports: "- Names begin with Uppercase" // processes: "*_PROCESS" // component instantiations: "I_<#|FUNC>" //---------------------------------------------------------------------------- `uselib lib=unisims_ver `uselib lib=proc_common_v3_00_a module user_logic ( // -- ADD USER PORTS BELOW THIS LINE --------------- RFA_AD_spi_sclk, RFA_AD_spi_cs_n, RFA_AD_spi_sdio, RFA_AD_reset_n, RFB_AD_spi_sclk, RFB_AD_spi_cs_n, RFB_AD_spi_sdio, RFB_AD_reset_n, RFC_AD_spi_sclk, RFC_AD_spi_cs_n, RFC_AD_spi_sdio, RFC_AD_reset_n, RFD_AD_spi_sclk, RFD_AD_spi_cs_n, RFD_AD_spi_sdio, RFD_AD_reset_n, RF_AD_TXCLK_out_en, // -- ADD USER PORTS ABOVE THIS LINE --------------- // -- DO NOT EDIT BELOW THIS LINE ------------------ // -- Bus protocol ports, do not add to or delete Bus2IP_Clk, // Bus to IP clock Bus2IP_Resetn, // Bus to IP reset Bus2IP_Data, // Bus to IP data bus Bus2IP_BE, // Bus to IP byte enables Bus2IP_RdCE, // Bus to IP read chip enable Bus2IP_WrCE, // Bus to IP write chip enable IP2Bus_Data, // IP to Bus data bus IP2Bus_RdAck, // IP to Bus read transfer acknowledgement IP2Bus_WrAck, // IP to Bus write transfer acknowledgement IP2Bus_Error // IP to Bus error response // -- DO NOT EDIT ABOVE THIS LINE ------------------ ); // user_logic // -- ADD USER PARAMETERS BELOW THIS LINE ------------ // --USER parameters added here // -- ADD USER PARAMETERS ABOVE THIS LINE ------------ parameter INCLUDE_RFC_RFD_IO = 0; // -- DO NOT EDIT BELOW THIS LINE -------------------- // -- Bus protocol parameters, do not add to or delete parameter C_NUM_REG = 16; parameter C_SLV_DWIDTH = 32; // -- DO NOT EDIT ABOVE THIS LINE -------------------- // -- ADD USER PORTS BELOW THIS LINE ----------------- output RFA_AD_spi_sclk; output RFA_AD_spi_cs_n; inout RFA_AD_spi_sdio; output RFA_AD_reset_n; output RFB_AD_spi_sclk; output RFB_AD_spi_cs_n; inout RFB_AD_spi_sdio; output RFB_AD_reset_n; output RFC_AD_spi_sclk; output RFC_AD_spi_cs_n; inout RFC_AD_spi_sdio; output RFC_AD_reset_n; output RFD_AD_spi_sclk; output RFD_AD_spi_cs_n; inout RFD_AD_spi_sdio; output RFD_AD_reset_n; output RF_AD_TXCLK_out_en; // -- ADD USER PORTS ABOVE THIS LINE ----------------- // -- DO NOT EDIT BELOW THIS LINE -------------------- // -- Bus protocol ports, do not add to or delete input Bus2IP_Clk; input Bus2IP_Resetn; input [C_SLV_DWIDTH-1 : 0] Bus2IP_Data; input [C_SLV_DWIDTH/8-1 : 0] Bus2IP_BE; input [C_NUM_REG-1 : 0] Bus2IP_RdCE; input [C_NUM_REG-1 : 0] Bus2IP_WrCE; output [C_SLV_DWIDTH-1 : 0] IP2Bus_Data; output IP2Bus_RdAck; output IP2Bus_WrAck; output IP2Bus_Error; // -- DO NOT EDIT ABOVE THIS LINE -------------------- //---------------------------------------------------------------------------- // Implementation //---------------------------------------------------------------------------- // --USER nets declarations added here, as needed for user logic // Nets for user logic slave model s/w accessible register example reg [C_SLV_DWIDTH-1 : 0] slv_reg0; reg [C_SLV_DWIDTH-1 : 0] slv_reg1; reg [C_SLV_DWIDTH-1 : 0] slv_reg2; reg [C_SLV_DWIDTH-1 : 0] slv_reg3; reg [C_SLV_DWIDTH-1 : 0] slv_reg4; reg [C_SLV_DWIDTH-1 : 0] slv_reg5; reg [C_SLV_DWIDTH-1 : 0] slv_reg6; reg [C_SLV_DWIDTH-1 : 0] slv_reg7; reg [C_SLV_DWIDTH-1 : 0] slv_reg8; reg [C_SLV_DWIDTH-1 : 0] slv_reg9; reg [C_SLV_DWIDTH-1 : 0] slv_reg10; reg [C_SLV_DWIDTH-1 : 0] slv_reg11; reg [C_SLV_DWIDTH-1 : 0] slv_reg12; reg [C_SLV_DWIDTH-1 : 0] slv_reg13; reg [C_SLV_DWIDTH-1 : 0] slv_reg14; reg [C_SLV_DWIDTH-1 : 0] slv_reg15; wire [15 : 0] slv_reg_write_sel; wire [15 : 0] slv_reg_read_sel; reg [C_SLV_DWIDTH-1 : 0] slv_ip2bus_data; wire slv_read_ack; wire slv_write_ack; integer byte_index, bit_index; // USER logic implementation added here // ------------------------------------------------------ // Example code to read/write user logic slave model s/w accessible registers // // Note: // The example code presented here is to show you one way of reading/writing // software accessible registers implemented in the user logic slave model. // Each bit of the Bus2IP_WrCE/Bus2IP_RdCE signals is configured to correspond // to one software accessible register by the top level template. For example, // if you have four 32 bit software accessible registers in the user logic, // you are basically operating on the following memory mapped registers: // // Bus2IP_WrCE/Bus2IP_RdCE Memory Mapped Register // "1000" C_BASEADDR + 0x0 // "0100" C_BASEADDR + 0x4 // "0010" C_BASEADDR + 0x8 // "0001" C_BASEADDR + 0xC // // ------------------------------------------------------ assign slv_reg_write_sel = Bus2IP_WrCE[15:0]; assign slv_reg_read_sel = Bus2IP_RdCE[15:0]; //Removed [14] from write_ack, so ack can be delayed following write to SPI Tx register // WrCE/RdCE[15:0] map to slv_reg[0:15] assign slv_write_ack = Bus2IP_WrCE[0] || Bus2IP_WrCE[1] || Bus2IP_WrCE[2] || Bus2IP_WrCE[3] || Bus2IP_WrCE[4] || Bus2IP_WrCE[5] || Bus2IP_WrCE[6] || Bus2IP_WrCE[7] || Bus2IP_WrCE[8] || Bus2IP_WrCE[9] || Bus2IP_WrCE[10] || Bus2IP_WrCE[11] || Bus2IP_WrCE[12] || Bus2IP_WrCE[13] || Bus2IP_WrCE[15]; assign slv_read_ack = Bus2IP_RdCE[0] || Bus2IP_RdCE[1] || Bus2IP_RdCE[2] || Bus2IP_RdCE[3] || Bus2IP_RdCE[4] || Bus2IP_RdCE[5] || Bus2IP_RdCE[6] || Bus2IP_RdCE[7] || Bus2IP_RdCE[8] || Bus2IP_RdCE[9] || Bus2IP_RdCE[10] || Bus2IP_RdCE[11] || Bus2IP_RdCE[12] || Bus2IP_RdCE[13] || Bus2IP_RdCE[14] || Bus2IP_RdCE[15]; // implement slave model register(s) always @( posedge Bus2IP_Clk ) begin if ( Bus2IP_Resetn == 1'b0 ) begin slv_reg0 <= 0; slv_reg1 <= 0; slv_reg2 <= 0; slv_reg3 <= 0; slv_reg4 <= 0; slv_reg5 <= 0; slv_reg6 <= 0; slv_reg7 <= 0; slv_reg8 <= 0; slv_reg9 <= 0; slv_reg10 <= 0; slv_reg11 <= 0; slv_reg12 <= 0; slv_reg13 <= 0; slv_reg14 <= 0; slv_reg15 <= 0; end else case ( slv_reg_write_sel ) 16'b1000000000000000 : for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 ) if ( Bus2IP_BE[byte_index] == 1 ) slv_reg0[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8]; 16'b0100000000000000 : for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 ) if ( Bus2IP_BE[byte_index] == 1 ) slv_reg1[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8]; 16'b0010000000000000 : for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 ) if ( Bus2IP_BE[byte_index] == 1 ) slv_reg2[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8]; 16'b0001000000000000 : for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 ) if ( Bus2IP_BE[byte_index] == 1 ) slv_reg3[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8]; 16'b0000100000000000 : for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 ) if ( Bus2IP_BE[byte_index] == 1 ) slv_reg4[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8]; 16'b0000010000000000 : for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 ) if ( Bus2IP_BE[byte_index] == 1 ) slv_reg5[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8]; 16'b0000001000000000 : for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 ) if ( Bus2IP_BE[byte_index] == 1 ) slv_reg6[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8]; 16'b0000000100000000 : for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 ) if ( Bus2IP_BE[byte_index] == 1 ) slv_reg7[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8]; 16'b0000000010000000 : for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 ) if ( Bus2IP_BE[byte_index] == 1 ) slv_reg8[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8]; 16'b0000000001000000 : for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 ) if ( Bus2IP_BE[byte_index] == 1 ) slv_reg9[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8]; 16'b0000000000100000 : for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 ) if ( Bus2IP_BE[byte_index] == 1 ) slv_reg10[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8]; 16'b0000000000010000 : for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 ) if ( Bus2IP_BE[byte_index] == 1 ) slv_reg11[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8]; 16'b0000000000001000 : for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 ) if ( Bus2IP_BE[byte_index] == 1 ) slv_reg12[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8]; 16'b0000000000000100 : for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 ) if ( Bus2IP_BE[byte_index] == 1 ) slv_reg13[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8]; 16'b0000000000000010 : for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 ) if ( Bus2IP_BE[byte_index] == 1 ) slv_reg14[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8]; 16'b0000000000000001 : for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 ) if ( Bus2IP_BE[byte_index] == 1 ) slv_reg15[(byte_index*8) +: 8] <= Bus2IP_Data[(byte_index*8) +: 8]; default : begin slv_reg0 <= slv_reg0; slv_reg1 <= slv_reg1; slv_reg2 <= slv_reg2; slv_reg3 <= slv_reg3; slv_reg4 <= slv_reg4; slv_reg5 <= slv_reg5; slv_reg6 <= slv_reg6; slv_reg7 <= slv_reg7; slv_reg8 <= slv_reg8; slv_reg9 <= slv_reg9; slv_reg10 <= slv_reg10; slv_reg11 <= slv_reg11; slv_reg12 <= slv_reg12; slv_reg13 <= slv_reg13; slv_reg14 <= slv_reg14; slv_reg15 <= slv_reg15; end endcase end // SLAVE_REG_WRITE_PROC wire [7:0] RFA_AD_spi_rx_byte; wire [7:0] RFB_AD_spi_rx_byte; wire [7:0] RFC_AD_spi_rx_byte; wire [7:0] RFD_AD_spi_rx_byte; // implement slave model register read mux always @*//( slv_reg_read_sel or slv_reg0 or slv_reg1 or slv_reg2 or slv_reg3 or slv_reg4 or slv_reg5 or slv_reg6 or slv_reg7 or slv_reg8 or slv_reg9 or slv_reg10 or slv_reg11 or slv_reg12 or slv_reg13 or slv_reg14 or slv_reg15 ) begin case ( slv_reg_read_sel ) 16'b1000000000000000 : slv_ip2bus_data <= slv_reg0; 16'b0100000000000000 : slv_ip2bus_data <= slv_reg1; 16'b0010000000000000 : slv_ip2bus_data <= {RFD_AD_spi_rx_byte, RFC_AD_spi_rx_byte, RFB_AD_spi_rx_byte, RFA_AD_spi_rx_byte}; 16'b0001000000000000 : slv_ip2bus_data <= slv_reg3; 16'b0000100000000000 : slv_ip2bus_data <= slv_reg4; 16'b0000010000000000 : slv_ip2bus_data <= slv_reg5; 16'b0000001000000000 : slv_ip2bus_data <= slv_reg6; 16'b0000000100000000 : slv_ip2bus_data <= slv_reg7; 16'b0000000010000000 : slv_ip2bus_data <= slv_reg8; 16'b0000000001000000 : slv_ip2bus_data <= slv_reg9; 16'b0000000000100000 : slv_ip2bus_data <= slv_reg10; 16'b0000000000010000 : slv_ip2bus_data <= slv_reg11; 16'b0000000000001000 : slv_ip2bus_data <= slv_reg12; 16'b0000000000000100 : slv_ip2bus_data <= slv_reg13; 16'b0000000000000010 : slv_ip2bus_data <= slv_reg14; 16'b0000000000000001 : slv_ip2bus_data <= slv_reg15; default : slv_ip2bus_data <= 0; endcase end // SLAVE_REG_READ_PROC // ------------------------------------------------------------ // Example code to drive IP to Bus signals // ------------------------------------------------------------ assign IP2Bus_Data = (slv_read_ack == 1'b1) ? slv_ip2bus_data : 0 ; // assign IP2Bus_WrAck = slv_write_ack; //Overridden below assign IP2Bus_RdAck = slv_read_ack; assign IP2Bus_Error = 0; /* Address map: HDL is coded [MSB:LSB] = [31:0], per Xilinx's convention for AXI peripherals regX[31] maps to 0x80000000 in C driver regX[0] maps to 0x00000001 in C driver 0: Config: {clk_div_sel[2:0], 1'b0, RFA_AD_rst_n, RFB_AD_rst_n, RFC_AD_rst_n, RFD_AD_rst_n, 24'b0} [ 2: 0] Clock divider bit sel (00=0.5*busclk, 01=0.25*busclk, ...) 0x00000007 [ 3] Reserved [ 4] RFA_AD reset (active low) 0x00000010 [ 5] RFB_AD reset (active low) 0x00000020 [ 6] RFC_AD reset (active low) 0x00000040 [ 7] RFD_AD reset (active low) 0x00000080 [ 8] RF_AD_TXCLK_out_en (1 = enable TXCLK output from ad_bridge) [31: 9] Reserved 1: SPI Tx [ 7: 0] Tx data byte 0x00FF [15: 8] 8-bit register address (0x00 to 0xFF all valid) 0xFF00 [20:16] 5'b0 (always zero) [22:21] Num bytes to Tx/Rx; must be 2'b0 for 1-byte Tx/Rx [ 23] RW# 1=Read, 0=Write [ 24] RFA_AD chip select mask [ 25] RFB_AD chip select mask [ 26] RFC_AD chip select mask [ 27] RFD_AD chip select mask [31:28] Reserved 2: SPI Rx: {RFA_AD_rxByte, RFB_AD_rxByte, RFC_AD_rxByte, RFD_AD_rxByte} [ 7: 0] SPI Rx byte for RFA_AD 0x000000FF [15: 8] SPI Rx byte for RFB_AD 0x0000FF00 [23:16] SPI Rx byte for RFC_AD 0x00FF0000 [31:24] SPI Rx byte for RFD_AD 0xFF000000 3-15: Reserved */ `define AD9963_SPI_XFER_LEN 24 //AD9963 `define AD9963_SPI_FIRST_RXBIT 5'd16 //AD9963 (16-bit instruction, 8-bit data) wire [4:0] spi_bitNum; wire spi_mosi; wire spi_sclk; wire spi_cs; wire spi_rnw; wire RFA_AD_spi_cs, RFB_AD_spi_cs, RFC_AD_spi_cs, RFD_AD_spi_cs; wire spi_tx_reg_write; wire [2:0] clk_div_sel; wire spi_xfer_done; wire [31:0] RFA_AD_spi_rxData; wire [31:0] RFB_AD_spi_rxData; wire [31:0] RFC_AD_spi_rxData; wire [31:0] RFD_AD_spi_rxData; wire RFA_AD_spi_mosi, RFA_AD_spi_miso; wire RFB_AD_spi_mosi, RFB_AD_spi_miso; wire RFC_AD_spi_mosi, RFC_AD_spi_miso; wire RFD_AD_spi_mosi, RFD_AD_spi_miso; //Extract bits from IPIF slave registers and control signals //spi_io stores 32 bits for Tx/Rx // AD9963 only outputs 8-bit words during reads, always the last 8 bits of the transfer assign RFA_AD_spi_rx_byte = RFA_AD_spi_rxData[7:0]; assign RFB_AD_spi_rx_byte = RFB_AD_spi_rxData[7:0]; assign RFC_AD_spi_rx_byte = RFC_AD_spi_rxData[7:0]; assign RFD_AD_spi_rx_byte = RFD_AD_spi_rxData[7:0]; //SPI clock divider selection assign clk_div_sel = slv_reg0[2:0]; //0x7 from driver //SPI device resets (active low) reg RFA_AD_reset_n_d, RFB_AD_reset_n_d, RFC_AD_reset_n_d, RFD_AD_reset_n_d; always @(posedge Bus2IP_Clk) begin //Pipeline regs (fewer bus -> pin routes is good) RFA_AD_reset_n_d <= slv_reg0[4]; RFB_AD_reset_n_d <= slv_reg0[5]; RFC_AD_reset_n_d <= slv_reg0[6]; RFD_AD_reset_n_d <= slv_reg0[7]; end assign RFA_AD_reset_n = RFA_AD_reset_n_d; //0x10 from driver assign RFB_AD_reset_n = RFB_AD_reset_n_d; //0x20 from driver assign RFC_AD_reset_n = RFC_AD_reset_n_d; //0x40 from driver assign RFD_AD_reset_n = RFD_AD_reset_n_d; //0x80 from driver //Output enable for ad_bridge TXCLK port (AD9963 TXCLK port is bidirectional, defaults to output from AD9963) reg RF_AD_TXCLK_out_en_d; always @(posedge Bus2IP_Clk) begin //Pipeline reg (fewer bus -> pin routes is good) RF_AD_TXCLK_out_en_d <= slv_reg0[8]; //0x100 from driver end assign RF_AD_TXCLK_out_en = RF_AD_TXCLK_out_en_d; //SPI device chip selects (active high; inverted before use below) assign RFA_AD_spi_cs = slv_reg1[24]; //0x01000000 from driver assign RFB_AD_spi_cs = slv_reg1[25]; //0x02000000 from driver assign RFC_AD_spi_cs = slv_reg1[26]; //0x04000000 from driver assign RFD_AD_spi_cs = slv_reg1[27]; //0x08000000 from driver //Internal signal for read vs. write transaction assign spi_rnw = slv_reg1[`AD9963_SPI_XFER_LEN-1]; //0x00800000 from driver //Use the IPIC write-enable for the SPI Tx register as the SPI go // The bus will be paused until this core ACKs the write assign spi_tx_reg_write = Bus2IP_WrCE[14]; //WrCE[15:0] maps to slv_reg[0:15] //spi_tx_reg_write (Bus2IP_WrCE[14]) de-asserts as soon as transaction is ACK'd // so this mux switches back to the generic ACK as soon as the SPI xfer is done //Thus, the duration of assertion for spi_xfer_done doesn't really matter //A bit fast-n-loose, but works ok assign IP2Bus_WrAck = spi_tx_reg_write ? spi_xfer_done : slv_write_ack; //SPI device chip selects are active low assign RFA_AD_spi_cs_n = ~(RFA_AD_spi_cs & spi_cs); assign RFB_AD_spi_cs_n = ~(RFB_AD_spi_cs & spi_cs); assign RFC_AD_spi_cs_n = ~(RFC_AD_spi_cs & spi_cs); assign RFD_AD_spi_cs_n = ~(RFD_AD_spi_cs & spi_cs); //Mask each device's SPI clock output by its CS; no point toggling signals that will be ignored assign RFA_AD_spi_sclk = (spi_sclk & RFA_AD_spi_cs); assign RFB_AD_spi_sclk = (spi_sclk & RFB_AD_spi_cs); assign RFC_AD_spi_sclk = (spi_sclk & RFC_AD_spi_cs); assign RFD_AD_spi_sclk = (spi_sclk & RFD_AD_spi_cs); //All SPI devices driven by same serial data output; CS signals control who listens assign RFA_AD_spi_mosi = RFA_AD_spi_cs ? spi_mosi : 1'b0; assign RFB_AD_spi_mosi = RFB_AD_spi_cs ? spi_mosi : 1'b0; assign RFC_AD_spi_mosi = RFC_AD_spi_cs ? spi_mosi : 1'b0; assign RFD_AD_spi_mosi = RFD_AD_spi_cs ? spi_mosi : 1'b0; //AD9963 SPI data is bi-directional; IOBUFs instantiated here to switch I vs. O mid-transfer //Set spi_sdio pins as inputs except when actively driving, to avoid accidental drive fights // FPGA drives the sdio pin when: // An SPI transaction is in progress AND // The transaction is a read AND the current bit is part of the instruction bytes // OR // The transaction is a write assign RFA_AD_spi_sdio_output_en = spi_cs & ( (spi_rnw & (spi_bitNum < `AD9963_SPI_FIRST_RXBIT)) | (~spi_rnw)); assign RFB_AD_spi_sdio_output_en = spi_cs & ( (spi_rnw & (spi_bitNum < `AD9963_SPI_FIRST_RXBIT)) | (~spi_rnw)); assign RFC_AD_spi_sdio_output_en = spi_cs & ( (spi_rnw & (spi_bitNum < `AD9963_SPI_FIRST_RXBIT)) | (~spi_rnw)); assign RFD_AD_spi_sdio_output_en = spi_cs & ( (spi_rnw & (spi_bitNum < `AD9963_SPI_FIRST_RXBIT)) | (~spi_rnw)); IOBUF IOBUF_RFA_AD_sdio ( .IO(RFA_AD_spi_sdio), //Connected to actual FPGA pin .I(RFA_AD_spi_mosi), //Logic-> Pad, input to OBUFT .O(RFA_AD_spi_miso), //Pad-> Logic, output of IBUF .T(~RFA_AD_spi_sdio_output_en) ); IOBUF IOBUF_RFB_AD_sdio ( .IO(RFB_AD_spi_sdio), //Connected to actual FPGA pin .I(RFB_AD_spi_mosi), //Logic-> Pad, input to OBUFT .O(RFB_AD_spi_miso), //Pad-> Logic, output of IBUF .T(~RFB_AD_spi_sdio_output_en) ); generate if(INCLUDE_RFC_RFD_IO==1) begin IOBUF IOBUF_RFC_AD_sdio ( .IO(RFC_AD_spi_sdio), //Connected to actual FPGA pin .I(RFC_AD_spi_mosi), //Logic-> Pad, input to OBUFT .O(RFC_AD_spi_miso), //Pad-> Logic, output of IBUF .T(~RFC_AD_spi_sdio_output_en) ); IOBUF IOBUF_RFD_AD_sdio ( .IO(RFD_AD_spi_sdio), //Connected to actual FPGA pin .I(RFD_AD_spi_mosi), //Logic-> Pad, input to OBUFT .O(RFD_AD_spi_miso), //Pad-> Logic, output of IBUF .T(~RFD_AD_spi_sdio_output_en) ); end else begin assign RFC_AD_spi_miso = 1'b0; assign RFD_AD_spi_miso = 1'b0; assign RFC_AD_spi_sdio = 1'b0; assign RFD_AD_spi_sdio = 1'b0; end endgenerate warp_spi_io #(.SPI_XFER_LEN(`AD9963_SPI_XFER_LEN)) spi_io ( .sys_clk(Bus2IP_Clk), .reset(~Bus2IP_Resetn),//warp_spi_io.reset is active high .go(spi_tx_reg_write), .done(spi_xfer_done), .clkDiv(clk_div_sel), .currBitNum(spi_bitNum), .txData(slv_reg1), .rxData1(RFA_AD_spi_rxData), .rxData2(RFB_AD_spi_rxData), .rxData3(RFC_AD_spi_rxData), .rxData4(RFD_AD_spi_rxData), .spi_cs(spi_cs), .spi_sclk(spi_sclk), .spi_mosi(spi_mosi), .spi_miso1(RFA_AD_spi_miso), .spi_miso2(RFB_AD_spi_miso), .spi_miso3(RFC_AD_spi_miso), .spi_miso4(RFD_AD_spi_miso) ); endmodule