第11回: 実習(6): FPGAへのCPUの実装(1)
前回概略を設計したCPUを、順番に作っていくことにします。
まず今回は、レジスタと演算器(データパス)のまわりをつくってみます。
全体構成
全体の動作は、クロックclkに同期して(=clkの立ち上がりで)行います。
若干天下り的ですが、全体構成を以下のようにすることにしてみます。
- datapath_reg: 演算結果・Zフラグの更新するべき値を生成
- reg: レジスタ・Zフラグフラグ。clkに同期して、control_regから受け取る
「r0, r1を更新するべき値」をr0, r1に書き込む。
- control_reg: 命令(op)に応じて、「r0, r1を更新するべき値」を生成する。
- datapath_pc: プログラムカウンタ(PC)の更新するべき値を生成
- pc: プログラムカウンタ。clkに同期して、datapath_pcから受け取る
「pcを更新するべき値」をpcに書き込む。要は機能はレジスタと同じ。
- mem: プログラム格納メモリ
演算関係のデータパスの設計
前回のCPUの仕様をもとに、以下のような入出力に対して
データパス部分(datapath_reg.vhd)を設計し、VHDLで記述してみましょう。
- 入力: op(4bit), imm(4bit), r0i(4bit), r1i(4bit), zi(1bit)
※r0i, r1iは「現在のレジスタの値」、 ziは「現在のZフラグの値」として与える。
- 出力: res(4bit), r0o(4bit), r1o(4bit), zo(1bit)
※zoは、次にZフラグにセットされるべき値を出力する
これらの入出力を使って、前回のCPUの命令実行の仕様を満たすように
レジスタに代入するべきresとZフラグにセットするべき値を求める
データパスを記述し、シミュレーション・実機により動作を確認してみましょう。
ただし次回の制御回路の設計で必要となるため、入力であるr0i, r1iを
そのまま出力する出力r0o, r1oをつけておきます。
以下、ひな形:
entity datapath_reg is
port( op, imm: in std_logic_vector(3 downto 0);
r0i, r1i: in std_logic_vector(3 downto 0);
zi: in std_logic;
res, r0o, r1o, : out std_logic_vector(3 downto 0);
zo: out std_logic_vector);
end datapath_reg;
architecture Behavioral of datapath_reg is
begin
...
end Behavioral;
ちなみにこのresの値を、クロックにあわせて
命令opに応じて別途レジスタ(r0またはr1)に保存することになります。
ヒント
- この部分は、クロックが現れない「組み合わせ論理回路」になります。
- これの上位に全体構成のdatapath_reg_top.vhdを記述し、これの入出力として
プッシュスイッチ(PSW)やLED、さらに必要に応じて7セグメントLED用の信号
(SG, SA)を定義し、その中で設計したcpuをインスタンスとして呼び出し、
さらにピン定義(edx001.ucf)を使ってコンパイルするとよい。
- 入力をプッシュSWで与え、結果のresをLEDや7セグメントLEDで
表示させて動作を確認するとよいでしょう。
- ただし入力のプッシュスイッチが4個しかないので、
opやimm、r0i、r1i、ziの足りない部分はdatapath_reg_top.vhdで
定数として与えるのが現実的でしょう
プログラムカウンタのデータパスの設計
続いて、プログラムカウンタ(PC)まわりとZフラグの動作を記述する
datapath_pc.vhdをつくってみます。
前回のCPUの仕様をもとに、以下のような入出力に対して
データパス部分(datapath_pc.vhd)を設計し、VHDLで記述してみましょう。
- 入力: op(4bit), imm(4bit), pci(4bit:「現在のPCの値」として与える), zi(1bit)
- 出力: pco(4bit:次にPCがとるるべき値を出力する)
※上のブロック図ではziに対応する線がありませんが、PCの値の決定には、現在のZフラグの値が必要なので、追加しておいてください。
これらの入出力と内部変数を使って、前回のCPUの命令実行の仕様を満たすように
PCに代入するべき値pcoをきめるデータパスを記述してみましょう。
以下、ひな形:
entity datapath_pc is
port( op, imm, pci: in std_logic_vector(3 downto 0);
zi: in std_logic;
pco: out std_logic_vector(3 downto 0));
end datapath_pc;
architecture Behavioral of datapath_pc is
begin
...
end Behavioral;
ヒント
- この部分は、クロックが現れない「組み合わせ論理回路」になります。
- これの上位に全体構成のdatapath_pc_top.vhdを記述し、これの入出力として
プッシュスイッチ(PSW)やLED、さらに必要に応じて7セグメントLED用の信号
(SG, SA)を定義し、その中で設計したcpuをインスタンスとして呼び出し、
さらにピン定義(edx001.ucf)を使ってコンパイルするとよい。
- 入力をプッシュSWで与え、結果のpcoをLEDや7セグメントLEDで
表示させて動作を確認するとよいでしょう。
- ただし入力のプッシュスイッチが4個しかないので、
opやimm、pciの足りない部分はdatapath_reg_top.vhdで
定数として与えるのが現実的でしょう
メモリの設計
今回はメモリは読み出し専用ですから、デコーダと同様に
入力として与えるアドレスaddrに応じて、そこの値dataを出力する
回路、として設計すればよいことになります。
例えばテスト用に次のような「プログラム」を保持するメモリを設計してみましょう。
アドレス | 内容 | 命令 |
0 | 0000 0001 | mov 1, r0 |
1 | 0010 0010 | add r0, 2, r0 |
2 | 0110 0010 | jmp 2 |
以下、ひな形:
entity mem is
port( addr: in std_logic_vector(3 downto 0);
data: out std_logic_vector(7 downto 0));
end mem;
architecture Behavioral of mem is
begin
...
end Behavioral;
戻る