まごころせいじつ堂

浜町庄金 研究開発  マイコンで遊んでばっかりで

FPGA

FPGA評価ボード BeMicro MAX10 準備

 AlteraのFPGA MAX10の評価ボードが安いということで入手した。

BEMICROMAX10(ARROW)
BeMicro Max10, FPGA Evaluation Kit adopts Altera's non-volatile MAX 10 FPGA built on 55-nm flash process

約$30。前見た時は送料が同じくらいかかっていたのが今は無料だったので注文。4日で届いた。

準備としてMAX10の開発環境 Quartus II 15.0をWindows7(64bit)マシンにインストール。
Quartus II 開発ソフトウェア v15.0 の新機能(ALTERA)

BeMicro MAX10をWindowsマシンにUSB接続しただけではドライバのインストールに失敗する。ドライバはQuartusIIをインストールした C:¥altera¥15.0¥quartus¥drivers¥ を参照する。

2015MAX10

 まずはここまで。


バレルシフタ 2段にして改善(お詫び 大きな間違いあり)

追記:@ikwzmさんから。https://gist.github.com/ikwzm/5558633 
バイト単位でシフトすべきところを4bit単位でやってました。あああ
ご指摘ありがとうございました。

※前段の 8byteシフト間違ってる気がしてきた。多分3bit分を<<5した時点ですべて'0'になってしまってるはず

(1)組み合わせ回路のシフトについて、下xx bitを削っていくような間違いをしていました。書きなおしたのは以下。
https://gist.github.com/houmei/5555418

(2)<<演算子を使ったbyte shiftは、いったん幅[6:0]の下位3bitを'000'とし、上位にシフト量を入れることで書き直しました。
比較結果:
349LE/214.92MHz (Megafunction)
343LE/214.55MHz (シフト演算子)
291LE/335.46MHz (組み合わせ回路)
ただし、組み合わせ回路によるものは(1)の間違いあり。

反省:見積もりに検証していない回路を軽い気持ちで使うと大失敗

以下は間違いありです。


 扱うbit幅が大きくなるとLE数は増え動作周波数は落ちていくバレルシフタ。ここでシフト量を制限したらどうなるか傾向を見てみた。例えば1bitシフトする/しないだけなら大幅にセレクタ数が減るはず。
以下の様なコードでシフト量を1,2,4,8...と変えながら試してみる。上位モジュールからは
sll64_partial #6 SLL(source,value,sftout); // partial shift
の様に呼び出す。
module sll64_partial (indata,val,outdata);
	parameter width=6; //[6:0]
	input [63:0] indata;
	input [width:0] val;
	output [63:0] outdata;
	assign outdata=indata<<val;
endmodule
結果は以下のとおり。
 64bitを部分シフト
[0:0] 129LE/615.38MHz
[1:0] 136LE/413.56MHz
[2:0] 143LE/357.65MHz
[3:0] 210LE/270.71MHz
[4:0] 285LE/250.38MHz
[5:0] 384LE/223.31MHz
[6:0] 390LE/220.17MHz

では、最初にバイト単位でシフトして次にビット単位で8つまでシフトするようにしてみる。
シフト量のnnnnxxxのうち、nnnnはバイトでのシフト量、xxxはビットのシフト量とする。nnnnについてはシフトする量がデータ幅をあふれたらall0とする。


ソースはこちら:https://gist.github.com/houmei/5541783 

コンパイル結果は207LE/284.41MHzとなった。組み合わせ回路でべたに書いた283LE/105.06MHzよりよい。

※以下も怪しい
 もし、もっと追求するとしたらbit幅の組み合わせを変える(4-3を3-4)、段数を増やす(2-2-3)、一部組み合わせ回路にしてみる、など。やりだすときりがなくなるけど構造的な改善である程度の性能が出たらしばらく放置して他に着手したほうがいいかも。

 あと、QuartusIIにはMagawizard Plugin Managerというのがあって、用途に合わせたライブラリが使える。今回の用途にはGates→LPMCLSHIFTというのが使えた。verilogやVHDLのインターフェース部分がソースとして出力されるのでこれを呼び出して使用する。

QuartusII 12.1 バレルシフタの記述比較

 前回、メモ:QuartusII 12.1 バレルシフタの記述とTimeQuestによる速度評価の続き。

 バレルシフタの入力、出力を64bitとすると、シフト量は0~64になる。つまりシフト量の指定に6bit+1必要。これらをfunction文による自前の組み合わせ回路と<<演算子による記述で比較してみた。

ソースはこちら:https://gist.github.com/houmei/5522404 

 function文によるRTLはこのようになる。(8bit幅)
sll8_15LE3 
 コンパイル結果は以下。27LEで3段。
62MHz


 <<演算子によるRTLはこんな表示。
sll8shiftop

 コンパイル結果。32LE4段。
33MHz


 このような感じで4~64bitまでの組み合わせ回路によるバレルシフタと演算子によるバレルシフタについて、LE数と動作周波数で比較した。
  barrel

 横軸は4,8,16,24,32,48,64が等間隔に並んでいるのに注意。組み合わせ回路はLE数が少なくて済むが、8~16bitのあたりで速度が逆転する。これを配置配線後の回路でみると、こうなっている。

組み合わせ回路によるもの:
06MHz

<<演算子によるもの:
05MHz
 <<演算子でコンパイラに任せたほうが、LEがまんべんなく散らばっているようにみえる。LE自体のディレイよりも配線のディレイが大きいように思える。
16bitくらいの大きさまでなら組み合わせ回路で手書きしたほうがいいが、回路をケチる必要がなければコンパイラに任せたほうがいい。


 <<の演算子で書くならparameter文で指示したら良さそうと思うでしょう?実験した。上位モジュールからは
 sllp #(63) SLL(source,value,sftout);
の様に書いてparameter文を使ったsllp.vを呼び出すようにコンパイルしてみる。すると、24bitで以下の様な結果となった。 
24bitでの<<演算子 / parameter文によるもの
128LE,295.33MHz / 133LE,280.74MHz

 bit幅によってはまったく同じではないことがあり得る。なんでわざわざこれを試したかというと、20年くらい前に論理合成ツールを使った時に怪しい挙動を経験したため。なので、ギチギチに詰める必要がある場合はいろいろ疑ってみたほうがいいかもしれない。

追記:@ikwzmさんにfor文を使った書き方を教えてもらいました。https://gist.github.com/ikwzm/5523178 398LE/199.76MHz
ちょっと8byteシフト&8bitシフトの組み合わせで64biシフタを構成したら210LE/310.95MHz

メモ:QuartusII 12.1 バレルシフタの記述とTimeQuestによる速度評価

 ALTERAのFPGA開発環境 QuartusII 12.1、Verilog HDLでバレルシフタを記述し、組み合わせ回路の動作速度をQuartusIIの機能であるTimeQuestで計ってみた。ターゲットはCycloneIII EP3C16F484C6(Terasic DE0)。I/Oのアサインはせずコンパイルのみ。

 バレルシフタは組み合わせ回路なので、最初はI/Oから入出力をとってそのまま接続していた。しかしこれではTimeQuestで評価されない。前後をFFではさむとfmaxが計算された。
 
sll64_rtl

 これに気づいたのはTimeQuestによるタイミング解析を学ぶ (1/3) 、FPGAの動作スピードを改善するポイントとは? (1/2)を読んでから。ディレイ計算はゲートの出力側から入力側に向けて積算して求めるものと思っていた。

ソースはこちら:https://gist.github.com/houmei/5510474 

 コンパイル後、[Tools]→[Netlist Viewers]以下のツールで回路を見ることができる。
→[RTL Viewer]でRTLの、→[Technology Map Viewer(Post-Fitting)]で配置配線後の回路を表示する。

[RTL Viewer]
sll4_rtl 

[Technology Map Viewer(Post-Fitting)]
76MHz

 Compilation ReportのTimeQuest Timing Analyzerの項目に最大動作周波数が載っている。ここのSlow 1200mV 85C Modelを開く(電圧が低く、温度が高い方が厳しい条件となる)。 ここのFmax Summaryを見ると712.76MHzとあり、これが最大動作周波数。

CADR 回路図 SPC MEMORY AND POINTER

CADRマシンの回路図を見ていきます。簡単そうな所から。
http://www.unlambda.com/download/cadr/CADR4_schematic.pdf

49ページは18bit+パリティ、32個のメモリでスタック(SPC)を構成。-WCLKに同期。
SPC POINTERは同期式アップダウンカウンタ 74S159を2個。CLK4Fに同期。
SPC POINTERはパワーオンでは不定だが、ポインタの出力SPCPTR4〜SPCPTR0は読めるのでソフトで初期化しろということだろう。スタックのオーバーフロー/アンダーフローはチェックしないので、ソフトの責任で使用しろと書いてある。

 ところで、TTLのみで96ページもある回路図を読むのはなかなかつらいので、信号の生成元とそれを使っている箇所についてのクロスリファレンスが必要かな。気合が足らんと言われそうだが。

cadr 
  

CADRソース調査 メモリについて

CADRマシンの回路図をたよりに中で使われているメモリについて調べた。
Retrocomputing - MIT CADR Lisp Machines

@natsutanさんのブロック図を参照してください。
制御パス 
データパス

以下はPROMだけど組み合わせ回路で実現:
part_32x32prom_maskright i_MSKR A[4:0] D[31:0] 
part_32x32prom_maskleft i_MSKL A[4:0] D[31:0]
part_32x8prom i_DMASK A[4:0] D[7:0]
part_512x49prom i_PROM0 A[8:0] D[48:0] 

このうち512ワードのi_PROM0はデータbit46が欠けている。元々のPROMには[48:47,45:0]の48bitが割り付けられている。74S472×12個。

以下はRAM、caddr.vでのソースではメモリ上のパリティはすでに取り除いてある:
part_32x19ram i_SPC A[4:0] D[18:0] SPC STACK
元は32x2bit 82S21 ラッチ×10個(パリティ付き)

part_32x32ram i_MMEM A[4:0] D[31:0] B-MEMORY(M-MEMORY)
元は32x2bit 82S21 ラッチ×17個(パリティ付き) 

part_2kx5ram i_VMEM0 A[10:0] D[4:0] VMAP STAGE0
元はRAM 1k×1bit 93425A×12個

part_1kx24ram i_VMEM1_2 A[9:0] D[23:0] VMAP STAGE1,2
元はRAM 1k×1bit 93425A×25個

part_1kx32ram i_PDL、i_AMEM A[9:0] D[31:0] PDL MEMORY、A-MEMORY
元はRAM 1k×1bit 93425A×33個(パリティ付き)が2セット

part_2kx17ram i_DRAM A[10:0] D[16:0] DISPATCH MEMORY
元はRAM 1k×1bit 93425A×36個

part_16x49ram i_IRAM A[13:0] D[48:0] INSTRUCTION MEMORY
元はRAM 4k×1bit IN2147×196個

部品としてのRAMは3種類。うちラッチと書いたものはパススルーができる?
INSTRUCTION MEMORYがいちばん大きい。次いでDISPATCH MEMORYで、このあたりを外に追い出せばいけるか。VMAP関連についてはSTAGE0,1,2とcaddr.vソースとの対応付けが今のところはっきりしない。(CADRマシンの前身、CONSマシンのブロック図を参照しているのでその違いかもしれない)

SPC STACK、B-MEMORYのみ中身があるものにしてDE0(CycloneIII EP3C16F484C6)ターゲットで合成してみたら約1時間で4,229/15,408LE (27%)だった。まだ行けそうね。

QuartusIIでCADRのソースをコンパイル 2

QuartusIIでCADRのソースをコンパイル 続き
i_DRAMの中身をカラ(reg 宣言を削りassign DO=DI; とする)にして再度コンパイルしてみた今回は5時間を越えてどんどん進むが停まる気配がない。10時間で打ち切り、すべてのRAMについて同様に中身をカラにしてみた。どうもreg宣言ばかりで明にRAMに割り当てていないようで、これがLE数を消費する原因と思われた。
結果は以下のとおり。
Flow Status Successful - Fri Feb 22 01:17:37 2013
Quartus II 64-Bit Version 12.1 Build 177 11/07/2012 SJ Web Edition
Revision Name caddr
Top-level Entity Name caddr
Family Cyclone IV GX
Device EP4CGX150DF31I7AD
Timing Models Final
Total logic elements 2,929 / 149,760 ( 2 % )
Total combinational functions 2,860 / 149,760 ( 2 % )
Dedicated logic registers 471 / 149,760 ( < 1 % )
Total registers 471
Total pins 27 / 508 ( 5 % )
Total virtual pins 0
Total memory bits 0 / 6,635,520 ( 0 % )
Embedded Multiplier 9-bit elements 0 / 720 ( 0 % )
Total GXB Receiver Channel PCS 0 / 8 ( 0 % )
Total GXB Receiver Channel PMA 0 / 8 ( 0 % )
Total GXB Transmitter Channel PCS 0 / 8 ( 0 % )
Total GXB Transmitter Channel PMA 0 / 8 ( 0 % )
Total PLLs 0 / 8 ( 0 % )
  2929LEですと?ちょっと少なすぎるみたいだけどもここからRAMを盛っていく。
i_DRAM については外付けのDRAMと勘違いしていたのだがDispatchRAMで17bit幅☓11bitアドレスのStaticRAMだった。主記憶はCADRマシンの外にある。caddrではすでにパリティ用の1bitについては削減してあった。
 あとはクロック周り。osc50mhzを外部からの入力として、以下の接続。
osc50mhz-->○--osc0-->○--hifreq1,hifreq2-->○--hfdlyd-->○--hftomm(未使用)
hifreq1,hifreq2は実質同じ、hfdlydはさらに位相の遅れたクロックのつもり。
これらを元にディレイラインで30ns,70nsの遅れを作りRAMのサイクル用などに使っている。
また、NAND2個のたすきがけで制御を行なっている場所が5箇所あり、図面のCLOCK DISTRIBUSIONとMASTER CLOCKはPLLを使用したクロック制御モジュールとして起こしてやらなければならないだろう。これに合わせて非同期SRAM部分も合わせるか。

QuartusIIでCADRのソースをコンパイル

LISPマシンCADRの回路図とVerilog-HDLに変換されたソースリストを見て、これ今のFPGAに収まりそうじゃないかなと思って試しにコンパイルしてみた。もともとはすべてTTLで構成されていて、それをそのままVerilogの記述に変換したものと、きちんと書きなおされたものがある。後者はCADDR Reviced CADR Verilogとして公開されているのでこちらを使った。
Retrocomputing - MIT CADR Lisp Machines
 すでに@natsutanさんが三年前に試されているけど、最近のはどうかな?
[Lisp][Verilog][FPGA]cadrのVerilogソースのコンパイル その1

環境:Windows7 PRIMERGY TX100S1(Core2Quad 2.67GHzに差し替えたもの)
QuartusII 12.1 Build 177 64-bit

新規プロジェクトを作成し、ターゲットデバイスを一番LE数の大きそうなものにする。今回はCycloneIV GXにした。制約条件などのオプション指定はなにもなし。コンパイルにかかった時間は4時間23分、結果はFittingに失敗(113%)、LE数は169,005と出た。

Flow Status Flow Failed - Wed Feb 20 18:15:59 2013
Quartus II 64-Bit Version 12.1 Build 177 11/07/2012 SJ Web Edition
Revision Name caddr
Top-level Entity Name caddr
Family Cyclone IV GX
Device EP4CGX150DF31I7AD
Timing Models Final
Total logic elements 169,055 / 149,760 ( 113 % )
Total combinational functions 109,428 / 149,760 ( 73 % )
Dedicated logic registers 136,714 / 149,760 ( 91 % )
Total registers 136714
Total pins 27 / 508 ( 5 % )
Total virtual pins 0
Total memory bits 787,040 / 6,635,520 ( 12 % )
Embedded Multiplier 9-bit elements 0 / 720 ( 0 % )
Total GXB Receiver Channel PCS 0 / 8 ( 0 % )
Total GXB Receiver Channel PMA 0 / 8 ( 0 % )
Total GXB Transmitter Channel PCS 0 / 8 ( 0 % )
Total GXB Transmitter Channel PMA 0 / 8 ( 0 % )
Total PLLs 0 / 8 ( 0 % )

ソースは以下の修正が必要。

・caddr.v 74181.v 74182.v busint.v  memory.v rom.v を新規ファイルとしてプロジェクトに追加。(New Files... でVerilog-HDLを指定してコピペ) lm2clock.vは多分いらない。

・caddr.vのソース修正 `includeをすべてコメントアウト。プロジェクト内のモジュールを多重に読み込むことになるので。
・memory.vのソース修正 initial begin~end部分をコメントアウト。
・busint.vのソース修正 initial begin~end部分をコメントアウトし、always@(posedge clk)部分とalways@(rst_n)部分をalways@(posedge clk or negedge rst_n)として合体させる。

 あとはメモリを外に出す、caddr.vが大きすぎるのである程度のモジュールに分割し面積を減らせるか検討。特にパリティ回路はまるっと削除しても問題なさそう。あとはALUをまとめてしまう、など。

DE0 QuartusIIのMegaWizardでPLLを使う

DE0の基板上のクロックは50MHz。搭載されているSDRAMは100MHzか133MHz動作なのでこれなんか必要だよなあPLLがあるはずだがどうやって使うんだろうと悩んでいたが解決した。
 これはメーカー/デバイスごと固有の設定であり、Verilog-HDLの記述でどうこうできる話ではない。 QuartusII(12.1sp1)では[Tools]→[MegaWizard Plug-in Manager]で呼び出す。
2013pll1
新規作成を選んで次へ。
2013pll2
ここでは出力する言語をverilog HDL、ファイル名はapll、使用するmegafunctionはI/O→ALTPLLを選択。
 2013pll3
ここからALTPLLの詳細設定画面。入力クロックは50MHzにする。
2013pll4
resetやlock信号は今回使わないのでチェックを外す。後はいくつか飛ばして以下の画面へ。
2013pll5
 c0~c4まで出力を設定できるが、ここではc0だけ。100MHzに設定。あとは飛ばす。
2013pll6
最終確認。[Finish]

メインの画面に戻って[File]→[Open...]でapll.bb.vを開く。以下の内容のダミーモジュールができる。

module apll (
	inclk0,
	c0);

	input	  inclk0;
	output	  c0;

endmodule
 これをつないでやれば良い。トップモジュールで定義したクロック入力をclk_50、PLLの出力をclkで分配すると
apll apll_0(clk_50,clk);
とすればよい。なおトップモジュールでクロック入力の名前を変えるとピンの対応付けが再度必要になるのでPinPlannerで定義する。これでチカチカ表示するのが二倍速になるのを確認した。

参考:
http://www.emb4fun.de/fpga/nutos1/

昔話:
昔はのう、クロック入力を分周してデューティ50%で使ってたんじゃ。例えば内部50MHz動作だと100MHzの発振器が必要で、当時CMOSでそんな出力のはなかったんでECLレベルの発振器を使っておったんじゃ……

DE0 FPGAでFizzBuzz 任意の数値で判定

続き。DE0 FPGAでFizzBuzz
 前回は3進5進カウンターを使ってFizzBuzzを判定していたが、これはリセットと同期してカウントアップしなければならないという制限がある。では4桁の任意のBCD入力に対して簡単に判定することはできるか?
 ソフトでは3の剰余を求めたりするがこれは除算でありそんな大げさなものは動かしたくない。ではテーブル?buzzなら5の倍数なので、最後の桁が0または5で判断できる。
 では3の倍数であるfizzは?ちょっとこねくりまわしてみた。

3の倍数だけ取り出す。
$ awk 'BEGIN{for(i=1;i<10000;i++) printf("%04d\n",i)}' > fizz.txt

それぞれの桁をすべて足して3の剰余を求めると
$ awk '{print substr($1,1,1) substr($1,2,1) substr($1,3,1) substr($1,4,1)}' fizz.txt | gawk '{print $1%3}' 

なんかいけそう。

組み合わせ回路で実現できる。
BCDの4桁それぞれに対して3の剰余を求める。それぞれの桁は0,1,2になる。これの総和は最大で8なので、これに対して3の剰余を求める。こうするとfizzが判定できる。
module bcdmod3(BCD,BCDout);
	input [3:0] BCD;
	output [3:0] BCDout;

	function [3:0] mod3;
		input [3:0] bcdin;
		begin
			case (bcdin)
				1: mod3=1;
				2: mod3=2;
				4: mod3=1;
				5: mod3=2;
				7: mod3=1;
				8: mod3=2;
				default: mod3=0;
			endcase
		end
	endfunction

	assign BCDout=mod3(BCD);

	endmodule


module chkfizz(BCD3,BCD2,BCD1,BCD0, fizz);
	input [3:0] BCD3;
	input [3:0] BCD2;
	input [3:0] BCD1;
	input [3:0] BCD0;
	output fizz;

	wire [3:0] sBCD3;
	wire [3:0] sBCD2;
	wire [3:0] sBCD1;
	wire [3:0] sBCD0;
	wire [3:0] tBCD;
	wire [3:0] aBCD;
	
	bcdmod3 bcdmod3_3(BCD3,sBCD3);
	bcdmod3 bcdmod3_2(BCD2,sBCD2);
	bcdmod3 bcdmod3_1(BCD1,sBCD1);
	bcdmod3 bcdmod3_0(BCD0,sBCD0);
	
	assign tBCD=sBCD3+sBCD2+sBCD1+sBCD0;
	
	bcdmod3 bcdmod3_a(tBCD,aBCD);
	
	assign fizz=(aBCD==4'd0);
endmodule


 確認のためにトップモジュールではスライドスイッチによりBCDを入力してボタン2を押すと、その設定値からFizzBuzzのカウントを開始するようにした。

 QuartusIIで[Project]→[Archive Project...]を選択するとプロジェクトをひとまとめにしてくれる。ダイアログで[Advanced]ボタンを押し、一番上のFileset:はService Requestを選択。これで出力するとoutout_filesディレクトリ以下にfizzbuzz.qarというようなファイルができる。これを他のQuartusIIがインストールされているマシンに持って行ってダブルクリックするとプロジェクトが展開される。

 以下に置いてみました。
fizzbuzz.qar(Googls Docs)

追記:
それぞれの桁をa,b,c,dとおく。a+b+c+d=mod3なら1000a+100b+10c+dもmod3か?
999a+99b+9c + a+b+c+dとすると、9(111a+11b+c) + a+b+c+d で 3で割り切れて0 と + mod3となる。
ってことでよいのかな。中学二年の範囲。

DE0 FPGAでFizzBuzz

やりたいと思って約二年。やっとやる気が出て一週間。verilogの記述でFizzBuzzができた。

ソース。
https://gist.github.com/4649209 

1〜9999までの数字を右詰めゼロサプレスで表示。3の倍数はFizz、5の倍数はBuzz、両方の倍数はFzBzとそれっぽく7セグメントのLEDで表示。
Fizz判定は3進カウンタ、Buzz判定は5進カウンタを使い、BCD4桁カウンタと同じクロックで同時に進む。
数字が0の場合を表示するとまずいので、この時は7セグメントデコーダをoffにして何も表示しないようにした。



 色々ハマったけどwarningは全て見て無視出来る理由がないものは調査。1つのモジュールに複数の機能を入れない。複雑になり作っていてよくわからなくなったので単一機能のモジュールに分割し、上位モジュールで配線する。
 別の方法として、BCD出力を受けてこの中でFizzBuzz判定し、表示を差し替えるようにすれば3進5進カウンタを使わずに任意のBCDに対して判定ができるが、テーブルを作ることになるかな。5の判定は最後の桁が0 or 5でよさそうだがちょっと考えよう。

DE0 QuartusIIでのコンパイル結果をちょっと見る

QuartusII 12.1 Windows 32bit

 ゼロサプレスのデコーダ作ってて、どんな回路が作られてるのだろうと覗いてみた。QuartusIIの[Tools]→[Netlist Viewers]→[RTL Viewer]

追記:
※この回路はゼロサプレス部分にミスがあります。 

入力がすべて0の判定を三項演算子でやると、コンパレータになってる。
 assign bout=(bcd==4'b0000)?1'b1:1'b0;
2013decoder_eq0
Flow Status Successful - Sat Jan 26 18:40:00 2013
Quartus II 32-bit Version 12.1 Build 177 11/07/2012 SJ Web Edition
Revision Name fizzbuzz
Top-level Entity Name fizzbuzz
Family Cyclone III
Device EP3C16F484C6
Timing Models Final
Total logic elements 112 / 15,408 ( < 1 % )
Total combinational functions 101 / 15,408 ( < 1 % )
Dedicated logic registers 67 / 15,408 ( < 1 % )
Total registers 67
Total pins 57 / 347 ( 16 % )
Total virtual pins 0
Total memory bits 0 / 516,096 ( 0 % )
Embedded Multiplier 9-bit elements 0 / 112 ( 0 % )
Total PLLs 0 / 4 ( 0 % )
 

ゲートレベルで考えるとちゃんとゲートになっている。
assign bout=(~(|bcd));
2013decorder_or0
 Flow Status Successful - Sat Jan 26 18:37:14 2013
Quartus II 32-bit Version 12.1 Build 177 11/07/2012 SJ Web Edition
Revision Name fizzbuzz
Top-level Entity Name fizzbuzz
Family Cyclone III
Device EP3C16F484C6
Timing Models Final
Total logic elements 110 / 15,408 ( < 1 % )
Total combinational functions 99 / 15,408 ( < 1 % )
Dedicated logic registers 67 / 15,408 ( < 1 % )
Total registers 67
Total pins 57 / 347 ( 16 % )
Total virtual pins 0
Total memory bits 0 / 516,096 ( 0 % )
Embedded Multiplier 9-bit elements 0 / 112 ( 0 % )
Total PLLs 0 / 4 ( 0 % )

 LEが2個少なくなった。差はないと思っていたんだけど、記述での最適化は効くということだろうか。 

DE0 ゼロサプレス付きカウンタ

続き。カウンタと7セグメントLEDに表示するデコーダ、スイッチ入力のチャタリング除去のモジュールを作成した。

 QuartusIIで新規プロジェクトを作成。[Assignment]→[Import Assignment...]で前回作成したピンアサインを取り込む。

20130126追記:肝心のゼロサプレス部分に間違いがあります。
このままだと4桁の1001表示で10□1の様になります。ゼロサプレスは直前ではなくずっと前の桁がすべて0でなければならないので、segleddec.vは以下書き換え。

assign bout=(bcd==4'b0000)?bin:0;

https://gist.github.com/4639707 

 segleddec.vは4bitの入力を0~Fの16パターンと解釈し、それぞれのパターンに対応する7セグメントのLEDを点灯させる。DE0の7セグメントLEDはアノードコモンなので'0'で点灯。
 TTLの7447はゼロサプレスの機能を持っている。これは普通の電卓の表示のように、桁の左側の余計なゼロを表示しないというもの。左側に位置する桁が'0'で、自分自身が'0'ならば表示を抑止する。ただし1桁目は'0'も表示する。

segleddec.v
assign bout=(bcd==4'b0000)?1'b1:1'b0; // ~&bcd
assign led=(bout&&bin)?8'b11111111:ALED(bcd,dp);

 左側の桁は'0000'ならboutを出力。右側の桁はそれをbinで受ける。右側の桁は自分が'0000'かつ左側の桁が'0000'(bin='1')なら表示を抑止。たくさん並んでいる桁なら、一番左側の桁のbinは'1'に吊ってあとはカスケード接続。ただし一番右、最後の桁はbinを'0'にして切り離す。

hexcounter.v:
segleddec seg0(cnt[27:24],1'b0,1'b0, hled0,bout0_0); // Digit xxx0 always on
segleddec seg1(cnt[31:28],1'b0,bout2_1, hled1,bout1_0);
segleddec seg2(cnt[35:32],1'b0,bout3_2, hled2,bout2_1);
segleddec seg3(cnt[39:36],1'b0,1'b1, hled3,bout3_2);

 こんな感じ。モジュールを定義しておいてこのように書くとインスタンスseg0,seg1,seg2,seg3を生成できる。
 

 二進カウンターは特に問題ないが、パラメータ化して任意のビット長まで指定できるようにしてある。非同期リセット付き。
 TTLなどは非同期リセットがかかるまでは値を保持するFFの内容は'1'か'0'かわからないものとして扱うが、パワーオン後にスキャンを行い初期設定するFPGAやASICは値が確定している。ただし'1'か'0'かは設定によるし、昔パワーオン直後のすべてのFFの値は'1'というPLDを使ったことがあった。

 ついでにスイッチ入力をFF受けで同期化してチャタリングを抑止するunchat.vを組み込んだ。同期回路に非同期の信号を直接入れるのは気持ち悪い。以下の様なトラブルを調査したことがあるが、こんなことがありえるのだ。

入力信号は必ずFF受けで 

 ここではカウンターで16分周した(50MHz÷65536=20ns×65536=1.3ms)間隔でスイッチの入力をサンプリングする。チャタリングはこの周期内には収まっている前提。
 パラメータ化はしていない。


DE0 オンボードのLED、スイッチ類のピンアサイン

「超入門!FPGAスタータ・キット DE0で始めるVerilog HDL」を見ながらDE0ボードで遊び始めているが、色々な実験をする前にピンアサインを入れてしまおう。毎回Pin Plannerで設定するのも嫌なので、本の途中を飛ばして第17章へ。最上位階層(top module)でないとFPGAのI/Oには接続できないが、ここで最上位階層の枠を決めて対応するピンもPin Plannerで定義してやると、あとはこれを保存しておけば別のデザインを始めるときに呼び出すだけでよい。ついでにLEDやスイッチのテストも兼ねた記述を入れた。

https://gist.github.com/4620609

// terasIC DE0 topmodule skeleton
// onboard I/O 3-button,10-sw,10-LED,4-7SEG
//
module Skeleton(clk,btn,sw,led,hled0,hled1,hled2,hled3,lcd_bl);
  input clk;
	input [2:0] btn;
	input [9:0] sw;
	output [9:0] led;
	output [7:0] hled0;
	output [7:0] hled1;
	output [7:0] hled2;
	output [7:0] hled3;
	output lcd_bl;
	
	assign led=(btn[2]==1'b1) ? sw: ~sw; // button2 press, then invert all LED
	assign hled0[7:0]=(btn[1:0]==2'b11) ? ~sw[7:0]: 8'b11111111; // 7segment digit xxx0
	assign hled1[7:0]=(btn[1:0]==2'b10) ? ~sw[7:0]: 8'b11111111; // 7segment digit xx0x press button 0
	assign hled2[7:0]=(btn[1:0]==2'b01) ? ~sw[7:0]: 8'b11111111; // 7segment digit x0xx press button 1
	assign hled3[7:0]=(btn[1:0]==2'b00) ? ~sw[7:0]: 8'b11111111; // 7segment digit 0xxx press button 1,0
	assign lcd_bl=sw[9]; // optiona LCD backlight
 
endmodule

プッシュボタンは押すと'0'、離した状態で'1'。
スライドスイッチは上の位置で'1'、下の位置で'0'。
緑のLEDは'1'で点灯。
7セグメントLEDはアノードコモンなので'0'で点灯。セグメントは上から時計回りにa,b,c,d,e,f、中央はg、小数点はdp。

 ピンプランナーでの画面。
pinplanner


せっかくピンアサインの対応表を作ったので以下にcsvファイルを置いときます。お手持ちの表計算ソフトで読み込んで下さい。

https://gist.github.com/4620569

動画はこちら。

terasIC DE0評価ボードで何か動かすまでのメモ

 2年ほど触らないままでいたFPGAの評価ボード(terasicのDE0)、ちょっときっかけがあったので使ってみた。サンプルの記述を論理合成してボードに転送し、スイッチとLEDを連動させるまでの手順。

terasIC Altera DE0 Board

DE0のマニュアルなど

以降Windows7(64bit)で作業。

開発用ソフトのダウンロード 最新はQuartus II v12.1 ウェブ・エディションをインストール
ALTERA

※これが約4GBと大きいのでウチなんかだと一晩コース


 「超入門!FPGAスタータ・キット DE0で始めるVerilog HDL」を参照しながら開始。
この本はQuartus II v9.0を例に説明してある。インストールと動作確認は1章、2章。
 論理回路がわかっている人は3〜6章は飛ばしていい。

 DE0をPCに接続する。デバイスがインストールされなかったら、 コントロールパネル>すべてのコントロールパネル項目>システム>デバイスマネージャーからUSB Blusterを探し、再インストール。C:\altera\12.1\quartus\drivers以下を指定。

☆最初のハマリどころ
[File]→[New Project Wizard...]でディレクトリを指定するが、ここがデスクトップだとパーミッションがないと言われ作成できなかった。自分のホームディレクトリだとOKだが、そこにプロジェクト用のファイルが散らばってしまうのでサブディレクトリを指定。

 FPGAデバイスは Family: CycloneIII で Available devices: から EP3C16F484C6を選択。
 他は設定しなくていい。


 プロジェクトウィザードが終了したら[File]→[New]でVerilog HDL Fileを選択。

この本のとおりにするとLesson1.vというファイル名で一旦保存。
次に以下のソースを入力。

module Lesson1( sw, led );
  input [9:0] sw ;
	output [9:0] led ;
 
	assign led=sw;
	
endmodule
 
/*
module Lesson1(
sw0,sw1,sw2,sw3,sw4,sw5,sw6,sw7,sw8,sw9,
led0,led1,led2,led3,led4,led5,led6,led7,led8,led9);
	input sw0,sw1,sw2,sw3,sw4,sw5,sw6,sw7,sw8,sw9;
	output led0,led1,led2,led3,led4,led5,led6,led7,led8,led9;
	
	assign led0=sw0;
	assign led1=sw1;
	assign led2=sw2;
	assign led3=sw3;
	assign led4=sw4;
	assign led5=sw5;
	assign led6=sw6;
	assign led7=sw7;
	assign led8=sw8;
	assign led9=sw9;
	
endmodule
*/

※コメント内は入出力をバラで書いた場合。

保存してから[Processing]→[Start]→[Start Anarysis & Elaboration]を実行。成功したら次はピンアサイン。
ピンアサインは[Assignments]→[Pin Planner]でピンプランナーを開く。
ここで NodeNameに対し以下のLocationを入力する。

NodeName Location
led[9] PIN_B1
led[8] PIN_B2
led[7] PIN_C2
led[6] PIN_C1
led[5] PIN_E1
led[4] PIN_F2
led[3] PIN_H1
led[2] PIN_J3
led[1] PIN_J2
led[0] PIN_J1
sw[9] PIN_D2
sw[8] PIN_E4
sw[7] PIN_E3
sw[6] PIN_H7
sw[5] PIN_J7
sw[4] PIN_G5
sw[3] PIN_G4
sw[2] PIN_H6
se[1] PIN_H5
sw[0] PIN_J6

このピン割当てについてはDE0_User_manualを参照。

[Processing]→[Start Compilation]でビルドする。

☆次のハマりどころ
[Processing]→[Start Compilation]でいきなりビルドするとピンアサインも勝手に割り当てられてしまい、ピンプランナーで付け替えることができない。
[Assignments]→[Remove Assignments]で□Pin,Location & Routing Assignmentsにチェックを入れて[OK]で解除。このあとピンプランナーで入力。

 あとはDE0に転送する。左側のスライドスイッチが[RUN]の位置にあることを確認し、DE0の電源を入れる。
[Tools]→[Programmer]で画面を開き、左上にある[Hardware Setup...]ボタンを押して USB-Blaster [USB-0] をダブルクリック。ここの設定は一回だけでよい。
転送はこの画面を開いて[Start]のボタンを押す。これでFPGAにConfigureが転送される。

 DE0の電源を入れるとデモがスタートするが、これは基板上のConfiguration用ROMからFPGAにデモが書いてあるイメージが転送されるため。上記操作だとDE0基板上のUSB-Bluster経由でPCからFPGAに直接転送される。

スライドスイッチをONにすると対応したLEDが点灯する。(動画)


 ビルド時のWarinigに関しては、今回はclockは使用していないので
332068 No clocks defines in design.
は無視。
332012 Synopsys Design Constraints File fine not found: ... 
は制約ファイルといってディレイのタイミングを調整するのに使うが今回は意識しないのでこれも無視。
(ってSynopsysの技術使ってるんだこれ)

 感想。こんなに気軽に出来るとは思ってなかった。身構え過ぎでした。
大昔、元職場の同僚がアルテラのPentium60/66MHzに似たパッケージの石を486DX100MHzのWindows3.1マシンで一生懸命設計しコンパイルに一晩かかっていたのを思い出しましたが、そんな話ではなかった。こんなに簡単に出来ていいのか、としばらくは興奮状態。

なつたんさん、今頃使いはじめてごめんなさい。これから使い潰します。

超入門!FPGAスタータ・キットDE0で始めるVerilog HDL: すぐ始められる!USB対応・書き込み器不要・大容量FPGA搭載! (トライアルシリーズ)超入門!FPGAスタータ・キットDE0で始めるVerilog HDL: すぐ始められる!USB対応・書き込み器不要・大容量FPGA搭載! (トライアルシリーズ)
芹井 滋喜

CQ出版 2011-07-22
売り上げランキング : 115091

Amazonで詳しく見る
by G-Tools

FPGA開発キットDE0の紹介

DE0_01
Terasic - FPGA Main Boards - Cyclone III - Altera DE0 Boardの紹介。USBケーブル、ACアダプタ、USBケーブル、プローブ、開発キット一式の入ったDVDも同梱され、あとは32bitのWindows環境があればOK。ソフトウェアの詳細は次回にでも。今回は舐め回すように基板を見てみよう。
DE0_02
主役、試作も量産も 低コストFPGA Cyclone III[ALTERA]のEP3C16、LE(ロジック・エレメント)数15,408、RAMメモリbit数516,096、18×18乗算器56、最大ユーザI/O数346。PLLは4系統だがこのボードでは50MHzしか使っていない。
DE0_03
 FLASH MEMORY SPANSION S29AL032D 2M×16bitでEP3C16に接続されている。
DE0_04
SDRAM Zentel A3V64S40ETP 4M×16bit PC166 これもEP3C16に直結。
DE0_05
USBブラスター部分。USBtoパラレルのFT245BLとCPLDのALTERA MAXII EPM240T、これらはPCとのインターフェースでありユーザは中をいじれない。
DE0_06
コンフィギュレーションROM、EPCS4。EP3C16の初期化に必要。DE0の"RUN"モードではUSBブラスターがこの代わりに初期化データをEP3C16に転送する。"PROG"モードではUSBブラスターはEPCS4の内容を書き換える。"RUN"モードでPCと接続されていない場合はEPCS4からEP3C16へ初期化データが与えられる。購入時はデモンストレーションが書きこまれてある。
 DE0_07
基板右上にあるのはシリアルポートの端子。レベル変換してあるのでそのままD-Sub15コネクタへ接続可能。
DE0_10
オプションの16×2桁LCD。5V品でおそらく同等品が使えると思われる。(動作時のVdd-Vss実測値は約4.1Vでした)
2011/8/7追記:バックライトLED端子の電圧は約4.0V。やはり5V相当品の模様。
DE0_12
オプションの16×2桁LCDをDE0基板に取り付けるには次の点に注意。先にDE0基板側にピンヘッダをハンダ付けしてからLCDをハンダ付けすること。また、写真の左上、液晶フレームを固定している金属部分がEP3C16の上に当たり干渉するので折り曲げておく。こうしないときちんとピンヘッダをハンダ付けできない。
DE0_14
付属のACアダプタ。7.5V/0.8A。こんなに小さい。

その他のTerasic製品ではDE0-NanoDE1DE2-115があるが、あらかじめLEDや入出力インターフェースがあり集積度もそこそこで価格が安いDE0が入門には向いていると思われる。また、DE0はすでに多数のユーザに使われてYouTubeなどにも動画がアップされており資料探しには困らないだろう。

 
とりあえず購入直後のデモンストレーションを実行し動作確認。
次回はソフトウェアです。

評価の機会を与えてくださった@natsutanさんに感謝。これからいじり倒しますので。

 DE0自体、DigikeyやSolitonWaveその他扱いが多く入手も容易であり、最近このような本が出たので導入は非常に楽になりました。記述はVerilogのみですが、開発環境のインストールからFPGA入門、DE0周辺の使用方法ひととおりとNIOS II(プロセッサ)の使用例が書いてあります。
 
 できるだけこの本に載ってないことを詳細に書いていく予定です。
 
 
記事検索
プロフィール

hardyboy

カテゴリ別アーカイブ
月別アーカイブ
QRコード
QRコード
  • ライブドアブログ