STM32通过FSMC读写FPGA

硬件平台:icore板(STM32F103VC + EP4C6E22C8)

STM32F103VC是100管脚的,FSMC引脚定义:
地址仅有A19-23  A16-18 共8根地址线,数据线有16根,控制信号RD、WR、NE1
FPGA挂在BANK1的第一区(NE1,还可以有NE2、3、4) 

这样可以在FPGA内定义8个寄存器(仅解析A16-18三根地址线)

 

 

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

       据此定义如下STM32与FPGA间通信用的寄存器 

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

#define ARM_FPGA_REG0 *((volatile unsigned short *)((u32)0x60000000))

#define ARM_FPGA_REG1 *((volatile unsigned short*)( (u32)0x60020000))

#define ARM_FPGA_REG2 *((volatile unsigned short*)( (u32)0x60040000))

#define ARM_FPGA_REG3 *((volatile unsigned short*)( (u32)0x60060000))

#define ARM_FPGA_REG4 *((volatile unsigned short*)( (u32)0x60080000))

#define ARM_FPGA_REG5 *((volatile unsigned short *)((u32)0x600a0000))

#define ARM_FPGA_REG6 *((volatile unsigned short *)((u32)0x600c0000))

#define ARM_FPGA_REG7 *((volatile unsigned short *)((u32)0x600e0000))

 

  /* FSMC对应的GPIO选第二功能,100pin的和非100pin的管脚是有差别的  */ 

void FSMC_GPIO_Configuration(void)

{

  GPIO_InitTypeDef GPIO_InitStructure;

 

  /* SRAM 数据线双向IO  PD 和 PE               */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_8 | GPIO_Pin_9 |

                                                    GPIO_Pin_10 | GPIO_Pin_14 | GPIO_Pin_15;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //GPIO_Mode_AF_PP是复用第二功能,也即FSMC

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_Init(GPIOD, &GPIO_InitStructure); 

  

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 |

                                                    GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | 

                                                    GPIO_Pin_15;

  GPIO_Init(GPIOE, &GPIO_InitStructure);

  

  /* SRAM Address lines configuration   PD11 12 13 对应 A16 17 18  

      PE2 3 4 5 6 对应 A23 19 20 21 22  总共8根地址线            */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 |GPIO_Pin_12 | GPIO_Pin_13;

  GPIO_Init(GPIOD, &GPIO_InitStructure);

  

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_2 | GPIO_Pin_3 | 

                                                    GPIO_Pin_4 | GPIO_Pin_5;

  GPIO_Init(GPIOE, &GPIO_InitStructure);

   

  /* WR and RD configuration */  

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 |GPIO_Pin_5;

  GPIO_Init(GPIOD, &GPIO_InitStructure);

  

  /* NE1 PD7 片选 */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; 

  GPIO_Init(GPIOD, &GPIO_InitStructure);

  

  /* NBL0, NBL1 configuration 高低字节使能*/

//  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; 

//  GPIO_Init(GPIOE, &GPIO_InitStructure); 

}

 

  /*设置FSMC接口时序,控制对象,以及BANK以及区(一个Bank有4个区(4个片选))        */ 

void FSMC_SRAM_Init(void)

{

  FSMC_NORSRAMInitTypeDef  FSMC_NORSRAMInitStructure;

  FSMC_NORSRAMTimingInitTypeDef  p;

  

/*-- FSMC Configuration ------------------------------------------------------*/

  p.FSMC_AddressSetupTime = 0;

  p.FSMC_AddressHoldTime = 0;

  p.FSMC_DataSetupTime = 2;

  p.FSMC_BusTurnAroundDuration = 0;

  p.FSMC_CLKDivision = 0;

  p.FSMC_DataLatency = 0;

  p.FSMC_AccessMode = FSMC_AccessMode_A;

 

  FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM1;

  FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;

  FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM;

  FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth =   

  FSMC_MemoryDataWidth_16b;//FSMC_MemoryDataWidth_8b;

  FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;

  FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;

  FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;

  FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;

  FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;

  FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;

  FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;

  FSMC_NORSRAMInitStructure.FSMC_AsyncWait = FSMC_AsyncWait_Disable;

  FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;

  FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p;

  FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p;

 

  FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure); 

 

  /* Enable FSMC Bank1_SRAM Bank */

  FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1, ENABLE);  

}

 

/*  另外不要忘了使能FSMC时钟以及对应GPIO的时钟,放在RCC_Configuration()里面了 */

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE, 

                                            ENABLE);

  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);

 

至此STM32配置FSMC就完成了,可以编写测试程序了:

void main(void)

{

        u32 i = 0;

        u16 j = 0; 
 

        RCC_Configuration();                        

        NVIC_Configuration();                       

        FSMC_GPIO_Configuration();                  

        FSMC_SRAM_Init();                           

        USART_Initial();//UART1端口配置             

                                                    

        printf("start test!\r\n");                  

                                                    

        for(j = 0; j < 256; j++)                    

        {                                           

               ARM_FPGA_REG2 = j << 8 | j;                 

               printf("0x%4x\r\n", ARM_FPGA_REG2);         

        }                                           

                                                    

        for(i = 0; i < 65536; i++)                  

        {                                           

               ARM_FPGA_REG1 = (u16)i;                    

               if(ARM_FPGA_REG1 != i)                      

                   printf("%d\r\n", ARM_FPGA_REG1);           

        }                                           

        printf("test over!\r\n");                   

        

         while(1)

         {

         }

}

 

 

 

/*   FPGA端得代码和上次DSP与FPGA通信的代码基本一致,如下:    */

module      STM32_FPGA(

                                          input  main_clk,  //25M晶振

                                          output arm_clk,  //FPGA输出8M时钟作为STM32的外部时钟HSE,经过PLL倍频后得

                                                                     //72M系统时钟

 

                                          output led,       //指示灯,无关紧要

 

                                          input [2:0] addr,

                                          inout [15:0] data,

                                          input FPGA_CS0,//FPGA片选

                                          input RD,

                                          input WR  

                                         );

 

 

wire clk;

 

pll_50M       pll_50M_inst (

                                          .inclk0 ( main_clk ),//25M

                                          .c0 ( clk ),             //50M

                                          .c1 ( arm_clk )      //8M    

                                        );

 

 

reg [24:0] cnt = 0;

always @(posedge clk)

     cnt <= cnt + 1'b1; 

 

assign led = cnt[24];

 

////////////////////////////////////////////////////////////////////

reg [15:0] ARM_FPGA_REG0; 

reg [15:0] ARM_FPGA_REG1;

reg [15:0] ARM_FPGA_REG2; 

reg [15:0] ARM_FPGA_REG3; 

reg [15:0] ARM_FPGA_REG4;

reg [15:0] ARM_FPGA_REG5; 

reg [15:0] ARM_FPGA_REG6; 

reg [15:0] ARM_FPGA_REG7; 

 

 

wire rd_en = ~FPGA_CS0 && ~RD;

 

reg [15:0] data_reg; 

//always @(posedge clk) //!                               

always @(*)

begin                                                

   if(rd_en)                                 

     begin                                           

        case(addr[2:0])                              

         3'd0   :  data_reg <= ARM_FPGA_REG0;        

         3'd1   :  data_reg <= ARM_FPGA_REG1;        

         3'd2   :  data_reg <= ARM_FPGA_REG2;        

         3'd3   :  data_reg <= ARM_FPGA_REG3;        

         3'd4   :  data_reg <= ARM_FPGA_REG4;        

         3'd5   :  data_reg <= ARM_FPGA_REG5;        

         3'd6   :  data_reg <= ARM_FPGA_REG6;        

         3'd7   :  data_reg <= ARM_FPGA_REG7;        

         default:  ;                                 

        endcase                               

     end                                                                                              

end                                           

 

/* WR上升沿STM32的数据写入FPGA,即sampling point */ 

 

reg WR_tmp1;

reg WR_tmp2;

always @(posedge clk)

begin

    WR_tmp1 <= WR;

    WR_tmp2 <= WR_tmp1;

end 

 

wire WR_RISING = ~WR_tmp2 && WR_tmp1;//与clk同步 

 

 

always @(*)                                  

begin                                      

  if(WR_RISING)                            

     begin                                    

        case(addr[2:0])                       

         3'd0   :  ARM_FPGA_REG0 <= data;     

         3'd1   :  ARM_FPGA_REG1 <= data;     

         3'd2   :  ARM_FPGA_REG2 <= data;     

         3'd3   :  ARM_FPGA_REG3 <= data;     

         3'd4   :  ARM_FPGA_REG4 <= data;     

         3'd5   :  ARM_FPGA_REG5 <= data;     

         3'd6   :  ARM_FPGA_REG6 <= data;     

         3'd7   :  ARM_FPGA_REG7 <= data;     

         default:  ;                          

        endcase                        

     end                                      

end                                        

 

assign data = rd_en ? data_reg : 16'hzzzz;

 

endmodule

你可能感兴趣的:(FPGA,STM32)