LoginSignup
2
1

More than 1 year has passed since last update.

FPGA Tang Nanoでstack machine CPUを動かす

Last updated at Posted at 2020-09-24

始めに

Tang Nanoという小さくて安価なFPGAボードで何かできないかというシリーズの第2弾。第1弾のSubleqという1命令CPUを作ったのですが、なかなか動作に癖があり、プログラミングというよりパズルを解いているようになってしまいます。もう少しCPUらしいものは作れないかと探すと、TTLでstack machineを作っている人がいました。これならレジスタの実装も要らなく、命令数を少なくすることで、Tang Nanoに載せられそうな大きさにできそうです。ということで、前作のSubleqで作ったUART利用のモニタ機能をそのまま使い、RTLを作成して動かしてみました。

参考ページ

Tang Nanoで1命令CPU Subleqを動かす

Tang NanoでuartのIPコアを動かした件

SiPeed Tang Nanoの環境構築(Windows編)

Sipeed Tang Nanoで遊んでみる (Linux版)

Tang NanoのFPGAとPC間でUART通信をする

GOWIN Semiconductor Corp.(IP仕様書等:要登録)

必要なもの

  • Windows10 PC
  • Tang Nano
  • USB typeCケーブル
  • Gowin IDE (windows 10版)
  • Teratermか、シリアル通信ソフト

Stack machineをTang Nanoに焼くまで

FPGAのIPをセットアップするところまでは、Tang Nanoで1命令CPU Subleqを動かすで書いた手順と全く同一です。そこまでが終了していることを前提とします。

githubからファイル一式をクローンします。windowsのgitを使うか、別途linuxでgit cloneしてディレクトリごとコピーしてください。

この中にはasm,sim,src,toolとありますが、srcのみを使用します。srcは以下のファイルリストになります。

clkgen.v
dram.v
iram.v
ramblk.v
sm_logics.v
sm_status.v
sm_top.cst
sm_top.sdc
sm_top.v
uart_controller.v
uart_if.v
uart_logics.v

これらのファイルをIDEに登録してください。以下のVerilog Filesというところを右クリックするとAdd Fileというメニューがでるので.vファイルをすべて登録してください。.cstファイルはPhysical Constraints Files、.sdcファイルはTiming Constraints Filesに登録してください。
ここまで来たら、processタブで、Synthesize、Place&Route、Program Deviceで焼くことができます。

接続はteratermを使用します。Tang NanoをUSBで接続した状態で、teratermを開きます。最初の通信相手の選択で、メニューの下の方にCOMポートの欄があります。ここが選択可能になっており、かつ、Tang NanoのCOMポートが選択できればOKで、それを選択して立ち上げます。

使用方法

操作はターミナル上で行います。仕様上の制約と思われるのは、キー入力のエコーバックが1入力分ずれます。しかも次のキャラクタの入力で、そのキャラクタがTang Nanoに受信されるように見えます。コツとしては、スペースを打つと、Stackmachineは無視するので、何かわからないときはスペースを打ってみると前の入力がエコーバックしてきます。(Bugfixしました。2021/8/22)

本Stack machineの仕様とUart monitorの使用方法です。gitのreadmeをそのまま引っ張ってきたので、へたくそで申し訳ありませんが、英語です。

Specification:

  • 8bit data stack machine archtecture with uart debugger
  • Instruction: 8bit or 16bit word length
  • 8 instructions available
  • Instruction memory: 8bit 256words : all for instructions
  • Data: 8bit length
  • Data stack 31 steps: because of Tang Nano's capacity of logics
  • Data register: reg_a and reg_b 8bit rength
  • Data reg_a is set stack's pop'ed data
  • Data reg_b is set reg_a's data when pop stack
  • Uart: controlling load programs, reading wiriting memory, excecutions, and monitoring

Instructions:

  • 1st byte 7:4 : opecode
  • 1st byte 3:0 : control bits
  • 2nd byte 7:0 : Immediate value or jump address (2byte instruction only)

  • opecode: 0 : JMP
    Jump command controlled by flag bits
    bit 3 : Stack Underflow : 1: data stack underflow : can be cleard by CLR
    bit 2 : Stack Overflow : 1: data stack underflow : can be cleard by CLR
    bit 1 : Carry : 1: previouse calculation results carry
    bit 0 : Zero : 1: previouse calculation results zero value
    calculation: ADD SUB CMP only

    none : Immediate Jump
    2nd byte : Jump address

  • opecode 2 : POP
    Pop 1 value from data stack and store reg_a
    reg_b also stored reg_a's previouse value

  • opecode 4 : PUSH
    Push 1 value to data stack
    value can be used as reg_a, reg_b and Immediate
    bit 1: reg_b selected
    bit 0: reg_a selected
    none : Immediate value selected
    2nd byte : Immediate value (when immediate selected)

  • opecode 6 : ADD
    Add reg_a and reg_b or Immediate value, push result to data stack and change flags
    bit 0: Add reg_a and reg_b
    none : Add reg_a and Immediate
    2nd byte : Immediate value (when immediate selected)

  • opecode 8 : SUB
    Subtract from reg_a to reg_b or Immediate value, push result to data stack and change flags
    bit 0: Subtract from reg_a to reg_b
    none : Subtract from reg_a to Immediate
    2nd byte : Immediate value (when immediate selected)

  • opecode a : SUB
    Subtract from reg_a to reg_b or Immediate value, and only change flags
    bit 0: Subtract from reg_a to reg_b
    none : Subtract from reg_a to Immediate
    2nd byte : Immediate value (when immediate selected)

  • opecode c : OUT
    Pop a data and output poped data to port#'s port, reg_a and reg_b also changed as POP
    2nd byte : port# ( only port 0 is impremented for LED )

  • opecode e : CLR
    Clear data stack pointer to zero and clear all flags to zero

  • opecode f : NOP
    Only step PC up

Uart monitor

Uart monitor can use to control CPU, read/write memory, monitor CPU status.
Control commands

  • g XX : Execute CPU form address XX

  • w XX : Write instruction memory from address XX

  • r XX YY : Dump instruction memory between XX and YY

  • p : Dump data stack memory

  • s : Step CPU execution

  • t : Trash and fill 0 to instuction memory, data stack, registers, flags

  • q : Quit : using g and w

Command g and s : Output log to uart. Each instruction makes log
incuding PC, instruction bytes, flag, reg_a, reg_b, stack pointer

Command r and p : Dump memory with 4 bytes per line.

プログラムの作り方

toolにperlで書いた簡単なアセンブラを置きました。asm2.plです。perlのある環境で、アセンブラのファイルを食わせるとバイナリ列を吐き出します。asmの下にあるファイルはすべて変換が可能です。これをもとに書いてみて下さい。Lチカなどあります。
これを実機で動作させる場合は、以下のようにバイナリ列をコピペしてください。
w 00
<バイナリ列をコピペ>
q
g 00

これで動作させることができます。uart monitorはスペースとCRを無視してくれるので、
asm2.plが吐くCRの多いテキストもそのままコピペできます。
動かしてみてください。

最後に

このRTLですが、ここから少しでも論理を増やすと配置エラーとなり、Tang Nanoで動かなくなります。もうこのFPGAでは限界かなと思っております。次はもう少し規模の大きなものに挑戦したいので、どのFPGAがよいか物色中です。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1