Spi Master(Verilog) --后附完整代码

Spi Master(Verilog) --后附完整代码

1.硬件接口(Port)

SPI = Serial Peripheral Interface,是串行外围设备接口,是一种高速,全双工,同步的通信总线。

SCK : 串行时钟,一般主机提供(Serial Clock)

MOSI : 主发从收(Master Output, Slave Input)

MISO : 主收从发(Master Input, Slave Output)

CS : 片选,一般低有效(Slave Select )

2.操作时序(Protocol)

不同的芯片可能有不同的操作时序,常见的不同如:地址位不同,有的32位,有的16位,有的8位;操作控制位;数据位不同等。

具体操作时序需要参考相关芯片手册。

本文依据以下时序编写。

3.Verilog 写SPI_Master

以下依次为:端口声明、reg和wire声明、状态机声明。

//端口声明
 `timescale 1ns / 1ps
module SPI_Master(
    input   wire           sclk               ,    // System Clock.
    input   wire           srstn              ,    // System Reset. Low Active 
    //====== Control / Status ======================
    input   wire  [ 7 : 0] sclk_divider       ,    // SPI Clock Control / Divid
    //====== Control / Status ======================
    input   wire           wr_start           ,    // Write  Start 
    input   wire           rd_start           ,    // Read   Start  

    output  wire           wr_finish          ,    // Write  Finish 
    output  wire           rd_finish          ,    // Read   Finish

    input   wire  [ 7 : 0] start_addr         ,    // Write / Read Start Address
    input   wire  [ 7 : 0] state_init         ,    // slaver state initial  
    //====== Rx Interface =========================
    input   wire  [ 7 : 0] rx_rd_data         ,    // Rx Read Data
    //====== Tx Interface =====================
    output  wire  [ 7 : 0] tx_wr_data         ,    // Tx Write Data
    //====== ReRAM SPI Interface ===================
    output  wire           SPI_SCLK           ,    // SPI Clock 
    output  wire           SPI_CSN            ,    // SPI Chip Select 
    output  wire           SPI_MOSI           ,    // SPI Master Output 
    input   wire           SPI_MISO                // SPI Master Input
);

//reg和wire声明   
//==============================================================
// Local Registe Declare 
//==============================================================
//control 
    reg                 r_wr_start     ;// Write Start 
    reg                 r_rd_start     ;// Read  Start 
//status
    reg                 r_wr_finish    ;// Write Finish
    reg                 r_rd_finish    ;// Read  Finish 

    reg     [ 7 : 0]    r_start_addr   ;// Write / Read Start Address
    reg     [ 7 : 0]    r_state_init   ;
    
    reg                 r_wr_mode      ;// Write / Read Mode. 1'b0: Write /1'b1: Read

// Tx 
    reg     [ 7 : 0]    r_tx_wr_data   ;// Tx Write Data 
// SPI Interface 
    reg                 r_sclk         ;  
    reg                 r_sclk_d0      ;// SPI Clock
    
    reg                 r_csn          ;// SPI Chip Select
    reg     [ 3 : 0]    r_csn_cnt      ;// SPI Chip Select Count 

    reg                 r_sclk_enable  ;//SPI Clock enable
    reg     [ 7 : 0]    r_sclk_divider ;// SPI Clock Divider Count 
    
    reg     [ 7 : 0]    r_wr_data      ;// SPI Write Data

    reg     [ 7 : 0]    r_spi_addr_cnt ;// SPI Write / Read Address Count 
    //reg     [11 : 0]    r_spi_data_cnt ;// SPI Write / Read Data    Count
// State
    reg     [ 7 : 0]    state          ;// FSM Current State 
    reg     [ 7 : 0]    state_nxt      ;// ---   Next State       
    
//==============================================================
// Local Wire Declare 
//==============================================================
    wire               sclk_pedge      ;// SPI Clock Positive Edge 
    wire               sclk_nedge      ;// SPI Clock Negative Edge  
    
//状态机声明    
//==============================================================
// Local Parameter Declare 
//==============================================================  
    localparam  ST_IDLE          = 8'h01;    // Idle  State 
    localparam  ST_CSN_ENABLE    = 8'h02;    // Chip  Select Enable 
    localparam  ST_WRITE_INITIAL = 8'h04;    // Write State Initial 
    localparam  ST_WRITE_ADDR    = 8'h08;    // Write Address 
    localparam  ST_WRITE_DATA    = 8'h10;    // Write Data
    localparam  ST_READ_DATA     = 8'h20;    // Read  Data
    localparam  ST_CSN_DISABLE   = 8'h40;    // Chip  Select Disable 
    localparam  ST_FINISH        = 8'h80;    // Finish State 

输入控制指令/buffer/状态

//==============================================================
// Input control / status
//==============================================================
//read / write start
    always @(posedge sclk)begin
        if(!srstn)begin
            r_wr_start  <=  1'b0;
            r_rd_start  <=  1'b0;
        end
        else begin
            r_wr_start  <=  wr_start;
            r_rd_start  <=  rd_start; 
        end
    end
      
// Write / Read Mode. 1'b0: Write / 1'b1: Read   
    always @(posedge sclk)begin
        if(!srstn)begin
            r_wr_mode   <=  1'b0;
        end
        else if(wr_start) begin
            r_wr_mode   <=  1'b0;
        end
        else if (rd_start)begin
            r_wr_mode   <=  1'b1;        
        end
    end  
//input buffer        
    always @(posedge sclk)begin
        if(!srstn)begin
            r_start_addr  <=  8'h0;
            r_state_init  <=  8'h0;
        end
        else if(wr_start | rd_start)begin
            r_start_addr  <=  start_addr;
            r_state_init  <=  state_init;
        end
    end  

生成SPI 时钟、片选使能

//==============================================================
// Generate SPI Clock 
//==============================================================
    always @ (posedge sclk)begin 
        if(!srstn)
            r_sclk_enable   <=  1'b0;
        else if(state==ST_IDLE)
            r_sclk_enable   <=  1'b0;
        else if(state==ST_CSN_ENABLE)
            r_sclk_enable   <=  1'b1;
    end 
//SPI_CLK divider
    always @ (posedge sclk)begin 
        if(!srstn)
            r_sclk_divider <= 8'h0;
        else if(r_sclk_enable) begin 
            if(r_sclk_divider == sclk_divider)
                r_sclk_divider   <= 8'h0;
            else 
                r_sclk_divider   <= r_sclk_divider + 1'b1;
        end 
        else 
            r_sclk_divider <= 8'h0;
    end 

    always @ (posedge sclk)begin
        if(~ srstn)
            r_sclk         <= 1'b0;
        else if(r_sclk_enable) begin 
            if(r_sclk_divider==sclk_divider)
                r_sclk           <= ~ r_sclk;
        end 
        else 
            r_sclk         <= 1'b0;
    end 

    always @ (posedge sclk)begin
        if(~ srstn)
            r_sclk_d0      <= 1'b0;
        else 
            r_sclk_d0      <= r_sclk;
    end 
    
    assign    sclk_pedge   = ~ r_sclk_d0 &    r_sclk ;    // SPI Clock Positive Edge (read /sample data at this edge)
    assign    sclk_nedge   =   r_sclk_d0 & (~ r_sclk);    // SPI Clock Negative Edge (write        data at this edge)   

//==============================================================
// SPI Chip Select 
//==================================================
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mukar7

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值