[prim_mubi_pkg] Add a generic multibit type and associated functions
Signed-off-by: Michael Schaffner <msf@google.com>
diff --git a/hw/ip/prim/data/prim_mubi_pkg.sv.tpl b/hw/ip/prim/data/prim_mubi_pkg.sv.tpl
new file mode 100644
index 0000000..b3977d3
--- /dev/null
+++ b/hw/ip/prim/data/prim_mubi_pkg.sv.tpl
@@ -0,0 +1,158 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// ------------------- W A R N I N G: A U T O - G E N E R A T E D C O D E !! -------------------//
+// PLEASE DO NOT HAND-EDIT THIS FILE. IT HAS BEEN AUTO-GENERATED WITH THE FOLLOWING COMMAND:
+//
+// hw/ip/prim/util/generate_prim_mubi_pkg.py hw/ip/prim/data/prim_mubi_pkg.sv.tpl >
+// hw/ip/prim/rtl/prim_mubi_pkg.sv
+//
+// This package defines common multibit signal types, active high and active low values and
+// the corresponding functions to test whether the values are set or not.
+
+package prim_mubi_pkg;
+
+% for n in range(1, n_max_nibbles + 1):
+<%
+ nbits = n * 4
+ hi_val = ''
+ lo_val = ''
+ for k in range(1,n+1):
+ hi_val = ('5' if (k % 2) else 'A') + hi_val
+ lo_val = ('A' if (k % 2) else '5') + lo_val
+%>\
+ //////////////////////////////////////////////
+ // ${nbits} Bit Multibit Type and Functions //
+ //////////////////////////////////////////////
+
+ parameter int MuBi${nbits}Width = ${nbits};
+ typedef enum logic [MuBi${nbits}Width-1:0] {
+ MuBi${nbits}Hi = ${nbits}'h${hi_val}, // enabled
+ MuBi${nbits}Lo = ${nbits}'h${lo_val} // disabled
+ } mubi${nbits}_e;
+
+ // make a typedef such that this can be used as an intersignal type as well
+ typedef mubi${nbits}_e mubi${nbits}_t;
+
+ // Return the multibit value to signal "enabled".
+ function automatic mubi${nbits}_e mubi${nbits}_hi_value();
+ return MuBi${nbits}Hi;
+ endfunction : mubi${nbits}_hi_value
+
+ // Return the multibit value to signal "disabled".
+ function automatic mubi${nbits}_e mubi${nbits}_lo_value();
+ return MuBi${nbits}Lo;
+ endfunction : mubi${nbits}_lo_value
+
+ // Test whether the multibit value signals an "enabled" condition.
+ // The strict version of this function requires
+ // the multibit value to equal Hi.
+ function automatic logic mubi${nbits}_tst_hi_strict(mubi${nbits}_e val);
+ return MuBi${nbits}Hi == val;
+ endfunction : mubi${nbits}_tst_hi_strict
+
+ // Test whether the multibit value signals a "disabled" condition.
+ // The strict version of this function requires
+ // the multibit value to equal Lo.
+ function automatic logic mubi${nbits}_tst_lo_strict(mubi${nbits}_e val);
+ return MuBi${nbits}Lo == val;
+ endfunction : mubi${nbits}_tst_lo_strict
+
+ // Test whether the multibit value signals an "enabled" condition.
+ // The loose version of this function interprets all
+ // values other than Lo as "enabled".
+ function automatic logic mubi${nbits}_tst_hi_loose(mubi${nbits}_e val);
+ return MuBi${nbits}Lo != val;
+ endfunction : mubi${nbits}_tst_hi_loose
+
+ // Test whether the multibit value signals a "disabled" condition.
+ // The loose version of this function interprets all
+ // values other than Hi as "disabled".
+ function automatic logic mubi${nbits}_tst_lo_loose(mubi${nbits}_e val);
+ return MuBi${nbits}Hi != val;
+ endfunction : mubi${nbits}_tst_lo_loose
+
+
+ // Performs a logical OR operation between two multibit values.
+ // This treats "act" as logical 1, and all other values are
+ // treated as 0. Truth table:
+ //
+ // A | B | OUT
+ //------+------+-----
+ // !act | !act | !act
+ // act | !act | act
+ // !act | act | act
+ // act | act | act
+ //
+ function automatic mubi${nbits}_e mubi${nbits}_or(mubi${nbits}_e a, mubi${nbits}_e b, mubi${nbits}_e act);
+ logic [MuBi${nbits}Width-1:0] a_in, b_in, act_in, out;
+ a_in = a;
+ b_in = b;
+ act_in = act;
+ for (int k = 0; k < MuBi${nbits}Width; k++) begin
+ if (act_in[k]) begin
+ out[k] = a_in[k] || b_in[k];
+ end else begin
+ out[k] = a_in[k] && b_in[k];
+ end
+ end
+ return mubi${nbits}_e'(out);
+ endfunction : mubi${nbits}_or
+
+ // Performs a logical AND operation between two multibit values.
+ // This treats "act" as logical 1, and all other values are
+ // treated as 0. Truth table:
+ //
+ // A | B | OUT
+ //------+------+-----
+ // !act | !act | !act
+ // act | !act | !act
+ // !act | act | !act
+ // act | act | act
+ //
+ function automatic mubi${nbits}_e mubi${nbits}_and(mubi${nbits}_e a, mubi${nbits}_e b, mubi${nbits}_e act);
+ logic [MuBi${nbits}Width-1:0] a_in, b_in, act_in, out;
+ a_in = a;
+ b_in = b;
+ act_in = act;
+ for (int k = 0; k < MuBi${nbits}Width; k++) begin
+ if (act_in[k]) begin
+ out[k] = a_in[k] && b_in[k];
+ end else begin
+ out[k] = a_in[k] || b_in[k];
+ end
+ end
+ return mubi${nbits}_e'(out);
+ endfunction : mubi${nbits}_and
+
+ // Performs a logical OR operation between two multibit values.
+ // This treats "Hi" as logical 1, and all other values are
+ // treated as 0.
+ function automatic mubi${nbits}_e mubi${nbits}_or_hi(mubi${nbits}_e a, mubi${nbits}_e b);
+ return mubi${nbits}_or(a, b, MuBi${nbits}Hi);
+ endfunction : mubi${nbits}_or_hi
+
+ // Performs a logical AND operation between two multibit values.
+ // This treats "Hi" as logical 1, and all other values are
+ // treated as 0.
+ function automatic mubi${nbits}_e mubi${nbits}_and_hi(mubi${nbits}_e a, mubi${nbits}_e b);
+ return mubi${nbits}_and(a, b, MuBi${nbits}Hi);
+ endfunction : mubi${nbits}_and_hi
+
+ // Performs a logical OR operation between two multibit values.
+ // This treats "Lo" as logical 1, and all other values are
+ // treated as 0.
+ function automatic mubi${nbits}_e mubi${nbits}_or_lo(mubi${nbits}_e a, mubi${nbits}_e b);
+ return mubi${nbits}_or(a, b, MuBi${nbits}Lo);
+ endfunction : mubi${nbits}_or_lo
+
+ // Performs a logical AND operation between two multibit values.
+ // Tlos treats "Lo" as logical 1, and all other values are
+ // treated as 0.
+ function automatic mubi${nbits}_e mubi${nbits}_and_lo(mubi${nbits}_e a, mubi${nbits}_e b);
+ return mubi${nbits}_and(a, b, MuBi${nbits}Lo);
+ endfunction : mubi${nbits}_and_lo
+
+% endfor
+endpackage : prim_mubi_pkg
diff --git a/hw/ip/prim/prim_mubi.core b/hw/ip/prim/prim_mubi.core
new file mode 100644
index 0000000..f400a3e
--- /dev/null
+++ b/hw/ip/prim/prim_mubi.core
@@ -0,0 +1,17 @@
+CAPI=2:
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+
+name: "lowrisc:prim:mubi:0.1"
+description: "Multibit types and functions"
+filesets:
+ files_rtl:
+ files:
+ - rtl/prim_mubi_pkg.sv
+ file_type: systemVerilogSource
+
+targets:
+ default:
+ filesets:
+ - files_rtl
diff --git a/hw/ip/prim/rtl/prim_mubi_pkg.sv b/hw/ip/prim/rtl/prim_mubi_pkg.sv
new file mode 100644
index 0000000..62cdb18
--- /dev/null
+++ b/hw/ip/prim/rtl/prim_mubi_pkg.sv
@@ -0,0 +1,545 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// ------------------- W A R N I N G: A U T O - G E N E R A T E D C O D E !! -------------------//
+// PLEASE DO NOT HAND-EDIT THIS FILE. IT HAS BEEN AUTO-GENERATED WITH THE FOLLOWING COMMAND:
+//
+// hw/ip/prim/util/generate_prim_mubi_pkg.py hw/ip/prim/data/prim_mubi_pkg.sv.tpl >
+// hw/ip/prim/rtl/prim_mubi_pkg.sv
+//
+// This package defines common multibit signal types, active high and active low values and
+// the corresponding functions to test whether the values are set or not.
+
+package prim_mubi_pkg;
+
+ //////////////////////////////////////////////
+ // 4 Bit Multibit Type and Functions //
+ //////////////////////////////////////////////
+
+ parameter int MuBi4Width = 4;
+ typedef enum logic [MuBi4Width-1:0] {
+ MuBi4Hi = 4'h5, // enabled
+ MuBi4Lo = 4'hA // disabled
+ } mubi4_e;
+
+ // make a typedef such that this can be used as an intersignal type as well
+ typedef mubi4_e mubi4_t;
+
+ // Return the multibit value to signal "enabled".
+ function automatic mubi4_e mubi4_hi_value();
+ return MuBi4Hi;
+ endfunction : mubi4_hi_value
+
+ // Return the multibit value to signal "disabled".
+ function automatic mubi4_e mubi4_lo_value();
+ return MuBi4Lo;
+ endfunction : mubi4_lo_value
+
+ // Test whether the multibit value signals an "enabled" condition.
+ // The strict version of this function requires
+ // the multibit value to equal Hi.
+ function automatic logic mubi4_tst_hi_strict(mubi4_e val);
+ return MuBi4Hi == val;
+ endfunction : mubi4_tst_hi_strict
+
+ // Test whether the multibit value signals a "disabled" condition.
+ // The strict version of this function requires
+ // the multibit value to equal Lo.
+ function automatic logic mubi4_tst_lo_strict(mubi4_e val);
+ return MuBi4Lo == val;
+ endfunction : mubi4_tst_lo_strict
+
+ // Test whether the multibit value signals an "enabled" condition.
+ // The loose version of this function interprets all
+ // values other than Lo as "enabled".
+ function automatic logic mubi4_tst_hi_loose(mubi4_e val);
+ return MuBi4Lo != val;
+ endfunction : mubi4_tst_hi_loose
+
+ // Test whether the multibit value signals a "disabled" condition.
+ // The loose version of this function interprets all
+ // values other than Hi as "disabled".
+ function automatic logic mubi4_tst_lo_loose(mubi4_e val);
+ return MuBi4Hi != val;
+ endfunction : mubi4_tst_lo_loose
+
+
+ // Performs a logical OR operation between two multibit values.
+ // This treats "act" as logical 1, and all other values are
+ // treated as 0. Truth table:
+ //
+ // A | B | OUT
+ //------+------+-----
+ // !act | !act | !act
+ // act | !act | act
+ // !act | act | act
+ // act | act | act
+ //
+ function automatic mubi4_e mubi4_or(mubi4_e a, mubi4_e b, mubi4_e act);
+ logic [MuBi4Width-1:0] a_in, b_in, act_in, out;
+ a_in = a;
+ b_in = b;
+ act_in = act;
+ for (int k = 0; k < MuBi4Width; k++) begin
+ if (act_in[k]) begin
+ out[k] = a_in[k] || b_in[k];
+ end else begin
+ out[k] = a_in[k] && b_in[k];
+ end
+ end
+ return mubi4_e'(out);
+ endfunction : mubi4_or
+
+ // Performs a logical AND operation between two multibit values.
+ // This treats "act" as logical 1, and all other values are
+ // treated as 0. Truth table:
+ //
+ // A | B | OUT
+ //------+------+-----
+ // !act | !act | !act
+ // act | !act | !act
+ // !act | act | !act
+ // act | act | act
+ //
+ function automatic mubi4_e mubi4_and(mubi4_e a, mubi4_e b, mubi4_e act);
+ logic [MuBi4Width-1:0] a_in, b_in, act_in, out;
+ a_in = a;
+ b_in = b;
+ act_in = act;
+ for (int k = 0; k < MuBi4Width; k++) begin
+ if (act_in[k]) begin
+ out[k] = a_in[k] && b_in[k];
+ end else begin
+ out[k] = a_in[k] || b_in[k];
+ end
+ end
+ return mubi4_e'(out);
+ endfunction : mubi4_and
+
+ // Performs a logical OR operation between two multibit values.
+ // This treats "Hi" as logical 1, and all other values are
+ // treated as 0.
+ function automatic mubi4_e mubi4_or_hi(mubi4_e a, mubi4_e b);
+ return mubi4_or(a, b, MuBi4Hi);
+ endfunction : mubi4_or_hi
+
+ // Performs a logical AND operation between two multibit values.
+ // This treats "Hi" as logical 1, and all other values are
+ // treated as 0.
+ function automatic mubi4_e mubi4_and_hi(mubi4_e a, mubi4_e b);
+ return mubi4_and(a, b, MuBi4Hi);
+ endfunction : mubi4_and_hi
+
+ // Performs a logical OR operation between two multibit values.
+ // This treats "Lo" as logical 1, and all other values are
+ // treated as 0.
+ function automatic mubi4_e mubi4_or_lo(mubi4_e a, mubi4_e b);
+ return mubi4_or(a, b, MuBi4Lo);
+ endfunction : mubi4_or_lo
+
+ // Performs a logical AND operation between two multibit values.
+ // Tlos treats "Lo" as logical 1, and all other values are
+ // treated as 0.
+ function automatic mubi4_e mubi4_and_lo(mubi4_e a, mubi4_e b);
+ return mubi4_and(a, b, MuBi4Lo);
+ endfunction : mubi4_and_lo
+
+ //////////////////////////////////////////////
+ // 8 Bit Multibit Type and Functions //
+ //////////////////////////////////////////////
+
+ parameter int MuBi8Width = 8;
+ typedef enum logic [MuBi8Width-1:0] {
+ MuBi8Hi = 8'hA5, // enabled
+ MuBi8Lo = 8'h5A // disabled
+ } mubi8_e;
+
+ // make a typedef such that this can be used as an intersignal type as well
+ typedef mubi8_e mubi8_t;
+
+ // Return the multibit value to signal "enabled".
+ function automatic mubi8_e mubi8_hi_value();
+ return MuBi8Hi;
+ endfunction : mubi8_hi_value
+
+ // Return the multibit value to signal "disabled".
+ function automatic mubi8_e mubi8_lo_value();
+ return MuBi8Lo;
+ endfunction : mubi8_lo_value
+
+ // Test whether the multibit value signals an "enabled" condition.
+ // The strict version of this function requires
+ // the multibit value to equal Hi.
+ function automatic logic mubi8_tst_hi_strict(mubi8_e val);
+ return MuBi8Hi == val;
+ endfunction : mubi8_tst_hi_strict
+
+ // Test whether the multibit value signals a "disabled" condition.
+ // The strict version of this function requires
+ // the multibit value to equal Lo.
+ function automatic logic mubi8_tst_lo_strict(mubi8_e val);
+ return MuBi8Lo == val;
+ endfunction : mubi8_tst_lo_strict
+
+ // Test whether the multibit value signals an "enabled" condition.
+ // The loose version of this function interprets all
+ // values other than Lo as "enabled".
+ function automatic logic mubi8_tst_hi_loose(mubi8_e val);
+ return MuBi8Lo != val;
+ endfunction : mubi8_tst_hi_loose
+
+ // Test whether the multibit value signals a "disabled" condition.
+ // The loose version of this function interprets all
+ // values other than Hi as "disabled".
+ function automatic logic mubi8_tst_lo_loose(mubi8_e val);
+ return MuBi8Hi != val;
+ endfunction : mubi8_tst_lo_loose
+
+
+ // Performs a logical OR operation between two multibit values.
+ // This treats "act" as logical 1, and all other values are
+ // treated as 0. Truth table:
+ //
+ // A | B | OUT
+ //------+------+-----
+ // !act | !act | !act
+ // act | !act | act
+ // !act | act | act
+ // act | act | act
+ //
+ function automatic mubi8_e mubi8_or(mubi8_e a, mubi8_e b, mubi8_e act);
+ logic [MuBi8Width-1:0] a_in, b_in, act_in, out;
+ a_in = a;
+ b_in = b;
+ act_in = act;
+ for (int k = 0; k < MuBi8Width; k++) begin
+ if (act_in[k]) begin
+ out[k] = a_in[k] || b_in[k];
+ end else begin
+ out[k] = a_in[k] && b_in[k];
+ end
+ end
+ return mubi8_e'(out);
+ endfunction : mubi8_or
+
+ // Performs a logical AND operation between two multibit values.
+ // This treats "act" as logical 1, and all other values are
+ // treated as 0. Truth table:
+ //
+ // A | B | OUT
+ //------+------+-----
+ // !act | !act | !act
+ // act | !act | !act
+ // !act | act | !act
+ // act | act | act
+ //
+ function automatic mubi8_e mubi8_and(mubi8_e a, mubi8_e b, mubi8_e act);
+ logic [MuBi8Width-1:0] a_in, b_in, act_in, out;
+ a_in = a;
+ b_in = b;
+ act_in = act;
+ for (int k = 0; k < MuBi8Width; k++) begin
+ if (act_in[k]) begin
+ out[k] = a_in[k] && b_in[k];
+ end else begin
+ out[k] = a_in[k] || b_in[k];
+ end
+ end
+ return mubi8_e'(out);
+ endfunction : mubi8_and
+
+ // Performs a logical OR operation between two multibit values.
+ // This treats "Hi" as logical 1, and all other values are
+ // treated as 0.
+ function automatic mubi8_e mubi8_or_hi(mubi8_e a, mubi8_e b);
+ return mubi8_or(a, b, MuBi8Hi);
+ endfunction : mubi8_or_hi
+
+ // Performs a logical AND operation between two multibit values.
+ // This treats "Hi" as logical 1, and all other values are
+ // treated as 0.
+ function automatic mubi8_e mubi8_and_hi(mubi8_e a, mubi8_e b);
+ return mubi8_and(a, b, MuBi8Hi);
+ endfunction : mubi8_and_hi
+
+ // Performs a logical OR operation between two multibit values.
+ // This treats "Lo" as logical 1, and all other values are
+ // treated as 0.
+ function automatic mubi8_e mubi8_or_lo(mubi8_e a, mubi8_e b);
+ return mubi8_or(a, b, MuBi8Lo);
+ endfunction : mubi8_or_lo
+
+ // Performs a logical AND operation between two multibit values.
+ // Tlos treats "Lo" as logical 1, and all other values are
+ // treated as 0.
+ function automatic mubi8_e mubi8_and_lo(mubi8_e a, mubi8_e b);
+ return mubi8_and(a, b, MuBi8Lo);
+ endfunction : mubi8_and_lo
+
+ //////////////////////////////////////////////
+ // 12 Bit Multibit Type and Functions //
+ //////////////////////////////////////////////
+
+ parameter int MuBi12Width = 12;
+ typedef enum logic [MuBi12Width-1:0] {
+ MuBi12Hi = 12'h5A5, // enabled
+ MuBi12Lo = 12'hA5A // disabled
+ } mubi12_e;
+
+ // make a typedef such that this can be used as an intersignal type as well
+ typedef mubi12_e mubi12_t;
+
+ // Return the multibit value to signal "enabled".
+ function automatic mubi12_e mubi12_hi_value();
+ return MuBi12Hi;
+ endfunction : mubi12_hi_value
+
+ // Return the multibit value to signal "disabled".
+ function automatic mubi12_e mubi12_lo_value();
+ return MuBi12Lo;
+ endfunction : mubi12_lo_value
+
+ // Test whether the multibit value signals an "enabled" condition.
+ // The strict version of this function requires
+ // the multibit value to equal Hi.
+ function automatic logic mubi12_tst_hi_strict(mubi12_e val);
+ return MuBi12Hi == val;
+ endfunction : mubi12_tst_hi_strict
+
+ // Test whether the multibit value signals a "disabled" condition.
+ // The strict version of this function requires
+ // the multibit value to equal Lo.
+ function automatic logic mubi12_tst_lo_strict(mubi12_e val);
+ return MuBi12Lo == val;
+ endfunction : mubi12_tst_lo_strict
+
+ // Test whether the multibit value signals an "enabled" condition.
+ // The loose version of this function interprets all
+ // values other than Lo as "enabled".
+ function automatic logic mubi12_tst_hi_loose(mubi12_e val);
+ return MuBi12Lo != val;
+ endfunction : mubi12_tst_hi_loose
+
+ // Test whether the multibit value signals a "disabled" condition.
+ // The loose version of this function interprets all
+ // values other than Hi as "disabled".
+ function automatic logic mubi12_tst_lo_loose(mubi12_e val);
+ return MuBi12Hi != val;
+ endfunction : mubi12_tst_lo_loose
+
+
+ // Performs a logical OR operation between two multibit values.
+ // This treats "act" as logical 1, and all other values are
+ // treated as 0. Truth table:
+ //
+ // A | B | OUT
+ //------+------+-----
+ // !act | !act | !act
+ // act | !act | act
+ // !act | act | act
+ // act | act | act
+ //
+ function automatic mubi12_e mubi12_or(mubi12_e a, mubi12_e b, mubi12_e act);
+ logic [MuBi12Width-1:0] a_in, b_in, act_in, out;
+ a_in = a;
+ b_in = b;
+ act_in = act;
+ for (int k = 0; k < MuBi12Width; k++) begin
+ if (act_in[k]) begin
+ out[k] = a_in[k] || b_in[k];
+ end else begin
+ out[k] = a_in[k] && b_in[k];
+ end
+ end
+ return mubi12_e'(out);
+ endfunction : mubi12_or
+
+ // Performs a logical AND operation between two multibit values.
+ // This treats "act" as logical 1, and all other values are
+ // treated as 0. Truth table:
+ //
+ // A | B | OUT
+ //------+------+-----
+ // !act | !act | !act
+ // act | !act | !act
+ // !act | act | !act
+ // act | act | act
+ //
+ function automatic mubi12_e mubi12_and(mubi12_e a, mubi12_e b, mubi12_e act);
+ logic [MuBi12Width-1:0] a_in, b_in, act_in, out;
+ a_in = a;
+ b_in = b;
+ act_in = act;
+ for (int k = 0; k < MuBi12Width; k++) begin
+ if (act_in[k]) begin
+ out[k] = a_in[k] && b_in[k];
+ end else begin
+ out[k] = a_in[k] || b_in[k];
+ end
+ end
+ return mubi12_e'(out);
+ endfunction : mubi12_and
+
+ // Performs a logical OR operation between two multibit values.
+ // This treats "Hi" as logical 1, and all other values are
+ // treated as 0.
+ function automatic mubi12_e mubi12_or_hi(mubi12_e a, mubi12_e b);
+ return mubi12_or(a, b, MuBi12Hi);
+ endfunction : mubi12_or_hi
+
+ // Performs a logical AND operation between two multibit values.
+ // This treats "Hi" as logical 1, and all other values are
+ // treated as 0.
+ function automatic mubi12_e mubi12_and_hi(mubi12_e a, mubi12_e b);
+ return mubi12_and(a, b, MuBi12Hi);
+ endfunction : mubi12_and_hi
+
+ // Performs a logical OR operation between two multibit values.
+ // This treats "Lo" as logical 1, and all other values are
+ // treated as 0.
+ function automatic mubi12_e mubi12_or_lo(mubi12_e a, mubi12_e b);
+ return mubi12_or(a, b, MuBi12Lo);
+ endfunction : mubi12_or_lo
+
+ // Performs a logical AND operation between two multibit values.
+ // Tlos treats "Lo" as logical 1, and all other values are
+ // treated as 0.
+ function automatic mubi12_e mubi12_and_lo(mubi12_e a, mubi12_e b);
+ return mubi12_and(a, b, MuBi12Lo);
+ endfunction : mubi12_and_lo
+
+ //////////////////////////////////////////////
+ // 16 Bit Multibit Type and Functions //
+ //////////////////////////////////////////////
+
+ parameter int MuBi16Width = 16;
+ typedef enum logic [MuBi16Width-1:0] {
+ MuBi16Hi = 16'hA5A5, // enabled
+ MuBi16Lo = 16'h5A5A // disabled
+ } mubi16_e;
+
+ // make a typedef such that this can be used as an intersignal type as well
+ typedef mubi16_e mubi16_t;
+
+ // Return the multibit value to signal "enabled".
+ function automatic mubi16_e mubi16_hi_value();
+ return MuBi16Hi;
+ endfunction : mubi16_hi_value
+
+ // Return the multibit value to signal "disabled".
+ function automatic mubi16_e mubi16_lo_value();
+ return MuBi16Lo;
+ endfunction : mubi16_lo_value
+
+ // Test whether the multibit value signals an "enabled" condition.
+ // The strict version of this function requires
+ // the multibit value to equal Hi.
+ function automatic logic mubi16_tst_hi_strict(mubi16_e val);
+ return MuBi16Hi == val;
+ endfunction : mubi16_tst_hi_strict
+
+ // Test whether the multibit value signals a "disabled" condition.
+ // The strict version of this function requires
+ // the multibit value to equal Lo.
+ function automatic logic mubi16_tst_lo_strict(mubi16_e val);
+ return MuBi16Lo == val;
+ endfunction : mubi16_tst_lo_strict
+
+ // Test whether the multibit value signals an "enabled" condition.
+ // The loose version of this function interprets all
+ // values other than Lo as "enabled".
+ function automatic logic mubi16_tst_hi_loose(mubi16_e val);
+ return MuBi16Lo != val;
+ endfunction : mubi16_tst_hi_loose
+
+ // Test whether the multibit value signals a "disabled" condition.
+ // The loose version of this function interprets all
+ // values other than Hi as "disabled".
+ function automatic logic mubi16_tst_lo_loose(mubi16_e val);
+ return MuBi16Hi != val;
+ endfunction : mubi16_tst_lo_loose
+
+
+ // Performs a logical OR operation between two multibit values.
+ // This treats "act" as logical 1, and all other values are
+ // treated as 0. Truth table:
+ //
+ // A | B | OUT
+ //------+------+-----
+ // !act | !act | !act
+ // act | !act | act
+ // !act | act | act
+ // act | act | act
+ //
+ function automatic mubi16_e mubi16_or(mubi16_e a, mubi16_e b, mubi16_e act);
+ logic [MuBi16Width-1:0] a_in, b_in, act_in, out;
+ a_in = a;
+ b_in = b;
+ act_in = act;
+ for (int k = 0; k < MuBi16Width; k++) begin
+ if (act_in[k]) begin
+ out[k] = a_in[k] || b_in[k];
+ end else begin
+ out[k] = a_in[k] && b_in[k];
+ end
+ end
+ return mubi16_e'(out);
+ endfunction : mubi16_or
+
+ // Performs a logical AND operation between two multibit values.
+ // This treats "act" as logical 1, and all other values are
+ // treated as 0. Truth table:
+ //
+ // A | B | OUT
+ //------+------+-----
+ // !act | !act | !act
+ // act | !act | !act
+ // !act | act | !act
+ // act | act | act
+ //
+ function automatic mubi16_e mubi16_and(mubi16_e a, mubi16_e b, mubi16_e act);
+ logic [MuBi16Width-1:0] a_in, b_in, act_in, out;
+ a_in = a;
+ b_in = b;
+ act_in = act;
+ for (int k = 0; k < MuBi16Width; k++) begin
+ if (act_in[k]) begin
+ out[k] = a_in[k] && b_in[k];
+ end else begin
+ out[k] = a_in[k] || b_in[k];
+ end
+ end
+ return mubi16_e'(out);
+ endfunction : mubi16_and
+
+ // Performs a logical OR operation between two multibit values.
+ // This treats "Hi" as logical 1, and all other values are
+ // treated as 0.
+ function automatic mubi16_e mubi16_or_hi(mubi16_e a, mubi16_e b);
+ return mubi16_or(a, b, MuBi16Hi);
+ endfunction : mubi16_or_hi
+
+ // Performs a logical AND operation between two multibit values.
+ // This treats "Hi" as logical 1, and all other values are
+ // treated as 0.
+ function automatic mubi16_e mubi16_and_hi(mubi16_e a, mubi16_e b);
+ return mubi16_and(a, b, MuBi16Hi);
+ endfunction : mubi16_and_hi
+
+ // Performs a logical OR operation between two multibit values.
+ // This treats "Lo" as logical 1, and all other values are
+ // treated as 0.
+ function automatic mubi16_e mubi16_or_lo(mubi16_e a, mubi16_e b);
+ return mubi16_or(a, b, MuBi16Lo);
+ endfunction : mubi16_or_lo
+
+ // Performs a logical AND operation between two multibit values.
+ // Tlos treats "Lo" as logical 1, and all other values are
+ // treated as 0.
+ function automatic mubi16_e mubi16_and_lo(mubi16_e a, mubi16_e b);
+ return mubi16_and(a, b, MuBi16Lo);
+ endfunction : mubi16_and_lo
+
+endpackage : prim_mubi_pkg
+
diff --git a/hw/ip/prim/util/generate_prim_mubi_pkg.py b/hw/ip/prim/util/generate_prim_mubi_pkg.py
new file mode 100755
index 0000000..705cac0
--- /dev/null
+++ b/hw/ip/prim/util/generate_prim_mubi_pkg.py
@@ -0,0 +1,41 @@
+#!/usr/bin/env python3
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+r"""Convert mako template to Hjson register description
+"""
+import argparse
+import sys
+from io import StringIO
+
+from mako.template import Template
+
+
+def main():
+ parser = argparse.ArgumentParser(prog="generate_prim_mubi_pkg")
+ parser.add_argument('input',
+ nargs='?',
+ metavar='file',
+ type=argparse.FileType('r'),
+ default=sys.stdin,
+ help='input template file')
+ parser.add_argument('--n_max_nibbles',
+ type=int,
+ help='The script will create all multibit types with 1 to n_max_nibbles.',
+ default=4)
+
+ args = parser.parse_args()
+
+ # Determine output: if stdin then stdout if not then ??
+ out = StringIO()
+
+ reg_tpl = Template(args.input.read())
+ out.write(reg_tpl.render(n_max_nibbles=args.n_max_nibbles))
+
+ print(out.getvalue())
+
+ out.close()
+
+
+if __name__ == "__main__":
+ main()