動かしてわかるCPUの作り方10講(技術評論社)

レジスタの読み出し部reg_dcをシンボルで書き換える

74シリーズはあきらめてmegafunctionsを使うことにする。クロックのタイミングで16ビット×8本のうち1本を選んで更新する。

4相クロックジェネレーターclk_genをシンボルで書き換える

テキストどおりVHDLで記述していた回路をシンボルで書き換える。これは単純なので問題ない。

レジスタに入っている16ビットデータを5桁の十進数値としてキャラクターLCDに表示する

テキストは、VHDLで組んだ二進 → 十進変換回路でOUTポートのデータを十進数に変換し、それを5桁の7セグLEDで表示している(pp.221ff.)。 ここでは、せっかくCPUを作ったのでソフトウェアで解決してみる。たとえば0d54321は次の手順で各桁を取り出す。詳細不明…

レジスタに入っている16ビットデータを4桁HEX値としてキャラクターLCDに表示する

############################ # アセンブラ(のようなもの) # ############################ import math def constrain(val, _max, _min): return int(min(max(val, _min), _max)) def generate_mif(file_name, width, depth, rom): f = open(file_name, "w…

キャラクターLCDに何かを表示する

3.3 Vで直接動かせるSC1602BBWB-XA-LB-Gを使う。PIC16F1789/1939 & MPUトレーナー カテゴリーの記事一覧 -の評価基板に載っていたのを外した。8ビットモードで動かす。 下のように接続する。 CPUのOUT[7:0] → LCDのDB[7:0] CPUのOUT[8] → LCDのRS CPUのOUT[9…

sra命令(算術右シフト)を廃止してjmp_reg命令(ジャンプ先のアドレスをレジスタで指定)を追加する

sra命令を廃止する。代わりに、即値ではなくレジスタでジャンプ先が指定できる命令を追加する。exec_jnc.vhdのsra命令の部分を下のように書き換える。 --when "0111" => -- SRA -- REG_IN_TEMP <= '0' & REG_A(15) & REG_A(15 downto 1); --REG_WEN <= '1'; …

追加したjnc命令でLチカ

今度は、hlt命令を廃止してjnc (jump if no carry)命令を追加する -で追加したjnc命令を使ってLチカをしてみる。ビジーループ自体は2命令で済む。もっと遅くしたい場合はnop命令を挟む。nopも4クロックを要する。 F_CPU = 10E3 DELAY = 0.5 # sec LOOPS = in…

reg_dc、reg_wbの両コンポーネントの入出力を2次元化して配線をスッキリする

register /レジスタ/ resistor /リズィスタ/ reg_dc、reg_wbの入出力を2次元化する。VHDLでの記述方法がわからないため回路図エディターを使った。 変更前: 変更後:

decodeコンポーネントを外す

/ディーコウドゥ/ p.178, p.182 結局第10講には進まず、パイプライン化はしないことにしたので、decodeコンポーネントは要らなくなった。下のように取り外して配線し直す。 変更前: 変更後:

割り算

今度は、『動かしてわかるCPUの作り方10講』第9講までのCPUと、テキストとは別に追加したjnc命令とを使って割り算をしてみる。値はunsigned shortであると見なす。 0xABCD ÷ 0x0123 = 0b 0000 0000 1001 0111を計算した。 .mifファイルを生成するアセンブラ…

hlt命令を廃止してjnc (jump if no carry)命令を追加する

テキストは加減算のキャリー、ボローを見ていないため少し不便である。そこで、hlt (停止)命令はよして代わりにjnc (jump if no carry)命令を追加する。要は、キャリービットを含む17ビットの信号REG_IN_TEMPを追加しただけである。hltの代用はjmp 自番地と…

掛け算

今度は掛け算をしてみる。 今、0x0010 * 0x0876 = 0b 1000 0111 0110 0000を計算したところである。 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("A…

『動かしてわかるCPUの作り方10講』第9講までのCPUでLチカをする

クロックは10 kHzにしてある。すべての命令が実行に4クロックを要する。 ROMの初期化データである.mifファイルを生成するためのアセンブラのようなもの: def generate_mif(file_name, width, depth, rom): f = open(file_name, "w") f.write("WIDTH=%d;\n" %…

第9講まで(パイプライン化の前まで)を実装

pp.290ff. 今度は、ROMと同じ要領でRAMもメモリーブロックへ移す。これでRAMは0~63番地まで使えるようになった。ただ、クロックの変更に関する理解が追いつかないため、テキストのVHDLのままシンボル化して配線するにとどめる。 テキストは最後の第10講でパ…

2つに分けていたRAMモジュールを排列化でひとつにまとめる

pp.274-276 コメントを足した以外はテキストのままである。 library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_unsigned.all; entity ram_dc_wb is port( CLK_DC : in std_logic; CLK_WB : in std_logic; RAM_ADDR : in std_logic_vector(7 do…

ROMをメモリーブロックに移す

pp.256ff. これまでROM (プログラムメモリー)は、15ビット×16本だけをLEで実装していたが、今度は15ビット×256本のROMをメモリーブロック上に作る。手順はROM: 1-PORTの使いかた -に示した。初期化データである.mifファイルを生成するためのアセンブラのよう…

.mifファイルを生成するアセンブラのようなものを作る

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 =…

低速動作用のクロックを生成する

pp.239ff. 前回までは、外部のFGからクロックを供給していた。今度は、評価ボードに実装されている48 MHz発振器(27番ピンに接続)からクロックを供給する。極端に遅くしたクロックを供給することにより、動作が目で追えるようにする。 テキストは、VHDLで構成…

モジュールごとにシンボル化する

今度は、モジュールごとにシンボル化してそれぞれを回路図エディターで結線してみる。中身はあいかわらずテキストのVHDL (pp.186-207)のままである。動作は前回とまったく同じ。

第1部のcpu15.vhdの動作確認

pp.216ff. テキスト第1部までのcpu15.vhd (pp.186-207)をそのまま動かしてみる。 ピンアサインは下のようにした(参考: 『MAX10実験キットで学ぶFPGA&コンピュータ (トライアルシリーズ)』)。今使っている評価ボードMAX10-FB (10M08SAE144C8G)にも発振器(48 M…

RAMへの書き込み部を74シリーズで作る

構造は、レジスタへの書き込み部と同じである。無駄を承知で8:256のデコーダーで256本まで選べるようにしたが、ここではテキストどおりに8+1本だけ実装した。クロックのタイミングで1本だけを書き換える。IO64_OUTを外部へのOUTポートに使う。 これも動作は…

レジスタへの書き込み部を74シリーズで作る

ここに、8本×16ビットの汎用レジスタを実装する。クロックのタイミングで1本だけを書き換える。 これも動作は未確認。

全部まとめてexec部を作る

動作は未確認。

HLT命令を74シリーズで実装する

halt命令。これで全16命令が一往実装できた。 /ホーるトゥ/

ST命令を74シリーズで実装する

汎用レジスタの値をRAMへ格納する命令。

LD命令を74シリーズで実装する

RAMからレジスタへデータを持ってくる命令。

JMP命令を74シリーズで実装する

PCを強制的に書き換える命令。

JE (jump if equal)命令を74シリーズで実装する

CMP_FLAGがHiのときにはPCを即値で書き換える。 CMP_FLAGがLoのときにはPCをカウントアップする。

CMP (比較)命令を74シリーズで実装する

74シリーズにコンパレーターはいくつかあるがここでは74684を使うことにする。 OP_CODEが10のときに2つの16ビットレジスタが同士が一致したらコンペアフラグが立つ。それ以外のOP_CODEのときは出力がオフになる。

LDL命令(2バイトのうち下位バイトを書き換え)およびLDH命令(2バイトのうち上位バイトを書き換え)を74シリーズで実装する

まずLDLを実装する。 次にLDHを実装する 2つを組み合わせる。 以下の2つを確かめる。 OP_CODEが8のときに下位バイトだけが書き換えられること。 OP_CODEが9のときに上位バイトだけが書き換えられること。 0xFFFFの下位バイトを0xAAで書き換える。 0xFFFFの上…