-- Four Bit Processor

entity processor is
port(
	vdd, vss	: in bit;
	clk		: in  bit;
	reset		: in  bit;
	cin		: in  bit;
	opcode		: in  bit_vector(2 downto 0);
	op1		: in  bit_vector(3 downto 0);
	op2		: in  bit_vector(3 downto 0);
	dout		: out bit_vector(3 downto 0);
	data_invalid	: out bit
);
end processor;


architecture proc of processor is
signal aluout,aluin1,ramin,bufin : bit_vector(3 downto 0);
signal s0,s1,s2 : bit;

signal p1opcode,p2opcode,p3opcode : reg_vector(2 downto 0) register;
signal p1op1,p2op1,p1op2,p2op2,p3op1: reg_vector(3 downto 0) register;
signal p1cin,acin,p3cin,tinvalid  :  reg_bit register;

  SIGNAL mem_loc0 : reg_vector(3 downto 0) REGISTER;
  SIGNAL mem_loc1 : reg_vector(3 downto 0) REGISTER;
  SIGNAL mem_loc2 : reg_vector(3 downto 0) REGISTER;
  SIGNAL mem_loc3 : reg_vector(3 downto 0) REGISTER;
  SIGNAL mem_loc4 : reg_vector(3 downto 0) REGISTER;
  SIGNAL mem_loc5 : reg_vector(3 downto 0) REGISTER;
  SIGNAL mem_loc6 : reg_vector(3 downto 0) REGISTER;
  SIGNAL mem_loc7 : reg_vector(3 downto 0) REGISTER;
  SIGNAL mem_loc8 : reg_vector(3 downto 0) REGISTER;
  SIGNAL mem_loc9 : reg_vector(3 downto 0) REGISTER;
  SIGNAL mem_loc10 : reg_vector(3 downto 0) REGISTER;
  SIGNAL mem_loc11 : reg_vector(3 downto 0) REGISTER;
  SIGNAL mem_loc12 : reg_vector(3 downto 0) REGISTER;
  SIGNAL mem_loc13 : reg_vector(3 downto 0) REGISTER;
  SIGNAL mem_loc14 : reg_vector(3 downto 0) REGISTER;
  SIGNAL mem_loc15 : reg_vector(3 downto 0) REGISTER;
  SIGNAL aluin2 : reg_vector(3 downto 0) REGISTER;
  signal memin,memout: bit;

signal k,a,b  :bit_vector(3 downto 0);
signal tempk  :bit_vector(3 downto 0);
signal mux : bit_vector(3 downto 0);
signal p0,p1,p3,p5,p7,ta:bit_vector(3 downto 0);
signal c0,c1,c3,c5,c7:bit_vector(3 downto 0);
signal reg     : REG_VECTOR(3 downto 0)REGISTER;
signal cout:bit;
-- signal cout  :reg_bit register; 



begin

ASSERT(vdd = '1' and vss = '0')
   REPORT "Wrong power supplies"
   SEVERITY WARNING;



DEC0 : block (clk = '1' and not clk'STABLE)
begin

	p3opcode <= guarded p2opcode;
	p3op1    <= guarded p2op1;
--	p3op2    <= guarded p2op2;
	p3cin	 <=  guarded acin;
	
	p2opcode <= guarded p1opcode;
	p2op1    <= guarded p1op1;
	p2op2    <= guarded p1op2;
	acin	 <= guarded p1cin;

	p1opcode <= guarded opcode;
	p1op1	 <= guarded op1;
	p1op2	 <= guarded op2;
        p1cin    <= guarded cin;

end block;

--addrin <= p3op1;
--addrout<= p1op1;

--aluin2 <= ramout;
aluin1 <= p2op2;
s2 <= p2opcode(2);
s1 <= p2opcode(1);
s0 <= p2opcode(0);

bufin <= aluout;
dout <= bufin;

memin <= (not p3opcode(2)) and p3opcode(1) and p3opcode(0) and p3cin;
--memin <= ((not p2opcode(2)) and p2opcode(1) and p2opcode(0) and acin) or cout;
--memin <= tmemin or cout;

with reset select
	ramin <= bufin when "1", "0000" when "0";


 R0 : BLOCK (clk ='0' and   not clk'STABLE)
          BEGIN
                  
	WITH memin&p3op1 SELECT 
	mem_loc0 <=   GUARDED
	ramin WHEN "00000",
	mem_loc0 WHEN Others;
           
       WITH memin&p3op1 SELECT 
       mem_loc1 <= GUARDED   
	ramin WHEN "00001",
	 mem_loc1 WHEN Others;
          
       WITH memin&p3op1 SELECT 
       mem_loc2 <= GUARDED   
	ramin WHEN "00010",
	 mem_loc2 WHEN Others;
           
       WITH memin&p3op1 SELECT 
       mem_loc3 <= GUARDED   
	ramin WHEN "00011", 
	 mem_loc3 WHEN Others;
          
       WITH memin&p3op1 SELECT 
       mem_loc4 <= GUARDED   
	ramin WHEN "00100",
	 mem_loc4 WHEN Others;
           
       WITH memin&p3op1 SELECT 
       mem_loc5 <= GUARDED  
	ramin WHEN "00101",
	 mem_loc5 WHEN Others;
          
       WITH memin&p3op1 SELECT 
       mem_loc6 <= GUARDED  
	ramin WHEN "00110",
	 mem_loc6 WHEN Others;
          
 
       WITH memin&p3op1 SELECT 
       mem_loc7 <= GUARDED  
	ramin WHEN "00111",
	 mem_loc7 WHEN Others;
                     
       WITH memin&p3op1 SELECT 
       mem_loc8 <= GUARDED  
	ramin WHEN "01000",
	 mem_loc8 WHEN Others;
            
          
       WITH memin&p3op1 SELECT 
       mem_loc9 <= GUARDED  
	ramin WHEN "01001",
	 mem_loc9 WHEN Others;
           
       WITH memin&p3op1 SELECT 
       mem_loc10 <= GUARDED  
	ramin WHEN "01010", 
	 mem_loc10 WHEN Others;
	          
       WITH memin&p3op1 SELECT 
       	mem_loc11 <= GUARDED  
	ramin WHEN "01011",
 	mem_loc11 WHEN Others;
          

       WITH memin&p3op1 SELECT 
       mem_loc12 <= GUARDED  
	ramin WHEN "01100",
	 mem_loc12 WHEN Others;
          

       WITH memin&p3op1 SELECT 
       mem_loc13 <= GUARDED  
	ramin WHEN "01101",
	 mem_loc13 WHEN Others;
          

       WITH memin&p3op1 SELECT 
       mem_loc14 <= GUARDED  
	ramin WHEN "01110",
	 mem_loc14 WHEN Others;
           

       	WITH memin&p3op1 SELECT 
       	mem_loc15 <= GUARDED  
	ramin WHEN "01111",
	mem_loc15 WHEN Others;
    
  -- END BLOCK;
         

-- ramread : BLOCK (clk ='0' and   not clk'STABLE)
  --        BEGIN
memout <= (not p1opcode(2)) and p1opcode(1) and p1opcode(0) and p1cin;  
        

WITH memout&p1op1 SELECT
            aluin2 <= GUARDED   
                       mem_loc0 WHEN "00000",
                       mem_loc1 WHEN "00001",
                       mem_loc2 WHEN "00010",
                       mem_loc3 WHEN "00011",
                       mem_loc4 WHEN "00100",
                       mem_loc5 WHEN "00101",
                       mem_loc6 WHEN "00110",
                       mem_loc7 WHEN "00111",
                       mem_loc8 WHEN "01000",
                       mem_loc9 WHEN "01001",
                       mem_loc10 WHEN "01010",
                       mem_loc11 WHEN "01011",
                       mem_loc12 WHEN "01100",
                       mem_loc13 WHEN "01101",
                       mem_loc14 WHEN "01110",
                       mem_loc15 WHEN "01111",
			"1111" when others;
         END BLOCK;
  --      ramout <= tempout;


mux <= (s2 & s1 & s0 & acin);
a <= aluin1;
b <= aluin2;


p0(0)<= not a(0) ;
c0(0)<= a(0);
p0(1)<= a(1) xor c0(0);
c0(1)<= a(1) and c0(0);
p0(2)<= a(2) xor c0(1);
c0(2)<= a(2) and c0(1);
p0(3)<= a(3) xor c0(2);
c0(3)<= a(3) and c0(2);



p1(0)<= a(0) xor b(0) xor acin;
c1(0)<= (a(0) and b(0)) or (( a(0) or b(0)) and acin);
p1(1)<= a(1) xor b(1) xor c1(0);
c1(1)<= (a(1) and b(1)) or (( a(1) or b(1)) and c1(0));
p1(2)<= a(2) xor b(2) xor  c1(1);
c1(2)<= (a(2) and b(2)) or (( a(2) or b(2)) and c1(1));
p1(3)<= a(3) xor b(3) xor c1(2);
c1(3)<= (a(3) and b(3)) or (( a(3) or b(3)) and c1(2));



p3(0)<= a(0) xor (not b(0)) xor acin;
c3(0)<= (a(0) and(not b(0))) or (( a(0) or(not  b(0))) and acin);
p3(1)<= a(1) xor ( not b(1)) xor c3(0);
c3(1)<= (a(1) and( not  b(1))) or (( a(1) or (not b(1))) and c3(0));
p3(2)<= a(2) xor( not  b(2)) xor  c3(1);
c3(2)<= (a(2) and ( not b(2))) or (( a(2) or( not  b(2))) and c3(1));
p3(3)<= a(3) xor(not  b(3)) xor  c3(2);
c3(3)<= (a(3) and ( not b(3))) or (( a(3) or ( not b(3))) and c3(2));



p5(0)<= not a(0);
c5(0)<= not a(0);
p5(1)<= a(1) xor c5(0);
c5(1)<= (not a(1)) and c5(0);
p5(2)<= a(2) xor c5(1);
c5(2)<= (not a(2)) and c5(1);
p5(3)<= a(3) xor c5(2);
c5(3)<= (not a(3)) and c5(2);

ta <= not a;
p7(0)<= not p0(0);
c7(0)<= ta(0);
p7(1)<= ta(1) xor c7(0);
c7(1)<= ta(1) and c7(0);
p7(2)<= ta(2) xor c7(1);
c7(2)<= ta(2) and c7(1);
p7(3)<= ta(3) xor c7(2);
c7(3)<= ta(3) and c7(2);

with mux select

 tempk <= a WHEN "0000",
      p0   WHEN "0001",
      P1   WHEN "0010",
      p1   WHEN  "0011",
      p3   WHEN "0100",
      p3   WHEN "0101",
      p5   WHEN "0110",
      (a or b) WHEN "1000",
      not(a or b) WHEN "1001",
      ( a xor b)WHEN "1010",
      not(a xor b) WHEN "1011",
      (a and b) WHEN "1100",
      not (a and b) WHEN "1101",
      ( not a) WHEN "1110",
      p7  WHEN "1111",
	"1111" when others;

with mux select

 cout <= c0(3)   WHEN "0001",
      c1(3)   WHEN "0010",
      c1(3)   WHEN  "0011",
      (not c3(3))   WHEN "0100",
      (not c3(3))   WHEN "0101",
   -- c5(3)   WHEN "0110",
	"0" when others;


with reset SELECT 
  k (3 downto 0) <= tempk(3 downto 0)    WHEN "1",
                       	 "0000"        WHEN "0" ;


  A0 : BLOCK (clk = '0' and not clk'STABLE)
     BEGIN
        reg<= GUARDED k;
   END BLOCK; 
    
    
  aluout <=  reg;
  inv0 : BLOCK (clk = '0' and not clk'STABLE)
     BEGIN
	tinvalid <= guarded (((not p2opcode(2)) and p2opcode(1) and p2opcode(0) and acin) or cout);
--	tinvalid <= guarded not memin;
   END BLOCK; 
    
data_invalid <= tinvalid;

end proc;
