まごころせいじつ堂

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

verilog

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

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%)だった。まだ行けそうね。

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でよさそうだがちょっと考えよう。
記事検索
プロフィール

hardyboy

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