|
1 | | -import selector_pkg::*; |
| 1 | +pub function select_binary::<N: p32, T: type,> ( |
| 2 | + sel : input logic<selector_pkg::calc_binary_select_width(N)>, |
| 3 | + data: input T <N> , |
| 4 | +) -> T { |
| 5 | + return data[sel]; |
| 6 | +} |
2 | 7 |
|
3 | | -pub module mux #( |
4 | | - param WIDTH : u32 = 1 , |
5 | | - param DATA_TYPE : type = logic<WIDTH> , |
6 | | - param ENTRIES : u32 = 2 , |
7 | | - param KIND : selector_kind = selector_kind::BINARY , |
8 | | - const SELECT_WIDTH: u32 = calc_select_width(ENTRIES, KIND), |
9 | | -) ( |
10 | | - i_select: input logic <SELECT_WIDTH>, |
11 | | - i_data : input DATA_TYPE<ENTRIES> , |
12 | | - o_data : output DATA_TYPE , |
13 | | -) { |
14 | | - const BINARY_SELECT_WIDTH: u32 = calc_binary_select_width(ENTRIES); |
15 | | - const MAX_DEPTH : u32 = $clog2(ENTRIES); |
16 | | - |
17 | | - function binary_mux ( |
18 | | - select: input logic <BINARY_SELECT_WIDTH>, |
19 | | - data : input DATA_TYPE<ENTRIES> , |
20 | | - ) -> DATA_TYPE { |
21 | | - return data[select]; |
22 | | - } |
| 8 | +pub function select_vector::<N: p32, T: type,> ( |
| 9 | + sel : input logic<N>, |
| 10 | + data: input T <N>, |
| 11 | +) -> T { |
| 12 | + const DEPTH: u32 = $clog2(N); |
| 13 | + |
| 14 | + var current_n: u32 ; |
| 15 | + var current_s: logic<N>; |
| 16 | + var current_d: T <N>; |
| 17 | + var next_n : u32 ; |
| 18 | + var next_s : logic<N>; |
| 19 | + var next_d : T <N>; |
23 | 20 |
|
24 | | - function vector_mux ( |
25 | | - select: input logic <ENTRIES>, |
26 | | - data : input DATA_TYPE<ENTRIES>, |
27 | | - ) -> DATA_TYPE { |
28 | | - var current_n : u32 ; |
29 | | - var current_select: logic <ENTRIES>; |
30 | | - var current_data : DATA_TYPE<ENTRIES>; |
31 | | - var next_n : u32 ; |
32 | | - var next_select : logic <ENTRIES>; |
33 | | - var next_data : DATA_TYPE<ENTRIES>; |
34 | | - |
35 | | - next_n = ENTRIES; |
36 | | - next_select = select; |
37 | | - next_data = data; |
38 | | - for _i: u32 in 0..MAX_DEPTH { |
39 | | - current_n = next_n; |
40 | | - current_select = next_select; |
41 | | - current_data = next_data; |
42 | | - |
43 | | - next_n = (current_n / 2) + (current_n % 2); |
44 | | - for j: u32 in 0..next_n { |
45 | | - let select_even: logic = current_select[2 * j + 0] || ((j + 1) == next_n && (current_n % 2) == 1); |
46 | | - if select_even { |
47 | | - next_select[j] = current_select[2 * j + 0]; |
48 | | - next_data[j] = current_data[2 * j + 0]; |
49 | | - } else { |
50 | | - next_select[j] = current_select[2 * j + 1]; |
51 | | - next_data[j] = current_data[2 * j + 1]; |
52 | | - } |
| 21 | + next_n = N; |
| 22 | + next_s = sel; |
| 23 | + next_d = data; |
| 24 | + for _i: u32 in 0..DEPTH { |
| 25 | + current_n = next_n; |
| 26 | + current_s = next_s; |
| 27 | + current_d = next_d; |
| 28 | + |
| 29 | + next_n = (current_n / 2) + (current_n % 2); |
| 30 | + for j: u32 in 0..next_n { |
| 31 | + var select_even: logic; |
| 32 | + |
| 33 | + if (j + 1) == next_n && (current_n % 2) == 1 { |
| 34 | + select_even = true; |
| 35 | + } else { |
| 36 | + select_even = current_s[2 * j + 0]; |
53 | 37 | } |
54 | | - } |
55 | 38 |
|
56 | | - return next_data[0]; |
| 39 | + if select_even { |
| 40 | + next_s[j] = current_s[2 * j + 0]; |
| 41 | + next_d[j] = current_d[2 * j + 0]; |
| 42 | + } else { |
| 43 | + next_s[j] = current_s[2 * j + 1]; |
| 44 | + next_d[j] = current_d[2 * j + 1]; |
| 45 | + } |
| 46 | + } |
57 | 47 | } |
58 | 48 |
|
59 | | - function onehot_mux ( |
60 | | - select: input logic <ENTRIES>, |
61 | | - data : input DATA_TYPE<ENTRIES>, |
62 | | - ) -> DATA_TYPE { |
63 | | - var current_n : u32 ; |
64 | | - var current_data: DATA_TYPE<ENTRIES>; |
65 | | - var next_n : u32 ; |
66 | | - var next_data : DATA_TYPE<ENTRIES>; |
67 | | - |
68 | | - next_n = ENTRIES; |
69 | | - for i: u32 in 0..ENTRIES { |
70 | | - next_data[i] = {select[i] repeat $bits(DATA_TYPE)} & data[i]; |
| 49 | + return next_d[0]; |
| 50 | +} |
| 51 | + |
| 52 | +pub function select_onehot::<N: p32, T: type,> ( |
| 53 | + sel : input logic<N>, |
| 54 | + data: input T <N>, |
| 55 | +) -> T { |
| 56 | + const DEPTH: u32 = $clog2(N); |
| 57 | + |
| 58 | + var current_n: u32 ; |
| 59 | + var current_d: T <N>; |
| 60 | + var next_n : u32 ; |
| 61 | + var next_d : T <N>; |
| 62 | + |
| 63 | + next_n = N; |
| 64 | + for i: u32 in 0..N { |
| 65 | + if sel[i] { |
| 66 | + next_d[i] = data[i]; |
| 67 | + } else { |
| 68 | + next_d[i] = 0 as T; |
71 | 69 | } |
| 70 | + } |
| 71 | + |
| 72 | + for _i: u32 in 0..DEPTH { |
| 73 | + current_n = next_n; |
| 74 | + current_d = next_d; |
72 | 75 |
|
73 | | - for _i: u32 in 0..MAX_DEPTH { |
74 | | - current_n = next_n; |
75 | | - current_data = next_data; |
76 | | - |
77 | | - next_n = (current_n / 2) + (current_n % 2); |
78 | | - for j: u32 in 0..current_n { |
79 | | - if (j + 1) == next_n && ((current_n % 2) == 1) { |
80 | | - next_data[j] = current_data[2 * j + 0]; |
81 | | - } else { |
82 | | - next_data[j] = current_data[2 * j + 0] | current_data[2 * j + 1]; |
83 | | - } |
| 76 | + next_n = (current_n / 2) + (current_n % 2); |
| 77 | + for j: u32 in 0..next_n { |
| 78 | + if (j + 1) == next_n && (current_n % 2) == 1 { |
| 79 | + next_d[j] = current_d[2 * j + 0]; |
| 80 | + } else { |
| 81 | + next_d[j] = (current_d[2 * j + 0] | current_d[2 * j + 1]) as T; |
84 | 82 | } |
85 | 83 | } |
86 | | - |
87 | | - return next_data[0]; |
88 | 84 | } |
89 | 85 |
|
90 | | - if ENTRIES <= 1 :g_mux { |
91 | | - assign o_data = i_data[0]; |
92 | | - } else if KIND == selector_kind::BINARY { |
93 | | - assign o_data = binary_mux(i_select, i_data); |
94 | | - } else if KIND == selector_kind::VECTOR { |
95 | | - assign o_data = vector_mux(i_select, i_data); |
| 86 | + return next_d[0]; |
| 87 | +} |
| 88 | + |
| 89 | +pub function select::<KIND: selector_pkg::selector_kind, N: p32, T: type,> ( |
| 90 | + sel : input logic<selector_pkg::calc_select_width(N, KIND)>, |
| 91 | + data: input T <N> , |
| 92 | +) -> T { |
| 93 | + const BINARY_SEL_WIDTH: u32 = selector_pkg::calc_binary_select_width(N); |
| 94 | + |
| 95 | + if N == 1 { |
| 96 | + return data[0]; |
| 97 | + } else if KIND == selector_pkg::selector_kind::BINARY { |
| 98 | + return select_binary::<N, T>(sel as BINARY_SEL_WIDTH, data); |
| 99 | + } else if KIND == selector_pkg::selector_kind::VECTOR { |
| 100 | + return select_vector::<N, T>(sel as N, data); |
96 | 101 | } else { |
97 | | - assign o_data = onehot_mux(i_select, i_data); |
| 102 | + return select_onehot::<N, T>(sel as N, data); |
| 103 | + } |
| 104 | +} |
| 105 | + |
| 106 | +pub module mux #( |
| 107 | + param WIDTH : u32 = 1 , |
| 108 | + param DATA_TYPE : type = logic<WIDTH> , |
| 109 | + param ENTRIES : u32 = 2 , |
| 110 | + param KIND : selector_kind = selector_kind::BINARY , |
| 111 | + const SELECT_WIDTH: u32 = calc_select_width(ENTRIES, KIND), |
| 112 | +) ( |
| 113 | + i_select: input logic <SELECT_WIDTH>, |
| 114 | + i_data : input DATA_TYPE<ENTRIES> , |
| 115 | + o_data : output DATA_TYPE , |
| 116 | +) { |
| 117 | + import selector_pkg::*; |
| 118 | + |
| 119 | + always_comb { |
| 120 | + o_data = select::<KIND, ENTRIES, DATA_TYPE>(i_select, i_data); |
98 | 121 | } |
99 | 122 | } |
0 commit comments