第5回: 組み合わせ論理回路のHDL記述(1)

前回の演習の続き

前回の演習を、一通り思い出して、 最後までやっておきましょう。 また以下に、いくつかの組み合わせ論理回路の記述の実例を、 VHDLの文法に関する説明とあわせて紹介しておきます。 すべての回路をシミュレーション・書き込みする必要はありませんが、 一通り目を通し、いくつかを選んでシミュレーション・書き込みをやってみてください。

自由設計の回路を今回のレポート課題とします。

組み合わせ論理回路のHDL記述

デコーダ

[p.62] 入力の2進数に対して、その数に対応する番号の出力のみを1とする 回路をデコーダと呼びます。 例えば入力aを3ビットとすれば、出力xは23=8本、つまりx(0)〜x(7)となり、 例えば入力aが001であれば、x(1)=1となります。 入力が3ビットのデコーダのVHDL記述を以下に示します。
library ieee;
use ieee.std_logic_1164.all;

entity dec is
  port (
    a: in std_logic_vector(2 downto 0);
    x: out std_logic_vector(7 downto 0)
  );
end dec;

architecture arch of dec is
begin
  process (a) begin
    case a is
      when "000"  => x <= "00000001";
      when "001"  => x <= "00000010";
      when "010"  => x <= "00000100";
      when "011"  => x <= "00001000";
      when "100"  => x <= "00010000";
      when "101"  => x <= "00100000";
      when "110"  => x <= "01000000";
      when "111"  => x <= "10000000";
      when others => x <= "XXXXXXXX";
    end case;
  end process;
end arch;
この中では、architecture記述の中で、プロセス文(process)[p.36]というものを 使っています。 このプロセス文は、非常によく使うものですので、ぜひ覚えておきましょう。 プロセス文は、カッコ内に書いた変数(センシティビティ・リスト、と呼ぶ)の 値が変化したときに、その中が実行されます。 このデコーダの場合は、出力xが変化するのは、変数aが変化したとき、ですから、 aをセンシティビティ・リストに入れてあります。

この場合に実行される内容は、aの値に応じて出力xの値を変える、 ということですので、それをcase文[p.43]を用いて記述しています。 VHDLのcase文はC言語などのcase文と似ていて、aの値がwhenで指定した値に 応じて、「=>」の右側の処理(値の代入)が行われます。 例えばa="001"の場合は、x(1)のみが1の、x="00000010"としています。 ちなみに、入力が"000"〜"111"の場合以外は、不定値である"X"を 代入しています。

このようにして入力が3ビットのデコーダは記述できるわけですが、 この調子でいけば、何ビットのデコーダでも、同じように記述できそうです。 これが、HDLを用いた論理回路設計の特徴といえます。 従来の論理回路の設計手法では、入力が3ビットのデコーダの論理回路図[p.63]を 設計したとしても、入力が4ビットのデコーダが必要になったら、 またゼロから作り直しになってしまいます。

エンコーダ

[p.64] 入力のうち、1の箇所を2進数の値として出力する回路を エンコーダ(プライオリティ・エンコーダ)と呼びます。 例えば、8ビットの入力aが、"00001000"であれば、右から4番目が1ですので、 出力は"100"となります。 この回路をVHDL記述すると次のようになります。
library ieee;
use ieee.std_logic_1164.all;

entity enc is
  port (
    a: in std_logic_vector(7 downto 0);
    x: out std_logic_vector(3 downto 0)
  );
end enc;

architecture arch of enc is
begin
  process (a) begin
    if     (a(0) = '1') then x <= "1000";
    elsif (a(1) = '1') then x <= "1001";
    elsif (a(2) = '1') then x <= "1010";
    elsif (a(3) = '1') then x <= "1011";
    elsif (a(4) = '1') then x <= "1100";
    elsif (a(5) = '1') then x <= "1101";
    elsif (a(6) = '1') then x <= "1110";
    elsif (a(7) = '1') then x <= "1111";
    else                     x <= "0000";
    end if;
  end process;
end arch;
この例では、プロセス文の中で、if文[p.42]を使って、出力の値を 決定しています。 具体的には、a(0)から順番に1があるかを探していき、 あったところでxを決定しています。

このエンコーダの論理回路図は[p.65]の図のようになりますが、 ビット数を変える場合でも、VHDL記述であれば楽チンですね。

セレクタ

[p.67] 複数の入力から、指定した1つのみを選んで出力に渡す回路を セレクタと呼びます。 4つの入力a, b, c, dから、2ビットの入力sで指定されたものを 出力xに渡す回路をVHDL記述したものを以下に示します。
library ieee;
use ieee.std_logic_1164.all;

entity sel is
  port (
    a, b, c, d: in std_logic;
    s: in std_logic_vector(1 downto 0);
    x: out std_logic
  );
end sel;

architecture arch of sel is
begin
  process (a, b, c, d, s) begin
    case s is
      when "00"   => x <= a;
      when "01"   => x <= b;
      when "10"   => x <= c;
      when "11"   => x <= d;
      when others => x <= 'X';
    end case;
  end process;
end arch;
case文が使われていますね。 ここでプロセス文のセンシティビティ・リストに、a, b, c, dに加えて sも入っていることに注意しておきましょう。 (その理由を考えておきましょう)

コンパレータ

[p.69] 2つの2進数の値のどちらが大きいか、あるいは等しいかを比較する回路を コンパレータと呼びます。 以下は、2つの8ビットの入力a, bのどちらが大きいかを比較し、 aの方が大きければgt(Greater Than)、 bの方が大きければlt(Less Than)、 aとbが等しければeqが1となるコンパレータをVHDLで記述したものです。
library ieee;
use ieee.std_logic_1164.all;

entity cmp is
  port (
    a, b: in std_logic_vector(7 downto 0);
    gt, lt, eq: out std_logic;
  );
end cmp;

architecture arch of cmp is
begin
  process (a, b) begin
    gt <= '0';
    lt <= '0';
    eq <= '0';
    if (a > b) then
      gt <= '1';
    elsif (a < b) then
      lt <= '1';
    else
      eq <= '1';
    end if
  end proess;
end arch;
この例では、まずgt, lt, eqを最初に0にしておき、 その後、該当するもののみを1にする、という処理を書いてあります。 この場合、プログラミング言語の場合は、gtなどの変数がまず0になり、 その後1になるわけですが、VHDLで記述しているのは回路ですので、 実際に、まずgtが0になったあとで1になる、ということは起こらず、 結果として(この場合はプロセス文が終わった時点で)gtの値が どうなっているか、だけが意味を持つことに注意しておきましょう。

レポート


戻る