全部FPGAでTD4を実装する

全体を組み合わせる。あとはメモリーブロックに直接プログラムが書き込めればいいのだが今のところ方法が分からず、プログラムメモリーの初期化ファイルを書き換えるたびに毎回全体をコンパイルしている。

TD4は、クロックを受けた時点でROMから命令を受け取り終えていなければならないため、DFFを2個挟み込んでCPU側のクロックを少しだけ遅らせた。

A_REG、B_REGについても、確認できるよう端子を出した。
f:id:ti-nspire:20210901093818p:plain

↓これが、プログラムメモリーの初期化ファイルを作るためのPythonスクリプト:

def generate_mif(file_name, width, depth, rom):
    f = open(file_name, "w")
    f.write("WIDTH=%d;\n" % width)
    f.write("DEPTH=%d;\n" % depth)
    f.write("ADDRESS_RADIX=UNS;\n")
    f.write("DATA_RADIX=BIN;\n")
    f.write("CONTENT BEGIN\n")
    format_of_code = "0" + str(width) + "b"
    for i in range(depth):
        machine_code = format(rom[i], format_of_code)
        f.write("%10d   :   %s;\n" % (i, machine_code))
    f.write("END;\n")
    f.close()

def MOV_A(Im): return ( 3 << 4)|(Im & 0xF) # AレジスタにImを転送
def MOV_B(Im): return ( 7 << 4)|(Im & 0xF) # BレジスタにImを転送
def MOV_AB() : return ( 1 << 4)            # AレジスタにBレジスタを転送
def MOV_BA() : return ( 4 << 4)            # BレジスタにAレジスタを転送
def ADD_A(Im): return ( 0 << 4)|(Im & 0xF) # AレジスタにImを加算
def ADD_B(Im): return ( 5 << 4)|(Im & 0xF) # BレジスタにImを加算
def IN_A()   : return ( 2 << 4)            # 入力ポートからAレジスタへ転送
def IN_B()   : return ( 6 << 4)            # 入力ポートからBレジスタへ転送
def OUT(Im)  : return (11 << 4)|(Im & 0xF) # 出力ポートへImを転送
def OUT_B()  : return ( 9 << 4)            # 出力ポートへBレジスタを転送
def JMP(Im)  : return (15 << 4)|(Im & 0xF) # Im番地へジャンプ
def JNC(Im)  : return (14 << 4)|(Im & 0xF) # Cフラグが1ではないときにIm番地へジャンプ


FILE_NAME = "rom_init.mif"
WIDTH =  8
DEPTH = 16
_ = [0] * DEPTH

pc = -1
jump_where = pc+1
_[(pc:=pc+1)] = MOV_B(0b0001)
_[(pc:=pc+1)] = MOV_AB()
_[(pc:=pc+1)] = OUT_B()
_[(pc:=pc+1)] = MOV_B(0b0010)
_[(pc:=pc+1)] = MOV_AB()
_[(pc:=pc+1)] = OUT_B()
_[(pc:=pc+1)] = MOV_B(0b0100)
_[(pc:=pc+1)] = MOV_AB()
_[(pc:=pc+1)] = OUT_B()
_[(pc:=pc+1)] = MOV_B(0b1000)
_[(pc:=pc+1)] = MOV_AB()
_[(pc:=pc+1)] = OUT_B()
_[(pc:=pc+1)] = JMP(jump_where)

generate_mif(FILE_NAME, WIDTH, DEPTH, _)

↓これが、上のPythonスクリプトで生成された初期化ファイル。

WIDTH=8;
DEPTH=16;
ADDRESS_RADIX=UNS;
DATA_RADIX=BIN;
CONTENT BEGIN
         0   :   01110001;
         1   :   00010000;
         2   :   10010000;
         3   :   01110010;
         4   :   00010000;
         5   :   10010000;
         6   :   01110100;
         7   :   00010000;
         8   :   10010000;
         9   :   01111000;
        10   :   00010000;
        11   :   10010000;
        12   :   11110000;
        13   :   00000000;
        14   :   00000000;
        15   :   00000000;
END;

実行結果:
右から4ビットずつ、B、A、OUTの各レジスタの値。