Xilinx FPGA:vivado SPI实现FLASH通信

一、实验要求

        要求使用SPI协议实现对flash芯片的页编程、读操作、页擦除等功能。

二、模块划分

大概的时序图:

三、程序设计
(1)接收端模块
`timescale 1ns / 1ps
module uart_rx(
   input                    sys_clk   ,
   input                    rst_n     ,
   (* MARK_DEBUG="true" *)input                    rx_data   ,
   (* MARK_DEBUG="true" *)output    reg[7:0]       uart_data ,
   (* MARK_DEBUG="true" *)output    reg            rx_done  
    );
    parameter               SYSCLK = 50_000_000 ;
    parameter               Baud   = 115200     ; 
    parameter               COUNT  = SYSCLK/Baud;
    parameter               MID    = COUNT/2    ;
    
    ///start_flag
    reg             rx_reg1 ;
    reg             rx_reg2 ;
    (* MARK_DEBUG="true" *)wire            start_flag ;
    
    always@(posedge sys_clk )
         if(!rst_n)begin
            rx_reg1 <= 1 ;
            rx_reg2 <= 1 ;
         end
         else
             begin
                  rx_reg1 <= rx_data  ;
                  rx_reg2 <= rx_reg1  ;
             end
    assign  start_flag = ~rx_reg1 & rx_reg2 ;
    
    /rx_flag
    (* MARK_DEBUG="true" *)reg               rx_flag  ;
    (* MARK_DEBUG="true" *)reg[4:0]          cnt_bit  ;
    (* MARK_DEBUG="true" *)reg[9:0]          cnt      ;
    
    always@(posedge sys_clk )
         if(!rst_n)
            rx_flag <= 0 ;
         else if ( start_flag == 1 )
            rx_flag <= 1 ;
         else if ( cnt_bit == 10 && cnt == MID - 1 )
            rx_flag <= 0 ;
         else
            rx_flag <= rx_flag ;
    
    //cnt
    always@(posedge sys_clk )
         if(!rst_n)
            cnt <= 0 ;
         else if ( rx_flag == 1 )begin
              if ( cnt == COUNT - 1 )
                   cnt <= 0 ;
              else
                   cnt <= cnt +1 ;
         end
         else
         cnt <= 0 ;
  
  /cnt_bit
    always@(posedge sys_clk )
         if(!rst_n)
            cnt_bit <= 0 ;
         else if ( rx_flag == 1 )begin
              if ( cnt == COUNT - 1 )begin
                  if( cnt_bit == 10 )
                      cnt_bit <= 0 ;
                  else
                      cnt_bit <= cnt_bit +1 ;
              end
              else
              cnt_bit <= cnt_bit ;
         end
         else
         cnt_bit <= 0 ;
         
         
            
  
  ///data_reg                         
     (* MARK_DEBUG="true" *)reg[8:0]         data_reg  ;  //data_reg:01234567 [8]
     always@(posedge sys_clk )     //cnt_bit:[0]12345678[9][10]
          if(!rst_n)
             data_reg <= 0 ;
          else if ( rx_flag == 1 )begin
               if ( cnt_bit > 0 && cnt_bit < 10 && cnt == MID - 1)
                    data_reg[cnt_bit - 1 ] <= rx_data  ;
               else
                    data_reg <= data_reg  ;
          end
          else
          data_reg <= 0 ;
 
 check
   (* MARK_DEBUG="true" *)reg                  check   ;
   always@(posedge sys_clk )
        if(!rst_n)
           check <= 0 ;
        else if ( rx_flag == 1 )begin
             if ( cnt_bit == 10 )
                 check <= ^data_reg  ;
             else
                 check <= 0 ;
        end
        else
        check <= 0 ;
 
 uart_data
 parameter            MODE_CHECK = 0 ;
 
    always@(posedge sys_clk )
         if(!rst_n)
            uart_data <= 0 ;
         else if ( rx_flag == 1 )begin
              if ( cnt_bit == 10 && cnt == 10 && check == MODE_CHECK)
                   uart_data <= data_reg[7:0] ;
              else
                   uart_data <= uart_data  ;
         end
         else
         uart_data <= uart_data  ;
 
 rx_done
 
     always@(posedge sys_clk )
          if(!rst_n)
             rx_done <= 0 ;
          else if ( rx_flag == 1 )begin
               if ( cnt_bit == 10 && cnt == MID/2 - 1 )
                    rx_done <= 1 ;
               else
                    rx_done <= 0 ;
          end
          else
          rx_done <= 0 ;
        
 
 

    
endmodule
(2)cmd模块
`timescale 1ns / 1ps
长度 指令 地址 数据
/* 这个模块的功能是把接收到的数据放在寄存器里,这个模块的功能也可以由fifo和ram完成

*/
module cmd_data(
    input                      clk      ,
    input                      rst_n    ,
    (* MARK_DEBUG="true" *)input       [7:0]          data_in  ,
    (* MARK_DEBUG="true" *)input                      rx_done  ,
    (* MARK_DEBUG="true" *)output     reg             spi_start,
    (* MARK_DEBUG="true" *)output     reg [7:0]       cmd      ,
    (* MARK_DEBUG="true" *)output     reg [7:0]       length   ,//长度
    (* MARK_DEBUG="true" *)output     reg [23:0]      addr     ,//地址
    (* MARK_DEBUG="true" *)output     reg [7:0]       data_out 
    );
    parameter               idle  =   1  ;
    parameter               s0    =   2  ;//长度
    parameter               s1    =   3  ;//指令
    parameter               s2    =   4  ;//地址
    parameter               s3    =   5  ;//地址
    parameter               s4    =   6  ;//地址
    parameter               s5    =   7  ;//数据
    
    (* MARK_DEBUG="true" *)reg[3:0]                 cur_state    ;
    (* MARK_DEBUG="true" *)reg[3:0]                 next_state   ;
    
    state1
    always@(posedge clk)
         if(!rst_n)
            cur_state <= idle ;
         else
            cur_state <= next_state ;
    
    ///state2
    always@(*)
           case(cur_state)
                idle :
                      begin
             
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值