ハードウェアエンジニアの備忘録

電子工学(半導体物性)→応用光学・半導体プロセス→アナログ回路→C/C++→C#/.NETと低レイヤーから順調に(?)キャリアを登ってきているハードウェアエンジニアの備忘録。ブログ開始時点でiOSやサーバーサイドはほぼ素人です。IoTがマイブーム。

FPGA入門 備忘録③ ~組み合わせ回路編~

備忘録②の続き。

加算回路

半加算器

2進数の足し算は、

0 + 0 = 0
0 + 1 = 1
1 + 0 = 1
1 + 1 = 10

と書ける。これの足される数を入力A、足す数を入力B、その桁の加算結果を出力S、桁上りを出力COとして真理値表で示すと、以下のようになる。COは桁上りが生じたかどうかを表すビットである。

A B S CO
0 0 0 0
0 1 1 0
1 0 1 0
1 1 0 1

この真理値表から回路を構成すると以下のようになる。 f:id:tosh419:20160711230333p:plain

この加算回路は下の桁からの桁上りを考慮しておらず、下からの桁上りがない最下位ビットのみにしか使えない。これを半加算器という。

全加算器

桁上りが生じたかどうかを表す出力COは2桁目以降、そのまま加算すればよい。この下からの桁上りを考慮して半加算器に、ビットの入力を追加した加算回路を全加算器と呼ぶ。以下に全加算器の真理値表と回路図を示す。

A B CI S CO
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

f:id:tosh419:20160719202925p:plain

次に、全加算器を用いた3bit加算回路の回路図を見てみよう。

f:id:tosh419:20160719205613p:plain

変数 変数の各ビット 信号名
被加数 A0 (LSB) SW0
A1 SW1
A2 (MSB) SW2
加数 B0 (LSB) SW3
B1 SW4
B2 (MSB) SW5
演算結果 S0 (LSB) LED0
S1 LED1
S2 (MSB) LED2
桁上げ出力 CO LED3

AとBを加算し、LEDに出力する回路になっている。これをverilogで書くと、

module FA3_VERILOG(CO, S, A, B);

  input [2:0] A;
  input [2:0] B;
  output  CO;
  output [2:0] S;

  assign {CO, S} = A + B;

endmodule

assign {CO, S} = A + Bのところだが、まず左辺はCOは1bitで、Sは3bit、合計で4bitである。右辺は3bit同士の論理和で4bitになる。

減算回路

半減算器

2進数の引き算は、

0 - 0 = 0
0 - 1 = 11
1 - 0 = 1
1 - 1 = 0

と書ける。これの足される数を入力A、足す数を入力B、その桁の加算結果を出力S、桁上りを出力COとして真理値表で示すと、以下のようになる。BOは桁借りが生じたかどうかを表すビットである。

A B D BO
0 0 0 0
0 1 1 1
1 0 1 0
1 1 0 0

この真理値表から回路を構成すると以下のようになる。 f:id:tosh419:20160719211654p:plain

この減算回路は下の桁への桁下がりを考慮しておらず、下への桁下がりがない最下位ビットのみにしか使えない。これを半減算器という。

全減算器

以下に全減算器の真理値表と回路図を示す。

A B BI D BO
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

f:id:tosh419:20160719212957p:plain

図は省略するが、加算器と同様に3bit減算回路のverilog

module FS3_VERILOG(A, B, BO, D);
  
  input [2:0] A;
  input [2:0] B;
  output  BO;
  output [2:0] D;

  assign {BO, D} = A - B;

endmodule

と書ける。

負の数

減算結果の負の数を2進数で表す場合、最も単純なのは符号を表すビットを追加して、符号ビット+絶対値として表す方法だ。符号ビットは正の時に0、負の時に1とする。つまり、-2dは値を3bitとすれば、1010bと表せる。3bitの絶対値に符号ビットを追加して表現した例を以下に示す。

10進数 符号なし2進数 符号付き2進数
15 1111 -
14 1110 -
13 1101 -
12 1100 -
11 1011 -
10 1010 -
9 1001 -
8 1000 -
7 0111 0111
6 0110 0110
5 0101 0101
4 0100 0100
3 0011 0011
2 0010 0010
1 0001 0001
0 0000 0000 or 1000
-1 - 1001
-2 - 1010
-3 - 1011
-4 - 1100
-5 - 1101
-6 - 1110
-7 - 1111

先ほどの3bit減算回路の演算結果出力と比べてみる。

減算結果(10進数) 出力パターン 符号付き2進数
BO,D2,D1,D0 符号1bit,絶対値3bit
7 0111 0111
6 0110 0110
5 0101 0101
4 0100 0100
3 0011 0011
2 0010 0010
1 0001 0001
0 0000 0000 or 1000
-1 1111 1001
-2 1110 1010
-3 1101 1011
-4 1100 1100
-5 1011 1101
-6 1010 1110
-7 1001 1111

3bit減算回路の出力パターンと符号付き2進数を比較すると、減算結果が正の時は一致しており、また負の時もBOと符号ビットは一致している。つまり、減算結果が負となる時のD2,D1,D0の3bitの絶対値部分を変換すれば良い。この変換には補数を用いる。具体的には、

-まず、D0〜D2の各ビットを反転 -次に反転した3bitのDに1bを加算

のように行う。表で変換過程を示すと以下のようになる。

減算結果 出力パターン D0〜D2を反転 さらに1を加算
(10進数) BO, D2, D1, D0 BO, ~D2, ~D1, ~D0 BO, (~D2, ~D1, ~D0)+001b
-1 1111 1000 1001
-2 1110 1001 1010
-3 1101 1010 1011
-4 1100 1011 1100
-5 1011 1100 1101
-6 1010 1101 1110
-7 1001 1110 1111

各ビットを反転して1bを加算する回路は補数機と呼ばれており、以下の様な回路で示される。 f:id:tosh419:20160719221148p:plain

本では最後に、補数機を3bit減算器に組み合わせ符号付き2進数3bit減算回路を示している。回路図は省略するが、verilogだけ書いておく。

module FS3_SIGN_VERILOG(A, B, BO, D);
 
  input [2:0] A;
  input [2:0] B;
  output BO;
  output [2:0] D;

  wire [3:0] sub;
  
  assign sub = {1'b0, A} - {1'b0, B};
  assign BO = sub[3];
  assign D = sub[3] ? (~sub[2:0] + 1'b1) : sub[2:0];

endmodule

今回はここまで。次回は順序回路から。