Semiconductor_VHDL

◎VHDL

◆文字、型、定数、コメント

_◇文字と名前

文字の大小は区別されない
⇒慣習的に名前を大文字で書き、他を小文字で書くことが多い

※” “” character型 string型 列挙型では大文字小文字の区別がある

※std_logicの’X’, ‘Z’は大文字で定義されている

※名前
英字ではじまり
英数字と_
(_は2つ続けてはならない、また末尾においてはならない)
⇒アンダーバーは文字列の途中に何か所か入れられるが1か所につき1つだけ

_◇コメント
「–」で始まり行末まで
⇒記号「-」が2個続いて存在すれば行末までコメントとなる

_◇型と信号
基本的に型が一致した信号どうしでのみ演算や接続が可能

※VHDLネイティブ
integer(32ビット)
real
bit(0,1のみ)
bit_vector
boolean
character
string

※integer型の宣言
例)
signal Q1:integer range 0 to 18431;
⇒定義した最小値と最大値を含む最小ビット数の2進整数データとして生成される
⇒最小値が負数の場合2の補数表示となる
⇒15ビットの信号となる
⇒rangeを省略した場合32ビットの信号となる
(range -2147483647 to + 2147483647)
⇒integer型は直接パルス信号として利用できない
⇒integer型信号Iをstd_logic_vector型信号として扱う場合
conv_std_logic_vector(I, サイズ)
サイズは変換後のビット数を表す整数定数またはinteger型データ
例)
Y<=conv_std_logic_vector(X,8);
⇒std_logic_vector型信号Sをinteger型信号として扱う場合
conv_integer(S)

※IEEE1164ライブラリで定義
std_logic
std_logic_vector
9状態定義されている
⇒0,1,X,Z,U
不定値X
ハイインピーダンスZ
未定(初期状態)U
記述上は’0′,’1′,’Z’,’X’,’U’
⇒U, X
シミュレータでは扱えるが、論理合成では扱えない
⇒W, L, H, -(don’t care)

※type文
例)
type tri_state_logic is (‘0′,’1′,’Z’);

※subtype文
例)
subtype nibble is std_logic_vector (3 downto 0);

※回路記述で通常使うのは
std_logic
std_logic_vector
integer
boolean

※シミュレーション記述で良く使うのは
character
time
string
text

※ほとんど使わない
bit
bit_vector

_◇vector型

※IEEE1164ライブラリで定義されるstd_logic_vector型は、多ビット信号を表す

std_logic_vector(幅)
⇒幅(dimension)は信号のビットの順番とビット数を示す

昇順幅
std_logic_vector( 0 to 3 )
┌─┬─┬─┬─┐
│0│1│2│3│
└─┴─┴─┴─┘

降順幅
std_logic_vector( 3 downto 0 )
┌─┬─┬─┬─┐
│3│2│1│0│
└─┴─┴─┴─┘

※降順幅の定義は整数型(integer)への互換性があり、数値データ演算などにも利用できる。
⇒特に昇順とする必要性がなければ降順幅の方が便利

※vector型信号の個々のビットの記述
⇒vector型の幅範囲に含まれる整数をindexとし、

信号名(index)

_◇定数
文字や文字列として表現するが、RTL記述では、実質2進数表記のみを用いる。

※1ビット定数
シングルクウォートする
‘0’, ‘Z’

※ベクタ信号
ダブルクウォートする
“ZZZ”, “100”

※定数宣言
constant 定数名 : type := 値;

architecture, procedureなどの中で定義
⇒グローバルにもローカルにもできる?

例)
constant DELAY1: time := 4ns;
constant DATA_BUS: integer := 16;

_◇配列タイプ
同じタイプのデータを集めて新たな型とするもの

type データ型名 is array 範囲 of 元の型名;

例)
type WORD is array(1 to 8) of std_logic;

_◇アトリビュート

信号やデータタイプ、ブロック、エンティティ、オブジェクトなどの付加情報を保持するもの
⇒抽象記述、パラメタライズ設計で使用する

※アトリビュートはコンパイル時に決まってしまうのでプログラミング言語のプロパティのように実行中で書き換えできない
⇒アトリビュートで既定された状況で動作する回路を生成する

例)
ベクタ信号 a のアトリビュート ‘length により
a’length とすることでベクタ長を得る

例)CLKの立ち上がりエッジの検出
process (CLK’event and CLK=’1′)
if ( CLK’evnet and CLK=’1′) then

①event
信号の変化の有無を意味する
例)
ck’event and ck=’1’
⇒ckに変化があり、かつ1のとき(ckの立ち上がり)

◆基本構造

_◇基本構造

①パッケージ呼び出し
各種の定義などが含まれるパッケージを呼び出す
②entity
外部インタフェースを定義する
③architecture
内部の動作を記述する。回路本体。1つのエンティティに対して複数のアーキテクチャを持たせることができる。どれを選択するかはコンフィグレーション宣言による。

_◇ライブラリ宣言
予め定義されたデータの集まりであるライブラリの使用を宣言
⇒IEEEライブラリはVHDL記述において必須

library IEEE;

_◇パッケージ呼び出し

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

※std_logic_1164パッケージ
基本的な型が定義されているので必須

※.all
パッケージの中の全てを使用する

_◇エンティティ

回路の入出力ポートを定義する

※エンティティ名とファイル名は必ずしも一致する必要はない

構文)
entity エンティティ名 is
ジェネリック宣言
ポート宣言
end エンティティ名;
⇒正式には
end entity エンティティ名;
であるが、entityとエンティティ名は省略できるため、entityは慣習的に省略される。

ポート宣言)
ポート信号名 : 入出力 型
⇒繰り返す場合は;で区切るが、最後の)の前には;を書かない

例)
entity adder is
port(a, b : in std_logic_vector(3 downto 0);
q: out std_logic_vector(3 downto 0)
);
end adder;

※信号の方向
in 入力
out 出力
inout 双方向
buffer (Xilinxではサポートされない)
linkage

※信号の型
std_logic ビット
std_logic_vector バス
ビット幅を定義する
downto
最上位ビットが番号の大きい信号
to
最上位ビットが番号の小さい信号
⇒基本的に型が一致した信号どうしでのみ演算や接続が可能
⇒型が一致しないと文法エラー

_◇generic宣言

※エンティティ宣言中のオプショナル

入出力ポートのビット幅や、アーキテクチャ内部の動作をパラメータ化する

記述例———————————————————————-

entity COMPARE is
    --4はデフォルト値
    generic( N:    integer := 4);
    port(    A, B:    in    std_logic_vector(0 to N-1);
            EN:        in    std_logic;
            F:        out    std_logic);
end COMPARE;

–インスタンスを作成するときにgeneric mapする
U1: COMPARE
generic map (N=>8)
port map(INA, INB, SIG_EN, SIG_F);

—————————————————————————-

_◇アーキテクチャ

構文)
architecture アーキテクチャ名 of エンティティ名 is
各種宣言
begin
本体
end アーキテクチャ名;
⇒これまた正式には
end architecture アーキテクチャ名;
である。上記は慣用。architectureもアーキテクチャ名も省略可能。

※回路名称はエンティティ名で与えられているのでアーキテクチャ名は任意。
⇒形式上の名前である
例えば、RTL, SIMなど用途を示す語などでよい。
⇒一般に使われるアーキテクチャ名
BEHAVIOR
RTL
NETLIST
DATAFLOW
STRUCTURE
SIM

※1つのエンティティに複数のアーキテクチャを区別して記述することが許されている
⇒しかし、多くのコンパイラには意味がない

※各種宣言…ノード宣言部
モジュール内部でのみ用い、外部には出力しない信号を宣言
signal ノード名:属性;
⇒同じデータ型の信号が複数ある場合には、それら信号名を「,」で区切って並べて記述してもよい。

コンポーネント宣言

※本体…動作記述部

_◇同時文
concurrent

各文は同時に作動する個々の電子回路ブロックに対応する
⇒文の記述の順序には意味がなく、透過

_◇コンフィギュレーション宣言
一つのエンティティに複数のアーキテクチャを対応させた場合、どれを選択するかを対応づけるための宣言

configuration コンフィギュレーション名 of エンティティ名 is
for アーキテクチャ名
end for;
end コンフィギュレーション名;

※回路記述は省略可能
※シミュレータによっては最上位階層にコンフィギュレーション宣言が必須のものもある

◆階層設計

process文とイベントアトリビュートで記述する

_◇下位ブロックのよびだし
①アーキテクチャ内で、呼び出すブロックのポート部分をコンポーネント宣言する
⇒該当ブロックのエンティティと同じ
②下位ブロックの接続に使用する内部ネットは全て宣言する(beginの前)
③信号の接続には2形態ある
順番による接続
名前による接続
定義側ポート名=>接続信号名
※接続信号には式や定数を記述できないので、定数などをたてる場合は、内部信号を使って与える。

例)

_◇コンポーネント宣言
使用するコンポーネントを宣言する
architecture部の中beginより前におく

component コンポーネント名 is
generic文
port宣言部
end component コンポーネント名;
⇒isと最後のコンポーネント名は省略可能

※port宣言部は該当のコンポーネントのentityをコピーし、componentに置き換えればよい。

※port名は仮の名前なので、上位層のport名や内部信号名などと重複してもよい
⇒下位の層の信号名の記述順とデータ型だけを示している。

_◇ポートマップ宣言

※architecture部の同時文である。

インスタンスを宣言し、コンポーネントの端子と実際の信号を対応づける
architecuture部のbeginより後の本体内におく

<ラベル> : <コンポーネント名>
port map (
コンポーネントの端子名=>使う側の信号線名,

);

※接続の方向があっていれば =>と書いても <=と書いても良い。

※単に信号の順序だけで結びつけることも可能ではある。

※下位層の信号の方向がoutかつ上位層でこの信号を使用することがない場合
何も書かない
open
としてもよい

_◇procedure

回路記述上の便宜を図る仕組みであって、ソフトのサブルーチンとは異なる。呼び出す外部はコンカレントに動作する。
内部は逐次処理として書く。

戻り値なし。

※引数次第でパラメータライズできる
※複数の入出力パラメータの受け渡しができる
⇒入力、出力の区別があり

procedure <プロシージャ名>(<入出力パラメータ>)
宣言文
begin
順次処理文
end プロシージャ名;

※順次処理部分は、変数代入文 := で書く

_◇function

回路記述上の便宜を図る仕組みであって、ソフトの関数とは異なる。呼び出す外部はコンカレントに動作する。
内部は逐次処理として書く。

戻り値あり。

※引数次第でパラメータライズできる
※複数の入力パラメータ(定数扱い)を受け取り、一つの戻り値を返す。

function <ファンクション名> (<入力パラメータ>) return <データタイプ> is
宣言文
begin
順次処理文
return <戻り値>;
end <ファンクション名>;

◆パッケージ

_◇パッケージ宣言

library宣言
パッケージ呼び出し

package パッケージ名 is
プロトタイプ宣言
constant宣言
end パッケージ名;

package body パッケージ名 is
パッケージ本体
end パッケージ名;

_◇ファンクション宣言とファンクション記述

※functionは逐次処理文しか実行できない
⇒組み合わせ回路に限られる
⇒case文の場合、全条件を記述するか、othersを記述する必要がある
⇒signalは使えず、variableかconstant

※ファンクション宣言(プロトタイプ)
function ファンクション名(
signal宣言)
return 返り値の型;

※ファンクション記述
function ファンクション名(
signal宣言)
return 返り値の型 is
variable宣言;
begin
ファンクション本体
end;

※variable 変数名 : 型

◆信号線、演算子、代入文

_◇信号線の区別

①外部とのインタフェース
エンティティ部のport文で宣言
信号の向きがある

②モジュール内信号
アーキテクチャ部でsignal文で宣言
信号の向きがない

※port文でoutとされている信号を内部に引き込んで使うことはできない
⇒方向でエラーとなる
⇒出力portと同じ値を持つ内部信号線として内部で接続し、それをport文のノードにも接続する
⇒outポートは何等かの回路素子を介して回路ブロックの外側に生成されるものと考える。

_◇signal文

内部信号の定義

signal

例)
signal: 信号名 型;

※初期値を与えることもできるが、論理合成では無視される
signal: 信号名 型 := 式;

※信号名には記号文字つかえない
⇒負論理を示すために、先頭に”n”をつけるなどのローカルルールを決めると良い

_◇演算子

①論理
not
C<=not A;
and
C<=A and B;
or
C<=A or B;
xor
C<=A xor B;
nand
C<=A nand B;
nor
C<=A nor B;

②関係
=
/=
< >
<= >=

③算術
対象がベクタ信号として定義されていること
+ ⇒加算回路が生成される
– ⇒減算回路が生成される
* ⇒乗算回路が生成される
/
mod 剰余
rem 余り
** 累乗
abs 絶対値
※算術演算子「+」「-」を使用した記述は全加算器を並べた加算器の記述よりも効率的な回路が生成される
※乗算演算子「*」により並列型乗算回路が生成されるのでハード量は多くなる

④連接
&
複数の信号やベクタ信号をつないで1つのベクタに合成

例)
Y=A&B&C;

※演算子の優先順位
notが高いだけで後は全て同じ
⇒()で順位を明示する必要あり
例)
C<=not A and B;

C<=not (A and B);
は異なる。

_◇bit_vector, boolean_vector型演算子

※シフト演算子
bit_vector, boolean_vector型信号Xをinteger型YビットシフトしてZを得るシフト演算子が存在する

Z<=X sll Y; shift left logical
Z<=X srl Y; shift right logical
Z<=X sla Y; shift left arithmetic
Z<=X sra Y; shift right arithmetic
Z<=X rol Y; rotate left logical
Z<=X ror Y; rotate right logical _◇型変換関数 型変換はVHDLの形式上の概念であり、変換関数を記述しても回路は実際には生成されない。 ※std_logic_vector -> bit_vector
to_bitvector(S)

※bit_vector -> std_logic_vector
to_stdlogicvector(B)

※std_logic_vector -> integer
CONV_INTEGER(S)

_◇信号代入文

ある信号線は左辺に一度しか記述できない

※順次処理文では信号代入の順序は意味を持つが、コンカレント文では、どこにおいても同じ動作となる

※同時代入文(同時処理代入文)
アーキテクチャ直下に記述する代入文
「<=」を使って代入する
⇒記述の順番に代入するのではなく、同時に代入される

_◇変数と変数代入文

process文、function文、procedure文の中でのみ使えるローカルな変数

※VHDLの変数は「記憶素子」ではないので、ソフトウエアの変数とは異なる。
⇒信号の状態を記述するためのシンボル。

変数への代入
:=
⇒信号とは異なり、代入文の評価と同時に変数に代入される
※変数に <= で代入してもエラーにはならないようだ

_◇多ビット信号のビット選択と部分選択

signal DBUS: std_logic_vector( 15 downto 0);
signal LO_BYTE, HI_BYTE: std_logic_vector( 7 downto 0);
signal MSB, LSB: std_logic;

MSB <= DBUS(15);
LSB <= DBUS(0);

HI_BYTE <= DBUS(15 downto 8);
LO_BYTE <= DBUS(7 downto 0);

※ビット位置を指定する信号代入
構文)
信号<=(ビット位置=>値 [, ビット位置=>値] );
⇒ビット位置の指定
整数 例 8
範囲 例 14 downto 12
others
⇒値は1ビットの値または1ビットの信号
例) ‘1’
⇒すべてのビットに値が代入されるように記述すること

※vectorをクリアする場合の定石
A<=”0000″;
の代わりに
A<=(others=>’0′);

◆process文
順次処理を記述するための文
⇒記述の順序に意味がある
⇒不要な信号代入を含めると、意図しないラッチが作られる
⇒別々のprocess文は並列に動作する
⇒一つの信号の値の定義は一つのprocess文によるブロックに限られる
⇒2つのprocess文によるブロックで定義されると、回路ブロックの外で信号が短絡されることになる。

※順序回路の動作記述に向くが、組み合わせ論理回路も記述可
⇒シーケンシャルな組み合わせ論理回路

※if文や、case文に対応する回路の生成
⇒各文単独の回路生成はおこなわれない
⇒各文をまとめて制御する回路ブロックとしてprocess文が必要

構文)
ラベル: process (センシティビティリスト)
プロセス宣言部
変数宣言, 定数宣言, タイプ宣言, サブプログラム宣言
begin
順次処理文
end process ラベル;
⇒末尾のprocessは省略可能

※センシティビティリストに記述された信号が変化する度にbeginとendの間が実行される⇒信号名をコンマで区切って並べる

⇒しかし、代入はwait文またはend processで一気に起きる
⇒ただし、variableへの代入は即座に起きる

※wait文
センシティビティリストとは両立しない待ち条件
シミュレーションなどで使われる

_◇同時処理文と逐次処理文

※同時処理文
記述の順序とは関係なく、すべての文の評価が同時に行われる
信号 <= 式;

⇒左辺にはsignalで宣言された信号が用いられる必要がある

※逐次処理文
記述順序を守って評価される
信号 := 式;

※左辺はvariableで宣言された信号が用いられる必要がある

_◇条件分岐:if

if文

※条件が真ならばthenに続く処理が行われる

if 条件1 then
順次処理1;
elsif 条件2 then
順次処理2;
else
順次処理3;
end if;

※elsif,elseはなくてもよいが、end ifは必須。
⇒elseに続く文列が1個のif文だけのときにはelsifが使える
⇒elsifの締めくくりには end ifが使えない
⇒elsifが使えないケースでは、
else if ~ end if;
とネストしたif文で記述する

_◇条件分岐:when else
when else文
真の時の値 when 条件 else 偽の時の値

※すべての条件を網羅したデータ・セレクタ回路の生成などに向く
結果 <= データ1 when 条件1 else

データn when 条件n;

※when else文は式ではないので、式のように続けて演算することはできない

_◇条件分岐:with select
with select文

特定の定数とのパターンマッチで入力を選択する
with 制御信号 select
結果 <= データ1 when 定数1, … データn when others; _◇条件分岐:case 多方向分岐 条件となる信号の値によって、それぞれ動作が異なる回路を記述する case文 case文の入力と、when直後の値が一致すれば =>以降が実行される
othersはどれも一致しないときに実行される

例)
case 信号 is
when 条件1 =>
条件1の時の論理
when 条件2 =>
条件2の時の論理
when others =>
どの条件にもあてはならないとき
end case;

※case分については各処理はシーケンシャル文でなく、コンカレント文扱いとなる

※when othersは省略不可だが、アクションを null とすることはできる。
⇒VHDLのstd_logic型では”ZZ”なども値として想定されている
⇒”00″などの実際に処理する値以外をothersで記述(たとえばすべて不定値’X’)
(一般にstd_logic型を使用するときには必要)

※複数の条件で同じ動作となる場合
⇒各地を記号「|」で区切って並べる
when 値 | 値 | … | 値 => 文列
⇒値が連続な場合は、開始値と終始値とでも記述できる
when 開始値 to 終始値 => 文列

_◇ループ:for

<ラベル> : for <識別子> in <範囲指定> loop
順次処理文
end loop;

※範囲指定例
0 to 7
7 downto 0

※exit

※next

_◇ループ:while loop

条件が true の間ループする

<ラベル> : while <条件文> loop
順次処理文;
end loop <ラベル>;

※exit

※next

_◇wait
なんらかの条件がそろうまで待つ

wait on 信号(オブジェクト)
信号が変化するまで待つ

wait until <条件>

wait for <時間>

※時間は ps, ns, us, ms, sを単位としてつけた整数

◆generate文
パラメータを変えて複数を回路を生成したり、回路の有効、無効を切り替えるためなどに使う。

_◇for generate

ラベル: for 変数 in 開始 to 終了 generate
同時処理文
end generate;

_◇if generate

ラベル: if (条件式) generate
同時処理文
end generate;

条件式にあたえる定数は以下の例のように定義する

constant COND : integer := 1;

◆構造記述と動作記述

_◇構造記述

ハードウエアの構造に依拠した記述

_◇動作記述

ハードウエアの構造に関わらず、その動作を記述

◆組み合わせ回路

※簡単な組み合わせ回路はアーキテクチャ内の同時処理代入文で記述する

※複雑な組み合わせ回路はprocess文を用いて記述する

_◇プライオリティ・エンコーダ

when ~ else をつなげる

_◇デコーダ

with ~ select文

例)2to4デコーダ

library IEEE;
use IEEE.std_logic_1164.all;

entity dec2to4 is
port (    d: in std_logic_vector(1 downto 0);
        q: out std_logic_vector(3 downto 0)
    );
end dec2to4;

arthitecture RTL of dec2to4 is
begin
    process( d ) begin
        case d is
            when "00" => q <= "0001";
            when "01" => q <= "0010";
            when "10" => q <= "0100";
            when "11" => q <= "1000";
            when others => q <"= "XXXX";
        end case;
    end process;
end RTL;

_◇コンパレータ

when ~ else であれば出力ラッチの生成なし

※process + if文だと、出力ラッチが生成されることがある

_◇加算器
符号なし

①入力信号の上位に1ビット連結
a_tmp <= ‘0’ & x_in;
②算術演算子 + で加算
q_tmp <= a_tmp + b_tmp;
③下位ビットを切り出し
y_out <= q_tmp(7 downto 0);
④最上位ビットを桁上げ出力とする

※符号付回路のコンパイルは注意

半加算器回路の記述例——————————————————–

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity HALF_ADDER is
    port (    A,B:        in    std_logic;
            C,S:        out    std_logic );
end HALF_ADDER;

architecture Behavioral of HALF_ADDER is
    signal    w:    std_logic;
begin
    W <= A and B;
    C <= W;
    S <= (A or B) and not W;
end Behavioral;

半加算器回路の記述例2——————————————————-

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity HALF_ADDER is
    port (    A,B:        in    std_logic;
            C,S:        out    std_logic );
end HALF_ADDER;

architecture Behavioral of HALF_ADDER is
begin
    C <= A and B;
    S <= A xor B;
end Behavioral;

半加算器の記述例2を使った全加算器——————————————-

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity FULL_ADDER is
    port (    A,B,COL:    in    std_logic;
            C,S:        out    std_logic );
end FULL_ADDER;

architecture Behavioral of FULL_ADDER is

    component HALF_ADDER is
        port (    A,B:        in    std_logic;
                C,S:        out    std_logic );
    end component;

    signal C1, C2, S1:    std_logic;

begin
    U1: HALF_ADDER port map(A, B, C1, S1);
    U2: HALF_ADDER port map(C1, COL, C2, S);
    C <= C1 or C2;
end Behavioral;

全加算器の記述例を使った並列4ビット加算器———————————-

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity ADDER_4bit is
    port (    X,Y:in    std_logic_vector(3 downto 0);
            CIN:in    std_logic;
            Z:out    std_logic_vector(3 downto 0);
            COUT:out    std_logic );
end ADDER_4bit;

architecture Behavioral of ADDER_4bit is

 component FULL_ADDER is
     port (    A,B,COL:    in    std_logic;
             C,S:        out    std_logic );
 end component;

 signal C1, C2, C3:    std_logic;

begin
    U1: FULL_ADDER port map(X(3), Y(3), C3, COUT, Z(3));
    U2: FULL_ADDER port map(X(2), Y(2), C2, C3, Z(2));
    U3: FULL_ADDER port map(X(1), Y(1), C1, C2, Z(1));
    U4: FULL_ADDER port map(X(0), Y(0), CIN, C1, Z(0));
end Behavioral;

半加算器回路の記述例3 process文による記述———————————–

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity HALF_ADDER is
    port (    A,B:        in    std_logic;
            C,S:        out    std_logic );
end HALF_ADDER;

architecture Behavioral of HALF_ADDER is
begin
    process(A, B)
    begin
        if A='1'
            then if B='1' then C<='1'; else C<='0'; end if;
            else C<='0';
        end if;
        if A='0'
            then if B='1' then S<='1'; else S<='0'; end if;
            else if B='0' then S<='0'; else S<='1'; end if;
        end if;
    end process;
end Behavioral;

半加算器回路の記述例4 case文による記述———————————–

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity HALF_ADDER is
    port (    A,B:        in    std_logic;
            C,S:        out    std_logic );
end HALF_ADDER;

architecture Behavioral of HALF_ADDER is
    signal IN_AB: std_logic_vector(0 to 1);
begin
    IN_AB <= A & B;
    process(IN_AB)
    begin
        case IN_AB is
            when "00" => C<='0'; S<='0';
            when "01" => C<='0'; S<='1';
            when "10" => C<='0'; S<='1';
            when "11" => C<='1'; S<='0';
            when others => C<='X'; S<='X';
        end case;
    end process;
end Behavioral;

_◇減算器
符号なし

2の補数回路+加算器でもよいが
⇒2の補数回路で加算器が生成されてしまう
⇒加算器同様に – で減算器を定義してもよい

※符号付回路のコンパイルは注意

_◇フルアダー呼び出しによる4ビット加算回路

library IEEE;
use IEEE.std_logic_1164.all;

entity adder_ripple is
    port ( a, b : in std_logic_vector(3 downto 0);
            q: out std_logic_vector(3 downto 0)
    );
end adder_ripple;

architecture RTL of adder_ripple is

component FULLADD
    port (
        A, B, CIN: in std_logic;
        Q, COUT : out std_logic
    );
end component;

signal cout: std_logic_vector(3 downto 0);
signal zero: std_logic;
begin
    zero <= 0;
    
    add0: FULLADD port map( a(0), b(0), zero, q(0), cout(0) );
    add1: FULLADD port map( a(1), b(1), cout(0), q(1), cout(1) );
    
    add2: FULLADD port map( A=>a(2), B=>b(2),
                Q=>q(2), CIN=>cout(1), COUT=>cout(2) );
    add3: FULLADD port map( A=>a(3), B=>b(3),
                Q=>q(3), CIN=>cout(2), COUT=>cout(3) );
end RTL;
library IEEE;
use IEEE.std_logic_1164.all;

entity FULLADD is
port(A, B, CIN: in std_logic;
    Q, COUT: out std_logic
    );
end FULLADD;

architecture RTL of FULLADD is
begin
    Q <= (A xor B) xor CIN;
    COUT <= (A and B) or (B and CIN) or (CIN and A);
end RTL;

_◇バレルシフタ

シフトするビット数によって、シフタを切り換えるセレクタ

_◇パリティ・ジェネレータ、チェッカ

※偶数パリティが一般的
⇒パリティビット含め1の数が偶数

※XORで構造設計するほうが簡単

敢えて動作記述するならば process文と forループでもかける

—————————————————————————-
signal A:std_logic_vector(7 downto 0);

P<=A(7) xor A(6) xor A(5) xor A(4) xor A(3) xor A(2) xor A(1) xor A(0);

_◇2の補数表示整数の加減算回路

※加減算回路のVHDL記述は、単に演算子を使用した加算の式、減算の式をかくだけでも良い。

※整数の加減算(2の補数)=符号ビットを含めた加減算
X-Y=X+(-Y)=X+Y~+1
-Yは2の補数
Y~は反転
⇒減算は被減算に減数の各ビットの反転と1とを加算すればよい

┌─┐
X────→┤ │
│ │
┌─┐ >+>─→Z=X±Y
│反│ │ │
Y→┤転├→┤ │
│器│ └┬┘
└┬┘ ↑C0
↑ │
p→─┴───┘
制御信号(p=0のとき加算、p=1のとき減算)

2の補数表示整数の加減算回路の記述例—————————————-

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity ADDER_SUBTRACTOR is
    port (    X,Y:in    std_logic_vector(15 downto 0);
            Z:out    std_logic_vector(15 downto 0);
            P:in    std_logic);
end ADDER_SUBTRACTOR;

architecture Behavioral of ADDER_SUBTRACTOR is
    signal    w:    std_logic_vector(15 downto 0);
begin
    Z<=X+W+P;
    process(P, Y)
        begin
        if P='0' then
            W<=Y;
        else
            W<=not Y;
        end if;
    end process;
end Behavioral;

※IEEE.STD_LOGIC_UNSIGNED.ALLにより算術演算子を使用した式で記述
⇒算術演算子「+」を2回使用しているが合成の際に最適化される
⇒原理構造に忠実な記述

2の補数表示整数の加減算回路の記述例2—————————————

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity ADDER_SUBTRACTOR is
    port (    X,Y:in    std_logic_vector(15 downto 0);
            Z:out    std_logic_vector(15 downto 0);
            P:in    std_logic);
end ADDER_SUBTRACTOR;

architecture Behavioral of ADDER_SUBTRACTOR is
begin
    process(P, X, Y)
        begin
        if P='0' then
            Z<=X+Y;
        else
            Z<=X-Y;
        end if;
    end process;
end Behavioral;

※IEEE.STD_LOGIC_UNSIGNED.ALLにより算術演算子を使用した式で記述
⇒合成時の最適化の自由度が増すのでかえって効率的

◆非同期式回路と同期式回路

_◇非同期式回路
asynchronous circuit

入力信号の変化がただちに出力に変化を及ぼす機構の回路
⇒回路素子の速度で値が決定される
⇒小さく、高速
⇒だが、異なる経路の信号の確定に遅速が生じ予期せぬ出力が生じる場合がある

_◇同期式回路
synchronous circuit

動作の時間基準となる同期信号を用い、各入力信号が確定する時間を考慮したタイミングで出力信号値を決定する機構
⇒順序回路の設計に広く用いられる

_◇VHDLによる順序回路の記述

process文
⇒一つの順序回路ブロック
⇒起因リストに順序回路が状態を遷移する起因となる信号を全て記述する

※非同期式
process文中に次の状態遷移をif文またはcase文で記述

※同期式
⇒event属性(attribute)で、立ち上がりか、立下りかを記述する

※同期信号と同期位置
①立上がりエッジ同期
CLOCK’event and CLOCK=’1′
②立下りエッジ同期
CLOCK’event and CLOCK=’0′

※event属性を使った動作の記述

①立ち上がり
if 信号’event and 信号=’1′ then
次の遷移状態を決定する文
出力信号値を決定する文
end if;

②立下り
if 信号’event and 信号=’0′ then
次の遷移状態を決定する文
出力信号値を決定する文
end if;

例)
process(C) begin
if C’event and C=’1′ then A<=B; end if;
if C’event and C=’1′ then B<=X; end if;
end process;

│  T0  T1  T2  T3  T4
│  ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐
│C─┘ └─┘ └─┘ └─┘ └─┘ └─
│  │┏━━┿━━━┿━━┓│   │
│X━┿┛  │   │  ┗┿━━━┿━━━
│  │   ┏━━━┿━━━┫   │
│B━┿━━━┫   │   ┗━━━┿━━━
│  │   │   ┏━━━┿━━━┫
│A━┿━━━┿━━━┫   │   ┗━━━
│  │   │   │   │   │

◆順序回路

※フリップフロップを含むデジタル回路

_◇フリップフロップ

0/1の記憶回路

※組み合わせ禁止
フリップフロップの出力が不定となるような入力値

※レジスタ(register)
デジタル値を明示的に記憶しておく回路

※ラッチ(latch)
単なる一時記憶回路

※遷移図の不遷移
⇒代入が何も生じないようにする⇒変化せず直前の値が保持される

フリッププロップの記述例—————————————————-

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity BASIC_FLIPFLOP is
    port (    I,J:    in    std_logic;
            Q:        out    std_logic );
end BASIC_FLIPFLOP;

architecture Behavioral of BASIC_FLIPFLOP is
begin
    process(I,J)
        begin
            if I='0' then
                Q<='1';
            elsif J='0' then
                Q<='0';
            end if;
        end process;
end Behavioral;

_◇順序回路の記述の2形式

①process文のセンシティビティリストで
同期タイプはクロック
非同期タイプはクロックと非同期制御信号
を記述
if文でクロック信号のeventアトリビュートと極性をみて動作を書く
※こちらのスタイルの方が普通

②センシティビティリストの無いprocess文を使う
⇒通常は無限ループとなる
wait until文によりクロックエッジを待って処理を行う。
※非同期リセットなどの記述はできない

例)
process begin
wait until ck’event and ck=’1′;
if res=’1′ then
q_reg <= “0000”;
else
q_reg <= q_reg + “1”;
end if;
end process;

_◇非同期リセット付きDフリップフロップ

process文で CLKとRSTの2本を見る
⇒RSTはロウアクティブとする

process文内のif文で先にRSTを見て
次に
CLK’event and CLK=’1′
で立ち上がりエッジを見る

_◇バイナリカウンタ

例)同期リセット

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

entity counter is
    port (    ck, res: in std_logic;
            q : out std_logic_vector(3 downto 0)
        );
end counter;

architecture RTL of counter is
signal q_reg: std_logic_vector( 3 downto 0 );
begin
    q <= q_reg;
    process ( ck ) begin
        if ck'event and ck='1' then
            if res='1' then
                q_reg <= "0000";
            else
                q_reg <= q_reg + "1";
            end if;
        end if;
    end process;
end RTL;

例)非同期リセット

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

entity counter is
    port (    ck, res: in std_logic;
            q: out std_logic_vector(3 downto 0)
        );
end counter;

architecture RTL of counter is
signal q_reg: std_logic_vector(3 downto 0);
begin
    q <= q_reg;
    process ( ck, res ) begin
        if res='1' then
            q_reg <= "0000";
        elsif ck'event and ck='1' then
            q_reg <= q_reg + "1";
        end if;
    end process;
end RTL;

_◇アップダウンカウンタ

_◇同期式10進カウンタ

※BCDカウンタ
binary coded decimal; 2進化10進カウンタ
⇒4ビットで10進1桁対応
⇒9から0への遷移時に桁上げ信号出力⇒複数桁の10進カウンタ構成
⇒リセット時には0に遷移

CI:カウント入力パルス
RESET
D:レジスタ値(4ビット)出力)
CO:桁上げ出力

BCDカウンタの記述例——————————————————–

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity BCD_COUNTER is
    port (    CI, RESET:    in    std_logic;
            CO:            out    std_logic;
            D:            out std_logic_vector(3 downto 0) );
end BCD_COUNTER;

architecture Behavioral of BCD_COUNTER is
    signal    Q:    std_logic_vector(3 downto 0);
begin
    D<=Q;
    process (CI, RESET)
    begin
        if RESET='1' then Q<="0000"; CO<='0';
        elsif CI'event and CI='1' then
            if Q=9    then
                Q<="0000"; CO<='1';
            else
                Q<=Q+1; CO<='0';
            end if;
        end if;
    end process;
end Behavioral;

※信号RESETは非同期RESET
※信号CIはアトリビュートにより立ち上がりエッジ同期

_◇周波数分周回路

※信号発生器
signal generator

※分周器
基本周波数パルスをN進カウンタでカウントし、基本周波数のN分の1の周波数を作り出す

周波数分周回路の記述例——————————————————

18.432MHzからCP1=1kHzとCP2=1Hzを生成する回路

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity FREQ_DIVIDER is
    port (    CP:            in    std_logic;
            CP1,CP2:    out    std_logic;);
end FREQ_DIVIDER;

architecture Behavioral of FREQ_DIVIDER is
    signal    Q1:    std_logic_vector(14 downto 0);
    signal    Q2:    std_logic_vector(9 downto 0);
begin
    CP1<=Q1(14);
    CP2<=Q2(9);
    process(CP)
        begin
            if CP'event and CP='1' then
                if Q1=18431 then
                    Q1<=(others=>'0');
                else
                    Q1<=Q1+1;
                end if;
            end if;
        end process;
    
    process(Q1(14))
        begin
            if Q1(14)'event and Q1(14)='1' then
                if Q2=999 then
                    Q2<=(others=>'0');
                else
                    Q2<=Q2+1;
                end if;
            end if;
        end process;
end Behavioral;

※信号RESETは非同期RESET
※信号CIはアトリビュートにより立ち上がりエッジ同期

周波数分周回路の記述例2—————————————————–
前例で、CP2の立ち上がりをCPに同期させる記述

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity FREQ_DIVIDER is
    port (    CP:            in    std_logic;
            CP1,CP2:    out    std_logic;);
end FREQ_DIVIDER;

architecture Behavioral of FREQ_DIVIDER is
    signal    Q1:    std_logic_vector(14 downto 0);
    signal    Q2:    std_logic_vector(9 downto 0);
begin
    CP1<=Q1(14);

    process(CP)
        begin
            if CP'event and CP='1' then CP2<=Q2(9);
        end process;

    process(CP)
        begin
            if CP'event and CP='1' then
                if Q1=18431 then
                    Q1<=(others=>'0');
                else
                    Q1<=Q1+1;
                end if;
            end if;
        end process;
    
    process(Q1(14))
        begin
            if Q1(14)'event and Q1(14)='1' then
                if Q2=999 then
                    Q2<=(others=>'0');
                else
                    Q2<=Q2+1;
                end if;
            end if;
        end process;
end Behavioral;

周波数分周回路の記述例3—————————————————–
順序回路の状態変数にintegerを用いる例

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity FREQ_DIVIDER_2 is
    port (    CP:            in    std_logic;
            CP1,CP2:    out    std_logic;);
end FREQ_DIVIDER_2;

architecture Behavioral of FREQ_DIVIDER_2 is
    signal    Q1:    integer range 0 to 18431;
    signal    Q2:    integer range 0 to 999;
    signal    P: std_logic;
begin
    CP1<=P;

    process(CP)
        begin
            if CP'event and CP='1' then
                if Q1<9215 then
                    P<='0';
                    Q1<=Q1+1;
                elsif Q1<18431 then
                    P<='1';
                    Q1<=Q1+1;
                else
                    P<='0';
                    Q1<=0;
                end if;
            end if;
        end process;
    
    process(P)
        begin
            if P'event and P='1' then
                if Q2<499 then
                    CP2<='0';
                    Q2<=Q2+1;
                elsif Q2<999 then
                    CP2<='1';
                    Q2<=Q2+1;
                else
                    CP2<='0';
                    Q2<=0;
                end if;
            end if;
        end process;
end Behavioral;

_◇バウンス除去回路
シフトレジスタの特殊用例

_◇シフトレジスタ

_◇メモリ

※ターゲット依存のIPによる実装の方が効率良い

※ROM
with ~ select文で構成可能
⇒FPGAの場合, LUT RAMに実装される

※RAM
arrayで記述する。
⇒アドレス線をラッチしてから使うと、同期メモリと推定し、FPGAのブロックRAMに実装してくれる可能性がある

_◇累算式演算回路

演算回路中に累算器(accumulator)とよばるレジスタを含む演算回路
⇒加算の場合、被加数、加数、和のうちの2個が累算器に特定されるので操作が簡単

例)
データ語長16ビット
3ビット制御信号による機能指定
000 “00..0”
001 B
010 ACC+B
011 ACC-B
100 ACC and B
101 ACC or B
110 ACC xor B
111 ACC not A
CLOCKの立ち上がりエッジ同期
入力E=1のときだけALU出力をACCに書き込み

│ ┌─────────┐
│ │ ┌─┐ ┌──┐│
│ └→┤A│ │A ││
│B  >L>→┤C ├┴→
│──→┐U│ │C │
│   └┬┘ └┬┬┘
│CNT ↑   ↑↑
│────┘   ││
│E       ││
│────────┘│
│CLOCK    │
│─────────┘

累算式演算装置の記述例——————————————————

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity ALU_ACC is
    port (    A:out        std_logic_vector(15 downto 0);
            B:in        std_logic_vector(15 downto 0);
            CNT:in        std_logic_vector(2 downto 0);
            CLOCK, E:in    std_logic);
end ALU_ACC;

architecture Behavioral of ALU_ACC is
    signal    ACC:    std_logic_vector(15 downto 0);
begin
    A<=ACC;
    process(CLOCK)
    begin
        if CLOCK'event and CLOCK='1' then
            if E='1' then
                case CNT is
                    when "000" => ACC<=(15 downto 0);
                    when "001" => ACC<=B;
                    when "010" => ACC<=ACC+B;
                    when "011" => ACC<=ACC-B;
                    when "100" => ACC<=ACC and B;
                    when "101" => ACC<=ACC or B;
                    when "110" => ACC<=ACC xor B;
                    when "111" => ACC<=not ACC;
                    when others => null;
                end case;
            end if;
        end if;
    end process;
end Behavioral;

_◇ALU(ステータスレジスタ含む)

※加減算、論理演算、シフト演算
※演算結果のステータス
⇒メモリアドレス生成のための演算とデータ演算の区別

※制御コードによって各種演算機能モジュールを選択するセレクタ

設計例)16ビット、2の補数表示整数演算装置
4ビット演算機能選択:FUNC
0000 A+B->C
0001 A-B->C
0010 B+1->C
0011 B-1->C
0100 A+B+CY->C
0101 A-B-CY->C
0110 A and B->C
0111 A or B->C
1000 A xor B->C
1001 not A->C
1010 A sll N -> C
1011 A srl N -> C
1100 A sla N -> C
1101 A sra N -> C
1110 A rol N -> C
1111 A ror N -> C

データ演算/アドレス演算動作識別:E
E=0アドレス演算(ステータスは変更なし)

ステータス信号:
OVER_FLOW(演算結果がオーバフロー)
ZERO(演算結果が0)
CARRY(桁上げ)
SIGN(BUS_CのMSBのコピー)

4ビットシフトビット数選択:AUX

レジスタへの書き込みはCLOCKの立ち上がり同期

BUS_A ┌─┐
─────→┤A├→OVER_FLOW
│L├→ZERO
│U├→CARRY
│ ├→SIGN
> >─→BUS_C
│ ├───┐
│ ├──┐│
BUS_B │ ├─┐││
─────→┤ ├┐│││
└─┘↑↑↑↑
FUNC ────┘│││
AUX ─────┘││
CLOCK──────┘│
E ───────┘

作業信号W,X,Yは17ビット。桁上げ、オーバーフローを知るため
X,Yは入力の最上位に0を加えて正整数化したもの。Wは演算の途中結果
⇒16ビットの2の補数表示整数をA,B
⇒A,Bの最上位に符号桁A(15),B(15)を付加して17ビットに拡張した数をA’,B’
⇒17ビット演算C’=A’±B’において
C’(16)≠C'(15)であるならば16ビット演算A±Bはオーバーフロー
⇒C'(16)については次の関係がある
C'(16)=A'(15)±B'(15)±(A±Bの桁上げ)
=A(15) xor B(15) xor (A±Bの桁上げ)
⇒W(16)=(A±Bの桁上げ)
⇒論理演算 C_16 xor W(15)でオーバーフローの検出ができる

※case文で代入を省く⇒前の値の保持とみなされる
⇒ラッチが生成される

ALUの記述例—————————————————————–

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity ALU is
    port (    RESET, CLOCK, E:in std_logic;
            FUNC, AUX:in std_logic_vector(3 downto 0);
            CARRY, SIGN, ZERO, OVER_FLOW:out    std_logic;
            BUS_A, BUS_B:in std_logic_vector(15 downto 0);
            BUS_C:out std_logic_vector(15 downto 0) );
end ALU;

architecture Behavioral of ALU is
    signal    W, X, Y:std_logic_vector(16 downto 0);
    signal    OVF, CRY, SGN, ZR, C_16:std_logic;
begin
    OVER_FLOW<=OVF;
    CARRY<=CRY;
    SIGN<=SGN;
    ZERO<=ZR;
    BUS_C<=W(15 downto 0);
    X<='0' & BUS_A;
    Y<='0' & BUS_B;
    C_16<=BUS_A(15) xor BUS_B(15) xor W(16);
    process(RESET, CLOCK) begin
        if RESET='1' then
            OVF<='0';
            CRY<='0';
            SGN<='0';
            ZR<='0';
        elsif CLOCK'event and CLOCK='1' then
            if E='1' then
                OVF<=C_16 xor W(15);
                CRY<=W(16);
                SGN<=W(15);
                ZR<=not(W(15) or W(14) or W(13) or W(12) or W(11) or W(10) or
                        W(9) or W(8) or W(7) or W(6) or W(5) or W(4) or W(3)
                        or W(1) or W(0));
            end if;
            case FUNC is
                when "0000" => W<=X+Y;
                when "0001" => W<=X-Y;
                when "0010" => W<=Y+1;
                when "0011" => W<=Y-1;
                when "0100" => W<=X+Y+CRY;
                when "0101" => W<=X-Y-CRY;
                when "0110" => W<=X and Y;
                when "0111" => W<=X or Y;
                when "1000" => W<=X xor Y;
                when "1001" => W<=not X;
                when "1010" => W(16)<='0';
                    W(15 downto 0)<=to_stdlogicvector(
                        to_bitvector(BUS_A) sll conv_integer(AUX));
                when "1011" => W(16)<='0';
                    W(15 downto 0)<=to_stdlogicvector(
                        to_bitvector(BUS_A) srl conv_integer(AUX));
                when "1100" => W(16)<='0';
                    W(15 downto 0)<=to_stdlogicvector(
                        to_bitvector(BUS_A) sla conv_integer(AUX));
                when "1101" => W(16)<='0';
                    W(15 downto 0)<=to_stdlogicvector(
                        to_bitvector(BUS_A) sra conv_integer(AUX));
                when "1110" => W(16)<='0';
                    W(15 downto 0)<=to_stdlogicvector(
                        to_bitvector(BUS_A) rol conv_integer(AUX));
                when "1111" => W(16)<='0';
                    W(15 downto 0)<=to_stdlogicvector(
                        to_bitvector(BUS_A) ror conv_integer(AUX));
                when others => W<=(others=>'X');
            end case;
        end if;
    end process;
end Behavioral;

◆パッケージ

定数定義、型変換関数、新演算子の定義、function,
procedure, componentなどを定義

_◇ユーザ作成パッケージ

※すべて work というライブラリ名となる

use work.パッケージ名.all;

_◇package宣言

①パッケージ宣言部

package <パッケージ名> is
宣言部;
end <パッケージ名>

※宣言部に含まれるもの
定数宣言
タイプ宣言
グローバル信号
ファイル
プロシージャ
ファンクション
コンポーネント

②パッケージ本体

package body <パッケージ名> is
本体
end <パッケージ名>

※本体に含まれるもの
ローカル定数
ローカルタイプ
ローカルファイル
プロシージャ本体
ファンクション本体

◆標準パッケージ

_◇ieee.std_logic_1164

※rising_edge
立ち上がりエッジを検出する関数

_◇ieee.std_logic_unsigned
符号なし演算用

※shift_left

※shift_right

※use IEEE.STD_LOGIC_UNSIGNED.ALLを追加することで
①カウントアップに Q+1 のような記述が使用できる
②if文の条件に Q=9 のような10進整数が使用できる
注)vectorに対する即値操作には使えない
Q<=”0000″ とすべきところをQ<=0とはできない
case Q is when “1001” => Q<=”0000″;を
case Q is when 9とはできない

⇒2進数記述でビット長が長いと記述を誤りやすい

_◇ieee.std_logic_signed
符号付き演算用

_◇ieee.std_logic_arith
符号付符号なし混在演算用

_◇textio
ファイルアクセス用

_◇std_logic_textio
textioの補足パッケージ

_◇標準変換関数

※conv_std_logic_vector(値, ビット幅)
integerの値からstd_logic_vectorへの変換

※conv_integer(値)
std_logic_vectorかintegerへの変換

◆RTL記述スタイル

_◇RTL記述のスタイル
論理合成を前提とした記述

_◇RTL記述:簡単な組み合わせ回路
1行で記述できるようなものは、同時処理代入文で既述する。

同時処理代入文例)
na <= not( in1 and in2);
2入力NAND
q <= d1 when sel=’1′ else d0;
セレクタ
carry <= ‘1’ when cnt10=”1001″ else ‘0’;
桁上がり信号
sum <= a + b;
加算回路

_◇RTL記述:複雑な組み合わせ回路
process文により記述する
processの引数となるセンシビティリストにある信号が変化したとき内部が実行される

例)
library IEEE;
use IEEE.std_logic_1164.all;

entity dec2to4 is
port(d: in std_logic_vector(1 downto 0);
q: out std_logic_vector(3 downto 0);
);
end dec2to4;

architecture RTL of dec2to4 is
begin
process( d ) begin
case d is
when “00” => q<= “0001”;
when “01” => q<= “0010”;
when “10” => q<= “0100”;
when “11” => q<= “1000”;
when others => q<= “XXXX”;
end case;
end process;
end RTL;

_◇RTL記述:順序回路
process文を使って記述する

①同期回路
センシティビティ・リストにはクロックのみ

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

entity counter is
port(ck, res: in std_logic;
q: out std_logic_vector(3 downto 0);
);
end counter;

architecture RTL of counter is

signal q_reg: std_logic_vector( 3 downto 0);
begin
q <= q_reg;
process( ck ) begin
if ck’event and ck=’1′ then
if res=’1′ then
q_reg <= “0000”;
else
q_reg <= q_reg + “1”;
end if;
end if;
end process;
end RTL;

②非同期回路
クロックと非同期制御信号
(例えば非同期リセット)

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

entity counter is
port(ck, res: in std_logic;
q: out std_logic_vector(3 downto 0);
);
end counter;

architecture RTL of counter is

signal q_reg: std_logic_vector( 3 downto 0);
begin
q <= q_reg;
process( ck, res ) begin
if res=’1′ then
q_reg <= “0000”;
elsif ck’event and ck=’1′ then
q_reg <= q_reg + “1”;
end if;
end process;
end RTL;

③同期回路のもう1つの記述方法
センシティビティ・リストのないprocess文を使う
⇒無限ループ
⇒wait untilによりクロックの立ち上がりを待ち、処理をおこなう。
⇒これでも論理合成可能

例)
process begin
wait until ck’event and ck=’1′;
if res=’1′ then
q_reg <= “0000”;
else
q_reg <= q_reg + “1”;
end if;
end process;

◆テストベンチ

_◇テストベンチの構造

①entity, architecture宣言
②テスト用信号の宣言
③被テストモジュールのインスタンシェイション
④スティミュラス

※追加機能
仮想ディスプレイ
エラー検出機能など

例)
entity エンティティ名 is
ポート等の記述
end エンティティ名;

architecture アーキテクチャ名 of エンティティ名 is
各種宣言
begin
機能の記述
end ;

configuration コンフィギュレーション名 of エンティティ名 is
for アーキテクチャ名
end for;
end コンフィグレーション名;

_◇テストベンチ記述の注意点

①入出力は無し
②テスト用信号は signal 定義
③アンダーテスト回路を呼び出し
④クロック生成
例)
constant CLOCKPERIOD : TIME := 10nS;

clk <= not clk after CLOCKPERIOD / 2;

または

GEN_CLK: process begin
wait for (CLOCKPERIOD /2)
clk <= ‘1’;
wait for (CLOCKPERIOD /2)
clk <= ‘0’;
end prcess;

※デューティサイクルを指定できる記述
process begin
CLOCKLOOP : loop
clk <= ‘0’;
wait for (PERIOD – (PERIOD * DUTY_CYCLE));
clk <= ‘1’;
wait for (PERIOD * DUTY_CYCLE);
end loop CLOCKLOOP;
end process

⑥process内にテストベクタ定義
⇒wait for などでタイミングを記述
⇒複数あっても良い

※絶対値で遅延を指定
例)
STIM: process begin
信号<= ‘1’;

wait for 10ns;
信号<= ‘0’;
end process

※相対的にクロック数を数えてスティミュラスを与える
process (clock) begin
if rising_edge(clock) then
count <= count + 1;
end if

count値に応じた印加
end process

※スティミュラスは関係のあるもの毎に分割した方が見通しが良くなる

※塊で繰り返されるスティミュリは procedureでサブルーチン化
process文の中で定義して、後ろで呼び出す

※不要なデータまでI/Oさせると速度が遅くなる

_◇シミュレーション結果の表示

std_texio
⇒i/o リダイレクション

◆TIPS

_◇ビット選択

※ビット選択で記述できるのはinteger型のみ
⇒std_logic_vector型ではビット選択できない
⇒std_logic_unsignedで用意されている型変換関数conv_integerを使うと変換可能

_◇others

(others=> ‘0’)
信号のビット幅を変更しても記述を変更する必用のない0代入につかえる。
‘1’もあり。

例)
q_vec <= (others=> ‘0’);

_◇トライステート

トライステート条件時に、出力信号線に’Z’を代入すればよい

※ターゲット・デバイスによっては実装できない

※VHDLにはプルアップ抵抗の記述がない
⇒1つの出力がトライステート状態でも、他の出力がバリッドな値を出し、該当信号自体は’Z’にならないようにする

例)
q <= ドライブ時の値 when g=’1′ else ‘Z’;

※双方向の信号などではトライステート必須

_◇両エッジ

2個のprocess文となる

_◇textio

ROMデータのSIM用読み込みなどにつかえる

_◇Xilinx Core Generatorモデル
configuration文でリンクされる

_◇メモリ初期化

FILE meminitfile: TEXT IS IN “<design.mif>”;