【FPGA】Tutorial 演習問題を解きながら理解しようと。。演習2 4ビット乗算器【Verlog HDの基礎の基礎】

スポンサーリンク
広告

ちょっとFPGAやってみない?

という安易な誘いに。。

安易な気持ちで、コピペでできるかな?って思ったけど。。基礎の基礎がわかっていないので、右往左往しています。

Quartusで開発環境作って。。

【FPGA】Intel/Altera DE10 standard メモ【リンク集】
DE10-Standard ちょっと職場で借りたので使うリンクをメモに Boadはこちら、Cyclone VとARMが乗っている開発ボー...

ModelSimの最初のチュートリアルやって。。

【FPGA】ModelSimをちょこっと使ってみる チュートリアルの演習1まで【Verilog HDL】
タイミングシミュレーション?? FPGAの資料ってたくさんWebにあるけど。。読むのがメンドクサイ上に、VerUpが頻繁なようで、なかなか...

演習問題の2の乗算器で。。なるほど。。いろんなRTL記述や実装方法があることがわかり。。少し勉強がてら。。まとめておこうかと思います。

知らないことばかりなので、もし間違いあったら、指摘ください。バカ丸出しのメモです。。

乗算器の記述方法

乗算器っていろいろな書き方あるんですね。

RTL記述

乗算器のRTL記述

シフト演算での記述

FPGAの信号処理論理:シフトと定数乗算
FPGAで信号処理する演算モジュールとしてシフトと定数乗算を解説します

乗算器の仕組み

乗算器 その3 - kivantium活動日記
この記事はkivantium Advent Calendarの9日目です。昨日はWallaceツリーを用いた乗算器の構成を紹介しました。 昨日までの方法ではbit数と同じ数の部分積の和を取る必要がありましたが、今日は部分積を減らすことで高速化を目指す方法を紹介します。 Radix-4 Booth Encoding Ra...

4ビット乗算器 DE0

PDF

乗算器のIntel(Altera)の推奨記述

PDF

どうやら。。いろんな記述方法があるようで、2進数の乗除はシフトと加算でできるので。。って思っていたら。。DSPを使ったりIPを使ったりするのが、今の基本のようですし、基本の基本がわかっていないことが分かりました(笑)

乗算自体は小難しいシフト演算と加算器の組み合わせで作らなくても。。RTL記述でかけちゃうってことも。。一応 理解(笑)

HDL・Verilog HDLの基本の基本

HDLのてにをは集

ここがよく基礎の基礎まとまっています。

http://www.lab3.kuis.kyoto-u.ac.jp/~takase/le3a/hdl/index.html
  1. Verilog-HDL の文法
http://cas.eedept.kobe-u.ac.jp/~arai/Verilog/chap5.html

HDLによるFPGA設計

http://zakii.la.coocan.jp/hdl/0_contents.htm

このあたりのことをまず勉強しないとな。。。っと(笑)

先人の知恵満載ですね。 このようなマトメありがたいです。

演習2の課題

always文
  • あるタイミングで処理を起こしたい場合
  • ループと同じ
assign文・always文とwire・regでの変数

wireで定義する変数 ネット型変数の信号への代入は,assign 文でのみ可能。
regで定義する変数 レジスタ変数の信号への代入は,always 文,initial 文,task,function の中で可能。

つまり,reg =順序回路という訳ではなく,wire や reg は上記の文法的な理由で使い分ける,と理解しておいて間違いなさそうです。いずれの変数も,式の右辺や引数としての利用(値を参照する場合)は可能。出典1

らしい。 ブロッキング文(=で代入)・ノンブロッキング文(<=で代入) の変数などについても理解が必要のようです。

Verilog HDLでは、変数は、線のつながりか、レジスターに入れた数値かってことなんですね。このあたりの使い分けは、こちら。。

always @(posegde clock) ってあるような記述は、クロック信号のポジティブエッジがきたらいつもってことみたい。。

always @(イベント式) 遅延時間 ステートメント あるいは always #定数値 ステートメント
イベント式には以下の 3 種類があります:
・ 信号名       …信号が立ち上がるときと,立ち下がるとき
・ posedge 信号名 …信号が立ち上がるとき(positive edge の略)
・ negedge 信号名 …信号が立ち下がるとき(negative edge の略)

らしい。出典1

ブロッキング文・ノンブロッキング文っていうのは、普通の変数だとブロッキング文のようにクロックの動作に関係なく保持されるようで、ノンブロッキング文は、クロックの動作にそって動く感じです。

演習問題2の課題とテストベンチ

always文を使う。 入力は a,b で4ビット幅 出力はproductで8ビット幅ってことが書かれています。

これのシミュレーションに使うテストベンチの記述を見て、まずこのテストベンチを勉強してみます。

`timescale 1 ps/ 1 ps
module mult4x4_sim();
// constants 
// general purpose registers
reg [3:0] a;
reg [3:0] b;
// wires 
wire [7:0] product;

// assign statements (if any) 
mult4x4 u1 (
// port map - connection between master ports and signals/registers 
.a(a),
.b(b),
.product(product)
);

parameter CYCLE=20000;

initial
begin
a = 4'b0000;
end
always # (CYCLE)
a <= a + 1;

initial
begin
b = 4'b1111;
end

always # (CYCLE)
b <= b - 1;

endmodule

timescale

シミュレータの時刻変数。Verilog記述上は時間経過を待つ文 #(時間)で使われる。この時刻変数(正の整数)と実際の時間(実数s/ms/us/ns/ps/fs)の対応づけをテストベンチの先頭(moduleの前)で指定する。

`timescale 1ns/1ps   // 単位/精度

このとき

#(10) 文; は10nsたったら文を実行

#(10/3) 文;は3.333nsたったら文を実行

という意味になる

出典3

`timescale 1 ps/ 1 ps

なので、今回は単位が1psで精度も1psってこと

変数 reg と wire

module mult4x4_sim();

で変数が定義されています。

reg [3:0] が入力変数 a,bでwire [7:0]がproductになっていますね。

[3:0]っていうのは、4ビット幅 [7:0]は8ビット幅を表すみたいです。

下層モジュールとの接続

// assign statements (if any)

ってところは、mult4x4_simとmult4x4の接続を示しているようです。

mult4x4 u1 (.a(a), .b(b), .product(product) );

下層モジュール名(mult4x4) インスタンス名(u1) パラメータリストで、()の中が、

.定義側ポート名(接続信号)

という記述のようです。 同じ名前使われているので、わかりやすいのか?わかりにくいのか?ですが。。

parameter

regやwireは回路と対応したデータなので、物理型データと呼ぶらしい。それに対して、parameterは抽象型データだそうな。。普通のプログラミングでいうと、Defineのような感じらしい。

parameter パラメータ名 = 定数;
定数を定義します。C言語でいうと #define と同じであり,宣言したモジュール以外のモジュールでも使用可能です。

  • parameterの使い道は主に次の2通りがあります。
    • 定数を、数値で書く代わりにparameterにする
    • ビット幅など[ ]内の数値をparameterにする
        ビット幅などはparameterで書くと設計変更や再利用が容易になります。
        • 数値の意味がわかりにくいマジックナンバー(e.g. 命令コード)をparameterで書くと可読性が上
        がります。

下で

always # (CYCLE)

と使っているので、20000ps (20ns) ごとに。。っていうことですね。

initial

initial begin a = 4'b0000; end always # (CYCLE) a <= a + 1;

initial文

  • シミュレーションで初期値を与える際にテストベンチファイル内で使用します(論理合成はされないので、本体のモジュールファイルに書いても意味はありません)
  • シミュレータ実行時に一度だけ実行される命令として、代入にはブロッキング代入(=)を使います
  • 代入文の左辺はreg型またはwire型、右辺は定数を使います
  • Quartusではinitial文で実機ボードに対しても初期値を与えられますが、ボードの電源を入れた時のみ一度だけ実行されます(実行途中でリセットボタンを押した場合は実行されず初期化されない(要確認))出典2

4ビットで0をaにブロッキングで代入して、20000psごとに、1つインクリメントするのをノンブロッキングで代入するってことですね。

bの変数は、最初に1111(十進数で15)を最初にセットされるってことであとは同じ。

演習2をもう一度みると。。

乗算器のRTL記述

のRTL記述で書いてみると。。

reg[3:0] a;
reg[3:0] b;
wire[7:0] product;

always @(posedge a) 
  begin
  a <= a;
  b <= b;
  product <= $signed(a) * $signed(b);
  end

って感じですかね?

Tutorialの演習2に戻りましょう(笑)  Verilog-HDL_Trial_Lab_r1_download__2.zip

モジュールにして。。戻り値を入れて。。という感じで作ると。。Github

module mult4x4(a,b,product);
input[3:0] a;
input[3:0] b; 
output[7:0] product;

reg[3:0] a_reg; 
reg[3:0] b_reg; 
reg[7:0] product_reg; 

always @(posedge a or negedge a) 
begin
a_reg <= a;
b_reg <= b;
product_reg <= $signed(a_reg) * $signed(b_reg);
end 
assign product = product_reg;
endmodule

一回全部 レジスタ変数として定義して、ノンブロッキングとして代入して、最後にassignで値を返す。。。と。。

一応シミュレーションできて、moduleの中も、テストベンチ側にも信号がでて。。できるんだけど。。

1クロックというか、a のエッジ毎に計算するので、1タイミング遅れて。。計算結果がproductに反映される。。クロックを信号に入れてあると。。できるんだけどなぁ~~。。

同時にやる方法って。。どうするの?(笑) 誰かこれの回答教えて(笑)

わからないので。。おいておいて。。演習3に行くか(笑)

って。。演習3をやろうとしたら。。分かった(笑)

always @(posedge a or negedge a)

always @(*)

ってすると、できた(笑) ここに。。MultiplexerのModuleの書き方に。。どんな入力の変化にもする表現として。。ありました。

Chapter 11: 2 to 1 multiplexor
Learn how to design digital systems and synthesize them into an FPGA using only opensource tools - Obijuan/open-fpga-verilog-tutorial

なるほど。。

では。。続いて。。

コメントを残していただけるとありがたいです

コメント

  1. @shibatchii より:

    通りすがりのLSI設計屋です。
    組み合わせ回路を作るのにposedge,negedgeは使いません。
    基本的にクロックに同期させる時と非同期リセットをかけるときです。
    あとはテストベンチでなにかのエッジで次に行くときくらいです。
    で、今回は組み合わせ回路の乗算器なので、センシビリティリストは @(a or b) で、
    aもしくはbが変化したら動作ということでよいと思います。
    また代入はブロッキング代入です。

    module mult4x4(a,b,product);
    input[3:0] a;
    input[3:0] b;
    output[7:0] product;

    reg[7:0] product_reg;

    always @(a or b)
    begin
    product_reg = $signed(a) * $signed(b);
    end

    assign product = product_reg;

    endmodule

    ちなみに、お仕事で書くときは always使わず
    assign product = $signed(a) * $signed(b);
    この1行です。

    • tom2rd より:

      ありがとうございます。
      全くの素人なので、よくわかっていません(笑)

      また、通りすがったら、教えてください

Loading Facebook Comments ...
%d人のブロガーが「いいね」をつけました。