1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
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
|