1、FSMC简介:FSMC即灵活的静态存储控制器,FSMC管理1GB空间,拥有4个Bank连接外部存储器,每个Bank有独立的片选信号和独立的时序配置;支持的存储器类型有S RAM 、PSRAM、NOR/ONENAND、 ROM 、LCD接口(支持8080和6800模式)、NANDFlash和16位的PCCard。
2、在设计中将FPGA当做SRAM来驱动,使用库函数来实现FSMC的初始化配置代码如下:
//初始化外部SRAM
void FSMC_SRAM_Init(void)
{
FSMC_NO RS RAMInitTypeDef FSMC_NORSRAMInitStructure; //定义FSMC初始化的结构体变量
FSMC_NORSRAM Ti mingInitTypeDef readWri te TI ming; //用来设置FSMC读时序和写时序的指针变量
G PI O_InitTypeDef GPIO_InitStructure; //初始化FSMC总线的IO口
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOE|RCC_APB2Periph_AFIO,ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC,ENABLE); //开启FSMC的 时钟
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_14
|GPIO_Pin_15|GPIO_Pin_0|GPIO_Pin_1
|GPIO_Pin_7|GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_4|GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //IO口配置为复用推挽输出
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_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOE, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOE, &GPIO_InitStructure);
readWrite TI ming.FSMC_AddressSetup TI me = 14;
readWrite TI ming.FSMC_AddressHoldTime = 0x00;
readWriteTiming.FSMC_DataSetupTime = 16;
readWriteTiming.FSMC_BusTurnAroundDuration = 0;
readWriteTiming.FSMC_CLKDivision = 0x00;
readWriteTiming.FSMC_DataLatency = 0x00;
readWriteTiming.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_MemoryDataW idt h= FSMC_MemoryDataWidth_16b;
FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode=FSMC_BurstAccessMode_Disable;
FSMC_NORSRAMInitStructure.FSMC_W ai tSignalPolarity = FSMC_WaitSignalPolarity_Low;
FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait=FSMC_AsynchronousWait_Disable;
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_WriteBurst = FSMC_WriteBurst_Disable;
FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &readWriteTiming;
FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &readWriteTiming;
FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);
FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1, ENABLE);
delay_ms(50);
}
FPGA代码:
//fsmc read / write ep4ce6 demo
module fsmc(
ab, //address
db, //data
wrn, //wr
rdn, //rd
resetn, //resetn
csn, //cs
clk
);
input[2:0] ab;
inout[15:0] db;
input wrn;
input rdn;
input resetn;
input csn;
input clk;
reg [15:0] ina = 16'd0; //存储数据供 ARM 读
reg [15:0] inb = 16'd1;
reg [15:0] inc = 16'd2;
reg [15:0] ind = 16'd3;
reg [15:0] ine = 16'd4;
reg [15:0] inf = 16'd5;
reg [15:0] ing = 16'd6;
reg [15:0] inh = 16'd7;
reg [15:0] outa;
reg [15:0] outb;
reg [15:0] outc;
reg [15:0] outd;
reg [15:0] oute;
reg [15:0] outf;
reg [15:0] outg;
reg [15:0] outh;
wire rd;
wire wr;
reg [15:0] indata;
assign rd = !(csn & rdn); //get rd pulse ____|~~~~|______
assign wr = !(csn & wrn) ; //get wr pulse ____|~~~~|______
/*********当不进行读写操作时db=indata*********
*********当进行写操作时db=16'hzzzz**********
*********当进行读操作时db=indata**********/
assign db = rd? indata:16'hzzzz;
//write data, 根据地址线选择八个空间写入,每个空间16位
always @(negedge wr or negedge resetn)
begin
if(!resetn)begin
outa <= 16'h0000;
outb <= 16'h0000;
outc <= 16'h0000;
outd <= 16'h0000;
oute <= 16'h0000;
outf <= 16'h0000;
outg <= 16'h0000;
outh <= 16'h0000;
end else begin
case (ab)
3'b000:outa <= db;
3'b001:outb <= db;
3'b010:outc <= db;
3'b011:outd <= db;
3'b100:oute <= db;
3'b101:outf <= db;
3'b110:outg <= db;
3'b111:outh <= db;
default:;
endcase
end
end
//red data 根据地址线选择8个空间读取,每个空间 16位
always @(rd or !resetn)
begin
if(!resetn)indata <= 16'h0000;
else begin
case (ab)
3'b000:indata <= ina;
3'b001:indata <= inb;
3'b010:indata <= inc;
3'b011:indata <= ind;
3'b100:indata <= ine;
3'b101:indata <= inf;
3'b110:indata <= ing;
3'b111:indata <= inh;
default:;
endcase
end
end
endmodule