赞
踩
根据项目需求,设计一个Flash控制器。以便将完成低速数据的存储。Flash选用了S25FL032。使用单线SPI接口,接线如图:
1,Flash S25fl032介绍
1.1 IO描述
1.2 相关命令介绍
1.3主要命令时序介绍
1.3.1 READ命令时序(读数据命令,最大支持40MHZ)
1.3.2 FAST_READ 命令时序(读数据命令,最大支持104MHZ)
1.3.3 READ_ID命令时序(读ID)
1.3.4 WREN,WRDI命令时序(写使能或写不使能)
1.3.5 PP命令(写时序)
1.3.6 SE命令时序(擦除)
2,控制器设计
该Flash支持4线和2线,1线读写;在设计中要求速率不高,因此,使用最简单的单线完成。
2.1 端口设计
- spi_flash_control #(
- parameter [31:0] SYSCLK = 32'd100_000_000,
- parameter [31:0] SPICLK = 32'd10_000_000
- )(
- input sys_clk,
- input sys_rst,
-
- input cmd_start,
- input [31:0] cmd_addr,
- input [31:0] wr_data, //write 4 byte
- output [31:0] rd_data, //read 4 byte
- output reg cmd_done,
-
- output flash_cs_n,
- output flash_sclk,
- input flash_sdi,
- output flash_sdo
- );
端口介绍:
cmd_start:发起命令,启动控制器;
cmd_addr:命令与地址;高8bit为命令,低24bit为地址;如果命令与地址无关,则低位为0;
wr_data:写数据;一次写4字节;
rd_data:读数据,一次读4自己;
cmd_done:命令完成,控制器完成一次操作。
2.2 命令解析
此处实现根据不同命令,控制实现读写选择,写寄存器装配;写时序bit长度计算。
- //flash cmd
- always @(posedge sys_clk) begin
- if(sys_rst) begin
- start_data_reg <= 0;
- spi_bit_len <= 0;
- wr_start <= 0;
- rd_start <= 0;
- end
- else if(cmd_start && cmd_addr[31:24] == 8'h03) begin
- start_data_reg <= {cmd_addr,32'd0};
- spi_bit_len <= 8 + 24 + 32;
- wr_start <= 0;
- rd_start <= 1;
- end
- else if(cmd_start && cmd_addr[31:24] == 8'h0b) begin
- start_data_reg <= {cmd_addr,32'd0};
- spi_bit_len <= 8 + 24 + 8 + 32;
- wr_start <= 0;
- rd_start <= 1;
- end
- else if(cmd_start && cmd_addr[31:24] == 8'h90) begin
- start_data_reg <= {cmd_addr,32'd0};
- spi_bit_len <= 8 + 24 + 8 + 8;
- wr_start <= 0;
- rd_start <= 1;
- end
- else if(cmd_start && cmd_addr[31:24] == 8'h05) begin
- start_data_reg <= {cmd_addr,32'd0};
- spi_bit_len <= 8 + 8;
- wr_start <= 0;
- rd_start <= 1;
- end
- else if(cmd_start && cmd_addr[31:24] == 8'h06) begin
- start_data_reg <= {cmd_addr,32'd0};
- spi_bit_len <= 8;
- wr_start <= 1;
- rd_start <= 0;
- end
- else if(cmd_start && cmd_addr[31:24] == 8'h02) begin
- start_data_reg <= {cmd_addr,wr_data};
- spi_bit_len <= 8 + 24 + 32;
- wr_start <= 1;
- rd_start <= 0;
- end
- else if(cmd_start && cmd_addr[31:24] == 8'h08) begin
- start_data_reg <= {cmd_addr,32'd0};
- spi_bit_len <= 8 + 24;
- wr_start <= 1;
- rd_start <= 0;
- end
- else begin
- start_data_reg <= start_data_reg;
- spi_bit_len <= spi_bit_len;
- wr_start <= 0;
- rd_start <= 0;
- end
- end
2.3 SPI CLK生成
- //spi clk
- always @ (posedge sys_clk) begin
- if(sys_rst) begin
- clk_div <= 0;
- clk_cnt <= 0;
- end
- else if(spi_run_en && clk_cnt >= spirate_val) begin
- clk_div <= !clk_div;
- clk_cnt <= 0;
- end
- else if(spi_run_en) begin
- clk_div <= clk_div;
- clk_cnt <= clk_cnt + 1;
- end
- else begin
- clk_div <= 0;
- clk_cnt <= 0;
- end
- clk_div_reg <= clk_div;
- clk_div_pose <= clk_div && !clk_div_reg;
- clk_div_nege <= !clk_div && clk_div_reg;
- end
2.4 控制器状态机
控制完成命令,数据读写设计。
- //spi state
- always @ (posedge sys_clk) begin
- if(sys_rst)
- spi_state <= idlestate;
- else case(spi_state)
- idlestate : if(wr_start)
- spi_state <= wrstartstate;
- else if(rd_start)
- spi_state <= rdstartstate;
- else
- spi_state <= idlestate;
-
- wrstartstate : spi_state <= wrstate;
-
- wrstate : if(spi_bit_cnt == 0)
- spi_state <= wrdonestate;
- else
- spi_state <= wrstate;
-
- wrdonestate : spi_state <= idlestate;
-
- rdstartstate : spi_state <= rdstate;
-
- rdstate : if(spi_bit_cnt == 0)
- spi_state <= rddonestate;
- else
- spi_state <= rdstate;
-
- rddonestate : spi_state <= idlestate;
-
- default : spi_state <= idlestate;
- endcase
- end
-
- always @ (posedge sys_clk) begin
- if(sys_rst) begin
- spi_run_en <= 0;
- spi_bit_cnt <= 0;
- cs_int <= 0;
- sclk_int <= 0;
- sdo_int <= 0;
- cmd_done <= 0;
- tx_shift_data <= 0;
- rx_shift_data <= 0;
- rx_data_reg <= 0;
- end
- else case(spi_state)
- idlestate : begin
- spi_run_en <= 0;
- spi_bit_cnt <= 0;
- cs_int <= 0;
- sclk_int <= 0;
- sdo_int <= 0;
- cmd_done <= 0;
- tx_shift_data <= 0;
- rx_shift_data <= 0;
- rx_data_reg <= rx_data_reg;
- end
-
- wrstartstate : begin
- spi_run_en <= 1;
- spi_bit_cnt <= spi_bit_len;
- cs_int <= 1;
- sclk_int <= 0;
- sdo_int <= 0;
- cmd_done <= 0;
- tx_shift_data <= start_data_reg;
- rx_shift_data <= 0;
- rx_data_reg <= rx_data_reg;
- end
-
- wrstate : if(clk_div_nege) begin
- tx_shift_data <= {tx_shift_data[62:0],1'b0};
- spi_bit_cnt <= spi_bit_cnt - 1;
- end
- else begin
- spi_run_en <= 1;
- spi_bit_cnt <= spi_bit_cnt;
- cs_int <= 1;
- cmd_done <= 0;
- sclk_int <= clk_div;
- sdo_int <= tx_shift_data[63];
- tx_shift_data <= tx_shift_data;
- rx_shift_data <= 0;
- rx_data_reg <= rx_data_reg;
- end
- wrdonestate : begin
- spi_run_en <= 0;
- spi_bit_cnt <= 0;
- cs_int <= 0;
- sclk_int <= 0;
- sdo_int <= 0;
- cmd_done <= 1;
- tx_shift_data <= 0;
- rx_shift_data <= 0;
- rx_data_reg <= rx_data_reg;
- end
-
- rdstartstate : begin
- spi_run_en <= 1;
- spi_bit_cnt <= spi_bit_len;
- cs_int <= 1;
- sclk_int <= 0;
- sdo_int <= 0;
- cmd_done <= 0;
- tx_shift_data <= start_data_reg;
- rx_shift_data <= 0;
- rx_data_reg <= rx_data_reg;
- end
-
- rdstate : if(clk_div_nege) begin
- tx_shift_data <= {tx_shift_data[62:0],1'b0};
- spi_bit_cnt <= spi_bit_cnt - 1;
- end
- else if(clk_div_pose) begin
- rx_shift_data <= {rx_shift_data[31:0],flash_sdi};
- end
- else begin
- spi_run_en <= 1;
- spi_bit_cnt <= spi_bit_cnt;
- cs_int <= 1;
- cmd_done <= 0;
- sclk_int <= clk_div;
- sdo_int <= tx_shift_data[63];
- tx_shift_data <= tx_shift_data;
- rx_shift_data <= rx_shift_data;
- rx_data_reg <= rx_data_reg;
- end
- rddonestate : begin
- spi_run_en <= 0;
- spi_bit_cnt <= 0;
- cs_int <= 0;
- sclk_int <= 0;
- sdo_int <= 0;
- cmd_done <= 1;
- tx_shift_data <= 0;
- rx_shift_data <= 0;
- rx_data_reg <= rx_shift_data;
- end
- endcase
- end
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。