002回
簡単な論理回路・1

key word :
AND , OR , Ex-OR , NOT , Half-Adder , Full-Adder
下位モジュールとの接続方法(順番・名前) 7セグメントデコーダー


001の方では大まかな構成を書いたので、今回は論理回路の記述を。


・AND
VHDL 記述 真理値表 記号

architecture RTL of add is
 signal a : std_logic;
 signal b : std_logic;
 signal c : std_logic_vector (1 downto 0);
 signal z : std_logic;
 signal z2 : std_logic;
 begin
  z <= a and b;
  z2 <= a and c(0);

end RTL
abz
000
010
100
111



ぱっと見ただけでもverilogより堅そうなイメージ。




・OR
VHDL 記述 真理値表 記号


architecture RTL of or is
 signal a : std_logic;
 signal b : std_logic;
 signal z : std_logic;
 begin
  z <= a or b;

end RTL
abz
000
011
101
111



OR。それ以上でもそれ以下でもない。



・Ex-OR
VHDL 記述 真理値表 記号

architecture RTL of xor is
 signal a : std_logic;
 signal b : std_logic;
 signal z : std_logic;
 begin
  z <= a xor b;

end RTL
abz
000
011
101
110



あんまり使わないから、久しぶりに使うときどっちが1だったか忘れてしまったり。



・Not
VHDL 記述 真理値表 記号


architecture RTL of not is
 signal a : std_logic;
 signal z : std_logic;
 begin
  z <= not a;

end RTL
az
01
10



否定。



とりあえず最低限の記述はこんなもんです。
一応、これは内部の信号を使った場合の記述です。
以降は、外部信号を利用した場合がメインになると思われます。



・半加算器 Half-Adder
VHDL 記述 真理値表 記号

entity ten_counter is
 port (
    a : in std_logic;
    b : in std_logic;
    z : out std_logic;
    c : out std_logic
);
end ten_counter;

architecture RTL of hadd is

 begin
  z <= a xor b;
  c <= a and b;

end RTL

xyzc
0000
0110
1010
1101



半加算。
入力した2つの値を加算し、その出力と桁上がり分を出力

真理値表を見ての通り、桁上がり無しの出力zはEx-ORの値。
桁上がりの分はANDの値。




・全加算器 Full-Adder
VHDL 記述 内容

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;

entity hadd is
 port (
    a : in std_logic;
    b : in std_logic;
    z : out std_logic;
    c : out std_logic
);
end hadd;

architecture RTL of hadd is

 begin
  z <= a xor b;
  c <= a and b;

end RTL





library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;

entity fadd is
 port (
    a : in std_logic;
    b : in std_logic;
    cin : in std_logic;
    zout : out std_logic;
    cout : out std_logic
);
end fadd;

architecture RTL of fadd is
component ten_counter
 port (
    a : in std_logic;
    b : in std_logic;
    z : out std_logic;
    c : out std_logic
);
end domponent

 begin

 hadd1:
  hadd port map
   (
    a,
    b,
    z1,
    c1
);

 hadd2:
  hadd port map
   (
    a => a,
    b => cin,
    z => zout1,
    c => c2
);

  cout <= c1 xor c2;

end RTL
全加算。
半加算器の入力に、桁上がり分を追加

Haを組み合わせて記述。

VHDL記述の上部に記述してあるのhaddがモジュール名で、作った各.vhdファイルの最初に定めたentity名と同じ。 別のファイルで作ってある。
一応、同一のファイル内に記述して後で呼び出してもRTLシミュでは動くが、 ゲートシミュで使うツールでは駄目な場合があるのでモジュール毎に分けるのが吉

下部でのhadd1,hadd2は、インスタンス名で、このモジュール内で使用する際の個別の名前
functionが回路内部に記述するのに対し、外部にある回路といったイメージである。

hadd1では、ポートリスト順による接続をしており、モジュールhaddに記述されている順に値が代入される。
使用する値が少なく、構造も簡単な場合は手間がかからず楽であるが、
信号数が増え、接続が複雑になるとhadd2の様な名前による接続を行ったほうが 見ただけで判るので良い。 他人に判り易く、後から記述を見ても判り易いという事を考えると、後者の方が優れている。
真理値表 記号
Cin x y z1 c1 Zout c2 Cout
0 0 0 0 0 0 0 0
0 0 1 1 0 1 0 0
0 1 0 1 0 1 0 0
0 1 1 0 1 0 0 1
1 0 0 0 0 1 0 0
1 0 1 1 0 0 1 1
1 1 0 1 0 0 1 1
1 1 1 0 1 1 0 1


・下位モジュールとの接続に関して


library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;

entity hadd is
 port (
    a : in std_logic;
    b : in std_logic;
    z : out std_logic;
    c : out std_logic
);
end hadd;

architecture RTL of hadd is

 begin
  z <= a xor b;
  c <= a and b;

end RTL

↑呼び出し対象

・順番による接続

 hadd1:
  hadd port map
   (
    a,
    b,
    z1,
    c1
);

名前の通り、呼び出し側モジュールで値が宣言されている順にならって値を代入。
xにはxを yにはyを zにはz1を cにはc1を入れる。

・名前による接続

 hadd2:
  hadd port map
   (
    a => a,
    b => cin,
    z => zout1,
    c => c2
);
同じく名前の通り、呼び出し対象のどの部分にどんな値を入れるかを記述。
a =>ってのが、呼び出し対象側のaに相当。
最初はちょっと面倒に感じるかもしれないけれど、視覚的に判り易いのでこちらで慣れるのをお勧めします。




・7セグメントデコーダ
動作 真理値表 記号

a-gの信号がLの時に点灯。
10進ABCDabcdefg16進
00000000000101
1000110011114F
20010001001012
30011000011006
4010010011004C
50101010010024
60110010000020
7011100011010D
81000000000000
9100100011000C



時間の入力信号qに対してそれをデコードし、入力信号に応じたデコード信号a-gを出力する。
真理値表より、 a が点灯する条件としては入力値A-Dが"0001"と"0100"の時であり、これを回路で表すと以下のようになる。



そして、VHDL記述は


a <= ((not A) and (not B) and (not C) and D) or ((not A) and B and (not C) and (not D));


となる
他のも同様に記述すればよいのだが、如何せん面倒なのでカルノー図を使ってちょっくら楽をする↓



・・・VHDL記述で書きたいところだけれど、

assign a = (~q[3] & ~q[2] & ~q[1] & q[0]) | (~q[3] & q[2] & ~q[1] & ~q[0]);

a <= ((not A) and (not B) and (not C) and D) or ((not A) and B and (not C) and (not D));

上記のようにverilog記述に比べてかったるいので、verilog記述でお送りします。後は上の例を見て脳内補完で。

assign e = (~A & D) | (~A & ~B & ~C) | (~B & ~C & D);

更に冗長項を利用すると
assign e = D | (~B & ~C);

となる。

今更カルノー図の説明は要らんよね?



library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;

entity segment is
 port (
    q  : in std_logic;
    seg : out std_logic_vector(6 downto 0);
);
end segment;

architecture RTL of segment is

 begin

seg(6) <= ((not A) and (not B) and (not C) and D) or ((not A) and B and (not C) and (not D));

 以下略

end RTL

そんな訳でカルノー図を使い記述を楽にするのだけれど、それでも結構面倒だし、 第一式を見ただけじゃ何をやっているのか分からんです。
一応動きますけど。。


library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;

entity segment is
 port (
    q  : in std_logic;
    seg : out std_logic_vector(6 downto 0);
);
end segment;

architecture RTL of segment is

 begin

 process (q) begin
  case q is
   when "0000" => seg <= "0000001";
   when "0001" => seg <= "1001111";
   when "0010" => seg <= "0010010";
   when "0011" => seg <= "0000110";
   when "0100" => seg <= "1001100";
   when "0101" => seg <= "0100100";
   when "0110" => seg <= "0100000";
   when "0111" => seg <= "0001101";
   when "1000" => seg <= "0000000";
   when "1001" => seg <= "0001100";
   when others => seg <= "0110000";
  end case;
 end process;
end RTL;


そこで登場するのが case文
qの値が 4'b000 だった場合 segment = 7'0000001;を行う
って感じです。
予期しない値が入力された場合に備えてothersを定めるのはデフォ。
この場合のprocessは、qが変化した際に動作するって意味。


◎定数の表現
 定数は'1' '1010'のように文字や文字列として扱う。
 16進や10進での表記も可能だが、制約が多いので実質的に2進数表記のみ用いる。

◎論理値
 1bitの信号が取り扱う値は、論理回路の世界では0or1であるが、
 この他にも不定値X、H・インピーダンスZがある。

◎演算子
 not、andなどは論理演算子

◎代入記号 
 信号に対する代入は <= を用いる。ここでの代入は、「同時処理代入文」
 記述の順番に行うのではなく、「同時」に代入される。

◎分岐条件  when 〜 elseを用いて2方向分岐を記述できる。when直後の条件式が
  真:when直前の式の値
  偽:else直後の式の値

◎コメント
 --で始まり、行末までがコメント
 複数行コメントは無し。

◎文字の大小の区別
 予約語も含めて文字の大小の区別は行わない。

◎変数の代入
 constantで定められた値には <= で値を代入するのではなく、 := で値を代入する。


[<<前へ | ↑Topへ戻る↑ | 次へ>>]