-------------------------------------------------------------------------------
-- Title      : cpu 2bit top-level
-- Project    : cpu 2bit
-------------------------------------------------------------------------------
-- File       : cpu_2bit_top_level.vhd
-- Author     : Sven Lasch
-- Company    : TU-Chemnitz
-- Created    : 2001-11-08
-- Last update: 2002-04-16
-- Platform   : ANY
-------------------------------------------------------------------------------
-- Description: 2-Bit CPU mit erweiterter Adressierung von 16 Worten a 2 Bit   
-------------------------------------------------------------------------------

-------------------------------------------------------------------------------
-- Entity ip_counter 4-bit
-------------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_unsigned.ALL;

ENTITY ip_counter IS

  PORT (
    clk    : IN  STD_LOGIC;
    reset  : IN  STD_LOGIC;
    step   : IN  STD_LOGIC;
    ip_ld  : IN  STD_LOGIC;
    ip_cnt : IN  STD_LOGIC;
    ip_in  : IN  STD_LOGIC_VECTOR(3 DOWNTO 0);
    ip_out : OUT STD_LOGIC_VECTOR(3 DOWNTO 0));

END ip_counter;

ARCHITECTURE A_behav OF ip_counter IS
  SIGNAL ip : STD_LOGIC_VECTOR(3 DOWNTO 0);

BEGIN
  P_ip : PROCESS (clk, reset)
  BEGIN
    IF reset = '0' THEN
      ip <= (OTHERS => '0');
    ELSIF clk'EVENT AND clk = '1' THEN
      IF step = '1' THEN
        IF ip_ld = '1' THEN
          ip <= ip_in;
        ELSIF ip_cnt = '1' THEN
          ip <= ip + 1;
        END IF;
      END IF;
    END IF;
  END PROCESS P_ip;
  ip_out <= ip;

END A_behav;

-------------------------------------------------------------------------------
-- Entity register_2bit
-------------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_unsigned.ALL;

ENTITY register_2bit IS

  PORT (
    clk     : IN  STD_LOGIC;
    reset   : IN  STD_LOGIC;
    step    : IN  STD_LOGIC;
    reg_en  : IN  STD_LOGIC;
    reg_in  : IN  STD_LOGIC_VECTOR(1 DOWNTO 0);
    reg_out : OUT STD_LOGIC_VECTOR(1 DOWNTO 0));

END register_2bit;

ARCHITECTURE A_behav OF register_2bit IS
  SIGNAL reg : STD_LOGIC_VECTOR(1 DOWNTO 0);

BEGIN
  P_reg : PROCESS (clk, reset)
  BEGIN
    IF reset = '0' THEN
      reg <= (OTHERS => '0');
    ELSIF clk'EVENT AND clk = '1' THEN
      IF step = '1' THEN
        IF reg_en = '1' THEN
          reg <= reg_in;
        END IF;
      END IF;
    END IF;
  END PROCESS P_reg;
  reg_out <= reg;

END A_behav;

-------------------------------------------------------------------------------
-- Entity mux2_bit
-------------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_unsigned.ALL;

ENTITY mux_2bit IS

  PORT (
    sel : IN  STD_LOGIC;
    a   : IN  STD_LOGIC_VECTOR(1 DOWNTO 0);
    b   : IN  STD_LOGIC_VECTOR(1 DOWNTO 0);
    y   : OUT STD_LOGIC_VECTOR(1 DOWNTO 0));

END mux_2bit;

ARCHITECTURE A_behav OF mux_2bit IS

BEGIN

  y <= a WHEN sel = '0' ELSE b;

END A_behav;

-------------------------------------------------------------------------------
-- Entity mux4_bit
-------------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_unsigned.ALL;

ENTITY mux_4bit IS

  PORT (
    sel : IN  STD_LOGIC;
    a   : IN  STD_LOGIC_VECTOR(3 DOWNTO 0);
    b   : IN  STD_LOGIC_VECTOR(3 DOWNTO 0);
    y   : OUT STD_LOGIC_VECTOR(3 DOWNTO 0));

END mux_4bit;

ARCHITECTURE A_behav OF mux_4bit IS

BEGIN

  y <= a WHEN sel = '0' ELSE b;

END A_behav;

-------------------------------------------------------------------------------
-- Entity alu
-------------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_unsigned.ALL;

ENTITY alu IS

  PORT (
    a : IN  STD_LOGIC_VECTOR(3 DOWNTO 0);
    b : IN  STD_LOGIC_VECTOR(3 DOWNTO 0);
    y : OUT STD_LOGIC_VECTOR(3 DOWNTO 0));

END alu;

ARCHITECTURE A_behav OF alu IS

BEGIN

  y <= a + b;
  
END A_behav;


-------------------------------------------------------------------------------
-- Entity steuerwerk
-------------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_arith.ALL;
USE ieee.std_logic_unsigned.ALL;

ENTITY steuerwerk IS

  PORT (
    clk    : IN  STD_LOGIC;
    reset  : IN  STD_LOGIC;
    step   : IN  STD_LOGIC;
    br     : IN  STD_LOGIC_VECTOR(1 DOWNTO 0);
    state  : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
    br_en  : OUT STD_LOGIC;
    arl_en : OUT STD_LOGIC;
    arh_en : OUT STD_LOGIC;
    aa_en  : OUT STD_LOGIC;
    ip_ld  : OUT STD_LOGIC;
    ip_cnt : OUT STD_LOGIC;
    rd     : OUT STD_LOGIC;
    wr     : OUT STD_LOGIC;
    m1_s   : OUT STD_LOGIC;
    m2_s   : OUT STD_LOGIC;
    m3_s   : OUT STD_LOGIC;
    m4_s   : OUT STD_LOGIC);

END steuerwerk;

ARCHITECTURE A_behav OF steuerwerk IS
  SIGNAL f       : STD_LOGIC_VECTOR(4 DOWNTO 1);
  SIGNAL modres  : STD_LOGIC;
  SIGNAL ip_cnt1 : STD_LOGIC;
  SIGNAL ip_cnt2 : STD_LOGIC;
  
BEGIN
  P_counter : PROCESS (clk, reset)
  BEGIN
    IF reset = '0' THEN
      f <= "0001";
    ELSIF clk'EVENT AND clk = '1' THEN
      IF step = '1' THEN
        IF modres = '1' THEN
          f <= "0001";
        ELSE
          f <= f(3 DOWNTO 1) & f(4);
        END IF;
      END IF;
    END IF;
  END PROCESS P_counter;

  state <= f;

  br_en   <= f(1);
  arl_en  <= ((f(2) AND NOT br(1) AND br(0)) OR (f(2) AND br(1) AND NOT br(0)) OR (f(2) AND NOT br(1) AND NOT br(0)));
  arh_en  <= ((f(3) AND NOT br(1) AND br(0)) OR (f(3) AND br(1) AND NOT br(0)) OR (f(3) AND NOT br(1) AND NOT br(0)));
  aa_en   <= ((f(2) AND br(1) AND br(0)) OR (f(4) AND NOT br(1) AND br(0)));
  ip_ld   <= (f(4) AND NOT br(1) AND NOT br(0));
  ip_cnt1 <= (f(2) AND NOT br(1) AND br(0)) OR (f(2) AND br(1) AND NOT br(0)) OR (f(2) AND NOT br(1) AND NOT br(0));
  ip_cnt2 <= (f(3) AND NOT br(1) AND br(0)) OR (f(3) AND br(1) AND NOT br(0)) OR (f(3) AND NOT br(1) AND NOT br(0));
  ip_cnt  <= f(1) OR ip_cnt1 OR ip_cnt2;

  rd     <= (f(1) OR f(2) OR f(3) OR (f(4) AND NOT br(1) AND br(0)));
  wr     <= (f(4) AND br(1) AND NOT br(0)) AND NOT clk AND step;
  modres <= (f(2) AND br(1) AND br(0));
  m1_s   <= f(4);
  m2_s   <= f(4);
  m3_s   <= f(4);
  m4_s   <= f(4);
  
END A_behav;

-------------------------------------------------------------------------------
-- CPU-2 Top Level
-------------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_arith.ALL;
USE ieee.std_logic_unsigned.ALL;

ENTITY cpu_2bit IS

  PORT (
    clk      : IN  STD_LOGIC;
    reset    : IN  STD_LOGIC;
    step     : IN  STD_LOGIC;
    rd       : OUT STD_LOGIC;
    wr       : OUT STD_LOGIC;
    addr     : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
    state    : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
    ar_out   : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
    br_out   : OUT STD_LOGIC_VECTOR(1 DOWNTO 0);
    ip_out   : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
    aa_out   : OUT STD_LOGIC_VECTOR(1 DOWNTO 0);
    bb_out   : OUT STD_LOGIC_VECTOR(1 DOWNTO 0);
    data_in  : IN  STD_LOGIC_VECTOR(1 DOWNTO 0);
    data_out : OUT STD_LOGIC_VECTOR(1 DOWNTO 0));

END cpu_2bit;

ARCHITECTURE A_behav OF cpu_2bit IS

  SIGNAL ar      : STD_LOGIC_VECTOR(3 DOWNTO 0);
  SIGNAL br      : STD_LOGIC_VECTOR(1 DOWNTO 0);
  SIGNAL ip      : STD_LOGIC_VECTOR(3 DOWNTO 0);
  SIGNAL aa_in   : STD_LOGIC_VECTOR(1 DOWNTO 0);
  SIGNAL aa      : STD_LOGIC_VECTOR(1 DOWNTO 0);
  SIGNAL bb      : STD_LOGIC_VECTOR(1 DOWNTO 0);
  SIGNAL alu_in1 : STD_LOGIC_VECTOR(3 DOWNTO 0);
  SIGNAL alu_in2 : STD_LOGIC_VECTOR(3 DOWNTO 0);
  SIGNAL alu_out : STD_LOGIC_VECTOR(3 DOWNTO 0);

  SIGNAL m3_ain : STD_LOGIC_VECTOR(3 DOWNTO 0);
  SIGNAL m4_ain : STD_LOGIC_VECTOR(3 DOWNTO 0);

  SIGNAL ip_cnt : STD_LOGIC;
  SIGNAL ip_ld  : STD_LOGIC;
  SIGNAL arl_en : STD_LOGIC;
  SIGNAL arh_en : STD_LOGIC;
  SIGNAL br_en  : STD_LOGIC;
  SIGNAL aa_en  : STD_LOGIC;
  SIGNAL rd_en  : STD_LOGIC;
  SIGNAL wr_en  : STD_LOGIC;
  SIGNAL m1_s   : STD_LOGIC;
  SIGNAL m2_s   : STD_LOGIC;
  SIGNAL m3_s   : STD_LOGIC;
  SIGNAL m4_s   : STD_LOGIC;

  COMPONENT ip_counter
    PORT (
      clk    : IN  STD_LOGIC;
      reset  : IN  STD_LOGIC;
      step   : IN  STD_LOGIC;
      ip_ld  : IN  STD_LOGIC;
      ip_cnt : IN  STD_LOGIC;
      ip_in  : IN  STD_LOGIC_VECTOR(3 DOWNTO 0);
      ip_out : OUT STD_LOGIC_VECTOR(3 DOWNTO 0));
  END COMPONENT;

  COMPONENT register_2bit
    PORT (
      clk     : IN  STD_LOGIC;
      reset   : IN  STD_LOGIC;
      step    : IN  STD_LOGIC;
      reg_en  : IN  STD_LOGIC;
      reg_in  : IN  STD_LOGIC_VECTOR(1 DOWNTO 0);
      reg_out : OUT STD_LOGIC_VECTOR(1 DOWNTO 0));
  END COMPONENT;

  COMPONENT mux_2bit
    PORT (
      sel : IN  STD_LOGIC;
      a   : IN  STD_LOGIC_VECTOR(1 DOWNTO 0);
      b   : IN  STD_LOGIC_VECTOR(1 DOWNTO 0);
      y   : OUT STD_LOGIC_VECTOR(1 DOWNTO 0));
  END COMPONENT;

  COMPONENT mux_4bit
    PORT (
      sel : IN  STD_LOGIC;
      a   : IN  STD_LOGIC_VECTOR(3 DOWNTO 0);
      b   : IN  STD_LOGIC_VECTOR(3 DOWNTO 0);
      y   : OUT STD_LOGIC_VECTOR(3 DOWNTO 0));
  END COMPONENT;

  COMPONENT alu
    PORT (
      a : IN  STD_LOGIC_VECTOR(3 DOWNTO 0);
      b : IN  STD_LOGIC_VECTOR(3 DOWNTO 0);
      y : OUT STD_LOGIC_VECTOR(3 DOWNTO 0));
  END COMPONENT;

  COMPONENT steuerwerk
    PORT (
      clk    : IN  STD_LOGIC;
      reset  : IN  STD_LOGIC;
      step   : IN  STD_LOGIC;
      br     : IN  STD_LOGIC_VECTOR(1 DOWNTO 0);
      state  : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
      br_en  : OUT STD_LOGIC;
      arl_en : OUT STD_LOGIC;
      arh_en : OUT STD_LOGIC;
      aa_en  : OUT STD_LOGIC;
      ip_ld  : OUT STD_LOGIC;
      ip_cnt : OUT STD_LOGIC;
      rd     : OUT STD_LOGIC;
      wr     : OUT STD_LOGIC;
      m1_s   : OUT STD_LOGIC;
      m2_s   : OUT STD_LOGIC;
      m3_s   : OUT STD_LOGIC;
      m4_s   : OUT STD_LOGIC);
  END COMPONENT;

BEGIN

  ar_out   <= ar;
  br_out   <= br;
  ip_out   <= ip;
  aa_out   <= aa;
  bb_out   <= bb;
  data_out <= aa;

  -- IP: IP-Counter
  --
  IP1 : ip_counter
    PORT MAP (
      clk    => clk,
      reset  => reset,
      step   => step,
      ip_ld  => ip_ld,
      ip_cnt => ip_cnt,
      ip_in  => alu_out,
      ip_out => ip);

  -- BR: Befehlsregister
  --
  BR1 : register_2bit
    PORT MAP (
      clk     => clk,
      reset   => reset,
      step    => step,
      reg_en  => br_en,
      reg_in  => data_in,
      reg_out => br);

  -- AR: Adressregister 2x2bit 
  --
  ARL : register_2bit
    PORT MAP (
      clk     => clk,
      reset   => reset,
      step    => step,
      reg_en  => arl_en,
      reg_in  => data_in,
      reg_out => ar(1 DOWNTO 0));

  ARH : register_2bit
    PORT MAP (
      clk     => clk,
      reset   => reset,
      step    => step,
      reg_en  => arh_en,
      reg_in  => data_in,
      reg_out => ar(3 DOWNTO 2));

  -- AA: Akkumulator
  --
  AA1 : register_2bit
    PORT MAP (
      clk     => clk,
      reset   => reset,
      step    => step,
      reg_en  => aa_en,
      reg_in  => aa_in,
      reg_out => aa);

  -- M1: Multiplexer IP,AR
  --
  M1 : mux_4bit
    PORT MAP (
      sel => m1_s,
      a   => ip,
      b   => ar,
      y   => addr);

  -- M2: Multiplexer ALU, Data_in
  --
  M2 : mux_2bit
    PORT MAP (
      sel => m2_s,
      a   => alu_out(1 DOWNTO 0),
      b   => data_in,
      y   => aa_in);

  -- M3: Multiplexer AA, AR
  --
  m3_ain <= ("00" & aa);

  M3 : mux_4bit
    PORT MAP (
      sel => m3_s,
      a   => m3_ain,
      b   => ar,
      y   => alu_in1);

  bb <= "01";

  -- M4: Multiplexer BB, IP
  --
  m4_ain <= ("00" & bb);

  M4 : mux_4bit
    PORT MAP (
      sel => m4_s,
      a   => m4_ain,
      b   => ip,
      y   => alu_in2);

  ALU1 : alu
    PORT MAP (
      a => alu_in1,
      b => alu_in2,
      y => alu_out);

  SW_1 : steuerwerk
    PORT MAP (
      clk    => clk,
      reset  => reset,
      step   => step,
      br     => br,
      state  => state,
      br_en  => br_en,
      arl_en => arl_en,
      arh_en => arh_en,
      aa_en  => aa_en,
      ip_ld  => ip_ld,
      ip_cnt => ip_cnt,
      rd     => rd,
      wr     => wr,
      m1_s   => m1_s,
      m2_s   => m2_s,
      m3_s   => m3_s,
      m4_s   => m4_s);


END A_behav;
-------------------------------------------------------------------------------
-- dual port memory
-------------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_arith.ALL;
USE ieee.std_logic_unsigned.ALL;

ENTITY memory IS
  
  PORT (
    addr         : IN  STD_LOGIC_VECTOR(3 DOWNTO 0);
    data_in      : IN  STD_LOGIC_VECTOR(1 DOWNTO 0);
    data_out     : OUT STD_LOGIC_VECTOR(1 DOWNTO 0);
    data_display : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
    preset       : IN  STD_LOGIC;
    rd           : IN  STD_LOGIC;
    wr           : IN  STD_LOGIC);
END memory;

ARCHITECTURE A_behav OF memory IS
  TYPE mem_type IS ARRAY (0 TO 15) OF STD_LOGIC_VECTOR(1 DOWNTO 0);

  SIGNAL memory_array : mem_type;
  
BEGIN
  P_memory : PROCESS
  BEGIN
    IF preset = '0' THEN

      -- Speichervoreinstellung wird hier vorgenommen. Durch Drücken
      -- des Tasters FLEX_PB1 werden die folgenden Werte in den
      -- Hauptspeicher der CPU geladen.

      memory_array(0)  <= "01";         -- READ 1010 ($10)
      memory_array(1)  <= "10";			--
      memory_array(2)  <= "10";			--
      memory_array(3)  <= "11";         -- ADD
      memory_array(4)  <= "10";         -- WRITE 1010 ($10)
      memory_array(5)  <= "10";         -- 
      memory_array(6)  <= "10";         -- 
      memory_array(7)  <= "00";         -- JUMP 0110 (zu $0)
      memory_array(8)  <= "10";         -- 
      memory_array(9)  <= "01";         -- 
      memory_array(10) <= "10";         -- $10
      memory_array(11) <= "00";			--
      memory_array(12) <= "00";			--
      memory_array(13) <= "00";         -- 
      memory_array(14) <= "00";			--
      memory_array(15) <= "00";			--

      --
      ---------------------------------------------------------------------------

    ELSIF wr = '1' THEN
      memory_array(conv_integer(addr)) <= data_in;
    END IF;
  END PROCESS P_memory;

  data_out <= memory_array(conv_integer(addr));

  data_display(1 DOWNTO 0) <= memory_array(0);
  data_display(3 DOWNTO 2) <= memory_array(1);
  data_display(5 DOWNTO 4) <= memory_array(2);
  data_display(7 DOWNTO 6) <= memory_array(3);
  
END A_behav;

-------------------------------------------------------------------------------
-- single step state maschine
-------------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_arith.ALL;
USE ieee.std_logic_unsigned.ALL;

ENTITY single_step IS
  PORT (
    clk    : IN  STD_LOGIC;
    reset  : IN  STD_LOGIC;
    button : IN  STD_LOGIC;
    step   : OUT STD_LOGIC);

END single_step;

ARCHITECTURE A_behav OF single_step IS

  CONSTANT DELAY : NATURAL RANGE 0 TO 131071 := 131071;

  TYPE   states IS (high, low, step_out, cnt_reset);
  SIGNAL current_state : states;
  SIGNAL next_state    : states;
  SIGNAL counter       : INTEGER RANGE 0 TO 131071;
  SIGNAL timeout       : STD_LOGIC;
  SIGNAL cnt_clear     : STD_LOGIC;
  SIGNAL cnt_count     : STD_LOGIC;
  
BEGIN
  P_step_state : PROCESS (clk, reset)
  BEGIN
    IF reset = '0' THEN
      current_state <= high;
    ELSIF clk'EVENT AND clk = '1' THEN
      current_state <= next_state;
    END IF;
  END PROCESS P_step_state;

  P_step_trans_out : PROCESS (button, current_state, timeout)
  BEGIN
    CASE current_state IS
      WHEN high =>
        IF timeout = '1' AND button = '0' THEN
          next_state <= cnt_reset;
        ELSE
          next_state <= high;
        END IF;
      WHEN low =>
        IF timeout = '1' AND button = '1' THEN
          next_state <= step_out;
        ELSE
          next_state <= low;
        END IF;
      WHEN step_out =>
        next_state <= high;
      WHEN cnt_reset =>
        next_state <= low;
      WHEN OTHERS => NULL;
    END CASE;
  END PROCESS P_step_trans_out;

  step      <= '1' WHEN current_state = step_out                                  ELSE '0';
  cnt_clear <= '1' WHEN (current_state = step_out) OR (current_state = cnt_reset) ELSE '0';
  cnt_count <= '1' WHEN (current_state = high) OR (current_state = low)           ELSE '0';

  P_timeout : PROCESS (clk, reset)
  BEGIN
    IF reset = '0' THEN
      counter <= 0;
    ELSIF clk'EVENT AND clk = '1' THEN
      IF cnt_clear = '1' THEN
        counter <= 0;
      ELSIF cnt_count = '1' THEN
        IF counter < delay THEN
          counter <= counter + 1;
        END IF;
      END IF;
    END IF;
  END PROCESS P_timeout;

  timeout <= '1' WHEN counter = DELAY ELSE '0';

END A_behav;

-------------------------------------------------------------------------------
-- Sieben-Segment-Decoder
-------------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_arith.ALL;
USE ieee.std_logic_unsigned.ALL;

ENTITY ssd IS
  PORT (
    data_in  : IN  STD_LOGIC_VECTOR(3 DOWNTO 0);
    data_out : OUT STD_LOGIC_VECTOR(6 DOWNTO 0));
END ssd;

ARCHITECTURE A_behav OF ssd IS

BEGIN
  WITH data_in SELECT
    data_out <=
    "0000001" WHEN "0000",
    "1001111" WHEN "0001",
    "0010010" WHEN "0010",
    "0000110" WHEN "0011",
    "1001100" WHEN "0100",
    "0100100" WHEN "0101",
    "0100000" WHEN "0110",
    "0001111" WHEN "0111",
    "0000000" WHEN "1000",
    "0000100" WHEN "1001",
    "0001000" WHEN "1010",
    "1100000" WHEN "1011",
    "0110001" WHEN "1100",
    "1000010" WHEN "1101",
    "0110000" WHEN "1110",
    "0111000" WHEN OTHERS;
END A_behav;

-------------------------------------------------------------------------------
-- top_level_entity
-------------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_arith.ALL;
USE ieee.std_logic_unsigned.ALL;

ENTITY cpu_2bit_top_level IS
  
  PORT (
    clk            : IN  STD_LOGIC;
    flex_pb1       : IN  STD_LOGIC;
    flex_pb2       : IN  STD_LOGIC;
    flex_d1        : OUT STD_LOGIC;
    flex_d2        : OUT STD_LOGIC;
    flex_d3        : OUT STD_LOGIC;
    flex_d4        : OUT STD_LOGIC;
    flex_d5        : OUT STD_LOGIC;
    flex_d6        : OUT STD_LOGIC;
    flex_d7        : OUT STD_LOGIC;
    flex_d8        : OUT STD_LOGIC;
    flex_d9        : OUT STD_LOGIC;
    flex_d10       : OUT STD_LOGIC;
    flex_d11       : OUT STD_LOGIC;
    flex_d12       : OUT STD_LOGIC;
    flex_d13       : OUT STD_LOGIC;
    flex_d14       : OUT STD_LOGIC;
    flex_d15       : OUT STD_LOGIC;
    flex_d16       : OUT STD_LOGIC;
    flex_digit1_a  : OUT STD_LOGIC;
    flex_digit1_b  : OUT STD_LOGIC;
    flex_digit1_c  : OUT STD_LOGIC;
    flex_digit1_d  : OUT STD_LOGIC;
    flex_digit1_e  : OUT STD_LOGIC;
    flex_digit1_f  : OUT STD_LOGIC;
    flex_digit1_g  : OUT STD_LOGIC;
    flex_digit1_dp : OUT STD_LOGIC;
    flex_digit2_a  : OUT STD_LOGIC;
    flex_digit2_b  : OUT STD_LOGIC;
    flex_digit2_c  : OUT STD_LOGIC;
    flex_digit2_d  : OUT STD_LOGIC;
    flex_digit2_e  : OUT STD_LOGIC;
    flex_digit2_f  : OUT STD_LOGIC;
    flex_digit2_g  : OUT STD_LOGIC;
    flex_digit2_dp : OUT STD_LOGIC);

END cpu_2bit_top_level;

ARCHITECTURE A_structure OF cpu_2bit_top_level IS

  SIGNAL preset_data  : STD_LOGIC_VECTOR(7 DOWNTO 0);
  SIGNAL addr         : STD_LOGIC_VECTOR(3 DOWNTO 0);
  SIGNAL data_in      : STD_LOGIC_VECTOR(1 DOWNTO 0);
  SIGNAL data_out     : STD_LOGIC_VECTOR(1 DOWNTO 0);
  SIGNAL rd           : STD_LOGIC;
  SIGNAL wr           : STD_LOGIC;
  SIGNAL step         : STD_LOGIC;
  SIGNAL state        : STD_LOGIC_VECTOR(3 DOWNTO 0);
  SIGNAL ar_out       : STD_LOGIC_VECTOR(3 DOWNTO 0);
  SIGNAL br_out       : STD_LOGIC_VECTOR(1 DOWNTO 0);
  SIGNAL ip_out       : STD_LOGIC_VECTOR(3 DOWNTO 0);
  SIGNAL aa_out       : STD_LOGIC_VECTOR(1 DOWNTO 0);
  SIGNAL bb_out       : STD_LOGIC_VECTOR(1 DOWNTO 0);
  SIGNAL data_display : STD_LOGIC_VECTOR(7 DOWNTO 0);
  SIGNAL ar_digit     : STD_LOGIC_VECTOR(6 DOWNTO 0);
  SIGNAL ip_digit     : STD_LOGIC_VECTOR(6 DOWNTO 0);

  COMPONENT single_step
    PORT (
      clk    : IN  STD_LOGIC;
      reset  : IN  STD_LOGIC;
      button : IN  STD_LOGIC;
      step   : OUT STD_LOGIC);
  END COMPONENT;

  COMPONENT cpu_2bit
    PORT (
      clk      : IN  STD_LOGIC;
      reset    : IN  STD_LOGIC;
      step     : IN  STD_LOGIC;
      rd       : OUT STD_LOGIC;
      wr       : OUT STD_LOGIC;
      addr     : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
      state    : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
      ar_out   : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
      br_out   : OUT STD_LOGIC_VECTOR(1 DOWNTO 0);
      ip_out   : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
      aa_out   : OUT STD_LOGIC_VECTOR(1 DOWNTO 0);
      bb_out   : OUT STD_LOGIC_VECTOR(1 DOWNTO 0);
      data_in  : IN  STD_LOGIC_VECTOR(1 DOWNTO 0);
      data_out : OUT STD_LOGIC_VECTOR(1 DOWNTO 0));
  END COMPONENT;

  COMPONENT memory
    PORT (
      addr         : IN  STD_LOGIC_VECTOR(3 DOWNTO 0);
      data_in      : IN  STD_LOGIC_VECTOR(1 DOWNTO 0);
      data_out     : OUT STD_LOGIC_VECTOR(1 DOWNTO 0);
      data_display : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
      preset       : IN  STD_LOGIC;
      rd           : IN  STD_LOGIC;
      wr           : IN  STD_LOGIC);
  END COMPONENT;

  COMPONENT ssd
    PORT (
      data_in  : IN  STD_LOGIC_VECTOR(3 DOWNTO 0);
      data_out : OUT STD_LOGIC_VECTOR(6 DOWNTO 0));
  END COMPONENT;
  
BEGIN

  I_single_step : single_step
    PORT MAP (
      clk    => clk,
      reset  => flex_pb1,
      button => flex_pb2,
      step   => step);

  cpu_2bit_1 : cpu_2bit
    PORT MAP (
      clk      => clk,
      reset    => flex_pb1,
      step     => step,
      rd       => rd,
      wr       => wr,
      addr     => addr,
      state    => state,
      ar_out   => ar_out,
      br_out   => br_out,
      ip_out   => ip_out,
      aa_out   => aa_out,
      bb_out   => bb_out,
      data_in  => data_in,
      data_out => data_out);

  flex_d1 <= NOT (state(2) OR state(3));
  flex_d5 <= NOT (state(1) OR state(3));
  flex_d2 <= NOT br_out(1);
  flex_d6 <= NOT br_out(0);
  flex_d3 <= NOT aa_out(1);
  flex_d7 <= NOT aa_out(0);
  flex_d4 <= NOT bb_out(1);
  flex_d8 <= NOT bb_out(0);

  flex_digit1_dp <= NOT rd;
  flex_digit2_dp <= NOT wr;

  -----------------------------------------------------------------------------

  I_memory_1 : memory
    PORT MAP (
      addr         => addr,
      data_in      => data_out,
      data_out     => data_in,
      data_display => data_display,
      preset       => flex_pb1,
      rd           => rd,
      wr           => wr);

  flex_d9  <= NOT data_display(1);
  flex_d13 <= NOT data_display(0);
  flex_d10 <= NOT data_display(3);
  flex_d14 <= NOT data_display(2);
  flex_d11 <= NOT data_display(5);
  flex_d15 <= NOT data_display(4);
  flex_d12 <= NOT data_display(7);
  flex_d16 <= NOT data_display(6);

  -----------------------------------------------------------------------------
  -- cpu ar-display at digit 1
  -----------------------------------------------------------------------------

  I_ar_display : ssd
    PORT MAP (
      data_in  => ar_out,
      data_out => ar_digit);

  flex_digit1_a <= ar_digit(6);
  flex_digit1_b <= ar_digit(5);
  flex_digit1_c <= ar_digit(4);
  flex_digit1_d <= ar_digit(3);
  flex_digit1_e <= ar_digit(2);
  flex_digit1_f <= ar_digit(1);
  flex_digit1_g <= ar_digit(0);

  -----------------------------------------------------------------------------
  -- cpu ip display at digit 2
  -----------------------------------------------------------------------------
  I_ip_display : ssd
    PORT MAP (
      data_in  => ip_out,
      data_out => ip_digit);

  flex_digit2_a <= ip_digit(6);
  flex_digit2_b <= ip_digit(5);
  flex_digit2_c <= ip_digit(4);
  flex_digit2_d <= ip_digit(3);
  flex_digit2_e <= ip_digit(2);
  flex_digit2_f <= ip_digit(1);
  flex_digit2_g <= ip_digit(0);

END A_structure;