-
-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
22cb6d6
commit 00bbdb9
Showing
4 changed files
with
341 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
}; | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
}}} |