基于FPGA的flash读写操作-S29GL064N-DE2-115

该博客围绕FPGA板及flash外设展开实验。实验要求利用二者编写代码,实现按键写入、断电验证、数据显示及擦除功能。介绍了实验原理,包括地址扇区选择、总线操作、操作指令和时序图。给出实验代码模块,展示了SignalTap仿真图和实物图验证实验效果。


前言:
本文主要介绍了集成电路EDA这门课程的相关实验及代码。使用的软件是Quartus Ⅱ,该实验使用fpga芯片为cyclone IV EP4CE115F29C7。

FPGA内板载flash芯片没有使用spi-flash进行操作,而是单纯使用S29GL064N的flash芯片,所有引脚直接连接到fpga板块。

1. 实验要求

利用FPGA板及flash外设,编写代码实现按键按下写入flash,并且断电验证是否写入成功,读出的数据显示在lcd1602显示屏上,并且可以实现擦除数据功能。

2. 实验原理

通过阅读S29GL064N的flash芯片手册,再对比板载芯片名称,我们知道该flash属于S29GL064N (Model 04)。
其中引脚:
	22位地址线输入
	8/16位数据线
	其他一些功能配置位

下图为S29GL064N (Model 04)的引脚图:
在这里插入图片描述

下图为DE2-115中flash的连线图:
我们可以看到:
地址位多了一位A-1,变为23位,这样我们选择地址的时候就需要注意一下,最低位为A-1,自己随意配置即可
数据位使用了8位

在这里插入图片描述

2.1 选择地址扇区

由flash手册p25页可知整个flash分为134个扇区,写入读出数据的话都需要先确定扇区地址,比如在该实验中我们操作读写扇区SA45,得知地址位为: 0100110xxx
选择完扇区后,我们再从中任意选择一个地址使用: 比如23’010 0110 0000 0000 0000 0001 即23’h260001,该实验都在这个地址操作。

在这里插入图片描述

2.2 设备总线操作

选择完地址后,我们就需要查看如何对flash进行读写操作了。
在手册p16页中我们可以找到flash设备总线操作:
在这里插入图片描述

  1. 通过该图我们得知: 读写操作的一些引脚简单配置
  2. 接下来我们简单阅读下表格下面的一些解释: 比如8.3 Writing Commands/Command Sequences:从中我们得知第40页上的Word程序命令序列包含了关于使用标准和解锁旁路命令序列向设备编程数据的详细信息。
  3. 跳转到p40的10.4.1 Word Program Command Sequence:
    由该节内容得知: 编程是一个四总线循环的操作。程序命令序列由写两个解锁写周期启动,然后是程序设置命令。然后写入程序地址和数据,进而启动嵌入式程序算法。
    第47页的表17和第50页的表19分别显示了字程序命令序列的地址和数据要求。
  4. 我们跳转到第47页
    可以看到是一些命令定义,不过我们的数据位为8位,所以找到p50页x8 Mode,这里就是我们需要找到的操作指令表。

2.3 查看操作指令

在上节中,我们找到了flash操作指令表:
在这里插入图片描述
其中划线的4个指令我们都是需要使用到的。
其中RA/PA为目标地址,PD/RD为数据。
很容易看出:
读操作不需要指令,直接输入需要读写的地址,并配置好目录2.2节的总线要求即可。
写操作与擦除指令都需要先往固定的地址写入固定的指令才能启动。

2.4 查看时序图

读时序(p62)如图:
在这里插入图片描述

写时序(p65)如图:
可以看到,在写入操作完成后,RY脚产生了一段时间的低脉冲,我们可以根据这个来判断是否执行完成过该写入操作。
在这里插入图片描述
擦除时序(p66)如图:
在这里插入图片描述

3. 实验代码

3.1 顶层模块flash

调用flash_control模块实现flash读写操作,读出数据显示在lcd1602模块上,并通过uart_tx串口发送模块发送给pc端,key_filiter为按键滤波器。

module flash (
    input   wire        sys_clk         ,// 时钟信号
    input   wire        sys_rst_n       ,// 复位信号
    input   wire        wr              ,//写按键
    input   wire        rd              ,//读按键
    input   wire        rset            ,//扇区擦除按键
    input   wire        fl_ry_by        ,//忙碌位,初始1为高,当写入完成后输出一段时间的低脉冲作为写入成功的判断    
    
    output  wire        fl_ce           ,//芯片使能输入,低电平有效
    output  wire        fl_oe           ,//输出使能,低电平读出有效
    output  wire        fl_we           ,//输入使能,低电平写入有效
    output  wire        fl_reset        ,//复位引脚输入,低电平复位        
    output  wire        fl_wp           ,//硬件写保护输入,默认为1即可  
    output  wire [22:0] fl_addr         ,//地址链接到flash的23个地址脚
    output  wire        tx              ,//传输给串口的数据
    output 	wire [7:0]  lcd_dat		    ,//LCD的8位数据口
    output  wire		lcd_rs		    ,//数据命令选择信号,高电平表示数据,低电平表示命令
    output	wire		lcd_rw		    ,//读写标志,高电平表示读,低电平表示写,该程序我们只对液晶屏进行写操作
    output	wire		lcd_en		    ,//LCD的控制脚
    
    inout   wire [7:0]  fl_dq           //数据输入/输出,链接到flash的8个地址脚
);

parameter   UART_BPS    =   'd115200,         //串口波特率
            CLK_FREQ    =   'd50_000_000;    //时钟频率

//reg  [2:0]   cmd;
wire [22:0] addr;      //地址
wire [7:0]  data_in;   //数据输入
wire [7:0]  pi_data;   //模块输入的8bit数据
wire        pi_flag;   //并行数据有效标志信号
wire [7:0]  dat_out;
wire [7:0]  lcd_out;   //读取的数据给lcd1602 
wire        wr_flag;
wire        rd_flag;
wire        rset_flag;     

assign addr = 23'h260001;   //23'010 0110 0000 0000 0000 0001
assign data_in = 8'h5a;  
    
flash_control flash_control_inst(
    .sys_clk  (sys_clk  )       ,// 时钟信号
    .sys_rst_n(sys_rst_n)       ,// 复位信号
    .wr_flag  (wr_flag  )       ,//按下,写入数据一次
    .rd_flag  (rd_flag  )       ,//按下,读出数据一次
    .rset_flag(rset_flag )      ,//
    .addr     (addr     )       ,//写入/读出数据的地址
    .data_in  (data_in  )       ,//需要写入的数据
    .fl_ry_by (fl_ry_by )       ,//忙碌位,初始1为高,当写入完成后输出一段时间的低脉冲作为写入成功的判断
    
    .fl_ce    (fl_ce    )       ,//芯片使能输入,低电平有效
    .fl_oe    (fl_oe    )       ,//输出使能,低电平读出有效
    .fl_we    (fl_we    )       ,//输入使能,低电平写入有效
    .fl_reset (fl_reset )       ,//复位引脚输入,低电平复位    
    .fl_wp    (fl_wp    )       ,//硬件写保护输入,默认为1即可
    .fl_addr  (fl_addr  )       ,//地址链接到flash的23个地址脚
    .dat_out  (dat_out  )       ,//读取数据输出给串口
    .pi_flag  (pi_flag  )       ,//打印数据到串口标志位
    .lcd_out  (lcd_out  )       ,//读取的数据给lcd1602                                 
    .fl_dq    (fl_dq    )        //数据输入/输出
);


lcd1602 lcd1602_inst( 
	.sys_clk	(sys_clk	),//系统时钟输入50M
	.sys_rst_n	(sys_rst_n	),//复位,低电平有效
 	.data       (lcd_out    ),

    .lcd_dat	(lcd_dat	),//LCD的8位数据口
 	.lcd_rs		(lcd_rs		),//数据命令选择信号,高电平表示数据,低电平表示命令
 	.lcd_rw		(lcd_rw		),//读写标志,高电平表示读,低电平表示写,该程序我们只对液晶屏进行写操作
 	.lcd_en		(lcd_en		) //LCD的控制脚
 );

uart_tx
#(
    .UART_BPS(UART_BPS), //串口波特率
    .CLK_FREQ(CLK_FREQ) //时钟频率
)
uart_tx_inst
(
    .sys_clk  (sys_clk  )   ,   //系统时钟50MHz
    .sys_rst_n(sys_rst_n)   ,   //全局复位
    .pi_data  (dat_out  )   ,   //模块输入的8bit数据
    .pi_flag  (pi_flag  )   ,   //并行数据有效标志信号

    .tx       (tx       )       //串转并后的1bit数据
);

key_filiter key_filiter_inst0
(
	.sys_clk   (sys_clk  )  ,
	.sys_rst_n (sys_rst_n)  ,
	.key_in    (wr      )  ,
	.key_flag  (wr_flag)
);
key_filiter key_filiter_inst1
(
	.sys_clk   (sys_clk  )  ,
	.sys_rst_n (sys_rst_n)  ,
	.key_in    (rd      )  ,
	.key_flag  (rd_flag)
);
key_filiter key_filiter_inst2
(
	.sys_clk   (sys_clk  )  ,
	.sys_rst_n (sys_rst_n)  ,
	.key_in    (rset      )  ,
	.key_flag  (rset_flag)
);

endmodule

3.2 flash读写操作模块flash_control

相关时序图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

module flash_control (
    input   wire        sys_clk         ,// 时钟信号
    input   wire        sys_rst_n       ,// 复位信号
    input   wire        wr_flag         ,//按下,写入数据一次
    input   wire        rd_flag         ,//按下,读出数据一次
    input   wire        rset_flag       ,//按下,擦除
    input   wire [22:0] addr            ,//写入/读出数据的地址
    input   wire [7:0]  data_in         ,//需要写入的数据
    input   wire        fl_ry_by        ,//忙碌位,初始1为高,当写入完成后输出一段时间的低脉冲作为写入成功的判断
           
    output  reg         fl_ce           ,//芯片使能输入,低电平有效
    output  reg         fl_oe           ,//输出使能,低电平读出有效
    output  reg         fl_we           ,//输入使能,低电平写入有效
    output  wire        fl_reset        ,//复位引脚输入,低电平复位    
    output  wire        fl_wp           ,//硬件写保护输
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值