計算機工学特論A 10/17 テキスト内容 1.1~1.4
第1章 やさしいVerilog HDL記述入門
1.1 HDLって何だ? 1.1.1 HDL記述と論理合成 HDL( hardware description language)とは? 論理合成ツールが実用レベルに達したこと ワークステーション、パーソナル・コンピュータの低価格化、高性能化 大規模論理回路を短期間で設計する必要が生じたこと などが挙げられる。
1.1 HDLって何だ? 1.1.1 HDL記述と論理合成 HDLには様々なものがあるが、これらの言語の中で最もよく用いられているのが、“Verilog HDL”と“VHDL”である。ここでは、実際に使う設計者の立場に立ってVerilog HDLのVHDLに対する優位性を示す。 C言語をベースにした文法体型であり、記述が簡潔 構文や演算子がC言語と同じなので、習得が容易 シミュレーション向けの記述力が充実 言語体型が簡素なため、シミュレータが高速。さらに、VHDLのようなパッケージ・ファイルが不要なため、シミュレーションの負担が軽い。 ASICの開発実績が多数あるため、シミュレーション用のライブラリやツール類がVHDLに比べて充実 種類 特徴 Verilog HDL VHDL UDL SFL C言語に似た文法体型。ASIC開発においては、ライブラリの充実、採用実績多数などの理由で、実質的な業界標準。1995年にIEEE 1364として標準化された。 米国国防省を中心に、いち早く標準化(IEEE 1076)されたHDL。言語仕様が豊富かつ厳格。 日本電子工業振興協会(電子協)の標準化委員会で採択された純国産の標準HDL。実用的な処置系(シミュレータ、論理合成ツール)が無いため、利用されない。 論理合成ツールPARTHENON(NTT)用のHDL。同期回路に用途を限定したため、記述や処理系が簡潔。いくつかのASIC開発実績はある。
1.1 HDLって何だ? 1.1.1 HDL記述と論理合成 ~ HDLによるASICおよびFPGAの開発手順 ~ 論理合成とは? 論理合成ツールは、HDLで記述された論理機能を実際のゲート回路に変換する。論理合成による出力は、目的のASICやFPGA用のネットリスト(回路部品(セル)の接続関係をテキストで表現したもの)である。 HDL記述では、ASICやFPGAなどの設計対象を意識せずに設計できる。論理合成時に使用する合成ライブラリを変えることで、ターゲットをFPGAやゲートアレイなどに変えることができる。 また、HDLは回路記述だけでなく、ボード・レベル・シミュレーションなどにも利用可能。 つまり、すべての論理回路に用いることができる。 ~ HDLによるASICおよびFPGAの開発手順 ~ テキスト・ エディタ HDL シミュレータ 論理合成ツール レイアウト・ ツール FPGA 開発ツール 作成 動作確認 HDL記述 論理合成用ライブラリ ASIC用ネットリスト FPGA用ネットリスト
1.1.2 HDL設計のメリット/デメリット HDL設計のメリット(設計の効率化) (1)半導体ベンダにとらわれない設計が可能 従来は、ベンダとASICの品種が決定してから詳細設計に着手していた。しかし、HDLでは論理合成時に用いるライブラリを換えるだけで、各社のネットリストに変換できるため、設計してから半導体ベンダを選ぶことが可能。 (2)論理合成による設計期間短縮 論理圧縮や遅延量の制御は、論理合成の得意とするところであり、論理式から回路を生成する点において、大幅な期間短縮が可能。 (3)設計資産の活用 半導体ベンダにとらわれない設計が可能であること、及びHDLライブラリを構築可能であることから、強力な設計資産が活用可能。
1.1.2 HDL設計のメリット/デメリット HDL設計のメリット(検証精度の向上) (1)設計の途中で検証できる HDLによる記述は、回路の「概略設計の段階」、「詳細設定の段階」、「ゲート回路の段階」で用いることができ、それぞれの段階でシミュレーションによる検証が可能。また、概略設計のブロックと、論理合成後のゲート回路ブロックが混在したシミュレーションが可能。 (2)入力の印加、出力の観測・比較が容易 回路検証のための検証用の入力も同じ文法体系の中で記述できるため、きめ細かい記述可能。これにより、例えばROMのデータをファイルから読み込んだり、あらかじめ用意した期待値との自動比較が可能となる。 (3)システム・レベルの検証が行える 検証のための設計対象に接続する周辺回路を、 HDLで記述可能(これを「シミュレーション・モデル」 と呼ぶ)。これによって、周辺チップを含めたシステ ム・レベルの検証が可能で、ボードで検証する前に、 シミュレーション上で基本的な動作を確認できる。 HDLによる 回路記述 CPU ROM RAM 購入または ベンダが提供 自作 システム・バス シミュレーション・ モデル
1.1.2 HDL設計のメリット/デメリット HDL設計のデメリット (1)現状の論理合成は単相同期回路向き 非同期回路や多相の回路では、タイミング条件が複雑なため、論理合成時の最適化が単相ほど容易でない。また、単相同期回路はクロックを常時印加する構成となるため、回路規模や消費電力が若干大きくなる。 (2)ツール類が高価 HDLの記述は、OS附属のテキスト・エディタなどで十分行えるが、HDLシミュレータと論理合成ツールの購入にはお金がかかる。 (3)ASICでは論理合成できない回路もある ASICでは、ROM、RAM、乗算回路などのように論理合成を用いずにコンパイルド・セルうぃ用いる回路がある。また、論理合成ツールに使用する合成ライブラリによっては、数多くの論理合成対象外の回路がある。こういった回路は、回路図入力で作成するか、セルを直接指定したネットリストをHDLで記述する必要がある。
1.1.3 記述レベル (1)現状の論理合成は単相同期回路向き 1.1.3 記述レベル (1)現状の論理合成は単相同期回路向き 非同期回路や多相の回路では、タイミング条件が複雑なため、論理合成時の最適化が単相ほど容易でない。また、単相同期回路はクロックを常時印加する構成となるため、回路規模や消費電力が若干大きくなる。 (2)ツール類が高価 HDLの記述は、OS附属のテキスト・エディタなどで十分行えるが、HDLシミュレータと論理合成ツールの購入にはお金がかかる。 (3)ASICでは論理合成できない回路もある ASICでは、ROM、RAM、乗算回路などのように論理合成を用いずにコンパイルド・セルうぃ用いる回路がある。また、論理合成ツールに使用する合成ライブラリによっては、数多くの論理合成対象外の回路がある。こういった回路は、回路図入力で作成するか、セルを直接指定したネットリストをHDLで記述する必要がある。
1.1.3 記述レベル 5階層の記述レベル HDLによる設計には「HDL記述のレベル」がいくつかあり、目的と場合によって記述レベルを変えることが行われる。この中でも良く使われる「記述レベル」は、「レジスタ・トランスファ・レベル」と「ビヘイビア・レベル」の2つである。 (1)レジスタ・トランスファ・レベル(RTL) RTLは、回路の構成要素であるレジスタやカウンタなどと、それらの間におけるデータ転送状態を表現している、「詳細なブロック図」のレベル。 (2)ビヘイビア・レベル ビヘイビア・レベルは、「動作をクロックの概念なしに表現したもの」である。クロックを考慮にいれないので、プログラム言語のように記述できる。 高 低
1.1.3 記述レベル 構造記述と機能記述 記述内容を表現する用語に構造記述、機能記述といった言い方がある。 1.1.3 記述レベル 構造記述と機能記述 記述内容を表現する用語に構造記述、機能記述といった言い方がある。 構造記述は、回路の接続関係だけの記述、つまりネットリストのことであり、上位ブロックにおいて下位ブロックを配置し接続しただけの記述も、構造記述と呼ぶ。 機能記述は、論理合成を行う回路に対してはRTLを意味し、論理合成を前提としない回路に対してはRTLとビヘイビア・レベルを意味する。
1.2 加算回路のHDL記述
1.2.1 加算演算子による加算回路 // 4bit adder module adder (a , b, q); 1.2.1 加算演算子による加算回路 // 4bit adder module adder (a , b, q); input [3:0] a, b; output [3:0] q; assign q = a + b; endmodule 1.コメントの記述 //~ もしくは /* ~ */を用いる 2.モジュールの宣言 Verilog HDL による記述は全てモジュールを基本単位とし、文の終わりにはセミコロン module モジュール名 (ポート・リスト) Verilog HDL 記述 3.入出力信号の宣言 a b q 4 4ビット加算回路 ポートリストに記述した信号の詳細(ビット幅など)を宣言する //で始まる1行は、行末までコメント扱い 文の終わりにはセミコロン;をつける。 4.加算回路の記述 assign 加算演算子 と書く 5.モジュールの終わり
1.2.2 フル・アダー呼び出しによる加算回路1 fulladd adder_ripple ・ポートリスト順の接続 1.2.2 フル・アダー呼び出しによる加算回路1 ・ポートリスト順の接続 ここでは、1ビットのフル・アダー(全加算器)を4個用いてリプル・キャリ型の4ビット加算回路を構成している。 下位モジュール 上位モジュール 4個 fulladd adder_ripple // fulladd module fulladd( A, B, CIN, Q,COUT ); input A, B, CIN; output Q, COUT; assign Q = A ^ B ^ CIN; assign COUT = (A&B) | (B&CIN) | (CIN&A); endmodule Verilog HDL 記述
1.2.2 フル・アダー呼び出しによる加算回路1 ・fulladd部の記述 1.モジュールの宣言 2.入出力信号の宣言 1.2.2 フル・アダー呼び出しによる加算回路1 ・fulladd部の記述 1.モジュールの宣言 module fulladd( A, B, CIN, Q,COUT ); 2.入出力信号の宣言 input A, B, CIN; output Q, COUT; 入出力の宣言部でビット幅を記述しなければ、1ビットの扱いとなる 3.加算出力とキャリ出力の記述 assign Q = A ^ B ^ CIN; assign COUT = (A&B) | (B&CIN) | (CIN&A); fulladd の加算出力Qと、キャリ(桁上げ)出力COUTをassign文を用いて記述 & : ビットAND演算 | : ビットOR演算 ^ : ビットEX-OR演算 Verilog HDL の演算子
1.2.2 フル・アダー呼び出しによる加算回路1 ・上位モジュール(adder_ripple)の記述 // call fulladd 1.2.2 フル・アダー呼び出しによる加算回路1 ・上位モジュール(adder_ripple)の記述 // call fulladd module adder_ripple(a, b, q); input [3:0] a, b; output [3:0] q; wire [3:0] cout; fulladd add0 ( a[0], b[0], 1'b0, q[0], cout[0]); fulladd add1 ( a[1], b[1], cout[0], q[1], cout[1]); fulladd add2 ( a[2], b[2], cout[1], q[2], cout[2]); fulladd add3 ( a[3], b[3], cout[2], q[3], cout[3]); endmodule Verilog HDL 記述
1.2.2 フル・アダー呼び出しによる加算回路1 ・上位モジュール(adder_ripple)の記述 1.モジュールの宣言、入出力信号の宣言 1.2.2 フル・アダー呼び出しによる加算回路1 ・上位モジュール(adder_ripple)の記述 1.モジュールの宣言、入出力信号の宣言 module adder_ripple(a, b, q); input [3:0] a, b; output [3:0] q; 2.各fulladd間のキャリ信号(内部信号)の宣言 wire [3:0] cout; 4ビットのCOUTがネット型(配線、ワイヤ)であると宣言 3.モジュール呼び出し部の記述 fulladd add0 ( a[0], b[0], 1'b0, q[0], cout[0]); fulladd add1 ( a[1], b[1], cout[0], q[1], cout[1]); このポート・リストは、記述順に下位モジュールと接続 モジュール名 インスタンス名 (ポート・リスト); インスタンス名とは、呼び出したモジュールに付加した個別の名前 定数にはビット幅、基数(何進数か)を付加することができ、「 1‘b0 」は1ビットの2進数で’0‘を示す。
1.2.3 フル・アダー呼び出しによる加算回路2 ・名前による接続 1.2.3 フル・アダー呼び出しによる加算回路2 ・名前による接続 下位モジュール呼び出し時のポート接続には、ポート・リスト順の接続以外に名前による接続もある。 定義側ポート名(接続信号)とし、呼び出し時の信号の記述順序は任意に決めることができる。 // fulladd呼び出しによる加算回路 module adder_ripple2( a, b, q ); input [3:0] a, b; output [3:0] q; wire [3:0] cout; fulladd add0 ( .Q(q[0]), .COUT(cout[0]), .A(a[0]), .B(b[0]), .CIN(1'b0) ); fulladd add1 ( .Q(q[1]), .COUT(cout[1]), .A(a[1]), .B(b[1]), .CIN(cout[0]) ); fulladd add2 ( .Q(q[2]), .COUT(cout[2]), .A(a[2]), .B(b[2]), .CIN(cout[1]) ); fulladd add3 ( .Q(q[3]), .COUT(cout[3]), .A(a[3]), .B(b[3]), .CIN(cout[2]) ); endmodule 前例のようなポート順による接続と名前による接続は混在できない Verilog HDL 記述
・4ビット加算回路のシミュレーション結果
1.2.4 セル呼び出しによる加算回路 ASICのセル・ライブラリの中には、「4ビット加算回路セル」のような面積・遅延ともに最適化されたセルがある場合がある。 しかし、今回使用したQuartusのソフトでは、セルを呼び出せない。 // セル呼び出しによる4ビット加算回路 module adder_macro( a, b, q); input [3:0] a, b; output [3:0] q; MKADD4 adder( .A1(a[0]), .A2(a[1]), .A3(a[2]), .A4(a[3]), .B1(b[0]), .B2(b[1]), .B3(b[2]), .B4(b[3]), .S1(q[0]), .S2(q[1]), .S3(q[2]), .S4(q[3]), .CI(1'b0) ); endmodule Quartusのソフトではセルは呼び出せない。 Verilog HDL 記述
1.3 カウンタのHDL記述 1.4 シミュレーションをしてみよう 担当内容 1.3.1 加算演算子によるバイナリ・カウンタ 1.3.1 加算演算子によるバイナリ・カウンタ 1.3.2 1ビットのカウンタ・ユニット呼び出しによる バイナリ・カウンタ 1.3.3 セル呼び出しによるバイナリ・カウンタ LPMによるカウンタの作成 1.4 シミュレーションをしてみよう
今回の仕様 4ビット・バイナリ・カウンタ 入力 : クロック(ck)、リセット(res) 4 出力 : q (4ビット) 出力 : q (4ビット) 動作 : クロックの立ち上がりで カウントアップ。 リセットが1なら、クロックと 無関係に(非同期に)出力 が0になる。 4 q ck res
加算演算子によるバイナリ・カウンタ // 4bit binary counter module counter(ck,res,q) ; input ck,res ; output [3:0] q ; reg [3:0] q ; always @(posedge ck or posedge res) begin if ( res == 1'b1 ) q <= 4'h0 ; else q <= q + 4'h1 ; end endmodule 入出力宣言部 カウンタ動作部 リセット信号(res)がHighなら → 出力を 0 にする それ以外なら → 出力を 現状の値+1 にする
加算演算子によるバイナリ・カウンタ - シミュレーション結果 - リセット信号なし リセット信号有り
ブロックキング代入とノン・ブロッキング代入 - ブロッキング代入とノン・ブロッキング代入 - - ブロッキング代入 - - ノン・ブロッキング代入 - A = 2 ; B = 4 ; A = B+1 ; C = A+1 ; A <= 2 ; B <= 4 ; A <= B+1 ; C <= A+1 ; A = 5 ; C = 6 ; A = 5 ; C = 3 ; 1つの代入処理が終了するま で次の処理を行わない。 (ブロックされる) 記述順序が動作に影響するた め、順序回路に適さない。 各右辺の処理が終了してから 代入処理が行われる。 (ブロックされない) 記述の順番が動作に影響され にくいため、順序回路向き。
1ビットのカウンタ・ユニット呼び出しによるバイナリ・カウンタ // 1bit counter unit module cnt_unit(CK,RES,EN,Q,CA) ; input CK,RES,EN ; output Q,CA ; reg Q ; always @( posedge CK or posedge RES ) begin if ( RES == 1'b1 ) Q <= 1'b0 ; else if ( EN == 1'b1 ) Q <= ~Q ; end assign CA = EN & Q ; endmodule 入出力宣言部 カウンタ動作部 リセット信号(RES)がHighなら → 出力を 0 にする イネーブル信号(EN)がHighなら → 現状の値のNOT回路で反転し たものを出力する 桁上げの信号(CA)をAND回路で判 定する
1ビットのカウンタ・ユニット呼び出しによるバイナリ・カウンタ // using 'cnt_unit' 4bit counter module counter_unit(ck,res,q) ; input ck,res ; output [3:0] q ; wire [3:0] ca ; cnt_unit cu0( ck, res, 1'b1, q[0], ca[0]) ; cnt_unit cu1( ck, res, ca[0], q[1], ca[1]) ; cnt_unit cu2( ck, res, ca[1], q[2], ca[2]) ; cnt_unit cu3( ck, res, ca[2], q[3], ca[3]) ; endmodule 入出力宣言部 カウンタユニット部 cnt_unit(CK,RES,EN,Q,CA) ; cnt_unit(CK,RES,EN,Q,CA) counter_unit(ck,res,q)
1ビットのカウンタ・ユニット呼び出しによるバイナリ・カウンタ - シミュレーション結果 - リセット信号なし リセット信号有り
LPMによるカウンタ作成 LPMライブラリとは、Altera 社が用意している基本論理モジュールで、LPM ( Library Parameterized Module )と呼ばれている。 LPMには、 ・カウンター ・加算/減算器 ・乗算器 などを用意している。
LPMによるカウンタ作成
LPMによるカウンタ作成 // using megafunctions 'lpm_counter‘ 4bit counter module counter_lpm(ck, res, q) ; input ck,res ; output [3:0] q ; reg [3:0] q ; lpm_counter cnt1( .clock(ck), .aclr(res), .q(q[3:0])) ; defparam cnt1 . LPM_WIDTH = 4 ; endmodule 入出力宣言部 カウンタ動作部 .q : 出力 .aclr : 非同期クリア Defparam文 LPMでパラメータを設定するために使用する文 defparam <instance name> .<parameter name> =<parameter value> defparam cnt1 . LPM_WIDTH = 4
LPMによるカウンタ作成 - シミュレーション結果 - リセット信号なし リセット信号有り
END