`timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: // // Create Date: 15:23:58 10/12/2020 // Design Name: spi发送模块 // Module Name: spi // Project Name: // Target Devices: // Tool versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// module spi_tx #(parameter WHITH=32)( input clk,//系统时钟 input rstn,//异步复位 input tx_en,//发送使能 input [WHITH-1:0] data_in,//待发送数据 output reg spi_cs, //片选 output reg spi_sclk, //同步时钟,等于clk/2 output reg spi_sdo, //发送数据的线 output reg DARY ); //localparam [1:0] polaeity = 2'b10;//negedge 数据下降沿保持 localparam [1:0] polaeity = 2'b01;//posedge 数据上降沿保持 reg [2:0] state ; //状态机 reg [WHITH-1:0] reg_data;//移位寄存器 reg [5:0] cnt;//计数器,必须大于数据位宽 wire CPOL ; //时钟空闲时电平 wire CPHA ; //极性 assign CPOL = polaeity[0] ; assign CPHA = polaeity[1] ; always @(posedge clk,negedge rstn)begin if(!rstn)begin state <= 3'd0; spi_cs <= 1'b1; spi_sclk <= CPOL; reg_data <= 1'd0; cnt <= 5'b0; spi_sdo <= 1'b0; DARY <= 1'b1; end else begin case(state) 3'd0:begin//空闲态 spi_sclk <= CPOL ; spi_cs <= 1'b1 ; spi_sdo <= 1'b0 ; DARY <= 1'b1 ; cnt <= 5'b0 ; reg_data <= data_in ; if(tx_en)//发送使能跳下一个状态 state <= 3'd1 ; else state <= state ; end 3'd1:begin spi_cs <= 1'b0 ; state <= 3'd2 ; reg_data <= data_in ; end 3'd2:begin//数据移位态 spi_cs <= 1'b0 ; reg_data <= reg_data<<1'b1 ; spi_sdo <= reg_data[WHITH-1] ; spi_sclk <= CPHA ; state <= (cnt >= WHITH-1) ? 3'd4:3'd3; end 3'd3:begin//时钟翻转 cnt <= cnt+1'b1 ; spi_sclk <= ~CPHA ; state <= 3'd2 ; end 3'd4:begin//结束态 state <= 3'd5; spi_sclk <= ~CPHA; end 3'd5:begin//结束态 state <= 3'd6; DARY <= 0; spi_sdo <= 1'b0 ; spi_cs <= 1'b1 ; end 3'd6:begin//结束态 state <= 3'd7; DARY <= 1; spi_cs <= 1'b1 ; end 3'd7:begin//结束态 state <= 3'd8; DARY <= 0; end 3'd8:begin//结束态 state <= 3'd0; DARY <= 1; end default :state<=3'd0; endcase end end endmodule