blob: eb91a3f8c9c7fb486b76c4f19494c87025073682 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
// AES mux selector buffer and checker
//
// When using sparse encodings for mux selector signals, this module can be used to:
// 1. Prevent aggressive synthesis optimizations on the selector signal, and
// 2. to check that the selector signal is valid, i.e., doesn't take on invalid values.
// Whenever the selector signal takes on an invalid value, an error is signaled.
`include "prim_assert.sv"
module aes_sel_buf_chk #(
parameter int Num = 2,
parameter int Width = 1,
parameter bit EnSecBuf = 1'b0
) (
input logic clk_i, // Used for assertions only.
input logic rst_ni, // Used for assertions only.
input logic [Width-1:0] sel_i,
output logic [Width-1:0] sel_o,
output logic err_o
);
import aes_pkg::*;
// Tie off unused inputs.
logic unused_clk;
logic unused_rst;
assign unused_clk = clk_i;
assign unused_rst = rst_ni;
////////////
// Buffer //
////////////
if (EnSecBuf) begin : gen_sec_buf
prim_sec_anchor_buf #(
.Width ( Width )
) u_prim_buf_sel_i (
.in_i ( sel_i ),
.out_o ( sel_o )
);
end else begin : gen_buf
prim_buf #(
.Width ( Width )
) u_prim_buf_sel_i (
.in_i ( sel_i ),
.out_o ( sel_o )
);
end
/////////////
// Checker //
/////////////
if (Num == 2) begin : gen_mux2_sel_chk
// Cast to generic type.
mux2_sel_e sel_chk;
assign sel_chk = mux2_sel_e'(sel_o);
// Actual checker
always_comb begin : mux2_sel_chk
unique case (sel_chk)
MUX2_SEL_0,
MUX2_SEL_1: err_o = 1'b0;
default: err_o = 1'b1;
endcase
end
// Assertion
`ASSERT(AesMux2SelValid, !err_o |-> sel_chk inside {
MUX2_SEL_0,
MUX2_SEL_1
})
end else if (Num == 3) begin : gen_mux3_sel_chk
// Cast to generic type.
mux3_sel_e sel_chk;
assign sel_chk = mux3_sel_e'(sel_o);
// Actual checker
always_comb begin : mux3_sel_chk
unique case (sel_chk)
MUX3_SEL_0,
MUX3_SEL_1,
MUX3_SEL_2: err_o = 1'b0;
default: err_o = 1'b1;
endcase
end
// Assertion
`ASSERT(AesMux3SelValid, !err_o |-> sel_chk inside {
MUX3_SEL_0,
MUX3_SEL_1,
MUX3_SEL_2
})
end else if (Num == 4) begin : gen_mux4_sel_chk
// Cast to generic type.
mux4_sel_e sel_chk;
assign sel_chk = mux4_sel_e'(sel_o);
// Actual checker
always_comb begin : mux4_sel_chk
unique case (sel_chk)
MUX4_SEL_0,
MUX4_SEL_1,
MUX4_SEL_2,
MUX4_SEL_3: err_o = 1'b0;
default: err_o = 1'b1;
endcase
end
// Assertion
`ASSERT(AesMux4SelValid, !err_o |-> sel_chk inside {
MUX4_SEL_0,
MUX4_SEL_1,
MUX4_SEL_2,
MUX4_SEL_3
})
end else if (Num == 6) begin : gen_mux6_sel_chk
// Cast to generic type.
mux6_sel_e sel_chk;
assign sel_chk = mux6_sel_e'(sel_o);
// Actual checker
always_comb begin : mux6_sel_chk
unique case (sel_chk)
MUX6_SEL_0,
MUX6_SEL_1,
MUX6_SEL_2,
MUX6_SEL_3,
MUX6_SEL_4,
MUX6_SEL_5: err_o = 1'b0;
default: err_o = 1'b1;
endcase
end
// Assertion
`ASSERT(AesMux6SelValid, !err_o |-> sel_chk inside {
MUX6_SEL_0,
MUX6_SEL_1,
MUX6_SEL_2,
MUX6_SEL_3,
MUX6_SEL_4,
MUX6_SEL_5
})
end else begin : gen_width_unsupported
// Selected width not supported, signal error.
assign err_o = 1'b1;
end
////////////////
// Assertions //
////////////////
// We only have generic sparse encodings defined for certain mux input numbers (see aes_pkg.sv).
`ASSERT_INIT(AesSelBufChkNum, Num inside {2, 3, 4, 6})
endmodule