// // Copyright 2021 Ettus Research, A National Instruments Brand // // SPDX-License-Identifier: LGPL-3.0-or-later // // Module: x4xx_versioning_regs // // Description: // // This module contains the motherboard registers for tracking // HDL components versions. // // This versioning module is comprised of up to 256 read-only registers, // which provide versioning information for up to 64 components (256/4). // Each component has 3 x 32-bit registers for the following purpose: // - Current version // - Oldest compatible version // - Last modified time stamp // // Note that in order to facilitate implementation, each component // allocates a 4th register address (Reserved) for future use. // // Allocation of the 64 addressable components is shown below. // This allocation determines the definition of COMPONENTS_INDEXES // in the register map documentation below. // // --- Common components --- // Reserved space for up to 24 components. // - FPGA // - MB CPLD interface // - RF core (db 0) // - RF core (db 1) // - GPIO interface (db 0) // - GPIO interface (db 1) // // --- UHD-specific components --- // Reserved space for up to 20 components. // - QSFP wrapper (port 0) // - QSFP wrapper (port 1) // // --- LV-specific components --- // Reserved space for up to 20 components. // // Parameters: // // REG_BASE : Base address to use for registers. // `default_nettype none module x4xx_versioning_regs #( parameter REG_BASE = 0 ) ( // Slave ctrlport interface input wire s_ctrlport_clk, input wire s_ctrlport_rst, 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, output reg s_ctrlport_resp_ack = 1'b0, output reg [ 1:0] s_ctrlport_resp_status = 2'b00, output reg [31:0] s_ctrlport_resp_data = {32 {1'bX}}, // Version (Constant) // Each component consists of a 96-bit vector (refer to versioning_utils.vh) input wire [64*96-1:0] version_info ); `include "regmap/versioning_regs_regmap_utils.vh" `include "regmap/versioning_utils.vh" `include "../../lib/rfnoc/core/ctrlport.vh" // 64 components * 4 registers * 4 addresses p/ register localparam REG_SIZE = MAX_NUM_OF_COMPONENTS*4*4; //-------------------------------------------------------------------- // Versioning Registers // ------------------------------------------------------------------- // Check that address is within this module's range. wire address_in_range = (s_ctrlport_req_addr >= REG_BASE) && (s_ctrlport_req_addr < REG_BASE + REG_SIZE); // Mask out 6 bits (64 components) to be able to compare all components // against the same base register address. wire [31:0] register_base_address = {s_ctrlport_req_addr[19:10], 6'b0, s_ctrlport_req_addr[3:0]}; // Extract masked out bits from the address, which represent the // component that is being addressed (0-63) = 6 bits. wire [ 5:0] component_index = s_ctrlport_req_addr[9:4]; // Obtain the indexed component's versions wire [COMPONENT_VERSIONS_SIZE-1:0] component_versions = get_component_versions(version_info, component_index); // Registers implementation always @ (posedge s_ctrlport_clk) begin if (s_ctrlport_rst) begin s_ctrlport_resp_ack <= 1'b0; s_ctrlport_resp_status <= 2'b00; s_ctrlport_resp_data <= {32 {1'bX}}; end else begin // Write registers if (s_ctrlport_req_wr) begin // Do not acknowledge by default s_ctrlport_resp_ack <= 1'b0; s_ctrlport_resp_data <= 32'h0; // No writable registers // Acknowledge and provide error status if address is in range if (address_in_range) begin s_ctrlport_resp_ack <= 1'b1; s_ctrlport_resp_status <= CTRL_STS_CMDERR; end // Read registers end else if (s_ctrlport_req_rd) begin // Acknowledge by default s_ctrlport_resp_ack <= 1'b1; s_ctrlport_resp_data <= 32'h0; s_ctrlport_resp_status <= CTRL_STS_OKAY; case (register_base_address) // Each concatenated 96-bit vector contains 3 x 32-bit values: // [31: 0] -> Current version // [63:32] -> Oldest compatible version // [95:64] -> Last modified REG_BASE + CURRENT_VERSION(0): begin s_ctrlport_resp_data[VERSION_TYPE_SIZE-1:0] <= current_version(component_versions); end REG_BASE + OLDEST_COMPATIBLE_VERSION(0): begin s_ctrlport_resp_data[VERSION_TYPE_SIZE-1:0] <= oldest_compatible_version(component_versions); end REG_BASE + VERSION_LAST_MODIFIED(0): begin s_ctrlport_resp_data[TIMESTAMP_TYPE_SIZE-1:0] <= version_last_modified(component_versions); end // Do not acknowledge if address is not defined default: begin if (address_in_range) begin s_ctrlport_resp_status <= CTRL_STS_CMDERR; // No response if out of range end else begin s_ctrlport_resp_ack <= 1'b0; end end endcase end else begin s_ctrlport_resp_ack <= 1'b0; end end end endmodule `default_nettype wire //XmlParse xml_on // // // // // // Major number (max = 511): an increase reflects a breaking change.{BR/} // IMPORTANT! @.MAJOR must always remain in sync between the component's // @.CURRENT_VERSION and @.OLDEST_COMPATIBLE_VERSION registers.{BR/}{BR/} // Update @.MAJOR when: //
  • the component has changed and requires a software changes as a result. //
  • the component's bitfields/registers have been modified or deleted. //
  • the component's bitfields/registers are initialized to different value (unexpected by software). //
  • new bitfields/registers are added that require software interaction for the component to operate. // // // // // Minor number (max = 2047): an increase reflects a non-breaking change that the driver should be aware of.{BR/}{BR/} // Update @.MINOR when: //
  • a new feature is added to the component, which does not conflict with the driver. //
  • minor implementation changes were made to the component which are worth tracking. //
  • the component has added new bitfields/registers that do not require software interaction // (i.e. the default value is 0 and writing 0 does not change behavior, assuming SW writes 0's to // previously undefined bits). //
  • @.MAJOR is updated (reset @.MINOR to 0). // // // // // Build number (max = 4095): an increase reflects a change in the source code that yields a new implementation, // but that should not impact the component's behavior {BR/} // Eventually, this number is intended to be automatically incremented for any new build.{BR/}{BR/} // Meanwhile, update @.BUILD when: //
  • the component's source code changes are not captured by @.MAJOR or @.MINOR. //
  • @.MINOR or @.MAJOR are updated (reset @.BUILD to 0). // // // // // // Component's versions update time.{BR/} // This register provides the time stamp for the last modification to // the component's versions (current & oldest compatible). // The time stamp is provided in hexadecimal format: 0xYYMMDDHH. // // // This is the year number after 2000 (e.g. 2019 = 0x19). // // // // // // // // Reserved. // // // // // // This enum contains indexes for all the components in the X410 // (both common and app-specific) which version information is // desired to be available for compatibility tracking purposes.{BR/} // {table border="1"} // {tr}{th}Description{/th} {th}Index range{/th} {th}Max # of components{/th}{/tr} // {tr}{td}Common components{/td} {td}0 to 23{/td} {td}24{/td}{/tr} // {tr}{td}UHD-specific components{/td} {td}24 to 43{/td} {td}20{/td}{/tr} // {tr}{td}LV-specific components{/td} {td}44 to 63{/td} {td}20{/td}{/tr} // {/table} // // // // // // // // // // // // Component's current version.{BR/} // This register contains the current component's version implemented in HDL. // The current version shall be used to detect a component being too // old for the driver/software:{BR/} // SW oldest compatible version > Component's current version --> Component is too old. // // // // // Component's oldest compatible version.{BR/} // This register contains the oldest compatible component's version, that is the oldest // component's implementation that is compatible with the current implementation.{BR/} // The oldest compatible version shall be used to detect a component being too // new for the driver/software:{BR/} // SW current version < Component's oldest compatible version --> Component is too new. // // // // // // // //XmlParse xml_off