blob: f4ad4929688f552fcaea7a23cfe0ec431ca19ac9 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
// Description: csrng ctr_drbg_update module
//
// implementation using security_strength = 256
module csrng_ctr_drbg_upd #(
parameter int Cmd = 3,
parameter int StateId = 4,
parameter int BlkLen = 128,
parameter int KeyLen = 256,
parameter int SeedLen = 384,
parameter int CtrLen = 32
) (
input logic clk_i,
input logic rst_ni,
// update interface
input logic ctr_drbg_upd_enable_i,
input logic ctr_drbg_upd_req_i,
output logic ctr_drbg_upd_rdy_o, // ready to process the req above
input logic [Cmd-1:0] ctr_drbg_upd_ccmd_i,
input logic [StateId-1:0] ctr_drbg_upd_inst_id_i, // instantance id
input logic [SeedLen-1:0] ctr_drbg_upd_pdata_i, // provided_data
input logic [KeyLen-1:0] ctr_drbg_upd_key_i,
input logic [BlkLen-1:0] ctr_drbg_upd_v_i,
output logic [Cmd-1:0] ctr_drbg_upd_ccmd_o,
output logic [StateId-1:0] ctr_drbg_upd_inst_id_o,
output logic [KeyLen-1:0] ctr_drbg_upd_key_o,
output logic [BlkLen-1:0] ctr_drbg_upd_v_o,
output logic ctr_drbg_upd_ack_o, // final ack when update process has been completed
input logic ctr_drbg_upd_rdy_i, // readu to process the ack above
// es_req/ack
input logic ctr_drbg_upd_es_req_i,
output logic ctr_drbg_upd_es_ack_o,
// block encrypt interface
output logic block_encrypt_req_o,
input logic block_encrypt_rdy_i,
output logic [Cmd-1:0] block_encrypt_ccmd_o,
output logic [StateId-1:0] block_encrypt_inst_id_o,
output logic [KeyLen-1:0] block_encrypt_key_o,
output logic [BlkLen-1:0] block_encrypt_v_o,
input logic block_encrypt_ack_i,
output logic block_encrypt_rdy_o,
input logic [Cmd-1:0] block_encrypt_ccmd_i,
input logic [StateId-1:0] block_encrypt_inst_id_i,
input logic [BlkLen-1:0] block_encrypt_v_i,
output logic ctr_drbg_upd_v_ctr_err_o,
output logic [2:0] ctr_drbg_upd_sfifo_updreq_err_o,
output logic [2:0] ctr_drbg_upd_sfifo_bencreq_err_o,
output logic [2:0] ctr_drbg_upd_sfifo_bencack_err_o,
output logic [2:0] ctr_drbg_upd_sfifo_pdata_err_o,
output logic [2:0] ctr_drbg_upd_sfifo_final_err_o,
output logic ctr_drbg_updbe_sm_err_o,
output logic ctr_drbg_updob_sm_err_o
);
localparam int UpdReqFifoDepth = 1;
localparam int UpdReqFifoWidth = KeyLen+BlkLen+SeedLen+StateId+Cmd;
localparam int BlkEncReqFifoDepth = 1;
localparam int BlkEncReqFifoWidth = KeyLen+BlkLen+StateId+Cmd;
localparam int BlkEncAckFifoDepth = 1;
localparam int BlkEncAckFifoWidth = BlkLen+StateId+Cmd;
localparam int PDataFifoDepth = 1;
localparam int PDataFifoWidth = SeedLen;
localparam int FinalFifoDepth = 1;
localparam int FinalFifoWidth = KeyLen+BlkLen+StateId+Cmd;
// signals
logic [SeedLen-1:0] updated_key_and_v;
logic [CtrLen-1:0] v_inc;
logic [BlkLen-1:0] v_first;
logic [BlkLen-1:0] v_sized;
// upd_req fifo
logic [UpdReqFifoWidth-1:0] sfifo_updreq_rdata;
logic sfifo_updreq_push;
logic [UpdReqFifoWidth-1:0] sfifo_updreq_wdata;
logic sfifo_updreq_pop;
logic sfifo_updreq_full;
logic sfifo_updreq_not_empty;
// breakout
logic [Cmd-1:0] sfifo_updreq_ccmd;
logic [StateId-1:0] sfifo_updreq_inst_id;
logic [SeedLen-1:0] sfifo_updreq_pdata;
logic [KeyLen-1:0] sfifo_updreq_key;
logic [BlkLen-1:0] sfifo_updreq_v;
// blk_encrypt_req fifo
logic [BlkEncReqFifoWidth-1:0] sfifo_bencreq_rdata;
logic sfifo_bencreq_push;
logic [BlkEncReqFifoWidth-1:0] sfifo_bencreq_wdata;
logic sfifo_bencreq_pop;
logic sfifo_bencreq_full;
logic sfifo_bencreq_not_empty;
// breakout
logic [Cmd-1:0] sfifo_bencreq_ccmd;
logic [StateId-1:0] sfifo_bencreq_inst_id;
logic [KeyLen-1:0] sfifo_bencreq_key;
logic [BlkLen-1:0] sfifo_bencreq_v;
// blk_encrypt_ack fifo
logic [BlkEncAckFifoWidth-1:0] sfifo_bencack_rdata;
logic sfifo_bencack_push;
logic [BlkEncAckFifoWidth-1:0] sfifo_bencack_wdata;
logic sfifo_bencack_pop;
logic sfifo_bencack_full;
logic sfifo_bencack_not_empty;
// breakout
logic [Cmd-1:0] sfifo_bencack_ccmd;
logic [StateId-1:0] sfifo_bencack_inst_id;
logic [BlkLen-1:0] sfifo_bencack_v;
// pdata_stage fifo
logic [PDataFifoWidth-1:0] sfifo_pdata_rdata;
logic sfifo_pdata_push;
logic [PDataFifoWidth-1:0] sfifo_pdata_wdata;
logic sfifo_pdata_pop;
logic sfifo_pdata_full;
logic sfifo_pdata_not_empty;
logic [SeedLen-1:0] sfifo_pdata_v;
// key_v fifo
logic [FinalFifoWidth-1:0] sfifo_final_rdata;
logic sfifo_final_push;
logic [FinalFifoWidth-1:0] sfifo_final_wdata;
logic sfifo_final_pop;
logic sfifo_final_full;
logic sfifo_final_not_empty;
// breakout
logic [Cmd-1:0] sfifo_final_ccmd;
logic [StateId-1:0] sfifo_final_inst_id;
logic [KeyLen-1:0] sfifo_final_key;
logic [BlkLen-1:0] sfifo_final_v;
logic v_ctr_load;
logic v_ctr_inc;
logic interate_ctr_done;
logic interate_ctr_inc;
logic concat_outblk_shift;
logic concat_ctr_done;
logic concat_ctr_inc;
logic [SeedLen+BlkLen-1:0] concat_outblk_shifted_value;
logic [CtrLen-1:0] v_ctr;
// flops
logic [1:0] interate_ctr_q, interate_ctr_d;
logic [1:0] concat_ctr_q, concat_ctr_d;
logic [SeedLen-1:0] concat_outblk_q, concat_outblk_d;
logic [Cmd-1:0] concat_ccmd_q, concat_ccmd_d;
logic [StateId-1:0] concat_inst_id_q, concat_inst_id_d;
// Encoding generated with:
// $ ./util/design/sparse-fsm-encode.py -d 3 -m 4 -n 5 \
// -s 47328894 --language=sv
//
// Hamming distance histogram:
//
// 0: --
// 1: --
// 2: --
// 3: |||||||||||||||||||| (66.67%)
// 4: |||||||||| (33.33%)
// 5: --
//
// Minimum Hamming distance: 3
// Maximum Hamming distance: 4
// Minimum Hamming weight: 2
// Maximum Hamming weight: 3
//
localparam int BlkEncStateWidth = 5;
typedef enum logic [BlkEncStateWidth-1:0] {
ReqIdle = 5'b11000,
ReqSend = 5'b10011,
ESHalt = 5'b01110,
BEError = 5'b00101
} blk_enc_state_e;
blk_enc_state_e blk_enc_state_d, blk_enc_state_q;
// SEC_CM: BLK_ENC.FSM.SPARSE
`PRIM_FLOP_SPARSE_FSM(u_blk_enc_state_regs, blk_enc_state_d,
blk_enc_state_q, blk_enc_state_e, ReqIdle)
// Encoding generated with:
// $ ./util/design/sparse-fsm-encode.py -d 3 -m 4 -n 6 \
// -s 400877681 --language=sv
//
// Hamming distance histogram:
//
// 0: --
// 1: --
// 2: --
// 3: |||||||||||||||||||| (66.67%)
// 4: ||||| (16.67%)
// 5: --
// 6: ||||| (16.67%)
//
// Minimum Hamming distance: 3
// Maximum Hamming distance: 6
// Minimum Hamming weight: 2
// Maximum Hamming weight: 4
//
localparam int OutBlkStateWidth = 6;
typedef enum logic [OutBlkStateWidth-1:0] {
AckIdle = 6'b110110,
Load = 6'b110001,
Shift = 6'b001001,
OBError = 6'b011100
} outblk_state_e;
outblk_state_e outblk_state_d, outblk_state_q;
// SEC_CM: OUTBLK.FSM.SPARSE
`PRIM_FLOP_SPARSE_FSM(u_outblk_state_regs, outblk_state_d,
outblk_state_q, outblk_state_e, AckIdle)
always_ff @(posedge clk_i or negedge rst_ni)
if (!rst_ni) begin
interate_ctr_q <= '0;
concat_ctr_q <= '0;
concat_outblk_q <= '0;
concat_ccmd_q <= '0;
concat_inst_id_q <= '0;
end else begin
interate_ctr_q <= interate_ctr_d;
concat_ctr_q <= concat_ctr_d;
concat_outblk_q <= concat_outblk_d;
concat_ccmd_q <= concat_ccmd_d;
concat_inst_id_q <= concat_inst_id_d;
end // else: !if(!rst_ni)
//--------------------------------------------
// input request fifo for staging update requests
//--------------------------------------------
prim_fifo_sync #(
.Width(UpdReqFifoWidth),
.Pass(0),
.Depth(UpdReqFifoDepth),
.OutputZeroIfEmpty(1'b0)
) u_prim_fifo_sync_updreq (
.clk_i (clk_i),
.rst_ni (rst_ni),
.clr_i (!ctr_drbg_upd_enable_i),
.wvalid_i (sfifo_updreq_push),
.wready_o (),
.wdata_i (sfifo_updreq_wdata),
.rvalid_o (sfifo_updreq_not_empty),
.rready_i (sfifo_updreq_pop),
.rdata_o (sfifo_updreq_rdata),
.full_o (sfifo_updreq_full),
.depth_o (),
.err_o ()
);
assign sfifo_updreq_push = !sfifo_updreq_full && ctr_drbg_upd_req_i;
assign sfifo_updreq_wdata = {ctr_drbg_upd_key_i,ctr_drbg_upd_v_i,ctr_drbg_upd_pdata_i,
ctr_drbg_upd_inst_id_i,ctr_drbg_upd_ccmd_i};
assign ctr_drbg_upd_rdy_o = !sfifo_updreq_full;
assign {sfifo_updreq_key,sfifo_updreq_v,sfifo_updreq_pdata,
sfifo_updreq_inst_id,sfifo_updreq_ccmd} = sfifo_updreq_rdata;
assign ctr_drbg_upd_sfifo_updreq_err_o =
{(sfifo_updreq_push && sfifo_updreq_full),
(sfifo_updreq_pop && !sfifo_updreq_not_empty),
(sfifo_updreq_full && !sfifo_updreq_not_empty)};
//--------------------------------------------
// prepare value for block_encrypt step
//--------------------------------------------
if (CtrLen < BlkLen) begin : g_ctrlen_sm
// for ctr_len < blocklen
assign v_inc = sfifo_updreq_v[CtrLen-1:0] + 1;
assign v_first = {sfifo_updreq_v[BlkLen-1:CtrLen],v_inc};
end else begin : g_ctrlen_lg
assign v_first = sfifo_updreq_v + 1;
end
// SEC_CM: DRBG_UPD.CTR.REDUN
prim_count #(
.Width(CtrLen)
) u_prim_count_ctr_drbg (
.clk_i,
.rst_ni,
.clr_i(!ctr_drbg_upd_enable_i),
.set_i(v_ctr_load),
.set_cnt_i(v_first[CtrLen-1:0]),
.incr_en_i(v_ctr_inc), // count up
.decr_en_i(1'b0),
.step_i(CtrLen'(1)),
.cnt_o(v_ctr),
.cnt_next_o(),
.err_o(ctr_drbg_upd_v_ctr_err_o)
);
assign v_sized = {v_first[BlkLen-1:CtrLen],v_ctr};
// interation counter
assign interate_ctr_d =
(!ctr_drbg_upd_enable_i) ? '0 :
interate_ctr_done ? '0 :
interate_ctr_inc ? (interate_ctr_q + 1) :
interate_ctr_q;
assign interate_ctr_done = (int'(interate_ctr_q) >= SeedLen/BlkLen);
//--------------------------------------------
// state machine to send values to block_encrypt
//--------------------------------------------
always_comb begin
blk_enc_state_d = blk_enc_state_q;
v_ctr_load = 1'b0;
v_ctr_inc = 1'b0;
interate_ctr_inc = 1'b0;
sfifo_pdata_push = 1'b0;
sfifo_bencreq_push = 1'b0;
sfifo_updreq_pop = 1'b0;
ctr_drbg_updbe_sm_err_o = 1'b0;
ctr_drbg_upd_es_ack_o = 1'b0;
unique case (blk_enc_state_q)
// ReqIdle: increment v this cycle, push in next
ReqIdle: begin
// Prioritize halt requests from entropy_src over disable, as CSRNG would otherwise starve
// those requests while it is idle.
if (ctr_drbg_upd_es_req_i) begin
blk_enc_state_d = ESHalt;
end else if (!ctr_drbg_upd_enable_i) begin
blk_enc_state_d = ReqIdle;
end else if (sfifo_updreq_not_empty && !sfifo_bencreq_full && !sfifo_pdata_full) begin
v_ctr_load = 1'b1;
sfifo_pdata_push = 1'b1;
blk_enc_state_d = ReqSend;
end
end
ReqSend: begin
if (!ctr_drbg_upd_enable_i) begin
blk_enc_state_d = ReqIdle;
end else if (!interate_ctr_done) begin
if (!sfifo_bencreq_full) begin
v_ctr_inc = 1'b1;
interate_ctr_inc = 1'b1;
sfifo_bencreq_push = 1'b1;
end
end else begin
sfifo_updreq_pop = 1'b1;
blk_enc_state_d = ReqIdle;
end
end
ESHalt: begin
ctr_drbg_upd_es_ack_o = 1'b1;
if (!ctr_drbg_upd_es_req_i) begin
blk_enc_state_d = ReqIdle;
end
end
BEError: begin
ctr_drbg_updbe_sm_err_o = 1'b1;
end
default: begin
blk_enc_state_d = BEError;
ctr_drbg_updbe_sm_err_o = 1'b1;
end
endcase // case (blk_enc_state_q)
end
//--------------------------------------------
// block_encrypt request fifo for staging aes requests
//--------------------------------------------
prim_fifo_sync #(
.Width(BlkEncReqFifoWidth),
.Pass(0),
.Depth(BlkEncReqFifoDepth),
.OutputZeroIfEmpty(1'b0)
) u_prim_fifo_sync_bencreq (
.clk_i (clk_i),
.rst_ni (rst_ni),
.clr_i (!ctr_drbg_upd_enable_i),
.wvalid_i (sfifo_bencreq_push),
.wready_o (),
.wdata_i (sfifo_bencreq_wdata),
.rvalid_o (sfifo_bencreq_not_empty),
.rready_i (sfifo_bencreq_pop),
.rdata_o (sfifo_bencreq_rdata),
.full_o (sfifo_bencreq_full),
.depth_o (),
.err_o ()
);
assign sfifo_bencreq_pop = block_encrypt_req_o && block_encrypt_rdy_i;
assign block_encrypt_req_o = sfifo_bencreq_not_empty;
assign sfifo_bencreq_wdata = {sfifo_updreq_key,v_sized,sfifo_updreq_inst_id,sfifo_updreq_ccmd};
assign {sfifo_bencreq_key,sfifo_bencreq_v,sfifo_bencreq_inst_id,
sfifo_bencreq_ccmd} = sfifo_bencreq_rdata;
// set outputs
assign block_encrypt_key_o = sfifo_bencreq_key;
assign block_encrypt_v_o = sfifo_bencreq_v;
assign block_encrypt_inst_id_o = sfifo_bencreq_inst_id;
assign block_encrypt_ccmd_o = sfifo_bencreq_ccmd;
assign ctr_drbg_upd_sfifo_bencreq_err_o =
{(sfifo_bencreq_push && sfifo_bencreq_full),
(sfifo_bencreq_pop && !sfifo_bencreq_not_empty),
(sfifo_bencreq_full && !sfifo_bencreq_not_empty)};
//--------------------------------------------
// block_encrypt response fifo from block encrypt
//--------------------------------------------
prim_fifo_sync #(
.Width(BlkEncAckFifoWidth),
.Pass(0),
.Depth(BlkEncAckFifoDepth),
.OutputZeroIfEmpty(1'b0)
) u_prim_fifo_sync_bencack (
.clk_i (clk_i),
.rst_ni (rst_ni),
.clr_i (!ctr_drbg_upd_enable_i),
.wvalid_i (sfifo_bencack_push),
.wready_o (),
.wdata_i (sfifo_bencack_wdata),
.rvalid_o (sfifo_bencack_not_empty),
.rready_i (sfifo_bencack_pop),
.rdata_o (sfifo_bencack_rdata),
.full_o (sfifo_bencack_full),
.depth_o (),
.err_o ()
);
assign sfifo_bencack_push = !sfifo_bencack_full && block_encrypt_ack_i;
assign sfifo_bencack_wdata = {block_encrypt_v_i,block_encrypt_inst_id_i,block_encrypt_ccmd_i};
assign block_encrypt_rdy_o = !sfifo_bencack_full;
assign {sfifo_bencack_v,sfifo_bencack_inst_id,sfifo_bencack_ccmd} = sfifo_bencack_rdata;
assign ctr_drbg_upd_sfifo_bencack_err_o =
{(sfifo_bencack_push && sfifo_bencack_full),
(sfifo_bencack_pop && !sfifo_bencack_not_empty),
(sfifo_bencack_full && !sfifo_bencack_not_empty)};
//--------------------------------------------
// fifo to stage provided_data, waiting for blk_encrypt to ack
//--------------------------------------------
prim_fifo_sync #(
.Width(PDataFifoWidth),
.Pass(0),
.Depth(PDataFifoDepth),
.OutputZeroIfEmpty(1'b0)
) u_prim_fifo_sync_pdata (
.clk_i (clk_i),
.rst_ni (rst_ni),
.clr_i (!ctr_drbg_upd_enable_i),
.wvalid_i (sfifo_pdata_push),
.wready_o (),
.wdata_i (sfifo_pdata_wdata),
.rvalid_o (sfifo_pdata_not_empty),
.rready_i (sfifo_pdata_pop),
.rdata_o (sfifo_pdata_rdata),
.full_o (sfifo_pdata_full),
.depth_o (),
.err_o ()
);
assign sfifo_pdata_wdata = sfifo_updreq_pdata;
assign sfifo_pdata_v = sfifo_pdata_rdata;
assign ctr_drbg_upd_sfifo_pdata_err_o =
{(sfifo_pdata_push && sfifo_pdata_full),
(sfifo_pdata_pop && !sfifo_pdata_not_empty),
(sfifo_pdata_full && !sfifo_pdata_not_empty)};
//--------------------------------------------
// shifting logic to receive values from block_encrypt
//--------------------------------------------
assign concat_outblk_shifted_value = {concat_outblk_q, {BlkLen{1'b0}}};
assign concat_outblk_d =
(!ctr_drbg_upd_enable_i) ? '0 :
sfifo_bencack_pop ? {concat_outblk_q[SeedLen-1:BlkLen],sfifo_bencack_v} :
concat_outblk_shift ? concat_outblk_shifted_value[SeedLen-1:0] :
concat_outblk_q;
// The following signal is used to avoid possible lint errors.
logic [BlkLen-1:0] unused_concat_outblk_shifted_value;
assign unused_concat_outblk_shifted_value = concat_outblk_shifted_value[SeedLen+BlkLen-1:SeedLen];
// concatination counter
assign concat_ctr_d =
(!ctr_drbg_upd_enable_i) ? '0 :
concat_ctr_done ? '0 :
concat_ctr_inc ? (concat_ctr_q + 1) :
concat_ctr_q;
assign concat_ctr_done = (int'(concat_ctr_q) >= (SeedLen/BlkLen));
assign concat_inst_id_d =
(!ctr_drbg_upd_enable_i) ? '0 :
sfifo_bencack_pop ? sfifo_bencack_inst_id :
concat_inst_id_q;
assign concat_ccmd_d =
(!ctr_drbg_upd_enable_i) ? '0 :
sfifo_bencack_pop ? sfifo_bencack_ccmd :
concat_ccmd_q;
//--------------------------------------------
// state machine to receive values from block_encrypt
//--------------------------------------------
always_comb begin
outblk_state_d = outblk_state_q;
concat_ctr_inc = 1'b0;
concat_outblk_shift = 1'b0;
sfifo_pdata_pop = 1'b0;
sfifo_bencack_pop = 1'b0;
sfifo_final_push = 1'b0;
ctr_drbg_updob_sm_err_o = 1'b0;
unique case (outblk_state_q)
// AckIdle: increment v this cycle, push in next
AckIdle: begin
if (!ctr_drbg_upd_enable_i) begin
outblk_state_d = AckIdle;
end else if (sfifo_bencack_not_empty && sfifo_pdata_not_empty && !sfifo_final_full) begin
outblk_state_d = Load;
end
end
Load: begin
if (!ctr_drbg_upd_enable_i) begin
outblk_state_d = AckIdle;
end else if (sfifo_bencack_not_empty) begin
concat_ctr_inc = 1'b1;
sfifo_bencack_pop = 1'b1;
outblk_state_d = Shift;
end
end
Shift: begin
if (!ctr_drbg_upd_enable_i) begin
outblk_state_d = AckIdle;
end else if (concat_ctr_done) begin
sfifo_pdata_pop = 1'b1;
sfifo_final_push = 1'b1;
outblk_state_d = AckIdle;
end else begin
concat_outblk_shift = 1'b1;
outblk_state_d = Load;
end
end
OBError: begin
ctr_drbg_updob_sm_err_o = 1'b1;
end
default: begin
outblk_state_d = OBError;
ctr_drbg_updob_sm_err_o = 1'b1;
end
endcase
end
//--------------------------------------------
// final update processing
//--------------------------------------------
// XOR the additional data with the new key and value from block encryption
assign updated_key_and_v = concat_outblk_q ^ sfifo_pdata_v;
prim_fifo_sync #(
.Width(FinalFifoWidth),
.Pass(0),
.Depth(FinalFifoDepth),
.OutputZeroIfEmpty(1'b0)
) u_prim_fifo_sync_final (
.clk_i (clk_i),
.rst_ni (rst_ni),
.clr_i (!ctr_drbg_upd_enable_i),
.wvalid_i (sfifo_final_push),
.wready_o (),
.wdata_i (sfifo_final_wdata),
.rvalid_o (sfifo_final_not_empty),
.rready_i (sfifo_final_pop),
.rdata_o (sfifo_final_rdata),
.full_o (sfifo_final_full),
.depth_o (),
.err_o ()
);
assign sfifo_final_wdata = {updated_key_and_v,concat_inst_id_q,concat_ccmd_q};
assign {sfifo_final_key,sfifo_final_v,sfifo_final_inst_id,sfifo_final_ccmd} = sfifo_final_rdata;
assign sfifo_final_pop = ctr_drbg_upd_rdy_i && sfifo_final_not_empty;
assign ctr_drbg_upd_ack_o = sfifo_final_pop;
assign ctr_drbg_upd_ccmd_o = sfifo_final_ccmd;
assign ctr_drbg_upd_inst_id_o = sfifo_final_inst_id;
assign ctr_drbg_upd_key_o = sfifo_final_key;
assign ctr_drbg_upd_v_o = sfifo_final_v;
assign ctr_drbg_upd_sfifo_final_err_o =
{(sfifo_final_push && sfifo_final_full),
(sfifo_final_pop && !sfifo_final_not_empty),
(sfifo_final_full && !sfifo_final_not_empty)};
// Make sure that the two state machines have a stable error state. This means that after the
// error state is entered it will not exit it unless a reset signal is received.
`ASSERT(CsrngDrbgUpdBlkEncErrorStStable_A,
blk_enc_state_q == BEError |=> $stable(blk_enc_state_q))
`ASSERT(CsrngDrbgUpdOutBlkErrorStStable_A,
outblk_state_q == OBError |=> $stable(outblk_state_q))
// If in error state, the error output must be high.
`ASSERT(CsrngDrbgUpdBlkEncErrorOutput_A, blk_enc_state_q == BEError |-> ctr_drbg_updbe_sm_err_o)
`ASSERT(CsrngDrbgUpdOutBlkErrorOutput_A, outblk_state_q == OBError |-> ctr_drbg_updob_sm_err_o)
endmodule