1
Verilog-HDL 講習会DE0編(7) 順序回路記述(2)
~状態遷移図に基づく設計~
3, July, 2013 鹿児島大学 中原 啓貴
2
状態遷移図 • 順序回路の「ふるまい」を記述する図 ‒ 円:状態を表す ‒ 枝:遷移先を表す ‒ 枝の値:状態遷移の条件(入力値)と出力値を表す
条件(入力値) 出力値
条件と出力値は 線で区切る 初期状態
(リセット後の初期値) を記入する
例題: 3進カウンタ (En==1でカウント)
Q0 Q1 Q2
En==1 Out=2'b01
En==1 Out=2'b10
En==1 Out=2'b00
En==0 Out=2'b00
En==0 Out=2'b01
En==0 Out=2'b10
Reset Out=2'b00
3
DE0ボードに合わせて 信号線名を変更
条件(入力値) 出力値
条件と出力値は 線で区切る 初期状態
(リセット後の初期値) を記入する
例題: 3進カウンタ (SW[0]==1でカウント)
Q0 Q1 Q2
SW[0]==1 LEDG=2'b01
SW[0]==1 LEDG=2'b10
SW[0]==1 LEDG=2'b00 SW[0]==0
LEDG=2'b00 SW[0]==0 LEDG=2'b01
SW[0]==0 LEDG=2'b10
Reset LEDG=2'b00
• Reset -> BUTTON[0]: 負論理(押す:0, 離す: 1) • Out -> LEDG[1:0]: 正論理(点灯:1, 消灯:0) • En -> SW[0]: 正論理(上にスライド:1, 下にスライド:0)
4
• ピン配置が面倒くさいので、デフォルトのプロジェクトを読み込みましょう! (DE0に限った事ではないが、Terasic製品はサンプルCD-ROMの プロジェクトを改変するのが楽でお勧め)
DE0付属のCD-ROM ”Demonstrations”内の "DE0_Top"フォルダの ファイル全てを C:¥verilog¥DE0_tutorial_7_1¥ 内にコピー
DE0_TOP.qpfをダブルクリックしてQuartus IIを起動
5
Pin Plannerを開いてみると ピン配置が終わっている!
Verilog-HDLを入力
6
ダブルクリック Verilog-HDLの テンプレートが 表示されるので コードを入力
コード入力したら保存を忘れずに!
7
状態遷移図からVerilog-HDL (1) • 状態に2進符号(状態変数)を割当て
条件(入力値) 出力値
条件と出力値は 線で区切る 初期状態
(リセット後の初期値) を記入する
例題: 3進カウンタ (SW[0]==1でカウント)
00 01 10
SW[0]==1 LEDG=2'b01
SW[0]==1 LEDG=2'b10
SW[0]==1 LEDG=2'b00 SW[0]==0
LEDG=2'b00 SW[0]==0 LEDG=2'b01
SW[0]==0 LEDG=2'b10
Reset LEDG=2'b00
8
状態遷移図から Verilog-HDL (2) • モジュール宣言を記述 ‒ クロックとリセットも 忘れずに!
00 01 10
SW[0]==1 LEDG=2'b01
SW[0]==1 LEDG=2'b10
SW[0]==1 LEDG=2'b00
SW[0]==0 LEDG=2'b00
SW[0]==0 LEDG=2'b01
SW[0]==0 LEDG=2'b10
module DE0_TOP(CLOCK_50, SW, BUTTON, LEDG );
endmodule
Reset LEDG=2'b00
ここはDE0_TOPの テンプレートで 既に記述済み
9
状態遷移図から Verilog-HDL (3) • 入出力宣言 • 出力値と状態変数を レジスタ宣言
00 01 10
module DE0_TOP(CLOCK_50, SW, BUTTON, LEDG ); input CLOCK_50; input [9:0]SW; input [2:0]BUTTON; output [9:0]LEDG; (途中テンプレート省略) reg [1:0]LEDG; reg [1:0]state;
endmodule
「LEDG」は出力でもあり レジスタでもある
ここはDE0_TOPの テンプレートで 既に記述済み
SW[0]==1 LEDG=2'b00
SW[0]==0 LEDG=2'b00
SW[0]==0 LEDG=2'b01
SW[0]==0 LEDG=2'b10
SW[0]==1 LEDG=2'b01
SW[0]==1 LEDG=2'b10
Reset LEDG=2'b00
10
状態遷移図から Verilog-HDL (4) • リセット後のレジスタの 初期値を記述
00 01 10
module DE0_TOP(CLOCK_50, SW, BUTTON, LEDG ); input CLOCK_50; input [9:0]SW; input [2:0]BUTTON; output [9:0]LEDG; (途中テンプレート省略) reg [1:0]LEDG; reg [1:0]state; always@( posedge CLOCK_50 or negedge SW[0]) begin if( SW[0] == 1'b0)begin LEDG <= 2'b00; state <= 2'b00; end else begin end end
endmodule
SW[0]==1 LEDG=2'b01
SW[0]==1 LEDG=2'b10
Reset LEDG=2'b00
SW[0]==1 LEDG=2'b00
SW[0]==0 LEDG=2'b00
SW[0]==0 LEDG=2'b01
SW[0]==0 LEDG=2'b10
11
状態遷移図から Verilog-HDL (5) • case文を使って状態を記述 defaultを忘れずに!
00 01 10
module DE0_TOP(CLOCK_50, SW, BUTTON, LEDG ); input CLOCK_50; input [9:0]SW; input [2:0]BUTTON; output [9:0]LEDG; (途中テンプレート省略) reg [1:0]LEDG; reg [1:0]state; always@( posedge CLOCK_50 or negedge SW[0]) begin if( SW[0] == 1'b0)begin LEDG <= 2'b00; state <= 2'b00; end else begin case( state) 2'b00: begin end 2'b01: begin end 2'b10: begin end default: begin end endcase end
end endmodule
SW[0]==1 LEDG=2'b01
SW[0]==1 LEDG=2'b10
Reset LEDG=2'b00
SW[0]==1 LEDG=2'b00
SW[0]==0 LEDG=2'b00
SW[0]==0 LEDG=2'b01
SW[0]==0 LEDG=2'b10
12
状態遷移図から Verilog-HDL (6) • if文を使って状態遷移を記述
00 01 10
module DE0_TOP(CLOCK_50, SW, BUTTON, LEDG ); input CLOCK_50; input [9:0]SW; input [2:0]BUTTON; output [9:0]LEDG; (途中テンプレート省略) reg [1:0]LEDG; reg [1:0]state; always@( posedge CLOCK_50 or negedge SW[0]) begin if( SW[0] == 1'b0)begin LEDG <= 2'b00; state <= 2'b00; end else begin case( state) 2'b00: begin if( SW[0] == 1'b1)begin state <= 2'b01; end else begin state <= state; end end
2'b01: begin if( SW[0] == 1'b1)begin state <= 2'b10; end else begin state <= state; end end 2'b10: begin if( SW[0] == 1'b1)begin state <= 2'b00; end else begin state <= state; end end default: begin state <= 2'b00; end endcase end end endmodule
SW[0]==1 LEDG=2'b00
SW[0]==0 LEDG=2'b00
SW[0]==0 LEDG=2'b01
SW[0]==0 LEDG=2'b10
SW[0]==1 LEDG=2'b01
SW[0]==1 LEDG=2'b10
Reset LEDG=2'b00
13
状態遷移図から Verilog-HDL (7) • 状態遷移時の出力を記述
00 01 10
module DE0_TOP(CLOCK_50, SW, BUTTON, LEDG ); input CLOCK_50; input [9:0]SW; input [2:0]BUTTON; output [9:0]LEDG; (途中テンプレート省略) reg [1:0]LEDG; reg [1:0]state; always@( posedge CLOCK_50 or negedge SW[0]) begin if( SW[0] == 1'b0)begin LEDG <= 2'b00; state <= 2'b00; end else begin if( SW[0] == 1'b1)begin state <= 2'b01; LEDG <= 2'b01; end else begin state <= state; LEDG <= 2'b00; end end
2'b01: begin if( SW[0] == 1'b1)begin state <= 2'b10; LEDG <= 2'b10; end else begin state <= state; LEDG <= 2'b01; end end 2'b10: begin if( SW[0] == 1'b1)begin state <= 2'b00; LEDG <= 2'b00; end else begin state <= state; LEDG <= 2'b10; end end default: begin state <= 2'b00; LEDG <= 2'b00; end endcase end end endmodule
SW[0]==1 LEDG=2'b01
SW[0]==1 LEDG=2'b10
Reset LEDG=2'b00
SW[0]==1 LEDG=2'b00
SW[0]==0 LEDG=2'b00
SW[0]==0 LEDG=2'b01
SW[0]==0 LEDG=2'b10
14
記述するVerilog-HDLコード
15
テストベンチの追加
右クリック-> New Source
論理合成(XST) を行う
シミュレーションモードに切替え
Verilog Test Fixture を選択
testbench_first_state_machine
残りはデフォルトのまま
16
テストベンチの記述
リセット信号の記述
イネーブル信号 (カウントを行う信号) をオン
クロック信号を記述 #1 で 1psec なので, #50000 (一周期#100000) 100000psec=100nsec つまり10MHz のクロック
17
動作の確認
3進カウンタを 確認する count_value = {LEDG[1],LEDG[0]}
count_value_decは十進表示
18
例題: 暗号鍵マシーン • 正しい鍵(4ビットのスイッチ)を4回入力で鍵が開く (LEDが点灯する) ‒ 初期状態(リセット後):LED消灯
‒ 1回目の鍵入力:LEDが1つ点灯
‒ 2回目の鍵入力:LEDが2つ点灯
‒ 3回目の鍵入力:LEDが3つ点灯
‒ 4回目の鍵入力:LEDが全て点灯
状態遷移図を書いてみよう!
0 1 1 0
1 1 0 0
0 0 1 0
1 1 1 0
19
暗号鍵マシーンの状態遷移図 (状態番号も割当て済み)
000 001 010
SW==4'b0111 LEDG=4'b0001
Reset LEDG=4'b0
011
SW==4'b1100 LEDG=4'b0011
SW==4'b0010 LEDG=4'b0111
SW!=4'b0111 LEDG=4'b0000
SW!=4'b1100 LEDG=4'b0001
SW!=4'b0010 LEDG=4'b0011
SW!=4'b1110 LEDG=4'b0111
100
SW==4'b1110 LEDG=4'b1111
NONE LEDG=4'b1111
不一致(成立しないとき)は 「!=」を使う 無条件で遷移するとき
(次のクロックで遷移) は「NONE」
20
• ピン配置が面倒くさいので、デフォルトのプロジェクトを読み込みましょう! (DE0に限った事ではないが、Terasic製品はサンプルCD-ROMの プロジェクトを改変するのが楽でお勧め)
DE0付属のCD-ROM ”Demonstrations”内の "DE0_Top"フォルダの ファイル全てを C:¥verilog¥DE0_tutorial_7_2¥ 内にコピー
DE0_TOP.qpfをダブルクリックしてQuartus IIを起動
21
Pin Plannerを開いてみると ピン配置が終わっている!
Verilog-HDLを入力
22
ダブルクリック Verilog-HDLの テンプレートが 表示されるので コードを入力
コード入力したら保存を忘れずに!
23
入力する Verilog-HDL
動作確認 • 合成してFPGAにダウンロードしてみよう • 順番に正しい鍵を入力するとLEDGが点灯するはず
24
0 1 1 0
1 1 0 0
0 0 1 0
1 1 1 0
リセット(初期化) スイッチ
25
まとめ • 今回の学習内容 ‒ 状態遷移図の書き方 ‒ 状態遷移図からVerilog-HDLを記述する方法
• 上記以外にVerilog-HDLを記述する方法 ‒ 回路図から記述 (パイプラインを組むときに使う) ‒ C言語で記述したビヘイビアから記述 (プロはこの方法を使います)
26
課題 • 例題1の2進カウンタにスイッチを1つ追加し ‒ ONのときはアップ・カウンタ(00→01→10→00) ‒ OFFのときはダウン・カウンタ(10→01→00→10) となる回路を設計し, シミュレーションで動作を確認せよ (余裕のある人はFPGA上で動作させる. ただし, そのままではクロックが早すぎてカウントが見えないから一工夫必要) • 例題2の暗号鍵マシーンに 各鍵を入力する前に全てのスイッチをOFFにしなければ動作しない ように修正し, FPGA上で正しく動作することを確認せよ