verilog-hdl 講習会de0編(8) 順序回路記述(3) ~コンパクトな乗算 … · 1...
TRANSCRIPT
1
Verilog-HDL 講習会DE0編(8) 順序回路記述(3)
~コンパクトな乗算器~
3, July, 2013 鹿児島大学 中原 啓貴
2
2進数の乗算 (例: 18 x 21 = 378)
1 0 0 1 0 1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 1 0 0 1 0
1 0 1 1 1 1 0 1 0
× 18 21
256+64+32+16+8+2=378
各列毎に加算
乗数=1 → 被乗数 乗数=0 → 0ベクトル
3
LUTを使った直接表現
LUT数が 入力ビット数nに 対して 指数関数的に 爆発してしまう
4
順序回路を使う • 乗数の各桁(ビット)に応じて ‒ 0のとき, 途中の結果を左シフト ‒ 1のとき, 被乗数を途中の結果に加算して左シフト
1 0 0 1 0 1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 1 0 0 1 0
1 0 1 1 1 1 0 1 0
× 18 21
各列毎に加算
乗数=1 → 被乗数 乗数=0 → 0ベクトル
よく見ると, 被乗数を左シフトしながら加算すれば良い 000010010 000100100 001001000 010010000 100100000
5
アルゴリズム 1. 途中結果を記憶するレジスタTEMPを初期化. TEMP <= 0; 2. 乗数Bのi番目のビットbi (i=0,1,2,...)に対して 1. bi==0のとき, TEMP <= TEMP; 2. bi==1のとき, TEMP <= TEMP + A; // A は被乗数
3. A <= A << 1; とし, 全ての桁の計算が終わるまで2. を繰返す 4. 全ての桁の計算が終われば, RESULT に TEMPを格納.
1 0 0 1 0 1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 1 0 0 1 0
1 0 1 1 1 1 0 1 0
× 18 21
各列毎に加算
乗数=1 → 被乗数 乗数=0 → 0ベクトル
6
状態遷移図
Inital Q1
Reset R_A <= 0; R_B <= 0; TEMP <= 0; RESULT <= 0;
NONE if (R_B[0] == 1'b0) TEMP <= 10'b0; else TEMP <= R_A; R_A <= R_A << 1;
Q2
NONE R_A <= A; R_B <= B; TEMP <= 0;
NONE if (R_B[1] == 1'b0) TEMP <= TEMP; else TEMP <= TEMP +R_A; R_A <= R_A << 1;
Q3
NONE if (R_B[2] == 1'b0) TEMP <= TEMP; else TEMP <= TEMP +R_A; R_A <= R_A << 1;
Q4 Q5
NONE if (R_B[3] == 1'b0) TEMP <= TEMP; else TEMP <= TEMP +R_A; R_A <= R_A << 1;
NONE if (R_B[4] == 1'b0) RESULT <= TEMP; else RESULT <= TEMP +R_A;
7
DE0ボードに合わせて 信号線名を変更
Inital Q1
Reset R_A <= 0; R_B <= 0; TEMP <= 0; LEDG <= 0;
NONE if (R_B[0] == 1'b0) TEMP <= 10'b0; else TEMP <= R_A; R_A <= R_A << 1;
Q2
NONE R_A <= {5'b0,SW[4:0]}; R_B <= SW[9:5]; TEMP <= 0;
NONE if (R_B[1] == 1'b0) TEMP <= TEMP; else TEMP <= TEMP +R_A; R_A <= R_A << 1;
Q3
NONE if (R_B[2] == 1'b0) TEMP <= TEMP; else TEMP <= TEMP +R_A; R_A <= R_A << 1;
Q4 Q5 NONE if (R_B[3] == 1'b0) TEMP <= TEMP; else TEMP <= TEMP +R_A; R_A <= R_A << 1;
NONE if (R_B[4] == 1'b0) LEDG <= TEMP; else LEDG <= TEMP +R_A;
• A -> SW[4:0], B -> SW[9:5], R_AとR_Bでそれぞれ保持 • RESULT -> LEDG[9:0] (5ビットx5ビットの乗算は高々10ビット)
8
状態符号を割当て • A -> SW[4:0], B -> SW[9:5], R_AとR_Bでそれぞれ保持 • OUT -> LEDG[9:0] (5ビットx5ビットの乗算は高々10ビット)
000 001
Reset R_A <= 0; R_B <= 0; TEMP <= 0; LEDG <= 0;
NONE if (R_B[0] == 1'b0) TEMP <= 10'b0; else TEMP <= R_A; R_A <= R_A << 1;
010
NONE R_A <= {5'b0,SW[4:0]}; R_B <= SW[9:5]; TEMP <= 0;
NONE if (R_B[1] == 1'b0) TEMP <= TEMP; else TEMP <= TEMP +R_A; R_A <= R_A << 1;
011
NONE if (R_B[2] == 1'b0) TEMP <= TEMP; else TEMP <= TEMP +R_A; R_A <= R_A << 1;
100 101 NONE if (R_B[3] == 1'b0) TEMP <= TEMP; else TEMP <= TEMP +R_A; R_A <= R_A << 1;
NONE if (R_B[4] == 1'b0) LEDG <= TEMP; else LEDG <= TEMP +R_A;
9
注意
000 001 010
NONE if (R_B[1] == 1'b0) LEDG <= LEDG; else LEDG <= LEDG +R_A; R_A <= R_A << 1;
011
100 101 NONE if (R_B[3] == 1'b0) LEDG <= LEDG; else TEMP <= TEMP +R_A; R_A <= R_A << 1;
• 異なるビット幅の信号を接続する時は, ビット幅を合わせる!
SW[4:0] (5ビット)
R_A (10ビット)
5'b0 つまり 0 0 0 0 0
Reset R_A <= 0; R_B <= 0; TEMP <= 0; LEDG <= 0;
NONE if (R_B[0] == 1'b0) TEMP <= 10'b0; else TEMP <= R_A; R_A <= R_A << 1;
NONE R_A <= {5'b0,SW[4:0]}; R_B <= SW[9:5]; TEMP <= 0;
NONE if (R_B[4] == 1'b0) LEDG <= TEMP; else LEDG <= TEMP +R_A;
10
• ピン配置が面倒くさいので、デフォルトのプロジェクトを読み込みましょう! (DE0に限った事ではないが、Terasic製品はサンプルCD-ROMの プロジェクトを改変するのが楽でお勧め)
DE0付属のCD-ROM ”Demonstrations”内の "DE0_Top"フォルダの ファイル全てを C:¥verilog¥DE0_tutorial_7_1¥ 内にコピー
DE0_TOP.qpfをダブルクリックしてQuartus IIを起動
11
Pin Plannerを開いてみると ピン配置が終わっている!
Verilog-HDLを入力
12
ダブルクリック Verilog-HDLの テンプレートが 表示されるので コードを入力
コード入力したら保存を忘れずに!
13
記述するVerilog-HDL
14
記述するテストベンチ
リセット信号と 入力値を記述
クロックを記述
15
シミュレーションで動作確認 • デフォルトでは入出力信号のみ表示 ‒ 回路内部の信号(特にレジスタ)がわからない
16
内部信号の表示
乗算回路の インスタンス名 「i1」を選択 (テストベンチ自動 生成で勝手に命名される) 内部信号が
リストアップされます
simタブをクリック
17
観測する信号の追加
追加したい信号を選択し、 右クリック->「Add Wave」を 選択
18
シミュレーションの再実行
Console に「restart」と入力し, 出現するウインドウの「OK」を選択 シミュレーションが初期化(波形がクリア)
「run 400ps」と入力し, #400時間シミュレーションをスタート
19
シミュレーション結果を確認 • 状態が000のときに出力値(18x21=378)が得られているか確認
リセット中は 初期値が出る
リセット後は 21x18を計算. 状態000で 出力値を得る.
FPGA上で動作させる • Compilation を行い, DE0ボード上に実現
20
1 0 1 0 1 21
1 0 0 1 0 18
378 0 1 0 1 1 1 1 0 1 0
21
まとめ • 今回学習したこと ‒ アルゴリズムから状態遷移図を作成 ‒ 状態遷移図からVerilog-HDLを記述 ‒ 内部信号のシミュレーション • 信号の追加 • シミュレーションの再実行
22
課題 (今回は非常に難しい)
• Page 6の状態遷移図の状態を併合し, 簡単化しなさい ‒ R_B[0] を変数 idx で指定できれば, 大幅に簡単化できる (つまりC言語の配列を使う)
• 簡単化した状態遷移図をVerilog-HDLで記述せよ ‒ C言語の配列は直接実現できないので, マルチプレクサ(選択回路)を使う. つまり, if( R_B[idx]== 1'b0) をFunction文を使ったマルチプレクサからの信号 mux_out に置き換える. if( mux_out == 1'b0) ... assign mux_out = mux_6( R_B, idx); function mux_6; input [5:0]R_B; input [2:0]idx; ... endfunction
• 6ビットの割り算回路を順序回路で設計せよ. 動作確認はシミュレーションで行え.