PicoBlazeのソースを見ていて、自分でもこういうカリカリのソースを書いてみたいけど、プリミティブ一覧はどこにあるんだろう……
と思っていたら、ドキュメントの中にありました。

\Xilinx\doc\japanese\books\docs\lib\lib.pdf

今まで知らなかった……
また、ISE8.1iからWebpackでもFPGA Editorが使えるようになったので、それを見ながら更にカリカリにチューニングできるなぁ……

ということで、書いてみることにしました。
PICを4ビット化したものをベースに、最低限を少し下回るくらいの仕様を考えます。
より素直な命令体系にするため、スキップ系の命令の代わりに、条件分岐にします。
また、キャリー付き加算/減算を追加します。
PICが持っているSFRは全く持たないので、間接アドレシング、間接ジャンプはできません。
(余談ですが、PICを初めて使ったとき、SFRなしには間接アドレシングができないことに愕然としたものです)
データアドレスは8ビット(I/Oと共通)、プログラムカウンタは8ビット、スタックは16段です。
割り込みはありません。
結局、以下のようなインストラクションセットにしました。
0100 vv0d aaaa aaaa
     00 ADDWF a,d キャリー無し加算       Z C
     01 ADCWF a,d キャリー付き加算       Z C
     10 SUBWF a,d キャリー無し減算       Z C
     11 SBCWF a,d キャリー付き減算       Z C
d=0のときは結果をWレジスタに格納し、d=1のときは同じアドレスに書き戻します。

0100 vv10 xxxx llll
     00 ADDLW l Wレジスタにlを加算       Z C
     01 ADCLW l Wレジスタにlとキャリーを加算  Z C
     10 SUBLW l lからWレジスタを減算      Z C
     11 SBCLW l lからWレジスタとキャリーを減算 Z C

0101 vv0d aaaa aaaa
     00 MOVF  a,d データメモリからロード    Z -
     01 ANDWF a,d 論理積            Z -
     10 IORWF a,d 論理和            Z -
     11 XORWF a,d 排他的論理和         Z -

0101 vv10 xxxx llll
     00 MOVLW l Wレジスタにlをロード      - -
     01 ANDLW l Wレジスタとlの論理積      Z -
     10 IORLW l Wレジスタとlの論理和      Z -
     11 XORLW l Wレジスタとlの排他的論理和   Z -

0110 xx0d aaaa aaaa
        RRF   a,d 右ローテート         Z C
前もってADDLW 0などでキャリーフラグをクリアしておけば論理右シフトになります。
左ローテートはADCWFで、左シフトはADDWFで代用します。

0111 xx01 aaaa aaaa
        MOVWF a Wレジスタからデータメモリへストア

1100 xxxx aaaa aaaa
        B     a 無条件分岐

1101 vvxx aaaa aaaa
     00 BNZ   a Z=0なら分岐
     01 BZ    a Z=1なら分岐
     10 BNC   a C=0なら分岐
     11 BC    a C=1なら分岐
減算時のキャリーフラグはPICとは逆で、Z80と同じです(C=1でボローあり)。

1110 xxxx aaaa aaaa
        CALL  a

1010 xxxx xxxx xxxx
        RETURN

実装

スパルタン3用に全てプリミティブで記述し、FPGA Editorで結果を見ながら適宜MUXF5,MUXCY,XORCYプリミティブを使ったり、RLOC,BEL制約を追加して詰め込んだ結果、コアのみで32スライスとなりました。
この程度の大きさならパズル感覚で全てのスライスを手動で最適化するのも簡単です。
本当は、普通に書いても同じ大きさになるくらいツールにがんばって欲しいものですが。
ところで、PICで引き算をしたとき、C=0でボローありになりますが、この仕様だとXORゲートが1つ減らせることが分かりました。PICらしい設計思想です。
今回は、スライス内で余っているXORCYプリミティブを使い、スライス数は同じで自分にとって分かりやすい方を採用しました。

サンプル

スパルタン3スターターキット用のサンプルです。
コアの外にプログラムメモリとしてブロックRAMを1つ、データメモリとして16ニブル(64ビット)追加します。
I/Oは入力にプッシュスイッチ4つ、出力にLEDを4つ繋げました。
一番右のスイッチを押すと右に、その1つ左のスイッチを押すと左に、光が流れます。
このサンプルで37スライス、fmax=84MHzとなりました。1命令当たり1クロックで動作するので、84MIPSとなります。

サンプルの使い方を説明します。
アセンブルにAASMを使いますので、インストールしておいてください。
あと、objcopyも必要なので適当なGNU binutilsをインストールしてください(参考:MIPSマイコンを作ろう)。
いったんmakeしたあと、ISEのプロジェクトファイルを作り、以下のファイルを登録します。
kp4_top.v
kp4_top.ucf
kp4_core.ngc
rom.sを書き換えればいろいろなプログラムを試すことができます。
スライドスイッチや7セグLEDなど、I/Oを追加したいときはkp4_top.vを適当に書き換え、ピン配置をkp4_top_ucf.tmplに書いてください。

PicoBlazeより非力でも、更に小さいコアが欲しいとき使えるかも知れません。

download

このソース(NGCファイルを含む)は、非営利目的に限り自由に使用できます。
ただし、いっさいの保証もサポートもありません。