硬件平台: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