版权所有,如转载,请注明出处。
硬件平台:
MPC8260,FPGA:xilink XC2VP30(2片),CPLD:XCV95288.
MPC8260与CPLD的连接关系:
----------------------------------CPLD和CPU的读写信号线--------------------------------
/CS6 :片选
A31-A24 : 地址线8根,能够寻址256字节
D0-D7 : 数据线8根
/WE0 : 写信号
PGPL2 : 读信号
-----------------------------CPLD与FPGA的配置管腿连接---------------------------------
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/