// // Copyright 2021 Ettus Research, A National Instruments Brand // // SPDX-License-Identifier: LGPL-3.0-or-later // // Module: x4xx_gpio_spi // // Description: // // This block enables control of a SPI master engine via CtrlPort // transactions. // It also enables customization on how signals from the SPI buses // connected to the master are mapped to the GPIO Ports. // This block supports configuring communication to up to 4 SPI slaves. // // Parameters: // // NUM_SLAVES : Number of SPI slaves to be supported. Values from 1 to 4 // are supported. SPI transfers can only target one slave // at a time. // BASE_ADDRESS : Start address for this register block. // SIZE_ADDRESS : Size of the CtrlPort window to consider in this block. // `default_nettype none module x4xx_gpio_spi #( parameter NUM_SLAVES = 4, parameter [19:0] BASE_ADDRESS = 0, parameter [19:0] SIZE_ADDRESS = 19'h20 ) ( input wire ctrlport_clk, input wire ctrlport_clk_2x, input wire ctrlport_rst, // Request input wire s_ctrlport_req_wr, input wire s_ctrlport_req_rd, input wire [19:0] s_ctrlport_req_addr, input wire [31:0] s_ctrlport_req_data, // Response output reg s_ctrlport_resp_ack = 1'b0, output reg [ 1:0] s_ctrlport_resp_status = 2'b0, output reg [31:0] s_ctrlport_resp_data = 32'b0, // GPIO control/status output wire [31:0] gpio_out, output wire [31:0] gpio_ddr, input wire [31:0] gpio_in ); `include "../../lib/rfnoc/core/ctrlport.vh" `include "regmap/dig_ifc_regmap_utils.vh" // Registers / wires for SPI core communication reg [31:0] set_data = 0; reg [ 7:0] set_addr = 0; reg set_stb = 1'b0; wire [31:0] readback; wire readback_stb; wire readback_stb_extended; wire sclk; wire mosi; wire miso; // This array is set to the maximum supported SPI slaves instead of // the provided NUM_SLAVES to facilitate concurrent re-mapping. // See section(GPIO Mapping) of this file. wire [3:0] ss; // Auxiliary signals to compute which GPIO lines are outputs reg [31:0] gpio_is_mosi = 32'b0; reg [31:0] gpio_is_sclk = 32'b0; reg [31:0] gpio_is_cs = 32'b0; // SPI-to-GPIO mapping signals. // These arrays are set to the maximum supported SPI slaves instead of // the provided NUM_SLAVES to facilitate concurrent re-mapping. // See section(GPIO Mapping) of this file. reg [ SLAVE_CLK_SIZE-1:0] sclk_mapping [3:0]; reg [SLAVE_MOSI_SIZE-1:0] mosi_mapping [3:0]; reg [SLAVE_MISO_SIZE-1:0] miso_mapping [3:0]; reg [ SLAVE_CS_SIZE-1:0] ss_mapping [3:0]; //--------------------------------------------------------------------------- // Address calculation //--------------------------------------------------------------------------- wire address_in_range = (s_ctrlport_req_addr >= BASE_ADDRESS) && (s_ctrlport_req_addr < BASE_ADDRESS + SIZE_ADDRESS); // Check that address is targeting slave configuration. wire address_is_slave = (s_ctrlport_req_addr >= BASE_ADDRESS + SPI_SLAVE_CONFIG(0)) && (s_ctrlport_req_addr <= BASE_ADDRESS + SPI_SLAVE_CONFIG(3)); // Decode the slave being addressed. wire [1:0]slave_address = s_ctrlport_req_addr[3:2]; //--------------------------------------------------------------------------- // Slave configuration signals //--------------------------------------------------------------------------- // These settings are registered individually for each slave reg [ NUM_SLAVES-1:0] data_in_edge = {NUM_SLAVES{1'b0}}; reg [ NUM_SLAVES-1:0] data_out_edge = {NUM_SLAVES{1'b0}}; reg [SPI_LENGTH_SIZE-1:0] slave_spi_length [NUM_SLAVES-1:0]; // One-hot encoding to indicate active slave reg [NUM_SLAVES-1:0] slave_select = {NUM_SLAVES{1'b0}}; //--------------------------------------------------------------------------- // FSM to handle transfers //--------------------------------------------------------------------------- localparam IDLE = 3'd0; localparam SET_DIVIDER = 3'd1; localparam WRITE_SPI = 3'd2; localparam CONFIG_TRANSFER = 3'd3; localparam WAIT_SPI = 3'd4; localparam DIVIDER_ADDRESS = 8'd0; localparam CTRL_ADDRESS = 8'd1; localparam DATA_ADDRESS = 8'd2; reg [ 2:0] state = IDLE; reg [ 31:0] data_cache; reg [SPI_CLK_DIV_SIZE-1:0] divider; reg [ 1:0] cs; reg spi_go = 1'b0; reg spi_ready = 1'b0; integer slave_i; //--------------------------------------------------------------------------- // CtrlPort Register endpoints //--------------------------------------------------------------------------- always @ (posedge ctrlport_clk) begin if (ctrlport_rst) begin s_ctrlport_resp_ack <= 1'b0; spi_go <= 1'b0; spi_ready <= 1'b0; divider <= {SPI_CLK_DIV_SIZE{1'b0}}; cs <= 2'b0; // Assigned to unassigned mapping. This avoids overwriting // signals with those from uninitialized slaves. for (slave_i=0; slave_i<4; slave_i=slave_i+1) begin sclk_mapping[slave_i] <= 5'h31; mosi_mapping[slave_i] <= 5'h31; miso_mapping[slave_i] <= 5'h31; ss_mapping [slave_i] <= 5'h31; end for (slave_i=0; slave_i // // // // // // Controls SPI Transaction // // // // Indicates which GPIO line to use for the SCLK signal.
// 0-11 : Port A GPIO
// 16-27: Port B GPIO //
//
// // // Indicates which GPIO line to use for the MOSI signal.
// 0-11 : Port A GPIO
// 16-27: Port B GPIO //
//
// // // Indicates which GPIO line to use for the MISO signal.
// 0-11 : Port A GPIO
// 16-27: Port B GPIO //
//
// // // Indicates which GPIO line to use for the CS signal.
// 0-11 : Port A GPIO
// 16-27: Port B GPIO //
//
// // // Indicates the length of SPI transactions to this slave. // // // // // Controls the edge in which the MISO line is latched.
// 0 = falling edge of SCLK.
// 1 = rising edge of SCLK. //
//
// // // Controls the edge in which the MOSI line is updated.
// 0 = falling edge of SCLK.
// 1 = rising edge of SCLK. //
//
//
// // Set of configuration registers for the supported slaves. // // // // Controls clock rate and target for subsequent SPI transactions. // // // Controls the rate for subsequent SPI transactions. SCLK = DataClk/[(SPI_CLK_DIV+1)] // // // // // // Starts a SPI transaction // // // Payload to be sent for the SPI transaction. If the payload is shorter than 32 bits, // it must be aligned to the MSbs in this field. LSbs are ignored in this scenario. // // // // // Contains the status of the SPI engine. // // // Indicates the SPI engine is ready to start a new SPI transaction. // // // Records the response of the last completed SPI transaction. // // // // // Contains information pertaining this SPI controller block. // // // Indicates the number SPI slaves configurable by the controller. // // //
// //XmlParse xml_off