Quartusを使って、FPGAで除算をやってみる

FPGA

FPGAで割り算をやる機会はないのですが、そもそもFPGAで除算ができるのか調べてみました。

VHDLの参考書で確認したところ、分母が2のべき乗であればできるとのこと。

ということで、本当にできるかQuartusを使って調べてみることにしました。

VHDLによるハードウェア設計入門?言語入力によるロジック回路設計手法を身につけよう (Design wave basic)

新品価格
¥2,860から
(2020/9/15 22:33時点)

スポンサーリンク

分母を2のべき乗にして、VHDLで試してみる

VHDLで除算の算術演算子は“/”で、剰余は“mod”のようです。

剰余は他にも“rem”というのがあるようですが、“mod”との違いがわかりませんでした。(正の数なのか、負の数なのかで違うらしいですが)

なので、今回は“mod”だけ使います。

“/”“mod”で、商と余りを求めてみたいと思います。

分母(割る数)は、で固定します。

分子(割られる数)は、外部ピン(4bit幅)から入力します。

まずはエラー発生

演算子は、“/”“mod”ということなので、以下のコードを作ってみました。

LIBRARY ieee;
USE ieee.std_logic_1164.all; 


ENTITY divider_hdl IS 
	PORT
	(
		IN_A :  IN  STD_LOGIC_vector(3 downto 0);
		OUT_Q :  OUT  STD_LOGIC_vector(3 downto 0);
		OUT_M :  OUT  STD_LOGIC_vector(3 downto 0)
	);
END divider_hdl;

ARCHITECTURE rtl OF divider_hdl IS 


BEGIN
	
	OUT_Q <= IN_A / 4 ;            -- 商の計算
	OUT_M <= IN_A mod 4 ;      -- 余りの計算


END rtl;

しかし、早速のコンパイルエラー発生です。

can’t determine definition of operator “”/”” — found 0 possible definitions

商を求める式でエラーが発生しているので、試しにこの式をコメントアウトして、再度コンパイルしてみました。

can’t determine definition of operator “”mod”” — found 0 possible definitions

“/”“mod”もダメなようです。

参考書をもう一度確認です。

Integerに変換する必要あり

参考書を確認したところ、”/”と”mod”はIntegerに変換する必要があるそうです。

Integer以外にも、Realでも大丈夫とのことですが、Realも使った経験がないので、ここでは触れません。

VHDLは以下に書き換えました。

LIBRARY ieee;
USE ieee.std_logic_1164.all; 
USE ieee.std_logic_unsigned.all;
USE ieee.std_logic_arith.all;

ENTITY divider_hdl IS 
	PORT
	(
		IN_A :  IN  STD_LOGIC_vector(3 downto 0);
		OUT_Q :  OUT  STD_LOGIC_vector(3 downto 0);
		OUT_M :  OUT  STD_LOGIC_vector(3 downto 0)
	);
END divider_hdl;

ARCHITECTURE rtl OF divider_hdl IS 
	
	signal num_in : integer range 0 to 15;
	signal num_out_q : integer range 0 to 15;
	signal num_out_m : integer range 0 to 15;

BEGIN
	
	num_in <= CONV_INTEGER(IN_A);   -- ①Integerに変換
	
	num_out_q <= num_in / 4;               -- ②商の計算
	num_out_m <= num_in mod 4;        -- ③余りの計算
	
	OUT_Q <= CONV_STD_LOGIC_VECTOR(num_out_q,4);   -- ④商をSTD_LOGIC_VECTORに変換
	OUT_M <= CONV_STD_LOGIC_VECTOR(num_out_m,4);  -- ⑤余りをSTD_LOGIC_VECTORに変換


END rtl;

分子(割られる数)は、IN_Aで、外部ピンからの入力を想定しています。

①は、IN_AをIntegerに変換しています。

②と③は、商と余りをIntegerで計算しています。割る数の分母は4で固定です。

④と⑤は、IntegerSTD_LOGIC_VECTORに戻し、外部ピンに出力しています。

これでコンパイルした結果、エラーが消えました。

コンパイル結果

こちらはコンパイル結果のウインドウです。

Total pinsは12本使用になっていますが、その他のリソースがすべて0%でした。

う~ん、、、なぜでしょう???

シミュレーション結果

分母の割る数は4で固定です。分子の割られる数(IN_A)は、外部ピンから入力します。

シミュレーション時、割られる数のIN_Aは、50ns毎にカウントアップしていくようにしました。

IN_Aは4bit幅なので、0から15までカウントアップし、0に戻ります。

入力データの波形は以下になります。

これで、メニューSimulation -> Run Timing Simulationを実行します。

以下がシミュレーション結果です。

ちょっと小さくなってしまって見づらいと思いますが、商も余りも正しく表示されていそうです。

分母を2のべき乗にした場合のまとめ

コンパイル結果でリソースが0%でしたが、シミュレーションは正しく動いたようです。

分母を2のべき乗にした場合は、割られる数を右にビットシフトさせるだけなので、FPGAのリソースは不要ということなんでしょうか???

今回は、割る数は4なので、割られる数を右に2bitシフトした結果が商で、右に飛び出した2bitが余りになると思うので、コンパイル結果のリソースが0%になったと予想です。

分母を2のべき乗以外にして、VHDLで試してみる

分母が2のべき乗であれば、大丈夫であることがわかりました。

では、2のべき乗以外では、本当にできないのか?を確認してみました。

今回は、分母の割る数を5にしてみました。

以下、VHDLの変更箇所です。

num_out_q <= num_in / 5;
num_out_m <= num_in mod 5;

変更後、コンパイルしましたが、エラーはでませんでした。

コンパイル結果

分母が2のべき乗の時は、Total logic elementsが0でしたが、今回は34になりました。

シミュレーション結果

分母が2のべき乗の時と同じ入力条件で、シミュレーションしてみました。

その結果がこちら。

予想に反して、正しく除算をやっていそうです。

分母を2のべき乗以外にした場合のまとめ

分母を2のべき乗以外にすると、論理合成されず、コンパイルエラーになるのかと思っていましたが、予想に反してできました。

Quartusが優秀なのでしょうか?IntelのFPGAが除算に対応しているということなのでしょうか?

残念ながら、詳細はわかりません。。。

RTL Viewerで比較してみる

割る数を4と5にして割り算をやってみましたが、各々の値でFPGA内の回路がどうなっているのかRTL Viewerの機能を使って見てみました。

RTL ViewerはメニューTools -> Netlist Viewers -> RTL Viewerを選択します。

RTL Viewerはこちらの記事でも紹介しているの、ぜひご参照ください。

まず割る数を4にした場合の結果です。

次に割る数を5にした場合の結果です。

この結果をみると、やはり割る数が4の時は、入力データのbit3とbit2を商として出力し、bit1とbit0を余りとして出力しているようです。

なんのロジックも使用されていないので、Total logic elementsが0だったんでしょう。

そして、割る数を5にした時ですが、Div0Mod0というブロックあります。

どうやら、このブロックで商と余りを計算しているようです。

これって、FPGAに内蔵された専用ハードウェアなのでしょうか???

専用のハードウェアだとすると、Total logic elementsは0のままになるはずでしょうか???

Div0とMod0の中身まではちょっとわかりませんでした。

Terasic DE0-NANO開発ボード 【P0082】

新品価格
¥14,520から
(2020/9/16 22:18時点)

処理時間

最後に、4と5で割った場合に、処理時間がどのくらい変わるのかを比べてみました。

まず、4と5で割って商を求めるシミュレーション結果です。

上の図で、IN_Aの割られる数が11から12になるタイミングを拡大してみました。

割る数が4の時、入力データが変化してから出力データ(商)が確定するまでは約3.6nsでした。

一方で、5の時は、約9.4nsでした。

2のべき乗である4の時は、演算がないので処理時間が短いです。

まとめ

FPGAで割り算はできるのかと疑問でしたが、できることがわかりました。

それと、割る数である分母は、2のべき乗以外でも大丈夫そうです。

タイトルとURLをコピーしました