//---------------------------------------------------------------------------- // user_logic.vhd - module //---------------------------------------------------------------------------- // // *************************************************************************** // ** Copyright (c) 1995-2011 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.vhd // Version: 3.00.a // Description: User logic module. // Date: Mon May 14 12:21:28 2012 (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>" //---------------------------------------------------------------------------- module user_logic ( // -- ADD USER PORTS BELOW THIS LINE --------------- samp_spi_sclk, samp_spi_mosi, samp_spi_miso, samp_spi_cs_n, samp_func, rfref_spi_sclk, rfref_spi_mosi, rfref_spi_miso, rfref_spi_cs_n, rfref_func, usr_reset0, usr_reset1, usr_reset2, usr_reset3, usr_status, // -- 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_Reset, // 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 ------------ // -- DO NOT EDIT BELOW THIS LINE -------------------- // -- Bus protocol parameters, do not add to or delete parameter C_SLV_DWIDTH = 32; parameter C_NUM_REG = 8; // -- DO NOT EDIT ABOVE THIS LINE -------------------- // -- ADD USER PORTS BELOW THIS LINE ----------------- output samp_spi_sclk; output samp_spi_mosi; input samp_spi_miso; output samp_spi_cs_n; output samp_func; output rfref_spi_sclk; output rfref_spi_mosi; input rfref_spi_miso; output rfref_spi_cs_n; output rfref_func; output usr_reset0; output usr_reset1; output usr_reset2; output usr_reset3; input [0:31] usr_status; // -- 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_Reset; input [0 : C_SLV_DWIDTH-1] Bus2IP_Data; input [0 : C_SLV_DWIDTH/8-1] Bus2IP_BE; input [0 : C_NUM_REG-1] Bus2IP_RdCE; input [0 : C_NUM_REG-1] Bus2IP_WrCE; output [0 : C_SLV_DWIDTH-1] 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 [0 : C_SLV_DWIDTH-1] slv_reg0; reg [0 : C_SLV_DWIDTH-1] slv_reg1; reg [0 : C_SLV_DWIDTH-1] slv_reg2; reg [0 : C_SLV_DWIDTH-1] slv_reg3; reg [0 : C_SLV_DWIDTH-1] slv_reg4; reg [0 : C_SLV_DWIDTH-1] slv_reg5; reg [0 : C_SLV_DWIDTH-1] slv_reg6; reg [0 : C_SLV_DWIDTH-1] slv_reg7; wire [0 : 7] slv_reg_write_sel; wire [0 : 7] slv_reg_read_sel; reg [0 : C_SLV_DWIDTH-1] 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[0:7]; assign slv_reg_read_sel = Bus2IP_RdCE[0:7]; //Removed [1] from _ack list, so ack can be delayed following write to SPI Tx register assign slv_write_ack = Bus2IP_WrCE[0] || Bus2IP_WrCE[2] || Bus2IP_WrCE[3] || Bus2IP_WrCE[4] || Bus2IP_WrCE[5] || Bus2IP_WrCE[6] || Bus2IP_WrCE[7]; 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]; // implement slave model register(s) always @( posedge Bus2IP_Clk ) begin: SLAVE_REG_WRITE_PROC if ( Bus2IP_Reset == 1 ) 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; end else case ( slv_reg_write_sel ) 8'b10000000 : for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 ) if ( Bus2IP_BE[byte_index] == 1 ) for ( bit_index = byte_index*8; bit_index <= byte_index*8+7; bit_index = bit_index+1 ) slv_reg0[bit_index] <= Bus2IP_Data[bit_index]; 8'b01000000 : for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 ) if ( Bus2IP_BE[byte_index] == 1 ) for ( bit_index = byte_index*8; bit_index <= byte_index*8+7; bit_index = bit_index+1 ) slv_reg1[bit_index] <= Bus2IP_Data[bit_index]; 8'b00100000 : for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 ) if ( Bus2IP_BE[byte_index] == 1 ) for ( bit_index = byte_index*8; bit_index <= byte_index*8+7; bit_index = bit_index+1 ) slv_reg2[bit_index] <= Bus2IP_Data[bit_index]; 8'b00010000 : for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 ) if ( Bus2IP_BE[byte_index] == 1 ) for ( bit_index = byte_index*8; bit_index <= byte_index*8+7; bit_index = bit_index+1 ) slv_reg3[bit_index] <= Bus2IP_Data[bit_index]; 8'b00001000 : for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 ) if ( Bus2IP_BE[byte_index] == 1 ) for ( bit_index = byte_index*8; bit_index <= byte_index*8+7; bit_index = bit_index+1 ) slv_reg4[bit_index] <= Bus2IP_Data[bit_index]; 8'b00000100 : for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 ) if ( Bus2IP_BE[byte_index] == 1 ) for ( bit_index = byte_index*8; bit_index <= byte_index*8+7; bit_index = bit_index+1 ) slv_reg5[bit_index] <= Bus2IP_Data[bit_index]; 8'b00000010 : for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 ) if ( Bus2IP_BE[byte_index] == 1 ) for ( bit_index = byte_index*8; bit_index <= byte_index*8+7; bit_index = bit_index+1 ) slv_reg6[bit_index] <= Bus2IP_Data[bit_index]; 8'b00000001 : for ( byte_index = 0; byte_index <= (C_SLV_DWIDTH/8)-1; byte_index = byte_index+1 ) if ( Bus2IP_BE[byte_index] == 1 ) for ( bit_index = byte_index*8; bit_index <= byte_index*8+7; bit_index = bit_index+1 ) slv_reg7[bit_index] <= Bus2IP_Data[bit_index]; default : ; endcase end // SLAVE_REG_WRITE_PROC wire [0:7] samp_spi_rx_byte; wire [0:7] rfref_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 ) begin: SLAVE_REG_READ_PROC case ( slv_reg_read_sel ) 8'b10000000 : slv_ip2bus_data <= slv_reg0; 8'b01000000 : slv_ip2bus_data <= slv_reg1; 8'b00100000 : slv_ip2bus_data <= {16'b0, rfref_spi_rx_byte, samp_spi_rx_byte}; 8'b00010000 : slv_ip2bus_data <= slv_reg3; 8'b00001000 : slv_ip2bus_data <= usr_status_d; 8'b00000100 : slv_ip2bus_data <= slv_reg5; 8'b00000010 : slv_ip2bus_data <= slv_reg6; 8'b00000001 : slv_ip2bus_data <= slv_reg7; default : slv_ip2bus_data <= 0; endcase end // SLAVE_REG_READ_PROC // ------------------------------------------------------------ // Example code to drive IP to Bus signals // ------------------------------------------------------------ assign IP2Bus_Data = slv_ip2bus_data; // 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] = [0:31] regX[0] maps to 0x80000000 in C driver regX[31] maps to 0x00000001 in C driver 0: Config: {clk_div_sel[2:0], 1'b0, samp_func, rfref_func, 26'b0} [29:31] Clock divider bit sel (00=0.5*busclk, 01=0.25*busclk, ...) 0x00000003 [28 ] Reserved [ 27] samp buf reset (active low) 0x00000010 [ 26] rf ref buf reset (active low) 0x00000020 [0 :25] Reserved 1: SPI Tx [24:31] Tx data byte [17:23] 7-bit register address (0x00 to 0xFF all valid) [11:16] 6'b0 (always zero) [ 9:10] Num bytes to Tx/Rx; must be 2'b0 for 1-byte Tx/Rx [ 8] RW# 1=Read, 0=Write [ 7] ad1 chip select mask [ 6] ad2 chip select mask [ 0: 5] Reserved 2: SPI Rx: {samp_rxByte, rfref_rxByte, 16'b0} [24:31] SPI Rx byte for samp buf 0x00FF [16:23] SPI Rx byte for rf ref buf 0xFF00 [ 0:15] Reserved 0xFFFF0000 3: RW: User reset outputs [31] usr_reset0 [30] usr_reset1 [29] usr_reset2 [28] usr_reset3 [0:27] reserved 4: RO: User status inputs [0:31] usr_status input 5-15: Reserved */ `define AD9512_SPI_XFER_LEN 5'd24 wire spi_mosi; wire spi_sclk; wire spi_cs; wire spi_rnw; wire spi_tx_reg_write; wire [0:2] clk_div_sel; wire spi_xfer_done; wire samp_spi_cs, rfref_spi_cs; wire [0:31] samp_spi_rxData; wire [0:31] rfref_spi_rxData; reg [0:31] usr_status_d; //Register the usr_status input here, to ease timing closure of potentially fast host PLBs always @(posedge Bus2IP_Clk) usr_status_d <= usr_status; //Extract bits from IPIF slave registers and control signals //spi_io stores 32 bits for Tx/Rx // AD9512 only outputs 8-bit words during reads, always the last 8 bits of the transfer assign samp_spi_rx_byte = samp_spi_rxData[24:31]; assign rfref_spi_rx_byte = rfref_spi_rxData[24:31]; //SPI clock divider selection assign clk_div_sel = slv_reg0[29:31]; //0x3 from driver //SPI device resets (active low) assign samp_func = slv_reg0[27]; //0x10 from driver assign rfref_func = slv_reg0[26]; //0x20 from driver //SPI device chip selects (active high; inverted before use below) assign samp_spi_cs = slv_reg1[7]; //0x01000000 from driver assign rfref_spi_cs = slv_reg1[6]; //0x02000000 from driver //User reset outputs assign usr_reset0 = slv_reg3[31]; assign usr_reset1 = slv_reg3[30]; assign usr_reset2 = slv_reg3[29]; assign usr_reset3 = slv_reg3[28]; //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[1]; //spi_tx_reg_write (Bus2IP_WrCE[1]) 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 samp_spi_cs_n = ~(samp_spi_cs & spi_cs); assign rfref_spi_cs_n = ~(rfref_spi_cs & spi_cs); //Mask each device's SPI clock output by its CS; no point toggling signals that will be ignored assign samp_spi_sclk = (spi_sclk & samp_spi_cs); assign rfref_spi_sclk = (spi_sclk & rfref_spi_cs); //All SPI devices driven by same serial data output; CS signals control who listens assign samp_spi_mosi = samp_spi_cs ? spi_mosi : 1'b0; assign rfref_spi_mosi = rfref_spi_cs ? spi_mosi : 1'b0; warp_spi_io #(.SPI_XFER_LEN(`AD9512_SPI_XFER_LEN)) spi_io ( .sys_clk(Bus2IP_Clk), .reset(Bus2IP_Reset), .go(spi_tx_reg_write), .done(spi_xfer_done), .clkDiv(clk_div_sel), .currBitNum(), .txData(slv_reg1), .rxData1(samp_spi_rxData), .rxData2(rfref_spi_rxData), .rxData3(), .rxData4(), .spi_cs(spi_cs), .spi_sclk(spi_sclk), .spi_mosi(spi_mosi), .spi_miso1(samp_spi_miso), .spi_miso2(rfref_spi_miso), .spi_miso3(1'b0), .spi_miso4(1'b0) ); endmodule