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);
}
}