SPI通讯

该代码实现了一个用于SPI接口的M25P16存储器控制的状态机,包括IDLE、WREN、DELAY和BE四个状态,通过key_flag触发写使能操作,使用多个计数器控制时序,如clk、byte、sck和bit计数器,确保正确发送和接收数据。
摘要由CSDN通过智能技术生成

状态机实现

module spi_m25p16  (
    input   sys_clk    ,
    input   sys_rst_n  ,
    input   key_flag   ,
    
    
    output  reg cs_n       ,
    output  reg sck        ,
    output  reg mosi     
    );

reg [3:0] current_state    , next_state ;
reg [4:0] cnt_clk  ;
reg [3:0] cnt_byte ;
reg [2:0] cnt_sck ;
reg [2:0] cnt_bit ;

parameter IDLE = 4'b0001,
           WREN = 4'b0010,
           DELAY= 4'b0100,
           BE   = 4'b1000;
//状态机三段式
always @(posedge sys_clk or negedge sys_rst_n) begin
      if(!sys_rst_n) 
            current_state <= IDLE;
      else 
            current_state <= next_state;   
end

always @(*) begin
    if(!sys_rst_n)
            next_state <= IDLE ;
    else   begin
            case(current_state)
                IDLE:  if(key_flag == 'd1)
              	   		   next_state <= WREN ;
                       else 
          	               next_state <= IDLE;
                WREN:  if (cnt_byte == 4'd2 && cnt_clk== 5'd31)
                           next_state <= DELAY ;
               	       else 
                           next_state <= WREN ;
                DELAY: if (cnt_byte == 4'd3 && cnt_clk== 5'd31)
                           next_state <= BE ;
               	       else 
                           next_state <= DELAY ;
                BE :   if (cnt_byte == 4'd6 && cnt_clk== 5'd31)
                           next_state <= IDLE ;
               	       else 
                           next_state <= BE ;
                default:
                           next_state <= IDLE ;
             endcase
            end
end

always @(posedge sys_clk or negedge sys_rst_n) begin
      if(!sys_rst_n) 
           cnt_clk <=  5'd0;
      else if (current_state != IDLE)
           cnt_clk <= cnt_clk + 1'b1 ;   // 32
end

//cnt_byte
always @(posedge sys_clk or negedge sys_rst_n) begin
      if(!sys_rst_n) 
             cnt_byte <= 4'd0 ;
      else if( cnt_byte == 4'd6 && cnt_clk == 5'd31)    //计数到头了
             cnt_byte  <=  4'd0;
      else if( cnt_clk == 5'd31 )
              cnt_byte  <= cnt_byte + 4'd1;  
end

always @(posedge sys_clk or negedge sys_rst_n) begin   //字节计数器  相当于 分频这这里分频
      if(!sys_rst_n) 
            cnt_sck <= 2'd0 ;
      else  if( current_state == WREN && cnt_byte == 4'd1 ) 
            cnt_sck <= cnt_sck + 2'd1 ;
      else if( current_state == BE && cnt_byte == 4'd5 ) 
            cnt_sck <= cnt_sck + 2'd1 ;   
end

//cnt_bit
always @(posedge sys_clk or negedge sys_rst_n) begin   //字节计数器    一个8个bit  字节的传输
      if(!sys_rst_n) 
          cnt_bit <= 3'd0 ;
      else if(cnt_sck == 2'd2)
          cnt_bit <=  cnt_bit + 2'd1;
end

always @(posedge sys_clk or negedge sys_rst_n) begin   //字节计数器    一个8个bit  字节的传输
      if(!sys_rst_n) 
           cs_n <= 1'b1 ;  //空闲
      else if( key_flag == 1'b1)
           cs_n <= 1'b0 ;
      else if( cnt_byte ==4'd2 && cnt_clk == 5'd31 && current_state == WREN   )
           cs_n <= 1'b1 ;
      else if( cnt_byte ==4'd3 && cnt_clk == 5'd31 && current_state == DELAY  )
           cs_n <= 1'b0;
      else if( cnt_byte ==4'd6 && cnt_clk == 5'd31 && current_state == BE  )
           cs_n <= 1'b1;
 end
 
 parameter WREN_IN = 8'b0000_0010 ,
            BE_IN   = 8'b1100_0111;
 
 
always @(posedge sys_clk or negedge sys_rst_n) begin   //字节计数器    一个8个bit  字节的传输
      if(!sys_rst_n) 
            mosi <= 1'b0 ;
      else if( current_state == WREN && cnt_byte == 4'd2)
            mosi <= 1'b0 ;
      else if( current_state== BE && cnt_byte == 4'd6)
            mosi <= 1'b0 ;
      else if( current_state ==WREN && cnt_byte == 4'd1 && cnt_sck == 2'd0)
            mosi <= WREN_IN [7 - cnt_bit] ;
      else if( current_state == BE && cnt_byte == 4'd5 && cnt_sck == 2'd0)
            mosi <= BE_IN [7 - cnt_bit] ;
end


always @(posedge sys_clk or negedge sys_rst_n) begin   //字节计数器    一个8个bit  字节的传输
      if(!sys_rst_n) 
           sck <= 1'b0 ;
      else if ( cnt_sck == 2'd0 )
           sck <= 1'b0 ;
      else if ( cnt_sck == 2'd2 )
           sck <= 1'b1 ;
end

endmodule

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值