• 検索結果がありません。

卒 業 研 究 報 告

N/A
N/A
Protected

Academic year: 2021

シェア "卒 業 研 究 報 告"

Copied!
122
0
0

読み込み中.... (全文を見る)

全文

(1)

業 研 究 報 告

題 目

VHDL を用いた電卓の設計と試作

指 導 教 員 橘 昌良 助教授 報 告 者 学籍番号:1040183 氏名:遠藤 彬浩

平成 16 年 2 月 17 日

(2)

高知工科大学

電子・光システム工学科

目次

1 章 はじめに・・・・・・・・・・・・・・・・・・・・・・1

2 章 2 進数での演算・・・・・・・・・・・・・・・・・・・2

2.1 2 進数での正と負

・・・・・・・・・・・・・・・・・・・2

2.1.1 1 の補数

・・・・・・・・・・・・・・・・・・・・2

2.1.2 2 の補数

・・・・・・・・・・・・・・・・・・・・2

2.2 加算

・・・・・・・・・・・・・・・・・・・・・・・・3

2.2.1 1ビットでの加算

・・・・・・・・・・・・・・・・3

2.2.2 複数ビットでの加算

・・・・・・・・・・・・・・・7

2.3 減算

・・・・・・・・・・・・・・・・・・・・・・・・7

2.3.1 1ビットでの減算

・・・・・・・・・・・・・・・・7

2.3.2 複数ビットでの加算

・・・・・・・・・・・・・・・8

2.4 乗算

・・・・・・・・・・・・・・・・・・・・・・・11

2.5 除算

・・・・・・・・・・・・・・・・・・・・・・・13

2.5.1 加え戻し法

・・・・・・・・・・・・・・・・・・13

2.5.2 引き放し法

・・・・・・・・・・・・・・・・・・14

3 章 演算回路の設計・・・・・・・・・・・・・・・・・・17

3.1 演算に必要な回路

・・・・・・・・・・・・・・・・・・17

3.2 レジスタの設計

・・・・・・・・・・・・・・・・・・・18

(3)

3.3 制御回路の設計

・・・・・・・・・・・・・・・・・・・19

3.4 加算回路の設計

・・・・・・・・・・・・・・・・・・・20

3.5 減算回路の設計

・・・・・・・・・・・・・・・・・・・22

3.6 乗算回路の設計

・・・・・・・・・・・・・・・・・・・23

3.7 除算回路の設計

・・・・・・・・・・・・・・・・・・・25

4 章 VHDL による電卓の設計・・・・・・・・・・・・・・27

4.1 電卓に必要な回路の設計

・・・・・・・・・・・・・・・・27

4.1.1 8 桁の BCD 入力を 2 進数で保存する回路の設計

・・・・27

4.1.2 同期化回路の設計

・・・・・・・・・・・・・・・・28

4.1.3 結果格納用レジスタの設計(REG_B)

・・・・・・・・29

4.1.4 演算出力切り替え用レジスタの設計(ASMD_SEL)

・・・29

4.1.5 状態遷移機械の設計(STATE)

・・・・・・・・・・・29

4.1.6 電卓のブロック図

・・・・・・・・・・・・・・・・31

4.2 VHDL による電卓の設計

・・・・・・・・・・・・・・・32

4.3 シミュレーション結果

・・・・・・・・・・・・・・・・55

5 章 おわりに・・・・・・・・・・・・・・・・・・・・・61

謝辞・・・・・・・・・・・・・・・・・・・・・・・・・・・62

参考文献・・・・・・・・・・・・・・・・・・・・・・・・・63

付録

VHDL のソース・・・・・・・・・・・・・・・・・・・64

(4)

1章 はじめに

現代社会では身の回りのものを見渡すと、多くのものがディジタル技術を使 用している。パソコン、携帯電話、だけでなく家電製品など様々なものに、CPU、 グラフィックスチップ、サウンドチップなどが組み込まれている。その内部に は複雑な回路があり、高速な演算によって処理が行われている。こうしたディ ジタル技術の進歩とともに集積度も向上してきたが、回路は複雑化してきた。 それ故に設計は膨大な時間と手間がかかる作業になってきている。そうした中 で集積回路を比較的簡単になおかつ短期間で設計する手段としてハードウェア 記述言語(Hardware Description Language : HDL)が生み出された。

ここでは、演算処理を機能の基本とする電卓をハードウェア記述言語の中の 一つであるVHDL(VHSIC HDL)を使って回路を設計、シミュレーションするこ とにより、2進数での演算の基本、そのために必要な回路、ハードウェア記述 言語での回路設計に対する知識と経験をつむ。 本論文の第1章ではここまでの研究の経緯を述べる。第2章では2進数での演算 の基礎を述べる。第3章では、VHDLで設計する回路の元となる演算回路を設計 する。第4章では、第3章で設計した演算回路に他の複数の機能を付与してVHDL で設計するとともに、シミュレーションを行いその結果について報告する。

(5)

2 章 2進数での演算

2.1 補数

2進数の負数は多くの場合、補数(complement)を使用して表現される。歩 数には1の補数(1’s complement)と2の補数(2’s complement)があるが、 一般的に用いられているのは2の補数である。どちらの補数も最上位ビット (MSB)(Most Significant Bit)で符合を表し、‘1’で負数、‘0’で正数、残 りのビットで値を表す。 補数にするということは数値の符号の反転を意味するので、加算操作で減算 が行えることが最大のメリットとなる。

2.1.1

1 の補数

1の補数は各ビットを反転させることで求めることができる。 例として“01011”の1の補数を求めてみる。まずこの値は MSB が‘0’な ので正数を表し、下位4ビットで値を表している。この2 進数は10進数で“11” なので、5 ビットで“+11”を表している。 各ビットを反転させることで 1 の補数を求めると、“10100”となり 10 進数 で“−13”を意味する。 例からわかるように、補数表現での負数は正数に変換しないと値を求めるこ とが難しいデメリットがある。

2.1.2

2 の補数

2 の補数を求める方法は 2 通りある。 1 つ目は 1 の補数を求め、その値に 1 を加える。つまり、値を反転させてから 最下位ビット(LSB)(Least Significant Bit)に‘1’を加えるだけである。

2 つ目の方法は LSB から MSB へ見ていき、最初の‘1’が出てくるビットま ではそのままにして置き、それ以降のビットは反転させる。

例として“01010”を 2 つの方法で求めてみる。この 2 進数を 10 進数で表す と“+10”である。1 つ目の方法で 2 の補数化は、1 の補数を求めてから 1 を加 えればよいので、“01010”→“10101”として‘1’を加えると“10110”とな

(6)

り、5 ビットで“−10”を表している。 2 つ目の方法では LSB から MSB 方向へ見て行き最初の‘1’が出てくるまで ビットをそのままにするので、下位2 ビット目の‘1’までをそのままにし、残 りの上位3 ビットを反転させる。すると“01010”→“10101”となり、1 つ目 の方法の値と等しくなる。

2.2 加算

2.2.1

2 進数での加算

2進数1 ビットでの加算の組み合わせは次の4通りになる。 1 ) ( 0 1 1 1 0 1 1 1 0 0 0 0    キャリー carry = + = + = + = + 最初の3つは簡単なので説明は不要と思われる。最後の1つは和が0になり、 上位ビットへの桁上げ(キャリー)が発生し、上位ビットへ1を繰り上げる。 1 ビットの加算を行うのには半加算器を用いる。 上の4 通りの組み合わせを元に被加数を「A」、加数を「B」、和を「SUM」、 キャリーを「CY_OUT」として真理値表を作ると図 2.1 となる。 表2.1 半加算器の真理値表 A B SUM CY_OUT 0 0 0 0 0 1 1 0 1 0 1 0 1 1 0 1

(7)

この真理値表から論理式を導き出すと B A OUT CY B A SUM • = ⊕ = _ となり、回路図は図2.2(a)となる。また、回路記号は(b)のように表記される。 A B CY_OUT SUM A B CY_OUT SUM

HA

図2.1(a) 半加算器の回路図 (b) 半加算器の回路記号

2.2.2 複数ビットでの加算

1 ビットの加算では下位桁からのキャリーがないが、複数ビットの加算では下 位桁からのキャリーも考慮しなければならないので、次の 8 通りの組み合わせ になる。 1 1 1 1 1 1 0 0 1 1 1 0 1 0 1 1 0 0 1 1 0 1 1 0 1 0 1 0 1 1 0 0 0 0 0 0                 carry carry carry carry = + + = + + = + + = + + = + + = + + = + + = + + 下位桁からのキャリーを考慮した加算を行うには全加算器を用いる。 半加算器は下位けたからのキャリーを加算することができなかった。全加算

(8)

器は下位桁からのキャリーを含めた計算が行えるようにしたものである。入力 と出力の結果は8 通りあるので、それをもとに被加数を「A」、加数を「B」、下 位けたからのキャリーを「CY_IN」、和を「SUM」、上位桁へのキャリーを 「CY_OUT」とした真理値表を図 2.3 に示す。

表2.2 全加算器の真理値表

A B CY_IN SUM CY_OUT 0 0 0 0 0 0 0 1 1 0 0 1 0 1 0 0 1 1 0 1 1 0 0 1 0 1 0 1 0 1 1 1 0 0 1 1 1 1 1 1 この真理値表を元に論理式を導き出すと B A IN CY B IN CY A OUT CY IN CY B A SUM • + • + • = ⊕ ⊕ = _ _ _ _ となり、回路図は図2.4(a)となる。また、回路記号は(b)のように表記される。 A B CY_OUT SUM CY_IN A B CY_IN CY_OUT SUM

FA

(9)

図 2.2(a) 全加算器の回路図 (b) 全加算器の回路記号 全加算器を計算したいビット数だけつなげることにより任意のビット数の加 算が可能になる。図2.5 に 4 ビットの加算回路を示す。この回路では LSB にも 全加算器を使用しているが、「Cin」に入力がない場合は‘0’に固定しておく。 この回路ではビットの数だけ全加算器を使用し、すべてのビットの加算を同時 に行っているので、並列加算回路と呼ばれている。これに対して、全加算器を1 つだけ使用して被加数「A」、加数「B」をシフトレジスタで制御することで、1 ビットずつ演算を繰り返しながら加算を行う回路を、直列加算回路と呼ぶ。直 列加算回路の場合、全加算器が1 つで済むので回路は簡単化されるが、1 ビット ずつ演算を繰り返しながら加算を行うので演算時間が長くなってしまう。その ため、現在ではほとんど使用されていない。 A B CY_IN CY_O UT SUM

FA3

A B CY_IN CY_O UT SUM

FA2

A B CY_IN CY_O UT SUM

FA1

A B C Y_IN CY_O UT SUM

FA0

A3 B3 A2 B2 A1 B1 A0 B0 Cin S0 S1 S2 S3 Cout C Y2 C Y1 C Y0 図 2.3 4 ビット並列加算回路

(10)

2.3 減算

減算の仕組みは加算とほとんど同じであり説明は同じになる。また、減算は 減数を2の補数にして加算することで行うことができる。

2.3.1

1 ビットでの減算

2 進数 1 ビットでの減算の組み合わせは次の4通りになる。 0 1 1 1 0 1 1 ) ( 1 1 0 0 0 0 = − = − = − = −     ボロー borrow 2つ目以外は加算と同じく簡単なので説明は不要だと思われる。2つ目では “−1”としたいところだが、ここでは上位桁からの借りが必要となり、これを ボロー(borrow)と呼ぶ。 1 ビットでの減算を行うには半減算器を用いる。 上の4 通りの組み合わせを元に、被減数を「A」、減数を「B」、差を「DIF」 ボローを「BR_OUT」として真理値表を作ると図 2.6 となる。 表2.3 半減算器の真理値表 A B DIF BR_OUT 0 0 0 0 0 1 1 1 1 0 1 0 1 1 0 0 この真理値表から論理式を導き出すと

(11)

B A OUT BR B A DIF • = ⊕ = _ となり、回路図は図2.7(a)となる。また、回路記号は(b)のように表記される。 A B DIF BR_OUT A B BR_OUT DIF

HS

図2.4(a) 半減算器の回路図 (b) 半減算器の回路記号

2.3.2 複数ビットでの減算

1 ビットの減算では下位桁からの桁借りがないが、複数ビットの減算では下位 桁からの桁借りも考慮しなければならないので、次の 8 通りの組み合わせにな る。 1 1 1 1 1 0 0 1 1 0 1 0 1 1 0 0 1 1 0 1 1 0 1 1 0 1 0 1 1 1 0 0 0 0 0 0                     borrow borrow borrow borrow = − − = − − = − − = − − = − − = − − = − − = − − 下位桁からのボローを考慮した減算を行うには全減算器を用いる。 半減算器は下位けたからのボローを減算することができなかった。全減算器 は下位桁からのボローを含めた計算が行えるようにしたものである。入力と出

(12)

力の結果は上の8 通りあるので、それをもとに被減数を「A」、減数を「B」、下 位けたからのボローを「BR_IN」、差を「DIF」、上位桁へのボローを「BR_OUT」 とした真理値表を図2.8 に示す。

表2.4 全加算器の真理値表

A B BR_IN DIF BR_OUT 0 0 0 0 0 0 0 1 1 1 0 1 0 1 1 0 1 1 0 1 1 0 0 1 0 1 0 1 0 0 1 1 0 0 0 1 1 1 1 1 この真理値表を元に論理式を導き出すと IN BR B IN BR A B A OUT BR IN BR B A DIF _ _ _ _ • + • + • = ⊕ ⊕ = となり、回路図は図2.9(a)となる。また、回路記号は(b)のように表記される。 A B BR_IN DIF BR_OUT A B BR_IN BR_OUT DIF

FS

(13)

図 2.5(a) 全減算器の回路図 (b) 全減算器の回路記号 全減算器を計算したいビット数だけつなげることにより任意のビット数の減 算が可能になる。図2.10 に 4 ビットの減算回路を示す。この回路では LSB に も全減算器を使用しているが、「Bin」に入力がない場合は‘0’に固定しておく。 この回路ではビットの数だけ全減算器を使用し、すべてのビットの減算を同時 に行っているので、並列減算回路と呼ばれている。これに対して、全減算器を1 つだけ使用して被減数「A」、減数「B」をシフトレジスタで制御することで、1 ビットずつ演算を繰り返しながら減算を行う回路を、直列減算回路と呼ぶ。 A B BR_IN BR_OUT DIF

FS3

A B BR_IN BR_OUT DIF

FS2

A B BR_IN BR_OUT DIF

FS1

A B BR_IN BR_OUT DIF

FS0

A3 B3 A2 B2 A1 B1 A0 B0 Bin D0 D1 D2 D3 Bout BR2 BR1 BR0 図2.6 4 ビット減算回路

(14)

2.4 乗算

2進数1ビットでの乗算は次の4通りになる。 1 1 1 0 0 1 0 1 0 0 0 0 = × = × = × = × これはAND ゲートの理論と同じである。 複数ビットの乗算の例として4ビットの乗算過程を図1.1 に示す。 まず、被乗数に乗数のLSB を掛け、部分積を得る。それを MSB まで繰り返 す。部分積は10進数での計算と同じで左に1ビットずつシフトさせる。これ らの部分積を加算することで複数ビットの乗算ができる。被乗数を「X」、乗数 を「Y」、積を「Z」とし、これを並列加算器と AND ゲートを組み合わせて回路 化したものが図2.12 となる。

1010

×1011

1010

1010

0000

1101110

1010

図2.7 2進数の乗算

(15)

4ビット並列加算回路 4ビット並列加算回路 4ビット並列加算回路 S0 S1 S2 S3 Cout S0 S1 S2 S3 Cout S0 S1 S2 S3 Cout X0 X1 X2 X3 Y0 Y1 Y2 Y3 Z3 Z4 Z5 Z6 Z7 Z2 Z1 Z0 図2.8 4 ビット乗算回路

(16)

2.5 除算

2 進数の除算の基本は 10 進数のときと同じで、比較と減算とシフトを繰り返 すことによりできる。除算方法の計算過程を図2.13 に示す。 まず、被除数の上位4 ビットの“1100”は除数“1101”より小さいため‘0’。 被除数の上位 4 ビット“1100”に 5 ビット目の‘1’を加え、除数“1101”で 割り‘1’。部分剰余“1100”に被除数の次のビット‘0’を加え、除数“1101” で割り‘1’。部分剰余“1011”に被除数の次のビット‘1’を加え、除数“1101” で割り‘1’。部分剰余“1010”に被除数の次のビット‘1’を加え、除数“1101” で割り‘1’。“10101”−“1101”により剰余が“1000”となる。 この方法は被除数と除数を比較し、その結果によって減算を行うため、回路 を組むときに比較回路と減算回路が必要となってしまう。そこで、とりあえず 減算を行い、その結果によって対応を変える方法が加え戻し法と引き放し法で ある

11001011

1101

01111

1101

11000

1101

10111

1101

10101

1101

1000

図2.9 2 進数の除算

2.5.1 加え戻し法

加え戻し法とは、被除数から除数を減算し、その結果がマイナスであれば再 び除数を加算し、「0」またはプラスであれば加算は行わず、そのまま次のビッ トの演算を行う方法である。 この方法で“10111000”÷“1011”を行ったものを図 2.14 で示す。

(17)

10111000 1011 -) 0000 + '1' -) 00011011 0110 1011 +) ボローあり 0001 - '0' 0010 1011 0111 1011 0010 -) +) ボローあり - '0' 0100 1011 1001 1011 0100 -) +) ボローあり - '0' 1000 1011 -) 1101 1011 1000 +) ボローあり - '0' 剰余 MSB LSB 図2.10 加え戻し法

2.5.2 引き放し法

引き放し法とは、被除数から除数を減算したときの結果がマイナスの時には 除数を加算し、次のビットの演算の減算を同時に行う方法である。 2.5.1 の加え戻し法で、結果がマイナスの場合に除数を加算するという操作を、 被除数を「A」、除数を「B」として考えると、 B B A− + となる。そして、次のビットの計算のために左に 1 ビットシフトし、再び除数 を減算する。この時、左に1 ビットシフトするということは、2 進数では 2 倍す ることと等しいため、 B B B A− + )×2− (

(18)

となる。これを変形すると、 B B A B B A B B B A B B B A + × − = + − = − + − = − × + − 2 ) ( 2 2 2 2 2 2 ) ( となる。つまり、減算の結果がマイナスのときには、次のビットで減算すると きに除数を加算すればよいことになる。この方法では、加え戻しという無駄な 加算操作を行わないので、演算時間を短縮することができる。 引き放し法の例として図2.15(a)に過程を示す。 まず、被除数の“10111100”の上位 4 ビット“1011”に 1 個‘0’を付け加 える。(‘0’を 1 個付け加える理由は、確実にボロー・キャリーを発生させるた め である。)上位4 ビットに‘0’を付け加えた“01011”から除数の“1011” を減算する。その結果ボローなしなので、商を‘1’となり、これが商の MSB となる。 減算結果に次のビットを付け加え、再び減算する。今度はボローが発生した ので、商を‘0’とする。 減算結果がマイナスだったので、減算結果に次のビットを付け加え、加算を 行う。結果、キャリーが発生しないので加算結果はまだマイナスのままであり、 商は‘0’とする。 加算の結果がまだマイナスなので、このビットでも加算を行う。結果にキャ リーが発生していないので、まだマイナスのままであり、商は‘0’とする。 まだマイナスなので、このビットでも加算を行う。結果にキャリーが発生し ているので、商は‘1’となり、これが商の LSB となる。 したがって、商は“10001”、剰余は“0001”となる。 引き放し法では、商の LSB が‘0’の場合には剰余がマイナスになってしま うので、除数を加え戻す必要がある。その例を図2.15(b)に示す。 表2.5 に引き放し法の除算の手順を示す。

(19)

010111100 1011 -) 00000 + '1' -)000011011 10110 ボローあり - '0' 01101 1011 11000 +) キャリーなし - '0' 10000 1011 11011 +) キャリーなし - '0' 10110 1011 +) 100001 キャリーあり - '1' 剰余(4ビット) ボローなし MSB LSB 010111000 1011 -) 00000 + '1' -) 00001 1011 10110 ボローあり - '0' 01100 1011 10111 +) キャリーなし - '0' 01110 1011 11001 +) キャリーなし - '0' 10010 1011 +) 11101 キャリーなし - '0' 剰余(4ビット) ボローなし 1011 +) 101000 MSB LSB 図2.11(a) 引き放し法 (b)商の LSB が‘0’の場合 表2.5 引き放し法の手順 加算・減算 キャリー・ボロー 答 商 次の演算 加算 0 − 0 加算 加算 1 + 1 減算 減算 0 + 1 減算 減算 1 − 0 加算

(20)

3 章 演算回路の設計

3.1 演算に必要な回路

演算回路を設計するためには、入力するビットと演算結果を記憶するための レジスタ(register)、各演算に必要な演算器、演算開始と終了を行うための制 御回路が必要になる。図3.1 に演算回路のブロック図を示す。

入力用レジスタ

入力用レジスタ

演算器

結果用レジスタ

制御回路

操作信号入力

数値入力

結果出力

演算回路

数値入力

図3.1 演算回路のブロック図

(21)

3.2 レジスタの設計

使用するレジスタとして、普通のレジスタとシフトレジスタの 2 つが必要と なった。シフトレジスタは1 ビットシフトするものと、4 ビットシフトするもの を設計する。 1 ビットシフトのレジスタは、乗算の部分積を求める時と除算の商を記憶させ るための時の、2 つの場合に必要になる。乗算の場合は出力側が 1 ビットで、除 算の場合は入力側が1 ビットとなる。 4 ビットシフトのレジスタは、加算と減算の時に使用する。入力されたビット と前回の結果を記憶するレジスタは、出力側が 4 ビットで、結果を記憶するレ ジスタは、入力側が5 ビットとなる。 図3.2 にロード機能付き 4 ビットシフトの 12 ビットレジスタの回路図を示す。 0D 1D 2D 3D 0Q 1Q 2Q 3Q 0D 1D 2D 3D 0Q 1Q 2Q 3Q 0D 1D 2D 3D 0Q 1Q 2Q 3Q EN RESET LO AD EN RESET LO AD EN RESET LO AD LOAD EN RESET 入 力 出 力 CLK CLK CLK CLK 4ビ ットシ フ トの 12ビ ットレ ジ ス タ 図3.2 4 ビットシフトの 12 ビットレジスタの回路図

(22)

「LOAD」は入力をセットするための信号、「EN」は入力に入っているビッ トを記憶させるかどうかを可能にする信号、「RESET」は非同期のリセット信 号。入力は「LOAD」に‘1’が入ったときだけにセットされ、「LOAD」が‘0’ のときは、「EN」が‘1’になってもセットされない。 図3.2 は出力側が 4 ビットであるが、入力側を 5 ビットにするには一番上の レジスタを5 ビットレジスタに変え、入力と出力を逆にすればよい。1 ビットの 入力、出力についても同じで、この場合は 1 ビットのレジスタをつなげればよ い。

3.3 制御回路の設計

制御回路の役割として、演算開始の入力が入ったときから演算終了までの間 に‘1’を出力する機能が必要になる。 演算終了を知るにはシフトの回数をカウントすればよいので、まずはカウン タが必要になる。さらに、演算開始から終了までの間だけ‘1’を出力するため には、図3.3 に示す状態遷移が必要になる。

0

1

演算開始入力=’1’ カウンタ出力=’X’ 演算開始入力=’X’ カウンタ出力=’1’ 演算開始入力=’X’ カウンタ出力=’0’ 演算開始入力=’0’ カウンタ出力=’X’ 図3.3 制御回路の状態遷移図 この状態遷移図から、JK フリップフロップの J に演算開始入力を、K にカウ ンタの出力を入れれば、Q の出力がこの状態遷移図と合致する。 これらのことから設計した制御回路の回路図を図3.4 に示す。

(23)

JK フリップフロップ カウンタ J K Q EN CLR 演算可能出力 演算開始入力 ’1’出力回路 制御回路 図3.4 制御回路の回路図 演算開始入力をカウンタのクリア端子に接続したのは、演算を何度も行える ようにするためである。

3.4 加算回路の設計

加算回路には全加算器を並べただけの並列加算回路と、シフトレジスタを使 用する直列加算回路があるが、本研究では、4 ビットの並列加算回路と 4 ビット シフトのシフトレジスタを使用した加算回路を設計する。 加算回路のブロック図を図3.5 に示す。

(24)

4ビットシフトの シフトレジスタ 4ビットシフトの シフトレジスタ 4ビット並列 加算回路 4ビットシフトの シフトレジスタ 制御回路

被加数

加数

加算開始

加算回路

リセット

クロック

図3.5 加算回路のブロック図 リセットは非同期リセットであり、そのほかの入力は同期入力とする。加算 開始入力は被加数用と加数用レジスタのロード端子に、結果用レジスタのクリ ア端子に接続されている。被加数と加数用レジスタは下位4 ビットが 4 ビット 並列加算回路に接続されている。結果格納用レジスタは上位5 ビットに 4 ビッ ト並列加算回路の結果の5 ビットが接続され、MSB は 4 ビット並列加算回路の キャリーインに接続されている。結果用レジスタのクリア端子に加算開始入力 が接続されているのは、2 回目以降の加算のときに MSB が‘1’の場合に計算 結果がおかしくなるのを防ぐためである。 動作としては加算開始の入力が入ると、4 ビットのシフトレジスタに被加数と 加数をロード、制御回路のカウンタと結果用レジスタがクリアされ演算開始に なる。そしてクロックごとに被加数と加数の下位 4 ビットが加算され、和の 5

(25)

ビットが結果格納用レジスタの上位 5 ビットに入力される。それを被加数、ま たは加数のビット数に応じた回数のシフトが終了するまで繰り返す。

3.5 減算回路の設計

減算回路は加算とほとんど同じで、4 ビット並列加算回路を 4 ビット並列減算 回路に換えるだけで済む。 図3.6 に減算回路のブロック図を示す。 4ビットシフトの シフトレジスタ 4ビットシフトの シフトレジスタ 4ビット並列 減算回路 4ビットシフトの シフトレジスタ 制御回路

被減数

減数

減算開始

減算回路

リセット

クロック

図3.6 減算回路のブロック図

(26)

3.6 乗算回路の設計

乗算回路では被乗数はシフトする必要はないが、乗数は部分積を求めるため に 1 ビットシフトのシフトレジスタが必要になる。部分積を求めるには、被乗 数の全ビットと乗数の1 ビットとのそれぞれの AND をとればいいだけである。 図3.7 に乗算回路のブロック図を示す。 1ビットシフトの シフトレジスタ レジスタ 並列加算回路 レジスタ 制御回路

被乗数

乗数

乗算開始

乗算回路

リセット

クロック

部分積 出力回路 図3.7 乗算回路のブロック図

(27)

配線の接続は、結果用レジスタ以外は加算回路とほぼ同じになる。 結果用レジスタと並列加算回路の配線を図3.8 に、仕組みを図 3.9 に示す。 レ ジ ス タ 並 列 加 算 回 路 部 分 積 (Kビ ッ ト) N ・ ・ ・ MSB (K+1ビ ット) 0 ・ ・ ・ N-1 (Kビ ット) (Kビ ット) 1 ・ ・ ・ N (Kビ ット) N+1 ・ ・ ・ M SB 図3.8 結果用レジスタの配線図 部分積

”1011”

”01011”

”0000”

”0_1011_0000_0000”

加算回路 部分積

”1110”

”10011”

”0101”

”1_0011_1000_0000”

加算回路 図3.9 結果用レジスタの仕組み

(28)

部分積を K ビットとすると、並列加算回路からの出力は結果用レジスタの上 位K+1 ビットへ入力される。そして、結果用レジスタの上位 K ビットを並列加 算器に入力することによって、部分積の加算結果のLSB を残した上で部分積の 加算が実現できる。また、結果用レジスタの1 ビット目から K ビットを結果用 レジスタのLSB から K ビット入力することによって、部分積の加算を 1 ビット ずらして上書きすることにより積が求められる。図3.9 は K=4の場合を示して いる。

3.7 除算回路の設計

除算は除数が0の場合計算ができない。そこで、除数が0では演算開始をで きないように0の検出回路をつけておく必要がある。 本研究で設計する除算回路では、2.5.2 節で説明した引き放し法で設計する。 図3.10 に除算回路のブロック図を示す。 レジスタ セレクタ レジスタ セレクタ 加減算回路 制御回路 1ビットシフトの シフトレジスタ 除算開始 リセット クロック 除数 被除数 商 除算回路 図3.10 除算回路のブロック図

(29)

引き放し法を利用するので加減算回路を使用する。加減算器の加算・減算の 選択は、2.5.2 節にある表から決まるようにすればよい。さらに、結果用レジス タへの入力も同じようにすればよい。 被除数用レジスタについて説明する。被除数がL ビット、除数が M ビットの 場合にレジスタのビット数は、被除数のMSB と除数の LSB を合わせるために L+M−1 ビット、さらに 2.5.2 節で説しているように、確実にボローまたはキャ リーを発生させるための1 ビットを付け加えた L+M ビットとなる。 入力は演算開始入力が入ったときには被除数をロードし、演算中は加減算回 路の出力とレジスタの一部の出力を入力する。剰余の出力用にMSB は加減算器 のキャリー・ボローを入力する。セレクタの出力は 1 ビットずらし、乗算回路 のときと同じシフトするように設計する。 除算の最後で商の LSB が‘0’の場合に剰余を求めるためには、被除数用レ ジスタの値と除数の値を足す必要があるが、そのためには除数の下位に‘0’を 付け加えなければならない。その理由は、剰余を求めるときにシフト動作は必 要ないが、この回路ではそれができないからである。 したがって、加減算回路には、剰余を求めるときは除数を 1 ビット上位にシ フトした値を、それ以外のときは除数をそのまま入力する。それを実現するた めに、セレクタは M+1 ビットで除数の下位に‘0’を付け加えた入力と、除数 の上位に‘0’を付け加えた入力にする。 ただし、商の LSB が‘1’で終了した場合は、除数を加算する必要がないの で、加減算回路の入力値を0にする。そのために、セレクタの出力はカウンタ の‘1’出力回路の出力と商の LSB の NAND 出力との AND をとる。

(30)

4 章 電卓の設計

4.1電卓に必要な回路の設計

4.1.1

8 桁の BCD 入力を 2 進数で保存する回路の設計

10キーからの 8 桁の入力を 2 進数で保存するには、以前の保存されている 値を10 倍してから次の入力を足してやればよい。 本研究で設計する電卓は 8 桁表示とした。保存用のレジスタは入力される値 が0∼99999999 なので、2 から27 ビ ットにする。 67108864 2 99999999 134217728 26 27 = > > = 以上から、2 進数保存のために必要な回路(REGA)は ・ 10 キーからの入力を BCD に変換する回路(DEC_TO_BIN) ・ 27 ビットの保存用レジスタ(REG_A) ・ 保存されている値を10 倍するための乗算回路(CNV_MUL) ・ 10 倍された値に BCD を加算するための加算回路(cnv_adder) ・ 演算後の 10 キー再入力時に、加算回路の出力から変換回路の出力へ切り替 えるためのセレクタ(INPUT_SEL) の5個の回路が必要になる。 2 進数で保存する回路のブロック図を図 4.1 に示す。 1 0 進 数 → 2 進 数 変 換 回 路 (D E C _T O _B IN ) 2 7 ビ ッ ト レ ジ ス タ (R E G _A ) 1 0 倍 用 乗 算 回 路 (C N V _M U L ) 加 算 回 路 (c n v _a d d e r ) セ レ ク タ (IN P U T _S E L ) R E G A 1 0 キ ー 入 力 2 進 出 力 図4.1 2 進数で保存する回路のブロック図

(31)

4.1.2同期化回路の設計

10 キーからの入力は手で入力を行うの場合、非同期入力を同期入力にする回 路(syncro)が必要になる。例えば、キーの入力をそのままシフトレジスタの 入力とすると、1 回の入力でクロックの遷移回の入力が入ってしまう。そこで、 図4.2 にある回路を入力に挿入する。動作は図のようになり、スイッチからの 1 回の入力に対して1 クロック分の出力波形が生成される。 Dフリップ フロップ Q0 Dフリップ Q1 Q2 フロップ Dフリップ フロップ キー入力 クロック リセット 出力 クロック 入力 Q0 Q1 Q2 出力 図4.2 同期化回路

(32)

4.1.3 結果格納用レジスタの設計(

REG_B)

入力されるビット数が27 ビットなので、演算結果がマイナスになることを考 慮し、符号ビット分の 1 ビットを付け加える。さらに、オーバーフローの検出 のためにもう1 ビット付け加え、29 ビットで設計する。

4.1.4 演算出力切り替え用セレクタの設計(

ASMD_SEL)

各演算回路からの出力を REG_B へ入力するためのセレクタだが、切り替え のタイミングが演算開始前になった場合、REG_B の値が演算回路にロードされ る前に、切り替えた演算回路からの出力の値に変化してしまうため、切り替え は演算開始と同時か、それ以降にしなければならない。

4.1.5 状態遷移機械の設計(

STATE)

電卓はただ演算をするだけでは実現できない。累算ができるようにするには 以前に何のキーが押されたかを記憶し、それにしたがって状態を決定しなけれ ばならない。 電卓の状態は3状態あり、10 キー入力状態(DECIMAL)、演算入力状態(OPE)、 オーバーフロー状態(HALT)がある。各入力と状態によって 7 セグメント LED への出力が決まる。入力、出力、状態の関係は表4.1 のようになる。 表4.1 入出力と状態の関係 入力 LED への出力 状態 10 キー REG_A DECIMAL 演算キー REG_B OPE オーバーフロー オーバーフロー用LED HALT 各状態間の遷移は、10 キーの入力回数を数えるためのカウンタを COUNT、 演算回路への演算開始出力をASMD_SEL、演算結果の選択用セレクタの切り替 え信号を ASMD_SELECET、LED への出力切り替え用セレクタの切り替え信

(33)

号をSEL、どの演算キーが入力されたかを保存するためのレジスタを CAL とし た状態遷移図を、図4.3 に示す。 演算開始出力は同期化回路を通して出力し、演算結果選択用セレクタの切り 替え信号は、D フリップフロップを 3 つ通して遅延を調整して出力する。 10キー入力 DECIMAL SEL = 1 停止 HALT SEL = 0 演算 OPE SEL = 0 REG_A <= 0 REG_B <= 0 COUNT <= 0 ASMD <= 00 ASMD_SEL <= 0001 REG_B <= REG_B*REG_A + : CAL <= 00 - : CAL <= 01 ×: CAL <= 10 ÷: CAL <= 11 = : CAL <= 00 BR <= '1' REG_B <= 0 COUNT <= 0

REG_A <= REG_A×10 + DECI COUNT<=COUNT + 1 演算結果が オーバーフロー +,-,×,÷ C,CE 10キー +,-,×,÷,= 10キー C,CE REG_ B< -99999999 or REG_B > 99999999 BR = '0' : REG_A <= DECI COUNT <= 1 ASMD_SELECT<="0000" BR = '1' : REG_A <= DECI COUNT <= 1 ASMD_SELECT<="0000" B_RST <= '1' + : CAL <= 00 - : CAL <= 01 ×: CAL <= 10 ÷: CAL <= 11 図4.3 電卓の状態遷移図

(34)

4.1.6 電卓のブロック図

電卓のブロック図を図4.4 に示す。 10進→2進変換回路 (DEC_TO_BIN) 27ビットレジスタ (REG_A) ×10 乗算回路 (CNV_MUL) 加算回路 (cnv_adder) 演算回路 (ADD、SUB、 MUL、DIV) 29ビットレジスタ (REG_B) セレクタ (ASMD_SEL) セレクタ (lastsel) 2の補数 出力回路 (2hosu) 非同期→同期変換回路 (syncro) 状態遷移機械 (state) 2進→BCD変換回路 (bintobcd) 7セグメントデコーダ回路 (7SEG_DEC)

電卓(calc)

7セグメントLED出力 (7LED) 符号出力 (SIGN) 10キー入力 (DECIMAL) 演算キー入力 (PLUS、MINUS、KAKERU、 WARU、EQUAL、C、CE) オーバーフロー出力 (OVF) エラー出力 (ERROR_OUT) リセット (RESET) クロック (CLK) セレクタ (INPUT_SEL)

REGB

図4.4 電卓のブロック図

(35)

4.2

VHDL による電卓の設計

第3 章の演算回路と、4.1 節のブロック図から VHDL で電卓を設計する。

library ieee;

use ieee.std_logic_1164.all; entity ADD is

port(A:in std_logic_vector(26 downto 0); B:in std_logic_vector(28 downto 0); S:out std_logic_vector(28 downto 0); START,CLOCK,RESET_B:in std_logic); end ADD;

architecture ADD of ADD is

signal ADDER4_OUT:std_logic_vector(4 downto 0); signal BIT_A_OUT:std_logic_vector(3 downto 0); signal BIT_B_OUT:std_logic_vector(3 downto 0); signal BIT_REG_OUT:std_logic_vector(28 downto 0); signal CNT16_OUT:std_logic_vector(4 downto 0); signal JK_FF_K_IN:std_logic;

signal JK_FF_Q_OUT:std_logic; component ADDER4

port(a,b:in std_logic_vector(3 downto 0); cin:in std_logic;

s:out std_logic_vector(4 downto 0)); end component;

component BIT_SHIFT_A

port(LOAD,CLK,EN:in std_logic;

A_IN:in std_logic_vector(26 downto 0); Q_A:out std_logic_vector(3 downto 0)); end component;

(36)

component BIT_SHIFT_B

port(LOAD,CLK,EN:in std_logic;

B_IN:in std_logic_vector(28 downto 0); Q_B:out std_logic_vector(3 downto 0)); end component;

component BIT_REG

port(RESET,RESET_B,CLK,EN:in std_logic; PIN:in std_logic_vector(4 downto 0); Q:out std_logic_vector(28 downto 0)); end component; component RS_SYJKFF port(RESET_B:in std_logic; SET_B:in std_logic := '1'; J,K,CLK:in std_logic; Q,Q_B:out std_logic); end component; component EN_CNT16

port(Q:out std_logic_vector(4 downto 0);

EN,CLK,CLR_SY,CLR_USY:in std_logic); end component;

begin

JK_FF_K_IN <= not CNT16_OUT(4) and not CNT16_OUT(3) and CNT16_OUT(2) and CNT16_OUT(1) and not CNT16_OUT(0);

S <= BIT_REG_OUT;

U_A:BIT_SHIFT_A port map(START,CLOCK,JK_FF_Q_OUT,A,BIT_A_OUT); U_B:BIT_SHIFT_B port map(START,CLOCK,JK_FF_Q_OUT,B,BIT_B_OUT); U_ADDER4:ADDER4 port map(BIT_A_OUT,BIT_B_OUT,BIT_REG_OUT(28), ADDER4_OUT); U_REG:BIT_REG port map(RESET_B,START,CLOCK,JK_FF_Q_OUT,

ADDER4_OUT,BIT_REG_OUT); JK_FF:RS_SYJKFF port map(RESET_B,open,START,JK_FF_K_IN,CLOCK,

JK_FF_Q_OUT,open);

(37)

CNT8:EN_CNT16 port map(CNT16_OUT,JK_FF_Q_OUT,CLOCK,START,RESET_B); end ADD; 図4.5 加算回路の VHDL(3/3) library ieee; use ieee.std_logic_1164.all; entity MUL is port(START,CLOCK,RESET_B:in std_logic; MD:in std_logic_vector(28 downto 0); MQ:in std_logic_vector(26 downto 0); ANS:out std_logic_vector(55 downto 0)); end MUL;

architecture MUL of MUL is signal MQ_S_OUT:std_logic; signal JK_FF_K_IN:std_logic; signal JK_FF_Q_OUT:std_logic;

signal MD_Q_OUT:std_logic_vector(28 downto 0); signal ADDER32_A_IN:std_logic_vector(28 downto 0); signal ADDER32_OUT:std_logic_vector(29 downto 0); signal CNT16_OUT:std_logic_vector(4 downto 0); signal ACC_D_IN:std_logic_vector(56 downto 0); signal ACC_Q_OUT:std_logic_vector(56 downto 0); component ADDER32

port(a,b:in std_logic_vector(28 downto 0); cin:in std_logic :='0';

s:out std_logic_vector(28 downto 0); cout:out std_logic);

end component;

(38)

component REG_MD

port(LOAD,CLK:in std_logic;

D:in std_logic_vector(28 downto 0); Q:out std_logic_vector(28 downto 0)); end component;

component EN_REG

port(RESET,EN,CLR,CLK:in std_logic; D:in std_logic_vector(56 downto 0); Q:out std_logic_vector(56 downto 0)); end component;

component BIT_SHIFT port(SIN:in std_logic :='0';

EN,LOAD,CLK:in std_logic; D:in std_logic_vector(26 downto 0); SOUT:out std_logic); end component; component RS_SYJKFF port(RESET_B:in std_logic; SET_B:in std_logic := '1'; J,K,CLK:in std_logic; Q,Q_B:out std_logic); end component; component EN_CNT16 port(EN,CLK,CLR_SY,CLR_USY:in std_logic; Q:out std_logic_vector(4 downto 0)); end component;

begin

ADDER32_A_IN <= MD_Q_OUT and (MQ_S_OUT & MQ_S_OUT & MQ_S_OUT & MQ_S_OUT & MQ_S_OUT & MQ_S_OUT & MQ_S_OUT & MQ_S_OUT& MQ_S_OUT & MQ_S_OUT & MQ_S_OUT & MQ_S_OUT & MQ_S_OUT & MQ_S_OUT & MQ_S_OUT & MQ_S_OUT& MQ_S_OUT & MQ_S_OUT & MQ_S_OUT & MQ_S_OUT & MQ_S_OUT & MQ_S_OUT & MQ_S_OUT & MQ_S_OUT& MQ_S_OUT & MQ_S_OUT & MQ_S_OUT & MQ_S_OUT & MQ_S_OUT);

(39)

ACC_D_IN <= ADDER32_OUT & ACC_Q_OUT(27 downto 1);

JK_FF_K_IN <= CNT16_OUT(4) and CNT16_OUT(3) and not CNT16_OUT(2) and CNT16_OUT(1) and CNT16_OUT(0);

ANS <= ACC_Q_OUT(55 downto 0);

U_MD:REG_MD port map(START,CLOCK,MD,MD_Q_OUT);

U_ADDER:ADDER32 port map(ADDER32_A_IN,ACC_Q_OUT(56 downto 28), open,ADDER32_OUT(28 downto 0),ADDER32_OUT(29)); ACC:EN_REG port map(RESET_B,JK_FF_Q_OUT,START,CLOCK,

ACC_D_IN,ACC_Q_OUT); U_MQ:BIT_SHIFT port map (open,JK_FF_Q_OUT,START,CLOCK,

MQ,MQ_S_OUT); JK_FF:RS_SYJKFF port map(RESET_B,open,START,JK_FF_K_IN,CLOCK,

JK_FF_Q_OUT,open); CNT16:EN_CNT16 port map(JK_FF_Q_OUT,CLOCK,START,RESET_B,

CNT16_OUT); end MUL; 図4.6 乗算回路の VHDL(3/3) library IEEE; use IEEE.std_logic_1164.all; entity DIV is

port(DD:in std_logic_vector(28 downto 0); DQ:in std_logic_vector(26 downto 0); ANS:out std_logic_vector(28 downto 0);

ARE:out std_logic_vector(26 downto 0); START,CLOCK,RESET_B:in std_logic ; ER : out std_logic);

end DIV;

(40)

architecture DIV of DIV is signal DQ_E_OUT:std_logic; signal E_JK_FF_J_IN:std_logic; signal STR:std_logic; signal DQ_SEL_IN:std_logic; signal ACC_SEL_IN:std_logic; signal ACC_EN1:std_logic; signal JK_FF_K_IN: std_logic; signal JK_FF_Q_OUT:std_logic; signal ANS_SIN:std_logic; signal ANS_EN:std_logic; signal LAST:std_logic;

signal DQ_Q_OUT:std_logic_vector(26 downto 0); signal DQ_SEL_A_IN:std_logic_vector(27 downto 0); signal DQ_SEL_B_IN:std_logic_vector(27 downto 0); signal DQ_SEL_OUT:std_logic_vector(27 downto 0); signal ADD_SUB_B_IN:std_logic_vector(27 downto 0); signal ADD_SUB_OUT:std_logic_vector(28 downto 0); signal ACC_SEL_A_IN:std_logic_vector(55 downto 0); signal ACC_SEL_B_IN:std_logic_vector(55 downto 0); signal ACC_D_IN:std_logic_vector(56 downto 0); signal ACC_Q_OUT:std_logic_vector(56 downto 0); signal ANS_Q_OUT:std_logic_vector(28 downto 0); signal CNT16_OUT:std_logic_vector(4 downto 0); component ADD_SUB

port(A,B:in std_logic_vector(27 downto 0); SUB:in std_logic;

S:out std_logic_vector(27 downto 0); CY_BR:out std_logic );

end component; component EN_REG4

port(D:in std_logic_vector(26 downto 0); Q:out std_logic_vector(26 downto 0);

(41)

EN,CLK:in std_logic); end component;

component EN_REG13

port( D:in std_logic_vector(56 downto 0); Q:out std_logic_vector(56 downto 0); RESET,EN,CLK:in std_logic); end component;

component EN_SIN_POUT_SHIFT port(SIN:in std_logic;

Q:out std_logic_vector(28 downto 0); EN,PS,CLK:in std_logic); end component; component RS_SYJKFF port(RESET_B:in std_logic; SET_B:in std_logic := '1'; J:in std_logic; K:in std_logic := '0'; CLK:in std_logic; Q,Q_B:out std_logic); end component; component EN_CNT16

port(Q:out std_logic_vector(4 downto 0); EN,CLK,CLR_SY,CLR_USY:in std_logic); end component;

component SEL5

port(A,B:in std_logic_vector(27 downto 0); O:out std_logic_vector(27 downto 0); SEL:in std_logic);

end component; component SEL12

port(A,B:in std_logic_vector(55 downto 0); O:out std_logic_vector(55 downto 0); SEL:in std_logic);

(42)

end component; begin

DQ_E_OUT <= not DQ(26) and not DQ(25) and not DQ(24) and not DQ(23) and not DQ(22) and not DQ(21) and not DQ(20) and not DQ(19) and not DQ(18) and not DQ(17) and not DQ(16) and not DQ(15) and not DQ(14) and not DQ(13) and not DQ(12) and not DQ(11) and not DQ(10) and not DQ(9) and DQ(8) and not DQ(7) and not DQ(6) and not DQ(5) and not DQ(4) and not DQ(3) and not DQ(2) and not DQ(1) and not DQ(0);

E_JK_FF_J_IN <= DQ_E_OUT and START; STR <= START and (not DQ_E_OUT);

DQ_SEL_IN <= not JK_FF_K_IN; ACC_SEL_IN <= not STR; ACC_EN1 <= STR or JK_FF_Q_OUT;

JK_FF_K_IN <= CNT16_OUT( 4 ) and CNT16_OUT( 3 ) and not CNT16_OUT( 2 ) and CNT16_OUT( 1 ) and CNT16_OUT( 0 );

LAST <= not ( JK_FF_K_IN and ANS_Q_OUT( 0 ));

DQ_SEL_A_IN <= '0' & DQ_Q_OUT; DQ_SEL_B_IN <= DQ_Q_OUT & '0';

ADD_SUB_B_IN <= DQ_SEL_OUT and ( LAST & LAST & LAST & LAST & LAST & LAST & LAST & LAST & LAST & LAST & LAST & LAST& LAST & LAST & LAST & LAST& LAST & LAST & LAST & LAST& LAST & LAST & LAST & LAST& LAST & LAST & LAST & LAST );

ACC_SEL_A_IN <= ADD_SUB_OUT( 26 downto 0 ) &

ACC_Q_OUT( 25 downto 0 ) & '0'; ACC_SEL_B_IN <= DD(28)& DD(28)& DD(28)& DD(28)& DD(28)& DD(28)& DD(28)& DD(28)& DD(28)& DD(28)& DD(28)& DD(28)& DD(28)& DD(28)& DD(28)& DD(28)& DD(28)& DD(28)& DD(28)& DD(28)& DD(28)& DD(28)& DD(28)& DD(28)& DD(28)& DD(28)& DD(28)& DD;

ACC_D_IN( 54 ) <= ADD_SUB_OUT( 27 ); ANS <= ANS_Q_OUT;

ANS_SIN <= ANS_Q_OUT( 0 ) xor ADD_SUB_OUT( 28 ); ANS_EN <= not JK_FF_K_IN and JK_FF_Q_OUT; ARE <= ACC_Q_OUT( 56 downto 30 );

U_ADD_SUB:ADD_SUB port map ( ACC_Q_OUT( 55 downto 28 ), ADD_SUB_B_IN, ANS_Q_OUT( 0 ), ADD_SUB_OUT( 27 downto 0 ), ADD_SUB_OUT( 28 )); U_D:EN_REG4 port map ( DQ, DQ_Q_OUT, STR, CLOCK );

(43)

ACC:EN_REG13 port map(ACC_D_IN,ACC_Q_OUT,RESET_B,

ACC_EN1,CLOCK ); U_ANS:EN_SIN_POUT_SHIFT port map(ANS_SIN,ANS_Q_OUT,ANS_EN,

STR,CLOCK ); JK_FF:RS_SYJKFF port map(RESET_B,open,STR,JK_FF_K_IN,

CLOCK, JK_FF_Q_OUT, open ); E_JK_FF:RS_SYJKFF port map(RESET_B,open,E_JK_FF_J_IN,open,

CLOCK,ER,open); CNT16:EN_CNT16 port map(CNT16_OUT,JK_FF_Q_OUT,CLOCK,

STR, RESET_B ); DQ_SEL:SEL5 port map(DQ_SEL_A_IN,DQ_SEL_B_IN,

DQ_SEL_OUT,DQ_SEL_IN); ACC_SEL:SEL12 port map(ACC_SEL_A_IN,ACC_SEL_B_IN,

ACC_D_IN( 55 downto 0 ),ACC_SEL_IN); end DIV;

図4.7 除算回路の VHDL(5/5)

library IEEE;

use IEEE.std_logic_1164.all; entity DEC_TO_BIN is

port(DEC:in std_logic_vector(9 downto 0); BIN:out std_logic_vector(3 downto 0)); end DEC_TO_BIN;

architecture DEC_TO_BIN of DEC_TO_BIN is begin

process(DEC) begin

case DEC is

(44)

when "0000000001" => BIN <= "0000"; when "0000000010" => BIN <= "0001"; when "0000000100" => BIN <= "0010"; when "0000001000" => BIN <= "0011"; when "0000010000" => BIN <= "0100"; when "0000100000" => BIN <= "0101"; when "0001000000" => BIN <= "0110"; when "0010000000" => BIN <= "0111"; when "0100000000" => BIN <= "1000"; when "1000000000" => BIN <= "1001"; when others => BIN <= "0000";

end case; end process; end DEC_TO_BIN; 図4.8 10 キー入力の BCD 変換回路の VHDL(2/2) library ieee; use ieee.std_logic_1164.all; entity REGA is

port(DECI:in std_logic_vector(9 downto 0); KEKKA:out std_logic_vector(26 downto 0); REG_EN,IN_SEL,RST,CLK:in std_logic); end REGA;

architecture REGA of REGA is

signal BCD:std_logic_vector(3 downto 0);

signal ADDER_OUT:std_logic_vector(26 downto 0); signal REG_A_IN:std_logic_vector(26 downto 0); signal REG_A_OUT:std_logic_vector(26 downto 0);

(45)

signal MUL_OUT:std_logic_vector(26 downto 0); component DEC_TO_BIN is

port(DEC:in std_logic_vector(9 downto 0); BIN:out std_logic_vector(3 downto 0)); end component;

component REG_A is

port(EN,RESET_B,CLK:in std_logic; PIN:in std_logic_vector(26 downto 0); Q:out std_logic_vector(26 downto 0)); end component;

component cnv_mul is

port(MD:in std_logic_vector(23 downto 0); ANS:out std_logic_vector(26 downto 0); MO:out std_logic);

end component;

component cnv_adder is

port(A:in std_logic_vector(26 downto 0); B:in std_logic_vector(3 downto 0); S:out std_logic_vector(26 downto 0)); end component;

component INPUT_SEL is

port(A,B:in std_logic_vector(26 downto 0); O:out std_logic_vector(26 downto 0); SEL:in std_logic);

end component; begin

KEKKA <= REG_A_OUT;

U_ENC:DEC_TO_BIN port map(DECI,BCD);

U_REG_A:REG_A port map(REG_EN,RST,CLK,REG_A_IN,REG_A_OUT); U_MUL:cnv_mul port map(REG_A_OUT(23 downto 0),MUL_OUT,open); U_ADD:cnv_adder port map(MUL_OUT,BCD,ADDER_OUT);

(46)

U_SEL:INPUT_SEL port map(ADDER_OUT,"00000000000000000000000" & BCD,REG_A_IN,IN_SEL); end REGA; 図4.9 REGA の VHDL(3/3) library ieee; use ieee.std_logic_1164.all; entity REGB is

port(ASMD:in std_logic_vector(1 downto 0);

REGA_OUT:in std_logic_vector(26 downto 0); REGB_OUT:out std_logic_vector(26 downto 0); TO_STATE:out std_logic_vector(28 downto 0);

CLK,REG_RST,ADD_EN,SUB_EN,MUL_EN,DIV_EN:in std_logic; ERR:out std_logic);

end REGB;

architecture REGB of REGB is

signal REG_B_IN:std_logic_vector(28 downto 0); signal REG_B_OUT:std_logic_vector(28 downto 0); signal HOSU_OUT:std_logic_vector(26 downto 0); signal ADDER_OUT:std_logic_vector(28 downto 0); signal SUB_OUT:std_logic_vector(28 downto 0); signal MUL_OUT:std_logic_vector(55 downto 0); signal DIV_OUT:std_logic_vector(28 downto 0); component REG_B is

port(RESET_B,CLK:in std_logic;

PIN:in std_logic_vector(28 downto 0); Q:out std_logic_vector(28 downto 0)); end component;

(47)

component hosu is

port(PIN:in std_logic_vector(27 downto 0); Q:out std_logic_vector(26 downto 0); CLK:in std_logic);

end component;

component ASMD_SEL is

port(A,S,M,D:in std_logic_vector(28 downto 0); O:out std_logic_vector(28 downto 0); SEL:in std_logic_vector(1 downto 0)); end component;

component ADD is

port(A:in std_logic_vector(26 downto 0); B:in std_logic_vector(28 downto 0); S:out std_logic_vector(28 downto 0); START,CLOCK,RESET_B:in std_logic); end component;

component SUB is

port(A:in std_logic_vector(26 downto 0);

B:in std_logic_vector(28 downto 0); DIF:out std_logic_vector(28 downto 0);

START,CLOCK,RESET_B:in std_logic); end component;

component MUL is

port(START,CLOCK,RESET_B:in std_logic; MD:in std_logic_vector(28 downto 0); MQ:in std_logic_vector(26 downto 0); ANS:out std_logic_vector(55 downto 0)); end component;

component DIV is

port(DD:in std_logic_vector(28 downto 0); DQ:in std_logic_vector(26 downto 0); ANS:out std_logic_vector(28 downto 0); ARE:out std_logic_vector(26 downto 0);

(48)

end component; begin

REGB_OUT<=HOSU_OUT; TO_STATE <= REG_B_OUT;

U_REG_B:REG_B port map(REG_RST,CLK,REG_B_IN,REG_B_OUT); U_HOSU:hosu port map(REG_B_OUT(27 downto 0),HOSU_OUT,CLK); U_SEL:ASMD_SEL port map(ADDER_OUT,SUB_OUT,

MUL_OUT(28 downto 0),DIV_OUT,REG_B_IN,ASMD);

U_ADD:ADD port map(REGA_OUT,REG_B_OUT,ADDER_OUT,ADD_EN,

CLK,REG_RST); U_SUB:SUB port map(REGA_OUT,REG_B_OUT,SUB_OUT,SUB_EN,

CLK,REG_RST); U_MUL:MUL port map(MUL_EN,CLK,REG_RST,REG_B_OUT,REGA_OUT,

MUL_OUT); U_DIV:DIV port map(REG_B_OUT,REGA_OUT,DIV_OUT,open,DIV_EN,CLK,

REG_RST,ERR); end REGB; 図4.10 REGB の VHDL(3/3) library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; entity machine is

port(REGB:in std_logic_vector(28 downto 0); ASMD:out std_logic_vector(1 downto 0);

CLK,RESET,DECI,PLUS,MINUS,KAKERU,WARU,EQUAL,C,CE:in std_logic;

SEL,EN,RST_A,RST_B,ADD,SUB,MUL,DIV:out std_logic); end machine;

(49)

signal BR:std_logic; signal B_RST:std_logic;

signal COUNT:std_logic_vector(3 downto 0); signal CAL:std_logic_vector(1 downto 0);

signal ASMD_SEL:std_logic_vector(1 downto 0); signal ASMD_SELECT:std_logic_vector(3 downto 0); begin process(CLK,RESET) begin if(RESET = '0') then COUNT <= "0000"; CAL <= "00"; state <= DECIMAL;

elsif(CLK'event and CLK ='1') then case state is

when DECIMAL => SEL <= '1';BR<='0';

if((DECI = '1') and (COUNT < 8)) then B_RST<='0'; COUNT <= COUNT + 1; state <= DECIMAL; elsif(C = '1') then COUNT <= "0000"; state <= DECIMAL; elsif(CE = '1') then COUNT <= "0000"; state <= DECIMAL;

elsif((PLUS or MINUS or KAKERU or WARU or EQUAL) = '1') then architecture machine of machine is

type t_state is (DECIMAL,OPE,HALT); signal state:t_state;

(50)

if(CAL = "00") then ASMD_SELECT <= "0001"; ASMD_SEL<="00"; elsif(CAL = "01") then ASMD_SELECT <= "0010"; ASMD_SEL<="01"; elsif(CAL = "10") then ASMD_SELECT <= "0100"; ASMD_SEL<="10"; elsif(CAL = "11") then ASMD_SELECT <= "1000"; ASMD_SEL<="11"; end if; if(PLUS = '1')then CAL <= "00"; elsif(MINUS = '1') then CAL <= "01"; elsif(KAKERU = '1') then CAL <= "10"; elsif(WARU = '1') then CAL <= "11"; elsif(EQUAL = '1') then CAL <= "00"; BR <= '1'; end if; state <= OPE; end if; when OPE => SEL <= '0';

if(((REGB(28) = '1') and (REGB < 436870913)) or ((REGB(28) ='0') and (REGB > 99999999))) then

state <= HALT;

elsif((PLUS or MINUS or KAKERU or WARU) = '1') then

(51)

if(PLUS = '1')then CAL <= "00"; elsif(MINUS = '1') then CAL <= "01"; elsif(KAKERU = '1') then CAL <= "10"; elsif(WARU = '1') then CAL <= "11"; end if; state <= OPE; elsif(DECI = '1') then if(BR = '0') then B_RST <= '0'; COUNT <= "0001"; ASMD_SELECT<="0000"; elsif(BR = '1') then B_RST <= '1'; COUNT <= "0001"; ASMD_SELECT<="0000"; end if; state <= DECIMAL; end if; when HALT => if(C = '1') then CAL <= "00"; COUNT <= "0000"; state <=DECIMAL; elsif(CE = '1') then CAL <= "00"; COUNT <= "0000"; state <=DECIMAL; end if; end case; 図4.11 状態遷移機械の VHDL(4/5)

(52)

end if; end process;

EN<=DECI and not(COUNT(3)and not COUNT(2)and not COUNT(1)and not COUNT(0)); RST_A<=not(CE or C); RST_B<=not (C or B_RST); ADD<=ASMD_SELECT(0); SUB<=ASMD_SELECT(1); MUL<=ASMD_SELECT(2); DIV<=ASMD_SELECT(3); ASMD<=ASMD_SEL; end machine; 図4.11 状態遷移機械の VHDL(5/5) library ieee; use ieee.std_logic_1164.all; entity state is

port(DECIMAL:in std_logic_vector(9 downto 0); REG_B_OUT:in std_logic_vector(28 downto 0); ASMD:out std_logic_vector(1 downto 0);

CLK,RESET,PLUS,MINUS,KAKERU,WARU,EQUAL,C,CE:in std_logic;

A_D_SEL,REGA_EN,REGA_RST,REGB_RST,ADD_EN,SUB_EN,MUL_EN,DIV_E N:out std_logic);

end state;

architecture state of state is signal DEC:std_logic; signal ADD_IN:std_logic; signal SUB_IN:std_logic;

(53)

signal MUL_IN:std_logic; signal DIV_IN:std_logic; signal ADD_OUT:std_logic; signal SUB_OUT:std_logic; signal MUL_OUT:std_logic; signal DIV_OUT:std_logic;

signal ASMD_SELECT:std_logic_vector(1 downto 0); component machine is

port(REGB:in std_logic_vector(28 downto 0); ASMD:out std_logic_vector(1 downto 0);

CLK,RESET,DECI,PLUS,MINUS,KAKERU,WARU,EQUAL,C,CE:in std_logic; SEL,EN,RST_A,RST_B,ADD,SUB,MUL,DIV:out std_logic); end component; component ASMD_OUT is port(input,RESET,CLK:in std_logic; output:out std_logic); end component; component syncro is port(input,RESET,CLK:in std_logic; output:out std_logic); end component; begin

DEC <= DECIMAL(9) or DECIMAL(8) or DECIMAL(7) or DECIMAL(6) or DECIMAL(5) or DECIMAL(4) or DECIMAL(3) or DECIMAL(2) or DECIMAL(1) or DECIMAL(0);

ADD_EN<=ADD_OUT; SUB_EN<=SUB_OUT; MUL_EN<=MUL_OUT; DIV_EN<=DIV_OUT;

U_STATE:machine port map(REG_B_OUT,ASMD_SELECT,CLK,RESET,DEC, PLUS,MINUS,KAKERU,WARU,EQUAL,C,CE,

A_D_SEL,REGA_EN,REGA_RST,REGB_RST,ADD_IN,SUB_IN,MUL_IN,DIV_IN);

(54)

U_SYNC_A:syncro port map(ADD_IN,RESET,CLK,ADD_OUT); U_SYNC_S:syncro port map(SUB_IN,RESET,CLK,SUB_OUT); U_SYNC_M:syncro port map(MUL_IN,RESET,CLK,MUL_OUT); U_SYNC_D:syncro port map(DIV_IN,RESET,CLK,DIV_OUT); U_SYNC_ENC0_OUT:ASMD_OUT port map(ASMD_SELECT(0),

RESET,CLK,ASMD(0)); U_SYNC_ENC1_OUT:ASMD_OUT port map(ASMD_SELECT(1),RESET,

CLK,ASMD(1)); end state; 図4.12 STATE の VHDL(3/3) library ieee; use ieee.std_logic_1164.all; entity calc is

port(DECIMAL:in std_logic_vector(9 downto 0);

OUT_A,OUT_B,ANS:out std_logic_vector(26 downto 0); ANS_BCD8,ANS_BCD7,ANS_BCD6,ANS_BCD5,ANS_BCD4,

ANS_BCD3,ANS_BCD2,ANS_BCD1:out std_logic_vector(3 downto 0); CLK,RESET,PLUS,MINUS,KAKERU,WARU,EQUAL,C,CE:in std_logic; SIGN,ERROR_OUT:out std_logic);

end calc;

architecture calc of calc is

signal DECIMAL_IN:std_logic_vector(9 downto 0); signal B_STATE:std_logic_vector(28 downto 0); signal A_OUT:std_logic_vector(26 downto 0); signal B_OUT:std_logic_vector(26 downto 0); signal REG_B_RST:std_logic;

(55)

signal ENZAN_OUT:std_logic_vector(1 downto 0); signal ANS_BIN:std_logic_vector(26 downto 0); signal ADD_IN:std_logic; signal SUB_IN:std_logic; signal MUL_IN:std_logic; signal DIV_IN:std_logic; signal E_IN:std_logic; signal C_IN:std_logic; signal CE_IN:std_logic; signal ADD:std_logic; signal SUB:std_logic; signal MUL:std_logic; signal DIV:std_logic; signal ANS_SEL:std_logic; component A_S is

port(DECIMAL:in std_logic_vector(9 downto 0); OUT_A:out std_logic_vector(26 downto 0);

OUT_B:in std_logic_vector(28 downto 0) :="00000000000000000000000000000"; ASMD:out std_logic_vector(1 downto 0);

CLK,RESET,PLUS,MINUS,KAKERU,WARU,EQUAL,C,CE:in std_logic; REGB_RST,ENZAN_ADD,ENZAN_SUB,ENZAN_

MUL,ENZAN_DIV,KIRIKAE:out std_logic); end component;

component REGB is

port(ASMD:in std_logic_vector(1 downto 0);

REGA_OUT:in std_logic_vector(26 downto 0); REGB_OUT:out std_logic_vector(26 downto 0); TO_STATE:out std_logic_vector(28 downto 0);

CLK,REG_RST,ADD_EN,SUB_EN,MUL_EN,DIV_EN:in std_logic; ERR:out std_logic);

end component;

(56)

component LASTSEL is

port(A,B:in std_logic_vector(26 downto 0); O:out std_logic_vector(26 downto 0); SEL:in std_logic );

end component; component bintobcd is

port(bin:in std_logic_vector(26 downto 0);

bcd8,bcd7,bcd6,bcd5,bcd4,bcd3,bcd2,bcd1:out std_logic_vector(3 downto 0)); end component; component syncro is port(input,RESET,CLK:in std_logic; output:out std_logic); end component; begin OUT_A<=A_OUT; OUT_B<=B_OUT; ANS<=ANS_BIN;

SIGN<=(not ANS_SEL) and B_STATE(27);

U_AS:A_S port map(DECIMAL_IN,A_OUT,open,ENZAN_OUT,CLK,

RESET,ADD_IN,SUB_IN,MUL_IN,DIV_IN,E_IN,C_IN, CE_IN,REG_B_RST,ADD,SUB,MUL,DIV,ANS_SEL); U_REGB:REGB port map(ENZAN_OUT,A_OUT,B_OUT,B_STATE,

CLK,RESET and REG_B_RST,ADD,SUB,MUL,DIV,ERROR_OUT); U_ANS:LASTSEL port map(A_OUT,B_OUT,ANS_BIN,ANS_SEL);

U_BCD:bintobcd port map(ANS_BIN,ANS_BCD8,ANS_BCD7,ANS_BCD6,

ANS_BCD5,ANS_BCD4,ANS_BCD3,ANS_BCD2,ANS_BCD1); U_SYNC_0:syncro port map(DECIMAL(0),RESET,CLK,DECIMAL_IN(0));

U_SYNC_1:syncro port map(DECIMAL(1),RESET,CLK,DECIMAL_IN(1)); U_SYNC_2:syncro port map(DECIMAL(2),RESET,CLK,DECIMAL_IN(2)); U_SYNC_3:syncro port map(DECIMAL(3),RESET,CLK,DECIMAL_IN(3)); U_SYNC_4:syncro port map(DECIMAL(4),RESET,CLK,DECIMAL_IN(4)); U_SYNC_5:syncro port map(DECIMAL(5),RESET,CLK,DECIMAL_IN(5));

(57)

U_SYNC_6:syncro port map(DECIMAL(6),RESET,CLK,DECIMAL_IN(6)); U_SYNC_7:syncro port map(DECIMAL(7),RESET,CLK,DECIMAL_IN(7)); U_SYNC_8:syncro port map(DECIMAL(8),RESET,CLK,DECIMAL_IN(8)); U_SYNC_9:syncro port map(DECIMAL(9),RESET,CLK,DECIMAL_IN(9)); U_SYNC_A:syncro port map(PLUS,RESET,CLK,ADD_IN);

U_SYNC_S:syncro port map(MINUS,RESET,CLK,SUB_IN); U_SYNC_M:syncro port map(KAKERU,RESET,CLK,MUL_IN); U_SYNC_D:syncro port map(WARU,RESET,CLK,DIV_IN); U_SYNC_E:syncro port map(EQUAL,RESET,CLK,E_IN); U_SYNC_C:syncro port map(C,RESET,CLK,C_IN); U_SYNC_CE:syncro port map(CE,RESET,CLK,CE_IN); end calc;

(58)

4.3 シミュレーション結果

図4.13 の VHDL のシミュレーション結果を図 4.14 から図 4.18 に示す。 図4.14 から図 4.18 のシミュレーションの結果だが、OUT_A が REG_A の値、 OUT_B が REGB の出力、ANS が LED に表示されている値である。これを見 ると、計算結果は正しい事がわかる。

(59)
(60)
(61)
(62)
(63)

VHDL をコンパイルした結果、使用する予定であった FPGA の論理素子数が 1152 に対して、電卓全体の論理素子数が 2856 となってしまい、FPGA への実 装はできなかった。 各回路の論理素子数を調べたところ、2 進 BCD 変換回路の論理素子数が 1591 で全体の半分以上を占めていた。このことから、内部で2 進数ではなく BCD で 演算を行えばFPGA に実装できたと思われる。 表4.1 に各回路の論理素子数を示す。 表4.1 各回路の論理素子数 回路名 論理素子数 電卓 2856 加算回路 152 減算回路 152 乗算回路 313 除算回路 249 状態遷移機械 76 2 進 BCD 変換回路 1591 REGA 130

(64)

5 章 おわりに

本研究において、ディジタル回路の設計方法およびVHDLの基礎を学び、電 卓を設計することで理解した。第4章ではVHDLによって電卓の設計を試みた。 VHDL記述では、なかなか思い通りにいなかったが、エラーを直しながら理解 を深めることができた。FPGAに実装する予定であったが、回路規模が大きくな りFPGAに収まらなくなってしまった。また、演算結果をシフトしながら出力す るため、オーバーフロー状態に遷移させることができなかった。 本研究において、電卓を設計することにより2進数での演算の仕組み、ディジ タル回路の設計およびVHDLの理解を深めるという目的を達成できた。今回の 研究を行ったことによって、今後の研究に役立っていくと思う。

(65)

謝辞

本研究を行うに際し、懇切丁寧な御指導を御鞭撻賜わりました高知工科大学 工学部電子・光システム工学科 橘昌良 助教授に心から感謝いたします。 研究中、懇切丁寧な御指導を御鞭撻賜わりました高知工科大学工学部電子・ 光システム工学科 原央 教授、橘昌良 助教授に厚くお礼申し上げます。 また、同研究室の皆様に心から感謝し、お礼申し上げます。

(66)

参考文献

(1)“VHDLによるデジタル回路の設計” … 並木秀明・永井亘道 共著、技術評論社 (2)“ディジタル集積回路の設計と試作”… 池田誠・小林和淑 著、培風館 (3)“HDLによるVLSI設計”… 深山正幸・北川章夫・秋田純一・鈴木正國 著、 共立出版株式会社 (4)“VHDLによるハードウェア設計入門”… 長谷川裕恭 著、CQ出版社

(67)

付録

VHDL のソース

回路に必要なVHDL のソースを以下に示す。 library ieee; use ieee.std_logic_1164.all; entity fulladder is port(a,b,cy_in:in std_logic; sum,cy_out:out std_logic); end fulladder;

architecture fulladder of fulladder is begin

sum<=a xor b xor cy_in;

cy_out<=(a and cy_in) or (b and cy_in) or (a and b); end fulladder;

全加算器のVHDL(1/1)

ibrary ieee;

use ieee.std_logic_1164.all; entity adder4 is

port(a,b:in std_logic_vector(3 downto 0); cin:in std_logic;

s:out std_logic_vector(4 downto 0)); end adder4;

architecture adder4 of adder4 is

(68)

signal cy:std_logic_vector(3 downto 0); component fulladder port(a,b,cy_in:in std_logic; sum,cy_out:out std_logic); end component; begin

fa0:fulladder port map(a(0),b(0),cin,s(0),cy(0)); fa1:fulladder port map(a(1),b(1),cy(0),s(1),cy(1)); fa2:fulladder port map(a(2),b(2),cy(1),s(2),cy(2)); fa3:fulladder port map(a(3),b(3),cy(2),s(3),cy(3)); s(4) <= cy(3); end adder4; 4ビット並列加算回路のVHDL(2/2) library ieee; use ieee.std_logic_1164.all; entity BIT_SHIFT_A is port(LOAD,CLK,EN:in std_logic;

A_IN:in std_logic_vector(26 downto 0); Q_A:out std_logic_vector(3 downto 0)); end BIT_SHIFT_A;

architecture BIT_SHIFT_A of BIT_SHIFT_A is signal REG_Q_A:std_logic_vector(26 downto 0); begin

Q_A <= REG_Q_A(3 downto 0); process(CLK)

begin

if(CLK'event and CLK = '1') then

表 2.2 全加算器の真理値表
表 2.4 全加算器の真理値表

参照

関連したドキュメント

・「下→上(能動)」とは、荷の位置を現在位置から上方へ移動する動作。

う東京電力自らPDCAを回して業 務を継続的に改善することは望まし

パキロビッドパックを処方入力の上、 F8特殊指示 →「(治)」 の列に 「1:する」 を入力して F9更新 を押下してください。.. 備考欄に「治」と登録されます。

・電源投入直後の MPIO は出力状態に設定されているため全ての S/PDIF 信号を入力する前に MPSEL レジスタで MPIO を入力状態に設定する必要がある。MPSEL

検討対象は、 RCCV とする。比較する応答結果については、応力に与える影響を概略的 に評価するために適していると考えられる変位とする。

今回のアンケート結果では、本学の教育の根幹をなす事柄として、

都調査において、稲わら等のバイオ燃焼については、検出された元素数が少なか

その対策として、図 4.5.3‑1 に示すように、整流器出力と減流回路との間に Zener Diode として、Zener Voltage 100V