diff options
Diffstat (limited to 'fpga/usrp3/top/x400/x4xx_versioning_regs.v')
-rw-r--r-- | fpga/usrp3/top/x400/x4xx_versioning_regs.v | 267 |
1 files changed, 267 insertions, 0 deletions
diff --git a/fpga/usrp3/top/x400/x4xx_versioning_regs.v b/fpga/usrp3/top/x400/x4xx_versioning_regs.v new file mode 100644 index 000000000..b34e1294e --- /dev/null +++ b/fpga/usrp3/top/x400/x4xx_versioning_regs.v @@ -0,0 +1,267 @@ +// +// 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 +//<regmap name="VERSIONING_REGS_REGMAP" readablestrobes="false" generatevhdl="true" ettusguidelines="true"> +// <group name="VERSIONING_REGS"> +// <regtype name="VERSION_TYPE" size="32" attributes="Readable"> +// <bitfield name="MAJOR" range="31..23" initialvalue="0"> +// <info> +// Major number (max = 511): an increase reflects a breaking change.{BR/} +// <b>IMPORTANT!</b> @.MAJOR must always remain in sync between the component's +// @.CURRENT_VERSION and @.OLDEST_COMPATIBLE_VERSION registers.{BR/}{BR/} +// Update @.MAJOR when: +// <li>the component has changed and requires a software changes as a result. +// <li>the component's bitfields/registers have been modified or deleted. +// <li>the component's bitfields/registers are initialized to different value (unexpected by software). +// <li>new bitfields/registers are added that require software interaction for the component to operate. +// </info> +// </bitfield> +// <bitfield name="MINOR" range="22..12" initialvalue="0"> +// <info> +// Minor number (max = 2047): an increase reflects a non-breaking change that the driver should be aware of.{BR/}{BR/} +// Update @.MINOR when: +// <li>a new feature is added to the component, which does not conflict with the driver. +// <li>minor implementation changes were made to the component which are worth tracking. +// <li>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). +// <li>@.MAJOR is updated (reset @.MINOR to 0). +// </info> +// </bitfield> +// <bitfield name="BUILD" range="11..0" initialvalue="0"> +// <info> +// 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: +// <li>the component's source code changes are not captured by @.MAJOR or @.MINOR. +// <li>@.MINOR or @.MAJOR are updated (reset @.BUILD to 0). +// </info> +// </bitfield> +// </regtype> +// <regtype name="TIMESTAMP_TYPE" size="32" attributes="Readable"> +// <info> +// 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. +// </info> +// <bitfield name="YY" range="31..24"> +// <info>This is the year number after 2000 (e.g. 2019 = 0x19).</info> +// </bitfield> +// <bitfield name="MM" range="23..16"/> +// <bitfield name="DD" range="15..8"/> +// <bitfield name="HH" range="7..0"/> +// </regtype> +// <regtype name="RESERVED_TYPE" size="32" attributes="Readable"> +// <info> +// Reserved. +// </info> +// </regtype> +// +// <enumeratedtype name="COMPONENTS_INDEXES"> +// <info> +// 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} +// </info> +// <value name="FPGA_VERSION_INDEX" integer="0"/> +// <value name="CPLD_IFC_INDEX" integer="1"/> +// <value name="DB0_RF_CORE_INDEX" integer="2"/> +// <value name="DB1_RF_CORE_INDEX" integer="3"/> +// <value name="DB0_GPIO_IFC_INDEX" integer="4"/> +// <value name="DB1_GPIO_IFC_INDEX" integer="5"/> +// </enumeratedtype> +// +// <register name="CURRENT_VERSION" offset="0x0" count="64" step="16" typename="VERSION_TYPE"> +// <info> +// 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/} +// <b>SW oldest compatible version > Component's current version --> Component is too old.</b> +// </info> +// </register> +// <register name="OLDEST_COMPATIBLE_VERSION" offset="0x4" count="64" step="16" typename="VERSION_TYPE"> +// <info> +// 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/} +// <b>SW current version < Component's oldest compatible version --> Component is too new.</b> +// </info> +// </register> +// <register name="VERSION_LAST_MODIFIED" offset="0x8" count="64" step="16" typename="TIMESTAMP_TYPE"/> +// <register name="RESERVED" offset="0xC" count="64" step="16" typename="RESERVED_TYPE"/> +// +// </group> +//</regmap> +//XmlParse xml_off |