xilinx在线升级+flash操作+N25Q128

xilinx在线升级+flash操作+N25Q128

 

因为使用xdc升级跳转方式,实际测试升级过程中无法回退版本,开始了使用ICAP方式来进行跳转

 

Flash操作:

说明:

 

擦除操作:收到擦除start命令--->读ID号匹配手册上的ID--->如果读ID成功--->开始进行擦除操作--->擦除一个块--->读状态寄存器不忙--->循环进行擦除操作

--->直到60个块擦完后--->IDLE

 

写操作:收到写start命令--->读ID号匹配手册上的ID--->如果读ID成功--->开始进行写操作--->1页写完后--->读状态寄存器不忙--->读出当前写入页数据--->循环写入读出(可验证数据是否写入)

--->直到4页完且读完--->IDLE

 

有的flash第一次擦不成功,所以得加一下读ID成功操作,

实际板子上使用:

module flash_top( // input wire       sys_clk_p,    //system clock positive// input wire       sys_clk_n,    //system clock negative input             clk   ,    input wire       rst_n ,       //reset ,low active    input           erase_start,input           write_start,input            fl_data_en ,input    [7:0]    fl_data    ,output      erase_completed,  //仿真output    four_pp_completed,//仿真input cmd_reply_clear_finish,input               miso    ,// output              sck     ,output              mosi    ,output              cs_n        );// wire    erase_completed;//调试// wire  four_pp_completed;//调试wire sck;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_spi (.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(1'b0),                       // 1-bit input: User start-up clock input.GSR(1'b0),                       // 1-bit input: Global Set/Reset input (GSR cannot be used for the port name).GTS(1'b0),                       // 1-bit input: Global 3-state input (GTS cannot be used for the port name).KEYCLEARB(1'b1),                 // 1-bit input: Clear AES Decrypter Key input from Battery-Backed RAM (BBRAM).PACK(1'b1),                      // 1-bit input: PROGRAM acknowledge input.USRCCLKO(sck),                   // 1-bit input: User CCLK input.USRCCLKTS(1'b0),                 // 1-bit input: User CCLK 3-state enable input.USRDONEO(1'b1),                  // 1-bit input: User DONE pin output control.USRDONETS(1'b1)                  // 1-bit input: User DONE 3-state enable output
   );// reg [5:0]     cnt_clk=0;
// wire      add_cnt_clk;
// wire      end_cnt_clk;
// always@(posedge sys_clk or negedge rst_n)begin// if(rst_n==1'b0)begin// cnt_clk<=0;// end// else if(add_cnt_clk)begin// if(end_cnt_clk)// cnt_clk<=0;// else// cnt_clk<=cnt_clk+1;// end 
// end 
// assign add_cnt_clk = 1;
// assign end_cnt_clk = add_cnt_clk && cnt_clk == 2-1;// reg clk;//100MHz
// always@(posedge sys_clk)begin// if(cnt_clk<1)begin// clk<=1'b1;// end// else begin// clk<=1'b0;// end 
// end   // wire clk;
// assign clk=sys_clk;// wire clk_out1;
// wire clk_out2;// clk_wiz_0 clk_wiz_0_uut// (// .clk_out1(clk_out1),     // output clk_out1// .clk_out2(clk_out2),     // output clk_out2// .reset(~rst_n), // input reset// .locked(locked),       // output locked// .clk_in1(sys_clk));      // input clk_in1// wire clk;
// assign clk=clk_out2 & locked;//===========================vio=========================================
// wire earse_start_vio;
// wire write_start_vio;
// wire read_start_vio;
// vio_0 uut_vio_0 (// .clk(clk),                    // .probe_out0(earse_start_vio), // .probe_out1(write_start_vio),// .probe_out2(read_start_vio)  
// ); // reg earse_start_r1;
// always@(posedge clk)begin
// earse_start_r1<=earse_start_vio;
// end// wire   earse_edge;
// assign earse_edge= earse_start_r1 & ~earse_start_vio;// reg write_start_r1;
// always@(posedge clk)begin
// write_start_r1<=write_start_vio;
// end// wire   write_edge;
// assign write_edge= write_start_r1 & ~write_start_vio;// reg read_start_r1;
// always@(posedge clk)begin
// read_start_r1<=read_start_vio;
// end// wire   read_edge;
// assign read_edge= read_start_r1 & ~read_start_vio;    
//===========================test=========================================                             
// reg         I_fl_data_en ;        
// wire        end_cnt0;// always @(posedge clk or negedge rst_n)begin // if(!rst_n)begin// I_fl_data_en <= 0;// end// else if(write_start) begin //仿真// else if(write_edge)begin     //实际// I_fl_data_en <= 1;// end // else if(end_cnt0) begin// I_fl_data_en <= 0;// end     
// end // reg [15:0] cnt0;
// wire      add_cnt0;// always@(posedge clk or negedge rst_n)begin// if(rst_n==1'b0)begin// cnt0<='d0;// end// else if(add_cnt0)begin// if(end_cnt0)// cnt0<=0;// else// cnt0<=cnt0+1;// end 
// end 
// assign add_cnt0 = I_fl_data_en;
// assign end_cnt0 = add_cnt0 && cnt0 == 1024-1;//256-1;//
(*mark_debug="true", dont_touch="true"*)wire        [7:0]   wr_rd_state_spi_out ;(*mark_debug="true", dont_touch="true"*)wire        [7:0]   dout                ;//读取数据(*mark_debug="true", dont_touch="true"*)wire                dout_vld            ;//数据有效(*mark_debug="true", dont_touch="true"*)wire                spi_vld             ;(*mark_debug="true", dont_touch="true"*)wire                en                  ;(*mark_debug="true", dont_touch="true"*)wire        [7:0]   spi_dout            ;//读取数据进入fifo                   (*mark_debug="true", dont_touch="true"*)wire                spi_one_byte_done   ; wr_control u_wr_control( /*input                  */.clk          (clk              ),/*input                  */.rst_n         (rst_n            ),// `ifdef simulation// `elsif.erase_start  (erase_start),// erase_start 仿真.write_start  (write_start),//write_start// .erase_start  (earse_edge  ),//erase_start 调试// .write_start  (write_edge  ),//write_start
                            .erase_completed(erase_completed),.four_pp_completed(four_pp_completed),.cmd_reply_clear_finish(cmd_reply_clear_finish),.read_start(read_edge),// `endif    /*input               */.spi_one_byte_done (spi_one_byte_done          ),/*input               */.din_vld   ( fl_data_en   ),//   (I_fl_data_en),//(rx_byte_vld      ),//
     /*input        [7:0]  */.din       ( fl_data),//   (cnt0[7:0]   ),//(rx_byte          ),//
/*input        [7:0]  */.read_data       (spi_dout         ),/*output    reg [7:0] */.wr_rd_state_spi_out  (wr_rd_state_spi_out           ),/*output      [7:0]   */.read_flash_data_fifo_out  (dout             ),/*output              */.read_flash_data_fifo_out_vld  (dout_vld         ),/*output              */.en           (en               ),/*output              */.spi_vld      (spi_vld          ) );spi_master u_spi_master( /*input               */.clk        (clk            ),/*input               */.rst_n      (rst_n          ),/*input               */.en         (en             ),/*input       [1:0]   */.spi_mode   (2'b00          ),/*input               */.spi_vld    (spi_vld        ),/*input        [7:0]  */.spi_din    (wr_rd_state_spi_out),//写入数据/*input               */.miso       (miso           ),/*output    reg       */.sck        (sck            ),/*output  reg         */.cs_n       (cs_n           ),/*output              */.mosi       (mosi           ),/*output  reg [7:0]   */.spi_dout   (spi_dout       ),//读取数据/*output  reg         */.busy       (         ),/*output              */.spi_one_byte_done  (spi_one_byte_done        ) );                                 endmodule 
flash_top

 

`include "param.v"
module wr_control( input                  clk        ,input                  rst_n      ,input           erase_start,
(*mark_debug="true", dont_touch="true"*)output   erase_completed,input           write_start,
(*mark_debug="true", dont_touch="true"*)output  reg four_pp_completed,input cmd_reply_clear_finish,input             read_start,input                 spi_one_byte_done     ,input        [7:0]     din          ,input                  din_vld      ,input        [7:0]      read_data       ,output    reg [7:0]     wr_rd_state_spi_out      ,output      [7:0]     read_flash_data_fifo_out        ,output                read_flash_data_fifo_out_vld    ,output                en          ,output  reg           spi_vld      );                                 //参数定义    parameter DATA_WIDTH   = 8'd12;//8'd15;parameter DATA_LENGTH  = 1024;//'d10240;    //中间信号定义    reg                 flag            ;reg                 flag0           ;reg                 en_r            ;wire                en_dge_n        ;reg                 read_data_vld        ;//例化中间信号wire read_id       ;wire read_rdsr     ;wire read_data_flag;wire read_only_data_flag;wire busy_read;wire                data_req        ;wire    [7:0]       write_state_spi_out           ;wire    [7:0]       read_state_spi_out           ;wire    [1:0]       en_             ;wire                read_spi_one_byte_vld      ;wire                write_done      ;wire                read_done       ;wire                rxf_rdreq       ;wire                rxf_wrreq       ;wire                rxf_empty       ;wire                rxf_full        ;wire    [7:0]       rxf_dout        ;// wire    [11:0]       rxf_usedw       ; wire    [DATA_WIDTH-1:0]       rxf_usedw       ; wire                txf_rdreq       ;wire                txf_wrreq       ;
(*mark_debug="true", dont_touch="true"*)    wire                txf_empty       ;wire                txf_full        ;
// (*mark_debug="true", dont_touch="true"*)    wire    [11:0]       txf_usedw    ;   wire    [DATA_WIDTH-1:0]       txf_usedw    ;            reg [7:0] din_fifo;
reg  din_fifo_vld; //标志信号//flag 1: uart 发送数据 0:停止发送数据always @(posedge clk or negedge rst_n)begin if(!rst_n)beginflag <= 0;end else if(txf_usedw >= DATA_LENGTH-1)begin // else if(txf_usedw >='d1023)begin          flag <= 1;end else if(txf_empty)begin flag <= 0;end end//flag0 0:fish读模块输出数据(命令、地址)1:fish写模块发送数据(命令、地址、写入数据)always @(posedge clk or negedge rst_n)begin if(!rst_n)beginflag0 <= 0;end else if(en_[0])begin flag0 <= 1;end else if(en_[1])begin flag0 <= 0;end end//en_r 打拍 检测en信号边沿always @(posedge clk or negedge rst_n)begin if(!rst_n)beginen_r <= 0;end else begin en_r <= en;end endassign en_dge_n = !en & en_r;//read_data_vldalways @(posedge clk or negedge rst_n)begin if(!rst_n)beginread_data_vld <= 0;end else begin read_data_vld <= read_spi_one_byte_vld;//读出数据有效end end//输出//wr_rd_state_spi_out  数据输出给spi_master模块always @(*)begin if(flag0)beginwr_rd_state_spi_out = write_state_spi_out;end else if(flag0 == 0)begin wr_rd_state_spi_out = read_state_spi_out; end else begin wr_rd_state_spi_out = wr_rd_state_spi_out;end end//enassign en = en_[0] | en_[1];//spi_vldalways @(posedge clk or negedge rst_n)begin if(!rst_n)beginspi_vld <= 0;end else if(en_dge_n)begin spi_vld <= 1;end else if(write_done | read_done)begin spi_vld <= 0; end else beginspi_vld <= spi_vld; endendflash_write u_flash_write
( /*input                 */.clk          (clk            ),/*input                 */.rst_n        (rst_n          ),/*input                 */.erase_start  (erase_start),.erase_completed(erase_completed),.cmd_reply_clear_finish(cmd_reply_clear_finish),/*input                 */.write_start  (write_start),.read_id      (read_id    ),.read_rdsr    (read_rdsr  ),.read_data_flag(read_data_flag),/*input                 */.read_data    (read_data),/*input                 */.read_data_vld(read_data_vld),/*input                 */.read_done    (read_done),.busy_read(busy_read),/*input              */.spi_one_byte_done (spi_one_byte_done   ),//spi一个字节数据传输完成/*input     [7:0]    */.din         (rxf_dout       ),/*output             */.data_req    (data_req       ),           //写入flash数据请求/*output             */.en          (en_[0]         ), /*output             */.write_done        (write_done     ),/*output reg [7:0]   */.write_state_spi_out        (write_state_spi_out          ) //给spi配置   

);flash_read u_flash_read
( /*input                  */.clk     (clk            ),/*input                  */.rst_n   (rst_n          ),.read_id      (read_id    ),.read_rdsr    (read_rdsr  ),    .read_data_flag(read_data_flag | read_start),.read_only_data_flag(read_only_data_flag),.busy_read(busy_read),/*input               */.spi_one_byte_done  (spi_one_byte_done  ),/*output              */.en         (en_[1]         ),/*output              */.read_done       (read_done      ),/*output              */.read_spi_one_byte_vld (read_spi_one_byte_vld     ),/*output  reg [7:0]   */.read_state_spi_out       (read_state_spi_out          )//给spi配置
);    //fifo例化
// rx_fifo    rx_fifo_inst (// .aclr  ( !rst_n     ),// .clock ( clk        ),// .data  ( din        ),                                          //uart输入数据// .rdreq ( rxf_rdreq  ),// .wrreq ( rxf_wrreq  ),// .empty ( rxf_empty  ),// .full  ( rxf_full   ),// .q     ( rxf_dout   ),// .usedw ( rxf_usedw  )// );

flash_fifo rx_fifo (.clk(clk),                // input wire clk.srst(!rst_n),              // input wire srst// .din(din),                // input wire [7 : 0] din
  .din(din_fifo),.wr_en(rxf_wrreq),            // input wire wr_en.rd_en(rxf_rdreq),            // input wire rd_en.dout(rxf_dout),              // output wire [7 : 0] dout.full(rxf_full),              // output wire full.empty(rxf_empty),            // output wire empty.data_count(rxf_usedw)  // output wire [8 : 0] data_count
);// assign rxf_wrreq = !rxf_full && din_vld;assign rxf_wrreq = !rxf_full && din_fifo_vld;assign rxf_rdreq = !rxf_empty && data_req;// fifo_tx    fifo_tx_inst (// .aclr  ( !rst_n     ),// .clock ( clk        ),// .data  ( read_data      ),//din_m从flash中读取数据// .rdreq ( txf_rdreq  ),// .wrreq ( txf_wrreq  ),// .empty ( txf_empty  ),// .full  ( txf_full   ),// .q     ( read_flash_data_fifo_out ),                                           //uart输出数据// .usedw ( txf_usedw  )// );

flash_fifo fifo_tx (.clk(clk),                // input wire clk.srst(!rst_n),              // input wire srst.din  (read_data  ),                // input wire [7 : 0] din.wr_en(txf_wrreq),            // input wire wr_en.rd_en(txf_rdreq),            // input wire rd_en.dout(read_flash_data_fifo_out),              // output wire [7 : 0] dout.full(txf_full),              // output wire full.empty(txf_empty),            // output wire empty.data_count(txf_usedw)  // output wire [11 : 0] data_count
);assign txf_wrreq = !txf_full && read_data_vld && read_only_data_flag;//从flash中读取数据  data_vld数据有效assign txf_rdreq = flag && (!txf_empty) ;//&& (!busy_t);assign read_flash_data_fifo_out_vld = txf_rdreq;                                    //uart数据输出有效
 
(*mark_debug="true", dont_touch="true"*)reg [8:0]     cnt_fifo;
wire      add_cnt_fifo;
wire      end_cnt_fifo;
always @(posedge clk or negedge rst_n)begin if(!rst_n)begincnt_fifo<=0;endelse if(add_cnt_fifo)beginif(end_cnt_fifo)cnt_fifo<=0;elsecnt_fifo<=cnt_fifo+1;end 
end 
assign add_cnt_fifo = txf_wrreq;
assign end_cnt_fifo = add_cnt_fifo && cnt_fifo == 256-1;//一页写字节//--------------------比较-----------------------

(*mark_debug="true", dont_touch="true"*)wire [7 : 0] original_dout;
wire compare_fifo_full;
(*mark_debug="true", dont_touch="true"*)wire compare_fifo_empty;
// (*mark_debug="true", dont_touch="true"*)wire [11 : 0] compare_fifo_usedw;
(*mark_debug="true", dont_touch="true"*)wire [DATA_WIDTH-1:0] compare_fifo_usedw;
flash_fifo compare_fifo (.clk(clk),                // input wire clk.srst(!rst_n),              // input wire srst// .din(din),                // input wire [7 : 0] din
  .din(din_fifo), .wr_en(rxf_wrreq),            // input wire wr_en.rd_en(txf_rdreq),            // input wire rd_en.dout(original_dout),              // output wire [7 : 0] dout.full(compare_fifo_full),              // output wire full.empty(compare_fifo_empty),            // output wire empty.data_count(compare_fifo_usedw)  // output wire [11 : 0] data_count
);// (*mark_debug="true", dont_touch="true"*)reg [11:0]     cnt_compare;
(*mark_debug="true", dont_touch="true"*)reg [DATA_WIDTH-1:0]     cnt_compare;
wire      add_cnt_compare;
wire      end_cnt_compare;
always @(posedge clk or negedge rst_n)begin if(!rst_n)begincnt_compare<=0;endelse if(add_cnt_compare)beginif(end_cnt_compare)cnt_compare<=0;elsecnt_compare<=cnt_compare+1;end 
end 
assign add_cnt_compare = txf_rdreq&original_dout==read_flash_data_fifo_out/* &(~compare_fifo_empty) */;
assign end_cnt_compare = add_cnt_compare && cnt_compare == DATA_LENGTH-1;//10240-1;//回读比较字节
// assign end_cnt_compare = add_cnt_compare && cnt_compare == 1024-1;// (*mark_debug="true", dont_touch="true"*)wire four_pp_completed;
// assign  four_pp_completed=end_cnt_compare;always @(posedge clk or negedge rst_n)begin if(!rst_n)beginfour_pp_completed <=1'b0;end else if(end_cnt_compare)begin four_pp_completed <= 1'b1;end else if(cmd_reply_clear_finish)begin four_pp_completed <= 1'b0; end 
end//不够1024字节后面都写ff
reg din_vld_r;
always @(posedge clk or negedge rst_n)begin if(!rst_n)begindin_vld_r<=0;endelse begindin_vld_r<=din_vld;end  
endwire   din_vld_pos;
assign din_vld_pos = din_vld & ~din_vld_r;always @(posedge clk or negedge rst_n)begin if(!rst_n)begindin_fifo<='hff;endelse if(din_vld)begindin_fifo<=din;end else begindin_fifo<='hff;    end 
end// reg  din_fifo_vld;wire      end_cnt_din;
always @(posedge clk or negedge rst_n)begin if(!rst_n)begindin_fifo_vld<=1'b0;endelse if(din_vld_pos)begindin_fifo_vld<=1'b1;end else if(end_cnt_din)begindin_fifo_vld<=0;    end 
endreg [15:0]     cnt_din;
wire       add_cnt_din;// wire      end_cnt_din;
always@(posedge clk or negedge rst_n)beginif(rst_n==1'b0)begincnt_din<='d0;endelse if(add_cnt_din)beginif(end_cnt_din)cnt_din<=0;elsecnt_din<=cnt_din+1;end 
end 
assign add_cnt_din = din_fifo_vld;
assign end_cnt_din = add_cnt_din && cnt_din == 1024-1;//256-1;//一页输入字节//收包统计个数

(*mark_debug="true", dont_touch="true"*)reg [15:0]     cnt_udp;
always @(posedge clk or negedge rst_n)begin if(!rst_n)begincnt_udp<=0;endelse if(din_vld_pos)begincnt_udp<=cnt_udp+1'b1;end else begincnt_udp<=cnt_udp;    end 
endendmodule
wr_control

 

`include "param.v"
module flash_write( input                clk            ,input                rst_n        ,input erase_start,output    reg erase_completed,input cmd_reply_clear_finish,input write_start,output     reg read_id,(*mark_debug="true", dont_touch="true"*)    output  reg read_rdsr,(*mark_debug="true", dont_touch="true"*)    output  reg read_data_flag,(*mark_debug="true", dont_touch="true"*)    input [7:0] read_data,(*mark_debug="true", dont_touch="true"*)    input       read_data_vld,(*mark_debug="true", dont_touch="true"*)    input read_done,input busy_read,input               spi_one_byte_done      ,input       [7:0]   din         ,output              data_req    ,           //写入flash数据请求output              en          ,    output              write_done        ,  output  reg [7:0]   write_state_spi_out    );                                 //参数定义    parameter M_IDLE =8'b0000_0001,M_RDID =8'b0000_0010,M_WREN =8'b0000_0100,M_SE   =8'b0000_1000, M_RDSR =8'b0001_0000,M_WAIT =8'b0010_0000,M_RDDA =8'b0100_0000,M_PP   =8'b1000_0000;      parameter S_IDLE  = 5'b00001, S_CMD   = 5'b00010, S_ADDR  = 5'b00100, S_DATA  = 5'b01000, S_DELAY = 5'b10000;    parameter INIT_ADDR   = 24'h80_0000;                        //中间信号定义    reg     [7:0]               m_state_c           ;reg     [7:0]               m_state_n           ;(*mark_debug="true", dont_touch="true"*)   reg     [4:0]               s_state_c           ;reg     [4:0]               s_state_n           ;reg     [7:0]               cnt_100ns           ;wire                        add_cnt_100ns       ;wire                        end_cnt_100ns       ;reg     [18:0]              cnt_pp              ;wire                        add_cnt_pp          ;wire                        end_cnt_pp          ;reg                         end_cnt_pp_r        ;reg     [10:0]              cnt_se              ;wire                        add_cnt_se          ;wire                        end_cnt_se          ;reg                         end_cnt_se_r        ;    reg     [8:0]               cnt_byte            ;wire                        add_cnt_byte        ;wire                        end_cnt_byte        ;reg     [8:0]               byte_num            ;(*mark_debug="true", dont_touch="true"*)    reg     [23:0]              addr_wr             ;
(*mark_debug="true", dont_touch="true"*)    reg     [1:0]               flag                ;//wire                        m_idle2m_rdid       ;wire                         m_rdid2m_wren       ;wire                        m_rdid2m_idle       ;wire                        m_wren2m_se         ;wire                        m_wren2m_pp         ;wire                         m_se2m_rdsr         ;wire                         m_rdsr2m_rdda       ;wire                         m_rdsr2m_idle       ;wire                        m_rdsr2m_wren       ;wire                        m_rdsr2m_wait       ;wire                        m_wait2m_rdsr       ;wire                         m_rdda2m_wren         ;wire                         m_rdda2m_idle        ;wire                         m_pp2m_rdsr            ;//wire                        s_idle2s_cmd        ;wire                        s_cmd2s_addr        ;wire                        s_cmd2s_data        ;wire                        s_cmd2s_delay       ;wire                        s_addr2s_data       ;wire                        s_addr2s_delay      ;wire                        s_data2s_idle       ;wire                        s_data2s_delay      ;wire                        s_delay2s_idle      ;reg [2:0] read_id_cnt;reg [7:0] first_id ;reg [7:0] second_id;reg [7:0] third_id ;reg  read_done_r1;reg  read_done_r2;reg  read_done_r3;reg [1:0] read_id_flag;reg [11:0] erase_cnt;reg  rdsr_sta_reg_vld ;reg [23:0] wait_time_cnt;reg [11:0] pp_cnt;reg second_erase_start;//状态机//主状态机always @(posedge clk or negedge rst_n)begin if(!rst_n)beginm_state_c <= M_IDLE;end else begin m_state_c <= m_state_n;end endalways @(*)begin case (m_state_c)M_IDLE: begin if(m_idle2m_rdid)beginm_state_n = M_RDID;endelse beginm_state_n = m_state_c;endend M_RDID: begin if(m_rdid2m_wren)beginm_state_n = M_WREN;end else if(m_rdid2m_idle)beginm_state_n = M_IDLE;end                else beginm_state_n = m_state_c;end            endM_WREN: begin if(m_wren2m_se)beginm_state_n = M_SE;end    else if(m_wren2m_pp)beginm_state_n = M_PP;endelse beginm_state_n = m_state_c;endendM_SE: begin if(m_se2m_rdsr)beginm_state_n = M_RDSR;endelse beginm_state_n = m_state_c;end    endM_RDSR: begin if(m_rdsr2m_rdda)beginm_state_n = M_RDDA;endelse if (m_rdsr2m_idle) beginm_state_n = M_IDLE;end            else if (m_rdsr2m_wren) beginm_state_n = M_WREN;endelse if (m_rdsr2m_wait) beginm_state_n = M_WAIT;end            else beginm_state_n = m_state_c;end    endM_WAIT:begin if(m_wait2m_rdsr)beginm_state_n = M_RDSR;end else beginm_state_n = m_state_c;end end M_RDDA:begin if(m_rdda2m_wren)beginm_state_n = M_WREN;end else if(m_rdda2m_idle)beginm_state_n = M_IDLE;end else beginm_state_n = m_state_c;end             end M_PP: begin if (m_pp2m_rdsr) beginm_state_n = M_RDSR;end        else beginm_state_n = m_state_c;end    enddefault: m_state_n = m_state_c;endcaseend//从状态机always @(posedge clk or negedge rst_n)begin if(!rst_n)begins_state_c <= S_IDLE;end else begin s_state_c <= s_state_n;end endalways @(*)begin case (s_state_c)S_IDLE  : begin if (s_idle2s_cmd) begins_state_n = S_CMD;endelse begins_state_n = s_state_c; end    endS_CMD   : begin if (s_cmd2s_addr) begins_state_n = S_ADDR;end// else if (s_cmd2s_data) begin// s_state_n = S_DATA;// endelse if (s_cmd2s_delay) begins_state_n = S_DELAY;endelse begins_state_n = s_state_c;end    endS_ADDR  : begin if (s_addr2s_data) begins_state_n = S_DATA;endelse if(s_addr2s_delay) begins_state_n = S_DELAY;endelse begins_state_n = s_state_c;end   endS_DATA  : begin // if (s_data2s_idle) begin// s_state_n = S_IDLE;// end// else if(s_data2s_delay)begins_state_n = S_DELAY;endelse begins_state_n = s_state_c;end    endS_DELAY : begin if(s_delay2s_idle)begins_state_n = S_IDLE;endelse begins_state_n = s_state_c;end    enddefault: s_state_n = s_state_c;endcaseend//主状态机转换条件assign m_idle2m_rdid   = m_state_c == M_IDLE && (erase_start || write_start ||second_erase_start);assign m_rdid2m_wren   = m_state_c == M_RDID && read_id_flag==2'b11;assign m_rdid2m_idle   = m_state_c == M_RDID && read_id_flag==2'b10;assign m_wren2m_se     = m_state_c == M_WREN && s_delay2s_idle && flag == 2'b01;    assign m_wren2m_pp     = m_state_c == M_WREN && s_delay2s_idle && flag == 2'b10;    assign m_se2m_rdsr     = m_state_c == M_SE   && s_delay2s_idle;assign m_rdsr2m_rdda   = m_state_c == M_RDSR && /* s_data2s_idle && */ rdsr_sta_reg_vld && flag == 2'b10;assign m_rdsr2m_idle   = m_state_c == M_RDSR && /* s_data2s_idle && */ rdsr_sta_reg_vld && erase_cnt==12'd60 &&flag == 2'b01;assign m_rdsr2m_wren   = m_state_c == M_RDSR && /* s_data2s_idle && */ rdsr_sta_reg_vld && erase_cnt <12'd60 &&flag == 2'b01;assign m_rdsr2m_wait   = m_state_c == M_RDSR && /* s_data2s_idle */ read_done_r1 && read_data_vld && read_data[1:0] == 2'b11;assign m_wait2m_rdsr   = m_state_c == M_WAIT && ((flag == 2'b01 && wait_time_cnt== 24'd250_0000)|(flag == 2'b10 && wait_time_cnt== 24'd150_000 ));assign m_rdda2m_wren   = m_state_c == M_RDDA && /* read_done */ (~read_data_flag)&&read_done_r3 &&flag == 2'b10 && pp_cnt< 12'd4;assign m_rdda2m_idle   = m_state_c == M_RDDA && /* read_done */ (~read_data_flag)&&read_done_r3 &&flag == 2'b10 && pp_cnt==12'd4;//1024字节4页assign m_pp2m_rdsr     = m_state_c == M_PP   && s_delay2s_idle;//从状态机转换条件assign s_idle2s_cmd   = s_state_c == S_IDLE  && (!(m_state_c == M_IDLE)) && (!(m_state_c == M_RDSR)) && (!(m_state_c == M_RDID)) && (!(m_state_c == M_RDDA)) ;assign s_cmd2s_addr   = s_state_c == S_CMD   && end_cnt_byte && (m_state_c == M_SE | m_state_c == M_PP);assign s_cmd2s_data   = s_state_c == S_CMD   && end_cnt_byte && (m_state_c == M_RDSR | m_state_c == M_RDID);assign s_addr2s_data  = s_state_c == S_ADDR  && end_cnt_byte && m_state_c == M_PP;assign s_addr2s_delay = s_state_c == S_ADDR  && end_cnt_byte && m_state_c == M_SE;assign s_data2s_idle  = s_state_c == S_DATA  && read_done_r3 && (m_state_c == M_RDSR|| m_state_c == M_RDID);assign s_data2s_delay = s_state_c == S_DATA  && end_cnt_byte && (m_state_c == M_PP);assign s_cmd2s_delay  = s_state_c == S_CMD   && end_cnt_byte && m_state_c == M_WREN;assign s_delay2s_idle = s_state_c == S_DELAY && ((( (m_state_c == M_SE)?end_cnt_se_r : end_cnt_pp_r)&& (m_state_c == M_SE || m_state_c == M_PP)) || (end_cnt_100ns && m_state_c == M_WREN));//计数器always @(posedge clk or negedge rst_n)begin if(!rst_n)begincnt_100ns <= 0;end else if(add_cnt_100ns)begin if(end_cnt_100ns)begin cnt_100ns <= 0;endelse begin cnt_100ns <= cnt_100ns + 1;end endelse  begincnt_100ns <= cnt_100ns;endend assign add_cnt_100ns = s_state_c == S_DELAY && m_state_c == M_WREN;assign end_cnt_100ns = add_cnt_100ns && cnt_100ns == 30;always @(posedge clk or negedge rst_n)begin if(!rst_n)begincnt_byte <= 0;end else if(add_cnt_byte)begin if(end_cnt_byte)begin cnt_byte <= 0;endelse begin cnt_byte <= cnt_byte + 1;end endelse  begincnt_byte <= cnt_byte;endend assign add_cnt_byte = spi_one_byte_done && (s_state_c == S_CMD | s_state_c == S_ADDR | s_state_c == S_DATA ) && ~busy_read;assign end_cnt_byte = add_cnt_byte && cnt_byte == byte_num-1; always @(posedge clk or negedge rst_n)begin if(!rst_n)begincnt_pp <= 0;end else if(add_cnt_pp)begin if(end_cnt_pp | s_delay2s_idle)begin cnt_pp <= 0;endelse begin cnt_pp <= cnt_pp + 1;end endelse  begincnt_pp <= cnt_pp;endend assign add_cnt_pp = s_state_c == S_DELAY && (m_state_c == M_PP || m_state_c == M_SE);assign end_cnt_pp = add_cnt_pp && cnt_pp == `DELAY_5MS-1;always @(posedge clk or negedge rst_n)begin if(!rst_n)begincnt_se <= 0;end else if(add_cnt_se)begin if(end_cnt_se)begin cnt_se <= 0;endelse begin cnt_se <= cnt_se + 1;end endelse  begincnt_se <= cnt_se;endend assign add_cnt_se= s_state_c == S_DELAY && end_cnt_pp && m_state_c == M_SE;assign end_cnt_se = add_cnt_se && cnt_se == 2-1;//flagalways @(posedge clk or negedge rst_n)begin if(!rst_n)beginflag <=2'b00;end else if(erase_start)beginflag <=2'b01;end else if(write_start)beginflag <=2'b10;end                 endalways @(posedge clk or negedge rst_n)begin if(!rst_n)beginend_cnt_pp_r <= 0;end_cnt_se_r <= 0;end else begin end_cnt_pp_r <= end_cnt_pp;end_cnt_se_r <= end_cnt_se;end end//byte_numalways @(posedge clk or negedge rst_n)begin if(!rst_n)beginbyte_num <= 0;end else if(s_state_c == S_CMD)begin byte_num <= `CMD_BYTE;end else if(s_state_c == S_ADDR)begin byte_num <= `ADDR_BYTE;end else if(s_state_c == S_DATA)beginbyte_num <= `DATA_BYTE;endelse beginbyte_num <= byte_num;endendreg [23:0] addr_erase;always @(posedge clk or negedge rst_n)begin if(!rst_n | m_state_c == M_IDLE)beginaddr_erase <= INIT_ADDR;//24'h40_0000;end else if(m_rdsr2m_wren & flag == 2'b01)begin addr_erase <= addr_erase +24'h01_0000;end else begin addr_erase <= addr_erase;end endreg [23:0] addr_pp;always @(posedge clk or negedge rst_n)begin if(!rst_n /* | m_state_c == M_IDLE */)beginaddr_pp <=INIT_ADDR;end// else if(addr_pp ==24'h7a_607b)begin        // addr_pp <=INIT_ADDR;// end        else if(m_pp2m_rdsr & flag == 2'b10)begin addr_pp <= addr_pp +24'h00_0100;end else begin addr_pp <= addr_pp;end end    //addr_wralways @(posedge clk or negedge rst_n)begin if(!rst_n)beginaddr_wr <= INIT_ADDR;end else if(flag==2'b01)begin addr_wr <= addr_erase;end else if(flag==2'b10 )begin addr_wr <= addr_pp;end         else begin addr_wr <= addr_wr;end end//输出//write_state_spi_outalways @(posedge clk or negedge rst_n)begin if(!rst_n)beginwrite_state_spi_out <= 0;end else if(s_state_c == S_CMD)begin if(m_state_c == M_WREN)beginwrite_state_spi_out <= `CMD_WREN;endelse if(m_state_c == M_SE ) beginwrite_state_spi_out <= `CMD_SE;endelse if (m_state_c == M_PP ) beginwrite_state_spi_out <= `CMD_PP;endelse beginwrite_state_spi_out <= write_state_spi_out;endend else if(s_state_c == S_ADDR)begin write_state_spi_out <=addr_wr[23-cnt_byte*8-:8];end else if (s_state_c == S_DATA && m_state_c == M_PP) beginwrite_state_spi_out <=din;endend//data_req en write_done read_data_vld busy// wire en_temp;assign data_req = m_state_c == M_PP && spi_one_byte_done  && s_state_c == S_DATA; assign /* en_temp */  en  = m_rdid2m_wren |m_rdsr2m_wren |m_wren2m_se |m_wren2m_pp |m_rdda2m_wren;assign write_done = s_data2s_delay | s_addr2s_delay | s_cmd2s_delay;// reg [7:0] en_r;// always @(posedge clk or negedge rst_n)begin // if(!rst_n)begin// en_r[7:0] <= 8'h0;// end // else begin// en_r[7:0] <= {en_r[6:0],en_temp};// end // end    // assign en=en_r[7];always @(posedge clk or negedge rst_n)begin if(!rst_n)beginread_id <= 1'b0;end else if(erase_start|write_start|second_erase_start)begin read_id <= 1'b1;endelse beginread_id <= 1'b0;end end    always @(posedge clk or negedge rst_n)begin if(!rst_n | m_state_c == M_IDLE)beginread_id_cnt <= 'd0;end else if(m_state_c == M_RDID && read_data_vld)begin read_id_cnt <= read_id_cnt + 1'b1;endelse beginread_id_cnt <= read_id_cnt;end end    always @(posedge clk or negedge rst_n)begin if(!rst_n | m_state_c == M_IDLE)beginfirst_id  <= 'd0;second_id <= 'd0;third_id  <= 'd0;end else if(m_state_c == M_RDID && read_data_vld &&read_id_cnt==0)begin first_id  <= read_data;endelse if(m_state_c == M_RDID && read_data_vld &&read_id_cnt==1)begin second_id  <= read_data;end        else if(m_state_c == M_RDID && read_data_vld &&read_id_cnt==2)begin third_id  <= read_data;endelse beginfirst_id  <= first_id ;second_id <= second_id;third_id  <= third_id ;        end end    always @(posedge clk or negedge rst_n)begin if(!rst_n )beginread_done_r1<=1'b0;read_done_r2<=1'b0;read_done_r3<=1'b0;end else begin read_done_r1<=read_done;read_done_r2<=read_done_r1;read_done_r3<=read_done_r2;endendalways @(posedge clk or negedge rst_n)begin if(!rst_n | m_state_c == M_IDLE)beginread_id_flag <= 2'b00;end else if(read_done_r3 && first_id==`MF_ID && second_id == `ID1 && third_id == `ID2)begin read_id_flag <= 2'b11;endelse if(read_done_r3 && (first_id != `MF_ID || second_id != `ID1 || third_id != `ID2))begin read_id_flag <= 2'b10;//实际// read_id_flag <= 2'b11;//仿真endelse if(m_state_c != M_RDID)beginread_id_flag <= 2'b00;        end else beginread_id_flag <= read_id_flag;end end        always @(posedge clk or negedge rst_n)begin if(!rst_n | m_state_c == M_IDLE)beginerase_cnt <= 'd0;end else if(m_se2m_rdsr)begin erase_cnt <= erase_cnt + 1'b1;endelse beginerase_cnt <= erase_cnt;end endalways @(posedge clk or negedge rst_n)begin if(!rst_n | m_state_c == M_IDLE)beginrdsr_sta_reg_vld  <= 1'b0;end else if(m_state_c == M_RDSR && read_data_vld && read_data[1:0] == 2'b00)begin rdsr_sta_reg_vld  <= 1'b1;endelse if(m_state_c != M_RDSR)beginrdsr_sta_reg_vld  <= 1'b0;end else beginrdsr_sta_reg_vld  <= rdsr_sta_reg_vld ;        end end    always @(posedge clk or negedge rst_n)begin if(!rst_n)beginread_rdsr <= 1'b0;end else if(m_se2m_rdsr|m_wait2m_rdsr|m_pp2m_rdsr)begin read_rdsr <= 1'b1;endelse beginread_rdsr <= 1'b0;end endalways @(posedge clk or negedge rst_n)begin if(!rst_n)beginwait_time_cnt <= 24'd0;end else if(m_state_c == M_WAIT)begin wait_time_cnt <= wait_time_cnt+1'b1;endelse if(m_state_c != M_WAIT)beginwait_time_cnt <= 24'd0;        end else beginwait_time_cnt <= wait_time_cnt;end end    always @(posedge clk or negedge rst_n)begin if(!rst_n | m_state_c == M_IDLE)beginpp_cnt <= 'd0;end else if(m_pp2m_rdsr)begin pp_cnt <= pp_cnt + 1'b1;endelse beginpp_cnt <= pp_cnt;end end    always @(posedge clk or negedge rst_n)begin if(!rst_n)beginread_data_flag <= 1'b0;end else if(m_rdsr2m_rdda)begin read_data_flag <= 1'b1;endelse beginread_data_flag <= 1'b0;end end// reg erase_completed;always @(posedge clk or negedge rst_n)begin if(!rst_n)beginerase_completed <= 1'b0;end else if(m_rdsr2m_idle)begin erase_completed <= 1'b1;endelse if(cmd_reply_clear_finish)beginerase_completed <= 1'b0;end end//// reg second_erase_start;always @(posedge clk or negedge rst_n)begin if(!rst_n)beginsecond_erase_start <= 1'b0;end else if(m_rdid2m_idle)begin second_erase_start <= 1'b1;endelse if(m_idle2m_rdid)beginsecond_erase_start <= 1'b0;end endendmodule
flash_write

 

`include "param.v"
module flash_read( input                clk            ,input                rst_n        ,input read_id,input read_rdsr,input read_data_flag,(*mark_debug="true", dont_touch="true"*)    output     reg read_only_data_flag,output  wire busy_read,input               spi_one_byte_done      ,output              en          ,output              read_done        ,output              read_spi_one_byte_vld  ,output  reg [7:0]   read_state_spi_out    
);                                 //参数定义        parameter IDLE      =9'b00000_0001,RDID_CMD  =9'b00000_0010, RDID_DATA =9'b00000_0100,RDSR_CMD  =9'b00000_1000,RDSR_DATA =9'b00001_0000,RDAD_CMD  =9'b00010_0000, RDAD_ADDR =9'b00100_0000, RDAD_DATA =9'b01000_0000, RD_DONE   =9'b10000_0000;parameter INIT_ADDR   = 24'h80_0000;//中间信号定义    
(*mark_debug="true", dont_touch="true"*)    reg     [8:0]               state_c                 ;reg     [8:0]               state_n                 ;reg        [8:0]               cnt_byte                ;wire                        add_cnt_byte            ;wire                        end_cnt_byte            ;reg     [8:0]               byte_num                ;(*mark_debug="true", dont_touch="true"*)    reg     [23:0]              addr_rd                 ;wire                        idle2rdid_cmd           ;wire                        idle2rdsr_cmd             ;wire                        idle2rdad_cmd           ;wire                        rdid_cmd2rdid_data      ;wire                         rdsr_cmd2rdsr_data      ;wire                        rdad_cmd2rdad_addr      ;wire                        rdad_addr2rdad_data     ;wire                        rdid_data2rd_done       ;wire                         rdsr_data2rd_done       ;wire                        rdad_data2rd_done       ;wire                        rd_done2idle            ;//状态机always @(posedge clk or negedge rst_n)begin if(!rst_n)beginstate_c <= IDLE;end else begin state_c <= state_n;end endalways @(*)begin case (state_c)IDLE      : begin if (idle2rdid_cmd) beginstate_n <= RDID_CMD;endelse if(idle2rdsr_cmd) beginstate_n <= RDSR_CMD;end        else if(idle2rdad_cmd) beginstate_n <= RDAD_CMD;endelse beginstate_n <= state_c;end  endRDID_CMD  : begin if(rdid_cmd2rdid_data)beginstate_n <= RDID_DATA;endelse beginstate_n <= state_c;end endRDID_DATA : begin if (rdid_data2rd_done) beginstate_n <= RD_DONE;endelse beginstate_n <= state_c;endend RDSR_CMD  : begin if(rdsr_cmd2rdsr_data)beginstate_n <= RDSR_DATA;endelse beginstate_n <= state_c;end end        RDSR_DATA : begin if (rdsr_data2rd_done) beginstate_n <= RD_DONE;endelse beginstate_n <= state_c;end        endRDAD_CMD  : begin if (rdad_cmd2rdad_addr) beginstate_n <= RDAD_ADDR;endelse beginstate_n <= state_c;endendRDAD_ADDR : begin if (rdad_addr2rdad_data ) beginstate_n <= RDAD_DATA;endelse beginstate_n <= state_c;end  endRDAD_DATA : begin if(rdad_data2rd_done)beginstate_n <= RD_DONE;endelse beginstate_n <= state_c;endendRD_DONE   : begin if(rd_done2idle)beginstate_n <= IDLE;endelse beginstate_n <= state_c;endenddefault: state_n <= state_c;endcaseendassign idle2rdid_cmd       = state_c == IDLE    && read_id   ; assign idle2rdsr_cmd       = state_c == IDLE    && read_rdsr ; assign idle2rdad_cmd       = state_c == IDLE    && read_data_flag ;     assign rdid_cmd2rdid_data  = state_c == RDID_CMD  && end_cnt_byte;  assign rdsr_cmd2rdsr_data  = state_c == RDSR_CMD  && end_cnt_byte; assign rdad_cmd2rdad_addr  = state_c == RDAD_CMD  && end_cnt_byte;     assign rdad_addr2rdad_data = state_c == RDAD_ADDR && end_cnt_byte;      assign rdid_data2rd_done   = state_c == RDID_DATA && end_cnt_byte;  assign rdsr_data2rd_done   = state_c == RDSR_DATA && end_cnt_byte;assign rdad_data2rd_done   = state_c == RDAD_DATA && end_cnt_byte; assign rd_done2idle        = state_c == RD_DONE   && 1'b1;//计数器always @(posedge clk or negedge rst_n)begin if(!rst_n)begincnt_byte <= 0;end else if(add_cnt_byte)begin if(end_cnt_byte)begin cnt_byte <= 0;endelse begin cnt_byte <= cnt_byte + 1;end endelse  begincnt_byte <= cnt_byte;endend assign add_cnt_byte = (state_c == RDID_CMD | state_c == RDID_DATA |state_c == RDSR_CMD | state_c == RDSR_DATA | state_c == RDAD_CMD | state_c == RDAD_ADDR |state_c == RDAD_DATA) && spi_one_byte_done;assign end_cnt_byte = add_cnt_byte && cnt_byte == byte_num-1;always @(posedge clk or negedge rst_n)begin if(!rst_n)beginbyte_num <= 0;end else if(state_c == RDID_CMD |state_c == RDSR_CMD | state_c == RDAD_CMD )begin byte_num <= `CMD_BYTE; end else if(state_c == RDID_DATA)begin byte_num <= `ID_BYTE; end else if(state_c == RDSR_DATA)begin byte_num <= `RDSR_BYTE; end         else  if (state_c == RDAD_ADDR) beginbyte_num <= `ADDR_BYTE;endelse if(state_c == RDAD_DATA)beginbyte_num <= `DATA_BYTE;endend//addr_rdalways @(posedge clk or negedge rst_n)begin if(!rst_n /* | addr_rd==24'h00_0400 */)beginaddr_rd <= INIT_ADDR;end else if(rdad_data2rd_done)begin addr_rd <= addr_rd + 24'h00_0100;end else begin addr_rd <= addr_rd;end end//输出 //read_state_spi_outalways @(posedge clk or negedge rst_n)begin if(!rst_n)beginread_state_spi_out <= 0;end else if(state_c == RDID_CMD)begin read_state_spi_out <= `CMD_RDID;end else if(state_c == RDSR_CMD)begin read_state_spi_out <= `CMD_RDSR;end         else if(state_c == RDAD_CMD)begin read_state_spi_out <= `CMD_READ;endelse if(state_c == RDAD_ADDR)beginif(cnt_byte == 0)beginread_state_spi_out <= addr_rd[23:16];endelse if(cnt_byte == 1)beginread_state_spi_out <= addr_rd[15:8];endelse if(cnt_byte == 2)beginread_state_spi_out <= addr_rd[7:0];endendelse beginread_state_spi_out <= read_state_spi_out;end end//en read_done dtat_m_vldassign en =(read_id |read_rdsr| read_data_flag) & state_c == IDLE;assign read_done = rdid_data2rd_done  | rdsr_data2rd_done| rdad_data2rd_done;assign read_spi_one_byte_vld = spi_one_byte_done && (state_c == RDID_DATA | state_c == RDSR_DATA | state_c == RDAD_DATA);// assign read_only_data_flag=state_c == RDAD_DATA;always @(posedge clk or negedge rst_n)begin if(!rst_n)beginread_only_data_flag<=1'b0;end else if(state_c == RDAD_DATA)beginread_only_data_flag<=1'b1;endelse beginread_only_data_flag<=1'b0;end        end         assign busy_read= !(state_c==IDLE);endmodule
flash_read

 

 `include "param.v"module spi_master( input                clk        ,input                rst_n    ,input               en      ,input       [1:0]   spi_mode,input               spi_vld ,input        [7:0]    spi_din   ,input               miso    ,output    reg      sck      ,output  reg         cs_n    ,output                mosi    ,output  reg [7:0]   spi_dout    ,output  reg         busy    ,output              spi_one_byte_done );                                 //中间信号定义        reg         [4:0]                   cnt_bit             ;wire                                add_cnt_bit         ;wire                                end_cnt_bit         ;reg         [8:0]                   cnt_sck             ;wire                                add_cnt_sck         ;wire                                end_cnt_sck         ;reg                                 end_cnt_sck_r       ;//计数器 //cnt_sckalways @(posedge clk or negedge rst_n)begin if(!rst_n)begincnt_sck <= 0;end else if(add_cnt_sck)begin if(end_cnt_sck | en)begin cnt_sck <= 0;endelse begin cnt_sck <= cnt_sck + 1;end endelse  begincnt_sck <= cnt_sck;endend assign add_cnt_sck = spi_vld;assign end_cnt_sck = add_cnt_sck && cnt_sck == `SCK_PERIOD-1;//cnt_bitalways @(posedge clk or negedge rst_n)begin if(!rst_n)begincnt_bit <= 0;end else if(add_cnt_bit )begin if(end_cnt_bit | en)begin cnt_bit <= 0;endelse begin cnt_bit <= cnt_bit + 1;end endelse  begincnt_bit <= cnt_bit;endend assign add_cnt_bit =  (cs_n == 0)&& end_cnt_sck;assign end_cnt_bit = add_cnt_bit && cnt_bit == 8-1;//sckalways @(*)begincase (spi_mode)0 : begin if(spi_vld && (cnt_sck <= `SCK_HALF-1))beginsck <= 0;endelse if(cnt_sck > `SCK_HALF-1)beginsck <= 1;end else beginsck <= 0; end  end1 : begin if(spi_vld && (cnt_sck <= `SCK_HALF-1))beginsck <= 1;endelse if(cnt_sck > `SCK_HALF-1)beginsck <= 0;end else beginsck <= 0; end end2 : begin if(spi_vld && (cnt_sck <= `SCK_HALF-1 ))beginsck <= 1;endelse if(cnt_sck > `SCK_HALF-1 )beginsck <= 0;end  else beginsck <= 1;endend3 : begin if(spi_vld && (cnt_sck <= `SCK_HALF-1))beginsck <= 0;endelse if(cnt_sck > `SCK_HALF-1 )beginsck <= 1;end  else beginsck <= 1;endend default: sck <= sck;endcaseend//end_cnt_sck_ralways @(posedge clk or negedge rst_n)begin if(!rst_n)beginend_cnt_sck_r <= 0;end else begin end_cnt_sck_r <= end_cnt_sck;end end//输出//cs_nalways @(posedge clk or negedge rst_n)begin if(!rst_n)begincs_n <= 1;end else if(en)begin cs_n <= 0; end else if(cs_n == 0 && (!spi_vld) && end_cnt_sck_r)begin cs_n <= 1;end end//mosiassign mosi = spi_din[7-cnt_bit]; //spi_dout    always @(posedge clk or negedge rst_n)begin if(!rst_n)beginspi_dout <= 0;end else if(cs_n == 0 && cnt_sck == `SCK_PERIOD-1)begin spi_dout[7-cnt_bit] <= miso;end else begin spi_dout <= spi_dout; end end//spi_one_byte_doneassign  spi_one_byte_done = end_cnt_bit;//busyalways @(posedge clk or negedge rst_n)begin if(!rst_n)beginbusy <= 0;end else if(add_cnt_bit && end_cnt_bit == 0)begin busy <= 1;end else if(end_cnt_bit)begin busy <= 0;end endendmodule
spi_master

 

 //参数定义//spi时钟参数`define  SCK_PERIOD  20`define  SCK_HALF    10//spi command`define  CMD_WREN       8'h06               // `define  CMD_WRDI       8'h04               // `define  CMD_RDID       8'h9f               // `define  CMD_RDSR       8'h05               // `define  CMD_WRSR       8'h01               // `define  CMD_READ       8'h03               // `define  CMD_FAST_READ  8'h0b               // `define  CMD_PP         8'h02               // `define  CMD_SE         8'hd8               // `define  CMD_BE         8'hc7               // `define  CMD_DP         8'hb9               // `define  CMD_RES        8'hab               //  //spi byte`define  CMD_BYTE        1               // 命令1字节数 `define  ADDR_BYTE       3               // 地址3字节数 `define  ID_BYTE         3               // 读取id字节数 `define  DATA_BYTE       256             // 读取数据字节数 `define  RDSR_BYTE       1               // 读状态寄存器字节数// `define  DELAY_5MS       250_000         // 5ms 数据写入后需要等待5ms才能读出`define  DELAY_5MS      50         // 5ms 数据写入后需要等待5ms才能读出 //波特率`define  BAUD_9600   5208`define  BAUD_19200  2604`define  BAUD_38400  1302`define  BAUD_115200 434`define STOP_BIT  1'b1      //数据停止位`define START_BIT 1'b0      //数据开始位
`define MF_ID  8'h20      `define ID1    8'hBA      `define ID2    8'h18 
param.v

仿真相关:

module top( input wire       sys_clk_p,    //system clock positiveinput wire       sys_clk_n,    //system clock negative input wire       rst_n ,       //reset ,low active    input           erase_start,input           write_start,// output erase_completed,  //仿真// output four_pp_completed,//仿真input               miso    ,// output              sck     ,output              mosi    ,output              cs_n        );wire    erase_completed;//调试wire  four_pp_completed;//调试wire sck;IBUFGDS sys_clk_ibufgds 
(
.O      (sys_clk     ),//200MHz
.I      (sys_clk_p   ),
.IB     (sys_clk_n   )
);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_spi (.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(1'b0),                       // 1-bit input: User start-up clock input.GSR(1'b0),                       // 1-bit input: Global Set/Reset input (GSR cannot be used for the port name).GTS(1'b0),                       // 1-bit input: Global 3-state input (GTS cannot be used for the port name).KEYCLEARB(1'b1),                 // 1-bit input: Clear AES Decrypter Key input from Battery-Backed RAM (BBRAM).PACK(1'b1),                      // 1-bit input: PROGRAM acknowledge input.USRCCLKO(sck),                   // 1-bit input: User CCLK input.USRCCLKTS(1'b0),                 // 1-bit input: User CCLK 3-state enable input.USRDONEO(1'b1),                  // 1-bit input: User DONE pin output control.USRDONETS(1'b1)                  // 1-bit input: User DONE 3-state enable output
   );reg [5:0]     cnt_clk=0;
wire      add_cnt_clk;
wire      end_cnt_clk;
always@(posedge sys_clk or negedge rst_n)beginif(rst_n==1'b0)begincnt_clk<=0;endelse if(add_cnt_clk)beginif(end_cnt_clk)cnt_clk<=0;elsecnt_clk<=cnt_clk+1;end 
end 
assign add_cnt_clk = 1;
assign end_cnt_clk = add_cnt_clk && cnt_clk == 2-1;// reg clk;//100MHz
// always@(posedge sys_clk)begin// if(cnt_clk<1)begin// clk<=1'b1;// end// else begin// clk<=1'b0;// end 
// end   wire clk;
assign clk=sys_clk;// wire clk_out1;
// wire clk_out2;// clk_wiz_0 clk_wiz_0_uut// (// .clk_out1(clk_out1),     // output clk_out1// .clk_out2(clk_out2),     // output clk_out2// .reset(~rst_n), // input reset// .locked(locked),       // output locked// .clk_in1(sys_clk));      // input clk_in1// wire clk;
// assign clk=clk_out2 & locked;//===========================vio=========================================
wire earse_start_vio;
wire write_start_vio;
wire read_start_vio;
vio_0 uut_vio_0 (.clk(clk),                    .probe_out0(earse_start_vio), .probe_out1(write_start_vio),.probe_out2(read_start_vio)  
); reg earse_start_r1;
always@(posedge clk)begin
earse_start_r1<=earse_start_vio;
endwire   earse_edge;
assign earse_edge= earse_start_r1 & ~earse_start_vio;reg write_start_r1;
always@(posedge clk)begin
write_start_r1<=write_start_vio;
endwire   write_edge;
assign write_edge= write_start_r1 & ~write_start_vio;reg read_start_r1;
always@(posedge clk)begin
read_start_r1<=read_start_vio;
endwire   read_edge;
assign read_edge= read_start_r1 & ~read_start_vio;    
//===========================test=========================================                             
reg         I_fl_data_en ;        
wire        end_cnt0;always @(posedge clk or negedge rst_n)begin if(!rst_n)beginI_fl_data_en <= 0;end// else if(write_start) begin //仿真else if(write_edge)begin     //实际I_fl_data_en <= 1;end else if(end_cnt0) beginI_fl_data_en <= 0;end     
end reg [15:0] cnt0;
wire      add_cnt0;
// wire      end_cnt0;
always@(posedge clk or negedge rst_n)beginif(rst_n==1'b0)begincnt0<='d0;endelse if(add_cnt0)beginif(end_cnt0)cnt0<=0;elsecnt0<=cnt0+1;end 
end 
assign add_cnt0 = I_fl_data_en;
assign end_cnt0 = add_cnt0 && cnt0 == 1024-1;//256-1;//
(*mark_debug="true", dont_touch="true"*)wire        [7:0]   wr_rd_state_spi_out ;(*mark_debug="true", dont_touch="true"*)wire        [7:0]   dout                ;//读取数据(*mark_debug="true", dont_touch="true"*)wire                dout_vld            ;//数据有效(*mark_debug="true", dont_touch="true"*)wire                spi_vld             ;(*mark_debug="true", dont_touch="true"*)wire                en                  ;(*mark_debug="true", dont_touch="true"*)wire        [7:0]   spi_dout            ;//读取数据进入fifo                   (*mark_debug="true", dont_touch="true"*)wire                spi_one_byte_done   ; // (*mark_debug="true", dont_touch="true"*) wire [1:0] key_out;// key_filter_fsm # (.KEY_W(2),.TIME_20MS(1_000_000))u_key_filter_fsm// (// /*input                         */.clk        (clk            ),// /*input                         */.rst_n    (rst_n          ),// /*input         [KEY_W - 1:0]    */.key_in    ({write_start,erase_start}         ),// /*output         [KEY_W - 1:0]    */.key_out    (key_out        )// );
wr_control u_wr_control( /*input                  */.clk          (clk              ),/*input                  */.rst_n         (rst_n            ),// `ifdef simulation// `elsif// .erase_start  (erase_start),// erase_start 仿真// .write_start  (write_start),//write_start
.erase_start  (earse_edge  ),//erase_start 调试.write_start  (write_edge  ),//write_start
                            .erase_completed(erase_completed),.four_pp_completed(four_pp_completed),.read_start(read_edge),// `endif    /*input               */.spi_one_byte_done (spi_one_byte_done          ),/*input        [7:0]  */.din          (cnt0[7:0]),//(rx_byte          ),//
     /*input               */.din_vld      (I_fl_data_en),//(rx_byte_vld      ),//
     /*input        [7:0]  */.read_data       (spi_dout         ),/*output    reg [7:0] */.wr_rd_state_spi_out  (wr_rd_state_spi_out           ),/*output      [7:0]   */.read_flash_data_fifo_out  (dout             ),/*output              */.read_flash_data_fifo_out_vld  (dout_vld         ),/*output              */.en           (en               ),/*output              */.spi_vld      (spi_vld          ) );spi_master u_spi_master( /*input               */.clk        (clk            ),/*input               */.rst_n      (rst_n          ),/*input               */.en         (en             ),/*input       [1:0]   */.spi_mode   (2'b00          ),/*input               */.spi_vld    (spi_vld        ),/*input        [7:0]  */.spi_din    (wr_rd_state_spi_out),//写入数据/*input               */.miso       (miso           ),/*output    reg       */.sck        (sck            ),/*output  reg         */.cs_n       (cs_n           ),/*output              */.mosi       (mosi           ),/*output  reg [7:0]   */.spi_dout   (spi_dout       ),//读取数据/*output  reg         */.busy       (         ),/*output              */.spi_one_byte_done  (spi_one_byte_done        ) );                                 endmodule 
top

 

`timescale 1ns / 1ps
// `define        simulation
module top_tb();//时钟与复位
reg sys_clk_p;
reg rst_n;//uut的输入信号
reg erase_start ;
reg write_start ;
reg miso;
//时钟周期,单位为ns,
parameter CYCLE = 5;
//复位时间,此时表示复位3个时钟周期的时间
parameter RST_TIME = 3;//待测试的模块例化

top uut(
.sys_clk_p(sys_clk_p),
.sys_clk_n(~sys_clk_p),
.rst_n (rst_n),.erase_start  (erase_start ),
.write_start  (write_start ),.miso (miso),
.mosi (mosi),
.cs_n (cs_n)
);//生成本地时钟200M
initial beginsys_clk_p =0;forever#(CYCLE/2)sys_clk_p =~sys_clk_p;    
end 
//产生复位信号
initial beginrst_n =1;#2;rst_n =0;    #(CYCLE*RST_TIME)rst_n =1;
end initial begin
write_start=0;erase_start =0;#1000erase_start =1; #100erase_start =0; #35_0000  //擦除4块
write_start=1;    
#100
write_start=0;#180_0000
write_start=1;    
#100
write_start=0; // #10_0000  //擦除4块
// write_start=1;    
// #100
// write_start=0;// #180_0000
// write_start=1;    
// #100
// write_start=0;end initial beginmiso =0;end endmodule 
top_tb

 

xilinx在线升级相关:

这里icap控制跳转的代码,测试可用,以下是原文连接:

https://blog.csdn.net/qq_43557686/article/details/134750377?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522028715b643b80c588730a73e4c1310ae%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=028715b643b80c588730a73e4c1310ae&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-1-134750377-null-null.nonecase&utm_term=icap&spm=1018.2226.3001.4450

/* * file            : multiboot_ctrl.v* author        : 今朝无言* Lab            : WHU-EIS-LMSWE* date            : 2023-11-30* version        : v1.0* description    : ICAP 原语实现程控 multiboot(多重启动),K7需要使用 ICAPE2 原语* Copyright © 2023 WHU-EIS-LMSWE, All Rights Reserved.*/module multiboot_ctrl(
input    wire            clk,
input    wire            rst_n,input    wire            multiboot_start,    //触发Multiboot, 上升沿有效
input    wire    [31:0]    multiboot_addr,        //要启动的Muliboot Image的起始地址output    reg                busy
);//-------------------ICAPE2原语-----------------------------
wire            ICAPE2_CLK;
wire    [31:0]    ICAPE2_O;
reg                ICAPE2_CSIB;
wire    [31:0]    ICAPE2_I;
reg                ICAPE2_RDWRB;assign    ICAPE2_CLK    = clk;ICAPE2 #(.DEVICE_ID            (32'h3631093),    // Specifies the pre-programmed Device ID value to be used for simulation purposes. K7-100T的为32'h3631093.ICAP_WIDTH        ("X32"),        // Specifies the input and output data width..SIM_CFG_FILE_NAME    ("NONE")        // Specifies the Raw Bitstream (RBT) file to be parsed by the simulation model.
)
ICAPE2_inst(.O                    (ICAPE2_O),        // 32-bit output: Configuration data output bus.CLK                (ICAPE2_CLK),    // 1-bit input: Clock Input.CSIB                (ICAPE2_CSIB),    // 1-bit input: Active-Low ICAP Enable.I                    (ICAPE2_I),        // 32-bit input: Configuration data input bus.RDWRB                (ICAPE2_RDWRB)    // 1-bit input: Read/Write Select input    1对应rd,0对应wr
);wire    [31:0]    Dummy        = 32'hFFFFFFFF;
wire    [31:0]    Sync_Word    = 32'hAA995566;
wire    [31:0]    NOOP        = 32'h20000000;
wire    [31:0]    WR_WBSTAR    = 32'h30020001;/*When using ICAPE2 to set the WBSTAR address, the 24 most significant address bits should be writtento WBSTAR[23:0]. For SPI 32-bit addressing mode, WBSTAR[23:0] are sent as address bits [31:8]. Thelower 8 bits of the address are undefined and the value could be as high as 0xFF. Any bitstreamat the WBSTAR address should contain 256 dummy bytes before the start of the bitstream.*/
wire    [31:0]    WBSTAR        = {3'b000, 5'h0, multiboot_addr[31:8]};wire    [31:0]    WR_CMD        = 32'h30008001;
wire    [31:0]    IPROG        = 32'h0000000F;//ICAPE2位翻转
reg        [31:0]    wrdat;
assign    ICAPE2_I    = {wrdat[24], wrdat[25], wrdat[26], wrdat[27], wrdat[28], wrdat[29], wrdat[30], wrdat[31], wrdat[16], wrdat[17], wrdat[18], wrdat[19], wrdat[20], wrdat[21], wrdat[22], wrdat[23], wrdat[8], wrdat[9], wrdat[10], wrdat[11], wrdat[12], wrdat[13], wrdat[14], wrdat[15], wrdat[0], wrdat[1], wrdat[2], wrdat[3], wrdat[4], wrdat[5], wrdat[6], wrdat[7]};//------------------------FSM----------------------------------
localparam    S_IDLE            = 16'h0001;
localparam    S_DUMMY            = 16'h0002;
localparam    S_SYN_WORD        = 16'h0004;
localparam    S_NOOP1            = 16'h0008;
localparam    S_WR_WBSTAR        = 16'h0010;
localparam    S_WBSTAR        = 16'h0020;
localparam    S_WR_CMD        = 16'h0040;
localparam    S_IPROG            = 16'h0080;
localparam    S_NOOP2            = 16'h0100;
localparam    S_STOP            = 16'h0200;

(*mark_debug="true", dont_touch="true"*)wire    multiboot_start_pe;
reg        multiboot_start_d0;
reg        multiboot_start_d1;assign    multiboot_start_pe    = multiboot_start_d0 & (~multiboot_start_d1);always @(posedge clk) beginmultiboot_start_d0        <= multiboot_start;multiboot_start_d1        <= multiboot_start_d0;
end(*mark_debug="true", dont_touch="true"*) reg        [15:0]    state        = S_IDLE;
reg        [15:0]    next_state;always @(posedge clk) beginif(~rst_n) beginstate    <= S_IDLE;endelse beginstate    <= next_state;end
endalways @(*) begincase(state)S_IDLE: beginif(multiboot_start_pe) beginnext_state    <= S_DUMMY;endelse beginnext_state    <= S_IDLE;endendS_DUMMY:        next_state    <= S_SYN_WORD;S_SYN_WORD:        next_state    <= S_NOOP1;S_NOOP1:        next_state    <= S_WR_WBSTAR;S_WR_WBSTAR:    next_state    <= S_WBSTAR;S_WBSTAR:        next_state    <= S_WR_CMD;S_WR_CMD:        next_state    <= S_IPROG;S_IPROG:        next_state    <= S_NOOP2;S_NOOP2:        next_state    <= S_STOP;S_STOP:            next_state    <= S_IDLE;default:        next_state    <= S_IDLE;endcase
endalways @(posedge clk) begincase(state)S_IDLE: beginwrdat            <= 32'd0;ICAPE2_CSIB        <= 1'b1;ICAPE2_RDWRB    <= 1'b1;endS_DUMMY: beginwrdat            <= Dummy;ICAPE2_CSIB        <= 1'b0;ICAPE2_RDWRB    <= 1'b0;endS_SYN_WORD: beginwrdat            <= Sync_Word;ICAPE2_CSIB        <= 1'b0;ICAPE2_RDWRB    <= 1'b0;endS_NOOP1: beginwrdat            <= NOOP;ICAPE2_CSIB        <= 1'b0;ICAPE2_RDWRB    <= 1'b0;endS_WR_WBSTAR: beginwrdat            <= WR_WBSTAR;ICAPE2_CSIB        <= 1'b0;ICAPE2_RDWRB    <= 1'b0;endS_WBSTAR: beginwrdat            <= WBSTAR;ICAPE2_CSIB        <= 1'b0;ICAPE2_RDWRB    <= 1'b0;endS_WR_CMD: beginwrdat            <= WR_CMD;ICAPE2_CSIB        <= 1'b0;ICAPE2_RDWRB    <= 1'b0;endS_IPROG: beginwrdat            <= IPROG;ICAPE2_CSIB        <= 1'b0;ICAPE2_RDWRB    <= 1'b0;endS_NOOP2: beginwrdat            <= NOOP;ICAPE2_CSIB        <= 1'b0;ICAPE2_RDWRB    <= 1'b0;endS_STOP: beginwrdat            <= 32'd0;ICAPE2_CSIB        <= 1'b1;ICAPE2_RDWRB    <= 1'b1;enddefault: beginwrdat            <= 32'd0;ICAPE2_CSIB        <= 1'b1;ICAPE2_RDWRB    <= 1'b1;endendcase
endalways@(*)beginif(state==S_IDLE)busy    <= 1'b0;else busy    <= 1'b1;
endendmodule
multiboot_ctrl

 

//上电初始化信号
// parameter    STA_EN_DLY    =    32'd399_999_999;
parameter    STA_EN_DLY    =    32'd7_999_999_999;//64s
(*mark_debug="true", dont_touch="true"*)reg [32:0] power_ini_cnt;
always  @(posedge clk or negedge rst_n)beginif(rst_n==1'b0)beginpower_ini_cnt<='d0;endelse if(power_ini_cnt < STA_EN_DLY)beginpower_ini_cnt<=power_ini_cnt+1'b1;endelse beginpower_ini_cnt<=power_ini_cnt;end    
end reg power_en;
always  @(posedge clk or negedge rst_n)beginif(rst_n==1'b0)beginpower_en<= 1'b0;end else if(power_ini_cnt == STA_EN_DLY) beginpower_en<= 1'b1;end else beginpower_en<= 1'd0;end
endreg power_en_r1;
reg power_en_r2;
always  @(posedge clk or negedge rst_n)beginif(rst_n==1'b0)beginpower_en_r1 <= 1'b0;power_en_r2 <= 1'b0;end else beginpower_en_r1 <= power_en;power_en_r2 <= power_en_r1;end
end//
(*mark_debug="true", dont_touch="true"*)wire   power_ini_pos;
assign power_ini_pos = power_en_r1 & ~power_en_r2;
//
(*mark_debug="true", dont_touch="true"*)reg erase_write_start_reg;
always  @(posedge clk or negedge rst_n)beginif(rst_n==1'b0)beginerase_write_start_reg<= 1'b0;end else if(erase_start|write_start) beginerase_write_start_reg<= 1'b1;end else beginerase_write_start_reg<= erase_write_start_reg;end
end
//
(*mark_debug="true", dont_touch="true"*)reg multiboot_start;
always  @(posedge clk or negedge rst_n)beginif(rst_n==1'b0)beginmultiboot_start<= 1'b0;end else if(power_ini_pos&(~erase_write_start_reg)) beginmultiboot_start<= 1'b1;end else if(update_end)beginmultiboot_start<= 1'b0;//1'b0不跳//1'b1跳end else beginmultiboot_start<= 1'b0;end
end//
multiboot_ctrl multiboot_ctrl_inst(.clk                (clk),//(sys_clk),
    .rst_n                (rst_n),.multiboot_start    (multiboot_start),//(~key_in[0]),//key_in[0]---key1 key_in[1]---key2 .multiboot_addr        (32'h80000000),    //实际是(32'h00800000),模块内部移动了8位        //加载0x01000000处的Multiboot Image
.busy                ()
);
icap_Jump

 

multiboot_addr的地址这里写的是0x8000_0000,实际上在multiboot_ctrl内部做了8位偏移,而我使用的FLASH型号的S25FL128,采用的是24位地址。实际上跳转地址是0x0080_0000,经过仿真输出的是0x0080_0000;

XDC相关:

############## NET - IOSTANDARD ######################
set_property CFGBVS VCCO [current_design]
set_property CONFIG_VOLTAGE 3.3 [current_design]
#############SPI Configurate Setting##################
#set_property BITSTREAM.CONFIG.CONFIGRATE 50 [current_design]set_property BITSTREAM.CONFIG.UNUSEDPIN Pullnone [current_design]
set_property BITSTREAM.CONFIG.CONFIGRATE 50 [current_design]
set_property BITSTREAM.CONFIG.TIMER_CFG 32'h0007A120 [current_design]

##for golden image
set_property BITSTREAM.CONFIG.CONFIGFALLBACK ENABLE [current_design]
#set_property BITSTREAM.CONFIG.NEXT_CONFIG_ADDR 32'h00800000 [current_design]
set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design]
set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 1 [current_design]
##for golden image

 

############## NET - IOSTANDARD ######################
set_property CFGBVS VCCO [current_design]
set_property CONFIG_VOLTAGE 3.3 [current_design]
#############SPI Configurate Setting##################
#set_property BITSTREAM.CONFIG.CONFIGRATE 50 [current_design]set_property BITSTREAM.CONFIG.UNUSEDPIN Pullnone [current_design]
set_property BITSTREAM.CONFIG.CONFIGRATE 50 [current_design]
set_property BITSTREAM.CONFIG.TIMER_CFG 32'h0007A120 [current_design]

#for multiboot image
set_property BITSTREAM.CONFIG.CONFIGFALLBACK ENABLE [current_design]
set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design]
set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 1 [current_design]
#for multiboot image

 

 

使用icap跳转升级流程:

1.升级指令顺序:

第一步,首先发送第六条升级启动指令,该指令将update区跳转到golden区,(如果已再golden区则可不用)

第二步,获取golden版本号,如果获取到golden版本号说明跳转成功

第三步,golden区版本号获取成功,开始进行擦除操作,

第四步,收到擦除完成信号,可以发送写升级包数据命令;发一包(1024字节写4页)后,收到应答后再下发一包,直到所有包发完,

第五步,掉电,拔掉jtag下载线,重启

 

2.注意事项:

每次重启后,先进入golden版本,一分钟内如果未收到擦除写flash命令,一分钟后,自动跳转到update版本;如果update版本破坏,则回退至golden版本,

如果需要升级,则需要跳转到golden区,update版本不具有擦写flash权,防止升级掉电版本不回退;

 

这里有一个问题:当update区没有数据或者数据破坏时,可以退回golden区,如果没有升级操作,两个区会一直来回跳,如果此时想使用golden区,那么这里的方法是,当进入golden区,一分钟内,发送擦除指令,这样就会一直停留在golden区,

 

使用工具:

软件:vivado2019.1

使用的FPGA型号为XC7A100T-2FGG4841,属于Xilinx 公司 Artix-7 系列的产品,速度等级为 2,温度等级为工业级。此型号为 FGG484封装,484 个引脚。

使用了一片 容量16M的 QSPI FLASH 芯片,型号为 N25Q128,它使用 3.3V CMOS 电压标准。由于它的非易失特性,在使用中,QSPIFLASH 可以作为 FPGA 系统的启动镜像。

vivado可选Mt25ql128-spi-x1_x2_x4

 

844b80173e9299dd573cb1a9751a13d7

 

 

 

 

 

 

 

c49db7e2c579968e15e445203c2de37d

 

合成mcs,

image

 

9f2653aa6586124551bc30a9cc55caf5

 

 

参考连接:

K7系列FPGA多重启动(Multiboot)(今朝无言

https://blog.csdn.net/qq_43557686/article/details/134750377?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522028715b643b80c588730a73e4c1310ae%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=028715b643b80c588730a73e4c1310ae&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-1-134750377-null-null.nonecase&utm_term=icap&spm=1018.2226.3001.4450

 

 

FPGA在线升级 -- Multiboot(热爱学习地派大星

https://blog.csdn.net/weixin_51418325/article/details/144370219?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-5-144370219-blog-136070049.235^v43^pc_blog_bottom_relevance_base8&spm=1001.2101.3001.4242.4&utm_relevant_index=7

 

 

感谢各位前辈的指路,记录一下,

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/972180.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Day23、24:2025年10月13日、14日,星期一、二,休息。

继续值1休2备1的形式补假,连休2日。15日到期2个,提前联系保证人到场。newcomer又说打电话家属不来,哎,无奈只有亲自打电话,我觉得也没那么难沟通嘛,其实有些时候,你换种别人容易接受的沟通方式,或许效果更好。…

【ESSC|连续三届检索】第四届教育科学与社会文化国际学术会议(ESSC 2025)

第四届教育科学与社会文化国际学术会议(ESSC 2025)定于2025年12月19-12月21日在中国厦门举行。【高录用快见刊,最快刊后1个月内上知网&谷歌 学术主题不设限,教育、艺术、语言、文化、社会学等人文社科主题均可 资…

Day25:2025年10月15日,星期三,上班。

今日任务就是Release和Change。妈蛋的,系统上午还扯拐,我真的是服了,现在的系统好复杂啊,简直是搞不懂了。好在也在下午上班前,搞定了,不喜欢加班,在我眼里,无谓的加班就是无能的体现。间隙还顺手完成了一个调…

【完结20章】AI Agent+MCP从0到1打造个人专属编程智能体

【完结20章】AI Agent+MCP从0到1打造个人专属编程智能体 学习地址:……/s/1V4PCK4YoC5E9BYEHnDIKtg 提取码:p1xu 在人工智能蓬勃发展的今天,每一位开发者都在寻找那个能够真正理解自己、助力自己编程之旅的智能伙伴…

2025年市场热门的河道护坡石笼网公司怎么选择,抗冲击抗腐蚀石笼网/柔韧抗压石笼网/双隔板石笼网河道护坡石笼网直销厂家有哪些

行业背景分析 随着国家水利基础设施建设的持续推进,河道护坡石笼网作为重要的防护材料,其市场需求呈现稳步增长态势。根据行业数据显示,2024年国内石笼网市场规模已达120亿元,预计2025年将保持8%以上的增速。在这一…

2025年深圳废旧18650电池回收公司权威推荐榜单:动力18650电池回收/大量回收18650锂电池/18650电池组回收源头公司精选

在新能源产业迅猛发展与资源循环利用需求日益提升的背景下,18650电池作为应用广泛的锂离子电池型号,其回收处理已成为资源再生行业的重要环节。据行业报告显示,2024年中国锂离子电池产量已达1170GWh,同比增长超过2…

gearman如何实现负载均衡

Gearman是一个多语言的应用程序框架,用于分布式任务处理。它允许你编写客户端程序来提交任务,然后编写worker程序来处理这些任务。为了实现负载均衡,你可以使用以下几种方法:多个worker:创建多个worker进程来处理…

gdb安装 linux

在 Linux 系统中,gdb(GNU Debugger)是一个用于调试程序的工具,通常随 GNU 编译器集合(GCC)一起提供。大多数 Linux 发行版(如 Debian、Ubuntu、Fedora 等)都默认安装了 gdb,但如果你需要安装或配置 gdb,可以…

gdb linux

gdb 是 GNU Debugger(GDB)的命令行界面,用于调试 C、C++、Java、Python 等语言编写的程序。在 Linux 系统中,gdb 是一个非常常用的调试工具,尤其在开发和调试应用程序时非常有用。一、基本用法1. 启动 GDBgdb <…

对数几率回归算法伪代码

对数几率回归算法伪代码步骤 伪代码 说明初始化 w = 0(权重向量)b = 0(偏置项)learning_rate = α(学习率)max_iterations = N(最大迭代次数) 初始化模型参数和超参数Sigmoid函数 def sigmoid(z): return 1…

2025 年质量好的四川球墨铸铁管 top 品牌厂家排行榜

2025 年质量好的四川球墨铸铁管 top 品牌厂家排行榜2025 年质量好的四川球墨铸铁管 top 品牌厂家排行榜 在城市基础设施建设高速推进的 2025 年,球墨铸铁管作为地下管廊生命线的核心建材,其质量稳定性与安全可靠性直…

Day16:2025年10月6日,星期一,值班,万事顺遂。

为什么直接就Day16了呢?因为10月1日至10月4日,国庆休假,放假分前4和后4耍,值一休一,就安排的是6号和8号值班。今天一切都比较顺利,就是晚上又有喝酒打架闹事的,先是一个人被三个人打,然后我们去了,他又开始嚣…

《从成本中心到价值创造:QMS系统的商业价值重构》‌

引言:重新定义质量管理的价值定位‌ 在传统认知中,质量管理往往被视为"成本中心"——需要投入大量人力物力,却很难直接看到经济回报。然而,随着数字化转型的深入推进,QMS系统正在帮助企业管理层重新认识…

2025 年评价高的四川自助洗车机厂家实力及用户口碑排行榜

2025 年评价高的四川自助洗车机厂家实力及用户口碑排行榜2025 年评价高的四川自助洗车机厂家实力及用户口碑排行榜 在汽车后市场数字化升级与创业需求爆发的 2025 年,自助洗车机凭借 “便捷高效、成本可控、绿色环保”…

Day18:2025年10月8日,星期三,值班,平安顺遂。

今天一天都还好,没什么事情。到了下午,发现了早上商铺steal手机的线索,立马带队去抓,后台马指挥强劲支撑,按图索骥,将他顺利擒拿归案。久经沙场的我,搁门外等着破门的那一刻竟有点小兴奋呢。小贼倒也爽快,竹筒…

《避开这7个坑,你的QMS项目就成功了一半》‌

亲爱的小伙伴们,今天咱们来聊聊企业上马QMS系统时最容易遇到的七个"坑"。据我多年观察,掉进这些坑里的企业,轻则项目延期、预算超支,重则系统废弃、前功尽弃。来来来,搬好小板凳,听我细细道来~ 第一坑…

【Springer|EI、SCOPUS双检索】第三届人工智能安全与隐私国际学术会议(AISP 2025)

第三届人工智能安全与隐私国际学术会议(AIS&P 2025)将于2025年12月5-7日在中国广州举行。【主办单位:广州大学,会议召开有保障往届均于会后3个月左右完成见刊并被EI检索,会议历史良好沿用往届出版社,已申请到…

浙江 GEO 企业 TOP4 榜单:解码 AI 时代的智能营销新势力

—— 四大企业如何领跑生成式引擎优化赛道 在生成式 AI 重构搜索生态的 2025 年,浙江凭借数字经济产业集群优势,已崛起为全国 GEO(生成式引擎优化)技术的核心聚集地。以下四家企业凭借差异化技术壁垒、全链路服务能力…

C++ 中打开记录的多种方式及相关流类

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

视频汇聚平台EasyCVR进程启动后视频却无法播放的原因排查

视频汇聚平台EasyCVR进程启动后视频却无法播放的原因排查最近我们接到用户反馈,在部署EasyCVR视频监控平台后,虽然设备显示在线且能够正常发流,但视频却无法正常播放。针对这一问题,我们的技术团队立即展开了排查。…