例えばテスト用に次のような「プログラム」を保持するメモリを設計してみましょう。
| アドレス | 内容 | 命令 | 
| 0 | 0000 0001 | mov 1, r0 | 
| 1 | 0010 0010 | add r0, 2, r0 | 
| 2 | 0110 0010 | jmp 2 | 
※ヒント: 例えばaddr=0を与えられたら、data="0000 0001"を出力する回路、ということになる
以下、ひな形:
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;
(1日目はこのあたりまでを目安にしておくとよいでしょう)
またst=1でr0またはr1へ書き込まれる値を、st=0のときにresに決めておく、 というルールを決めておきます。
| op | 命令の内容 | res | resを代入する先 | 
| 0000 | mov imm, r0 | imm | r0 | 
| 0001 | mov imm, r1 | imm | r1 | 
| 0010 | add r0, imm, r0 | r0 + imm | r0 | 
| 0011 | |||
| ... | 
またプログラムカウンタ(PC)の更新は、jmp/jz命令では分岐先のアドレス (つまりimmの値)に、それ以外の命令では+1を行う、ことになります。 つまり、op(とjz命令ではZフラグの値)に応じて、 pcの値を更新すればよいことになります。 先ほどと同様に、pcの値の更新の内容を整理しておきましょう。
| op | 命令の内容 | 次のpcの値 | 
| 0000 | mov imm, r0 | pc + 1 | 
| 0001 | mov imm, r1 | pc + 1 | 
| ... | ... | ... | 
| 0110 | jmp imm | imm | 
| ... | ... | ... | 
以下、ひな形:
 
entity cpu is
  port( clk, rst: in std_logic;
        addr: out std_logic_vector(3 downto 0);
        data: in std_logic_vector(7 downto 0);
        r0, r1: out std_logic_vector(3 downto 0);
        z : out std_logic
        );
end cpu;
architecture Behavioral of cpu is
  signal op, imm, pc, res : std_logic_vector(3 downto 0);
  signal r0_reg, r1_reg : std_logic_vector(3 downto 0); -- r0/r1 variable
  signal z_reg, st : std_logic; -- z flag variable
begin
  op <= data(7 downto 4);  -- op from mem's data
  imm <= data(3 downto 0); -- imm from mem's data
  addr <= ... -- address for mem
  r0 <= r0_reg; -- r0 output
  r1 <= r1_reg; -- r1 output
  z <= z_reg;   -- z output
  process (rst, clk) begin
    if (rst = '1') then
      -- reset variables
      pc <= "0000"; z_reg <= '0'; st <= '0'; r0_reg <= "0000"; r1_reg <= "0000";
    elsif (clk'event and clk = '1') then
      if (st = '0') then
        -- state 0 : fetch, register updadate preparation
        -- setting res
        case op is
          when "0000" => res <= imm;
          ...
          when others => null;
        end case;
        -- st update
        st <= '1';
      else
        -- state 1 : register & PC & Z update
        -- PC update
        if (op = "0110") then pc ... -- jmp
        elsif (op = "0111" and ...) then pc <= imm; -- jz
        else pc <= pc + 1;
        end if;
        -- register update
        case op is
          when "0000" => r0_reg <= res;
          when "0001" => r1_reg <= res;
          ...
          when others => null;                         
        end case;
        -- Z flag update
        z_reg <= '0';
        case op is
          when "0000" => if (res = "0000") then z_reg <= '1'; end if;
          ...
          when others => null;                         
        end case;
        -- st update
        st <= '0';
      end if;
    end if;
  end process;
end Behavioral;
 
またこのほか、ピン定義ファイルとしてsub3_cpu.ucfをプロジェクトに追加しておきます。
以下、cpu_topのひな型(ほぼこの通り使えばOKのはず)。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity cpu_top is
  port (
       CLK50M : in  STD_LOGIC;
       SA : out STD_LOGIC_VECTOR(3 downto 0);
       SG : out STD_LOGIC_VECTOR(7 downto 0);
       SW : in STD_LOGIC_VECTOR(5 downto 0);
       LED : out std_logic_vector(1 downto 0)
    );
end cpu_top;
architecture Behavioral of cpu_top is
  component sw_clk
    port (
      ia, ib: in std_logic;
      clk : out std_logic
      );
  end component;
  component cpu
    port( clk, rst: in std_logic;
        addr: out std_logic_vector(3 downto 0);
        data: in std_logic_vector(7 downto 0);
        r0, r1: out std_logic_vector(3 downto 0);
		  z : out std_logic
        );
  end component;
  component seg7
    Port ( clk : in  STD_LOGIC;
           rst : in  STD_LOGIC;
           d0 : in  STD_LOGIC_VECTOR (3 downto 0);
           d1 : in  STD_LOGIC_VECTOR (3 downto 0);
           d2 : in  STD_LOGIC_VECTOR (3 downto 0);
           d3 : in  STD_LOGIC_VECTOR (3 downto 0);
           sa : out  STD_LOGIC_VECTOR (3 downto 0);
           sg : out  STD_LOGIC_VECTOR (7 downto 0));
  end component;
  component mem is
    port( addr: in std_logic_vector(3 downto 0);
          data: out std_logic_vector(7 downto 0));
  end component;
  signal ia, ib, clk_cpu, rst, z : std_logic;
  signal addr, r0, r1 : std_logic_vector(3 downto 0);
  signal data : std_logic_vector(7 downto 0);
begin
  ia <= SW(4); ib <= SW(5); -- sw_clk's input
  rst <= SW(2);
  LED(0) <= clk_cpu;
  LED(1) <= z;
  icpu : cpu port map(clk_cpu, rst, addr, data, r0, r1);
  iseg7 : seg7 port map(CLK50M, rst, r0, r1, addr, data(7 downto 4), SA, SG);
  isw_clk : sw_clk port map(ia, ib, clk_cpu);
  imem : mem port map(addr, data);
end Behavioral;
  
(2日目はこのあたりまでを目安にしておくとよいでしょう) (補足) 新規ファイルをつくるとき、必要な冒頭の定義(includeのようなもの)が入らない場合があるようです。冒頭のuse文の付近に次の2行がない場合は、追記しておいてください。
use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL;
プログラム1: レジスタへの値の代入
addr data 0 00000001 : mov 1, r0 1 00010010 : mov 2, r1 2 01100010 : jmp 2
プログラム2: 乗算(3×4=12)
addr data 0 00000000 : mov 0, r0 1 00010100 : mov 4, r1 2 00100011 : add r0, 3, r0 3 01011111 : add r1, 15, r1 4 01110110 : jz 6 5 01100010 : jmp 2 6 01100110 : jmp 6この他にも、例えば除算の実行などのいろいろなプログラムを記述して 実行させてみましょう。