Skip to content

Commit

Permalink
add selector modules to std library
Browse files Browse the repository at this point in the history
  • Loading branch information
taichi-ishitani committed Dec 16, 2024
1 parent 69464ff commit 1848f46
Show file tree
Hide file tree
Showing 4 changed files with 341 additions and 0 deletions.
36 changes: 36 additions & 0 deletions crates/std/veryl/src/selector/demux.veryl
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import selector_pkg::*;

pub module demux #(
param WIDTH : u32 = 1 ,
param DATA_TYPE : type = logic<WIDTH> ,
param DEFUALT_DATA: u32 = 0 as DATA_TYPE ,
param ENTRIES : u32 = 2 ,
param KIND : selector_kind = selector_kind::BINARY ,
param SELECT_WIDTH: u32 = calc_select_width(ENTRIES, KIND),
) (
i_select: input logic <SELECT_WIDTH>,
i_data : input DATA_TYPE ,
o_data : output DATA_TYPE<ENTRIES> ,
) {
if KIND == selector_kind::BINARY :g_demux {
always_comb {
for i: u32 in 0..ENTRIES {
o_data[i] = if i_select == i as SELECT_WIDTH {
i_data
} else {
DEFUALT_DATA
};
}
}
} else {
always_comb {
for i: u32 in 0..ENTRIES {
o_data[i] = if i_select[i] {
i_data
} else {
DEFUALT_DATA
};
}
}
}
}
99 changes: 99 additions & 0 deletions crates/std/veryl/src/selector/mux.veryl
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import selector_pkg::*;

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 ,
) {
const BINARY_SELECT_WIDTH: u32 = calc_binary_select_width(ENTRIES);
const MAX_DEPTH : u32 = $clog2(ENTRIES);

function binary_mux (
select: input logic <BINARY_SELECT_WIDTH>,
data : input DATA_TYPE<ENTRIES> ,
) -> DATA_TYPE {
return data[select];
}

function vector_mux (
select: input logic <ENTRIES>,
data : input DATA_TYPE<ENTRIES>,
) -> DATA_TYPE {
var current_n : u32 ;
var current_select: logic <ENTRIES>;
var current_data : DATA_TYPE<ENTRIES>;
var next_n : u32 ;
var next_select : logic <ENTRIES>;
var next_data : DATA_TYPE<ENTRIES>;

next_n = ENTRIES;
next_select = select;
next_data = data;
for _i: u32 in 0..MAX_DEPTH {
current_n = next_n;
current_select = next_select;
current_data = next_data;

next_n = (current_n / 2) + (current_n % 2);
for j: u32 in 0..next_n {
let select_even: logic = current_select[2 * j + 0] || ((j + 1) == next_n && (current_n % 2) == 1);
if select_even {
next_select[j] = current_select[2 * j + 0];
next_data[j] = current_data[2 * j + 0];
} else {
next_select[j] = current_select[2 * j + 1];
next_data[j] = current_data[2 * j + 1];
}
}
}

return next_data[0];
}

function onehot_mux (
select: input logic <ENTRIES>,
data : input DATA_TYPE<ENTRIES>,
) -> DATA_TYPE {
var current_n : u32 ;
var current_data: DATA_TYPE<ENTRIES>;
var next_n : u32 ;
var next_data : DATA_TYPE<ENTRIES>;

next_n = ENTRIES;
for i: u32 in 0..ENTRIES {
next_data[i] = {select[i] repeat $bits(DATA_TYPE)} & data[i];
}

for _i: u32 in 0..MAX_DEPTH {
current_n = next_n;
current_data = next_data;

next_n = (current_n / 2) + (current_n % 2);
for j: u32 in 0..current_n {
if (j + 1) == next_n && ((current_n % 2) == 1) {
next_data[j] = current_data[2 * j + 0];
} else {
next_data[j] = current_data[2 * j + 0] | current_data[2 * j + 1];
}
}
}

return next_data[0];
}

if ENTRIES <= 1 :g_mux {
assign o_data = i_data[0];
} else if KIND == selector_kind::BINARY {
assign o_data = binary_mux(i_select, i_data);
} else if KIND == selector_kind::VECTOR {
assign o_data = vector_mux(i_select, i_data);
} else {
assign o_data = onehot_mux(i_select, i_data);
}
}
28 changes: 28 additions & 0 deletions crates/std/veryl/src/selector/selector_pkg.veryl
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
pub package selector_pkg {
enum selector_kind {
BINARY,
VECTOR,
ONEHOT,
}

function calc_binary_select_width (
entries: input u32,
) -> u32 {
return if entries >= 2 {
$clog2(entries)
} else {
1
};
}

function calc_select_width (
entries: input u32 ,
kind : input selector_kind,
) -> u32 {
if kind == selector_kind::BINARY {
return calc_binary_select_width(entries);
} else {
return entries;
}
}
}
178 changes: 178 additions & 0 deletions crates/std/veryl/src/selector/test_selector.veryl
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
#[test(test_binary_mux)]
embed (inline) sv{{{
module test_binary_mux;
import std_selector_pkg::*;

logic [3:0] select;
logic [15:0][3:0] input_data;
logic [3:0] mux_data;
logic [15:0][3:0] output_data;

std_mux #(
.WIDTH (4 ),
.ENTRIES (16 ),
.KIND (selector_kind_BINARY )
) u_mux (
.i_select (select ),
.i_data (input_data ),
.o_data (mux_data )
);

std_demux #(
.WIDTH (4 ),
.ENTRIES (16 ),
.KIND (selector_kind_BINARY )
) u_demux (
.i_select (select ),
.i_data (mux_data ),
.o_data (output_data )
);

initial begin
for (int i = 0;i < 16;++i) begin
input_data[i] = i;
end

for (int i = 0;i < 16;++i) begin
select = i;
#1;
for (int j = 0;j < 16;++j) begin
logic [3:0] expected_data;

if (j == i) begin
expected_data = input_data[j];
end else begin
expected_data = 0;
end

assert (output_data[j] == expected_data)
else $error("output_data[%0d]: %h expected_data: %h", j, output_data[j], expected_data);
end
end

$finish;
end
endmodule
}}}

#[test(test_binary_vector)]
embed (inline) sv{{{
module test_vector_mux;
import std_selector_pkg::*;

logic [15:0] select_mux;
logic [15:0] select_demux;
logic [15:0][3:0] input_data;
logic [3:0] mux_data;
logic [15:0][3:0] output_data;

std_mux #(
.WIDTH (4 ),
.ENTRIES (16 ),
.KIND (selector_kind_VECTOR )
) u_mux (
.i_select (select_mux ),
.i_data (input_data ),
.o_data (mux_data )
);

std_demux #(
.WIDTH (4 ),
.ENTRIES (16 ),
.KIND (selector_kind_VECTOR )
) u_demux (
.i_select (select_demux ),
.i_data (mux_data ),
.o_data (output_data )
);

initial begin
for (int i = 0;i < 16;++i) begin
input_data[i] = i;
end

select_mux = '1;
for (int i = 0;i < 16;++i) begin
select_demux = '0;
select_demux[i] = '1;

#1;
for (int j = 0;j < 16;++j) begin
logic [3:0] expected_data;

if (j == i) begin
expected_data = input_data[j];
end else begin
expected_data = 0;
end

assert (output_data[j] == expected_data)
else $error("output_data[%0d]: %h expected_data: %h", j, output_data[j], expected_data);
end

select_mux[i] = '0;
end

$finish;
end
endmodule
}}}

#[test(test_onehot_mux)]
embed (inline) sv{{{
module test_onehot_mux;
import std_selector_pkg::*;

logic [15:0] select;
logic [15:0][3:0] input_data;
logic [3:0] mux_data;
logic [15:0][3:0] output_data;

std_mux #(
.WIDTH (4 ),
.ENTRIES (16 ),
.KIND (selector_kind_ONEHOT )
) u_mux (
.i_select (select ),
.i_data (input_data ),
.o_data (mux_data )
);

std_demux #(
.WIDTH (4 ),
.ENTRIES (16 ),
.KIND (selector_kind_ONEHOT )
) u_demux (
.i_select (select ),
.i_data (mux_data ),
.o_data (output_data )
);

initial begin
for (int i = 0;i < 16;++i) begin
input_data[i] = i;
end

for (int i = 0;i < 16;++i) begin
select = '0;
select[i] = '1;

#1;
for (int j = 0;j < 16;++j) begin
logic [3:0] expected_data;

if (j == i) begin
expected_data = input_data[j];
end else begin
expected_data = 0;
end

assert (output_data[j] == expected_data)
else $error("output_data[%0d]: %h expected_data: %h", j, output_data[j], expected_data);
end
end

$finish;
end
endmodule
}}}

0 comments on commit 1848f46

Please sign in to comment.