天津做陶瓷的公司网站,做公众号和网站主页的区别,企业信用中国官网查询,凡客之家推广平台前言
最近在收拾抽屉时找到一个某宝的spi flash模块#xff0c;如下图所示#xff0c;我就想用能不能串口来读写flash#xff0c;大致过程就是#xff0c;串口向fpga发送一条指令#xff0c;fpga解析出指令控制flah#xff0c;这个指令协议目前就是#xff1a; 55 AA …前言
最近在收拾抽屉时找到一个某宝的spi flash模块如下图所示我就想用能不能串口来读写flash大致过程就是串口向fpga发送一条指令fpga解析出指令控制flah这个指令协议目前就是 55 AA CMD LEN_h LEN_m LEN_l DATA CMD01 写02 读03 擦除片擦除 LEN_h/m/l三个字节表示读写长度高字节在前低字节灾后 DATA如果是写flahDATA则为需要写入的数据其它两种状态可以不填
1. 串口指令解析
软件使用序列式状态机完成串口指令解析最后解析出三个使能信号以及相应的数据、长度、地址。
always(posedge clk,negedge rst_n)if(!rst_n)stateS0;else begincase(state)S0:if(uart_vld)beginif(uart_dat 8h55)stateS1;elsestateS0; end else stateS0; S1:if(uart_vld)beginif(uart_dat 8hAA)stateS2;elsestateS0; end else stateS1;S2:if(uart_vld)stateS3;elsestateS2;S3://命令字if(uart_vld)stateS4;elsestateS3; S4://长度hif(uart_vld)stateS5;elsestateS4; S5://长度mif(uart_vld)stateS6;elsestateS5;S6://长度lif(uart_vld)stateS7;elsestateS6;S7:stateS7;default:stateS0; endcaseend2. flash 控制
对于flash三个功能读、写、擦书分别设计了三个模块每个模块完成对应功能以及输出flash的cs、sclk、sdi等信号但是flash接口只有一组控制信号因此需要对三个模块输出的flash控制信号进行选择输出如下所示。
always(posedge clk,negedge rst_n)if(!rst_n)begino_spi_cen 1b1; o_spi_sclk 1b0; o_spi_sdi 1b0; end else begincase(work_state)3b001:begin//xieo_spi_cen wr_flash_csn ;o_spi_sclk wr_flash_sclk ;o_spi_sdi wr_flash_sdi ;end3b010:begin//duo_spi_cen rd_flash_csn ;o_spi_sclk rd_flash_sclk ;o_spi_sdi rd_flash_sdi ;end 3b100:begin//cachuo_spi_cen er_flash_csn ;o_spi_sclk er_flash_sclk ;o_spi_sdi er_flash_sdi ;end default:begino_spi_cen 1b1; o_spi_sclk 1b0; o_spi_sdi 1b0; endendcaseendassign work_state {spi_flash_erctl,spi_flash_rdctl,spi_flash_wrctl}; 2.1 flash写控制
软件对flash写控制的基本方法是收到一个串口数据就写进flash并不是先缓存256个字节然后直接进行页编程这样搞控制逻辑比较复杂。方法确定后就是软件实现上级输出了vld和datavld和data上上沿对齐vld只有一个时钟宽度使用vld作为触发条件完成数据写入。 同样软件使用序列式状态机器进行流程控制。然后先写使能然后正常写指令02、地址数据。
always(posedge clk,negedge rst_n)if(!rst_n)stateS0;else if(clken)begincase(state)S0:if(spi_flash_ctlr[2] vld_zk)stateS1;elsestateS0;S1://xieshineng function code 06if(cnt cnt_bitd7)stateS2;else stateS1;S2://delayif(cnt cnt_bitWIDTH-1)stateS3;else stateS2;S3://xie gongneng ma 02if(cnt cnt_bitd7)stateS4;else stateS3;S4://xie dizhiif(cnt cnt_bitd23)stateS5;else stateS4;S5://xie shuju if(cnt cnt_bitd7)stateS6;else stateS5;S6:if(cnt)stateS7;else stateS6;S7:if(cnt_byte wr_len)stateS8;elsestateS0;S8:stateS8;default:stateS0;endcaseend2.2 flash擦除
直接在写控制上面改前面有个写使能下图是擦除指令C7/60
always(posedge clk,negedge rst_n)if(!rst_n)stateS0;else if(clken)begincase(state)S0:if(spi_flash_ctlr[2:1]2b01)stateS1;elsestateS0;S1://xieshineng function code 06if(cnt cnt_bitd7)stateS2;else stateS1;S2://delayif(cnt cnt_bitWIDTH-1)stateS3;else stateS2;S3://if(cnt cnt_bitd7)stateS6;else stateS3;S6:if(cnt)stateS7;else stateS6;S7:stateS8;S8:stateS8;default:stateS0;endcaseend2.3 flash读控制
从falsh读数据比较简单接口时序如下图软件实现同样还是序列式状态机根据传入的长度决定读取的字节数。 因为数据从flash读出后需要通过串口发送因此为了减少工作量从flash读出一个数据串口就发送一个数据因此为了避免flash两个数据都读出来了串口一个都没发完需要控制flash读数间隔使得这个间隔大于串口发完一个字节的时间举个栗子假设现在串口波特率为115200那么发完一个字节的时间约为86.8us10位那么flash读数间隔要大于86.9us。
always(posedge clk,negedge rst_n)if(!rst_n)stateS0;else if(clken)begincase(state)S0:if(spi_flash_ctlr[2:1]2b01)stateS1;elsestateS0;S1:stateS2;S2://cs xian ladi if(cnt) stateS3;else stateS2;S3://xie gongneng ma 02if(cnt cnt_bitd7)stateS4;else stateS3;S4://xie dizhiif(cnt cnt_bitd23)stateS5;else stateS4;S5://xie shuju if(cnt cnt_bitd7)stateS6;else stateS5;S6:if(cnt)stateS7;else stateS6;S7:if(cnt_byte rd_len)stateS8;elsestateS9;S9:if(dly_end)stateS1;else stateS9;S8:stateS8;default:stateS0;endcaseend3. 实物测试
开始我设置的波特率为921600擦除和写没问题至少在时序上是很完美的但是回读出来的数据如下图前十个字节一样本来写入是01~0a现在读出的数据中第2、3、5、7、9都是FF后来我把波特率降到9600然后就好了下图最后10个字节。中间10个ff是擦除完后读出来数据。 软件工程链接 软件工程、源码、仿真、数据手册、fllash仿真模型 最后来张全家福