SPI读写FLASH

一.SPI协议简介

  • 同步:SPI使用单独的数据线和单独的时钟线来控制着收发同步

  • 全双工:主机从机之间通过两条线传输数据,可以由主机发送给从机,也可以由从机发送给主机。并可以同时传输

  • 主机从机之间通过四根线交互.其中sclk为时钟信号,mosi为主机发送给从机的数据信号,miso为从机发送给主机的数据信号,cs_n为片选信号。(其中发送方式为MSB高位先发)
    在这里插入图片描述

  • 四种模式:
    `其中CPOL为时钟极性:空闲状态为高电平时为1,空闲状态为低电平时为0; CPHA为时钟相位:表示第一个边沿为0,表示第二个边沿为1;

    模式CPOLCPHA描述
    模式000sclk上升沿采样,sclk下降沿发送
    模式101sclk上升沿发送,sclk下降沿采样
    模式210sclk上升沿发送,sclk下降沿采样
    模式311sclk上升沿采样,sclk下降沿发送

    我们常用的是模式0和模式3

  • 模式0:

    CPOL = 0:空闲时为低电平,第一个跳变沿是上升沿,第二个跳变沿是下降沿。

    CPHA = 0:在第一个跳变沿(上升沿)采样
    在这里插入图片描述

  • 模式1:

    CPOL = 0:空闲时为低电平,第一个跳变沿是上升沿,第二个跳变沿是下降沿。

    CPHA = 1:在第二个跳变沿(下降沿)采样
    在这里插入图片描述

  • 模式2:

    CPOL = 1:空闲时为高电平,第一个跳变沿是下降沿,第二个跳变沿为上升沿。

    CPHA = 0:在第一个跳变沿(下降沿)采样
    在这里插入图片描述

  • 模式3:

    CPOL = 1:空闲时为高电平,第一个跳变沿是下降沿,第二个跳变沿为上升沿。

    CPHA = 1:在第二个跳变沿(上升沿)采样
    在这里插入图片描述

二.FLASH(M25P16)简介

  • 存储结构:FLASH包括32个扇区(sector),每个扇区包含256个页(page),每个页包含256个字节(byte)。因此,每个字节的存储地址需要8bit的扇区地址+8bit的页地址+8bit的字节地址才能定位。
  • 指令集
    在这里插入图片描述

常用的指令有WREN(读使能),RDID(读ID),RDSR(读状态寄存器),READ(读数据),PP(页编程),SE(扇区擦除)

  • 时间满足条件:页写,全擦除,扇区擦除指令执行完成需要一定的时间
    在这里插入图片描述

指令与指令之间需要相隔一段时间
在这里插入图片描述

三.指令操作(手册分析)

3.1 WREN写使能

  • 在执行PP,SE,BE,RESR指令前需要执行写使能操作。当片选信号拉低
    后,就开始执行写使能指令,接着传输指令。指令发送完后,片选信号置为高电平。其时序如下
    在这里插入图片描述

3.2 PP页编程

  • 页编程操作需要3字节的地址字节确定编程起始地址,操作空间在1-256字节,也就是说,最多写满一页。其时序如下
    在这里插入图片描述

3.3 SE扇区擦除

  • 在页编程前,需要进行扇区擦除操作(将扇区内所有字节都变为FFh),但是在扇区擦除前需要先执行写使能操作,扇区擦除需要3个字节的地址字节,其时序如下
    在这里插入图片描述

3.4 RDID读ID

  • RDID指令允许读取8位的制造商标识,然后读取两个字节的设备标识。设备标识由设备制造商指定,第一个字节表示内存类型(20h),第二个字节表示内存类型(20h),第三个字节表示设备的内存容量(15h)。
    在这里插入图片描述

  • 其时序如下
    在这里插入图片描述

3.5 RDSR读状态寄存器

  • 状态寄存器格式如下
    在这里插入图片描述

WIP:表示内存是否处于写状态寄存器、页编程或擦除周期。当设置为1时,表示设备处于工作状态,当设置为0时,表示设备处于空闲状态。

WEL:表示内部Write Enable Latch的状态。当设置为1时,内部写使能被设置,当设置为0时,表示没有接收写状态寄存器,页编程或擦除指令。

BP2、BP1、BP0:块保护(BP2,BP1, BP0)位是非易失性的。它们定义了被软件保护的区域的大小编程和擦除指令。这些位是用写状态寄存器(WRSR)指令写的。

  • 其时序如下
    在这里插入图片描述

3.6 READ读数据

  • 需要3字节的地址字节来确定开始读的位置,其时序如下
    在这里插入图片描述

四.总体设计

4.1状态转移图

  • 下图为spi_control模块的状态转移图
    在这里插入图片描述

4.2模块框图

在这里插入图片描述

4.3 spi_interface模块

/**************************************功能介绍***********************************
Date	: 
Author	: Alegg xy.
Version	: 
Description: 
*********************************************************************************/
    
//---------<模块及端口声名>------------------------------------------------------
module spi_interface( 
    input				clk			,
    input				rst_n		,
    input       [7:0]   data_in     ,
    input               data_in_vld ,
    output              master_ready,
    output  reg [7:0]   data_out    ,
    output              data_out_vld,
    output              done        ,

    input               miso        ,
    output  reg         sclk        ,
    output  reg         mosi        ,
    output  reg         cs_n        
);								 
//---------<参数定义>--------------------------------------------------------- 
    parameter   DIV = 4,//时钟分频倍数
                MAX_100ns = 5;//100ns

    //状态机参数定义
    localparam  IDLE        = 5'b00001,//
                DELAY_1     = 5'b00010,//
                DATA        = 5'b00100,//
                DELAY_2     = 5'b01000,//
                HOLD        = 5'b10000;//
    
    reg 	[4:0]	cstate     ;//现态
    reg		[4:0]	nstate     ;//次态

    wire    IDLE_DEALY_1;
    wire    DELAY_1_DATA;
    wire    DATA_DELAY_2;
    wire    DELAY_2_HOLD;
    wire    HOLD_IDLE   ;

    //fifo
    wire            fifo_empty;
    wire            fifo_full;
    wire    [7:0]   fifo_q;
    wire            fifo_rdreq;
    //时钟分频计数器
    reg			[1:0]	cnt_div	   	;
    wire				add_cnt_div	;
    wire				end_cnt_div	;
    //bit计数器
    reg			[2:0]	cnt_bit	   	;
    wire				add_cnt_bit	;
    wire				end_cnt_bit	;
    //延时计数器100ns
    reg			[2:0]	cnt_delay	   	;
    wire				add_cnt_delay	;
    wire				end_cnt_delay	;
//---------<内部信号定义>-----------------------------------------------------
    fifo	fifo_inst (
	    .aclr ( ~rst_n ),
	    .clock ( clk ),
	    .data ( data_in ),
	    .rdreq ( fifo_rdreq ),
	    .wrreq ( data_in_vld ),
	    .empty ( fifo_empty ),
	    .full ( fifo_full ),
	    .q ( fifo_q ),
	    .usedw (  )
	); 

    assign fifo_rdreq  = !fifo_empty && (cnt_div == DIV - 2) && (cnt_bit == 7) ; 

    //第一段:时序逻辑描述状态转移
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            cstate <= IDLE;
        end 
        else begin 
            cstate <= nstate;
        end 
    end
    
    //第二段:组合逻辑描述状态转移规律和状态转移条件
    always @(*) begin
        case(cstate)
            IDLE    :begin
                if (IDLE_DEALY_1) begin
                    nstate = DELAY_1;
                end
                else begin
                    nstate = cstate;
                end
            end
            DELAY_1 :begin
                if (DELAY_1_DATA) begin
                    nstate = DATA;
                end
                else begin
                    nstate = cstate;
                end
            end
            DATA    :begin
                if (DATA_DELAY_2) begin
                    nstate = DELAY_2;
                end
                else begin
                    nstate = cstate;
                end
            end
            DELAY_2 :begin
                if (DELAY_2_HOLD) begin
                    nstate = HOLD;
                end
                else begin
                    nstate = cstate;
                end
            end
            HOLD    :begin
                if (HOLD_IDLE) begin
                    nstate = IDLE;
                end
                else begin
                    nstate = cstate;
                end
            end
            default : nstate = IDLE;
        endcase
    end

    assign IDLE_DEALY_1 = (cstate == IDLE)      && !fifo_empty;
    assign DELAY_1_DATA = (cstate == DELAY_1)   && 1;
    assign DATA_DELAY_2 = (cstate == DATA)      && fifo_empty;
    assign DELAY_2_HOLD = (cstate == DELAY_2)   && 1;
    assign HOLD_IDLE    = (cstate == HOLD)      && end_cnt_delay;                

    //时钟分频    
    always @(posedge clk or negedge rst_n)begin 
       if(!rst_n)begin
            cnt_div <= 'd0;
        end 
        else if(add_cnt_div)begin 
            if(end_cnt_div)begin 
                cnt_div <= 'd0;
            end
            else begin 
                cnt_div <= cnt_div + 1'd1;
            end 
        end
    end 
    
    assign add_cnt_div = cstate == DATA;
    assign end_cnt_div = add_cnt_div && cnt_div == DIV - 1;
    
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            sclk <= 1;
        end
        else if (cstate == DATA && (cnt_div < (DIV >> 1))) begin
            sclk <= 0;
        end
        else begin
            sclk <= 1;
        end
    end
    
    //bit计数器           
    always @(posedge clk or negedge rst_n)begin 
       if(!rst_n)begin
            cnt_bit <= 'd0;
        end 
        else if(add_cnt_bit)begin 
            if(end_cnt_bit)begin 
                cnt_bit <= 'd0;
            end
            else begin 
                cnt_bit <= cnt_bit + 1'd1;
            end 
        end
    end 
    
    assign add_cnt_bit = end_cnt_div;
    assign end_cnt_bit = add_cnt_bit && cnt_bit == 7;

    //数据发送
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            mosi <= 1;
        end
        else if (cstate == DATA && (cnt_div == 0)) begin
            mosi <= fifo_q[7-cnt_bit];//MSB高位先发
        end
        else begin
            mosi <= mosi;
        end
    end
    
    //cs_n
    always @(*) begin
        if (!rst_n) begin
            cs_n = 1;
        end
        else if (cstate == IDLE || cstate == HOLD) begin
            cs_n = 1;
        end
        else begin
            cs_n = 0;
        end
    end
    
    //延时计数器
    always @(posedge clk or negedge rst_n)begin 
       if(!rst_n)begin
            cnt_delay <= 'd0;
        end 
        else if(add_cnt_delay)begin 
            if(end_cnt_delay)begin 
                cnt_delay <= 'd0;
            end
            else begin 
                cnt_delay <= cnt_delay + 1'd1;
            end 
        end
    end 
    
    assign add_cnt_delay = cstate == HOLD;
    assign end_cnt_delay = add_cnt_delay && cnt_delay == MAX_100ns - 1;
    
    //数据接收
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            data_out <= 0;
        end
        else if (cstate == DATA && (cnt_div == (DIV >> 1))) begin
            data_out <= {data_out[6:0],miso};
        end
    end

    assign data_out_vld = end_cnt_bit;
    assign done = HOLD_IDLE;
    assign master_ready = ~fifo_full;
    
endmodule

4.4 spi_control模块

/**************************************功能介绍***********************************
Date	: 
Author	: Alegg xy.
Version	: 
Description: 
*********************************************************************************/
    
//---------<模块及端口声名>------------------------------------------------------
module spi_control( 
    input				clk			,
    input				rst_n		,
    input               rdid_req    ,
    input               read_req    ,
    input               wren_req    ,
    input               ready       ,
    input       [23:0]  rd_addr     ,//需要读出的数据地址
    input       [7:0]   read_num    ,//需要读出的数据数量
    input       [23:0]  wr_addr     ,//需要写入的数据地址
    input       [7:0]   wr_num      ,//需要写入的数据数量
    input       [7:0]   data_in     ,//需要写入的数据
    input               data_in_vld ,
    input       [7:0]   data_out    ,//返回的数据
    input               data_out_vld,

    input               miso        ,
    output              sclk        ,
    output              mosi        ,
    output              cs_n        
);								 
//---------<参数定义>--------------------------------------------------------- 
    parameter   MAX_TSE = 28'd150_000_000,//3s
                MAX_TPP = 18'd150_000;//3ms
    
    //状态机参数定义
    localparam  IDLE    = 10'b0000000001,
                RDID    = 10'b0000000010,
                READ    = 10'b0000000100,
                WREN    = 10'b0000001000,
                WAIT    = 10'b0000010000,
                SE      = 10'b0000100000,
                TSE     = 10'b0001000000,
                PP      = 10'b0010000000,
                TPP     = 10'b0100000000,
                HOLD    = 10'b1000000000;
    
    reg 	[9:0]	cstate     ;//现态
    reg		[9:0]	nstate     ;//次态

    wire    IDLE_RDID;
    wire    IDLE_READ;
    wire    IDLE_WREN;
    wire    RDID_HOLD;
    wire    READ_HOLD;
    wire    WREN_WAIT;
    wire    WAIT_SE  ;
    wire    WAIT_PP  ;
    wire    SE_TSE   ;
    wire    PP_TPP   ;
    wire    TSE_WREN ;
    wire    TPP_IDLE ;
    wire    HOLD_IDLE;

    //与spi_interface交互
    reg     [7:0]   master_data_in;
    wire            master_data_in_vld;
    wire            done;
    wire    [7:0]   master_data_out;
    wire            master_data_out_vld;
    wire            master_ready;

    reg			[2:0]	cnt_bit	   	;
    wire				add_cnt_bit	;
    wire				end_cnt_bit	;

    reg			[3:0]	cnt_byte	   	;
    wire				add_cnt_byte	;
    wire				end_cnt_byte	;
    reg         [3:0]   num;

    reg			[27:0]	cnt_tse	   	;
    wire				add_cnt_tse	;
    wire				end_cnt_tse	;

    reg			[17:0]	cnt_tpp	   	;
    wire				add_cnt_tpp	;
    wire				end_cnt_tpp	;

    reg     flag;//判断wait状态到se还是pp   0:se;1:pp
    reg     delay_flag;//延时开始使能
    reg     data_in_r;//数据寄存

    reg     rdid_flag;
    reg     read_flag;
//---------<内部信号定义>-----------------------------------------------------
    
    //第一段:时序逻辑描述状态转移
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            cstate <= IDLE;
        end 
        else begin 
            cstate <= nstate;
        end 
    end
    
    //第二段:组合逻辑描述状态转移规律和状态转移条件
    always @(*) begin
        case(cstate)
            IDLE    :begin
                if (IDLE_RDID) begin
                    nstate = RDID;
                end
                else if (IDLE_READ) begin
                    nstate = READ;
                end
                else if (IDLE_WREN) begin
                    nstate = WREN;
                end
                else begin
                    nstate = cstate;
                end
            end
            RDID    :begin
                if (RDID_HOLD) begin
                    nstate = HOLD;
                end
                else begin
                    nstate = cstate;
                end
            end
            READ    :begin
                if (READ_HOLD) begin
                    nstate = HOLD;
                end
                else begin
                    nstate = cstate;
                end
            end
            WREN    :begin
                if (WREN_WAIT) begin
                    nstate = WAIT;
                end
                else begin
                    nstate = cstate;
                end
            end
            WAIT    :begin
                if (WAIT_SE) begin
                    nstate = SE;
                end
                else if (WAIT_PP) begin
                    nstate = PP;
                end
                else begin
                    nstate = cstate;
                end
            end
            SE      :begin
                if (SE_TSE) begin
                    nstate = TSE;
                end
                else begin
                    nstate = cstate;
                end
            end
            TSE     :begin
                if (TSE_WREN) begin
                    nstate = WREN;
                end
                else begin
                    nstate = cstate;
                end
            end
            PP      :begin
                if (PP_TPP) begin
                    nstate = TPP;
                end
                else begin
                    nstate = cstate;
                end
            end
            TPP     :begin
                if (TPP_IDLE) begin
                    nstate = IDLE;
                end
                else begin
                    nstate = cstate;
                end
            end
            HOLD    :begin
                if (HOLD_IDLE) begin
                    nstate = IDLE;
                end
                else begin
                    nstate = cstate;
                end
            end
            default : nstate = IDLE;
        endcase
    end
                
    assign IDLE_RDID = (cstate == IDLE) && rdid_req;
    assign IDLE_READ = (cstate == IDLE) && read_req;
    assign IDLE_WREN = (cstate == IDLE) && wren_req;
    assign RDID_HOLD = (cstate == RDID) && end_cnt_byte;
    assign READ_HOLD = (cstate == READ) && end_cnt_byte;
    assign WREN_WAIT = (cstate == WREN) && end_cnt_byte;
    assign WAIT_SE   = (cstate == WAIT) && done && ~flag;
    assign WAIT_PP   = (cstate == WAIT) && done && flag;
    assign SE_TSE    = (cstate == SE)   && end_cnt_byte;
    assign PP_TPP    = (cstate == PP)   && end_cnt_byte;
    assign TSE_WREN  = (cstate == TSE)  && end_cnt_tse;
    assign TPP_IDLE  = (cstate == TPP)  && end_cnt_tpp;
    assign HOLD_IDLE = (cstate == HOLD) && done;
                
    //字节计数器
    always @(posedge clk or negedge rst_n)begin 
       if(!rst_n)begin
            cnt_bit <= 'd0;
        end 
        else if(add_cnt_bit)begin 
            if(end_cnt_bit)begin 
                cnt_bit <= 'd0;
            end
            else begin 
                cnt_bit <= cnt_bit + 1'd1;
            end 
        end
    end 
    
    assign add_cnt_bit = (cstate == RDID || cstate == READ || cstate == WREN || cstate == SE || cstate == PP) && master_ready;
    assign end_cnt_bit = add_cnt_bit && cnt_bit == 7;
    
    always @(posedge clk or negedge rst_n)begin 
       if(!rst_n)begin
            cnt_byte <= 'd0;
        end 
        else if(add_cnt_byte)begin 
            if(end_cnt_byte)begin 
                cnt_byte <= 'd0;
            end
            else begin 
                cnt_byte <= cnt_byte + 1'd1;
            end 
        end
    end 
    
    assign add_cnt_byte = end_cnt_bit;
    assign end_cnt_byte = add_cnt_byte && cnt_byte == num - 1;
               
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            num <= 1;
        end
        else if (cstate == RDID) begin
            num <= 4;
        end
        else if (cstate == READ) begin
            num <= 4 + read_num;
        end
        else if (cstate == WREN) begin
            num <= 1;
        end
        else if (cstate == SE) begin
            num <= 4;
        end
        else if (cstate == PP) begin
            num <= 5;
        end
        else begin
            num <= 1;
        end
    end
    
    //指令发送
    always @(*) begin
        case (cstate)
            RDID : case (cnt_byte)
                        0 : master_data_in = 8'h9f;
                        1 : master_data_in = 8'hff;
                        2 : master_data_in = 8'hff;
                        3 : master_data_in = 8'hff;
                        default: master_data_in = 8'hff;
                   endcase
            READ : case (cnt_byte)
                        0 : master_data_in = 8'h03;
                        1 : master_data_in = rd_addr[23:16];
                        2 : master_data_in = rd_addr[15:8];
                        3 : master_data_in = rd_addr[7:0];
                        default: master_data_in = 8'hff;
                   endcase
            WREN : case (cnt_byte)
                        0 : master_data_in = 8'h06;
                        default: master_data_in = 8'hff;
                   endcase
            SE   : case (cnt_byte)
                        0 : master_data_in = 8'hd8;
                        1 : master_data_in = rd_addr[23:16];
                        2 : master_data_in = rd_addr[15:8];
                        3 : master_data_in = rd_addr[7:0];
                        default: master_data_in = 8'hff;
                   endcase
            PP   : case (cnt_byte)
                        0 : master_data_in = 8'h02;
                        1 : master_data_in = rd_addr[23:16];
                        2 : master_data_in = rd_addr[15:8];
                        3 : master_data_in = rd_addr[7:0];
                        4 : master_data_in = 8'hF1;
                        default: master_data_in = 8'hff;
                   endcase
        endcase
    end

    assign  master_data_in_vld = add_cnt_byte;
    
    //数据寄存
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            data_in_r <= 0;
        end
        else if (data_in_vld) begin
            data_in_r <= data_in;
        end
        else begin
            data_in_r <= data_in_r;
        end
    end
    
    //滤除无用数据
    reg			[3:0]	cnt_out	   	;
    wire				add_cnt_out	;
    wire				end_cnt_out	;
    reg         [3:0]   num_out;

    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            cnt_out <= 'd0;
        end
        else if (HOLD_IDLE || TPP_IDLE) begin
            cnt_out <= 'd0;
        end
        else if(add_cnt_out)begin 
            if(end_cnt_out)begin 
                cnt_out <= 'd0;
            end
            else begin 
                cnt_out <= cnt_out + 1'd1;
            end 
        end
    end 
    
    assign add_cnt_out = master_data_out_vld;
    assign end_cnt_out = add_cnt_out && cnt_out == num_out - 1;
    
    always @(*) begin
        if (!rst_n) begin
            num_out = 0;
        end
        else if (cstate == RDID) begin
            num_out = 1;
        end
        else if (cstate == READ) begin
            num_out = 4;
        end
    end

    //记录操作
    reg     [1:0]   op_flag;
    `define         OP_RDID 1
    `define         OP_READ 2
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            op_flag <= 0;
        end
        else if (IDLE_RDID) begin
            op_flag <= `OP_RDID;
        end
        else if (IDLE_READ) begin
            op_flag <= `OP_READ;
        end
        else if (HOLD_IDLE) begin
            op_flag <= 0;
        end
    end

    //读ID使能
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            rdid_flag <= 0;
        end
        else if (end_cnt_out && op_flag == `OP_RDID) begin
            rdid_flag <= 1;
        end
        else if (HOLD_IDLE) begin
            rdid_flag <= 0;
        end
    end
    
    //读read使能
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            read_flag <= 0;
        end
        else if (end_cnt_out && op_flag == `OP_READ) begin
            read_flag <= 1;
        end
        else if (HOLD_IDLE) begin
            read_flag <= 0;
        end
    end

    //延时开始使能
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            delay_flag <= 0;
        end
        else if ((cstate == TSE || cstate == TPP) && done) begin
            delay_flag <= 1;
        end
        else if (end_cnt_tpp || end_cnt_tse) begin
            delay_flag <= 0;
        end
    end

    //tSE延时
    always @(posedge clk or negedge rst_n)begin 
       if(!rst_n)begin
            cnt_tse <= 'd0;
        end 
        else if(add_cnt_tse)begin 
            if(end_cnt_tse)begin 
                cnt_tse <= 'd0;
            end
            else begin 
                cnt_tse <= cnt_tse + 1'd1;
            end 
        end
    end 
    
    assign add_cnt_tse = (cstate == TSE) && delay_flag;
    assign end_cnt_tse = add_cnt_tse && cnt_tse == MAX_TSE - 1;

    //tPP延时
    always @(posedge clk or negedge rst_n)begin 
       if(!rst_n)begin
            cnt_tpp <= 'd0;
        end 
        else if(add_cnt_tpp)begin 
            if(end_cnt_tpp)begin 
                cnt_tpp <= 'd0;
            end
            else begin 
                cnt_tpp <= cnt_tpp + 1'd1;
            end 
        end
    end 
    
    assign add_cnt_tpp = (cstate == TPP) && delay_flag;
    assign end_cnt_tpp = add_cnt_tpp && cnt_tpp == MAX_TPP - 1;
    
    //flag
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            flag <= 0;
        end
        else if (TSE_WREN) begin
            flag <= 1;
        end
        else if (TPP_IDLE) begin
            flag <= 0;
        end
    end

    spi_interface u_spi_interface(
        .clk	     (clk),
        .rst_n		 (rst_n),
        .data_in     (master_data_in),
        .data_in_vld (master_data_in_vld),
        .master_ready(master_ready),
        .data_out    (master_data_out),
        .data_out_vld(master_data_out_vld),
        .done        (done),
        .miso        (miso),
        .sclk        (sclk),
        .mosi        (mosi),
        .cs_n        (cs_n)
    );
    
    
endmodule
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值