次のように、一般的なマルチビット マルチプレクサを実装できます。
type data is array(natural range <>) of
std_ulogic_vector(data_width-1 downto 0);
--## Compute the integer result of the function ceil(log(n))
--# where b is the base
function ceil_log(n, b : positive) return natural is
variable log, residual : natural;
begin
residual := n - 1;
log := 0;
while residual > 0 loop
residual := residual / b;
log := log + 1;
end loop;
return log;
end function;
function mux_data(Inputs : data; Sel : unsigned)
return std_ulogic_vector is
alias inputs_asc : data(0 to Inputs'length-1) is Inputs;
variable pad_inputs : data(0 to (2 ** Sel'length) - 1);
variable result : std_ulogic_vector(inputs_asc(0)'range);
begin
assert inputs_asc'length <= 2 ** Sel'length
report "Inputs vector size: " & integer'image(Inputs'length)
& " is too big for the selection vector"
severity failure;
pad_inputs := (others => (others => '0'));
pad_inputs(inputs_asc'range) := inputs_asc;
result := pad_inputs(to_integer(Sel));
return result;
end function;
signal mux_in : data(0 to entries-1);
signal mux_out : std_ulogic_vector(data_width-1 downto 0);
signal mux_sel : unsigned(ceil_log(entries, 2)-1 downto 0);
...
mux_out <= mux_data(mux_in, mux_sel);
この関数は、2 のべき乗であり、エントリ数以上であることが保証されてmux_data
いる一時配列を作成することによって機能します。pad_inputs
入力をこの配列にコピーし、占有されていない位置をデフォルトで にコピーし(others => '0')
ます。その後、整数のインデックス付けを安全に使用して、選択した入力を引き出すことができます。エイリアスは、関数が非 0 ベースの配列を適切に処理できるようにするために存在します。
型data
は の制約のない配列として定義されていstd_ulogic_vector
ます。関数は、ジェネリックmux_data
を知る必要なく、任意のサイズに自動的に適応します。entries
この関数は、昇順の範囲配列が渡されることを前提として記述されています。降順の配列は引き続き機能しますが、選択されたインデックスは選択コントロールのバイナリ値と一致しません。unsigned
選択コントロールは、関数で必要なサイズになるように自動的に構成されますceil_log
。このようにして、ロジックは および の任意の値に適応しentries
ますdata_width
。そこに懐疑的な人にとって、これは合成されます。
(VHDL-2008 より前のバージョンでは) タイプのシグナルをdata
ポートに配置することはできません。これは、ジェネリックによって設定された制約を使用して宣言する必要があるためです。これを処理する標準的な方法は、入力を 1 次元配列にフラット化することです。
port (
mux_in_1d : std_ulogic_vector(entries*data_width-1 downto 0);
...
);
...
-- Expand the flattened array back into an array of arrays
process(mux_in_1d)
begin
for i in mux_in'range loop
mux_in(i) <= mux_in_1d((i+1)*data_width-1 downto i*data_width);
end loop;
end process;
VHDL-2008 では、完全に制約のない型data
を宣言してポートで使用できます。
-- Declare this in a package
type data is array(natural range <>) of std_ulogic_vector;
...
port (
mux_in : data(0 to entries-1)(data_width-1 downto 0);
...
);
...
-- Substitute this line in the mux_data function
variable pad_inputs : data(0 to (2 ** Sel'length) - 1)(inputs_asc(0)'range);