2610 views|6 replies

270

Posts

0

Resources
The OP
 

[Evaluation of domestic FPGA Gaoyun GW1N-4 series development board] FLASH operation [Copy link]

 This post was last edited by 怀穿少年梦 on 2021-12-28 14:12

1. Purpose

Use Gaoyun GW1N-4 series development board to erase and write FLASH . The FLASH model used is W25Q 64JV .

2. Features of W25Q64JVSSIQ

1. Supports 3 communication modes: SPI , Dual SPI and Quad SPI . The storage unit of FLASH cannot write bit 1 , only bit 0 , so the original data must be erased (FFh) before writing data , and no processing is performed when writing bit 1. The characteristics of W25QQ 64JV are shown in the following figure :

2. FLASH storage structure

W25Q64JV consists of 128 blocks from Block0 to Block127 , with a capacity of 64M-bit, that is, 64M =128*64*1024*8bit/1024/1024 . Each Block consists of 16 sectors from Sector0 to Sector15 , each sector is 4KB in size and consists of 16 pages . Taking the first sector as an example, the first page address starts from xx0000h~xx00FF , the second page address starts from xx0100~xx01FF , the third page address starts from xx0200~xx02FF , and so on ... The 16th page address starts from xx0F00~xx0FFF . The size of each page is 256 bytes , and you will see later that Page Programd supports a maximum of 256 bytes . The explanation block diagram is as follows :


  1. FLASH related operation timing diagram

1 ) Write enable timing

2 ) Full Erase Timing

3 ) Page write timing

Draw a waveform according to the above timing, which is the SPI simulation timing waveform. Because the FPGA clock is 50MHz , 50M is divided into four, and 32 clock cycles are delayed by 640ns . It can be used as the delay period between two data intervals.

3. Programming

1. Full Erase Procedure

1) Full erase waveform drawing

2) Write code

//`timescale1ns/1ns
/*
Module Name : flash_ce
Project Name: flash
Description : flash全擦除模块
把主时钟四分频成12.5MHz,作为spi的输入时钟。
写一次数据与下一次数据之间必须等待50ns,每个时钟周期只能写入1bit数据,写一个字节即需要8个spi时钟周期,即32个系统时钟周期,说明一条完整指令需要640ns

*/

module flash_ce(
  input wire sys_clk,  //系统时钟,频率50MHz   
  input wire sys_rst_n,  //复位信号,低电平有效
  input wire key,    //按键输入信号 

  output reg spi_cs_n,  //片选信号   
  output reg spi_clk, //串行时钟   
  output reg spi_mosi //主输出从输入数据
);



//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//
//parameter define
parameter IDLE  = 4'b0001 , //初始状态 状态机四个状态
    WR_EN = 4'b0010 , //写状态
    DELAY = 4'b0100 , //等待状态
    CE  = 4'b1000 ; //全擦除状态
parameter WR_EN_INST= 8'b0000_0110, //写使能指令06
    CE_INST = 8'b1100_0111; //全擦除指令C7



//reg define
reg [2:0] cnt_byte; //字节计数器 记录输出字节个数和等待时间
reg [3:0] state ; //状态机状态
reg [4:0] cnt_clk ; //系统时钟计数器,用以记录单子字节
reg [1:0] cnt_sck ; //串行时钟计数器,生成系统时钟
reg [2:0] cnt_bit ; //比特计数器,产生高低位,控制MOSI输出

//除了在空闲状态,其他状态都进行系统时钟计数器,如果只使用cnt_clk作为状态跳转的约束条件不充分,
always@(posedge sys_clk or negedge sys_rst_n)
begin
  if(!sys_rst_n)
  cnt_clk <= 5'd0;
  else if(state != IDLE)
  cnt_clk <= cnt_clk + 1'b1;
end

//由于状态跳转的约束条件不充分,所以使用cnt_byte 计数器对cnt_clk的计数周期进行计数,同时使用cnt_byte增加一次表示延时640ns
always@(posedge sys_clk or negedge sys_rst_n)
begin
  if(!sys_rst_n)
  cnt_byte <= 3'd0;
  else if((cnt_clk == 5'd31) && (cnt_byte == 3'd6))//当写完擦除指令后,等待640ns,片选拉高,此时cnt_byte = 6,并且刚好cnt_clk进行一个计数循环,就清零
  cnt_byte <= 3'd0;
  else if(cnt_clk == 5'd31)//cnt_clk每完成一个循环周期cnt_byte就加1,其他不变
  cnt_byte <= cnt_byte + 1'b1;
end

//在进行写使能指令以及全擦除指令,并且已经发送一个字节时,记录系统时钟的个数
always@(posedge sys_clk or negedge sys_rst_n)
begin
  if(!sys_rst_n)
  cnt_sck <= 2'd0;
  else if((state == WR_EN) && (cnt_byte == 1'b1)) // 当进行写使能时,先等待640ns,即cnt_byte =1
  cnt_sck <= cnt_sck + 1'b1;
  else if((state == CE) && (cnt_byte == 3'd5)) //当写完使能信号,等待640ns,再片选拉高,继续等待640ns,再片选拉低,继续等待640ns,此时cnt_byte =5,此时又开始写擦除指令
  cnt_sck <= cnt_sck + 1'b1;
end

//进行四分频,产生12.5MHz时钟.根据cnt_sck 记录系统时钟的个数,2个cnt_sck为低,2个cnt_sck为高
always@(posedge sys_clk or negedge sys_rst_n)
begin 
  if(!sys_rst_n)
  spi_clk <= 1'b0;
  else if(cnt_sck == 2'd0)
  spi_clk <= 1'b0;
  else if(cnt_sck == 2'd2)
  spi_clk <= 1'b1;

end

//片选信号输出
always@(posedge sys_clk or negedge sys_rst_n)
begin
  if(!sys_rst_n)
  spi_cs_n <= 1;
  else if(key == 1'b1)
  spi_cs_n <= 0;
  else if((cnt_byte == 3'd2) && (cnt_clk == 5'd31) && (state == WR_EN))
  spi_cs_n <= 1;
  else if((cnt_byte == 3'd3) && (cnt_clk == 5'd31) && (state == DELAY))
  spi_cs_n <= 0; 
  else if((cnt_byte == 3'd6) && (cnt_clk == 5'd31) && (state == CE))
  spi_cs_n <= 1;
end

//cnt_bit 高低位对调,控制MOSI输出。用于输出MOSI的哪一位
always@(posedge sys_clk or negedge sys_rst_n)
begin 
  if(!sys_rst_n)
  cnt_bit <= 3'd0;
  else if(cnt_clk == 2'd2)
  cnt_bit <= cnt_bit + 1'b1;
end

//state 状态机跳转
always@(posedge sys_clk or negedge sys_rst_n)
begin 
  if(!sys_rst_n)
  state <= IDLE;
  else 
  case(state)
    IDLE:if(key == 1'b1)
      state <= WR_EN;
    WR_EN:if((cnt_byte == 3'd2) && (cnt_clk == 5'd31))
      state <= DELAY;
    DELAY:if((cnt_byte == 3'd3) && (cnt_clk == 5'd31))
      state <= CE;
    CE:if((cnt_byte == 3'd6) && (cnt_clk == 5'd31))
      state <= IDLE;
    default:
      state <= IDLE;
  endcase
end


//MOSI输出
always@(posedge sys_clk or negedge sys_rst_n)
begin 
  if(!sys_rst_n)
  spi_mosi <= 1'b0;
  else if((state == WR_EN) && (cnt_byte == 3'd2))
  spi_mosi <= 1'b0;
  else if((state == CE) && (cnt_byte == 3'd6))
  spi_mosi <= 1'b0;
  else if((state == WR_EN) && (cnt_byte == 3'd1) && (cnt_sck == 5'd0))
  spi_mosi <= WR_EN_INST[7-cnt_bit];
  else if((state == CE) && (cnt_byte == 3'd5) && (cnt_sck == 5'd0))
  spi_mosi <= CE_INST[7-cnt_bit]; 
end


endmodule

3) Co-simulation with Modelsim . (For the co-simulation video, please refer to the B station Gaoyun Semiconductor video tutorial Gaoyun

Create a project file, add related files to the project, and cancel optimization. This simulation uses the M25P16 simulation module for simulation. The simulation waveform is as follows:

Write Enable

Erase instruction

Erase Complete

4 ) Online logic analyzer waveform

a . When setting the pin, the MSPI pin is used , so please right-click on the Process page and select configuration , as shown in the figure, and select MSPI as the regular pin in Dual-purpose . Otherwise, an error will appear during compilation.

Compile Errors

b . Create a GAO file; refer to the tutorial of the forum master for detailed steps. The link is as follows:

[Evaluation of domestic FPGA Gaoyun GW1N-4 series development board]——4. Use of embedded logic analyzer - Domestic chip exchange - Electronic Engineering World Forum (eeworld.com.cn)

c . On the online logic analysis page, I made a mistake. I jumped the jumper cap to JTAG mode in advance, but I still used USB download. As a result, the program could not be downloaded and it prompted that the code did not match. In fact, the GWIN1-4B MINI development board already has JTAG download, which uses the FT232H chip to support the JTAG download mode. This mistake made me stagnant for a few days. Thanks to the forum leader @gs001588 for his help . Thank you very much.

d . The online logic waveform is not uploaded because there is no screenshot

2. Page code writing

1 ) Page write waveform drawing, reference timing drawing

2 ) Write code according to the waveform diagram

moduleflash_pp_ctrl(

  input wire    sys_clk , //系统时钟,频率50MHz
  input wire    sys_rst_n , //复位信号,低电平有效
  input wire    key   , //按键输入信号

  outputreg     cs_n  , //片选信号
  outputreg     sck   , //串行时钟
  outputreg     mosi    //主输出从输入数据

);

//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//

//parameter define
parameter IDLE  = 4'b0001 , //初始状态
    WR_EN = 4'b0010 , //写状态
    DELAY = 4'b0100 , //等待状态
    PP  = 4'b1000 ; //页写状态
parameter WR_EN_INST  = 8'b0000_0110, //写使能指令
    PP_INST   = 8'b0000_0010; //页写指令
parameter SECTOR_ADDR = 8'b0000_0000, //扇区地址
    PAGE_ADDR   = 8'b0000_0100, //页地址
    BYTE_ADDR   = 8'b0010_0101; //字节地址
parameter NUM_DATA  = 8'd100  ; //页写数据个数(0-99)

//reg define
reg [7:0] cnt_byte  ; //字节计数器
reg [3:0] state   ; //状态机状态
reg [4:0] cnt_clk   ; //系统时钟计数器
reg [1:0] cnt_sck   ; //串行时钟计数器
reg [2:0] cnt_bit   ; //比特计数器
reg [7:0] data    ; //页写入数据

//********************************************************************//
//***************************** Main Code ****************************//
//********************************************************************//

//cnt_clk:系统时钟计数器,用以记录单个字节
always@(posedge sys_clk ornegedge sys_rst_n)
  if(sys_rst_n == 1'b0)
  cnt_clk<=5'd0;
  else  if(state != IDLE)
  cnt_clk<=cnt_clk + 1'b1;

//cnt_byte:记录输出字节个数和等待时间
always@(posedge sys_clk ornegedge sys_rst_n)
  if(sys_rst_n == 1'b0)
  cnt_byte  <=8'd0;
  else  if((cnt_clk == 5'd31) && (cnt_byte == NUM_DATA + 8'd9))
  cnt_byte  <=8'd0;
  else  if(cnt_clk == 5'd31)
  cnt_byte  <=cnt_byte + 1'b1;

//cnt_sck:串行时钟计数器,用以生成串行时钟
always@(posedge sys_clk ornegedge sys_rst_n)
  if(sys_rst_n == 1'b0)
  cnt_sck <=2'd0;
  else  if((state == WR_EN) && (cnt_byte == 8'd1))
  cnt_sck <=cnt_sck + 1'b1;
  else  if((state == PP) && (cnt_byte >= 8'd5)
      && (cnt_byte <= NUM_DATA + 8'd9 - 1'b1))
  cnt_sck <=cnt_sck + 1'b1;

//cs_n:片选信号
always@(posedge sys_clk ornegedge sys_rst_n)
  if(sys_rst_n == 1'b0)
  cs_n  <=1'b1;
  else  if(key == 1'b1)
  cs_n  <=1'b0;
  else  if((cnt_byte == 8'd2) && (cnt_clk == 5'd31) && (state == WR_EN))
  cs_n  <=1'b1;
  else  if((cnt_byte == 8'd3) && (cnt_clk == 5'd31) && (state == DELAY))
  cs_n  <=1'b0;
  else  if((cnt_byte == NUM_DATA + 8'd9) && (cnt_clk == 5'd31) && (state == PP))
  cs_n  <=1'b1;

//sck:输出串行时钟
always@(posedge sys_clk ornegedge sys_rst_n)
  if(sys_rst_n == 1'b0)
  sck <=1'b0;
  else  if(cnt_sck == 2'd0)
  sck <=1'b0;
  else  if(cnt_sck == 2'd2)
  sck <=1'b1;

//cnt_bit:高低位对调,控制mosi输出
always@(posedge sys_clk ornegedge sys_rst_n)
  if(sys_rst_n == 1'b0)
  cnt_bit <=3'd0;
  else  if(cnt_sck == 2'd2)
  cnt_bit <=cnt_bit + 1'b1;

//data:页写入数据
always@(posedge sys_clk ornegedge sys_rst_n)
  if(sys_rst_n == 1'b0)
  data <=8'd0;
  else  if((cnt_clk == 5'd31) && ((cnt_byte >= 8'd9)
      && (cnt_byte < NUM_DATA + 8'd9 - 1'b1)))
  data <=data + 1'b1;

//state:两段式状态机第一段,状态跳转
always@(posedge sys_clk ornegedge sys_rst_n)
  if(sys_rst_n == 1'b0)
  state <=IDLE;
  else
  case(state)
  IDLE: if(key == 1'b1)
      state <=WR_EN;
  WR_EN:if((cnt_byte == 8'd2) && (cnt_clk == 5'd31))
      state <=DELAY;
  DELAY:if((cnt_byte == 8'd3) && (cnt_clk == 5'd31))
      state <=PP;
  PP: if((cnt_byte == NUM_DATA + 8'd9) && (cnt_clk == 5'd31))
      state <=IDLE;
  default:  state <=IDLE;
  endcase

//mosi:两段式状态机第二段,逻辑输出
always@(posedge sys_clk ornegedge sys_rst_n)
  if(sys_rst_n == 1'b0)
  mosi  <=1'b0;
  else  if((state == WR_EN) && (cnt_byte== 8'd2))
  mosi  <=1'b0;
  else  if((state == PP) && (cnt_byte == NUM_DATA + 8'd9))
  mosi  <=1'b0;
  else  if((state == WR_EN) && (cnt_byte == 8'd1) && (cnt_sck == 5'd0))
  mosi  <=WR_EN_INST[7 - cnt_bit];//写使能指令
  else  if((state == PP) && (cnt_byte == 8'd5) && (cnt_sck == 5'd0))
  mosi  <=PP_INST[7 - cnt_bit];  //页写指令
  else  if((state == PP) && (cnt_byte == 8'd6) && (cnt_sck == 5'd0))
  mosi  <=SECTOR_ADDR[7 - cnt_bit];//扇区地址
  else  if((state == PP) && (cnt_byte == 8'd7) && (cnt_sck == 5'd0))
  mosi  <=PAGE_ADDR[7 - cnt_bit];  //页地址
  else  if((state == PP) && (cnt_byte == 8'd8) && (cnt_sck == 5'd0))
  mosi  <=BYTE_ADDR[7 - cnt_bit];  //字节地址
  else  if((state == PP) && ((cnt_byte >= 8'd9)
      && (cnt_byte <= NUM_DATA + 8'd9 - 1'b1)) && (cnt_sck == 5'd0))
  mosi  <=data[7 - cnt_bit];//页写入数据

endmodule

3 ) Online logic diagram waveform

Write Enable

Write instruction

Write Address

This post is from Domestic Chip Exchange

Latest reply

Thumbs up, thumbs up, the review article helped other forum members   Details Published on 2021-12-30 09:36
 
 

1366

Posts

6

Resources
2
 

Clear and concise, I envy those who can use FPGA

This post is from Domestic Chip Exchange
 
 
 

664

Posts

104

Resources
3
 

Good, you do it as soon as you say it, your efficiency is amazing!

What software did you use to draw the timing diagram? The effect is very good.

This post is from Domestic Chip Exchange

Comments

Thanks to your help.  Details Published on 2021-12-29 08:12
 
 
 

6547

Posts

0

Resources
4
 

The timing diagram is very professional

This post is from Domestic Chip Exchange

Comments

Thank you for your praise  Details Published on 2021-12-29 08:12
 
 
 

270

Posts

0

Resources
5
 
gs001588 posted on 2021-12-28 21:38 Not bad, you do it right away, the efficiency is awesome! What software did you use to draw the timing diagram? The effect is very good

Thanks to your help.

This post is from Domestic Chip Exchange

Comments

Thumbs up, thumbs up, the review article helped other forum members:)  Details Published on 2021-12-30 09:36
 
 
 

270

Posts

0

Resources
6
 
Jacktang posted on 2021-12-29 07:17 The timing diagram is very professional

Thank you for your praise

This post is from Domestic Chip Exchange
 
 
 

2w

Posts

74

Resources
7
 
Posted by A Young Man's Dream on 2021-12-29 08:12 Thanks to your help. Use Visio software to draw it

Thumbs up, thumbs up, the review article helped other forum members:)

This post is from Domestic Chip Exchange
Add and join groups EEWorld service account EEWorld subscription account Automotive development circle
Personal signature

加油!在电子行业默默贡献自己的力量!:)

 
 
 

Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

Featured Posts
Some experience summary on AD conversion design

I saw a blog post about the basic issues in AD conversion design, so I reposted it here to share with you. Understanding ...

Brushless motor drive control hardware circuit sharing

In our work, we often encounter problems with the coordination between hardware and software, which affects our work eff ...

Please help explain how the resistor values shown in the figure are estimated. Thank you

This circuit controls a micro DC motor to rotate forward and reverse to open and close the water meter valve. Please hel ...

STM32 timer (automatic reload) experience sharing

This post was last edited by annysky2012 on 2021-2-5 14:19 A netizen posted a message on the forum asking for advice. T ...

[Silicon Labs Development Kit Review] + Serial port printing temperature and humidity sensor Si7021 data

The EFM32PG22 Dev Kit has an I2C interface digital temperature and humidity sensor Si7021 on board. The main parameters ...

34 "Ten Thousand Miles" Raspberry Pi Car——Installation of ROS Noetic on Ubuntu System

This post was last edited by lb8820265 on 2022-4-16 00:54 Ubuntu is installed for the purpose of installing ROS. The of ...

[NUCLEO-WBA52CG STM32 wireless product family new series] +2, hardware i2c driver temperature and humidity sensor SHT40

This post was last edited by dql2016 on 2023-7-30 22:04 I have a Grove SHT40 sensor module, as shown in the figure belo ...

Staying up late makes people become wretched, so I decided to stop staying up late

During the past three years of the epidemic, I have been unlucky for three years due to my own mistakes. Although it has ...

MCU sharing 2

This post was last edited by Yin Xiaozhou on 2024-3-30 11:16 Purpose We use the button controls to control the RGB o ...

【2024 DigiKey Innovation Competition】Smart Home Control Center

This post was last edited by Netseye on 2024-10-28 12:52 1. Introduction This work uses ESP32-S3-LCD-EV-BOARD and STEMM ...

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list