当前位置:   article > 正文

FPGA接口_N25Q128型号的spi flash驱动verilog代码编写_和美光n25q128命令兼容的flash

和美光n25q128命令兼容的flash

# N25Q128型号的spi flash驱动verilog代码编写

提示:使用正点原子达芬奇pro做的小例子,由于教程中无flash的读写,因此撰写记录



前言

主要实现标准的spi_flash读写,以及4路quad_spi_flash读写

一、阅读datasheet

通过datasheet知道他的工作时序,实现读写。

1. 查看第4章

可以看到该spi有3种模式

在这里插入图片描述

2. 查看第6章

可以看到flash状态寄存器的信息,当我们执行擦除、读写之类的命令后,有时是需要查看一下状态寄存器的,确保之前的指令执行完成后,再进行下一步的操作。

在这里插入图片描述状态寄存器

3. 查看第9章

这章节就包含了读写之类的时序,根据这里的时序编写状态机就行了。9.1是传统标准的spi时序(其中也有两路和四路的spi读写),9.2是两路的,9.3是四路的
在这里插入图片描述
在这里插入图片描述

二、注意事项

代码的编写,写了两种,一种是传统spi的,一种是四路的quad_spi的,但用的时序都是datasheet第9.1里的时序。试过用9.3的时序实现四路的spi,但读出的状态寄存器不太对头,就暂时没有尝试了。因为用9.1里的时序也能实现。
(这里代码借鉴了https://www.cnblogs.com/liujinggang/p/9651170.html)
基本上标准上spi和四路的quad_spi的工作时序和借鉴处代码相同。就配寄存器的值不太一样等一些小细节不同。所以就不列出太多代码了。
只讲几个需要注意的地方

1. 第一个注意的地方,就是要用STARTUPE2 的原语

因为外部存储器的时钟管脚一般与fpga的CCLK_0连接,这时时钟管脚已经连接到CCLK_0,但我们想要自己制造spi_flash的时钟来使用,这时STARTUPE2就派上用场了
代码如下:

//给予flash时钟    
 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_inst
(
.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(0), // 1-bit input: User start-up clock input
.GSR(0), // 1-bit input: Global Set/Reset input (GSR cannot be used for the port name)
.GTS(0), // 1-bit input: Global 3-state input (GTS cannot be used for the port name)
.KEYCLEARB(1), // 1-bit input: Clear AES Decrypter Key input from Battery-Backed RAM (BBRAM)
.PACK(1), // 1-bit input: PROGRAM acknowledge input
.USRCCLKO(f_clk), // 1-bit input: User CCLK input**将SPI的时钟链接到这里**
.USRCCLKTS(0), // 1-bit input: User CCLK 3-state enable input
.USRDONEO(1), // 1-bit input: User DONE pin output control
.USRDONETS(1) // 1-bit input: User DONE 3-state enable outpu
);   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

1. 第二个需要注意的地方就是vivado想要进行debug的时候,用inout类型是不能debug的

第二个需要注意的地方就是vivado想要进行debug的时候,用inout类型是不能debug的会报错,所以需要用iobuf原语,再对T_qspi_io0和R_qspi_io0进行debug。(T_qspi_io0相当于flash输出的数据,R_qspi_io0相当于flash输入的数据)
代码如下:

//wire T_qspi_io0;
IOBUF #(
  .DRIVE(12), // Specify the output drive strength
  .IBUF_LOW_PWR("TRUE"),  // Low Power - "TRUE", High Performance = "FALSE"
  .IOSTANDARD("DEFAULT"), // Specify the I/O standard
  .SLEW("SLOW") // Specify the output slew rate
) IOBUF_inst0 (
  .O(T_qspi_io0),     // Buffer output
  .IO(IO_qspi_io0),   // Buffer inout port (connect directly to top-level port)
  .I(R_qspi_io0),     // Buffer input
  .T(~R_qspi_io0_out_en)      // 3-state enable input, high=input, low=output
);  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

总结

对N25Q128_flash的驱动撰写心得就是这些。

部分代码

可以参考https://www.cnblogs.com/liujinggang/p/9651170.html尝试,里面讲的很好

`timescale 1ns / 1ps

module flash_driver
(
output                  O_qspi_clk          , // QSPI Flash Quad SPI(QPI)总线串行时钟线
output reg              O_qspi_cs           , // QPI总线片选信号
inout                   IO_qspi_io0         , // QPI总线输入/输出信号线
inout                   IO_qspi_io1         , // QPI总线输入/输出信号线
inout                   IO_qspi_io2         , // QPI总线输入/输出信号线
inout                   IO_qspi_io3         , // QPI总线输入/输出信号线
//----------------------------------------------
output                   T_qspi_io0,
output                   T_qspi_io1,
output                   T_qspi_io2,
output                   T_qspi_io3,

output       reg            R_qspi_io0,
output       reg            R_qspi_io1,
output       reg            R_qspi_io2,
output       reg           R_qspi_io3,
//-----------------------------------------------
                                            
input                   I_rst_n             , // 复位信号

input                   I_clk_25M           , // 25MHz时钟信号
input       [4:0]       I_cmd_type          , // 命令类型
input       [7:0]       I_cmd_code          , // 命令码
input       [23:0]      I_qspi_addr         , // QSPI Flash地址

output reg              O_done_sig          , // 指令执行结束标志
output reg  [7:0]       O_read_data         , // 从QSPI Flash读出的数据
output reg              O_read_byte_valid   , // 读一个字节完成的标志
output reg  [3:0]       O_qspi_state          // 状态机,用于在顶层调试用
);

parameter   C_IDLE            =   4'b0000  ; // 空闲状态
parameter   C_SEND_CMD        =   4'b0001  ; // 发送命令码
parameter   C_SEND_ADDR       =   4'b0010  ; // 发送地址码
parameter   C_READ_WAIT       =   4'b0011  ; // 读等待
parameter   C_WRITE_DATA      =   4'b0101  ; // 写数据
parameter   C_FINISH_DONE     =   4'b0110  ; // 一条指令执行结束

parameter     C_WRITE_DATA_QUAD =   4'b1000  ; // 四线模式写数据到QSPI Flash
parameter     C_DUMMY           =   4'b1001  ; // 四线模式读数据需要8个时钟周期的dummy clock,这可以加快读数据的速度
parameter     C_READ_WAIT_QUAD  =   4'b1010  ; // 四线模式读等待状态

reg         R_qspi_io0_out_en   ;
reg         R_qspi_io1_out_en   ;
reg         R_qspi_io2_out_en   ;
reg         R_qspi_io3_out_en   ;

reg         [7:0]   R_read_data_reg     ; // 从Flash中读出的数据用这个变量进行缓存,等读完了在把这个变量的值给输出
reg                 R_qspi_clk_en       ; // 串行时钟使能信号
reg                 R_data_come_single  ; // 单线操作读数据使能信号,当这个信号为高时
reg                 R_data_come_quad      ; // 单线操作读数据使能信号,当这个信号为高时
           
reg         [7:0]   R_cmd_reg           ; // 命令码寄存器
reg         [23:0]  R_address_reg       ; // 地址码寄存器 
reg         [7:0]   R_write_bits_cnt    ; // 写bit计数器,写数据之前把它初始化为7,发送一个bit就减1
reg         [8:0]   R_write_bytes_cnt   ; // 写字节计数器,发送一个字节数据就把它加1
reg         [7:0]   R_read_bits_cnt     ; // 写bit计数器,接收一个bit就加1
reg         [8:0]   R_read_bytes_cnt    ; // 读字节计数器,接收一个字节数据就把它加1
reg         [8:0]   R_read_bytes_num    ; // 要接收的数据总数
reg                 R_read_finish       ; // 读数据结束标志位

wire        [7:0]   W_rom_addr          ;  
wire        [7:0]   W_rom_out           ;  

assign O_qspi_clk = R_qspi_clk_en ? I_clk_25M : 0   ; // 产生串行时钟信号
assign W_rom_addr = R_write_bytes_cnt               ;

// QSPI IO方向控制
//assign IO_qspi_io0     =   R_qspi_io0_out_en ? R_qspi_io0 : 1'bz ;                
//assign IO_qspi_io1     =   R_qspi_io1_out_en ? R_qspi_io1 : 1'bz ;                
//assign IO_qspi_io2     =   R_qspi_io2_out_en ? R_qspi_io2 : 1'bz ;                
//assign IO_qspi_io3     =   R_qspi_io3_out_en ? R_qspi_io3 : 1'bz ; 

//wire T_qspi_io0;
IOBUF #(
  .DRIVE(12), // Specify the output drive strength
  .IBUF_LOW_PWR("TRUE"),  // Low Power - "TRUE", High Performance = "FALSE"
  .IOSTANDARD("DEFAULT"), // Specify the I/O standard
  .SLEW("SLOW") // Specify the output slew rate
) IOBUF_inst0 (
  .O(T_qspi_io0),     // Buffer output
  .IO(IO_qspi_io0),   // Buffer inout port (connect directly to top-level port)
  .I(R_qspi_io0),     // Buffer input
  .T(~R_qspi_io0_out_en)      // 3-state enable input, high=input, low=output
);
//wire T_qspi_io1;
IOBUF #(
  .DRIVE(12), // Specify the output drive strength
  .IBUF_LOW_PWR("TRUE"),  // Low Power - "TRUE", High Performance = "FALSE"
  .IOSTANDARD("DEFAULT"), // Specify the I/O standard
  .SLEW("SLOW") // Specify the output slew rate
) IOBUF_inst1 (
  .O(T_qspi_io1),     // Buffer output
  .IO(IO_qspi_io1),   // Buffer inout port (connect directly to top-level port)
  .I(R_qspi_io1),     // Buffer input
  .T(~R_qspi_io1_out_en)      // 3-state enable input, high=input, low=output
);
//wire T_qspi_io2;
IOBUF #(
  .DRIVE(12), // Specify the output drive strength
  .IBUF_LOW_PWR("TRUE"),  // Low Power - "TRUE", High Performance = "FALSE"
  .IOSTANDARD("DEFAULT"), // Specify the I/O standard
  .SLEW("SLOW") // Specify the output slew rate
) IOBUF_inst2 (
  .O(T_qspi_io2),     // Buffer output
  .IO(IO_qspi_io2),   // Buffer inout port (connect directly to top-level port)
  .I(R_qspi_io2),     // Buffer input
  .T(~R_qspi_io2_out_en)      // 3-state enable input, high=input, low=output
);
//wire T_qspi_io3;
IOBUF #(
  .DRIVE(12), // Specify the output drive strength
  .IBUF_LOW_PWR("TRUE"),  // Low Power - "TRUE", High Performance = "FALSE"
  .IOSTANDARD("DEFAULT"), // Specify the I/O standard
  .SLEW("SLOW") // Specify the output slew rate
) IOBUF_inst3 (
  .O(T_qspi_io3),     // Buffer output
  .IO(IO_qspi_io3),   // Buffer inout port (connect directly to top-level port)
  .I(R_qspi_io3),     // Buffer input
  .T(~R_qspi_io3_out_en)      // 3-state enable input, high=input, low=output
);

// 功能:用时钟的下降沿发送数据

always @(negedge I_clk_25M)
begin
    if(!I_rst_n)
        begin
            O_qspi_cs           <=  1'b1   ;        
            O_qspi_state        <=  C_IDLE ;
            R_cmd_reg           <=  0      ;
            R_address_reg       <=  0      ;
            R_qspi_clk_en       <=  1'b0   ;  //SPI clock输出不使能
            R_write_bits_cnt    <=  0      ;
            R_write_bytes_cnt   <=  0      ;
            R_read_bytes_num    <=  0      ;    
            R_address_reg       <=  0      ;
            O_done_sig          <=  1'b0   ;
            R_data_come_single  <=  1'b0   ;           
        end
    else
        begin
            case(O_qspi_state)
                C_IDLE:  // 初始化各个寄存器,当检测到命令类型有效(命令类型的最高位位1)以后,进入发送命令码状态
                    begin                              
                        R_qspi_clk_en  <=   1'b0         ;
                        O_qspi_cs      <=   1'b1         ;
                        R_qspi_io0    <=   1'b0         ;    
                        R_cmd_reg      <=   I_cmd_code   ;
                        R_address_reg  <=   I_qspi_addr  ;
                        O_done_sig     <=   1'b0         ; 
                        R_qspi_io3_out_en   <=   1'b0         ; // 设置IO_qspi_io3为高阻
                        R_qspi_io2_out_en   <=   1'b0         ; // 设置IO_qspi_io2为高阻
                        R_qspi_io1_out_en   <=   1'b0         ; // 设置IO_qspi_io1为高阻
                        R_qspi_io0_out_en   <=   1'b0         ; // 设置IO_qspi_io0为高阻
                                                           
                        if(I_cmd_type[4] == 1'b1) 
                            begin                //如果flash操作命令请求
                                O_qspi_state        <=  C_SEND_CMD  ;
                                R_write_bits_cnt    <=  7           ;        
                                R_write_bytes_cnt   <=  0           ;
                                R_read_bytes_num    <=  0           ;                    
                            end
                    end
                C_SEND_CMD: // 发送8-bit命令码状态 
                    begin
                        R_qspi_io0_out_en   <=  1'b1    ;   // 设置IO0为输出                    
                        R_qspi_clk_en       <=  1'b1    ; // 打开SPI串行时钟SCLK的使能开关
                        O_qspi_cs           <=  1'b0    ; // 拉低片选信号CS
                        if((I_cmd_type[3:0] == 4'b1000) ||  (I_cmd_type[3:0] == 4'b1001) )
                            begin
                                R_qspi_io3_out_en   <=  1'b1;   // 设置IO0为输出                              
                            end
                        if(R_write_bits_cnt > 0) 
                            begin                           //如果R_cmd_reg还没有发送完
                                R_qspi_io0        <=  R_cmd_reg[R_write_bits_cnt] ;         //发送bit7~bit1位
                                R_qspi_io3         <= 1'b1; 
                                R_write_bits_cnt   <=  R_write_bits_cnt-1'b1       ;
                            end                            
                        else 
                            begin                                 //发送bit0
                                R_qspi_io0 <=  R_cmd_reg[0]    ;
                                if ((I_cmd_type[3:0] == 4'b0001) | (I_cmd_type[3:0] == 4'b0100)) 
                                    begin    //如果是写使能指令(Write Enable)或者写不使能指令(Write Disable)
                                        O_qspi_state    <=  C_FINISH_DONE   ;
                                    end                          
                                else if (I_cmd_type[3:0] == 4'b0011) 
                                    begin    //如果是读状态寄存器指令(Read Register)
                                        O_qspi_state        <=  C_READ_WAIT ;
                                        R_write_bits_cnt    <=  7           ;
                                        R_read_bytes_num    <=  2           ;//读状态寄存器指令需要接收一个数据 
                                    end
								else if(I_cmd_type[3:0] == 4'b0000)//读设备ID指令(Read Device ID) 
									begin
                                        O_qspi_state        <=  C_READ_WAIT ;
                                        R_read_bytes_num    <=  20          ; // 									
									end
                                else if( (I_cmd_type[3:0] == 4'b0010) ||
                                         (I_cmd_type[3:0] == 4'b0101) || 
                                         (I_cmd_type[3:0] == 4'b0111) ||
                                         (I_cmd_type[3:0] == 4'b1000)   // 如果是四线模式页编程指令(Quad Page Program)                                       
                                         )  
                                    begin // 如果是扇区擦除(Sector Erase),页编程指令(Page Program),读数据指令(Read Data)                        
                                        O_qspi_state        <=  C_SEND_ADDR ;
                                        R_write_bits_cnt    <=  23          ; // 这几条指令后面都需要跟一个24-bit的地址码
                                    end
                                 else if(I_cmd_type[3:0] == 4'b1001) // 如果是四线模式读数据指令(Quad Read Data) 
                                    begin
                                         O_qspi_state        <=  C_SEND_ADDR ;
                                         R_write_bits_cnt    <= 23         ; // 这几条指令后面都需要跟一个24-bit的地址码                                   
                                    end
                            end
                    end
                C_SEND_ADDR: // 发送地址状态
                    begin
                        if(R_write_bits_cnt > 0)  //如果R_cmd_reg还没有发送完
                            begin                                 
                                R_qspi_io0        <=  R_address_reg[R_write_bits_cnt] ; //发送bit23~bit1位
                                R_write_bits_cnt   <=  R_write_bits_cnt    -   1       ;    
                            end                                 
                        else 
                            begin 
                                R_qspi_io0 <=  R_address_reg[0]    ;   //发送bit0
                                if(I_cmd_type[3:0] == 4'b0010) // 扇区擦除(Sector Erase)指令
                                    begin  //扇区擦除(Sector Erase)指令发完24-bit地址码就执行结束了,所以直接跳到结束状态
                                        O_qspi_state <= C_FINISH_DONE   ;    
                                    end
                                else if (I_cmd_type[3:0] == 4'b0101) // 页编程(Page Program)指令
                                    begin                              
                                        O_qspi_state        <=  C_WRITE_DATA    ;
                                        R_write_bits_cnt    <=  7               ;                       
                                    end                                                       
                                else if (I_cmd_type[3:0] == 4'b0111) // 读数据(Read Data)指令
                                    begin
                                        O_qspi_state        <=  C_READ_WAIT     ;
                                        R_read_bytes_num    <=  256             ;   //接收256个数据        
                                    end 
                                else if (I_cmd_type[3:0] == 4'b1000) 
                                    begin   //如果是四线模式页编程指令(Quad Page Program)                               
                                        O_qspi_state        <=  C_WRITE_DATA_QUAD   ;
                                        R_write_bits_cnt    <=  7                   ;                       
                                    end 
                                else if (I_cmd_type[3:0] == 4'b1001) 
                                    begin   //如果是四线读操作                               
                                        O_qspi_state        <=  C_DUMMY         ;
                                        R_read_bytes_num    <=  256             ; //接收256个数据    
                                        R_write_bits_cnt    <=  7               ;                      
                                    end                                       
                            end
                    end  
                C_DUMMY:  // 四线读操作之前需要等待8个dummy clock
                    begin  
                        R_qspi_io3_out_en   <=  1'b0            ; // 设置IO_qspi_io3为高阻
                        R_qspi_io2_out_en   <=  1'b0            ; // 设置IO_qspi_io2为高阻
                        R_qspi_io1_out_en   <=  1'b0            ; // 设置IO_qspi_io1为高阻
                        R_qspi_io0_out_en   <=  1'b0            ; // 设置IO_qspi_io0为高阻       
                        if(R_write_bits_cnt > 0)    
                            R_write_bits_cnt    <=  R_write_bits_cnt - 1 ;                                    
                        else 
                            O_qspi_state        <=  C_READ_WAIT_QUAD     ;                                          
                    end
                C_READ_WAIT_QUAD: // 四线模式读等待状态
                    begin   
                        if(R_read_finish)  
                            begin
                                O_qspi_state        <=  C_FINISH_DONE   ;
                                R_data_come_quad    <=  1'b0            ;
                            end
                        else
                            R_data_come_quad        <=  1'b1            ;
                    end
                C_WRITE_DATA_QUAD    :
                    begin
                        R_qspi_io0_out_en   <=  1'b1    ;   // 设置IO0为输出
                        R_qspi_io1_out_en   <=  1'b1    ;   // 设置IO1为输出
                        R_qspi_io2_out_en   <=  1'b1    ;   // 设置IO2为输出
                        R_qspi_io3_out_en   <=  1'b1    ;   // 设置IO3为输出                          
                        if(R_write_bytes_cnt == 9'd256)
                            begin
                                O_qspi_state   <=  C_FINISH_DONE    ;    
                                R_qspi_clk_en  <=  1'b0             ; 
                            end 
                        else
                            begin      
                                if(R_write_bits_cnt == 8'd3)
                                    begin
                                        R_write_bytes_cnt   <=  R_write_bytes_cnt + 1'b1         ;
                                        R_write_bits_cnt    <=  8'd7                             ;
                                        R_qspi_io3          <=  W_rom_out[3]                     ; // 分别发送bit3
                                        R_qspi_io2          <=  W_rom_out[2]                     ; // 分别发送bit2
                                        R_qspi_io1          <=  W_rom_out[1]                     ; // 分别发送bit1
                                        R_qspi_io0          <=  W_rom_out[0]                     ; // 分别发送bit0
                                    end
                                else
                                    begin
                                        R_write_bits_cnt    <=  R_write_bits_cnt - 4            ;
                                        R_qspi_io3          <=  W_rom_out[R_write_bits_cnt - 0] ; // 分别发送bit7
                                        R_qspi_io2          <=  W_rom_out[R_write_bits_cnt - 1] ; // 分别发送bit6
                                        R_qspi_io1          <=  W_rom_out[R_write_bits_cnt - 2] ; // 分别发送bit5
                                        R_qspi_io0          <=  W_rom_out[R_write_bits_cnt - 3] ; // 分别发送bit4
                                    end 
                            end                                            
                    end                                     
                C_READ_WAIT: // 读等待状态
                    begin
                        if(R_read_finish)  
                            begin
                                O_qspi_state        <=  C_FINISH_DONE   ;
                                R_data_come_single  <=  1'b0            ;
                            end
                        else
                            begin
                                R_data_come_single  <=  1'b1            ; // 单线模式下读数据标志信号,此信号为高标志正在接收数据
                            end
                    end
                C_WRITE_DATA: // 写数据状态
                    begin
                        if(R_write_bytes_cnt < 256) // 往QSPI Flash中写入 256个数据
                            begin                       
                                if(R_write_bits_cnt > 0) //如果数据还没有发送完
                                    begin                           
                                        R_qspi_io0         <=  W_rom_out[R_write_bits_cnt] ; //发送bit7~bit1位
                                        R_write_bits_cnt    <=  R_write_bits_cnt  - 1'b1    ;                        
                                    end                 
                                else 
                                    begin                                 
                                        R_qspi_io0         <=  W_rom_out[0]                ; //发送bit0
                                        R_write_bits_cnt    <=  7                           ;
                                        R_write_bytes_cnt   <=  R_write_bytes_cnt + 1'b1    ;
                                    end
                            end
                        else 
                            begin
                                O_qspi_state    <=  C_FINISH_DONE   ;
                                R_qspi_clk_en   <=  1'b0            ;
                            end
                    end
                C_FINISH_DONE:
                    begin
                        O_qspi_cs           <=  1'b1    ;
                        R_qspi_io0          <=  1'b0    ;
                        R_qspi_clk_en       <=  1'b0    ;
                        O_done_sig          <=  1'b1    ;
                        R_qspi_io3_out_en   <=  1'b0    ; // 设置IO_qspi_io3为高阻
                        R_qspi_io2_out_en   <=  1'b0    ; // 设置IO_qspi_io2为高阻
                        R_qspi_io1_out_en   <=  1'b0    ; // 设置IO_qspi_io1为高阻
                        R_qspi_io0_out_en   <=  1'b0    ; // 设置IO_qspi_io0为高阻                        
                        R_data_come_single  <=  1'b0    ;
                        R_data_come_quad    <=  1'b0    ;                        
                        O_qspi_state        <=  C_IDLE  ;
                    end
                default:O_qspi_state    <=  C_IDLE      ;
            endcase         
        end
end

//
// 功能:接收QSPI Flash发送过来的数据    
//
always @(posedge I_clk_25M)
begin
    if(!I_rst_n)
        begin
            R_read_bytes_cnt    <=  0       ;
            R_read_bits_cnt     <=  0       ;
            R_read_finish       <=  1'b0    ;
            O_read_byte_valid   <=  1'b0    ;
            R_read_data_reg     <=  0       ;
            O_read_data         <=  0       ;
        end
    else if(R_data_come_single)   // 此信号为高表示接收数据从QSPI Flash发过来的数据
        begin
            if(R_read_bytes_cnt < R_read_bytes_num) 
                begin            
                    if(R_read_bits_cnt < 7)  //接收一个Byte的bit0~bit6    
                        begin                         
                            O_read_byte_valid   <=  1'b0                               ;
                            R_read_data_reg     <=  {R_read_data_reg[6:0],T_qspi_io1} ;
                            R_read_bits_cnt     <=  R_read_bits_cnt +   1'b1           ;
                        end
                    else  
                        begin
                            O_read_byte_valid   <=  1'b1                               ;  //一个byte数据有效
                            O_read_data         <=  {R_read_data_reg[6:0],T_qspi_io1} ;  //接收bit7
                            R_read_bits_cnt     <=  0                                  ;
                            R_read_bytes_cnt    <=  R_read_bytes_cnt    +   1'b1       ;
                        end
                end                                               
            else 
                begin 
                    R_read_bytes_cnt    <=  0       ;
                    R_read_finish       <=  1'b1    ;
                    O_read_byte_valid   <=  1'b0    ;
                end
        end
    else if(R_data_come_quad)   
        begin
            if(R_read_bytes_cnt < R_read_bytes_num) 
                begin  //接收数据              
                    if(R_read_bits_cnt < 8'd1)
                        begin
                            O_read_byte_valid       <=  1'b0                    ;
                            R_read_data_reg         <=  {R_read_data_reg[3:0],T_qspi_io3,T_qspi_io2,T_qspi_io1,T_qspi_io0};//接收前四位
                            R_read_bits_cnt         <=  R_read_bits_cnt + 1     ; 
                        end
                    else    
                        begin
                            O_read_byte_valid       <=  1'b1                    ;
                            O_read_data             <=  {R_read_data_reg[3:0],T_qspi_io3,T_qspi_io2,T_qspi_io1,T_qspi_io0};  //接收后四位
                            R_read_bits_cnt         <=  0                       ;
                            R_read_bytes_cnt        <=  R_read_bytes_cnt + 1'b1 ;     
                        end
                end                               
            else 
                begin 
                    R_read_bytes_cnt    <=  0       ;
                    R_read_finish       <=  1'b1    ;
                    O_read_byte_valid   <=  1'b0    ;
                end
        end                              
    else 
        begin
            R_read_bytes_cnt    <=  0       ;
            R_read_bits_cnt     <=  0       ;
            R_read_finish       <=  1'b0    ;
            O_read_byte_valid   <=  1'b0    ;
            R_read_data_reg     <=  0       ;
        end
end         

rom_data rom_data_inst (
  .clka(I_clk_25M), // input clka
  .ena  (1'b1),
  .addra(W_rom_addr), // input [7 : 0] addra
  .douta(W_rom_out) // output [7 : 0] douta
);

endmodule   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • 360
  • 361
  • 362
  • 363
  • 364
  • 365
  • 366
  • 367
  • 368
  • 369
  • 370
  • 371
  • 372
  • 373
  • 374
  • 375
  • 376
  • 377
  • 378
  • 379
  • 380
  • 381
  • 382
  • 383
  • 384
  • 385
  • 386
  • 387
  • 388
  • 389
  • 390
  • 391
  • 392
  • 393
  • 394
  • 395
  • 396
  • 397
  • 398
  • 399
  • 400
  • 401
  • 402
  • 403
  • 404
  • 405
  • 406
  • 407
  • 408
  • 409
  • 410
  • 411
  • 412
  • 413
  • 414
  • 415
  • 416
  • 417
  • 418
  • 419
  • 420
  • 421
  • 422
  • 423
  • 424
  • 425
  • 426
  • 427
  • 428
  • 429
  • 430
  • 431
  • 432
  • 433
  • 434
  • 435
  • 436
  • 437
  • 438
  • 439
  • 440
  • 441
  • 442
声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号