FPGAでTD4を作成する1(ROM作成)
「CPUの創りかた」という本に載っている4bitCPU「TD4」をFPGAで作成します。
使用するFPGAボードはXilinxのBasys2で、言語はVHDLです。
各パーツごとに作成して最後に全体を統合します。今回はROMを作成します。
TD4の作成について
使用ボード:Basys2 (Xilinx)
ツール:ISE Project Navigator 14.7
シミュレーション:Isim
言語:VHDL
TD4の全体構成をブロック図で表したのが下図です。
今回はFPGAで作りますが、構成は「CPUの創りかた」に合わせていきます。
ちなみに矢印の色が青とオレンジの2色ありますが、色の違いに特に意味はなく、単に見やすくしただけです。
ROMの機能
TD4のROMは8bit×16で16byteあります。
「CPUの創りかた」では16個のスライドスイッチを使っています。
これを全て配線するのはかなり骨が折れますが、FPGAならコードを書くだけで実現できます。
TD4で用いるプログラムは各8bitです。
ROMは16byteなので全部で16ステップのプログラムを格納できます。
プログラムカウンタからプログラムが格納されているアドレスを指定する4bitの信号が送られ、対応するプログラム8bitを出力します。
8bitのプログラムのうち上位4bitは命令の機能である「オペレーションコード」であり、デコーダに出力されます。
下位4bitは命令に組み込まれたデータであり、「イミディエイトデータ」と呼ばれます。こちらはALUに出力されます。
ROMのコード
以下はVHDLで書いたROMのコードです。
TD4のプログラムは以下のコードに直接書き込みます。
"0000"から"1111"の16byteありますが、プログラムコードを"0000"から順番に書き込みます。
ちなみに以下に載せたコードは「CPUの創りかた」の295ページにあるサンプルプログラム1「LEDちかちか」のコードを書き込んでいます。
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity rom_16byte is Port ( ADDRESS : in STD_LOGIC_VECTOR(3 downto 0); ROM_DATA : out STD_LOGIC_VECTOR(3 downto 0); OP_CODE : out STD_LOGIC_VECTOR(3 downto 0)); end rom_16byte; architecture RTL of rom_16byte is signal data : STD_LOGIC_VECTOR(7 downto 0); begin ROM_DATA <= data(3 downto 0); OP_CODE <= data(7 downto 4); process (ADDRESS) begin case ADDRESS is when "0000" => data <= "10110011"; when "0001" => data <= "10110110"; when "0010" => data <= "10111100"; when "0011" => data <= "10111000"; when "0100" => data <= "10111000"; when "0101" => data <= "10111100"; when "0110" => data <= "10110110"; when "0111" => data <= "10110011"; when "1000" => data <= "10110001"; when "1001" => data <= "11110000"; when "1010" => data <= "00000000"; when "1011" => data <= "00000000"; when "1100" => data <= "00000000"; when "1101" => data <= "00000000"; when "1110" => data <= "00000000"; when "1111" => data <= "00000000"; when others => data <= "00000000"; end case; end process; end RTL;
ROMのシミュレーション
上で書いたROMのコードをシミュレーションするためのテストベンチのコードが以下です。
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; ENTITY rom_16byte_tb IS END rom_16byte_tb; ARCHITECTURE behavior OF rom_16byte_tb IS -- Component Declaration for the Unit Under Test (UUT) COMPONENT rom_16byte PORT ( ADDRESS : in STD_LOGIC_VECTOR(3 downto 0); ROM_DATA : out STD_LOGIC_VECTOR(3 downto 0); OP_CODE : out STD_LOGIC_VECTOR(3 downto 0) ); END COMPONENT; --Inputs signal ADDRESS : std_logic_vector(3 downto 0); --Outputs signal ROM_DATA : std_logic_vector(3 downto 0); signal OP_CODE : std_logic_vector(3 downto 0); BEGIN -- Instantiate the Unit Under Test (UUT) uut: rom_16byte PORT MAP ( ADDRESS => ADDRESS, ROM_DATA => ROM_DATA, OP_CODE => OP_CODE ); -- Clock process definitions process begin Address <= "0000"; wait for 100 ns; Address <= "0001"; wait for 100 ns; Address <= "0010"; wait for 100 ns; Address <= "0011"; wait for 100 ns; Address <= "0100"; wait for 100 ns; Address <= "0101"; wait for 100 ns; Address <= "0110"; wait for 100 ns; Address <= "0111"; wait for 100 ns; Address <= "1000"; wait for 100 ns; Address <= "1001"; wait for 100 ns; Address <= "1010"; wait for 100 ns; Address <= "1011"; wait for 100 ns; Address <= "1100"; wait for 100 ns; Address <= "1101"; wait for 100 ns; Address <= "1110"; wait for 100 ns; Address <= "1111"; wait for 100 ns; wait; end process; END;
アドレスを指定する入力に"0000"から"1111"を順番に入れています。
シミュレーション結果は以下のようになりました。
addressの4bitを順番に変えていくと、そのアドレスに応じた8bitのdataが出力されます。
まとめ
4bitCPU「TD4」のROMを作成しました。
プログラムカウンタからアドレスを表す4bitのコードが入力され、対応するアドレスに格納されている8bitのデータを出力します。
次の記事はこちらです。
www.hirobiro-life.com