ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

基于FPGA的SPI接口讲解——flash M25P28为例(3)

2020-01-11 13:39:44  阅读:219  来源: 互联网

标签:wire FPGA 为例 flash key output input reg


flash M25P128读操作


我们本次实验的内容是,对flash读一个字节的数据,系统框图如下:

在这里插入图片描述所用到的软硬件环境为:
硬件:锆石A4plus开发板
软件:quartus II 13.1
从技术手册中我们可以得到如下信息:
在这里插入图片描述
从上述信息中我们可以得到:
1、一个读指令操作可以读取整个flash的数据。
2、所利用的时序仍为SPI时序

时序图设计

同样我们也对flash的擦除时序进行一定程度的更改如下:
在这里插入图片描述
这里的时序图画的稍微乱点,但相信同学们有了前面的基础肯定可以学会。接下来便直接上代码。

flash_read模块的书写

这里的传统不说废话,直接上代码:

`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author       : zhangningning
// Email        : nnzhang1996@foxmail.com
// Website      : 
// Module Name  : flash_read.v
// Create Time  : 2020-01-09 12:52:26
// Editor       : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date             By              Version                 Change Description
// -----------------------------------------------------------------------
// XXXX       zhangningning          1.0                        Original
//  
// *********************************************************************************

module flash_read(
    input                   sclk            ,
    input                   rst_n           ,
    input                   key_flag        ,
    output  reg             cs_n            ,
    output  reg             sck             ,
    output  reg             sdi             ,
    input                   sdo             ,
    output  reg     [ 7:0]  data_out        , 
    output  reg             data_flag       
);

 
//========================================================================================\
//**************Define Parameter and  Internal Signals**********************************
//========================================================================================/
parameter   READ_INST   =   8'h03           ;
parameter   READ_ADDR   =   24'h00_03_21    ;

reg                 [ 4:0]  cnt_32          ;
reg                 [ 2:0]  cnt_state       ;
reg                 [ 1:0]  cnt_4           ;
reg                 [ 4:0]  bit_cnt         ;


 
//========================================================================================\
//**************     Main      Code        **********************************
//========================================================================================/
always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        cs_n                <=      1'b1;
    else if(key_flag == 1'b1)
        cs_n                <=      1'b0;
    else if(cnt_32 == 'd31 && cnt_state == 'd6)
        cs_n                <=      1'b1;
    else
        cs_n                <=      cs_n;

always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        cnt_32              <=      5'd0;
    else if(cnt_32 == 'd31)
        cnt_32              <=      5'd0;
    else if(cs_n == 1'b0)
        cnt_32              <=      cnt_32 + 1'b1; 
    else
        cnt_32              <=      5'd0;

always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        cnt_state           <=      3'd0;
    else if(cnt_state == 'd6 && cnt_32 == 'd31)
        cnt_state           <=      3'd0;
    else if(cnt_32 == 'd31)
        cnt_state           <=      cnt_state + 1'b1;
    else
        cnt_state           <=      cnt_state;
        
always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        cnt_4               <=      2'd0;
    else if(cnt_state >= 'd1 && cnt_state <= 'd5) 
        cnt_4               <=      cnt_4 + 1'b1;
    else
        cnt_4               <=      2'd0;
        
always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        sck                 <=      1'b0;
    else if(cnt_4 == 'd0)
        sck                 <=      1'b0;
    else if(cnt_4 == 'd2)
        sck                 <=      1'b1;
    else
        sck                 <=      sck;

always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        sdi                 <=      1'b0;
    else if(cnt_32 == 'd31 && cnt_state == 'd4)
        sdi                 <=      1'b0;
    else if(cnt_4 == 'd0 && cnt_state == 'd1)
        sdi                 <=     READ_INST[7-bit_cnt];  
    else if(cnt_4 == 'd0 &&cnt_state >= 3'd2 && cnt_state <= 3'd4)
        sdi                 <=     READ_ADDR[23-bit_cnt];
    else
        sdi                 <=      sdi;

always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        bit_cnt             <=      5'd0;
    else if(cnt_32 == 'd30 && cnt_state == 3'd1)
        bit_cnt             <=      5'd0;
    else if(cnt_32 == 'd30 && cnt_state == 3'd4)
        bit_cnt             <=      5'd0;
    else if(cnt_4 == 'd2 && cnt_state >= 3'd1 && cnt_state <= 3'd4)
        bit_cnt             <=      bit_cnt + 1'b1; 
    else
        bit_cnt             <=      bit_cnt;
        
always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        data_out            <=      8'd0; 
    else if(cnt_4 == 'd2 && cnt_state == 3'd5)
        data_out            <=      {data_out[6:0],sdo};
    else if(cnt_32 == 'd31 && cnt_state == 'd6)
        data_out            <=      8'd0;
    else 
        data_out            <=      data_out;

always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        data_flag           <=      1'b0;
    else if(cnt_state == 'd5 && cnt_32 == 'd30)
        data_flag           <=      1'b1;
    else
        data_flag           <=      1'b0;

endmodule

结合时序图和手册信息相信大家可以很容易理解上面代码的书写。

flash_read测试模块的代码

这里为了方便同学们调试代码,直接给出该模块的测试代码:

`timescale 1ns / 1ps
`define     CLOCK   20
// *********************************************************************************
// Project Name : OSXXXX
// Author       : zhangningning
// Email        : nnzhang1996@foxmail.com
// Website      : 
// Module Name  : flash_earse_tb.v
// Create Time  : 2020-01-08 19:57:13
// Editor       : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date             By              Version                 Change Description
// -----------------------------------------------------------------------
// XXXX       zhangningning          1.0                        Original
//  
// *********************************************************************************

module flash_read_tb();

reg                     sclk             ;
reg                     rst_n            ;
reg                     key_flag         ;
wire                    cs_n             ;
wire                    sck              ;
wire                    sdi              ;
wire            [ 7:0]  data_out         ; 
wire                    data_flag        ;

initial begin
    sclk                <=          1'b0;
    rst_n               <=          1'b0;
    key_flag            <=          1'b0;
    #(100*`CLOCK)
    rst_n               <=          1'b1;
    #(100*`CLOCK)
    key_flag            <=          1'b1;
    #(`CLOCK)
    key_flag            <=          1'b0;
    #(1000*`CLOCK)
    key_flag            <=          1'b1;
    #(`CLOCK)
    key_flag            <=          1'b0;
end
always      #(`CLOCK/2)     sclk    <=      ~sclk;

flash_read flash_read_inst(
    .sclk               (sclk               ),
    .rst_n              (rst_n              ),
    .key_flag           (key_flag           ),
    .cs_n               (cs_n               ),
    .sck                (sck                ),
    .sdi                (sdi                ),
    .sdo                (1'b1               ),
    .data_out           (data_out           ), 
    .data_flag          (data_flag          )
);

endmodule

其他模块的代码

为了方便同学们可以直接使用该代码,这里我们将所有的代码复制如下,整体的工程也可以进群自取:
key模块代码:

`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author       : zhangningning
// Email        : nnzhang1996@foxmail.com
// Website      : 
// Module Name  : key.v
// Create Time  : 2020-01-05 13:49:36
// Editor       : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date             By              Version                 Change Description
// -----------------------------------------------------------------------
// XXXX       zhangningning          1.0                        Original
//  
// *********************************************************************************

module key(
    input                       sclk            ,
    input                       rst_n           ,
    input                       key             ,
    output  reg                 key_o       
);
 
//========================================================================================\
//**************Define Parameter and  Internal Signals**********************************
//========================================================================================/
parameter       IDLE        =       4'b0001     ;    
parameter       S1          =       4'b0010     ;
parameter       S2          =       4'b0100     ;
parameter       S3          =       4'b1000     ;

reg                 [ 3:0]      state           ;
reg                 [ 9:0]      cnt             ;
reg                             key_r1          ;
reg                             key_r2          ;
reg                             key_r3          ;
reg                             nege_flag       ;
reg                             pose_flag       ;
 
//========================================================================================\
//**************     Main      Code        **********************************
//========================================================================================/
always @(posedge sclk)
    key_r1          <=      key;

always @(posedge sclk)
    key_r2          <=      key_r1;

always @(posedge sclk)
    key_r3          <=      key_r2;

always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        nege_flag       <=      1'b0;
    else if(key_r3 == 1'b1 && key_r2 == 1'b0)
        nege_flag       <=      1'b1;
    else
        nege_flag       <=      1'b0;

always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        pose_flag       <=      1'b0;
    else if(key_r3 == 1'b0 && key_r2 == 1'b1) 
        pose_flag       <=      1'b1;
    else
        pose_flag       <=      1'b0;

always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        state           <=      IDLE;
    else case(state)
        IDLE    :   if(nege_flag == 1'b1)
                        state           <=      S1;
                    else
                        state           <=      IDLE;                        
        S1      :   if(cnt == 10'd999)
                        state           <=      S2;
                    else if(pose_flag == 1'b1)
                        state           <=      IDLE;
                    else
                        state           <=      S1;                        
        S2      :   if(pose_flag == 1'b1)
                        state           <=      S3;
                    else
                        state           <=      S2;                        
        S3      :   if(cnt == 10'd999)
                        state           <=      IDLE;
                    else if(nege_flag == 1'b1)
                        state           <=      S2;
                    else
                        state           <=      S3;
                        
        default :   state           <=      IDLE;
    endcase

always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        cnt             <=      10'd0;
    else if(state != S1 && state != S3)
        cnt             <=      10'd0;
    else
        cnt             <=      cnt + 1'b1;

always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        key_o           <=      1'b0;
    else if(state == S1 && cnt == 10'd999) 
        key_o           <=      1'b1;
    else
        key_o           <=      1'b0;

endmodule

top模块:

`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author       : zhangningning
// Email        : nnzhang1996@foxmail.com
// Website      : 
// Module Name  : top.v
// Create Time  : 2020-01-08 21:18:52
// Editor       : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date             By              Version                 Change Description
// -----------------------------------------------------------------------
// XXXX       zhangningning          1.0                        Original
//  
// *********************************************************************************

module top(
    input                   sclk            ,
    input                   rst_n           ,
    input                   key             ,
    output  wire            cs_n            ,
    output  wire            sck             ,
    output  wire            sdi             ,
    input                   sdo             ,
    output  reg     [ 7:0]  led
);
 
//========================================================================================\
//**************Define Parameter and  Internal Signals**********************************
//========================================================================================/
wire                        key_flag        ;
wire                [ 7:0]  data_out        ; 
wire                        data_flag       ;

 
//========================================================================================\
//**************     Main      Code        **********************************
//========================================================================================/
always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        led             <=      8'd0;
    else if(data_flag == 1'b1)
        led             <=      data_out;
    else
        led             <=      led;

key key_inst(
    .sclk                   (sclk                   ),
    .rst_n                  (rst_n                  ),
    .key                    (~key                   ),
    .key_o                  (key_flag               )
);

flash_read flash_read_inst(
    .sclk                   (sclk                   ),
    .rst_n                  (rst_n                  ),
    .key_flag               (key_flag               ),
    .cs_n                   (cs_n                   ),
    .sck                    (sck                    ),
    .sdi                    (sdi                    ),
	.sdo                    (sdo                    ),
    .data_out               (data_out               ), 
    .data_flag              (data_flag              )
);

endmodule 

实验结果

这里的实验结果就是我们把上一篇文章中写入flash的数据读出并且显示再led上面,实验结果证明了我们flash读写操作的正确性。

结束语

创作不易,认为文章有帮助的同学们可以收藏点赞支持。(工程也都在群中)对文章有什么看法或者需要更近一步交流的同学,可以加入下面的群:
在这里插入图片描述

朽月 发布了12 篇原创文章 · 获赞 2 · 访问量 326 私信 关注

标签:wire,FPGA,为例,flash,key,output,input,reg
来源: https://blog.csdn.net/zhangningning1996/article/details/103935670

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有