[PR]
[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
subprogram宣言を使ってみた
そこでsubprogram宣言に挑戦してみました。これを使うと、
-----------------------------------------------------
ARCHITECTURE behavior OF hoge IS
function func_hoge(以下略...)
end func_hoge;
signal A,B,x,y : std_logic;
begin
A := func_hoge(x);
B:= func_hoge(y);
end hoge;
-------------------------------------------------------
みたいな感じで書けます。
コンポーネントとどこが違うんだ?と思いますよね。
ファンクション文は出力が一個だけで、それこそC言語の関数みたいですが、
プローシージャ文は入出力を任意に設定でき、それこそコンポーネントと大差無い様に見えます。
サブプログラムとコンポーネントの違いは、コンポーネントが下位層にある全く別の回路(別ファイル)を繋げて階層化するのに対して、サブプログラムの場合、機能自体を信号やコンポーネントのI/Oを定義するアーキテクチャ宣言部に書いてしまうので、一つ回路内で完結しているということです。
よって、C言語と違って関数を別ファイルにすることが出来ません。
従って、一つのソース内で何度も使用するが階層化するほどでもない、
小さい処理を関数にしたいときにサブプログラムを使うと良さそうです。
--追記、サブプログラム宣言の入出力は、信号か変数しかとらないそうです。
fprintfみたいな関数を作ろうとしていたが残念。
ファイル入出力用の便利なパッケージを作りたいです。
てかサブプログラムに出力がある必然性を感じられない。void型みたいなのがあればいいのに、
ファイル入出力ぐらいしか需要がなさそうだが。
----まとめ----
ファンクション 戻り値一個の組み合わせ回路
プロシージャー 戻り値複数の組み合わせ回路
コンポーネント 順序回路
綺麗にまとまった!
ファイルへの入出力
テストベンチの際に、ファイルへ任意の値を入出力するやり方
1.まず、use ieee.std_logic_textio.all; と、use std.textio.all; を宣言。
2.ファイル型を定義
file read_file text open read_mode is "input.txt"; --入力ファイル
file write_file text open write_mode is "output.txt" --出力ファイル
3.入力ファイルから値の読み出し(値は2進数)
variable read_line : line; --変数のライン型を定義
variable read_value : std_logic_vector();
readline(read_file,read_line); --ファイルの一行を読み出し
read(read_line,read_value); --行中の値を読み出し(信号ではなく変数)
hoge <= read_value; --信号に代入して、後は煮るなり焼くなり
4.出力ファイルへの書き出し
variable write_line : line;
variable write_value : std_logic_vector(); --signalでもok!
write(write_line,write_value,right,10); --10の文字幅で値を行に右詰め格納(値は信号可)
writeline(write_file,write_line); --行をファイルに書き出し
5.バリエーション
oread(); owrite(); --read,writeの8進数ver. bit数は3の倍数
hread(); hwrite(); --read,writeの16進数ver. bit数は4の倍数
条件に満たない場合は適当に&で連結して任意の倍数bit長にしましょう。
--追記
16進数をファイルからreadする場合は
型の大きさより小さい数は、空白を0で埋めなきゃ駄目ですね。
Excelでもそうですしファイル読み取り全般に言えることらしいです。
FIFOもどきを作る
そこでFIFOのソースを探してみたら、何やらFullFlagやらEmptyFlagやら難しい機能がやたら目に付きました。単に信号を遅延させるだけでいいのに・・・。
1.シフトレジスタで代用
IPでもいいのですがgeneric文で汎用性の高い部品を作りたかったので、自分でソースを書くことにしました。とりあえず、ROMやRAMのソースをベースにして作るということでarray文にも挑戦してみたのですが、なかなか上手くいかず・・・
結局2次元配列なんてかっこいいことは出来ずに、複数ビット分だけシフトするシフトレジスタでFIFOの機能を実現することにしました。要はデータ×レイテンシの幅のシフトレジスタを作るわけです。
記述がかなりシンプルで済みました。動作速度800MHz
ん?何か間違っているんじゃないか??
それに、実用的な機能を再現するだけでも恐ろしい幅になってしまいます。
32bit×50レイテンシ=1600bit
怖い怖い。
2.BRAMを使用
メモリにスライスを割り当てると案の定回路がものすごく大きくなってしまったので、FPGAに搭載されているBRAMを使用することにしました。既存のRAM回路からアドレス関係のI/Oを取り除き、内部にアドレス指定のカウンタを取り付けることでそれっぽく動作させました。メモリ関係のソースはこちらのページが参考になります。
http://www.nahitech.com/nahitafu/fpgavhdl/bram/bram.html
VHDLの定数に関して
固定された整数を表現。#で囲み、基数を指定することも可能(2,8,16のみ)
2#101001# -- 2進定数
16#AC# -- 16進定数
文字定数
' '(クオート)で囲まれた1bitのバイナリを表現、Std_Logicで良く使う。
ストリング定数
" "(ダブルクオート)で囲まれた複数bitのバイナリを表現、Std_Logic_Vectorで良く使う。
VHDLの型に関して
そこで型に関して簡単に紹介するので参考にして下さい。それぞれの型がどのライブラリで定義されているかまで説明すれば、長くなるんで割愛します。
- Std_Logic
- 1bitデータを扱う。
- Std_Logic_Vector(基本はこれ)
- 複数ビットデータを扱う
- Signed(Std_Logic_Vectorのサブタイプ。符号アリ)
- Unsigned(Std_Logic_Vectorのサブタイプ。符号ナシ)
- Integer(整数。constantで定数を宣言するときに使ったりします。)
- Real(実数。これは使わないなー)
Xが符号ナシ、Yが符号アリの場合このようにキャストすると正しい値が出てきます。
Z<=unsigned(X)*signed(Y)