3

汎用マルチプレクサを作成したいと考えています。つまり、可変数の入力と可変 data_width を持つことができます。これは、データ入力を宣言するために、次のような配列が必要であることを意味します。

type data is array(entries-1 downto 0) of std_logic_vector(data_width-1 downto 0);

しかし、どうすればこれを達成できるかわかりません。入力ポート宣言で使用する必要があるため、タイプ「データ」をどこで宣言する必要があるかについて混乱しています

4

3 に答える 3

4

次のように、一般的なマルチビット マルチプレクサを実装できます。

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);
于 2014-05-17T16:12:59.220 に答える
0

組み合わせマルチプレクサ操作のみで、データの特別な型がない場合は、次のような関数が便利な場合があります。

function mux(constant ENTRIES : natural;
                      sel     : std_logic_vector;
                      data    : std_logic_vector)  -- Data for sel = 0 at left position
  return std_logic_vector is
  constant DATA_WIDTH   : natural := data'length / ENTRIES;
  alias    data_norm    : std_logic_vector(0 to data'length - 1) is data;
  type     data_split_t is array (0 to ENTRIES - 1) of std_logic_vector(0 to DATA_WIDTH - 1);
  variable data_split_v : data_split_t;
  variable res_v        : std_logic_vector(0 to DATA_WIDTH - 1);
begin
  for i in 0 to ENTRIES - 1 loop
    data_split_v(i) := data(i * DATA_WIDTH to (i + 1) * DATA_WIDTH - 1);
  end loop;
  res_v := data_split_v(to_integer(unsigned(sel)));
  return res_v;
end function;

dataDATA_WIDTH は、指定されたエントリの数に基づいて、全長から導出されます。

使用するために、関数は次のように同時関数呼び出しとして呼び出すことができます。

dut_out <= mux(ENTRIES,
               dut_sel,
               dut_in_0 &
               dut_in_1 &
               dut_in_2);
于 2014-05-17T10:37:54.010 に答える