ＶＴＬ＿ｏｎ＿ＦＰＧＡ[その３　ＦＰＧＡへのプログラミング]

#効能
　FPGAに書き込むと、FPGAでVTLを使うことが出来るようになります。

#元ネタ
　スクラッチからでは能力的にも時間がかかりそうなので、下記サイトのものをベースに使わせてもらっています。
　　[［■[fpga] CPUの創りかた TD4 を Spartan-3A で］](http://d.hatena.ne.jp/propella/20080616/p1)
　※許諾については記載が無いので、黙って使わせていただいておりますが、問題あれば取り下げます。
　当初は気付かなかったが、フェッチと演算が非同期、命令処理が同期式の、２段パイプライン?になっていました。

#方針(方向性)
##メモリは身の丈に合ったサイズで
　これを作る前に、下記を参考に(パクッて)32bitバージョンを作成した。
 　 [［独自CPUを作る（Verilog HDL版）］](http://cellspe.matrix.jp/zerofpga/simple_cpu_verilog.html)
　　　1.命令語長　32bit
　　　2.レジスタ　16bit(A-Z)
　　　3.実行速度　50Mhz - 90Mhz
　　　4.ハード　　Xilix xc6slx9(Papilio)
　　　5.処理構成　３段パイプライン(元ネタの性能です)
　機能的には今回のものと同程度に仕上がったが、オブジェクト効率が悪いため放置。
　※コンパイラソースが8KB、機械語オブジェクトが16KB、オブジェクトがスカスカで悲しい。
　　但し、処理は早く「A=B」を1clockで実行できた。
##FPGAは小さく、安くがよろしい
　つらつら考える。
　　1.Papilioもよくできているが、もう少し小さく(安く)てもいいではないか。
　　2.spaltan6はXilinxに切り捨てられ、継子扱い。
　　3.alteraの旧世代を使った中華製のボードがEbayで見つかる。
　「そうだ、CycloneIVが有るじゃないか」とEP4CE6に趣旨替えをする(だがメモリは少ない!)。

#ハードウェア
　Ebayで下記のボードを購入(\4975ナリ)
　　「EP4CE6 FPGA Board with Programmer Altera Cyclone IV NIOS II」

  ![image2.jpg](https://qiita-image-store.s3.amazonaws.com/0/159764/39724c7a-6ab1-266f-dd4e-a3a410a79465.jpeg)

　使用例がここに有りました。
　　[［[FPGA] EP4CE6 Starter Board］](http://www.jakubcabal.cz/blog/2016/09/16/fpga-ep4ce6-starter-board/)
　ボードの解説がここに有ります。
　　[［EP4CE6-Starter-Board-Docs］](https://drive.google.com/file/d/0B29qKrGuvpGDcEx3QjVUNG9qRVE/view)
　　※プレビューエラーとなるがダウンロードは可能
　USBブラスター機能もついていて、パソコンとUSBケーブルで繋げは即開発可能。
　全体的にショボく、もう少し頑張ってほしい部分もあるが、値段を考えればこんなものか。

#開発内容
　1.4bitを8bitに拡張(TD4x2)、さらに16bitに拡張(TD4x4)。名前も拡張したがセンスが..。
　2.VTLのコンパイル後の機械語命令を想定し、まずは単純な命令から、必要となる機械語を算出。
　　C=B+1     ; VTLソースの例
　　　↓
　　LD  Ra,B  ; 機械語
　　LD  Rb,#1 ;
　　ADD Ra,Rb ;
　　ST  C,Ra  ;
　3.実行ロジックをverilogでしこしこ書き出す。
　　個々の命令にcase文で分解して、個別の処理をはめ込んでいく。
　　　begin regx[regno] <= regx[varno]; PC <= PC + 1; end // LD Rx,Vx
　4.演算はFPGAにおまかせで処理する。
　　assign ALU =  (calno == 5'd1)  ? regx[0] + regx[1] : // ragA=ragA + regB
　　※まさか割り算が使えないとは気が付かなった。(泣く泣くソフトで処理)
　5.複雑な命令はなるべくコンパイラで分解、それでもだめならシーケンス処理。
　　4'b0100, 4'b0101: // LDM Ra,(Ra).b,w
　　case(op_cycl)
　　　0: begin SP <= SP + 1; mwe <= 0;  memsel <= 2; op_cyclm <= 10; op_holdct <= 9; end
　　　1: begin SP <= SP + 1; end
　　　2: begin SP <= SP + 1; regw[15:8] <= memout; end // 配列先頭読み出し
　6.ロジックが完成したら、シミュレーターで単体機能の動作を確認する。
　7.動作OKならコンパイルし、実機にのRAMにロードして確認する。
　8.実機OKなら、実機に書き込む。書き込み方法は２種類有る。
　　(1)ASモード　　接続コネクタが２個あり(JTAG,AS)、差し替えて書き込む方法
　　(2)JICモード 　jicファイルを作成し、１つのコネクタで書き込む方法
　　　※場所を取りますが、JICへのコンバートと、JICの書き込み画面を表示。(少しはまったので)
![jic.jpg](https://qiita-image-store.s3.amazonaws.com/0/159764/acb9b1c8-f873-9084-2979-1253b8c14cd1.jpeg)
![programer.jpg](https://qiita-image-store.s3.amazonaws.com/0/159764/9bec55b4-b207-690b-6acf-5d7cf7c19d38.jpeg)

#コンパイル
  Quartus Prime ライト・エディション(17.1)でコンパイラしています。(18.0でも問題ないと思われる)
　　[［ダウンロード・センター］](https://www.altera.co.jp/downloads/download-center.html)
　プログラムソースはこちらに上げています。
　　[［TD4X4］](https://github.com/hi631/VTL_on_FPGA/tree/master/td4x4)
　※通信モード　115200bps　8.n.1
#ＴＤ４ｘ４ 命令一覧
##　TD4x4はの命令語長は３種類
　　1.1byte 計算命令、レジスタへのロード/ストア
　　2.2byte 8bitの数値ロード
　　3.3byte 16bitの数値ロード、ジャンプ、メモリアクセス等
　　※命令一覧の更新漏れが有るかも
##下記の命令を実装(しているはずです)

```
	---------------+---------------+---------------------------------------------------------------
	命令　			ビット構成　		動作
	---------------+---------------+---------------------------------------------------------------
	計算 Ra,Rb　　	0000CCCC		Ra <- RaとRb間で計算  CCCCC=
									___ ADD SUB AND OR_ ^__ MUL SR_ EQU GT  GE  LT  LE  NE  NEG NOP
					0010CCCC		(未定義)
					00010xxx		(未定義)
	LD  Rs,Rx		00m11000		m:条件=0:$18:SP -> A =1:$38:SP <- A
	LD  Rx,Rx		00m11001		m:条件=0:$19:A -> B  =1:$39:A <- B
	XAB Ra,Rb		00011010		$1A レジスタ交換 A <-> B
					00m11xxx		
	IN/OUT			00m11111		M:条件=0:Input($1F)  =1:Output($3F)
	LD  Rx,Vx		01RVVVVV		$40+R+V Rx <- Vx  Rx=regA/B  Vx(変数)=regA/B,A-Z($1B)/%/&/*/_
	ST  Vx,Rx		10RVVVVV		$80+R+V Vx <- Rx
					1100000m		(未定義)
	RTS				1100001b		$C2+b(0)
	LDM Ra,(Ra)		1100010b		$C4+b メモリ読み出し　b:バイト数=0:1byte  =1:2byte
	LDM (Ra),Rb		1100011b		$C6+b メモリ書き込み　
	PE/PO (SP)		11001mxx		$C8+m regAと(SP+xx*2)でデータ交換　m:条件=0:Read  =1:Write
	PUSH/POP Rx		1110mxxx		$Ex m:条件=0:$E0:POP  =1:$E8:PUSH xxx=0:regA 1:regB 2-7:A-F
	JPx xxyy		1101JJJJ+xx+yy	$Dx 条件成立時ジャンプ　JJJJ=0($D0):JZ =1($D1)JNZ
	JPx xxyy		11011JJJ+xx+yy	$Dx($D6/D7/F6/F7除外) 条件ジャンプ JJJ=0:$D8:JZ 1:$D9:JNZ
					11111xxx+xx+yy	$Fx($D6/D7/F6/F7除外)
	JSR				11011110+xx+yy	$D6/$DE
	JMP				11111110+xx+yy	$F6/$FE
	LDI Rx,xxyy		11R1b111+xx+yy	Rx <- #xxxx b:バイト数 =1:$DF/$FF(2byte) =0:$D7/$F7(1byte)
	---------------+---------------+---------------------------------------------------------------

```


## その他
　とりあえず動いているのレベルであり、状況によっては動かない可能性が有ります。
　上記記載のハード、ソフトは無保証であり、各自の責任においてご利用願います。