------------------------------------------------------------------------
  
--© 2022 Microchip Technology Inc. and its subsidiaries
--  All rights reserved.
  
--  ANY USE OR REDISTRIBUTION IN PART OR IN WHOLE MUST BE HANDLED IN
--  ACCORDANCE WITH THE MICROCHIP LICENSE AGREEMENT AND MUST BE APPROVED
--  IN ADVANCE IN WRITING.
 
 -------------------------------------------------------------------------
--  Title : Fabric_Logic.vhd
--  Created :  March 13, 2017
--  Description : 4464 stage 8-bit Loadable Up Counters, 252 stage 16 bit shift registers 
               -- 56-uSRAMs,55-LSRAMs and 42-Math blocks.
--  Hierarchy :top
                --Fabric_Logic    <-- This module
  
 -------------------------------------------------------------------------
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;

entity Fabric_Logic is
  generic (
    WIDTH  : integer := 16);
  port (
    CLK    : in std_logic;
    RST    : in std_logic;
    LD     : in std_logic;
    DIN    : in std_logic_vector(WIDTH-1 downto 0);
    DOUT   : out std_logic_vector(WIDTH-1 downto 0);
	LED_1  : out std_logic;
	LED_2  : out std_logic;
	LED_3  : out std_logic;
	LED_4  : out std_logic);
end Fabric_Logic;

ARCHITECTURE STRUCT OF Fabric_Logic IS

type state_values is (idle,start_c2);
signal pres_state: state_values;

signal ENA1       : std_logic;
signal ENA2       : std_logic;

signal REG_ARRAY1 :  std_logic_vector(WIDTH-1 downto 0);
signal REG_ARRAY2 :  std_logic_vector(17 downto 0);
signal REG_ARRAY3 :  std_logic_vector(17 downto 0);
signal REG_ARRAY4 :  signed(17 downto 0);
signal REG_ARRAY5 :  signed(17 downto 0);
signal REG_ARRAY6 :  std_logic_vector(15 downto 0);

signal CNT_DIN    : std_logic_vector (17 downto 0);
signal CNT_WAddr  : std_logic_vector (9 downto 0);
signal CNT_RAddr  : std_logic_vector (9 downto 0);
signal CNTVAL     : std_logic_vector(25 downto 0);

component cnt_cascaded
  generic (
    WIDTH      : integer := 8);
  port (
    CLK        : in std_logic;
    RST        : in std_logic;
    LD         : in std_logic;
    ENA        : in std_logic;
    DIN        : in std_logic_vector(WIDTH-1 downto 0);
    DOUT       : out std_logic_vector(WIDTH-1 downto 0));
end component;

component lsram_cascaded  
   generic (width  : integer := 18;   
            depth  : integer := 1024;   
            addr   : integer := 10);   
   port (Din       : in std_logic_vector (width-1 downto 0);
         CLK       : in std_logic;
         WE        : in std_logic;
         WAddr     : in std_logic_vector (addr-1 downto 0);
         RAddr     : in std_logic_vector (addr-1 downto 0);
         Dout      : out std_logic_vector (width-1 downto 0));
end component;

component usram_cascaded
   generic (width  : integer := 18;   
            depth  : integer := 64;   
            addr   : integer := 6);   
   port (Din       : in std_logic_vector (width-1 downto 0);
         CLK       : in std_logic;
         WE        : in std_logic;
         WAddr     : in std_logic_vector (addr-1 downto 0);
         RAddr     : in std_logic_vector (addr-1 downto 0);
         Dout      : out std_logic_vector (width-1 downto 0));
end component;

component macc_cascaded
  generic (
    WIDTH      : integer := 18);
  port (
    CLK        : in std_logic;
    RST        : in std_logic;
    DIN1       : in signed(WIDTH-1 downto 0);
    DIN2       : in signed(WIDTH-1 downto 0);
    DOUT       : out signed((WIDTH * 2)-1 downto 0));
end component;

component shift_register
  port (
    CLK        : in std_logic;
    RST        : in std_logic;
    DIN        : in std_logic_vector(15 downto 0);
    DOUT       : out std_logic_vector(15 downto 0));
end component;

BEGIN

process (CLK, RST)
begin
  if(RST = '0')then
		pres_state <= idle;
  elsif (CLK'event and CLK ='1') then
	case pres_state is
	   when idle=>
		 if (REG_ARRAY1(7 downto 0) = "11111110")then
			  pres_state <= start_c2;
		 end if;
	   when start_c2=>
		 if (REG_ARRAY1(15 downto 8) = "11111110")then
		      pres_state <= idle;
		 end if;
       when others => null;
	end case;
 end if;
end process;

process (CLK, RST)
begin
  if(RST = '0')then
		ENA1  <= '0';
		ENA2  <= '0';
  elsif (CLK'event and CLK ='1') then
	 if(pres_state = idle)then
		ENA1  <= '1';
		ENA2  <= '0';
	 else
		ENA1  <= '0';
		ENA2  <= '1';
	 end if;
  end if;
end process;	

 P1 : process (CLK, RST)
    begin
      if (RST = '0') then
          CNT_DIN <= (others => '0');    
      elsif (CLK'event and CLK = '1') then
          CNT_DIN <= CNT_DIN + 1;
      end if;            
 end process;

 P2 : process (CLK, RST)
    begin
      if (RST = '0') then
          CNT_WAddr <= (others => '0');    
      elsif (CLK'event and CLK = '1') then
          CNT_WAddr <= CNT_WAddr + 1;
      end if;            
 end process;

 P3 : process (CLK, RST)
    begin
      if (RST = '0') then
          CNT_RAddr <= "1111111110";    
      elsif (CLK'event and CLK = '1') then
          CNT_RAddr <= CNT_RAddr + 1;
      end if;            
 end process;

 P4 : process (CLK, RST)
    begin
      if (RST = '0') then
          CNTVAL <= (others => '0');    
      elsif (CLK'event and CLK = '1') then
		if (REG_ARRAY1(15) = '1') then
          CNTVAL <= CNTVAL + 1;
		else
		  CNTVAL <= CNTVAL;
		end if;            
      end if;            
 end process;

 DOUT  <= (REG_ARRAY6 and 
           std_logic_vector (REG_ARRAY4 (15 downto 0)) and
           std_logic_vector (REG_ARRAY5 (15 downto 0)));
 LED_1 <= CNTVAL(22);
 LED_2 <= CNTVAL(23);
 LED_3 <= CNTVAL(24);
 LED_4 <= CNTVAL(25);

 U1_1 : cnt_cascaded
    generic map(WIDTH  => 8)
    port map ( CLK  => CLK,
               RST  => RST,
               LD   => LD,
               ENA  => ENA1,
               DIN  => DIN(7 downto 0),
               DOUT => REG_ARRAY1(7 downto 0));

 U1_2 : cnt_cascaded
    generic map(WIDTH  => 8)
    port map ( CLK  => CLK,
               RST  => RST,
               LD   => LD,
               ENA  => ENA2,
               DIN  => DIN(15 downto 8),
               DOUT => REG_ARRAY1(15 downto 8));

 U2 : lsram_cascaded 
    generic map (width => 18,   
                 depth => 1024,   
                 addr  => 10)
    port map    (Din   => CNT_DIN,
                 CLK   => CLK,
                 WE    => CNT_DIN(0),
                 WAddr => CNT_WAddr,
                 RAddr => CNT_RAddr,
                 Dout  => REG_ARRAY2);

 U3 : usram_cascaded 
    generic map (width => 18,   
                 depth => 64,   
                 addr  => 6)
    port map    (Din   => CNT_DIN,
                 CLK   => CLK,
                 WE    => CNT_DIN(0),
                 WAddr => CNT_WAddr(5 downto 0),
                 RAddr => CNT_RAddr(5 downto 0),
                 Dout  => REG_ARRAY3);

 U4 : macc_cascaded
    generic map( WIDTH => 18)
    port map   ( CLK   => CLK,
                 RST   => RST,
                 DIN1  => signed (REG_ARRAY2),
                 DIN2  => signed (REG_ARRAY3),
                 DOUT (17 downto 0)  => REG_ARRAY4,
                 DOUT (35 downto 18) => REG_ARRAY5);

 U5 : shift_register
      port map ( CLK  => CLK,
    			 RST  => RST,
                 DIN  => REG_ARRAY1,
                 DOUT => REG_ARRAY6);

END STRUCT;






