--                                                               
-- config_top.vhd
--
-- This design uses the sconfig block and a couple Fusion NVM blocks
-- to demonstrate logic to configure an Altera FPGA from Fusion.
--        
------------------------------------------------------------------------
--
-- Version 1.0  09/01/06 - Initial release
--
------------------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity config_top is 
port(RST    : in    std_logic; -- Starter Kit is active high
     CSn    : in    std_logic;
     CLK    : in    std_logic;      
     DI     : in    std_logic;
     DO     : inout std_logic
; atck : IN std_logic; tms : IN std_logic; tdi : IN std_logic; trstb : IN std_logic; tdo : OUT std_logic);
end config_top;

architecture rtl of config_top is

component rc_osc is 
    port(CLKOUT : out std_logic) ;
end component;

component PLL_60_40_10 is 
    port(POWERDOWN, CLKA : in std_logic;  LOCK, GLA, GLB, GLC : 
        out std_logic;  OADIVRST : in std_logic) ;
end component;

component cfgnvm is
    port(USER_CLK, USER_RESET : in std_logic; USER_ADD : 
        in std_logic_vector(17 downto 0); USER_AUX_BLOCK : in
         std_logic; USER_DATA : in std_logic_vector(31 downto 0); 
        USER_DISCARD_PAGE, USER_ERASE_PAGE, USER_OVERWRITE_PAGE, 
        USER_OVERWRITE_PROT, USER_PAGELOSS_PROT, USER_PROGRAM, 
        USER_READ, USER_READ_NEXT, USER_LOCK, USER_SPARE_PAGE, 
        USER_UNPROT_PAGE : in std_logic; USER_WIDTH : 
        in std_logic_vector(1 downto 0); USER_WRITE : in
         std_logic; USER_DOUT : out std_logic_vector(31 downto 0); 
        USER_PAGE_STATUS : in std_logic; USER_NVM_STATUS : 
        out std_logic_vector(1 downto 0); USER_NVM_BUSY : out
         std_logic);
end  component;

component sconfig is 
port(rstn   : in    std_logic;
     fclk   : in    std_logic;

     CSn    : in    std_logic;
     CLK    : in    std_logic;      
     DI     : in    std_logic;
     DO     : inout std_logic;

     addr      : out   std_logic_vector(18 downto 0);
     din       : in    std_logic_vector( 7 downto 0);
     dout      : out   std_logic_vector( 7 downto 0);
     rden      : out   std_logic;
     nvm_busy  : in    std_logic;
     nvm_erase : out   std_logic;
     nvm_pgm   : out   std_logic;
     nvm_we    : out   std_logic
; uplink_13_a : OUT std_logic_vector(0 TO 46));
end component;

signal rstn      : std_logic;
signal clk100M   : std_logic;
signal clk60M    : std_logic;
signal clk40M    : std_logic;
signal clk10M    : std_logic;
signal busy1     : std_logic;
signal busy2     : std_logic;
signal nvm_busy  : std_logic;
signal nvm_erase : std_logic;
signal nvm_pgm   : std_logic;
signal nvm_we    : std_logic;
signal adata     : std_logic_vector(31 downto 0);
signal bdata     : std_logic_vector(31 downto 0);
signal nvm_addr  : std_logic_vector(18 downto 0);
signal nvm_din   : std_logic_vector(31 downto 0);
signal nvm_dout  : std_logic_vector( 7 downto 0);
signal aerase    : std_logic;
signal berase    : std_logic;
signal apgm      : std_logic;
signal bpgm      : std_logic;
signal awe       : std_logic;
signal bwe       : std_logic;
signal awen      : std_logic;
signal bwen      : std_logic;
signal nvm_read  : std_logic;

COMPONENT comm_block PORT ( atck : IN std_logic; tms : IN std_logic; tdi : IN std_logic; trstb : IN std_logic; tdo : OUT std_logic; comm2iice_link_iice_0 : OUT std_logic_vector(0 TO 9); iice2comm_link_iice_0 : IN std_logic); END COMPONENT; attribute syn_noprune : boolean; attribute syn_noprune of comm_block_inst : label is true; SIGNAL downlink_14_a : std_logic_vector(0 TO 46); COMPONENT ldic1_0 PORT ( clk : IN std_logic; csn : IN std_logic; di : IN std_logic; do : IN std_logic; rst : IN std_logic; clk60m : IN std_logic; uplink_8 : OUT std_logic_vector(0 TO 52); downlink_14 : IN std_logic_vector(0 TO 46)); END COMPONENT; SIGNAL uplink_8_a : std_logic_vector(0 TO 52); SIGNAL comm2iice_link_iice_0_a_0 : std_logic_vector(0 TO 9); SIGNAL iice2comm_link_iice_0_a_0 : std_logic; COMPONENT iice_0 PORT ( comm2iice_link_iice_0 : IN std_logic_vector(0 TO 9); iice2comm_link_iice_0 : OUT std_logic; mdic_link : IN std_logic_vector(0 TO 52)); END COMPONENT; attribute syn_noprune of iice_inst_0 : label is true; begin

rstn <= NOT(rst);

C1: rc_osc  
port map(CLKOUT => clk100M);

C2: PLL_60_40_10  
port map(POWERDOWN => '1',
         OADIVRST  => rstn,
         CLKA      => clk100M,
         GLA       => clk60M,
         GLB       => clk40M,
         GLC       => clk10M,
         LOCK      => open
);

U1: sconfig
port map (rstn   => rstn,
          fclk   => CLK60M,

          CSn    => CSn,
          CLK    => CLK,    
          DI     => DI,
          DO     => DO,

          addr   => nvm_addr,
          rden   => nvm_read,
          din    => nvm_dout,
          dout   => nvm_din(7 downto 0),

          nvm_busy  => nvm_busy,
          nvm_erase => nvm_erase,
          nvm_pgm   => nvm_pgm,
          nvm_we    => nvm_we
, uplink_13_a => downlink_14_a);

nvm_din(31 downto 8) <= (OTHERS => '0');

nvm_dout  <= adata(7 downto 0) when (nvm_addr(18) = '0') else
             bdata(7 downto 0);

aerase <= nvm_erase AND NOT(nvm_addr(18));
berase <= nvm_erase AND nvm_addr(18);

apgm   <= nvm_pgm AND NOT(nvm_addr(18));
bpgm   <= nvm_pgm AND nvm_addr(18);

awe    <= nvm_we AND NOT(nvm_addr(18));
bwe    <= nvm_we AND nvm_addr(18);

awen   <= NOT(awe);
bwen   <= NOT(bwe);

nvm_busy <= busy1 OR busy2;

M1:cfgnvm
port map(USER_RESET                => rstn,
         USER_CLK                  => clk60M,
         USER_ADD                  => nvm_addr(17 downto 0),
         USER_DATA                 => nvm_din,
         USER_DOUT                 => adata,
         USER_NVM_BUSY             => busy1,

         USER_WIDTH                => "00",
         USER_AUX_BLOCK            => '0',          
         USER_DISCARD_PAGE         => '0',
         USER_ERASE_PAGE           => aerase,
         USER_OVERWRITE_PAGE       => '0',
         USER_OVERWRITE_PROT       => '0',
         USER_PAGELOSS_PROT        => '0',
         USER_PROGRAM              => apgm, 
         USER_READ                 => nvm_read,
         USER_READ_NEXT            => nvm_read,   -- 1
         USER_LOCK                 => '0',
         USER_SPARE_PAGE           => '0', 
         USER_UNPROT_PAGE          => '0',
         USER_WRITE                => awe,
         USER_PAGE_STATUS          => '0',
         USER_NVM_STATUS           => open);

M2:cfgnvm
port map(USER_RESET                => rstn,
         USER_CLK                  => clk60M,
         USER_ADD                  => nvm_addr(17 downto 0),
         USER_DATA                 => nvm_din,
         USER_DOUT                 => bdata,
         USER_NVM_BUSY             => busy2,

         USER_WIDTH                => "00",
         USER_AUX_BLOCK            => '0',          
         USER_DISCARD_PAGE         => '0',
         USER_ERASE_PAGE           => berase,
         USER_OVERWRITE_PAGE       => '0',
         USER_OVERWRITE_PROT       => '0',
         USER_PAGELOSS_PROT        => '0',
         USER_PROGRAM              => bpgm, 
         USER_READ                 => nvm_read,
         USER_READ_NEXT            => nvm_read,   -- 1
         USER_LOCK                 => '0',
         USER_SPARE_PAGE           => '0', 
         USER_UNPROT_PAGE          => '0',
         USER_WRITE                => bwe,
         USER_PAGE_STATUS          => '0',
         USER_NVM_STATUS           => open);

comm_block_inst : comm_block PORT MAP ( atck => atck, tms => tms, tdi => tdi, trstb => trstb, tdo => tdo, comm2iice_link_iice_0 => comm2iice_link_iice_0_a_0, iice2comm_link_iice_0 => iice2comm_link_iice_0_a_0); ldic1_inst_0 : ldic1_0 PORT MAP ( clk => clk, csn => csn, di => di, do => do, rst => rst, clk60m => clk60m, uplink_8 => uplink_8_a, downlink_14 => downlink_14_a); iice_inst_0 : iice_0 PORT MAP ( comm2iice_link_iice_0 => comm2iice_link_iice_0_a_0, iice2comm_link_iice_0 => iice2comm_link_iice_0_a_0, mdic_link => uplink_8_a); end rtl;