STM32通过FSMC读写FPGA

STM32与FPGA通信设计
本文详细介绍了如何利用STM32F103VC和EP4C6E22C8 FPGA进行硬件设计,实现两者之间的通信。通过STM32的FSMC接口与FPGA的直接连接,定义了8个寄存器用于数据交换,同时提供了STM32端和FPGA端的代码示例。
本文章已经生成可运行项目,

目录

1.硬件设计

2.STM32F103端代码

3.FPGA端代码


1.硬件设计

硬件平台:(STM32F103VC + EP4C6E22C8)

STM32F103VC是100管脚的,FSMC引脚定义:地址仅有A19-23  A16-18 共8根地址线,数据线有16根,控制信号RD、WR、NE1

FPGA挂在BANK1的第一区(NE1,还可以有NE2、3、4) 这样可以在FPGA内定义8个寄存器(仅解析A16-18三根地址线)。

2.STM32F103端代码

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

       据此定义如下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)

         {

         }

}

3.FPGA端代码

/*   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

1.本文部分素材来源网络,版权归原作者所有,如涉及作品版权问题,请与我联系删除。

2.未经原作者允许不得转载本文内容,否则将视为侵权;

3.转载或者引用本文内容请注明来源及原作者;

4.对于不遵守此声明或者其他违法使用本文内容者,本人依法保留追究权等。

下面是我的个人微信公众号,关注【一个早起的程序员】精彩系列文章每天不断。

本文已生成可运行项目
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一个早起的程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值