この回路がやること
8ビット加算器は、2つの8ビット数 a(0〜255)と b(0〜255)を足し合わせ、 8ビットの和 sum と 1ビットの桁上がり cout を出力する回路である。
| 入力 a | 入力 b | cin | sum(8bit) | cout | 10進の結果 |
|---|---|---|---|---|---|
| 0000_0001 (1) | 0000_0010 (2) | 0 | 0000_0011 (3) | 0 | 3 |
| 1111_1111 (255) | 0000_0001 (1) | 0 | 0000_0000 (0) | 1 | 256(桁あふれ) |
| 1010_1010 (170) | 0101_0101 (85) | 0 | 1111_1111 (255) | 0 | 255 |
第1章で「見た」回路を、今度は「書く」
第1章の 4ビット加算器 では、全加算器を4個つなぎ、桁上がりが下の桁から上の桁へ伝わる様子を画面上で追った。 この演習は同じ回路の8ビット版である。違うのは、図を組み立てる代わりに Verilog の文で回路を表すこと。
各段の cout が次の段の cin へ
最後の cout が 9 ビット目
下位 8 ビットは sum に、
9 ビット目は cout に入れる
Verilog では全加算器を8個並べる必要はない。「足す」と書けば桁上がりの配線は言語が用意する。 その結果を何ビットで受け取るかを決めるのが、あなたの仕事である。
作るモジュールの仕様
- module
- adder8
- input
- a [7:0] — 被加数 / b [7:0] — 加数 / cin — 下位からの桁上がり入力
- output
- sum [7:0] — 和(下位8ビット) / cout — 桁上がり出力
書いて、その場でチェック
枠の中に assign 文を書き、「チェックする」を押してください。 いくつかの入力パターンで、正しい答えとあなたの回路の出力を自動で比べる。間違えても減点はない。何度でも試せる。
module adder8 (
input [7:0] a,
input [7:0] b,
input cin,
output [7:0] sum,
output cout
);
endmodule
答え合わせ(自分で試してから開く)
どちらも正解である。1行で書く方法と、9ビットの wire を経由する方法。
// 書き方 1:左辺を {cout, sum} の9ビットにまとめる assign {cout, sum} = a + b + cin;
// 書き方 2:9ビットの wire で一度受けてから分ける wire [8:0] result; assign result = {1'b0, a} + {1'b0, b} + cin; assign sum = result[7:0]; assign cout = result[8];
よくある間違い:assign sum = a + b + cin; だけだと、9ビット目が捨てられて cout を作れない。
考えてみよう
- a=200, b=100 のとき sum と cout はどうなりますか。手で計算してから、チェッカーの結果と照らし合わせてみましょう。
- なぜ wire [8:0] result は9ビットなのでしょうか。8ビットにすると何が起きますか。
- 第1章の 4ビット加算器 と、この8ビット版の違いは何ですか。リップルキャリー構造との関係を説明してみましょう。
- cin を 1 にすると、何ビットの加算器でも使えるテクニックがある。それは何に使えるでしょうか。(ヒント:次の演習B)
発展:本物のツール(EDA Playground)でも動かす 任意
上のチェッカーは授業用の簡易版である。実際の開発で使われるシミュレータ(Icarus Verilog)と波形ビューアを体験したい人は、 EDA Playground に設計を貼り付けて実行できる(Gmail アカウントが必要)。 手順は 使い方ガイド へ。
module tb_adder8; reg [7:0] a, b; reg cin; wire [7:0] sum; wire cout; adder8 uut (.a(a), .b(b), .cin(cin), .sum(sum), .cout(cout)); initial begin $dumpfile("dump.vcd"); $dumpvars(0, tb_adder8); $monitor("a=%0d b=%0d cin=%0d | sum=%0d cout=%0d", a, b, cin, sum, cout); a = 8'd1; b = 8'd2; cin = 0; #10; a = 8'd0; b = 8'd0; cin = 0; #10; a = 8'd255; b = 8'd1; cin = 0; #10; a = 8'd100; b = 8'd100; cin = 1; #10; a = 8'd255; b = 8'd255; cin = 1; #10; $display("--- テスト完了 ---"); $finish; end endmodule