基于FPGA 外置qspi Flash的读写

这篇具有很好参考价值的文章主要介绍了基于FPGA 外置qspi Flash的读写。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.写在前面

FPGA内部不具有掉电存储程序的功能,所以都需要外置的flash存储器来存储程序,上电后从flash加载程序到FPGA中运行。外置的flash可以存储程序,也可以存储任何用户数据,可以更有效的利用flash的存储空间。

值得注意的是,用于存储程序的flash和fpga连接用的是fpga的专用引脚,flash时钟信号不可以直接驱动,这个信号是fpga硬件直接管理的,需要使用原语才可以驱动时钟信号,这个原语叫STARTUPE2。

STARTUPE2 #(
.PROG_USR("FALSE"), // Activate program event security feature. Requires encrypted bitstreams.
.SIM_CCLK_FREQ(0.0) // Set the Configuration Clock Frequency(ns) for simulation
)
STARTUPE2_inst
(
.CFGCLK(), // 1-bit output: Configuration main clock output
.CFGMCLK(), // 1-bit output: Configuration internal oscillator clock output
.EOS(), // 1-bit output: Active high output signal indicating the End Of Startup.
.PREQ(), // 1-bit output: PROGRAM request to fabric output
.CLK(0), // 1-bit input: User start-up clock input
.GSR(0), // 1-bit input: Global Set/Reset input (GSR cannot be used for the port name)
.GTS(0), // 1-bit input: Global 3-state input (GTS cannot be used for the port name)
.KEYCLEARB(1), // 1-bit input: Clear AES Decrypter Key input from Battery-Backed RAM (BBRAM)
.PACK(1), // 1-bit input: PROGRAM acknowledge input
.USRCCLKO(flash_clk), // 1-bit input: User CCLK input
.USRCCLKTS(0), // 1-bit input: User CCLK 3-state enable input
.USRDONEO(1), // 1-bit input: User DONE pin output control
.USRDONETS(1) // 1-bit input: User DONE 3-state enable output
)

里边的flash_clk就是要约束的flash时钟信号,通过这个原语才能约束用于配置程序的flash的时钟信号。

不想这么麻烦也可以,在硬件上再加一片flash接到通用管脚上就完了,但是想做远程程序更新功能就必须这么干,通过串口或者网口或者什么其他通信接口将要更新的程序发送至fpga,fpga存储空间不够的话就暂存到ddr或者外置sram里,再按顺序操作flash烧入,扯远了,有机会一定要搞一下这个功能肯定有用,只是我现在还不会写上位机。

2.FPGA实现qspi flash读写

前面扯了很多没用的,直接上源码,自己写的,为了省事没搞qspi只用了spi,智商感人的领导把时间全给硬件开发了,硬件平台搭了一年多,软件只给了3个月,交货前2个月才知道具体需求,之前全是含糊其辞,没办法全是赶工出来的,凑活看吧,改改就能用,你问我为啥敢吐槽,已经被辞了,项目干的甲方无比懊恼,钱都不想给了,领导肯定是没错的,所以嘛只能这样了,硬件做的一言难尽时间全耽误了硬件平台到我手里连4个月都没有中间还反复改硬件,硬件做不到了就拿程序填,硬件做的垃圾最后全是做软件的背了锅,所以最后只有我走人,做垃圾的还好好的呢,说多了直接上码,前面发的牢骚各位直接忽略。

顶层命令控制

///
/* Document info
document class : RES
module name    : flash
module purpose : n25q256 256byte per page
version        : V1.0
author         : mayidianzi
*/
///


module flash_ctrl(
   input  I_clk            , //  clk
   input  I_TEST_CLK       ,
   input  I_reset_n        , // module reset signal
   input  I_read_en        , 
   input  I_write_en       ,
   input  I_ID_en          ,
   input  I_erase_en       ,
   input [63:0] I_wr_data  ,
   input  I_wraddr_clear   ,
   input  I_rdaddr_clear   ,
   output reg O_flash_ready,
   output reg O_flash_end  ,
   input  I_SDO         , // flash D1信号     
   output O_SDI         , // flash D0信号 
   output O_SCK         , // flash SCK信号 
   output O_CS          ,
   input  I_flash_dq3   ,
   input  I_flash_dq2   ,
   output reg [63:0] O_rd_data,
   output reg [23:0] O_flash_id
    );
    
/  parameter set  \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\            
parameter READ_STATUS_REGISTER      = 16'h05_00,
           READ_ID                   = 48'h9F_00_00_00_00_00,
           WRITE_ENABLE              = 8'h06,
           BULK_ERASE                = 8'hC7;
parameter C_empty        = 8'd12,
          C_READID_idle   = 8'd0,
          C_READID_valid  = 8'd1,
          C_erase_idle    = 8'd2,
          C_erase_valid   = 8'd3,
          C_check_idle    = 8'd4,
          C_check_valid   = 8'd5,
          C_write_idle    = 8'd6,
          C_write_valid   = 8'd7,
          C_read_idle     = 8'd8,
          C_read_valid    = 8'd9,
          C_wrenable_idle = 8'd10,
          C_wrenable_valid= 8'd11;

  internal signal  \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
reg  [23:0] S_rd_addr        ;
reg  [23:0] S_wr_addr        ;
wire [95:0] S_rd_data       ;
reg  [63:0] S_wr_data        ;
wire [15:0] S_rd_status     ;
wire [95:0] READ_Command    ;
wire [95:0] WRITE_Command   ;
reg  [7:0] S_status          ;
reg  [1:0] S_w_e_flag        ;
reg  S_readID_start          ;
reg  S_read_start            ;
reg  S_write_start           ;
reg  S_erase_start           ;
reg  S_wrenable_start        ;
reg  S_check_start           ;
wire S_end                  ;
wire S_busy                 ;
wire [31:0] S_read_id       ;
reg  S_rdaddr_clear, S_wraddr_clear;

assign READ_Command = {8'h03,S_rd_addr,64'h00_00_00_00_00_00_00_00};
assign WRITE_Command = {8'h02,S_wr_addr,S_wr_data};
assign S_busy = S_rd_status[0]; 
      instance       \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
//ila_1 ila_1_i(
//.clk(I_clk),
//.probe0(S_rd_addr),
//.probe1(S_wr_addr),
//.probe2(I_wraddr_clear),
//.probe3(I_rdaddr_clear),
//.probe4(O_rd_data),
//.probe5(I_wr_data),
//.probe6(I_write_en)
//);

spi_port spi_port_i(
    .I_CLK(I_clk),
    .I_reset(I_reset_n),
    .I_wrcmd(WRITE_Command),
    .I_rdcmd(READ_Command),
    .I_erasecmd(BULK_ERASE),
    .I_rdIDcmd(READ_ID),
    .I_wrencmd(WRITE_ENABLE),
    .I_checkcmd(READ_STATUS_REGISTER),
    .I_wrstart(S_write_start),
    .I_rdstart(S_read_start),
    .I_readID_start(S_readID_start),
    .I_erase_start(S_erase_start),
    .I_wrenable_start(S_wrenable_start),
    .I_check_start(S_check_start),
    .I_SDO(I_SDO),
    .O_end(S_end),
    .O_SCK(O_SCK),
    .O_CS(O_CS),
    .O_SDI(O_SDI),
    .I_flash_dq2(I_flash_dq2),
    .I_flash_dq3(I_flash_dq3),
    .O_rddata(S_rd_data),
    .O_rd_status(S_rd_status),
    .O_rd_id(S_read_id)
   );
    
    main programe    \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

/*          config procedure        */
always @(posedge I_clk or negedge I_reset_n) 
begin
    if(!I_reset_n)
     begin
    S_status <= C_check_idle;
    O_flash_ready <= 0;
    S_w_e_flag    <= 0;
    O_flash_end <= 0;
   end
    else
     begin
   case(S_status)
         C_empty:
          begin           
           if(I_ID_en == 1)
             begin
               S_status <= C_READID_idle;
               O_flash_ready <= 0;
               O_flash_end <= 0;
             end
           else if(I_erase_en == 1)
             begin
                 S_status <= C_wrenable_idle;
               O_flash_ready <= 0;
               S_w_e_flag    <= 1;
               O_flash_end <= 0;
             end
           else if(I_read_en == 1)
             begin
                 S_status <= C_read_idle;
               O_flash_ready <= 0;
               O_flash_end <= 0;
             end
           else if(I_write_en == 1)
             begin
                 S_status <= C_wrenable_idle;
               O_flash_ready <= 0;
               S_w_e_flag    <= 2;
               O_flash_end <= 0;
             end
           else
             begin
                 O_flash_ready <= 1;
                 O_flash_end <= 0;
                 S_w_e_flag    <= 0;
                 S_status <= C_empty;
             end 
          end
           C_READID_idle:
            begin                
                 S_status <= C_READID_valid;
            end
           C_READID_valid:
            begin
                if(S_end == 1)
                 begin
                  S_status <= C_empty;
                  O_flash_end <= 1;
                 end
            end
           C_wrenable_idle:
            begin
                 S_status <= C_wrenable_valid;
            end
           C_wrenable_valid:
            begin
                if(S_end == 1)
                 begin
                     if(S_w_e_flag == 1)
                      S_status <= C_erase_idle;
                     else if(S_w_e_flag == 2)
                      S_status <= C_write_idle;
                 end                
            end
           C_erase_idle:
            begin
                S_status <= C_erase_valid;
            end
           C_erase_valid:
            begin
                if(S_end == 1)
                 begin
                  S_status <= C_check_idle;
                  S_w_e_flag <= 0;
                 end
            end
           C_check_idle:
            begin
                S_status <= C_check_valid;
            end
           C_check_valid:
            begin
                if(S_end == 1)
                  begin
                   if(S_busy == 1)
                     S_status <= C_check_idle;
                   else
                     begin
                       S_status <= C_empty;
                       O_flash_end <= 1;
                     end
                  end
            end
           C_read_idle:
            begin
                S_status <= C_read_valid;
            end
           C_read_valid:
            begin
                if(S_end == 1)
                 S_status <= C_check_idle;
            end
           C_write_idle:
            begin
                S_status <= C_write_valid;
            end
           C_write_valid:
            begin
                if(S_end == 1)
                 begin
                  S_status <= C_check_idle;
                  S_w_e_flag <= 0;
                 end
            end           
           default:
            begin
                S_status = C_empty;
                S_w_e_flag <= 0;
                O_flash_ready <= 0;
                O_flash_end <= 0;
            end
       endcase
   end
end

always @(posedge I_clk or negedge I_reset_n) 
begin
    if(!I_reset_n)
     begin
     S_readID_start <= 0;
     S_read_start   <= 0;
     S_write_start  <= 0;
     S_erase_start  <= 0;
     S_wrenable_start <= 0;
     S_check_start  <= 0;
     O_rd_data <= 0;
     O_flash_id <= 0;
     end
    else
     begin
         case(S_status)
             C_empty:
              begin
                  S_readID_start <= 0;
        S_read_start   <= 0;
        S_write_start  <= 0;
        S_erase_start  <= 0;
        S_wrenable_start <= 0;
        S_check_start  <= 0;
              end
           C_READID_idle:
            begin
                S_readID_start <= 1;
            end
           C_READID_valid:
            begin
                S_readID_start <= 0;
                if(S_end == 1)
                  O_flash_id <= S_read_id[23:0];
            end
           C_wrenable_idle:
            begin
                S_wrenable_start <= 1;
            end
           C_wrenable_valid:
            begin
                S_wrenable_start <= 0;
            end
           C_erase_idle:
            begin                
        S_erase_start  <= 1;
            end
           C_erase_valid:
            begin
                S_erase_start  <= 0;
            end
           C_check_idle:
            begin
                S_check_start  <= 1;
            end
           C_check_valid:
            begin
                S_check_start  <= 0;
            end
           C_read_idle:
            begin
                S_read_start   <= 1;
            end
           C_read_valid:
            begin
                S_read_start   <= 0;
        if(S_end == 1)
         O_rd_data <= S_rd_data[63:0];
            end
           C_write_idle:
            begin
                S_write_start <= 1;
                S_wr_data <= I_wr_data;
            end
           C_write_valid:
            begin
                S_write_start <= 0;
            end
           default:
            begin
                S_readID_start <= 0;
        S_read_start   <= 0;
        S_write_start  <= 0;
        S_erase_start  <= 0;
        S_wrenable_start <= 0;
        S_check_start  <= 0;
        O_rd_data <= 0;
        O_flash_id <= 0;
            end
       endcase
   end
end

always @(posedge I_clk or negedge I_reset_n)
begin
    if(!I_reset_n)
     begin
         S_wraddr_clear <= 0;
         S_rdaddr_clear <= 0;
     end
    else
     begin
        S_wraddr_clear <= I_wraddr_clear;
         S_rdaddr_clear <= I_rdaddr_clear;
     end
end

always @(posedge I_clk or negedge I_reset_n)
begin
    if(!I_reset_n)
     begin
         S_rd_addr <= 0;
     end
    else
     begin
       case(S_status)
            C_read_valid:
             if(S_end == 1)
              S_rd_addr <= S_rd_addr + 8;
            default:
             begin
              if(S_rdaddr_clear == 1)
                S_rd_addr <= 0;
             end
       endcase
     end
end

always @(posedge I_clk or negedge I_reset_n)
begin
    if(!I_reset_n)
     begin
         S_wr_addr <= 0;
     end
    else
     begin
       case(S_status)
            C_write_valid:
             if(S_end == 1)
              S_wr_addr <= S_wr_addr + 8;
            default:
             begin
              if(S_wraddr_clear == 1)
                S_wr_addr <= 0;
             end
       endcase
     end
end
endmodule

这里边的读写地址是自动管理的,每做一次读写操作自行增加,根据外部清地址信号来清零的,不想这么用的可以自行更改。我太懒不想改了。这个模块怎么操作可以自己写个仿真文件仿真一下,或者来问我,我会捡我想得起来的说说,不解释了就是太懒了。

通信底层spi文章来源地址https://www.toymoban.com/news/detail-519994.html

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2022/03/15 15:08:39
// Design Name: 
// Module Name: spi_wr_port
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module spi_port
   (
   input I_CLK,
   input I_reset,
   input[95:0] I_wrcmd,
   input[95:0] I_rdcmd,
   input[7:0] I_erasecmd,
   input[47:0] I_rdIDcmd,
   input[7:0] I_wrencmd,
   input[15:0] I_checkcmd,
   input I_wrstart,
   input I_rdstart,
   input I_readID_start,
   input I_erase_start,
   input I_wrenable_start,
   input I_check_start,
   input I_SDO,
   input I_flash_dq2,
   input I_flash_dq3,
   output reg O_end,
   output reg O_SCK,
   output reg O_CS,
   output reg O_SDI,
   output reg[95:0] O_rddata,
   output reg[15:0] O_rd_status,
   output reg[31:0] O_rd_id
   );
    
//
reg[47:0] S_rd_id;
reg[95:0] S_rddata;
reg[15:0] S_rd_status;
reg[15:0] S_state;
reg[31:0] S_cnt;

parameter READ_STATUS_REGISTER      = 16'h05_00,
           READ_ID                   = 48'h9F_00_00_00_00_00,
           WRITE_ENABLE              = 8'h06,
           BULK_ERASE                = 8'hC7;

parameter C_idle = 0,
          C_rdID_valid = 2,
          C_rdID_end  = 3,
          C_rdID_stop = 4,
          C_WEN_valid = 6,
          C_WEN_end  = 7,
          C_WEN_stop = 8,
          C_erase_valid = 10,
          C_erase_end  = 11,
          C_erase_stop = 12,
          C_check_valid = 14,
          C_check_end  = 15,
          C_check_stop = 16,
          C_rd_valid = 18,
          C_rd_end  = 19,
          C_rd_stop = 20,
          C_wr_valid = 22,
          C_wr_end  = 23,
          C_wr_stop = 24;    
                
//
//ila_1 ila_1_i(
//.clk(I_CLK),
//.probe0(O_rd_status),
//.probe1(O_rd_id),
//.probe2(O_CS),
//.probe3(O_SDI),
//.probe4(I_SDO),
//.probe5(O_SCK),
//.probe6(S_state),
//.probe7(I_readID_start),
//.probe8(O_rddata[63:0]),
//.probe9(I_rdcmd[95:64]),
//.probe10(I_wrcmd[95:64])
//);            
//
always @(posedge I_CLK or negedge I_reset)
begin
    if(!I_reset)
     begin
          S_state <= C_idle;
          S_cnt <= 0;
     end
    else
     begin
         case(S_state)
             C_idle:
              begin
                  S_cnt <= 0;
                  if(I_readID_start == 1)
                   S_state <= C_rdID_valid;    
                  else if(I_wrenable_start == 1)     
                   S_state <= C_WEN_valid;     
                  else if(I_erase_start == 1)
                   S_state <= C_erase_valid;
                  else if(I_check_start == 1)     
                   S_state <= C_check_valid;     
                  else if(I_rdstart == 1)
                   S_state <= C_rd_valid;
                  else if(I_wrstart == 1)
                   S_state <= C_wr_valid; 
              end
             C_rdID_valid:
              begin
                  if(S_cnt == 48*2)
                   begin
                    S_cnt <= 0;
                    S_state <= C_rdID_end;
                   end
                  else
                   S_cnt <= S_cnt + 1;
              end
             C_rdID_end:
              begin
                  if(S_cnt == 30)
                   begin
                    S_cnt <= 0;
                    S_state <= C_rdID_stop;
                   end
                  else
                   S_cnt <= S_cnt + 1;
              end
             C_rdID_stop:
              begin
                  S_state <= C_idle;
                  S_cnt <= 0;
              end
//
             C_WEN_valid:
              begin
                  if(S_cnt == 8*2)
                   begin
                    S_cnt <= 0;
                    S_state <= C_WEN_end;
                   end
                  else
                   S_cnt <= S_cnt + 1;
              end
             C_WEN_end:
              begin
                  if(S_cnt == 30)
                   begin
                    S_cnt <= 0;
                    S_state <= C_WEN_stop;
                   end
                  else
                   S_cnt <= S_cnt + 1;
              end
             C_WEN_stop:
              begin
                  S_state <= C_idle;
                  S_cnt <= 0;
              end
//
             C_erase_valid:
              begin
                  if(S_cnt == 8*2)
                   begin
                    S_cnt <= 0;
                    S_state <= C_erase_end;
                   end
                  else
                   S_cnt <= S_cnt + 1;
              end
             C_erase_end:
              begin
                  if(S_cnt == 30)
                   begin
                    S_cnt <= 0;
                    S_state <= C_erase_stop;
                   end
                  else
                   S_cnt <= S_cnt + 1;
              end
             C_erase_stop:
              begin
                  S_state <= C_idle;
                  S_cnt <= 0;
              end
//
             C_check_valid:
              begin
                  if(S_cnt == 16*2)
                   begin
                    S_cnt <= 0;
                    S_state <= C_check_end;
                   end
                  else
                   S_cnt <= S_cnt + 1;
              end
             C_check_end:
              begin
                  if(S_cnt == 30)
                   begin
                    S_cnt <= 0;
                    S_state <= C_check_stop;
                   end
                  else
                   S_cnt <= S_cnt + 1;
              end
             C_check_stop:
              begin
                  S_state <= C_idle;
                  S_cnt <= 0;
              end
//
             C_rd_valid:
              begin
                  if(S_cnt == 96*2)
                   begin
                    S_cnt <= 0;
                    S_state <= C_rd_end;
                   end
                  else
                   S_cnt <= S_cnt + 1;
              end
             C_rd_end:
              begin
                  if(S_cnt == 30)
                   begin
                    S_cnt <= 0;
                    S_state <= C_rd_stop;
                   end
                  else
                   S_cnt <= S_cnt + 1;
              end
             C_rd_stop:
              begin
                  S_state <= C_idle;
                  S_cnt <= 0;
              end
//
             C_wr_valid:
              begin
                  if(S_cnt == 96*2)
                   begin
                    S_cnt <= 0;
                    S_state <= C_wr_end;
                   end
                  else
                   S_cnt <= S_cnt + 1;
              end
             C_wr_end:
              begin
                  if(S_cnt == 30)
                   begin
                    S_cnt <= 0;
                    S_state <= C_wr_stop;
                   end
                  else
                   S_cnt <= S_cnt + 1;
              end
             C_wr_stop:
              begin
                  S_state <= C_idle;
                  S_cnt <= 0;
              end
             default:
              begin
                  S_state <= C_idle;
            S_cnt <= 0;
              end
      endcase
     end
end


always @(posedge I_CLK or negedge I_reset)
begin
    if(!I_reset)
     begin
          O_end <= 0;
      O_SCK <= 0;
      O_CS <= 1;
      O_SDI <= 0;
      S_rd_id <= 0;
      O_rd_id <= 0;
      S_rddata <= 0;
      O_rddata <= 0;
      S_rd_status <= 0;
      O_rd_status <= 0;
     end
    else
     begin
         case(S_state)
             C_idle:
              begin
                  O_end <= 0;    
                  O_SCK <= 0;
                  O_CS <= 1;
                  O_SDI <= 0;              
              end
//     
             C_rdID_valid:
              begin                  
                  O_CS <= 0;
                  case(S_cnt[0])
                      1'b0:
                       begin
                          O_SCK <= 0;
                          if(S_cnt == 48*2)
                           begin
                              O_SDI <= I_rdIDcmd[0];
                            end
                           else
                             begin
                              O_SDI <= I_rdIDcmd[47-S_cnt/2];
                             end
                       end
                      1'b1:
                       begin
                          O_SCK <= 1;
                          if(S_cnt == 48*2)
                            begin
                               O_SDI <= I_rdIDcmd[0];
                               S_rd_id[0] <= I_SDO;
                             end
                           else
                             begin
                               O_SDI <= I_rdIDcmd[47-S_cnt/2];
                               S_rd_id[47-S_cnt/2] <= I_SDO;
                             end
                       end
               endcase
              end
             C_rdID_end:
              begin
                  O_end <= 0;
                  O_CS <= 1;
                  O_SDI <= 0;
                  O_rd_id <= S_rd_id[39:8];
              end
             C_rdID_stop:
              begin
                  O_end <= 1;
                  O_CS <= 1;
                  O_SDI <= 0;
              end
//             
             C_WEN_valid:
              begin                  
                  O_CS <= 0;
                  case(S_cnt[0])
                      1'b0:
                       begin
                         O_SCK <= 0;
                         if(S_cnt == 8*2)
                            O_SDI <= I_wrencmd[0];
                         else
                           O_SDI <= I_wrencmd[7-S_cnt/2];
                       end
                      1'b1:
                       begin
                         O_SCK <= 1;
                         if(S_cnt == 8*2)
                            O_SDI <= I_wrencmd[0];
                         else
                           O_SDI <= I_wrencmd[7-S_cnt/2];
                       end
                  endcase
              end
             C_WEN_end:
              begin
                  O_end <= 0;
                  O_CS <= 1;
                  O_SDI <= 0;
              end
             C_WEN_stop:
              begin
                  O_end <= 1;
                  O_CS <= 1;
                  O_SDI <= 0;
              end
//     
             C_erase_valid:
              begin                  
                  O_CS <= 0;
                  case(S_cnt[0])
                      1'b0:
                       begin
                         O_SCK <= 0;
                         if(S_cnt == 8*2)
                            O_SDI <= I_erasecmd[0];
                         else
                           O_SDI <= I_erasecmd[7-S_cnt/2];
                       end
                      1'b1:
                       begin
                         O_SCK <= 1;
                         if(S_cnt == 8*2)
                            O_SDI <= I_erasecmd[0];
                         else
                           O_SDI <= I_erasecmd[7-S_cnt/2];
                       end
                  endcase
              end
             C_erase_end:
              begin
                  O_end <= 0;
                  O_CS <= 1;
                  O_SDI <= 0;
              end
             C_erase_stop:
              begin
                  O_end <= 1;
                  O_CS <= 1;
                  O_SDI <= 0;
              end
//     
             C_check_valid:
              begin                  
                  O_CS <= 0;
                  case(S_cnt[0])
                      1'b0:
                       begin
                           O_SCK <= 0;
                          if(S_cnt == 16*2)
                              O_SDI <= I_checkcmd[0];
                          else
                             O_SDI <= I_checkcmd[15-S_cnt/2];
                       end
                      1'b1:
                       begin
                           O_SCK <= 1;
                           if(S_cnt == 16*2)
                              O_SDI <= I_checkcmd[0];
                          else
                             O_SDI <= I_checkcmd[15-S_cnt/2];
                          if(S_cnt == 16*2)
                              S_rd_status[0] <= I_SDO;
                          else
                              S_rd_status[15-S_cnt/2] <= I_SDO;
                       end
               endcase
              end
             C_check_end:
              begin
                  O_end <= 0;
                  O_CS <= 1;
                  O_SDI <= 0;
                  O_rd_status <= S_rd_status;
              end
             C_check_stop:
              begin
                  O_end <= 1;
                  O_CS <= 1;
                  O_SDI <= 0;
              end
//              
             C_rd_valid:
              begin                  
                  O_CS <= 0;
                  case(S_cnt[0])
                      1'b0:
                       begin
                           O_SCK <= 0;
                           if(S_cnt == 96*2)
                              O_SDI <= I_rdcmd[0];
                          else
                             O_SDI <= I_rdcmd[95-S_cnt/2];
                       end
                      1'b1:
                       begin
                           O_SCK <= 1;
                           if(S_cnt == 96*2)
                              O_SDI <= I_rdcmd[0];
                          else
                             O_SDI <= I_rdcmd[95-S_cnt/2];
                          if(S_cnt == 96*2)
                              S_rddata[0] <= I_SDO;
                          else
                              S_rddata[95-S_cnt/2] <= I_SDO;
                        end
                   endcase
              end
             C_rd_end:
              begin
                  O_end <= 0;
                  O_CS <= 1;
                  O_SDI <= 0;
                  O_rddata <= S_rddata;
              end
             C_rd_stop:
              begin
                  O_end <= 1;
                  O_CS <= 1;
                  O_SDI <= 0;
              end
//              
             C_wr_valid:
              begin                  
                  O_CS <= 0;
                  case(S_cnt[0])
                      1'b0:
                       begin
                           O_SCK <= 0;
                           if(S_cnt == 96*2)
                              O_SDI <= I_wrcmd[0];
                          else
                             O_SDI <= I_wrcmd[95-S_cnt/2];
                       end
                      1'b1:
                       begin
                           O_SCK <= 1;
                           if(S_cnt == 96*2)
                              O_SDI <= I_wrcmd[0];
                          else
                             O_SDI <= I_wrcmd[95-S_cnt/2];
                       end
                  endcase
              end
             C_wr_end:
              begin
                  O_end <= 0;
                  O_CS <= 1;
                  O_SDI <= 0;
              end
             C_wr_stop:
              begin
                  O_end <= 1;
                  O_CS <= 1;
                  O_SDI <= 0;
              end
             default:
              begin
                  O_end <= 0;
        O_SCK <= 0;
        O_CS <= 1;
        O_SDI <= 0;
        S_rd_id <= 0;
        O_rd_id <= 0;
        S_rddata <= 0;
        O_rddata <= 0;
        S_rd_status <= 0;
        O_rd_status <= 0;
              end
      endcase
     end
end

endmodule

到了这里,关于基于FPGA 外置qspi Flash的读写的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【FPGA】SPI读写FLASH闪存

    通信原理 SPI也是以主从方式工作,通常需要四根线来完成数据的传输,分别是MISO MOSI CS SCLK。以下是这四根线代表的含义: MISO:主设备输入,从设备输出 MOSI:主设备输出,从设备输入 CS :片选信号,选择进行通信的从设备 SCLK:时钟线,由主设备产生给到从设备 SPI通信的

    2024年02月16日
    浏览(40)
  • FPGA模块——SPI协议(读写FLASH)

    芯片引脚图: 内部结构图: 存储区域总共分成了32块,每块64KB。每块又分成了16个部分,每个部分4KB。方便进行读取和局部操作。 电路设计 SPI的四种模式 这里使用这个模式: 主机和从机在时钟上升沿放入要输出的数据,在时钟下降沿读取要输入的数据。 8个时钟后交换一个

    2024年02月05日
    浏览(47)
  • FPGA怎么读写外部FLASH中的用户数据?(超详细)

    一、 软件平台与硬件平台 软件平台: 1、操作系统:Windows-8.1 2、开发套件:ISE14.7 3、仿真工具:ModelSim-10.4-SE 4、Matlab版本:Matlab2014b/Matlab2016a 硬件平台: 1、 FPGA型号:Xilinx公司的XC6SLX45-2CSG324 2、 Flash型号:WinBond公司的W25Q128BV   Quad SPI Flash存储器 提示:如果图片不清晰,请

    2024年02月07日
    浏览(43)
  • K7系列FPGA进行FLASH读写1——CCLK控制(STARTUPE2原语)

      最近的工作涉及对 FPGA 进行远程更新,也就是通过远程通信接口将 .bin 文件送到 FPGA,然后写入 FLASH,这样当 FPGA 重新上电后就可以执行更新后的程序了。因此第一步工作就是进行 FLASH 的读写控制。   然而如果尝试配置 FLASH 管脚时,会发现 CCLK 管脚是不可配置的,这

    2024年02月05日
    浏览(45)
  • 基于FPGA的flash远程UART更新的实现

    整体架构:micro blaze 、AXI UART 、AXI SPI; 语言:Verilog 、C 开发软件:vivdao2019.1 接口:UART 、SPI 、QUAD SPI uart 通用异步收发器(Universal Asynchronous Receiver/Transmitter:UART) UART首先将接收到的并行数据转换成串行数据来传输。消息帧从一个低位起始位开始,后面是5~8个数据位,一个可

    2024年02月09日
    浏览(43)
  • 基于FPGA的DS2431 DS2408读写操作(1-wire多器件)

    前段有个FPGA的开发任务,用到了ADI的DS2431和DS2408芯片,涉及到的难点有1-wire的读写操作和多个1-wire器件共用一根线进行通信,于是写一篇文章记录使用芯片中遇到的困难。 1-Wire总线是一种简单的信号交换架构,通过一条线路在主机与外围器件之间进行双向通信。所有的1-Wi

    2024年04月09日
    浏览(39)
  • FPGA实现基于SPI协议的Flash驱动控制(全擦除、页擦除、读数据、页写、连续写—地址写)

    本论文使用Verilog HDL硬件描述语言,结合野火可以FPGA征途Pro开发板,实现了SPI通信协议的全擦除,扇区擦除,读数据,页写,连续写的驱动设计。在 Altera Cyclone Ⅳ 芯片上采用“自顶向下”的模块化设计思想及 Verilog HDL 硬件描述语言,设计并实现串行外设接口(SPI)。在 Qu

    2024年02月12日
    浏览(49)
  • FPGA 固化 烧写进Flash!

    1、Generate Programming File  生成bit 流文件; 2、生成.msc文件: 双击Manage Configuration Project,弹出烧程序界面(同RAM); 双击Create PROM File (PROM File……),弹出新界面,分3个步骤; 根据芯片型号进行配置: 选择Xilinx Flash/PROM类型的设备 选择PROM family (为platform Flash);选择具体型

    2024年02月07日
    浏览(43)
  • FPGA使用SPI控制FLASH

    通过控制FLASH芯片进一步熟悉SPI协议 Flash 存储器 : Flash 存储器是一种非易失性存储器,它具有 RAM 和 ROM 的一些特点。与 ROM 类似,Flash 存储器的内容在断电时不会丢失,但与 RAM 类似,它可以通过编程来修改存储的内容。Flash 存储器通常用于嵌入式系统中存储程序代码、配置

    2024年03月19日
    浏览(54)
  • 提高Xilinx FPGA Flash下载速度

    最近在编写完FPGA逻辑,成功生成.bin文件后,可以通过Vivado软件进行设置,提高烧写速度。操作如下: (1)布局布线完成后,点击Open Implementation。 (2)点击Tool----- Edit Device Properties... (3)General -----Enable Bitstream Compression -----TRUE,选择压缩数据流,提高下载速度。 (4)Co

    2024年02月03日
    浏览(59)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包