flash M25P128 read operation
The content of our experiment is to read a byte of flash data. The system diagram is as follows:
The hardware and software environments used are:
Hardware: Zircon A4plus development board
Software: quartus II 13.1
From the technical manual, we can get the following information:
From the above information, we can get:
1. A read instruction operation can read the entire flash data.
2. The time sequence used is still SPI time sequence
Sequence diagram design
In the same way, we also change the erasure sequence of flash to some extent as follows:
The time sequence picture here is a little disorderly, but I believe that students can learn with the foundation in front. Next, go straight to the code.
The writing of flash read module
The tradition here doesn't talk nonsense. It goes directly to the code:
`timescale 1ns / 1ps // ********************************************************************************* // Project Name : OSXXXX // Author : zhangningning // Email : nnzhang1996@foxmail.com // Website : // Module Name : flash_read.v // Create Time : 2020-01-09 12:52:26 // Editor : sublime text3, tab size (4) // CopyRight(c) : All Rights Reserved // // ********************************************************************************* // Modification History: // Date By Version Change Description // ----------------------------------------------------------------------- // XXXX zhangningning 1.0 Original // // ********************************************************************************* module flash_read( input sclk , input rst_n , input key_flag , output reg cs_n , output reg sck , output reg sdi , input sdo , output reg [ 7:0] data_out , output reg data_flag ); //========================================================================================\ //**************Define Parameter and Internal Signals********************************** //========================================================================================/ parameter READ_INST = 8'h03 ; parameter READ_ADDR = 24'h00_03_21 ; reg [ 4:0] cnt_32 ; reg [ 2:0] cnt_state ; reg [ 1:0] cnt_4 ; reg [ 4:0] bit_cnt ; //========================================================================================\ //************** Main Code ********************************** //========================================================================================/ always @(posedge sclk or negedge rst_n) if(rst_n == 1'b0) cs_n <= 1'b1; else if(key_flag == 1'b1) cs_n <= 1'b0; else if(cnt_32 == 'd31 && cnt_state == 'd6) cs_n <= 1'b1; else cs_n <= cs_n; always @(posedge sclk or negedge rst_n) if(rst_n == 1'b0) cnt_32 <= 5'd0; else if(cnt_32 == 'd31) cnt_32 <= 5'd0; else if(cs_n == 1'b0) cnt_32 <= cnt_32 + 1'b1; else cnt_32 <= 5'd0; always @(posedge sclk or negedge rst_n) if(rst_n == 1'b0) cnt_state <= 3'd0; else if(cnt_state == 'd6 && cnt_32 == 'd31) cnt_state <= 3'd0; else if(cnt_32 == 'd31) cnt_state <= cnt_state + 1'b1; else cnt_state <= cnt_state; always @(posedge sclk or negedge rst_n) if(rst_n == 1'b0) cnt_4 <= 2'd0; else if(cnt_state >= 'd1 && cnt_state <= 'd5) cnt_4 <= cnt_4 + 1'b1; else cnt_4 <= 2'd0; always @(posedge sclk or negedge rst_n) if(rst_n == 1'b0) sck <= 1'b0; else if(cnt_4 == 'd0) sck <= 1'b0; else if(cnt_4 == 'd2) sck <= 1'b1; else sck <= sck; always @(posedge sclk or negedge rst_n) if(rst_n == 1'b0) sdi <= 1'b0; else if(cnt_32 == 'd31 && cnt_state == 'd4) sdi <= 1'b0; else if(cnt_4 == 'd0 && cnt_state == 'd1) sdi <= READ_INST[7-bit_cnt]; else if(cnt_4 == 'd0 &&cnt_state >= 3'd2 && cnt_state <= 3'd4) sdi <= READ_ADDR[23-bit_cnt]; else sdi <= sdi; always @(posedge sclk or negedge rst_n) if(rst_n == 1'b0) bit_cnt <= 5'd0; else if(cnt_32 == 'd30 && cnt_state == 3'd1) bit_cnt <= 5'd0; else if(cnt_32 == 'd30 && cnt_state == 3'd4) bit_cnt <= 5'd0; else if(cnt_4 == 'd2 && cnt_state >= 3'd1 && cnt_state <= 3'd4) bit_cnt <= bit_cnt + 1'b1; else bit_cnt <= bit_cnt; always @(posedge sclk or negedge rst_n) if(rst_n == 1'b0) data_out <= 8'd0; else if(cnt_4 == 'd2 && cnt_state == 3'd5) data_out <= {data_out[6:0],sdo}; else if(cnt_32 == 'd31 && cnt_state == 'd6) data_out <= 8'd0; else data_out <= data_out; always @(posedge sclk or negedge rst_n) if(rst_n == 1'b0) data_flag <= 1'b0; else if(cnt_state == 'd5 && cnt_32 == 'd30) data_flag <= 1'b1; else data_flag <= 1'b0; endmodule
Combined with the timing chart and manual information, I believe you can easily understand the above code writing.
Code of flash read test module
In order to facilitate the students to debug the code, the test code of the module is directly given here:
`timescale 1ns / 1ps `define CLOCK 20 // ********************************************************************************* // Project Name : OSXXXX // Author : zhangningning // Email : nnzhang1996@foxmail.com // Website : // Module Name : flash_earse_tb.v // Create Time : 2020-01-08 19:57:13 // Editor : sublime text3, tab size (4) // CopyRight(c) : All Rights Reserved // // ********************************************************************************* // Modification History: // Date By Version Change Description // ----------------------------------------------------------------------- // XXXX zhangningning 1.0 Original // // ********************************************************************************* module flash_read_tb(); reg sclk ; reg rst_n ; reg key_flag ; wire cs_n ; wire sck ; wire sdi ; wire [ 7:0] data_out ; wire data_flag ; initial begin sclk <= 1'b0; rst_n <= 1'b0; key_flag <= 1'b0; #(100*`CLOCK) rst_n <= 1'b1; #(100*`CLOCK) key_flag <= 1'b1; #(`CLOCK) key_flag <= 1'b0; #(1000*`CLOCK) key_flag <= 1'b1; #(`CLOCK) key_flag <= 1'b0; end always #(`CLOCK/2) sclk <= ~sclk; flash_read flash_read_inst( .sclk (sclk ), .rst_n (rst_n ), .key_flag (key_flag ), .cs_n (cs_n ), .sck (sck ), .sdi (sdi ), .sdo (1'b1 ), .data_out (data_out ), .data_flag (data_flag ) ); endmodule
Code for other modules
In order to facilitate the students to use the code directly, here we copy all the codes as follows, and the whole project can also be taken by the group itself:
key module code:
`timescale 1ns / 1ps // ********************************************************************************* // Project Name : OSXXXX // Author : zhangningning // Email : nnzhang1996@foxmail.com // Website : // Module Name : key.v // Create Time : 2020-01-05 13:49:36 // Editor : sublime text3, tab size (4) // CopyRight(c) : All Rights Reserved // // ********************************************************************************* // Modification History: // Date By Version Change Description // ----------------------------------------------------------------------- // XXXX zhangningning 1.0 Original // // ********************************************************************************* module key( input sclk , input rst_n , input key , output reg key_o ); //========================================================================================\ //**************Define Parameter and Internal Signals********************************** //========================================================================================/ parameter IDLE = 4'b0001 ; parameter S1 = 4'b0010 ; parameter S2 = 4'b0100 ; parameter S3 = 4'b1000 ; reg [ 3:0] state ; reg [ 9:0] cnt ; reg key_r1 ; reg key_r2 ; reg key_r3 ; reg nege_flag ; reg pose_flag ; //========================================================================================\ //************** Main Code ********************************** //========================================================================================/ always @(posedge sclk) key_r1 <= key; always @(posedge sclk) key_r2 <= key_r1; always @(posedge sclk) key_r3 <= key_r2; always @(posedge sclk or negedge rst_n) if(rst_n == 1'b0) nege_flag <= 1'b0; else if(key_r3 == 1'b1 && key_r2 == 1'b0) nege_flag <= 1'b1; else nege_flag <= 1'b0; always @(posedge sclk or negedge rst_n) if(rst_n == 1'b0) pose_flag <= 1'b0; else if(key_r3 == 1'b0 && key_r2 == 1'b1) pose_flag <= 1'b1; else pose_flag <= 1'b0; always @(posedge sclk or negedge rst_n) if(rst_n == 1'b0) state <= IDLE; else case(state) IDLE : if(nege_flag == 1'b1) state <= S1; else state <= IDLE; S1 : if(cnt == 10'd999) state <= S2; else if(pose_flag == 1'b1) state <= IDLE; else state <= S1; S2 : if(pose_flag == 1'b1) state <= S3; else state <= S2; S3 : if(cnt == 10'd999) state <= IDLE; else if(nege_flag == 1'b1) state <= S2; else state <= S3; default : state <= IDLE; endcase always @(posedge sclk or negedge rst_n) if(rst_n == 1'b0) cnt <= 10'd0; else if(state != S1 && state != S3) cnt <= 10'd0; else cnt <= cnt + 1'b1; always @(posedge sclk or negedge rst_n) if(rst_n == 1'b0) key_o <= 1'b0; else if(state == S1 && cnt == 10'd999) key_o <= 1'b1; else key_o <= 1'b0; endmodule
top module:
`timescale 1ns / 1ps // ********************************************************************************* // Project Name : OSXXXX // Author : zhangningning // Email : nnzhang1996@foxmail.com // Website : // Module Name : top.v // Create Time : 2020-01-08 21:18:52 // Editor : sublime text3, tab size (4) // CopyRight(c) : All Rights Reserved // // ********************************************************************************* // Modification History: // Date By Version Change Description // ----------------------------------------------------------------------- // XXXX zhangningning 1.0 Original // // ********************************************************************************* module top( input sclk , input rst_n , input key , output wire cs_n , output wire sck , output wire sdi , input sdo , output reg [ 7:0] led ); //========================================================================================\ //**************Define Parameter and Internal Signals********************************** //========================================================================================/ wire key_flag ; wire [ 7:0] data_out ; wire data_flag ; //========================================================================================\ //************** Main Code ********************************** //========================================================================================/ always @(posedge sclk or negedge rst_n) if(rst_n == 1'b0) led <= 8'd0; else if(data_flag == 1'b1) led <= data_out; else led <= led; key key_inst( .sclk (sclk ), .rst_n (rst_n ), .key (~key ), .key_o (key_flag ) ); flash_read flash_read_inst( .sclk (sclk ), .rst_n (rst_n ), .key_flag (key_flag ), .cs_n (cs_n ), .sck (sck ), .sdi (sdi ), .sdo (sdo ), .data_out (data_out ), .data_flag (data_flag ) ); endmodule
experimental result
The experimental result here is that we read the data written in flash in the previous article and display it on the led. The experimental results prove the correctness of our flash reading and writing operations.
Concluding remarks
Creation is not easy. Students who think the article is helpful can collect some praise and support. (projects are also in the group) students who have any opinions on the article or need to communicate further can join the following group: