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