module spi_write( input clk, //system clock:50M input rst, output reg cs, //chip select output sck, //chip clock:50K input din, //DO output reg dout, //DI input wflag, //write enable input[7:0] data ); //general chip clock:50K /*reg temp; reg[9:0] count; always@(posedge clk or posedge rst) if(rst) begin count <= 10'd0; temp <= 1'b0; end else begin count <= count+1'b1; if(count == 10'd999) begin temp <= 1'b1; count <= 10'd0; end else if(count == 10'd499) temp <= 1'b0; end assign sck = temp; `define high (count == 10'd999) // 时钟上升沿 `define low (count == 10'd499)*/ // 时钟下降沿 reg temp; reg[9:0] count; always@(posedge clk or posedge rst) if(rst) begin count <= 10'd0; temp <= 1'b0; end else if(count >= 10'd500) begin count <= 10'd0; temp <= ~temp; end else count <= count+1'b1; assign sck = temp; //capture posedge and negedge of sck reg sck_m; wire high; // 时钟上升沿 wire low; // 时钟下降沿 always@(posedge clk or posedge rst) if(rst) sck_m <= 1'b0; else sck_m <= sck; assign high = ~sck_m & sck; assign low = sck_m & ~sck; //load reg[7:0] data_medium; reg[5:0] wstate; always@(negedge clk or posedge rst) begin if(rst) begin wstate <= 6'b0; cs <= 1'b0; dout <= 1'b0; end else begin case(wstate) 6'd0: begin if(wflag) begin data_medium <= data; wstate <= 6'd1; cs <= 1'b1; dout <= 1'b0; end else begin wstate <= 6'd0; cs <= 1'b0; dout <= 1'b0; end end 6'd1: begin if(low) begin wstate <= 6'd2; dout <=1'b1; cs <= 1'b1; end // 先执行写使能命令,高位在前,低位在后 else begin wstate <= 6'd1; end //SB=1 end 6'd2: begin if(low) begin wstate <= 6'd3; dout <=1'b0; cs <= 1'b1; end //OP1=0 else begin wstate <= 6'd2; end end 6'd3: begin if(low) begin wstate <= 6'd4; dout <=1'b0; cs <= 1'b1; end //OP0=0 else begin wstate <= 6'd3; end end 6'd4: begin if(low) begin wstate <= 6'd5; dout <=1'b1; cs <= 1'b1; end //A6=1 else begin wstate <= 6'd4; end end 6'd5: begin if(low) begin wstate <= 6'd6; dout <=1'b1; cs <= 1'b1; end //A5=1 else begin wstate <= 6'd5; end end 6'd6: begin if(low) begin wstate <= 6'd7; dout <=1'b1; cs <= 1'b1; end //A4=1 else begin wstate <= 6'd6; end end 6'd7: begin if(low) begin wstate <= 6'd8; dout <=1'b1; cs <= 1'b1; end //A3=1 else begin wstate <= 6'd7; end end 6'd8: begin if(low) begin wstate <= 6'd9; dout <=1'b1; cs <= 1'b1; end //A2=1 else begin wstate <= 6'd8; end end 6'd9: begin if(low) begin wstate <= 6'd10; dout <=1'b1; cs <= 1'b1; end //A1=1 else begin wstate <= 6'd9; end end 6'd10: begin if(low) begin wstate <= 6'd11; dout <=1'b1; cs <= 1'b1; end //A0=1 else begin wstate <= 6'd10; end end 6'd11: begin if(low) begin wstate <= 6'd12; dout <= 1'b0;cs <= 1'b0; end // 先停一个周期,将CS 拉低,再进行写操作(Address) else begin wstate <= 6'd11; end end 6'd12: begin if(low) begin wstate <= 6'd13; dout <=1'b1; cs <= 1'b1; end //SB=1 else begin wstate <= 6'd12; end end 6'd13: begin if(low) begin wstate <= 6'd14; dout <=1'b0; cs <= 1'b1; end //OP1=0 else begin wstate <= 6'd13; end end 6'd14: begin if(low) begin wstate <= 6'd15; dout <=1'b1; cs <= 1'b1; end //OP0=1 else begin wstate <= 6'd14; end end 6'd15: begin if(low) begin wstate <= 6'd16; dout <=1'b0; cs <= 1'b1; end //A6=0 else begin wstate <= 6'd15; end end 6'd16: begin if(low) begin wstate <= 6'd17; dout <=1'b0; cs <= 1'b1; end //A5=0 else begin wstate <= 6'd16; end end 6'd17: begin if(low) begin wstate <= 6'd18; dout <=1'b0; cs <= 1'b1; end //A4=0 else begin wstate <= 6'd17; end end 6'd18: begin if(low) begin wstate <= 6'd19; dout <=1'b0; cs <= 1'b1; end //A3=0 else begin wstate <= 6'd18; end end 6'd19: begin if(low) begin wstate <= 6'd20; dout <=1'b1; cs <= 1'b1; end //A2=1 else begin wstate <= 6'd19; end end 6'd20: begin if(low) begin wstate <= 6'd21; dout <=1'b0; cs <= 1'b1; end //A1=0 else begin wstate <= 6'd20; end end 6'd21: begin if(low) begin wstate <= 6'd22; dout <=1'b1; cs <= 1'b1; end //A0=1 else begin wstate <= 6'd21; end end 6'd22: begin if(low) begin wstate <= 6'd23; dout <=data[7]; cs <= 1'b1; end // 开始写入数据:器件数据在上升沿更新,FPGA要在下降沿写出 else begin wstate <= 6'd22; end // D7 end 6'd23: begin if(low) begin wstate <= 6'd24; dout <=data[6]; cs <= 1'b1; end //D6 else begin wstate <= 6'd23; end end 6'd24: begin if(low) begin wstate <= 6'd25; dout <=data[5]; cs <= 1'b1; end //D5 else begin wstate <= 6'd24; end end 6'd25: begin if(low) begin wstate <= 6'd26; dout <=data[4]; cs <= 1'b1; end //D4 else begin wstate <= 6'd25; end end 6'd26: begin if(low) begin wstate <= 6'd27; dout <=data[3]; cs <= 1'b1; end //D3 else begin wstate <= 6'd26; end end 6'd27: begin if(low) begin wstate <= 6'd28; dout <=data[2]; cs <= 1'b1; end //D2 else begin wstate <= 6'd27; end end 6'd28: begin if(low) begin wstate <= 6'd29; dout <=data[1]; cs <= 1'b1; end //D1 else begin wstate <= 6'd28; end end 6'd29: begin if(low) begin wstate <= 6'd30; dout <=data[0]; cs <= 1'b1; end //D0 else begin wstate <= 6'd29; end end 6'd30: begin if(low) begin wstate <= 6'd31; dout <= 1'b0;cs <= 1'b0; end // 数据写完,停止一个周期,拉低CS else begin wstate <= 6'd30; end end 6'd31: begin if(low) begin wstate <= 6'd32; cs <= 1'b1; end //拉高CS,读DO状态,看其是否忙 else begin wstate <= 6'd31; end end 6'd32: begin if(din == 1'b1) begin wstate <= 6'd33; cs <= 1'b0; end //若忙,停在此状态继续检测 else begin wstate <= 6'd32; cs <= 1'b1; end end 6'd33: begin if(low) begin wstate <= 6'd34; cs <= 1'b0; end //数据写完,停止一个周期 else begin wstate <= 6'd33; end end 6'd34: begin if(low) begin wstate <= 6'd35; dout <= 1'b1; cs <= 1'b1; end //当写操作完成后,为了保护数据,对器件进行擦/写禁止指令 else begin wstate <= 6'd34; end end 6'd34: begin if(low) begin wstate <= 6'd35; dout <= 1'b0; cs <= 1'b1; end //OP=1 else begin wstate <= 6'd34; end end 6'd35: begin if(low) begin wstate <= 6'd36; dout <= 1'b0; cs <= 1'b1; end //OP=2 else begin wstate <= 6'd35; end end 6'd36: begin if(low) begin wstate <= 6'd37; dout <= 1'b0; cs <= 1'b1; end //A6 else begin wstate <= 6'd36; end end 6'd37: begin if(low) begin wstate <= 6'd38; dout <= 1'b0; cs <= 1'b1; end //A5 else begin wstate <= 6'd37; end end 6'd38: begin if(low) begin wstate <= 6'd39; dout <= 1'b1; cs <= 1'b1; end //A4 else begin wstate <= 6'd38; end end 6'd39: begin if(low) begin wstate <= 6'd40; dout <= 1'b1; cs <= 1'b1; end //A3 else begin wstate <= 6'd39; end end 6'd40: begin if(low) begin wstate <= 6'd41; dout <= 1'b1; cs <= 1'b1; end //A2 else begin wstate <= 6'd40; end end 6'd41: begin if(low) begin wstate <= 6'd42; dout <= 1'b1; cs <= 1'b1; end //A1 else begin wstate <= 6'd41; end end 6'd42: begin if(low) begin wstate <= 6'd43; dout <= 1'b1; cs <= 1'b1; end //A0 else begin wstate <= 6'd42; end end 6'd43: begin if(low) begin wstate <= 6'd44; dout <= 1'b0; end //over else begin wstate <= 6'd43; end end 6'd44: begin if(low) begin wstate <= 6'd0; cs <= 1'b0; end //cs down else begin wstate <= 6'd44; end end endcase end end endmodule