blob: 975ee3731675552a417b71f45ba528be2e27cacd [file] [log] [blame]
Timothy Chen15adeee2020-09-09 15:44:35 -07001// Copyright lowRISC contributors.
2// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3// SPDX-License-Identifier: Apache-2.0
4//
5// Key manager top level
6//
7
8`include "prim_assert.sv"
9
Timothy Chen5d06aac2021-08-09 17:08:24 -070010module keymgr_ctrl import keymgr_pkg::*; #(
11 parameter bit KmacEnMasking = 1'b1
12) (
Timothy Chen15adeee2020-09-09 15:44:35 -070013 input clk_i,
14 input rst_ni,
15
16 // lifecycle enforcement
Timothy Chen6d99c342020-11-13 12:02:42 -080017 input en_i,
Timothy Chen15adeee2020-09-09 15:44:35 -070018
Timothy Chen80fb8f42021-08-02 14:36:28 -070019 // faults that can occur outside of operations
20 input regfile_intg_err_i,
Timothy Chen4fb25fc2021-08-19 18:15:08 -070021 input shadowed_update_err_i,
22 input shadowed_storage_err_i,
Timothy Chen80fb8f42021-08-02 14:36:28 -070023
Timothy Chen15adeee2020-09-09 15:44:35 -070024 // Software interface
Timothy Chen15adeee2020-09-09 15:44:35 -070025 input op_start_i,
Timothy Chen1d05bd62020-10-07 18:42:07 -070026 input keymgr_ops_e op_i,
Timothy Chen1a162112021-06-30 18:35:59 -070027 input [CdiWidth-1:0] op_cdi_sel_i,
Timothy Chen15adeee2020-09-09 15:44:35 -070028 output logic op_done_o,
29 output keymgr_op_status_e status_o,
30 output logic [ErrLastPos-1:0] error_o,
Timothy Chen80fb8f42021-08-02 14:36:28 -070031 output logic [FaultLastPos-1:0] fault_o,
Timothy Chen8cf1a3a2020-12-08 19:05:29 -080032 output logic data_en_o,
Timothy Chen15adeee2020-09-09 15:44:35 -070033 output logic data_valid_o,
Timothy Chen6d99c342020-11-13 12:02:42 -080034 output logic wipe_key_o,
Timothy Chen15adeee2020-09-09 15:44:35 -070035 output keymgr_working_state_e working_state_o,
Timothy Chen12ca8622020-12-08 12:29:44 -080036 output logic sw_binding_unlock_o,
Timothy Chen0a120942020-12-14 17:20:51 -080037 output logic init_o,
Timothy Chen15adeee2020-09-09 15:44:35 -070038
39 // Data input
Timothy Chen65e16672020-12-05 09:17:14 -080040 input otp_ctrl_pkg::otp_keymgr_key_t root_key_i,
Timothy Chen15adeee2020-09-09 15:44:35 -070041 output keymgr_gen_out_e hw_sel_o,
42 output keymgr_stage_e stage_sel_o,
Timothy Chen1a162112021-06-30 18:35:59 -070043 output logic [CdiWidth-1:0] cdi_sel_o,
Timothy Chen15adeee2020-09-09 15:44:35 -070044
45 // KMAC ctrl interface
46 output logic adv_en_o,
47 output logic id_en_o,
48 output logic gen_en_o,
Timothy Chen8cf1a3a2020-12-08 19:05:29 -080049 output hw_key_req_t key_o,
Timothy Chen15adeee2020-09-09 15:44:35 -070050 input kmac_done_i,
51 input kmac_input_invalid_i, // asserted when selected data fails criteria check
52 input kmac_fsm_err_i, // asserted when kmac fsm reaches unexpected state
Timothy Cheneaa3f2b2020-10-27 17:10:15 -070053 input kmac_op_err_i, // asserted when kmac itself reports an error
Timothy Chen15adeee2020-09-09 15:44:35 -070054 input kmac_cmd_err_i, // asserted when more than one command given to kmac
Timothy Chend5820b02020-12-05 17:19:06 -080055 input [Shares-1:0][KeyWidth-1:0] kmac_data_i,
56
57 // prng control interface
Timothy Chenbe2da9e2021-01-07 18:29:01 -080058 input [Shares-1:0][RandWidth-1:0] entropy_i,
Timothy Chend5820b02020-12-05 17:19:06 -080059 input prng_reseed_ack_i,
60 output logic prng_reseed_req_o,
61 output logic prng_en_o
Timothy Chen15adeee2020-09-09 15:44:35 -070062);
Timothy Chend5820b02020-12-05 17:19:06 -080063
Timothy Chen15adeee2020-09-09 15:44:35 -070064 localparam int EntropyWidth = LfsrWidth / 2;
65 localparam int EntropyRounds = KeyWidth / EntropyWidth;
Timothy Chen38033242021-06-29 10:06:12 -070066 localparam int EntropyRndWidth = prim_util_pkg::vbits(EntropyRounds);
Timothy Chen1a162112021-06-30 18:35:59 -070067 localparam int CntWidth = EntropyRounds > CDIs ? EntropyRndWidth : CdiWidth;
Timothy Chen15adeee2020-09-09 15:44:35 -070068
Timothy Chen9e365452020-12-07 19:04:00 -080069 // Enumeration for working state
Timothy Chen80fb8f42021-08-02 14:36:28 -070070 // Encoding generated with:
71 // $ ./util/design/sparse-fsm-encode.py -d 5 -m 11 -n 10 \
72 // -s 4101887575 --language=sv
73 //
74 // Hamming distance histogram:
75 //
76 // 0: --
77 // 1: --
78 // 2: --
79 // 3: --
80 // 4: --
81 // 5: |||||||||||||||||||| (54.55%)
82 // 6: |||||||||||||||| (45.45%)
83 // 7: --
84 // 8: --
85 // 9: --
86 // 10: --
87 //
88 // Minimum Hamming distance: 5
89 // Maximum Hamming distance: 6
90 // Minimum Hamming weight: 2
91 // Maximum Hamming weight: 8
92 //
93 localparam int StateWidth = 10;
94 typedef enum logic [StateWidth-1:0] {
95 StCtrlReset = 10'b1101100001,
96 StCtrlEntropyReseed = 10'b1110010010,
97 StCtrlRandom = 10'b0011110100,
98 StCtrlRootKey = 10'b0110101111,
99 StCtrlInit = 10'b0100000100,
100 StCtrlCreatorRootKey = 10'b1000011101,
101 StCtrlOwnerIntKey = 10'b0001001010,
102 StCtrlOwnerKey = 10'b1101111110,
103 StCtrlDisabled = 10'b1010101000,
104 StCtrlWipe = 10'b0000110011,
105 StCtrlInvalid = 10'b1011000111
Timothy Chen9e365452020-12-07 19:04:00 -0800106 } keymgr_ctrl_state_e;
107
Timothy Chen38033242021-06-29 10:06:12 -0700108 // Enumeration for operation handling
Timothy Chen8e374342021-08-25 20:55:31 -0700109 typedef enum logic [1:0] {
Timothy Chen38033242021-06-29 10:06:12 -0700110 StIdle,
Timothy Chen38033242021-06-29 10:06:12 -0700111 StAdv,
112 StAdvAck,
113 StWait
114 } keymgr_op_state_e;
Timothy Chen15adeee2020-09-09 15:44:35 -0700115
Timothy Chen38033242021-06-29 10:06:12 -0700116 keymgr_ctrl_state_e state_q, state_d;
117 keymgr_op_state_e op_state_q, op_state_d;
118
119 // There are two versions of the key state, one for sealing one for attestation
120 // Among each version, there are multiple shares
121 // Each share is a fixed multiple of the entropy width
Timothy Chen1a162112021-06-30 18:35:59 -0700122 logic [CDIs-1:0][Shares-1:0][EntropyRounds-1:0][EntropyWidth-1:0] key_state_q, key_state_d;
Timothy Chen15adeee2020-09-09 15:44:35 -0700123 logic [CntWidth-1:0] cnt;
Timothy Chen1a162112021-06-30 18:35:59 -0700124 logic [CdiWidth-1:0] cdi_cnt;
Timothy Chen38033242021-06-29 10:06:12 -0700125
Timothy Chen8e374342021-08-25 20:55:31 -0700126 // error conditions
Timothy Chen28bbd322021-09-01 00:06:10 -0700127 logic invalid_kmac_out;
Timothy Chen15adeee2020-09-09 15:44:35 -0700128 logic invalid_op;
Timothy Chen8e374342021-08-25 20:55:31 -0700129 logic cnt_err;
Timothy Chen80fb8f42021-08-02 14:36:28 -0700130 // states fall out of sparsely encoded range
131 logic state_intg_err_q, state_intg_err_d;
132
Timothy Chen8e374342021-08-25 20:55:31 -0700133 ///////////////////////////
134 // General operation decode
135 ///////////////////////////
Timothy Chenbe2da9e2021-01-07 18:29:01 -0800136
Timothy Chen8e374342021-08-25 20:55:31 -0700137 logic adv_op, dis_op, gen_id_op, gen_sw_op, gen_hw_op, gen_op;
138 assign adv_op = (op_i == OpAdvance);
Timothy Chen8e374342021-08-25 20:55:31 -0700139 assign gen_id_op = (op_i == OpGenId);
140 assign gen_sw_op = (op_i == OpGenSwOut);
141 assign gen_hw_op = (op_i == OpGenHwOut);
Timothy Chend391e882021-09-08 12:27:13 -0700142 assign dis_op = ~(op_i inside {OpAdvance, OpGenId, OpGenSwOut, OpGenHwOut});
Timothy Chen8e374342021-08-25 20:55:31 -0700143 assign gen_op = (gen_id_op | gen_sw_op | gen_hw_op);
144
145 ///////////////////////////
146 // interaction between software and main fsm
147 ///////////////////////////
148 // disable is treated like an advanced call
149 logic advance_sel;
150 logic disable_sel;
151 logic gen_out_hw_sel;
152
153 assign advance_sel = op_start_i & adv_op & en_i;
154 assign gen_out_hw_sel = op_start_i & gen_hw_op & en_i;
155
156 // disable is selected whenever a normal operation is not set
157 assign disable_sel = (op_start_i & dis_op) | !en_i;
158
159
160 ///////////////////////////
161 // interaction between main control fsm and operation fsm
162 ///////////////////////////
Timothy Chen38033242021-06-29 10:06:12 -0700163
164 // req/ack interface with op handling fsm
165 logic op_req;
Timothy Chenbe2da9e2021-01-07 18:29:01 -0800166 logic op_ack;
Timothy Chen38033242021-06-29 10:06:12 -0700167 logic op_update;
Timothy Chen8e374342021-08-25 20:55:31 -0700168 logic op_busy;
169 logic disabled;
Timothy Chend86f3852021-09-08 16:03:38 -0700170 logic invalid;
Timothy Chen38033242021-06-29 10:06:12 -0700171
Timothy Chen8e374342021-08-25 20:55:31 -0700172 logic adv_req, dis_req, id_req, gen_req;
173 assign adv_req = op_req & adv_op;
174 assign dis_req = op_req & dis_op;
175 assign id_req = op_req & gen_id_op;
176 assign gen_req = op_req & (gen_sw_op | gen_hw_op);
Timothy Chen15adeee2020-09-09 15:44:35 -0700177
Timothy Chen8e374342021-08-25 20:55:31 -0700178 ///////////////////////////
179 // interaction between operation fsm and software
180 ///////////////////////////
Timothy Chen28bbd322021-09-01 00:06:10 -0700181 // categories of keymgr errors
182 logic [SyncErrLastIdx-1:0] sync_err;
183 logic [AsyncErrLastIdx-1:0] async_err;
184 logic [SyncFaultLastIdx-1:0] sync_fault;
185 logic [AsyncFaultLastIdx-1:0] async_fault;
Timothy Chen15adeee2020-09-09 15:44:35 -0700186
Timothy Chen8e374342021-08-25 20:55:31 -0700187 logic op_err;
188 logic op_fault_err;
Timothy Chen15adeee2020-09-09 15:44:35 -0700189
Timothy Chen12ca8622020-12-08 12:29:44 -0800190 // unlock sw binding configuration whenever an advance call is made without errors
Timothy Chen28bbd322021-09-01 00:06:10 -0700191 assign sw_binding_unlock_o = adv_req & op_ack & ~(op_err | op_fault_err);
Timothy Chen12ca8622020-12-08 12:29:44 -0800192
Timothy Chen8e374342021-08-25 20:55:31 -0700193 // error definition
Timothy Chen15adeee2020-09-09 15:44:35 -0700194 // check incoming kmac data validity
Timothy Chen28bbd322021-09-01 00:06:10 -0700195 // Only check during the periods when there is actual kmac output
196 assign invalid_kmac_out = (op_update | op_ack) &
197 (~valid_data_chk(kmac_data_i[0]) |
198 (~valid_data_chk(kmac_data_i[1]) & KmacEnMasking));
Timothy Chen754a5272021-01-06 10:41:08 -0800199
Timothy Chen28bbd322021-09-01 00:06:10 -0700200 assign op_err = sync_err[SyncErrInvalidOp] |
201 sync_err[SyncErrInvalidIn];
Timothy Chenbe2da9e2021-01-07 18:29:01 -0800202
Timothy Chen28bbd322021-09-01 00:06:10 -0700203 assign op_fault_err = |sync_fault |
204 |async_fault;
Timothy Chen15adeee2020-09-09 15:44:35 -0700205
Timothy Chen80fb8f42021-08-02 14:36:28 -0700206
Timothy Chen8e374342021-08-25 20:55:31 -0700207 ///////////////////////////
208 // key update controls
209 ///////////////////////////
210
211 // update select can come from both main and operation fsm's
212 keymgr_key_update_e update_sel, op_update_sel;
213
214 // req from main control fsm to key update controls
215 logic wipe_req;
216 logic random_req;
217 logic random_ack;
218
219 // wipe and initialize take precedence
220 assign update_sel = wipe_req ? KeyUpdateWipe :
221 random_req ? KeyUpdateRandom :
222 init_o ? KeyUpdateRoot : op_update_sel;
223
224 ///////////////////////////
225 // interaction between main fsm and prng
226 ///////////////////////////
227
228 logic prng_en;
Timothy Chend86f3852021-09-08 16:03:38 -0700229 assign prng_en_o = prng_en | disabled | invalid | wipe_req;
Timothy Chen8e374342021-08-25 20:55:31 -0700230
231 //////////////////////////
232 // Main Control FSM
233 //////////////////////////
Timothy Chen15adeee2020-09-09 15:44:35 -0700234
Timothy Chen80fb8f42021-08-02 14:36:28 -0700235 logic [StateWidth-1:0] state_raw_q;
236 assign state_q = keymgr_ctrl_state_e'(state_raw_q);
237 prim_flop #(
238 .Width(StateWidth),
239 .ResetValue(StateWidth'(StCtrlReset))
240 ) u_state_regs (
241 .clk_i,
242 .rst_ni,
243 .d_i ( state_d ),
244 .q_o ( state_raw_q )
245 );
246
Timothy Chen8e374342021-08-25 20:55:31 -0700247 always_ff @(posedge clk_i or negedge rst_ni) begin
248 if (!rst_ni) begin
249 state_intg_err_q <= '0;
250 end else begin
251 state_intg_err_q <= state_intg_err_d;
252 end
253 end
254
Timothy Chen15adeee2020-09-09 15:44:35 -0700255 // prevents unknowns from reaching the outside world.
Timothy Chen68c311a2020-12-04 12:31:17 -0800256 // - whatever operation causes the input data select to be disabled should not expose the key
257 // state.
258 // - when there are no operations, the key state also should be exposed.
Timothy Chen38033242021-06-29 10:06:12 -0700259 assign key_o.valid = op_req;
Timothy Chen1a162112021-06-30 18:35:59 -0700260 assign cdi_sel_o = advance_sel ? cdi_cnt : op_cdi_sel_i;
Timothy Chen70151fe2021-07-08 12:59:21 -0700261
262 for (genvar i = 0; i < Shares; i++) begin : gen_key_out_assign
263 assign key_o.key[i] = stage_sel_o == Disable ?
264 {EntropyRounds{entropy_i[i]}} :
Timothy Chenf433eea2021-07-21 10:53:46 -0700265 key_state_q[cdi_sel_o][i];
Timothy Chen70151fe2021-07-08 12:59:21 -0700266 end
267
Timothy Chen15adeee2020-09-09 15:44:35 -0700268
269 // key state is intentionally not reset
270 always_ff @(posedge clk_i) begin
271 key_state_q <= key_state_d;
272 end
273
Timothy Chen65e16672020-12-05 09:17:14 -0800274 // root key valid sync
275 logic root_key_valid_q;
276
277 prim_flop_2sync # (
278 .Width(1)
279 ) u_key_valid_sync (
280 .clk_i,
281 .rst_ni,
282 .d_i(root_key_i.valid),
283 .q_o(root_key_valid_q)
284 );
285
Timothy Chenf433eea2021-07-21 10:53:46 -0700286 // Do not let the count toggle unless an advance operation is
287 // selected
288 assign cdi_cnt = op_req ? cnt[CdiWidth-1:0] : '0;
Timothy Chen38033242021-06-29 10:06:12 -0700289
Timothy Chenbe2da9e2021-01-07 18:29:01 -0800290 always_comb begin
291 key_state_d = key_state_q;
292 data_valid_o = 1'b0;
293 wipe_key_o = 1'b0;
294
Timothy Chen38033242021-06-29 10:06:12 -0700295 // if a wipe request arrives, immediately destroy the
296 // keys regardless of current state
Timothy Chenbe2da9e2021-01-07 18:29:01 -0800297 unique case (update_sel)
298 KeyUpdateRandom: begin
Timothy Chen1a162112021-06-30 18:35:59 -0700299 for (int i = 0; i < CDIs; i++) begin
Timothy Chen38033242021-06-29 10:06:12 -0700300 for (int j = 0; j < Shares; j++) begin
301 key_state_d[i][j][cnt[EntropyRndWidth-1:0]] = entropy_i[j];
302 end
Timothy Chenbe2da9e2021-01-07 18:29:01 -0800303 end
304 end
305
306 KeyUpdateRoot: begin
307 if (root_key_valid_q) begin
Timothy Chen1a162112021-06-30 18:35:59 -0700308 for (int i = 0; i < CDIs; i++) begin
Timothy Chen5d06aac2021-08-09 17:08:24 -0700309 if (KmacEnMasking) begin : gen_two_share_key
310 key_state_d[i][0] = root_key_i.key_share0;
311 key_state_d[i][1] = root_key_i.key_share1;
312 end else begin : gen_one_share_key
313 key_state_d[i][0] = root_key_i.key_share0 ^ root_key_i.key_share1;
314 key_state_d[i][1] = '0;
315 end
Timothy Chen38033242021-06-29 10:06:12 -0700316 end
Timothy Chenbe2da9e2021-01-07 18:29:01 -0800317 end
318 end
319
320 KeyUpdateKmac: begin
Timothy Chen8e374342021-08-25 20:55:31 -0700321 data_valid_o = gen_op;
322 key_state_d[cdi_sel_o] = (adv_op || dis_op) ? kmac_data_i : key_state_q[cdi_sel_o];
Timothy Chenbe2da9e2021-01-07 18:29:01 -0800323 end
324
325 KeyUpdateWipe: begin
326 wipe_key_o = 1'b1;
Timothy Chen1a162112021-06-30 18:35:59 -0700327 for (int i = 0; i < CDIs; i++) begin
Timothy Chen38033242021-06-29 10:06:12 -0700328 for (int j = 0; j < Shares; j++) begin
329 key_state_d[i][j] = {EntropyRounds{entropy_i[j]}};
330 end
Timothy Chenbe2da9e2021-01-07 18:29:01 -0800331 end
332 end
333
334 default:;
335 endcase // unique case (update_sel)
336 end
337
Timothy Chendf2c0a72021-09-16 16:10:12 -0700338 prim_count #(
Timothy Cheneb7bf612021-08-03 16:17:09 -0700339 .Width(CntWidth),
Timothy Chendf2c0a72021-09-16 16:10:12 -0700340 .CntStyle(prim_count_pkg::DupCnt)
Timothy Cheneb7bf612021-08-03 16:17:09 -0700341 ) u_cnt (
342 .clk_i,
343 .rst_ni,
344 .clr_i(op_ack | random_ack),
345 .set_i('0),
346 .set_cnt_i('0),
Timothy Chen8e374342021-08-25 20:55:31 -0700347 .en_i(op_update | random_req),
Timothy Cheneb7bf612021-08-03 16:17:09 -0700348 .cnt_o(cnt),
349 .err_o(cnt_err)
350 );
Timothy Chenbe2da9e2021-01-07 18:29:01 -0800351
Timothy Chen9e365452020-12-07 19:04:00 -0800352 // TODO: Create a no select option, do not leave this as binary
353 assign hw_sel_o = gen_out_hw_sel ? HwKey : SwKey;
354
Timothy Chen71779e12021-01-06 12:09:57 -0800355
Timothy Chen38033242021-06-29 10:06:12 -0700356 // when in a state that accepts commands, look at op_ack for completion
Timothy Chenbe2da9e2021-01-07 18:29:01 -0800357 // when in a state that does not accept commands, wait for other triggers.
Timothy Chen38033242021-06-29 10:06:12 -0700358 assign op_done_o = op_req ? op_ack :
359 (init_o | invalid_op);
Timothy Chenbe2da9e2021-01-07 18:29:01 -0800360
361
Timothy Chen8e374342021-08-25 20:55:31 -0700362 // There are 3 possibilities
363 // advance to next state (software command)
364 // advance to disabled state (software command)
365 // advance to invalid state (detected fault)
366 logic adv_state;
367 logic dis_state;
368 logic inv_state;
Timothy Chen28bbd322021-09-01 00:06:10 -0700369 assign adv_state = op_ack & adv_req & ~op_err;
Timothy Chen8e374342021-08-25 20:55:31 -0700370 assign dis_state = op_ack & dis_req;
Timothy Chend02fba72021-09-01 22:49:21 -0700371 assign inv_state = op_ack & op_fault_err;
Timothy Chen38033242021-06-29 10:06:12 -0700372
Timothy Chen15adeee2020-09-09 15:44:35 -0700373 always_comb begin
374 // persistent data
375 state_d = state_q;
Timothy Chen15adeee2020-09-09 15:44:35 -0700376
Timothy Chen38033242021-06-29 10:06:12 -0700377 // request to op handling
378 op_req = 1'b0;
379 random_req = 1'b0;
Timothy Chen8e374342021-08-25 20:55:31 -0700380 random_ack = 1'b0;
Timothy Chenbe2da9e2021-01-07 18:29:01 -0800381
Timothy Chen38033242021-06-29 10:06:12 -0700382 // request to key updates
383 wipe_req = 1'b0;
Timothy Chenbe2da9e2021-01-07 18:29:01 -0800384
385 // invalid operation issued
Timothy Chen15adeee2020-09-09 15:44:35 -0700386 invalid_op = 1'b0;
387
388 // data update and select signals
Timothy Chen15adeee2020-09-09 15:44:35 -0700389 stage_sel_o = Disable;
390
Timothy Chen8e374342021-08-25 20:55:31 -0700391 // indication that state is disabled
392 disabled = 1'b0;
393
Timothy Chend86f3852021-09-08 16:03:38 -0700394 // indication that state is invalid
395 invalid = 1'b0;
396
Timothy Chen15adeee2020-09-09 15:44:35 -0700397 // enable prng toggling
Timothy Chend5820b02020-12-05 17:19:06 -0800398 prng_reseed_req_o = 1'b0;
Timothy Chen8e374342021-08-25 20:55:31 -0700399 prng_en = 1'b0;
Timothy Chen15adeee2020-09-09 15:44:35 -0700400
Timothy Chen0a120942020-12-14 17:20:51 -0800401 // initialization complete
402 init_o = 1'b0;
403
Timothy Chen80fb8f42021-08-02 14:36:28 -0700404 // if state is ever faulted, hold on to this indication
405 // until reset.
406 state_intg_err_d = state_intg_err_q;
407
Timothy Chen15adeee2020-09-09 15:44:35 -0700408 unique case (state_q)
Timothy Chen9e365452020-12-07 19:04:00 -0800409 // Only advance can be called from reset state
410 StCtrlReset: begin
Timothy Chen15adeee2020-09-09 15:44:35 -0700411 // in reset state, don't enable entropy yet, since there are no users.
Timothy Chen8e374342021-08-25 20:55:31 -0700412 prng_en = 1'b0;
Timothy Chen15adeee2020-09-09 15:44:35 -0700413
Timothy Chen9e365452020-12-07 19:04:00 -0800414 // always use random data for advance, since out of reset state
415 // the key state will be randomized.
416 stage_sel_o = Disable;
417
418 // key state is updated when it is an advance call
419 // all other operations are invalid, including disable
420 if (advance_sel) begin
421 state_d = StCtrlEntropyReseed;
422 end else if (op_start_i) begin
Timothy Chen9e365452020-12-07 19:04:00 -0800423 invalid_op = 1'b1;
Timothy Chen1d05bd62020-10-07 18:42:07 -0700424 end
Timothy Chen15adeee2020-09-09 15:44:35 -0700425 end
426
Timothy Chend5820b02020-12-05 17:19:06 -0800427 // reseed entropy
Timothy Chen9e365452020-12-07 19:04:00 -0800428 StCtrlEntropyReseed: begin
Timothy Chend5820b02020-12-05 17:19:06 -0800429 prng_reseed_req_o = 1'b1;
Timothy Chen84b7d1b2021-08-12 16:42:45 -0700430
Timothy Chend5820b02020-12-05 17:19:06 -0800431 if (prng_reseed_ack_i) begin
Timothy Chen8e374342021-08-25 20:55:31 -0700432 state_d = StCtrlRandom;
Timothy Chend5820b02020-12-05 17:19:06 -0800433 end
434 end
435
Timothy Chen1d05bd62020-10-07 18:42:07 -0700436 // This state does not accept any command.
Timothy Chen9e365452020-12-07 19:04:00 -0800437 StCtrlRandom: begin
Timothy Chen8e374342021-08-25 20:55:31 -0700438 prng_en = 1'b1;
Timothy Chenbe2da9e2021-01-07 18:29:01 -0800439
Timothy Chen8e374342021-08-25 20:55:31 -0700440 if (cnt < EntropyRounds-1) begin
441 random_req = 1'b1;
442 end
443 // when mask population is complete, xor the root_key into the zero share
444 // if in the future the root key is updated to 2 shares, it will direclty overwrite
445 // the values here
446 else begin
447 random_ack = 1'b1;
448 state_d = StCtrlRootKey;
Timothy Chen15adeee2020-09-09 15:44:35 -0700449 end
450 end
451
Timothy Chenbe2da9e2021-01-07 18:29:01 -0800452 // load the root key.
453 StCtrlRootKey: begin
Timothy Chend02fba72021-09-01 22:49:21 -0700454 // we cannot directly use inv_state here for 2 reasons
455 // - inv_state is sync'd to the completion of a real kmac operation,
456 // which is not the case here.
457 // - using inv_state would cause a combo loop between init_o and inv_state.
458 init_o = en_i & ~|async_fault;
459 state_d = !init_o ? StCtrlWipe : StCtrlInit;
Timothy Chenbe2da9e2021-01-07 18:29:01 -0800460 end
461
Timothy Chen15adeee2020-09-09 15:44:35 -0700462 // Beginning from the Init state, operations are accepted.
463 // Only valid operation is advance state. If invalid command received,
464 // random data is selected for operation and no persistent state is changed.
Timothy Chen9e365452020-12-07 19:04:00 -0800465 StCtrlInit: begin
Timothy Chen38033242021-06-29 10:06:12 -0700466 op_req = op_start_i;
Timothy Chen15adeee2020-09-09 15:44:35 -0700467
Timothy Chen68c311a2020-12-04 12:31:17 -0800468 // when advancing select creator data, otherwise use random input
469 stage_sel_o = advance_sel ? Creator : Disable;
Timothy Chenbe2da9e2021-01-07 18:29:01 -0800470 invalid_op = op_start_i & ~(advance_sel | disable_sel);
Timothy Chen68c311a2020-12-04 12:31:17 -0800471
Timothy Chen8e374342021-08-25 20:55:31 -0700472 if (!en_i || inv_state) begin
Timothy Chen9e365452020-12-07 19:04:00 -0800473 state_d = StCtrlWipe;
Timothy Chen8e374342021-08-25 20:55:31 -0700474 end else if (dis_state) begin
Timothy Chen9e365452020-12-07 19:04:00 -0800475 state_d = StCtrlDisabled;
Timothy Chen8e374342021-08-25 20:55:31 -0700476 end else if (adv_state) begin
Timothy Chen9e365452020-12-07 19:04:00 -0800477 state_d = StCtrlCreatorRootKey;
Timothy Chen15adeee2020-09-09 15:44:35 -0700478 end
479 end
480
Timothy Chen38033242021-06-29 10:06:12 -0700481 // all commands are valid during this stage
Timothy Chen9e365452020-12-07 19:04:00 -0800482 StCtrlCreatorRootKey: begin
Timothy Chen38033242021-06-29 10:06:12 -0700483 op_req = op_start_i;
Timothy Chen15adeee2020-09-09 15:44:35 -0700484
485 // when generating, select creator data input
486 // when advancing, select owner intermediate key as target
487 // when disabling, select random data input
Timothy Chen6d99c342020-11-13 12:02:42 -0800488 stage_sel_o = disable_sel ? Disable :
489 advance_sel ? OwnerInt : Creator;
Timothy Chen15adeee2020-09-09 15:44:35 -0700490
Timothy Chen8e374342021-08-25 20:55:31 -0700491 if (!en_i || inv_state) begin
Timothy Chen9e365452020-12-07 19:04:00 -0800492 state_d = StCtrlWipe;
Timothy Chen8e374342021-08-25 20:55:31 -0700493 end else if (dis_state) begin
Timothy Chen9e365452020-12-07 19:04:00 -0800494 state_d = StCtrlDisabled;
Timothy Chen8e374342021-08-25 20:55:31 -0700495 end else if (adv_state) begin
Timothy Chen9e365452020-12-07 19:04:00 -0800496 state_d = StCtrlOwnerIntKey;
Timothy Chen15adeee2020-09-09 15:44:35 -0700497 end
498 end
499
Timothy Chen15adeee2020-09-09 15:44:35 -0700500 // all commands are valid during this stage
Timothy Chen9e365452020-12-07 19:04:00 -0800501 StCtrlOwnerIntKey: begin
Timothy Chen38033242021-06-29 10:06:12 -0700502 op_req = op_start_i;
Timothy Chen15adeee2020-09-09 15:44:35 -0700503
Timothy Chen6d99c342020-11-13 12:02:42 -0800504 // when generating, select owner intermediate data input
505 // when advancing, select owner as target
Timothy Chen15adeee2020-09-09 15:44:35 -0700506 // when disabling, select random data input
Timothy Chen6d99c342020-11-13 12:02:42 -0800507 stage_sel_o = disable_sel ? Disable :
508 advance_sel ? Owner : OwnerInt;
Timothy Chen15adeee2020-09-09 15:44:35 -0700509
Timothy Chen8e374342021-08-25 20:55:31 -0700510 if (!en_i || inv_state) begin
Timothy Chen9e365452020-12-07 19:04:00 -0800511 state_d = StCtrlWipe;
Timothy Chen8e374342021-08-25 20:55:31 -0700512 end else if (dis_state) begin
Timothy Chen9e365452020-12-07 19:04:00 -0800513 state_d = StCtrlDisabled;
Timothy Chen8e374342021-08-25 20:55:31 -0700514 end else if (adv_state) begin
Timothy Chen9e365452020-12-07 19:04:00 -0800515 state_d = StCtrlOwnerKey;
Timothy Chen15adeee2020-09-09 15:44:35 -0700516 end
517 end
518
519 // all commands are valid during this stage
520 // however advance goes directly to disabled state
Timothy Chen9e365452020-12-07 19:04:00 -0800521 StCtrlOwnerKey: begin
Timothy Chen38033242021-06-29 10:06:12 -0700522 op_req = op_start_i;
Timothy Chen15adeee2020-09-09 15:44:35 -0700523
Timothy Chen6d99c342020-11-13 12:02:42 -0800524 // when generating, select owner data input
525 // when advancing, select disable as target
526 // when disabling, select random data input
Timothy Chen68c311a2020-12-04 12:31:17 -0800527 stage_sel_o = disable_sel | advance_sel ? Disable : Owner;
Timothy Chen15adeee2020-09-09 15:44:35 -0700528
Timothy Chen8e374342021-08-25 20:55:31 -0700529 if (!en_i || inv_state) begin
Timothy Chen9e365452020-12-07 19:04:00 -0800530 state_d = StCtrlWipe;
Timothy Chen8e374342021-08-25 20:55:31 -0700531 end else if (adv_state || dis_state) begin
Timothy Chen9e365452020-12-07 19:04:00 -0800532 state_d = StCtrlDisabled;
Timothy Chen15adeee2020-09-09 15:44:35 -0700533 end
534 end
535
Timothy Chen6d99c342020-11-13 12:02:42 -0800536 // The wipe state immediately clears out the key state, but waits for any ongoing
537 // transaction to finish before going to disabled state.
538 // Unlike the random state, this is an immedaite shutdown request, so all parts of the
539 // key are wiped.
Timothy Chen9e365452020-12-07 19:04:00 -0800540 StCtrlWipe: begin
Timothy Chen38033242021-06-29 10:06:12 -0700541 wipe_req = 1'b1;
Timothy Chen8e374342021-08-25 20:55:31 -0700542 // if there was already an operation ongoing, maintain the request until completion
543 op_req = op_busy;
Timothy Chen38033242021-06-29 10:06:12 -0700544 invalid_op = op_start_i;
Timothy Chen6d99c342020-11-13 12:02:42 -0800545
546 // If the enable is dropped during the middle of a transaction, we clear and wait for that
547 // transaction to gracefully complete (if it can).
548 // There are two scenarios:
549 // 1. the operation completed right when we started wiping, in which case the done would
550 // clear the start.
551 // 2. the operation completed before we started wiping, or there was never an operation to
552 // begin with (op_start_i == 0), in this case, don't wait and immediately transition
553 if (!op_start_i) begin
Timothy Chen71779e12021-01-06 12:09:57 -0800554 state_d = StCtrlInvalid;
Timothy Chen6d99c342020-11-13 12:02:42 -0800555 end
556 end
557
Timothy Chen8e374342021-08-25 20:55:31 -0700558 // StCtrlDisabled and StCtrlInvalid are almost functionally equivalent
559 // The only difference is that Disabled is entered through software invocation,
560 // while Invalid is entered through life cycle disable or operational fault.
561 //
562 // Both states continue to kick off random transactions
Timothy Chen38033242021-06-29 10:06:12 -0700563 // All transactions are treated as invalid despite completing
Timothy Chen8e374342021-08-25 20:55:31 -0700564 StCtrlDisabled: begin
Timothy Chen38033242021-06-29 10:06:12 -0700565 op_req = op_start_i;
Timothy Chen8e374342021-08-25 20:55:31 -0700566 disabled = 1'b1;
567
568 if (!en_i || inv_state) begin
569 state_d = StCtrlWipe;
570 end
571 end
572
573 StCtrlInvalid: begin
574 op_req = op_start_i;
Timothy Chend86f3852021-09-08 16:03:38 -0700575 invalid = 1'b1;
Timothy Chen15adeee2020-09-09 15:44:35 -0700576 end
Timothy Chen80fb8f42021-08-02 14:36:28 -0700577
578 // latch the fault indication and start to wipe the key manager
579 default: begin
580 state_intg_err_d = 1'b1;
581 state_d = StCtrlWipe;
582 end
583
Timothy Chen15adeee2020-09-09 15:44:35 -0700584 endcase // unique case (state_q)
Timothy Chenbe2da9e2021-01-07 18:29:01 -0800585 end // always_comb
Timothy Chen15adeee2020-09-09 15:44:35 -0700586
587 // Current working state provided for software read
Timothy Chen9e365452020-12-07 19:04:00 -0800588 // Certain states are collapsed for simplicity
Timothy Chen8e374342021-08-25 20:55:31 -0700589 keymgr_working_state_e last_working_st;
590 logic state_update;
591
592 always_ff @(posedge clk_i or negedge rst_ni) begin
593 if (!rst_ni) begin
594 last_working_st <= StReset;
595 end else if (state_update) begin
596 last_working_st <= working_state_o;
597 end
598 end
599
Timothy Chen9e365452020-12-07 19:04:00 -0800600 always_comb begin
Timothy Chen8e374342021-08-25 20:55:31 -0700601 state_update = 1'b1;
Timothy Chen71779e12021-01-06 12:09:57 -0800602 working_state_o = StInvalid;
Timothy Chen9e365452020-12-07 19:04:00 -0800603
604 unique case (state_q)
Timothy Chenbe2da9e2021-01-07 18:29:01 -0800605 StCtrlReset, StCtrlEntropyReseed, StCtrlRandom, StCtrlRootKey:
Timothy Chen9e365452020-12-07 19:04:00 -0800606 working_state_o = StReset;
607
608 StCtrlInit:
609 working_state_o = StInit;
610
611 StCtrlCreatorRootKey:
612 working_state_o = StCreatorRootKey;
613
614 StCtrlOwnerIntKey:
615 working_state_o = StOwnerIntKey;
616
617 StCtrlOwnerKey:
618 working_state_o = StOwnerKey;
619
Timothy Chen71779e12021-01-06 12:09:57 -0800620 StCtrlDisabled:
Timothy Chen9e365452020-12-07 19:04:00 -0800621 working_state_o = StDisabled;
622
Timothy Chen8e374342021-08-25 20:55:31 -0700623 StCtrlWipe: begin
624 state_update = 1'b0;
625 working_state_o = last_working_st;
626 end
627
628 StCtrlInvalid:
Timothy Chen71779e12021-01-06 12:09:57 -0800629 working_state_o = StInvalid;
630
Timothy Chen9e365452020-12-07 19:04:00 -0800631 default:
Timothy Chen71779e12021-01-06 12:09:57 -0800632 working_state_o = StInvalid;
Timothy Chen9e365452020-12-07 19:04:00 -0800633 endcase // unique case (state_q)
634 end
Timothy Chen15adeee2020-09-09 15:44:35 -0700635
Timothy Chen8e374342021-08-25 20:55:31 -0700636
637 /////////////////////////
638 // Operateion state, handle advance and generate
639 /////////////////////////
640
Timothy Chen38033242021-06-29 10:06:12 -0700641 always_ff @(posedge clk_i or negedge rst_ni) begin
642 if (!rst_ni) begin
Timothy Chen8e374342021-08-25 20:55:31 -0700643 op_state_q <= StIdle;
Timothy Cheneb7bf612021-08-03 16:17:09 -0700644 end else begin
Timothy Chen8e374342021-08-25 20:55:31 -0700645 op_state_q <= op_state_d;
Timothy Chen38033242021-06-29 10:06:12 -0700646 end
647 end
648
649 always_comb begin
650 op_state_d = op_state_q;
Timothy Chen38033242021-06-29 10:06:12 -0700651 op_update = 1'b0;
652 op_ack = 1'b0;
Timothy Chen8e374342021-08-25 20:55:31 -0700653 op_busy = 1'b1;
Timothy Chen38033242021-06-29 10:06:12 -0700654
655 // output to kmac interface
656 adv_en_o = 1'b0;
657 id_en_o = 1'b0;
658 gen_en_o = 1'b0;
659
Timothy Chen38033242021-06-29 10:06:12 -0700660 unique case (op_state_q)
661 StIdle: begin
Timothy Chen8e374342021-08-25 20:55:31 -0700662 op_busy = '0;
663 if (adv_req || dis_req) begin
Timothy Chen38033242021-06-29 10:06:12 -0700664 op_state_d = StAdv;
665 end else if (id_req || gen_req) begin
666 op_state_d = StWait;
667 end
668 end
669
Timothy Chen38033242021-06-29 10:06:12 -0700670 StAdv: begin
671 adv_en_o = 1'b1;
672
Timothy Chen1a162112021-06-30 18:35:59 -0700673 if (kmac_done_i && (cdi_cnt == CDIs-1)) begin
Timothy Chen38033242021-06-29 10:06:12 -0700674 op_ack = 1'b1;
675 op_state_d = StIdle;
Timothy Chen1a162112021-06-30 18:35:59 -0700676 end else if (kmac_done_i && (cdi_cnt < CDIs-1)) begin
Timothy Chen38033242021-06-29 10:06:12 -0700677 op_update = 1'b1;
678 op_state_d = StAdvAck;
679 end
Timothy Chen38033242021-06-29 10:06:12 -0700680 end
681
682 // drop adv_en_o to allow kmac interface handshake
683 StAdvAck: begin
684 op_state_d = StAdv;
685 end
686
687 // Not an advanced operation
688 StWait: begin
Timothy Chen8e374342021-08-25 20:55:31 -0700689 id_en_o = gen_id_op;
690 gen_en_o = gen_sw_op | gen_hw_op;
Timothy Chen38033242021-06-29 10:06:12 -0700691
692 if (kmac_done_i) begin
693 op_ack = 1'b1;
694 op_state_d = StIdle;
695 end
Timothy Chen38033242021-06-29 10:06:12 -0700696 end
697
698 // What should go here?
699 default:;
700
701 endcase // unique case (adv_state_q)
702 end
703
Timothy Chen8e374342021-08-25 20:55:31 -0700704 // operations fsm update precedence
Timothy Chend86f3852021-09-08 16:03:38 -0700705 // when in invalid state, always update.
706 // when in disabled state, always update unless a fault is encountered.
707 assign op_update_sel = (op_ack | op_update) & invalid ? KeyUpdateKmac :
Timothy Chend02fba72021-09-01 22:49:21 -0700708 (op_ack | op_update) & op_fault_err ? KeyUpdateWipe :
Timothy Chend86f3852021-09-08 16:03:38 -0700709 (op_ack | op_update) & disabled ? KeyUpdateKmac :
Timothy Chend02fba72021-09-01 22:49:21 -0700710 (op_ack | op_update) & op_err ? KeyUpdateIdle :
711 (op_ack | op_update) ? KeyUpdateKmac : KeyUpdateIdle;
Timothy Chen38033242021-06-29 10:06:12 -0700712
Timothy Chen80fb8f42021-08-02 14:36:28 -0700713
Timothy Chen28bbd322021-09-01 00:06:10 -0700714 // Advance calls are made up of multiple rounds of kmac operations.
715 // Any sync error that occurs is treated as an error of the entire call.
716 // Therefore sync errors that happen before the end of the call must be
717 // latched.
718 logic[SyncErrLastIdx-1:0] sync_err_q, sync_err_d;
719 logic[SyncFaultLastIdx-1:0] sync_fault_q, sync_fault_d;
720
721 logic err_vld;
722 assign err_vld = op_update | op_done_o;
723
724 // sync errors
725 // When an operation encounters a fault, the operation is always rejected as the FSM
Timothy Chend02fba72021-09-01 22:49:21 -0700726 // transitions to wipe. When an operation is ongoing and en drops, it is also rejected.
Timothy Chend86f3852021-09-08 16:03:38 -0700727 assign sync_err_d[SyncErrInvalidOp] = err_vld & (invalid_op | disabled | invalid | op_fault_err);
Timothy Chen28bbd322021-09-01 00:06:10 -0700728 assign sync_err_d[SyncErrInvalidIn] = err_vld & kmac_input_invalid_i;
729 always_ff @(posedge clk_i or negedge rst_ni) begin
730 if (!rst_ni) begin
731 sync_err_q <= '0;
732 end else if (op_done_o) begin
733 sync_err_q <= '0;
734 end else if (op_update) begin
735 sync_err_q <= sync_err_d;
736 end
737 end
738 assign sync_err = sync_err_q | sync_err_d;
739
740 // async errors
741 assign async_err[AsyncErrShadowUpdate] = shadowed_update_err_i;
742
743 // sync faults
744 assign sync_fault_d[SyncFaultKmacOp] = err_vld & kmac_op_err_i;
745 assign sync_fault_d[SyncFaultKmacOut] = err_vld & invalid_kmac_out;
746 always_ff @(posedge clk_i or negedge rst_ni) begin
747 if (!rst_ni) begin
748 sync_fault_q <= '0;
749 end else if (op_update) begin
750 sync_fault_q <= sync_fault_d;
751 end
752 end
753 assign sync_fault = sync_fault_q | sync_fault_d;
754
755 // async faults
Timothy Chena8527ca2021-09-15 15:45:42 -0700756 logic [AsyncFaultLastIdx-1:0] async_fault_q, async_fault_d;
757 always_ff @(posedge clk_i or negedge rst_ni) begin
758 if (!rst_ni) begin
759 async_fault_q <= '0;
760 end else begin
761 async_fault_q <= async_fault;
762 end
763 end
764 assign async_fault = async_fault_q | async_fault_d;
765 assign async_fault_d[AsyncFaultKmacCmd] = kmac_cmd_err_i;
766 assign async_fault_d[AsyncFaultKmacFsm] = kmac_fsm_err_i;
767 assign async_fault_d[AsyncFaultRegIntg] = regfile_intg_err_i;
768 assign async_fault_d[AsyncFaultShadow ] = shadowed_storage_err_i;
769 assign async_fault_d[AsyncFaultFsmIntg] = state_intg_err_q;
770 assign async_fault_d[AsyncFaultCntErr ] = cnt_err;
Timothy Chen28bbd322021-09-01 00:06:10 -0700771
772 // output to error code register
773 assign error_o[ErrInvalidOp] = op_done_o & sync_err[SyncErrInvalidOp];
774 assign error_o[ErrInvalidIn] = op_done_o & sync_err[SyncErrInvalidIn];
775 assign error_o[ErrShadowUpdate] = async_err[AsyncErrShadowUpdate];
776
777 // output to fault code register
778 assign fault_o[FaultKmacOp] = op_done_o & sync_fault[SyncFaultKmacOp];
779 assign fault_o[FaultKmacOut] = op_done_o & sync_fault[SyncFaultKmacOut];
780 assign fault_o[FaultKmacCmd] = async_fault[AsyncFaultKmacCmd];
781 assign fault_o[FaultKmacFsm] = async_fault[AsyncFaultKmacFsm];
782 assign fault_o[FaultRegIntg] = async_fault[AsyncFaultRegIntg];
783 assign fault_o[FaultShadow] = async_fault[AsyncFaultShadow];
784 assign fault_o[FaultCtrlFsm] = async_fault[AsyncFaultFsmIntg];
785 assign fault_o[FaultCtrlCnt] = async_fault[AsyncFaultCntErr];
Timothy Chen15adeee2020-09-09 15:44:35 -0700786
787 always_comb begin
788 status_o = OpIdle;
789 if (op_done_o) begin
Timothy Chen28bbd322021-09-01 00:06:10 -0700790 status_o = |error_o | |fault_o ? OpDoneFail : OpDoneSuccess;
Timothy Chen15adeee2020-09-09 15:44:35 -0700791 end else if (op_start_i) begin
792 status_o = OpWip;
793 end
794 end
795
796
Timothy Chen8cf1a3a2020-12-08 19:05:29 -0800797 ///////////////////////////////
798 // Suppress kmac return data
799 ///////////////////////////////
800 // This is a separate data path from the FSM used to control the data_en_o output
801
802 typedef enum logic [1:0] {
803 StCtrlDataIdle,
804 StCtrlDataEn,
805 StCtrlDataDis,
806 StCtrlDataWait
807 } keymgr_ctrl_data_state_e;
808
809 keymgr_ctrl_data_state_e data_st_d, data_st_q;
810
811 always_ff @(posedge clk_i or negedge rst_ni) begin
812 if (!rst_ni) begin
813 data_st_q <= StCtrlDataIdle;
814 end else begin
815 data_st_q <= data_st_d;
816 end
817 end
818
819 // The below control path is used for modulating the datapath to sideload and sw keys.
820 // This path is separate from the data_valid_o path, thus creating two separate attack points.
821 // The data is only enabled when a non-advance operation is invoked.
822 // When an advance operation is called, the data is disabled. It will stay disabled until an
823 // entire completion sequence is seen (op_done_o assert -> start_i de-assertion).
824 // When a generate operation is called, the data is enabled. However, any indication of this
825 // supposedly being an advance call will force the path to disable again.
826 always_comb begin
827 data_st_d = data_st_q;
828 data_en_o = 1'b0;
829 unique case (data_st_q)
830
831 StCtrlDataIdle: begin
832 if (adv_en_o) begin
833 data_st_d = StCtrlDataDis;
834 end else if (id_en_o || gen_en_o) begin
835 data_st_d = StCtrlDataEn;
836 end
837 end
838
839 StCtrlDataEn: begin
840 data_en_o = 1'b1;
Timothy Chen8e374342021-08-25 20:55:31 -0700841 if (op_done_o) begin
842 data_st_d = StCtrlDataWait;
843 end else if (adv_en_o) begin
Timothy Chen8cf1a3a2020-12-08 19:05:29 -0800844 data_st_d = StCtrlDataDis;
845 end
846 end
847
848 StCtrlDataDis: begin
849 if (op_done_o) begin
850 data_st_d = StCtrlDataWait;
851 end
852 end
853
854 StCtrlDataWait: begin
855 if (!op_start_i) begin
856 data_st_d = StCtrlDataIdle;
857 end
858 end
859
860 default:;
861
862 endcase // unique case (data_st_q)
863 end
864
Timothy Chen15adeee2020-09-09 15:44:35 -0700865 ///////////////////////////////
866 // Functions
867 ///////////////////////////////
868
869 // unclear what this is supposed to be yet
870 // right now just check to see if it not all 0's and not all 1's
Timothy Chenae05e942020-12-21 21:09:57 -0800871 function automatic logic valid_data_chk (logic [KeyWidth-1:0] value);
Timothy Chen15adeee2020-09-09 15:44:35 -0700872
873 return |value & ~&value;
874
875 endfunction // byte_mask
876
Timothy Chenae05e942020-12-21 21:09:57 -0800877 /////////////////////////////////
878 // Assertions
879 /////////////////////////////////
880
881 // stage select should always be Disable whenever it is not enabled
882 `ASSERT(StageDisableSel_A, !en_i |-> stage_sel_o == Disable)
883
884 // Unless it is a legal command, only select disable
885 `ASSERT(InitLegalCommands_A, op_start_i & en_i & state_q inside {StCtrlInit} &
886 !(op_i inside {OpAdvance}) |-> stage_sel_o == Disable)
887
888 // All commands are legal, so select disable only if operation is disable
889 `ASSERT(GeneralLegalCommands_A, op_start_i & en_i &
890 state_q inside {StCtrlCreatorRootKey, StCtrlOwnerIntKey} &
891 (op_i inside {OpDisable}) |-> stage_sel_o == Disable)
892
893 `ASSERT(OwnerLegalCommands_A, op_start_i & en_i & state_q inside {StCtrlOwnerKey} &
894 (op_i inside {OpAdvance, OpDisable}) |-> stage_sel_o == Disable)
895
Timothy Chen77758a62021-01-12 18:45:47 -0800896 // load_key should not be high if there is no ongoing operation
Timothy Chen38033242021-06-29 10:06:12 -0700897 `ASSERT(LoadKey_A, key_o.valid |-> op_start_i)
898
899 // The count value should always be 0 when a transaction start
900 `ASSERT(CntZero_A, $rose(op_start_i) |-> cnt == '0)
Timothy Chen77758a62021-01-12 18:45:47 -0800901
Timothy Chen8e374342021-08-25 20:55:31 -0700902 // Whenever a transaction completes, data_en must return to 0 on the next cycle
903 `ASSERT(DataEnDis_A, op_start_i & op_done_o |=> ~data_en_o)
904
905 // Whenever data enable asserts, it must be the case that there was a generate or
906 // id operation
907 `ASSERT(DataEn_A, data_en_o |-> (id_en_o | gen_en_o) & ~adv_en_o)
908
Timothy Chen15adeee2020-09-09 15:44:35 -0700909endmodule