veryl-std 0.20.3

A modern hardware description language
Documentation
pub function select_binary::<N: p32, T: type> (
    sel : input logic<selector_pkg::calc_binary_select_width(N)>,
    data: input T    <N>                                        ,
) -> T {
    return data[sel];
}

pub function select_vector::<N: p32, T: type> (
    sel : input logic<N>,
    data: input T    <N>,
) -> T {
    const DEPTH: u32 = $clog2(N);

    var current_n: u32     ;
    var current_s: logic<N>;
    var current_d: T    <N>;
    var next_n   : u32     ;
    var next_s   : logic<N>;
    var next_d   : T    <N>;

    next_n = N;
    next_s = sel;
    next_d = data;
    for _i in 0..DEPTH {
        current_n = next_n;
        current_s = next_s;
        current_d = next_d;

        next_n = (current_n / 2) + (current_n % 2);
        for j in 0..next_n {
            var select_even: logic;

            if (j + 1) == next_n && (current_n % 2) == 1 {
                select_even = true;
            } else {
                select_even = current_s[2 * j + 0];
            }

            if select_even {
                next_s[j] = current_s[2 * j + 0];
                next_d[j] = current_d[2 * j + 0];
            } else {
                next_s[j] = current_s[2 * j + 1];
                next_d[j] = current_d[2 * j + 1];
            }
        }
    }

    return next_d[0];
}

pub function select_onehot::<N: p32, T: type> (
    sel : input logic<N>,
    data: input T    <N>,
) -> T {
    const DEPTH: u32 = $clog2(N);

    var current_n: u32   ;
    var current_d: T  <N>;
    var next_n   : u32   ;
    var next_d   : T  <N>;

    next_n = N;
    for i in 0..N {
        if sel[i] {
            next_d[i] = data[i];
        } else {
            next_d[i] = 0 as T;
        }
    }

    for _i in 0..DEPTH {
        current_n = next_n;
        current_d = next_d;

        next_n = (current_n / 2) + (current_n % 2);
        for j in 0..next_n {
            if (j + 1) == next_n && (current_n % 2) == 1 {
                next_d[j] = current_d[2 * j + 0];
            } else {
                next_d[j] = (current_d[2 * j + 0] | current_d[2 * j + 1]) as T;
            }
        }
    }

    return next_d[0];
}

pub function select::<KIND: selector_pkg::selector_kind, N: p32, T: type> (
    sel : input logic<selector_pkg::calc_select_width(N, KIND)>,
    data: input T    <N>                                       ,
) -> T {
    const BINARY_SEL_WIDTH: u32 = selector_pkg::calc_binary_select_width(N);

    if N == 1 {
        return data[0];
    } else if KIND == selector_pkg::selector_kind::BINARY {
        return select_binary::<N, T>(sel as BINARY_SEL_WIDTH, data);
    } else if KIND == selector_pkg::selector_kind::VECTOR {
        return select_vector::<N, T>(sel as N, data);
    } else {
        return select_onehot::<N, T>(sel as N, data);
    }
}

pub module mux #(
    param WIDTH       : u32           = 1                               ,
    param DATA_TYPE   : type          = logic<WIDTH>                    ,
    param ENTRIES     : u32           = 2                               ,
    param KIND        : selector_kind = selector_kind::BINARY           ,
    const SELECT_WIDTH: u32           = calc_select_width(ENTRIES, KIND),
) (
    i_select: input  logic    <SELECT_WIDTH>,
    i_data  : input  DATA_TYPE<ENTRIES>     ,
    o_data  : output DATA_TYPE              ,
) {
    import selector_pkg::*;

    always_comb {
        o_data = select::<KIND, ENTRIES, DATA_TYPE>(i_select, i_data);
    }
}