順序回路は組合せ回路を記述できる!?【Altera DE0】

組合せ回路を状態遷移図で書いてみる

順序回路で組合せ回路を記述することができる。
何のことかわけがわからなくなりそうなので、実際に設計してみよう。

DE0ボードにはスライドスイッチがあるので、4個を入力とした2ビット加算器を組合せ回路で実現してみる。出力は桁上げを含めると3ビットなので、LED3個に表示してみる。

Quartus2_000000.JPG

つまり、上の回路を組み合わせ回路で設計してみる。

module adder_2bit(
SLIDE_SW,
LED
);
input [3:0]SLIDE_SW;
output [2:0]LED;

assign LED = SLIDE_SW[1:0] + SLIDE_SW[3:2];

endmodule

はい、おしまい。非常に単純明快。 ちなみに、半加算器と加算器を使った設計もできる。 ソースと解説はモジュールとwire【Altera DE0】を見てください。

さて、この回路を1桁毎逐次計算する方法を考えてみよう。 つまり、

Quartus2_000001.JPG

各桁の計算を行っていくと

Quartus2_000002.JPG

各桁の計算は2ステップ、つまり

  1. 全加算器の入力をセット
  2. 全加算器の出力を取り込み

で行える。2ビット加算器ならば合計4ステップ必要だということだ。 各ステップで行う信号線の値の変化を全て書き出してみるのがポイント。

では、この過程を状態遷移図に書き起こしてみよう。

  • 丸の中に状態(ステップの番号)を書き、矢印に状態遷移する条件を書く(正しくは入力)。
  • つまり、矢印には(状態遷移する条件)/(変化する信号の値)
  • '---'は無条件(どんな入力でも)を示す。

この場合、遷移する条件はないので、遷移の際の信号線の変化を書けばよい。 で、各桁毎に加算を行う回路の状態遷移図は

Quartus2_000003.JPG

となる。あとは各状態に二進符号を割当てると

Quartus2_000004.JPG

こうなる。

順序回路方式2ビット加算器のVerilogソースコード

まず、プロジェクトを作成。 Quartus IIのプロジェクトの作成【Altera DE0】を参考に。 今回は

  • プロジェクトを置くディレクトリ→C:\verilog\DE0_tutorial\seq_adder
  • プロジェクト名→seq_adder

とした。(ディレクトリや名前は任意でかまわないが、プロジェクト名とトップレベル・エンティティ名は同一にしておくこと)

もう一度、順序回路の設計法を復習すると

  1. 仕様から状態遷移図を起こす
  2. 状態遷移図の状態に二進符号を割当てる
  3. モジュール宣言を行う
  4. 入出力宣言を行う。reg宣言も忘れずに。
  5. always@()のイベントを記述する(どんなクロックで記憶素子を更新するか)
  6. リセットの記述を加える。
  7. 状態遷移図をif文で再現する。代入は'<='で。
  8. 最後に'assign'文(function文)を使って状態から出力値を得る

ということで記述を始めよう。 ステップ1と2は既に終わったので、ステップ3からを順に行っていく。 すると、以下のソースになる。

module sequential_adder(
	clock,
	reset_n,
	SLIDE_SW,
	LED
);

input clock;
input reset_n;

input [3:0]SLIDE_SW;
output [2:0]LED;

reg [2:0]LED;
reg [1:0]state;
reg x, y, carry_in;

wire sum;
wire carry_out;

always@( posedge clock or negedge reset_n)begin //負論理のリセット
	if( !reset_n)begin //押しボタンの値が0のとき、(!)は否定を表す
		LED	 <= 3'b000;
		x	 <= 1'b0;
		y	 <= 1'b0;
		carry_in <= 1'b0;
		state	 <= 2'b0;
	end else begin
		case( state)
		2'b00:begin
			state	 <= 2'b01;
			x	 <= SLIDE_SW[0];
			y	 <= SLIDE_SW[2];
			carry_in <= 1'b0;
		end
		2'b01:begin
			state	<= 2'b10;
			LED[0]	<= sum; 
		end
		2'b10:begin
			state	 <= 2'b11;
			x	 <= SLIDE_SW[1];
			y	 <= SLIDE_SW[3];
			carry_in <= carry_out;
		end
		2'b11:begin
			state	 <= 2'b00;
			LED[2:1] <= { carry_out, sum};
		end
		endcase
	end
end

full_adr full_adr_inst(
	.x( x),
	.y( y),
	.carry_in( carry_in),
	.sum( sum),
	.carry_out( carry_out)
);

endmodule

module full_adr( x, y, carry_in, sum, carry_out);
  input x, y, carry_in;
  output sum, carry_out;
  
  wire w1, w2, w3;
  
  half_adr half_adr_inst1( .x( x), .y( y), .s( w1), .c( w2));
  half_adr half_adr_inst2( .x( carry_in), .y( w1), .s( sum), .c( w3));
  
  assign carry_out = w2 | w3;
  
endmodule

module half_adr( x, y, s, c);
  input x, y;
  output s, c;
  
  assign s = x ^ y;
  assign c = x & y;

endmodule

モジュール全加算器(full_adr)半加算器(half_adr)はモジュールとwire【Altera DE0】と同じ。
DE0の押しボタン(reset_n)は負論理なので、リセットも負論理で記述していることに注意。つまり、信号値は常に1であり, 押しボタンが押される(リセット)と信号値が0になる。
これを予約語negaedgeでalways@ブロックのリセットルーチンを呼び出す。

DE0ボードで動作させてみよう

ということで、DE0ボードで動作させてみよう。
動作は設計データのダウンロード【Altera DE0】を参考に。
スライドスイッチに応じて、加算結果が正しく表示されただろうか。

回路を解析してみよう

RTLビューワで合成した回路を解析できる。

Quartus2_000005.JPG

プロジェクト名を右クリックし、RTLビューワを呼び出してみよう。 (初期設定では緑の部分が展開されているかもしれない)

Quartus2_000006.JPG

緑の部分をダブルクリックすると、全加算器(full_adr)が表示されるはずだ。 Verilogの記述通りになっている。

Quartus2_000007.JPG

さらに全加算器をダブルクリックすると、半加算器が表示される。 これもVerilogのソースコードの記述通りになっている。

Quartus2_000008.JPG

Quartus2_000009.JPG


最上位階層に戻ろう。回路以外の部分(白いところのどこでも)をダブルクリックすると、上位の階層に戻れる。
では、黄色い部分をダブルクリックしてみよう。

Quartus2_000010.JPG

Quartus2_000011.JPG

状態遷移図が表示される。さきほど書き起こした状態遷移図と同じになっているはずだ。 RTLビューワを使うと、回路図や状態遷移図を視覚的に確認でき、デバッグの役に立つ。設計が終わったらRTLビューワを使って確認するクセをつけておこう。

ズバリ、順序回路で組合せ回路を記述するメリットとは?

加算器の例でわかったように、順序回路を設計するのは面倒だ。 では、何故順序回路で組み合わせ回路を設計するのか?それは

順序回路を用いると小さな回路になるから

だ。加算器を例に取ると、組合せ回路で設計した場合、 全加算器が桁数だけ必要になる(2ビット加算器では2個)。
先ほどのRTLビューワでもわかるように、順序回路ではたったの1個。 確かにレジスタとか制御回路が必要ではあるが、この差は大きい。

では、順序回路で組み合わせ回路を記述するデメリットは何だろう。

設計が面倒

つまり、時間がかかる・バグが入りやすくなるということ。

動作が遅い

加算器の例で明らかなように、逐次処理は遅いのだ。 ただし、動作の遅さを隠蔽するテクニックがあり、 順序回路=低速とは限らない場合も多々ある。 興味があるなら、「パイプライン処理」を調べてもらいたい。

さて、加算器の例を何度も取り上げて恐縮だが、 実際の加算器はもっとビット数が多い。 一度に計算するビット数を増やせば、処理時間は短くなる。 ただし、計算する回路の面積(この例では、全加算器の個数)は増加する。
つまり

面積と処理時間にはトレード・オフが存在する

これを図示すると

Quartus2_000012.JPG

こういう関係になる。実際には、消費電力やコストや設計時間とか、様々な要因がからんでくるのでこんなに単純にはならないが、要はトレード・オフがあるということだ。
CやJAVAから回路を合成する高位合成ツールを使うと設計が楽になるが、このトレード・オフは設計者が指定する必要がある。

つまり、面積と処理時間を決めるのは設計者(人間)の仕事なのだ。 どんなにツールが発展しても最終的な決定はやっぱり人間がやるのだ。 回路記述の習得も大事だが、トレード・オフを決定する「センス」も身につけて欲しい。

演習問題

  1. 4bit加算器を上記に示した順序回路の記述法を使って設計せよ。
  2. 上記の記述は4ビット加算器を1クロック毎に1ビット(つまり1桁)加算している。 4ビット加算器を1クロック毎に2ビット(2桁)加算する回路を設計せよ。 また、使用LE数と加算を行うのに必要なクロック数をグラフに示し、面積と性能のトレードオフを議論せよ。

お疲れ様でした。これで順序回路編はおしまいです。 次回は設計検証編です! 頑張って習得していきましょう。

Verilog入門へ戻る


トップ   編集 凍結解除 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2011-04-15 (金) 16:37:29 (2202d)