--Datapath and Controller combined structually
--Created by:
--Eric Frohnhoefer
--Ron Feliciano

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
use IEEE.std_logic_arith.all;

entity LC2_all is
   port(rst: in  STD_LOGIC;
      clk: in  STD_LOGIC);
end LC2_all;

architecture str of LC2_all is

component LC2_ALU
   port( A: in std_logic_vector (15 downto 0);
      B: in std_logic_vector (15 downto 0);
      S: in std_logic_vector (1 downto 0);
      O: out std_logic_vector (15 downto 0));
end component;

component adder
   port(A : in std_logic_vector (15 downto 0);
      B : in std_logic_vector (15 downto 0);
      O : out std_logic_vector (15 downto 0));
end component;

component cat
   port(A : in std_logic_vector (8 downto 0);
      B : in std_logic_vector (6 downto 0);
      O : out std_logic_vector (15 downto 0));	
end component;

component increment
   port(data: in std_logic_vector (15 downto 0); 
      O: out std_logic_vector (15 downto 0));
end component;

component mux2
   port(a: in std_logic_vector(15 downto 0); 
      b: in std_logic_vector(15 downto 0);
      s: in std_logic;
      mux2output : out std_logic_vector(15 downto 0));
end component;

component mux4
   port(c : in std_logic_vector(15 downto 0);
      d : in std_logic_vector(15 downto 0);
      e : in std_logic_vector(15 downto 0);
      f : in std_logic_vector(15 downto 0);
      s : in std_logic_vector(1 downto 0);
      muxoutput	: out std_logic_vector(15 downto 0));
end component;

component NZP_logic
   port(data: in std_logic_vector (15 downto 0); 
      O: out std_logic_vector (2 downto 0));
end component;

component reg
   port(clk : in std_logic; 
      load : in std_logic;
      data : in std_logic_vector (15 downto 0); 
      O : out std_logic_vector (15 downto 0);
      clear : in std_logic);
end component;

component NZP_reg
   port(clk : in std_logic; 
      load : in std_logic;
      data : in std_logic_vector (2 downto 0); 
      O : out std_logic_vector (2 downto 0);
      clear : in std_logic);
end component;

component register_file
   port(clk : in std_logic;
      DR_enable : in std_logic;
      DR_address : in std_logic_vector (2 downto 0);
      SR1_address: in std_logic_vector(2 downto 0);
      SR2_address: in std_logic_vector(2 downto 0);	  
      data_in: in std_logic_vector (15 downto 0);
      SR1_out: out std_logic_vector (15 downto 0);
      SR2_out: out std_logic_vector (15 downto 0));
end component;

component tri_state
   port(data_in: in STD_LOGIC_VECTOR (15 downto 0);
      s: in STD_LOGIC;
      data_out: out STD_LOGIC_VECTOR (15 downto 0));
end component;

component sext
   port(A : in std_logic_vector (4 downto 0);
      O : out std_logic_vector (15 downto 0));
end component;

component zext10
   port(A : in std_logic_vector (5 downto 0);
      O : out std_logic_vector (15 downto 0));
end component;

component zext8
   port(A : in std_logic_vector (7 downto 0);
      O : out std_logic_vector (15 downto 0));
end component;

component ram_module
   port(clk		: in std_logic;
      enable    : in std_logic;
      R_W		: in std_logic;
      addr		: in std_logic_vector (15 downto 0);  
      data_in	: in std_logic_vector (15 downto 0);	
      data_out	: out std_logic_vector (15 downto 0));
end component;

component mem_logic
   port(read_write :in std_logic;
      MAR          :in std_logic_vector (15 downto 0);
      MIO_enable   :in std_logic;
	  mem_enable   :out std_logic;
	  mux_sel_out  :out std_logic_vector(1 downto 0);
	  KBSR_ld      :out std_logic;
	  CRTDR_ld     :out std_logic;
	  CRTSR_ld     :out std_logic);	
end component;

component FSM
   port(clk:      in   std_logic;
      rst:        in   std_logic;
      IR:         in   std_logic_vector(15 downto 0);
      CC:         in   std_logic_vector(2 downto 0); --NZP Bits
      PC_ld:      out  std_logic;
      PC_mux:     out  std_logic_vector(1 downto 0);
      IR_ld:      out  std_logic;
      MAR_mux:	  out  std_logic_vector(1 downto 0);	
      MAR_gate:   out  std_logic;
      DR_addr:	  out  std_logic_vector(2 downto 0);
      DR_enable:  out  std_logic;
      SR1_addr:	  out  std_logic_vector(2 downto 0);
      SR2_addr:	  out  std_logic_vector(2 downto 0);
      SR2_mux:	  out  std_logic;
      ALU_sel:	  out  std_logic_vector(1 downto 0);
      CC_ld:      out  std_logic;
      MDR_ld:     out  std_logic;
      MAR_ld:     out  std_logic;
      PC_gate:    out  std_logic;
      ALU_gate:   out  std_logic;
      MDR_gate:   out  std_logic;
      MDR_mux :   out  std_logic;
      MIO_enable: out  std_logic;
      Read_Write: out  std_logic;
      PC_clear:   out  std_logic;
      MDR_clear:  out  std_logic;
      MAR_clear:  out  std_logic;
      IR_clear:   out  std_logic;
      CC_clear:   out  std_logic);
end component;

   signal data_bus       : std_logic_vector(15 downto 0);
   signal MAR_mux_out    : std_logic_vector(15 downto 0);
   signal PC_out         : std_logic_vector(15 downto 0);
   signal SR1_out        : std_logic_vector(15 downto 0);
   signal SR2_out        : std_logic_vector(15 downto 0);
   signal SR2_mux_out    : std_logic_vector(15 downto 0);
   signal ALU_out        : std_logic_vector(15 downto 0);
   signal IR_out         : std_logic_vector(15 downto 0);
   signal NZP_out        : std_logic_vector(2 downto 0);
   signal MAR_out        : std_logic_vector(15 downto 0);
   signal MDR_out        : std_logic_vector(15 downto 0);
   signal RAM_out        : std_logic_vector(15 downto 0);
   signal CC_out         : std_logic_vector(2 downto 0);
   signal PC_ld          : std_logic;
   signal PC_mux         : std_logic_vector(1 downto 0);
   signal IR_ld          : std_logic;
   signal MAR_mux        : std_logic_vector(1 downto 0);
   signal DR_addr        : std_logic_vector(2 downto 0);
   signal DR_enable      : std_logic;
   signal SR1_addr       : std_logic_vector(2 downto 0);
   signal SR2_addr       : std_logic_vector(2 downto 0);
   signal SR2_mux        : std_logic;
   signal ALU_sel        : std_logic_vector(1 downto 0);
   signal CC_ld          : std_logic;
   signal MDR_ld         : std_logic;
   signal MAR_ld         : std_logic;
   signal PC_gate        : std_logic;
   signal ALU_gate       : std_logic;
   signal MDR_gate       : std_logic;
   signal MAR_gate       : std_logic;
   signal MIO_enable     : std_logic;
   signal Read_Write     : std_logic;
   signal MDR_mux        : std_logic;
   signal PC_clear       : std_logic;
   signal MDR_clear      : std_logic;
   signal MAR_clear      : std_logic;
   signal IR_clear       : std_logic;
   signal CC_clear       : std_logic;
   signal KBSR_ld        : std_logic;
   signal CRTSR_ld       : std_logic;
   signal CRTDR_ld       : std_logic;
   signal mem_enable     : std_logic;
   signal KBSR_out       : std_logic_vector(15 downto 0);
   signal KBDR_out       : std_logic_vector(15 downto 0);
   signal CRTSR_out      : std_logic_vector(15 downto 0);
   signal CRTDR_out      : std_logic_vector(15 downto 0);
   signal inmux_out      : std_logic_vector(15 downto 0);
   signal inmux_sel      : std_logic_vector(1 downto 0);
   signal sext_out       : std_logic_vector(15 downto 0);
   signal MDR_mux_out    : std_logic_vector(15 downto 0);
   signal zext8_out      : std_logic_vector(15 downto 0);
   signal zext10_out     : std_logic_vector(15 downto 0);
   signal adder_out      : std_logic_vector(15 downto 0);
   signal cat_out        : std_logic_vector(15 downto 0);
   signal PC_mux_out     : std_logic_vector(15 downto 0);
   signal increment_out	 : std_logic_vector(15 downto 0);
   signal ground         : std_logic;
   signal ground16       : std_logic_vector(15 downto 0);
   signal Vcc            : std_logic;
	
begin
   ground <= '0';
   ground16 <= "0000000000000000";
   Vcc <= '1';
   U_reg_bank   : register_file port map (clk, DR_enable, DR_addr, SR1_addr, SR2_addr, data_bus, SR1_out, SR2_out);
   U_ALU_mux    : mux2 port map (SR2_out, sext_out, SR2_mux, SR2_mux_out);
   U_ALU        : LC2_ALU port map (SR1_out, SR2_mux_out, ALU_sel, ALU_out);
   U_ALU_buff   : tri_state port map (ALU_out, ALU_gate, data_bus);
   U_MAR_reg    : reg port map (clk, MAR_ld, data_bus, MAR_out, MAR_clear);
   U_ram_logic  : mem_logic port map(Read_Write, MAR_out, MIO_enable, mem_enable,inmux_sel, KBSR_ld, CRTDR_ld, CRTSR_ld);
   U_inmux      : mux4 port map(KBDR_out, KBSR_out, CRTSR_out, RAM_out, inmux_sel, inmux_out);
   U_ram        : ram_module port map (clk, mem_enable, Read_Write, MAR_out, MDR_out, RAM_out);
   U_KBSR       : reg port map (clk, KBSR_ld, MDR_out, KBSR_out, ground);
   U_KBDR       : reg port map (clk, Vcc, MDR_out, KBDR_out, ground);
   U_CRTSR      : reg port map (clk, CRTSR_ld, MDR_out, CRTSR_out, ground);
   U_CRTDR      : reg port map (clk, CRTDR_ld, MDR_out, CRTDR_out, ground);
   U_MDR_mux    : mux2 port map (data_bus, inmux_out, MDR_mux, MDR_mux_out);
   U_MDR_reg    : reg port map (clk, MDR_ld, MDR_mux_out, MDR_out, MDR_clear);
   U_MDR_buff   : tri_state port map (MDR_out, MDR_gate, data_bus);
   U_IR_reg     : reg port map (clk, IR_ld, data_bus, IR_out, IR_clear);
   U_sext       : sext port map (IR_out(4 downto 0), sext_out);
   U_NZP        : NZP_logic port map (data_bus, NZP_out);
   U_NZP_reg    : NZP_reg port map (clk, CC_ld, NZP_out, CC_out, CC_clear);
   U_ctrl       : FSM port map (clk, rst, IR_out, CC_out, PC_ld, PC_mux, IR_ld, MAR_mux, MAR_gate, DR_addr, DR_enable, 
                                SR1_addr, SR2_addr, SR2_mux, ALU_sel, CC_ld, MDR_ld, MAR_ld, PC_gate, ALU_gate, MDR_gate,
                                MDR_mux, MIO_enable, Read_Write, PC_clear, MDR_clear,MAR_clear, IR_clear, CC_clear);
   U_zext8	    : zext8 port map (IR_out(7 downto 0), zext8_out);
   U_zext10     : zext10 port map (IR_out(5 downto 0), zext10_out);
   U_adder      : adder port map (zext10_out, SR1_out, adder_out);
   U_cat        : cat port map (IR_out(8 downto 0), PC_out(15 downto 9), cat_out);
   U_MAR_mux    : mux4 port map (cat_out, adder_out, zext8_out, ground16, MAR_mux, MAR_mux_out);
   U_MAR_buff   : tri_state port map (MAR_mux_out, MAR_gate, data_bus);
   U_increment  : increment port map (PC_out,increment_out);
   U_PC_mux     : mux4 port map (increment_out, data_bus, SR1_out,cat_out, PC_mux,PC_mux_out);
   U_PC         : reg port map (clk, PC_ld,PC_mux_out, PC_out, PC_clear);
   U_PC_buff    : tri_state port map (PC_out, PC_gate, data_bus);

end str;