栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

FPGA接口

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

FPGA接口

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

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


文章目录
    • # N25Q128型号的spi flash驱动verilog代码编写
  • 前言
  • 一、阅读datasheet
    • 1. 查看第4章
    • 2. 查看第6章
    • 3. 查看第9章
  • 二、注意事项
    • 1. 第一个注意的地方,就是要用STARTUPE2 的原语
    • 1. 第二个需要注意的地方就是vivado想要进行debug的时候,用inout类型是不能debug的
  • 总结
  • 部分代码


前言

主要实现标准的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. 第二个需要注意的地方就是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
);  

总结

对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   
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/297436.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号