使用嵌入式CPU对FPGA进行SelectMAP加载配置程序 

版权所有,如转载,请注明出处。

硬件平台:

MPC8260,FPGA:xilink XC2VP30(2片),CPLD:XCV95288.

MPC8260与CPLD的连接关系:

----------------------------------CPLDCPU的读写信号线--------------------------------

/CS6               :片选

A31-A24     地址线8根,能够寻址256字节

D0-D7       数据线8

/WE0              写信号

PGPL2            读信号

 

-----------------------------CPLDFPGA的配置管腿连接---------------------------------

PROGRAM

CS

WRITE

CLK

DATA[7-0]

INIT

DOWN

BUSY

 

CPLD端的VHDL程序:

-----------------------------------------------------------------------------                                                              
--written by xiyong8260                                                               
                     
--                                                                    
--                                                                     
--                                                                
-------------------------------------------------------------------------------

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;

entity SelectMAP is
 port(
 
 -- Original Springboard Signals:
 
 ADDR  : in   STD_LOGIC_VECTOR(1 DOWNTO 0);
 DATA : inout STD_LOGIC_VECTOR(7 DOWNTO 0);
 WEn   : in   STD_LOGIC;
 OEn  : in   STD_LOGIC;
 CS1n    : in   STD_LOGIC;

 -- Virtex Configuration Signals:

 Virtex_DATA      : out STD_LOGIC_VECTOR(7 DOWNTO 0);
 Virtex_CCLK    : out STD_LOGIC;
 
 Virtex1_CS   : out STD_LOGIC;
 Virtex1_WRITE   : out STD_LOGIC;
 Virtex1_PROGRAM   : out STD_LOGIC;
 Virtex1_BUSY     : in  STD_LOGIC;
 Virtex1_DONE    : in  STD_LOGIC;
 Virtex1_INIT    : in  STD_LOGIC;
 
 Virtex2_CS   : out STD_LOGIC;
 Virtex2_WRITE   : out STD_LOGIC;
 Virtex2_PROGRAM   : out STD_LOGIC;
 Virtex2_BUSY     : in  STD_LOGIC;
 Virtex2_DONE    : in  STD_LOGIC;
 Virtex2_INIT    : in  STD_LOGIC
 
 );


end SelectMAP;

architecture BEHAVE of SelectMAP is

constant DATA_ADDR
 : STD_LOGIC_VECTOR(1 downto 0) := "00";
constant CCLK_ADDR
 : STD_LOGIC_VECTOR(1 downto 0) := "01";
constant Program_Register_ADDR  
 : STD_LOGIC_VECTOR(1 downto 0) := "10";
constant Input_Register_ADDR
 : STD_LOGIC_VECTOR(1 downto 0) := "11";

signal Output_Buffer_Enable  : std_logic; -- Output Buffer Enable Signal

signal input_reg_d2  : std_logic;
signal input_reg_d1  : std_logic;
signal input_reg_d0  : std_logic;
signal output_register_data  : std_logic_vector(7 DOWNTO 0);
signal input_register_data  : std_logic_vector(7 DOWNTO 0);

signal Virtex1_PROGRAM_OE : std_logic;
signal Virtex2_PROGRAM_OE : std_logic;
signal WHICHFPGA  : std_logic;

begin

Output_Buffer_Enable <= not OEn and not CS1n;

DATA(7 DOWNTO 0) <= output_register_data(7 DOWNTO 0)
 when (Output_Buffer_Enable = '1') else (others => 'Z');


--CCLK Register
process(ADDR, DATA, CS1n, WEn)
begin
 if(WEn'event and WEn='1') then
  if(CS1n = '0') then
    if (ADDR = CCLK_ADDR) then
   Virtex_CCLK   <= DATA(0);
    end if;
  end if;
 end if;
end process;


--DATA Register
process(ADDR, DATA, CS1n, WEn)
begin
 if(WEn'event and WEn='1') then
  if(CS1n = '0') then
--    input_register_data <= DATA;
    if (ADDR = DATA_ADDR) then
   Virtex_DATA   <= DATA;
   end if;
  end if;
 end if;
end process;


--Program Register
process(ADDR, DATA, CS1n, WEn)
begin
 if(WEn'event and WEn='1') then
  if(CS1n = '0') then
    if (ADDR = Program_Register_ADDR) then
        WHICHFPGA  <=   DATA(3);
     
          if (WHICHFPGA='0') then
             Virtex1_CS       <= DATA(2);
            Virtex1_WRITE     <= DATA(1);
            Virtex1_PROGRAM_OE <= DATA(0);
           
            Virtex2_CS       <= '1';
            Virtex2_WRITE     <= '1';
            Virtex2_PROGRAM_OE <= '0';
         else
            Virtex2_CS       <= DATA(2);
            Virtex2_WRITE     <= DATA(1);
            Virtex2_PROGRAM_OE <= DATA(0);
           
            Virtex1_CS       <= '1';
            Virtex1_WRITE     <= '1';
            Virtex1_PROGRAM_OE <= '0';
         end if;
              
    end if;
  end if;
 end if;
end process;

Virtex1_PROGRAM <= '0' when Virtex1_PROGRAM_OE = '1' else 'Z';
Virtex2_PROGRAM <= '0' when Virtex2_PROGRAM_OE = '1' else 'Z';

--output Register
process(ADDR, DATA, CS1n, OEn)
begin

 if(CS1n = '0') then
  if(OEn'event and OEn='0') then
    if (ADDR = Input_Register_ADDR) then
      
       if (WHICHFPGA='0') then
          Input_Reg_D2   <= Virtex1_BUSY;
          Input_reg_D1  <= Virtex1_DONE;
          Input_reg_D0   <= Virtex1_INIT;
      else
          Input_Reg_D2   <= Virtex2_BUSY;
          Input_reg_D1  <= Virtex2_DONE;
          Input_reg_D0   <= Virtex2_INIT;
      end if;
    end if;
  end if;
 end if;

end process;

output_Register_Data <= ("10110" & Input_Reg_D2 & Input_Reg_D1  & Input_Reg_D0);

END BEHAVE;

 

CPU端C程序:

/***************************************************************
 * FileName:
 *    SelectMAP.c
 *
 * Project:
 *    SelectMAP Configuration via embedded microprocessor.
 *
 * Description:
 *
 *      This is the main source file that will allow a microprocessor
 *      to configure Xilinx Virtex, Virtex-E, Virtex-EM, Virtex-II,
 *      and Spartan-II devices via the SelectMAP Configuration Mode.
 *      This code is discussed in Xilinx Application Note, XAPP502.
 *
 * authors: modified by xiyong [email protected]

 ****************************************************************/


#include <stdio.h>
 //**********************************************************************
 //  Virtex Configuration Constants (Global Variables)
 //******************* ***************************************************


 /*CPLD Register Addresses:*/
 #define     CPLD_BASE_ADD          0x61000000   /*xiyong:must be the same to memory settings*/
 
 /*xiyong: we define four 8 bits register*/
 
 unsigned long  CPLD_DATA_Reg          = CPLD_BASE_ADD+0x0;
 unsigned long  CPLD_CCLK_Reg          = CPLD_BASE_ADD+0x1;
 unsigned long  CPLD_Program_Reg       = CPLD_BASE_ADD+0x2;
 unsigned long  CPLD_STATUS_Reg        = CPLD_BASE_ADD+0x3;

 /*Constants:

 //Mask Values for CCLK bit in the Configuration Register:
 //Used in SelectMAP configuration
*/
 
 /*CCLK register,the last bit used to define CLK value, 0 or 1*/
 
 unsigned char  CCLK_LOW_MASKVALUE  = 0x0;
 unsigned char  CCLK_HIGH_MASKVALUE = 0x1;


 /*Program Register: we use last three bit*/

 unsigned char CS_Bit         = 0x4;
 unsigned char Write_Bit      = 0x2;
 unsigned char Prog_Bit       = 0x1;
 
 unsigned char  FPGA0ADDR =0x0;
 unsigned char  FPGA1ADDR =0x8;
 unsigned char  FPGAADDR=FPGA0ADDR;
 
  /*Status Register: we use last three bit*/

 unsigned char BUSY_Bit       = 0x4;
 unsigned char DONE_Bit       = 0x2;
 unsigned char INIT_Bit       = 0x1;


#define IOWrite(reg, data)  *(unsigned char *)(reg)=data
#define IORead(reg)  *(unsigned char *)(reg)

#define FPGA0_FILE_START_ADDR 0x50000000
#define FPGA0_FILE_END_ADDR   0x50161b24  /*actual 161b6f 24*/

#define FPGA1_FILE_START_ADDR 0x50200000
#define FPGA1_FILE_END_ADDR   0x50361b24  /*actual 161b6f 24*/

#define CHECKDONE_TIMEOUT 10000  //超时标记
#define CHECKBUSY_TIMEOUT 1000
#define CHECKINIT_TIMEOUT 10000
/***************************************
****************************************/
void  Start_SelectMAP( unsigned char whichFPGA );
void  SelectMAP( unsigned long flash_start_addr, unsigned long flash_end_addr, unsigned char whichFPGA) ;
int  SelectMAP_output( unsigned char Data8 );
int  Check_BUSY(void);
void  Check_DONE_Bit(void);
  /***********************************************************************
   *
   * Function:     Start_SelectMAP
   *
   * Description:  Begins SelectMAP configuration of Xilinx FPGA
   *
   *
   * Parameters:
   *      void
   *
   * Returns:
   *      void
   *
   * Called By:
   *      Main()
   *
   *
   * History:
   *      3-October-2001  MN/MP  - Created
   *
   ***********************************************************************/


/*

whichFPGA=0, FPGA0 is choosed;
whichFPGA=1, FPGA1 is choosed;

*/
 void
 loadfpga( unsigned char whichFPGA )
 {

    //Address Range varaibles
    unsigned long flash_start_addr;
    unsigned long flash_end_addr;

    //Location of configuration data stored in flash
    if (whichFPGA==0)
    { 
    flash_start_addr = FPGA0_FILE_START_ADDR;
    flash_end_addr   = FPGA0_FILE_END_ADDR;
    }
    else
    {
    flash_start_addr = FPGA1_FILE_START_ADDR;
    flash_end_addr   = FPGA1_FILE_END_ADDR;
    } 

    //----------------------------------------------------------------------
    // SelectMAP()
    //----------------------------------------------------------------------

    SelectMAP(flash_start_addr,flash_end_addr,whichFPGA);

    //----------------------------------------------------------------------
    // Monitor the DONE bit in the CPLD Input Register to see if
    // configuration successful
    //----------------------------------------------------------------------

    Check_DONE_Bit();

 }


 /***********************************************************************
  *
  * Function:     SelectMAP
  *
  * Description:  Initiates SelectMAP Configuration.
  *               Calls SelectMAP_Output() to output MSByte and LSByte
  *
  * Parameters:
  *   flash_start_addr = Address value where Virtex bitstream begins
  *   flash_end_addr   = Address value where Virtex bitstream ends
  *
  * Returns:
  *   void
  *
  * Called By:
  *   Start_SelectMAP
  *
  * History:
  *   3-October-2001  MN/MP  - Created
  *
  ***********************************************************************/


 void
 SelectMAP( unsigned long flash_start_addr, unsigned long flash_end_addr,unsigned char whichFPGA )
 {
    unsigned char Data8;
    unsigned long flash_addr,timeout=0;

   
    //----------------------------------------------------------------------
    //Toggle Program_OE, /CS, and /WRITE  (Bring all three bits LOW)
    //This is accomplished by writing to the Program Register in the CPLD.
    //Note that /CS and /WRITE bits in the Program Register have been
    //configured to preset upon powerup.
    //
    //NOTE: The Program_OE bit should be driven high to bring the
    //      Virtex Program Pin low.  Likewise, it should be driven
    //      low to bring the Virtex Program Pin to High-Z
    //----------------------------------------------------------------------
    if (whichFPGA==0)
     FPGAADDR = FPGA0ADDR;
    else
     FPGAADDR = FPGA1ADDR; 

    //Bring CS, WRITE and PROGRAM_OE LOW:
    IOWrite(CPLD_Program_Reg, FPGAADDR |Prog_Bit );

    for (timeout=0;timeout<1000;timeout++);

    //----------------------------------------------------------------------
    //Bring Program High
    //But leave /CS and /WRITE Low:
    //----------------------------------------------------------------------

    //Program_OE bit Low brings the Virtex Program Pin to High Z:
    IOWrite(CPLD_Program_Reg, FPGAADDR | 0x0);

 

    //----------------------------------------------------------------------
    //Check for /INIT after Program is High Z:
    //----------------------------------------------------------------------


    Data8 = 0;  //Initialize Data8 variable before entering While Loop

    do
    {
     
         timeout++;
         Data8 = IORead(CPLD_STATUS_Reg);  //Read STATUS Register
                 
    }while( (!(Data8 & INIT_Bit)) && (timeout<CHECKINIT_TIMEOUT));
   
    if (!(Data8 & INIT_Bit))
    { 
      printf("INIT signal is not high/n");
       return;
    } 
    else
      printf("INIT time is %x %x cycle/n",timeout,Data8);  
   
    

    //----------------------------------------------------------------------
    //Begin SelectMAP Configuration
    //----------------------------------------------------------------------


   
    for(flash_addr = flash_start_addr; flash_addr <= flash_end_addr; flash_addr++){
        Data8 = IORead(flash_addr); //Read Flash
     //Pass the 16-bit unsigned char to SelectMAP_output() function:
        if (SelectMAP_output(Data8)) {printf("check busy/n"); break;}
    }
 }

 

 

  /***********************************************************************
   *
   * Function:     SelectMAP_output
   *
   * Description:  This function takes a byte to CPLD
   *               This function is also responsible for strobing the
   *               Configuration Clock (CCLK)
   *
   * Parameters:
   *      Data8 = 8 bit configuration unsigned char previously stored in flash
   *               memory
   *
   * Returns:
   *      void
   *
   * Called By:
   *      SelectMAP()
   *
   *
   ***********************************************************************/

 int
 SelectMAP_output( unsigned char Data8 )
 {
    unsigned char temp;
    unsigned char DataOut;
    unsigned long Busy_Check;
    unsigned long busy_count;

 

   
    /*xiyong: first set clk low, them put data on the bus, them set clk high*/
    IOWrite(CPLD_CCLK_Reg, CCLK_LOW_MASKVALUE);
   
    IOWrite(CPLD_DATA_Reg, Data8);
   
    IOWrite(CPLD_CCLK_Reg,CCLK_HIGH_MASKVALUE);


    //----------------------------------------------------------------------
    //  xiyong: Optional:  Check for BUSY, it may be not needed
    //----------------------------------------------------------------------

    //for (temp=0;temp<2;temp++);
    return 0; /*Check_BUSY(); */ //Check BUSY pin for this Upper Byte

 }

 

  /***********************************************************************
   *
   * Function:     Check_Busy  (OPTIONAL)
   *
   * Description:  This function takes monitors the CPLD Input Register
   *               by checking the status of the BUSY bit in that Register.
   *               By doing so, it monitors the Xilinx Virtex device's
   *               BUSY Pin. This function may not be necessary depending
   *               upon the speed of the microprocessor.
   *
   *               The maximum speed of SelectMAP configuration
   *               is different for different FPGA families.
   *               Please refer to the appropriate data sheet.
   *
   * Parameters:
   *      void
   *
   *
   * Returns:
   *      void
   *
   * Called By:
   *      SelectMAP_output()
   *
   * History:
   *      3-October-2001  MN/MP  - Created
   *
   ***********************************************************************/


int Check_BUSY(void ) {

    unsigned char Busy_Check;
    int timeout=0;

            //----------------------------------------------------------------------
            //Check For BUSY:
            //  If BUSY is HIGH, keep giving CCLK's.
            //  Else, return and send the next Byte
            //----------------------------------------------------------------------

     Busy_Check=0;
     do{
                timeout++;
                Busy_Check = IORead(CPLD_STATUS_Reg);  //Read STATUS Register
             
                if(Busy_Check & BUSY_Bit){    //If Busy is High,

                    //Bring CCLK Low:
                    IOWrite(CPLD_CCLK_Reg, CCLK_LOW_MASKVALUE);
                    //Bring CCLK HIgh:
                    IOWrite(CPLD_CCLK_Reg, CCLK_HIGH_MASKVALUE);
                }

      }while( (Busy_Check & BUSY_Bit) && (timeout<CHECKBUSY_TIMEOUT )); //Keep doing this until Busy is low
     
      if (Busy_Check & BUSY_Bit)
      { 
       printf("Busy_Check is %x/n",Busy_Check);
       return 1;
      }
      else return 0;
}

 

 

  /***********************************************************************
   *
   * Function:     Check_Done_Bit
   *
   * Description:  This function takes monitors the CPLD Input Register
   *               by checking the status of the DONE bit in that Register.
   *               By doing so, it monitors the Xilinx Virtex device's DONE
   *               Pin to see if configuration bitstream has been properly
   *               loaded
   *
   * Parameters:
   *      void
   *
   *
   * Returns:
   *      void
   *
   * Called By:
   *      Start_SelectMAP()
   *
   * History:
   *      3-October-2001  MN/MP  - Created
   *
   ***********************************************************************/

void Check_DONE_Bit(void){

    unsigned char Data8;
    unsigned char Done;
    unsigned char Init;
    unsigned char ExtraCclk;
    int timeout=0;

    Done = 0;
    Init = 1;

    while ( (Done==0) && (Init==1) && (timeout<CHECKDONE_TIMEOUT ))
    {
        //Apply additional CCLK pulse until DONE=1
        timeout++;
        IOWrite(CPLD_CCLK_Reg, CCLK_LOW_MASKVALUE); //CCLK=0;DATA=0xFF
        IOWrite(CPLD_DATA_Reg, 0xFF);
        IOWrite(CPLD_CCLK_Reg, CCLK_HIGH_MASKVALUE);//CCLK=1;DATA=0xFF

        //Read CPLD Status Register:
        Data8 = IORead(CPLD_STATUS_Reg);

        //Check the DONE bit of the CPLD Status Register:
        Done = (Data8 & DONE_Bit) ? 1 : 0;

        //Check the INIT bit of the CPLD Status Register
        Init = (Data8 & INIT_Bit) ? 1 : 0;
        //Note: FPGA user design should drive INIT High or make INIT HIGHZ
        //      to ensure no false INIT error detected by this code.
    }

    if (Done == 1){                     //If DONE Pin is High, display message
        for(ExtraCclk=0;ExtraCclk<8;ExtraCclk++){
            //Apply additional CCLK pulse to ensure end-of-startup
         IOWrite(CPLD_CCLK_Reg, CCLK_LOW_MASKVALUE); //CCLK=0;DATA=0xFF
         IOWrite(CPLD_DATA_Reg, 0xFF);
         IOWrite(CPLD_CCLK_Reg, CCLK_HIGH_MASKVALUE);//CCLK=1;DATA=0xFF
            //Note:  FPGA user design should keep CCLK and DATA HIGHZ to avoid
            //       conflict with this code.
        }
        IOWrite(CPLD_Program_Reg, FPGAADDR | 0x6);
        printf("Successful! DONE is High!/n");   //"Successful! DONE is High!"
    }
    else{//Done==0 and Init==0
        printf("Configuration Failed!/n");    //"Configuration Failed", DONE is Low, Init is Low"
    }
}


void finishFPGA()
{
  IOWrite(CPLD_Program_Reg, FPGAADDR | 0x6);
 
}

void startFPGA()
{
    int timeout;
   
    IOWrite(CPLD_Program_Reg, FPGAADDR | Prog_Bit );

    for (timeout=0;timeout<1000;timeout++);

    //----------------------------------------------------------------------
    //Bring Program High
    //But leave /CS and /WRITE Low:
    //----------------------------------------------------------------------

    //Program_OE bit Low brings the Virtex Program Pin to High Z:
    IOWrite(CPLD_Program_Reg, FPGAADDR | 0x0);

}

 

来自:http://xiyong8260.blog.163.com/blog/static/665146212008112001215175/

你可能感兴趣的:(vector,Flash,嵌入式,input,Parameters,output)