Presentation is loading. Please wait.

Presentation is loading. Please wait.

Verilog設計演習 Ⅰ 入 門 編 広島県立西部工業技術センター

Similar presentations


Presentation on theme: "Verilog設計演習 Ⅰ 入 門 編 広島県立西部工業技術センター"— Presentation transcript:

1 Verilog設計演習 Ⅰ 入 門 編 広島県立西部工業技術センター
Verilog設計演習 Verilog設計演習 Ⅰ  入 門 編 広島県立西部工業技術センター 広島県立西部工業技術センター

2 1.作業ディレクトリの作成  まず、エクスプローラを起動し、  ルートディレクトリの下にseminarというディレクトリを、  その下にVerilogというディレクトリを作成して下さい。 (DOS/Vの場合) C:¥seminar¥Verilog (98の場合) A:¥seminar¥Verilog 以下、Verilog演習で作成するファイルはVerilogの下に作ります。 それ以外の、ディレクトリには何も作らないで下さい。

3 2.Verilogの基本ブロック 例題1 aoiゲート aoi.v module aoi(a,b,c,d,f);
input a,b,c,d; output f; assign f=~((a & b)|(c & d));   endmodule

4 (1)verilogの基本ブロックはモジュール。
(2)モジュールはキーワードmoduleではじまり,endmoduleで終わる。 (3)キーワードmoduleの次にモジュール名と(ポートリスト);がつづく。 (4)ポートリストに書いた信号名の入出力宣言を次に行う。 入 力 = input 出 力 = output 双方向 = inout (5)入出力宣言とendmoduleの間にモジュールの本体機能を書く。   endmoduleにはセミコロン;はいらない。 (6)簡単な本体機能は,信号代入文assignを使って記述する。 assign 左辺 = 右辺 (7)Verilogのビット演算子は,C言語と同じ。 & AND 小林テキストP64 表3.2 | OR ~ NOT ^ EX-OR (8)わかりやすい様に( )を使ってよい。

5 クイックロジック社QuickWorks 配置配線ツールSpDE 兼 統合化環境 回路図入力 SYNARIO 論理合成 Synplify
兼 統合化環境 回路図入力 SYNARIO 論理合成 Synplify Verilogシミュレータ SILOSⅢ Verilog学習 VHDL学習 HDLエディタ ターボライタ

6 3.SpDEの起動  スタート - プログラム - QuickLogic ー SpDEで SpDEを起動します。

7 4.HDLエディタの起動 SpDEのツールバーから、HDLエディタのアイコン   を 押して、HDLエディタを起動し、クリエイトアイコン   を押す。

8 5.Verilogコードの入力、保存  例題1のVerilogコードを入力し、FileーSaveAsメニューから ¥seminar¥verilogの下に、ファイル名aoi.vで保存する。  拡張子が定まると、module、inputなどのVerilogキーワード が紺色でハイライトされます。紺色は見にくいのでHDLエディタの   WindowーColorsーKeyword で、青色に変更して下さい。 File-ExitでHDLエディタを終了し、SpDEに戻ります。 6.論理合成Synplifyの起動  SpdeのFile-Import-Verilogメニューから ¥seminar¥verilog¥aoi.vを指定し、論理合成ツールを 起動します。

9 7.ターゲットデバイスの指定と論理合成  RUNボタンのすぐ上のChangeボタンを押して、 Partをp8x12b、Packageをpl44に変更し、OKを押します。 次に、RUNボタンを押して、論理合成をかけます。

10 8.エラーの修正  ソースファイルにエラーがあると、下の画面で停止します。 ViewLogボタンでエラー内容を確認した後、Editボタンを 押して、HDLエディタを再度起動し、エラー箇所を修正します。

11 9.論理合成プロジェクトの保存  エラーがなければDoneが表示されて、下の画面で停止します。 「はい」を選んで論理合成プロジェクトを保存し、SpDEに戻ります。

12 10.配置配線の実行  SpDEのツールバーからRunToolsアイコン   を押して、 配置配線を実行します。途中、RUNと「いいえ」を選択します。

13 11.配置配線結果の確認  SpDEツールバーからFullFitアイコン   を選択し、 チップ全体を表示させます。

14  次に、View-NormalFitメニューを選択し、Zカーソルを
回路のある部分でクリックして、回路部分を拡大表示します。  さらに拡大したければZoomInアイコン   を使います。

15  回路部分のみを拡大すると、下図のようになります。
台形印のセレクタはr=s・p+s・qを表しますので、全体として a・b=1またはc・d=1の時 f=0 それ以外の時         f=1 となり、最初のVerilogコードを満す回路が生成されていること が分かります。 入力s  出力r  0     p  1     q ※論理合成結果を確認したら、 File-Saveメニューで結果を 保存します。

16 12.基本ブロック(続き)  HDLエディタを起動し、aoi.vを次のように修正します。 module aoi(a,b,c,d,f); input a,b,c,d; output f; // assign f=~((a & b)|(c & d)); wire ab,cd,o; assign ab=a & b; assign cd=c & d; assign o =ab | cd; assign f = ~o; endmodule AB CD

17 (1)やや複雑な機能を記述する時は,wireで宣言した
   ローカル信号を使うこともできる。        ab,cd,o (2)1ビット幅のwireは宣言なしでも使える。暗黙宣言。    後出の複数ビット幅のwireは宣言が必要。 (3)//は1行のみのコメント行。   /*・・・・・*/は複数行にわたるコメント行である。 修正が終わったらソースコードを保存し、論理合成をかけて 配置配線を実行して下さい。結果は同じになります。

18 問題1  インバータLS04.vを設計し、結果を確認しなさい。 問題2  NANDゲートLS00.vを設計し、結果を確認しなさい。 問題3  NORゲートLS02.vを設計し、結果を確認しなさい。

19 13.階層設計 例題2 マルチプレクサ mux2.v `include "aoi.v" module inv(a,f); input a;
output f; assign f=~a; endmodule module mux2(sel,a,b,f); input sel,a,b; inv g1 (sel,selb); aoi g2 (sel,a,selb,b,fb); inv g3 (.a(fb),.f(f)); g1 g2 g3 SELB FB SEL AOI

20 (1)もっと複雑な回路記述には階層設計を使う。
(2) 階層設計は,複数のモジュール宣言と モジュールインスタンスで行う。 (3) 複数モジュールの宣言は, invの様に,同一ファイル内に書いても良いし, aoiの様に,別ファイルに書いて,`includeしても良い。 (4) モジュールインスタンスは,サブルーチンコールの様なもので, モジュール名 インスタンス名(ポートリスト); の形式で行う。上の例では,g1,g2,g3がインスタンス名。

21 (5) モジュールインスタンスのポートリストは上位モジュールと
下位モジュールを接続するもので, g1,g2の様に,並びによる接続が一般的。 g3の様に,名前による接続も使える。 (6) 出力信号を接続しない時はカンマを余分に書く。 (7) 上の例ではselbとfbは,暗黙宣言されたwireである。 ※ `はバック・シングル・クォートで DOSVでは shift 98 では shift + ^  shift + 7 ではないことに注意。

22 例題2を入力し、論理合成、配置配線を実行します。
結果は、論理圧縮の効果で例題1より簡単になり、 下図のようになります。 sel=1なら f=a sel=0なら f=b となっています。 sel

23 14.条件付きassign文 例題3 セレクタ mux21.v   module mux21(sel,a,b,f); input sel,a,b; output f; assign f=sel ? a:b;   endmodule mux21 sel (1) 例題2(mux2.v)では階層設計を説明するため,複雑な書き方を    したが,セレクタ自体はもっと簡単に記述できる。 (2)assign文にはC言語の3項演算子(条件演算子ともいう)に似た   条件付きassign文があり, assign 左辺=(条件式1) ? (右辺1) : (右辺2);   が使える。 (3)上の例では,sel=1ならf=a,sel=0ならf=bになる。

24 15.always文とif文 例題3 セレクタ mux21.v   module mux21(sel,a,b,f); input sel,a,b; output f; reg f; or a or b) begin if(sel==1'b1) f=a; else f=b; end   endmodule mux21 sel (1)3項演算子よりも,わかりやすいif文もあるが,   module-endmodule間に,ダイレクトには記述できない。   上の例のように,alwaysブロックの中で記述する。

25 (2)always文は begin : end   ←セミコロンがないのに注意 の形で記述し,( )内の信号名の値が変化したときのみ評価される。 つまり,( )内にはalwaysブロックとしての入力信号を記述する。 正しくはセンシティビティ・リストという。  複数の入力信号が有る時は,カンマではなく orで区切って記述する。 (3)alwaysブロックで組合せ回路を生成する場合,入力信号を 全てセンシティビティ・リストに記述しなければならない。  (順序回路の場合はそうとは限らない)

26 (4)alwaysブロック内では,if文,case文が使え,
if(条件式) 式1; else 式2;  と書く。多重if文も使える。 if(条件式1) 式1; else if(条件式2) 式2; else 式3; (5)条件式に使う関係演算子はC言語と同じで == 等しい > 大    >= 以上 != 等しくない < 小    <= 以下 が使え,かつ,それらの論理演算 && 論理積 || 論理和    ! 論理否定 も使える。 (6)1ビット幅の定数は 1,0,1'b1,1'b0 と書く。 ' はSHIFT+7です。

27 (7)最も重要なのは,alwaysブロック内での
・信号代入には,assign文は使わないこと。 ・代入文の左辺にくる信号は,レジスタ宣言  しなければならないこと。 である。上の例では f がこれにあたる。 (8)上の例からわかる様に,生成される回路が組合せ回路で  あってもレジスタ宣言が必要である。逆に言うと,レジスタ宣言  してもフリップフロップが必ず生成されるわけではない。 (9)if文で全ての条件が列挙されていれば,つまり,   ifの数だけelseがあれば,組合せ回路が,   そうでなければ,順序回路が生成される。 例題3を入力し、論理合成、配置配線を実行します。 結果は例題2と同じになります。

28  Verilog設計演習 Ⅱ シミュレーション編    広島県立西部工業技術センター

29 1.テスト・フィクスチャの準備  例題3の設計mux21.vを、Verilogシミュレータを用いて 検証します。  設計検証用テストパターンを発生させるVerilogコードのことを テスト・フィクスチャと呼びます。拡張子は通常 .tf を使います。  HDLエディタでmux21.vを開いた状態で、 HDLー GenerateTestBench を実行すると、テストフィクスチャの雛形mux21.tfが生成されます。 (遅いマシンでは数分かかることも有ります。) (1) `timescale 1ns/1ns (2) module t; (3) reg sel,a,b; (4) wire f; (5) mux21 m (.sel(sel),.a(a),.b(b),.f(f)); (6) // Enter fixture code here (7) endmodule // t

30 (1)timescale文はシミュレーションの時間単位を定めるもので、
  /の前がこのモジュール内での時間記述#の時間単位、   /の後ろがシミュレーション時に使用される時間精度   になります。この例ではいずれも1nsになります。 (2)テストフィクスチャのモジュールには、ポートリストが有りません。   モジュール名は何でもかまいませんが、ここでは t です。 (3)元の設計データの入力信号は、このモジュール内では値を代入   するので、レジスタ宣言します。 (4)出力信号は観測するだけなので、ワイヤ宣言します。 (5)元の設計データをモジュールインスタンスとして、呼び出します。   信号の接続には、名前による接続が行われていますが、   並びによる接続でも構いません。 (6)この位置に、実際のテストパターン用コードを追加します。

31 `timescale 1ns/1ns module t; reg sel,a,b; wire f; mux21 m (.sel(sel),.a(a),.b(b),.f(f)); // Enter fixture code here initial begin   sel=0; a=0; b=0; #100 sel=0; a=0; b=1; #100 sel=0; a=1; b=0; #100 sel=0; a=1; b=1; #100 sel=1; a=0; b=0; #100 sel=1; a=0; b=1; #100 sel=1; a=1; b=0; #100 sel=1; a=1; b=1; end endmodule // t  それでは、6行目の位置に 右の四角の部分を追加して テスト・フィクスチャを完成さ せてから、mux21.tfとして 保存して下さい。  この例で分かるように、テスト フィクスチャでの信号値の代入 には、initial文を使用します。  意味としては、 sel,a,bの初期値として 全て0を代入した後、100ns 毎に異なる値を代入しています。

32 2.機能シミュレーション(Pre-Layout)
(1)SpDEのツールバーから、シミュレータのアイコン   を 押して、SILOS3を起動します。  シミュレーションタイプでPre-Layoutを選択します。 テストフィクスチャがmux21.tf、 トップレベルモジュールがmux21.vになっていることを 確認後、OKを押して下さい。

33 (2)mux21.vは論理合成のチェックを通っているので、
エラーがあるとすればmux21.tfの方です。  エラーがあるとoutputウインドウにエラーメッセージが表示され、 下の画面で停止するので、キャンセルを押します。  outputウインドウにエラーがなければ、(4)に進みます。

34 (3)エラーメッセージを確認後、SILOS3のFileーOpenメニュー
からmux21.tfを選択し、エラー箇所を修正します。  修正が終わったら、SILOS3のFile-Saveで保存し、 mux21.tfウインドウのアイコン化ボタン   でアイコン化します。  Load/Reloadアイコン   を押して、修正結果をSILOS3に 反映させます。  outputウインドウにエラーが無ければ、GOアイコン   を 押して(4)に進みます。  outputウインドウにエラーが有れば、エラーメッセージを確認後 アイコン化していたmux21.tfを通常の大きさに戻し、 修正を繰り返します。

35 (4)テストフィクスチャにエラーが無ければ、下の画面で停止します
ので、シミュレーション時間1000nsを入力し、OKを押します。

36 (5)エラーが無ければ、outputウインドウに
32 State changes on observable nets. Simulation stopped at the end of time 1.000us.が表示されるので データアナライザのアイコン   を押して、波形表示ウインドウ を開きます。 

37 次に、モジュールエクスプローラのアイコン   を押して、
t:tのa,b,f,selを選択後、マウス右クリックから AddSignaltoAnalyzerを選ぶと、波形が表示されます。

38  データアナライザ・ウインドウをアクティブにしてから、
View-ZoomAllを選ぶと、波形全体が表示されます。 sel=0の時f=b、   sel=1の時f=aを確認します。

39 (1)データアナライザ・ウインドウの時間軸上で、マウス右クリックし、
timescaleを選んで、切りの良い値を入れれば、時間軸を見やすい 値に変更できます。 (2)波形上でマウスを左クリックすると、青色の第1カーソル、 右クリックすると、赤色の第2カーソルを置くことができます。 各カーソルの時間および時間差がT1,T2,Tdeltaで表示されます。 (3)信号名を選択後、カーソルスキャン・アイコン           を 押すと、カーソルが選択信号の変化点に移動します。  この機能を使って、入力信号a,b,selと出力信号fの時間差を 測定してみると、Tdelta=0になります。  これは、現在表示している結果が、遅延時間情報の入っていない 機能シミュレーション(Pre Layout)であるためです。  結果を確認したら、SILO3のFile-Exitを選び、途中、「はい」を 選んで終了します。

40 3.遅延シミュレーション(Post-Layout)
 再びSpDEのツールバーから、シミュレータのアイコン   を 押して、SILOS3を起動します。  今度はシミュレーションタイプでPost-Layoutを選択します。 テストフィクスチャがmux21.tf、 SDFがmux21.sdf、 トップレベルモジュールがmux21.vq になっていることを 確認後、OKを押して下さい。

41 1000nsを確認後、OKを押します。

42 outputウインドウに92 State changes on observable nets.
Simulation stopped at the end of time ns.が表示され、 モジュールエクスプローラ、データアナライザウインドウも表示 されるので、ズームオール   で波形全体を表示させます。

43 (1)波形上でマウスを左クリックすると、青色の第1カーソル、
右クリックすると、赤色の第2カーソルを置くことができます。 各カーソルの時間および時間差がT1,T2,Tdeltaで表示されます。 (2)信号名を選択後、カーソルスキャン・アイコン           を 押すと、カーソルが選択信号の変化点に移動します。  この機能を使って、入力信号a,b,selと出力信号fの時間差を 測定してみると、今度はTdelta=9ns程度が表示されます。  これは、現在表示している結果が、遅延時間情報(mux21.sdf) を考慮した遅延シミュレーション(Post Layout)であるためです。  また、Verilogコードも元のmux21.vではなく、配置配線ツール の出力したmux21.vqが使用されています。 SDFはスタンダード・ディレイ・フォーマットといい、遅延時間情報の 標準フォーマットです。  結果を確認したら、SILO3のFile-Exitを選び、終了します。 興味があれば、*.sdf、*.vqをエディタで開いて見て下さい。

44 遅延シミュレーションの結果

45 問題4 インバータLS04.vのテストパターンを設計し、
     機能シミュレーションと遅延シミュレーションを  実行しなさい。 問題5 NANDゲートLS00.vのテストパターンを設計し、 問題6 NORゲートLS02.vのテストパターンを設計し、

46 4.ピン配置の指定  ピン配置は配置配線ツールが遅延時間や配線効率を考慮して 最適に近いものに自動配置するので、これを使うのが無難です。  しかし、設計の最終段階に近く、プリント基板の変更ができない 場合などは、次の方法でピン配置を直接指定することも可能です。  SpDEのTools-Optionsメニューから、BackAnnotationタブ を選択し、FixPlacementのIOcellsをチェックonにします。

47  OKを選択後、RunToolsアイコン   を押して、配置配線を
実行すると、ピン配置情報mux21.scpが生成されます。  現在、ピン16,17,18,19が割り当てられていることを確認 します。(マシンによっては異なることも有ります。) エディタでql_placement以下のピン番号を変更し、保存します。 #mux21.scp #Synplicity Synthesis pin location command file #Automatically generated by SpDE version SpDE 7.0 #Date: 8/10/98 at 10:02 # #---Fixed I/O cells--- portprop f ql_placement="IO2"; portprop a ql_placement="IO3"; portprop sel ql_placement="IO4"; portprop b ql_placement="IO5";

48  論理合成Synplifyを立ち上げて、Addボタンを押します。
ファイルの種類をPropertyFiles(*.sc*)にして、 mux21.scpを選択し、「開く」を押します。

49  SourceFilesにmux21.scpが追加されたことを確認後、
RUNを押して論理合成をかけます。  途中「はい」とOKを選択すると、mux21.scpで指定した ピン配置での配置配線が実行されます。

50 Verilog設計演習 Ⅲ  基 礎 編 広島県立西部工業技術センター

51 1.ビット幅のある信号の表現 例題1 コンパレータ comp.v module comp(a,b,eq,ge,le); parameter n=4; input [n-1:0] a,b; output eq,ge,le; reg eq,ge,le; or b) begin if(a==b) eq=1; else eq=0; if(a>=b) ge=1; else ge=0; if(a<=b) le=1; else le=0; end endmodule comp ge eq le

52 (1)今までは1ビット幅の信号だけ扱ってきたが,
  ビット幅のある信号も扱える。input,output宣言時に [MSB:LSB] 信号名,信号名;   とすれば良い。   同じビット幅,ビットオーダーの信号は1行で宣言できる。 [15:0] [8:1] [1:16] [0:7]   のいずれも使える。MSB,LSBの値の大小にかかわらず,   左端がMSB,右端がLSBである。 (2)ビット幅を変更しやすくするためにparameterを使うことができる。

53 例題1の続き module comp(a,b,eq,ge,le); parameter n=4; input [n-1:0] a,b; output eq,ge,le; assign eq=(a==b); assign ge=(a>=b); assign le=(a<=b); endmodule comp ge eq le (3)上の例の様に,コンパレータ等はif文よりもassign文の方が コンパクトに記述できる。

54 (1)initial文の中では integer宣言した i 、jを用いた forループが使えます。 i++ではないことに注意。
例題1のテストフィクスチャ comp.tf `timescale 1ns/1ns module t; parameter n=4; reg [n-1:0] a,b; wire eq,ge,le; integer i,j; comp m (.a(a),.b(b),.eq(eq),.ge(ge),.le(le)); // Enter fixture code here    initial begin for(i=0;i<16;i=i+1) begin a=i; for(j=0;j<16;j=j+1) begin b=j; #100; end end    end endmodule // t (1)initial文の中では integer宣言した i 、jを用いた forループが使えます。 i++ではないことに注意。

55 2.case文とビット幅のある定数 例題2 デコーダ decoder.v decode enb 8 y 3 adr
例題2 デコーダ decoder.v module decoder(enb,adr,y); input enb; input [2:0] adr; output [7:0] y; reg [7:0] y; or adr) begin if(!enb) case(adr) 3'b000: y=8'b ; 3'b001: y=8'b ; 3'b010: y=8'b ; 3'b011: y=8'b ; 3'b100: y=8'b ; 3'b101: y=8'b ; 3'b110: y=8'b ; 3'b111: y=8'b ; endcase else y=8'b ; end endmodule decode adr enb

56 (1)デコーダは,if文を並べて書くこともできるが, case文を使った方がわかりやすい。 case(信号名) ケース1:式1;
ケース2:式2; : default:式n; endcase と記述する。endcaseにはセミコロンはつけない。 (2)ビット幅のある定数は, ( 2進数)3'b001,8'b1111_1101,8'bZZZZ_ZZZZ (16進数)3'h1,8'hfc,8'hZZと書く。   'の前はビット幅である。 (3)if文の条件(!enb)は,本来(~enb)と書くべきであるが,    (!enb)も許される。 (4)else y=8'b ; が無いとラッチが生成されるので注意。

57 例題2のテストフィクスチャ decoder.tf
initial begin enb=0; for(i=0;i<8;i=i+1) begin adr=i; #100; end enb=1; endmodule // t 例題2のテストフィクスチャ decoder.tf `timescale 1ns/1ns module t; reg enb; reg [2:0] adr; wire [7:0] y; integer i; decoder m (.enb(enb),.adr(adr),.y(y)); // Enter fixture code here

58 3.算術演算子と連接演算子 例題3 アダー adder.v 4 adder 4 a s 4 b cin cout
module adder(cin,a,b,cout,s); parameter n=4; input cin; input [n-1:0]a,b; output [n-1:0]s; output cout; // assign {cout,s}=a+b+cin; reg [n-1:0]s; reg cout; or b or cin) begin {cout,s}=a+b+cin; end endmodule adder cin cout (1)加算器,減算器,乗算器を生成するのに算術演算子+、-、*が使える。 (2)加算結果には,キャリ出力がつきものであるが,連接演算子{ , }を使って {cout,s}=a+b+cin; とわかりやすく記述できる。

59 例題3のテストフィクスチャ adder.tf
例題3のテストフィクスチャ adder.tf `timescale 1ns/1ns module t; parameter n=4; reg cin; reg [n-1:0]a,b; wire [n-1:0]s; wire cout; integer i; adder m (.cin(cin),.a(a),.b(b),.cout(cout),.s(s)); // Enter fixture code here initial begin cin=0; for(i=0;i<256;i=i+1) begin {a,b}=i; #100; end cin=1; endmodule // t このテストフィクスチャでは連接演算子を使って、二重ループを一重ループで済ませています。

60 4.フリップフロップの記述 例題4 フリップフロップ dff.v d clk q d clk qsc sclr d clk qac aclr
例題4 フリップフロップ dff.v module dff(d,clk,sclr,aclr,enb,q,qsc,qac,qen); input d,clk,sclr,aclr,enb; output q,qsc,qac,qen; reg q,qsc,qac,qen; // simple ff // clk) q <= d; // sync clear ff // if(~sclr) qsc <= 0; else qsc <= d; // async clear ff // clk or negedge aclr) if(~aclr) qac <= 0; else qac <= d; // enb ff // if(enb) qen <= d; endmodule clk 通常  FF clk qsc sclr 同期 クリア  FF clk qac aclr 非同期 クリア  FF clk qen enb イネーブル 機能付  FF

61 (1)フリップフロップの生成には clk)   を使う。clk信号の立ち上がりエッジでalways文が実行される。   立ち下がり動作のFFにはnegedgeを使います。   センシティビティ・リストに記述しない。 (3)非同期クリア信号は,センシティビティ・リストに記述する。   aclrが正論理なら、posedgeを使います。 (4)イネーブル信号は同期クリア信号と同じ。 (5)この例で用いている<=はノンブロッキング代入文と呼ばれ,   順序回路では,これを使った方がよい。   =はブロッキング代入文と呼ばれ組合せ回路用。   但し,上の例では全て=にしても同じ回路が生成される。

62 例題4のテストフィクスチャ dff.tf ※クロック生成の無限ループにはforever を使うことができる。 module t;
例題4のテストフィクスチャ dff.tf module t; reg d,clk,sclr,aclr,enb; wire q,qsc,qac,qen; dff m (.d(d),.clk(clk), .sclr(sclr),.aclr(aclr),.enb(enb), .q(q),.qsc(qsc),.qac(qac),.qen(qen)); // Enter fixture code here initial begin clk=0; forever begin #50; clk=~clk; end initial begin aclr=1; sclr=1; enb=1; d=1; #125 d=0; #200 d=1; #300 aclr=0;sclr=0;enb=0; #200 d=0; #300 aclr=1;sclr=1;enb=1; end endmodule // t ※クロック生成の無限ループにはforever  を使うことができる。

63 5.ブロッキング代入文とノンブロッキング代入文 例題5 エッジ検出 edg.v
例題5 エッジ検出 edg.v module edg(clk,d,reset,rise,fall); input clk,d,reset; output rise,fall; reg q1,q2; clk) begin if(!reset) begin  q1=0; end   else  begin q1=d; end end if(!reset) begin q2=0;  end   else  begin q2=q1; end assign rise= q1 & !q2; assign fall=!q1 & q2; endmodule clk q1 q2 fall rise

64 (1)スイッチが押された時,1回だけある動作をさせたい時など,
入力信号の立ち上がり,立ち下がりを検出する手段として, 図のようなエッジ検出回路が使用される。 (2)このrise,fall検出回路を1つのalways文で実現しようとすれば, <= ノンブロッキング      = ブロッキング の違いがわかる。上記の四角の部分は下記に置き換えられるが、 <=の代わりに、=を使うと,q1とq2が同じになり,rise,fallも消える。 clk) begin if(!reset) begin q1<=0; q2<=0;  end   else  begin q1<=d; q2<=q1; end end (3)ノンブロッキング<=は、各右辺の処理が終了してから代入処理 が行われる。記述の順番に動作が影響されないので順序回路向き。 (4)ブロッキング=は、一つの代入処理が終了するまで次の処理が 行われない。記述の順番に動作が影響される。組合せ回路向き。

65 例題5のテストフィクスチャ edg.tf `timescale 1ns/1ns module t; reg clk,d,reset;
wire rise,fall; edg m (.clk(clk),.d(d),.reset(reset), .rise(rise),.fall(fall)); // Enter fixture code here initial begin clk=0; forever begin #50 clk=~clk; end initial begin reset=0; d=0; #75 reset=1; #200 d=1; #300 d=0; #400 d=1; #400 d=0; end endmodule // t

66 6.同期クリア付きカウンタ 例題6 countsc.v module countsc(clk,clr,count); input clk,clr; output [3:0]count;  reg [3:0]count; clk) begin if(!clr) count <= 0; else count <=count+1; end endmodule countsc count clk clr (1)同期クリア付カウンタは,同期クリアFFのクリア信号の書き方と,  算術演算子+の応用であり,上の例の様にかける。  順序回路なので代入には、ノンブロッキングを使った方が良い。 (小テスト)これを10進カウンタにするには、どうすればよいか。

67 例題6のテストフィクスチャ countsc.tf
例題6のテストフィクスチャ countsc.tf `timescale 1ns/1ns module t; reg clk,clr; wire [3:0]count; countsc m (.clk(clk),.clr(clr),.count(count)); // Enter fixture code here initial begin clk=0; forever begin #50; clk=~clk; end initial begin clr=1; #125; clr=0; #200; clr=1; end endmodule // t

68 countac 7.非同期クリア付きカウンタ 例題7 countac.v module countac(clk,clr,count); input clk,clr; output [3:0]count;  reg [3:0]count; clk or negedge clr) begin if(!clr) count <= 0; else count <=count+1; end endmodule count clk clr (1)非同期クリア付カウンタは,非同期クリアFFのクリア信号の   書き方と,算術演算子+の応用であり,上の例の様にかける。   順序回路なので代入には、ノンブロッキングを使った方が良い。 (小テスト)これにキャリー入出力を付けるには、どうすればよいか。

69 例題7のテストフィクスチャ countac.tf
例題7のテストフィクスチャ countac.tf `timescale 1ns/1ns module t; reg clk,clr; wire [3:0]count; countac m (.clk(clk),.clr(clr),.count(count)); // Enter fixture code here initial begin clk=0; forever begin #50; clk=~clk; end initial begin clr=1; #125; clr=0; #200; clr=1; end endmodule // t

70 8.ステートマシンの記述 例題8 state.v 1 S11 a a a a S01 S10 a a S00
例題8 state.v module state(clk,a,res,ss); input clk,a,res; output [1:0]ss; reg [1:0]ss; parameter s00=2'b00; parameter s01=2'b01; parameter s10=2'b10; parameter s11=2'b11; clk) begin   if(~res) ss=s00; else case(ss) s00: if(a) ss=s01; else ss=s10; s01: if(a) ss=s11; s10: if(~a) ss=s11; s11: ss=s00; endcase end endmodule S11 S01 S10 S00

71 (1)verilogのステートマシン記述では,上の例の様に
  ステートの値は,parameterを使って,物理的な値を割り当てます。 (2)このステートマシンは,s00が初期状態で,  入力 a=1なら s00 → s01 → s11  (但し,s01でa=0なら,s01のまま) ↑ │ └─────┘  入力 a=0なら s00 → s10 → s11  (但し ,s10でa=1なら,s10のまま) と回るものです。case文を使えば,上述のようにすっきり書けます。 (3)ステートマシンには、出力値が ステート値のみに依存するムーア型と 入力値とステート値に依存するミーリー型 がありますが、ここでは深くは述べません。

72 例題8のテストフィクスチャ state.tf
例題8のテストフィクスチャ state.tf `timescale 1ns/1ns module t; reg clk,a,res; wire [1:0]ss; state m (.clk(clk),.a(a),.res(res),.ss(ss)); // Enter fixture code here initial begin clk=0; forever begin #50; clk=~clk; end initial begin res=0;a=0; #100; res=1; #700; res=0;a=1; end endmodule // t

73 9.トライステート出力 例題9 triout.v module triout(a,oe,y); input a,oe; output y; assign y=oe? a: 1'bZ; endmodule oe (1)トライステート出力、双方向バスの記述は実用的なLSIを   設計する上でさけて通れない。 (2)1ビットのハイインピーダンスは1'bZと書く。   Zだけではローカル信号になるので注意。 8ビットは 8'bZZZZ_ZZZZ または 8'hZZ (3)トライステート出力は,上の例の様に条件付assign文で記述する。   トライステート出力はoutput宣言する。 (小問題)if文を使って、トライステート出力を記述しなさい。

74 例題9のテストフィクスチャ triout.tf
例題9のテストフィクスチャ triout.tf `timescale 1ns/1ns module t; reg a,oe; wire y; integer i; triout m (.a(a),.oe(oe),.y(y)); // Enter fixture code here initial begin oe=0; #450; oe=1; #500; end initial begin a=0; for(i=0;i<10;i=i+1) #100 a=~a; end endmodule // t

75 (1)双方向バスも,上の例の様に条件付assign文で記述する。 双方向バスはinout宣言する。
10.双方向バスの記述 例題10 bidir.v module bidir(rd,wr,db);  input rd,wr;  inout  db;  wire idb;  reg odb;  assign idb=db; wr) odb<=idb;  assign db=rd? 1'bZ : odb; endmodule rd wr db idb odb D Q (1)双方向バスも,上の例の様に条件付assign文で記述する。   双方向バスはinout宣言する。 (2)if文を使って書こうとしても、双方向バスはうまくいかない。

76 例題10のテストフィクスチャ bidir.tf 0 50 100 150 200 rd rd_dt 前の値 rd↑時のdbの値
例題10のテストフィクスチャ  bidir.tf `timescale 1ns/1ns module t; reg rd,wr; wire db; reg rd_data; bidir m (.rd(rd),.wr(wr),.db(db)); // Enter fixture code here task wr_task;   input wr_dt;     begin force db=wr_dt; #50; wr=0; #50; wr=1; #50; release db; #50;     end endtask rd rd_dt 前の値   rd↑時のdbの値 task rd_task;   output rd_dt;     begin rd=0; #100; rd_dt=db; rd=1; #100;     end endtask initial begin   rd=1; wr=1; db=1'bZ;   #100; wr_task(1); rd_task(rd_data);   $display("time=%4d rd_data=%b", $time,rd_data);   #100; wr_task(0); rd_task(rd_data); end endmodule // t db wr_dt Z wr

77 (1)タスクはテストフィクスチャで使用されるサブルーチン。
(2)タスクはキーワードtaskで始まり、endtaskで終わる。 (3)キーワードtaskの次に、タスク名を書く。   上の例ではでは wr_task と rd_task がタスク名。 (4)タスク名の次に引数宣言を行う。 wr_taskでは、入力引数wr_dt  rd_taskでは、出力引数rd_dt が宣言されている。 (5)上の例ではinitial文のメインルーチンから、  wr_taskとrd_taskを2回づつコールして、  データバスから1と0の書込み、読出しの確認をしている。

78 (6)双方向バスdbはテストフィクスチャ内では、ワイヤ宣言する。
(7)双方向バスdbの初期値=Zとする。(Zは代入可能) (8)双方向バスdbにZ以外の値を代入するときは、force文を使う。 (9)強制代入を解除するときは、release文を使う。 (10)$displayはoutputウインドウに値を表示するための   システムタスクであり、書式はC言語のprintf文と同じ。   $timeは現在時刻を表すシステム関数。

79 Verilog設計演習 Ⅳ  応 用 編 広島県立西部工業技術センター

80 次の回路図のハードウエアを用意しています。
1.ストップウオッチの設計  次の回路図のハードウエアを用意しています。 (問題1) 100Hzの方形波をカウントして、下記の仕様の4桁ストップ ウオッチをVerilog-HDLで記述しなさい。 startスイッチを押すと、カウント開始 stopスイッチを押すと、カウント停止 両方同時に押すと、リセット (問題2)  startスイッチだけで、スタート、ストップ、リセットができる 仕様に変更しなさい。

81 ①module digit(clk,res,cin,cout,led);
  input clk,res,cin;   output cout;   output [6:0]led;   reg [3:0]dgt;   reg [6:0]led; clk) begin if( ) dgt<=0; else if(cin && ( )) dgt<=dgt+1; else if(cin && (dgt==9)) dgt<=0;   end ③assign cout=cin & ( ); begin case(dgt) 0: led=~7'h3f; 1: led=~7'h06; 2: led= ; 3: led= ; 4: led= ; 5: led= ; 6: led= ; 7: led= ; 8: led= ; 9: led= ; default: led=~7’h00; endcase  end  endmodule ①モジュールdigitはLED一桁に相当す るサブモジュールで、カウンタ部と7セグ メントデコーダ部で構成されています。 ②カウンタ部はclkをクロック、resを正論 理の同期クリア信号とする4ビットカウン タです。10進カウンタなので、9の次は 0に戻らなければなりません。 ③キャリー入力が有り、かつカウント値が9の時、キャリー出力が出なければなりません。 ④7セグメントデコーダ部は、カウント値を数字表示用データに変換する組合せ回路です。

82 ⑤module watch1(start,stop,clk,led1,led2,led3,led4);
  input start,stop,clk;   output [6:0]led1,led2,led3,led4;   reg [1:0]state;   wire dres,enb1,enb2,enb3,enb4; ⑤parameter reset=2'b00;   parameter count=2'b01;   parameter display=2'b10; clk) begin if(start & stop) state=reset; else if(    &    ) state=count; else if(    &    ) state=display;   end   assign enb1=(       );   assign dres=(state==reset); ⑥digit digit1(clk,dres,enb1,enb2,led1); ⑦digit digit2(clk,dres,   ,   ,led2);  digit digit3(clk,dres,   ,   ,led3);  digit digit4(clk,dres,   ,   ,led4); endmodule ⑤モジュールwatch1がメインモジュールで reset,count,displayの3つの状態を遷移する ステートマシンです。条件は下記の通り。 startのみでcountへ stopのみでdisplayへ 両方でresetへ ⑥digit1~digit4はそれぞれ   digit1 1/100秒の桁   digit2 1/10秒の桁   digit 秒の桁   digit 秒の桁 に相当するモジュールインスタンスです。 ⑦enb1~enb4はdigit1~digit4のキャリ入力 とキャリ出力を接続するローカル信号です。 digit4 enb4 digit3 enb3 digit2 enb2 digit1 enb1

83 2.並列IOの設計 下記仕様の8ビット×3ポート入出力LSI (インテル8255の簡易版)を設計しなさい。 cs rd wr adr 動 作
 下記仕様の8ビット×3ポート入出力LSI (インテル8255の簡易版)を設計しなさい。 cs rd wr adr 動    作 H × × ×× 非 動 作 00 DB←PAピン L L  H  01 DB←PBピン 10 DB←PCピン 11 DB←CRレジスタ 00 DB→PAレジスタ L H ↑ 01 DB→PBレジスタ 10 DB→PCレジスタ 11 DB→CRレジスタ CRレジスタはPA、PB、PCの入出力を 決める内部レジスタ。 CR(0) 0 PA=出力モード       1 PA=入力モード CR(1) 0 PB=出力モード              1 PB=入力モード        CR(2) 0 PC=出力モード              1 PC=入力モード    PIO ADR   PA CS    PB RD WR    PC DB   CR RES RESはPA,PB,PCを全て 入力モードにする負論理の 非同期リセット信号。

84 ① 並列IO pio.v module pio(cs,rd,wr,adr,res,db,pa,pb,pc); parameter n=8;
並列IO  pio.v module pio(cs,rd,wr,adr,res,db,pa,pb,pc); parameter n=8; input cs,rd,wr,res; input [1:0]adr; inout [n-1:0]db,pa,pb,pc; reg [n-1:0]qa,qb,qc,cr,odb; /***** internal register (reset , cs & wr) *****/ begin if(    )begin qa=0; qb=0; qc=0; cr=8'hFF; end else if(   ) case(   ) 0:qa=db; 1:qb=db; 2:qc=db; 3:cr=db; endcase ①qa,qb,qc,crはwrをクロック、 ~resを非同期クリア信号とするFFで csがアクティブの時、dbの値がadrで 選択されたqa,qb,qc,crのいずれか に書き込まれる。

85 ② ③ ④ /***** port tri-state assign *****/ assign pa=( )?qa:8'hZZ;
assign pb=(      )?qb:8'hZZ; assign pc=(      )?qc:8'hZZ; /***** data selecter *****/ or    or    or    or   ) begin case(adr) 0:odb=pa; 1:odb=pb; 2:odb=pc; 3:odb=cr; endcase end /***** databus tri-state assign (cs & rd) *****/ assign db=(    &     )? odb:8'hZZ; endmodule ②paは~cr[0]を制御信号とする双方向バッファ pbは~cr[1]を制御信号とする双方向バッファ pcは~cr[2]を制御信号とする双方向バッファ ③はpa,pb,pc,crをデータ入力   adrをセレクト信号   odbをデータ出力とする   データセレクタ ④dbは~csと~rdの論理積を 制御信号とする双方向バッファ

86 PIOのテストフィクスチャ pio.tf `timescale 1ns/1ns module t; reg cs,rd,wr,res; reg [1:0]adr; wire [7:0]db,pa,pb,pc; integer i; reg [7:0]rd_data; pio m (.cs(cs),.rd(rd),.wr(wr),.adr(adr),.res(res),.db(db),.pa(pa),.pb(pb),.pc(pc)); assign pa=pb; // connect PB to PA // Enter fixture code here task wr_task; input [1:0]adr_dt; input [7:0]wr_dt; begin cs=0; adr=adr_dt; force db=wr_dt; #50; wr=0; #100; wr=1; #50; cs=1; adr=2'b11; release db; #50; end endtask

87 task rd_task; input [1:0]adr_dt; output [7:0]rd_dt; begin cs=0; adr=adr_dt; #50; rd=0; #100; rd_dt=db; rd=1; #50; cs=1; adr=2'b11; #50; end endtask initial begin cs=1; rd=1; wr=1; adr=2'b11; db=8'bZZ; res=0; #50; res=1; #50; wr_task(3,1); //write CW to CR (PA=in PB,PC=out) for(i=0;i<=255;i=i+1) begin wr_task(1,i);   // write to PB rd_task(0,rd_data); // read from PA $display("i=%x rd_data=%x",i,rd_data); #1000; $finish; endmodule // t

88

89 解答例 watch1.v ①module digit(clk,res,cin,cout,led); input clk,res,cin;
  output cout;   output [6:0]led;   reg [3:0]dgt;   reg [6:0]led; clk) begin if(res) dgt<=0; else if(cin && (dgt!=9)) dgt<=dgt+1; else if(cin && (dgt==9)) dgt<=0;   end ③assign cout=cin & (dgt==9); begin case(dgt) 0: led=~7'h3f; 1: led=~7'h06; 2: led= ~7’h5b; 3: led=~7’h4f; 4: led= ~7’h66; 5: led=~7’h6d; 6: led=~7’h7d; 7: led=~7’h27; 8: led=~7’h7f; 9: led=~7’h6f; default: led=~7’h00; endcase  end  endmodule 解答例 watch1.v

90 ⑤module watch1(start,stop,clk,led1,led2,led3,led4);
  input start,stop,clk;   output [6:0]led1,led2,led3,led4;   reg [1:0]state;   wire dres,enb1,enb2,enb3,enb4; ⑤parameter reset=2'b00;   parameter count=2'b01;   parameter display=2'b10; clk) begin if(start & stop) state=reset; else if(start & ~stop) state=count; else if(~start & stop) state=display;   end   assign enb1=(state==count);   assign dres=(state==reset); ⑥digit digit1(clk,dres,enb1,enb2,led1); ⑦digit digit2(clk,dres,enb2,enb3,led2);  digit digit3(clk,dres,enb3,enb4,led3);  digit digit4(clk,dres,enb4,   ,led4); endmodule

91 解答例 pio.v module pio(cs,rd,wr,adr,res,db,pa,pb,pc); parameter n=8;
解答例  pio.v module pio(cs,rd,wr,adr,res,db,pa,pb,pc); parameter n=8; input cs,rd,wr,res; input [1:0]adr; inout [n-1:0]db,pa,pb,pc; reg [n-1:0]qa,qb,qc,cr,odb; /***** internal register (reset , cs & wr) *****/ wr or negedge res) begin if(~res)begin qa=0; qb=0; qc=0; cr=8'hFF; end else if(~cs) case(adr) 0:qa=db; 1:qb=db; 2:qc=db; 3:cr=db; endcase

92 /***** port tri-state assign *****/
assign pa=(~cr[0])?qa:8'hZZ; assign pb=(~cr[1])?qb:8'hZZ; assign pc=(~cr[2])?qc:8'hZZ; /***** data selecter *****/ or pa or pb or pc or cr) begin case(adr) 0:odb=pa; 1:odb=pb; 2:odb=pc; 3:odb=cr; endcase end /***** databus tri-state assign (cs & rd) *****/ assign db=(~cs & ~rd)? odb:8'hZZ; endmodule


Download ppt "Verilog設計演習 Ⅰ 入 門 編 広島県立西部工業技術センター"

Similar presentations


Ads by Google