写SPI的时候,想接收SDO传过来的数据。检测SCLK的上升沿,对SDO进行移位存储。
然后就出现一个很神奇的事,write_cnt从10到18只有7个clk进行了数据的存储。
//rdata
always @ (posedge SCLK or negedge rst_n) begin
if(!rst_n) begin
rdata <= 8'd0 ;
end else begin
if(swith[15] == 1'b1 && write_cnt > 8'd10 && write_cnt <= 8'd18) begin
rdata <= {rdata[6:0],SDO} ;
end else begin
rdata <= 8'd0 ;
end
end
end
同步性太差导致的?看一下write_cnt==20时写数据看是什么时序。果然是有问题的,cnt为20时,已经存数据了。
//rdata
always @ (posedge SCLK or negedge rst_n) begin
if(!rst_n) begin
rdata <= 8'd0 ;
end else begin
if(swith[15] == 1'b1 && write_cnt > 8'd10 && write_cnt <= 8'd18) begin
rdata <= {rdata[6:0],SDO} ;
end else if(write_cnt == 8'd20) begin
rdata <= 8'haa ;
end else begin
rdata <= 8'b0 ;
end
end
end
所以我们用一个SCLK取反来对SDO进行读取,这样确保SCLK_r的上升沿在write_cnt的中间。结果证明时序是正确的。
//rdata
wire SCLK_R ;
assign SCLK_R = ~SCLK ;
always @ (posedge SCLK_R or negedge rst_n) begin
if(!rst_n) begin
rdata <= 8'd0 ;
end else begin
if(swith[15] == 1'b1 && write_cnt > 8'd10 && write_cnt <= 8'd18) begin
rdata <= {rdata[6:0],SDO} ;
end else begin
rdata <= 8'd0 ;
end
end
end
因为SCLK是由50M时钟clk产生的,我们用产生SCLK的信号,对SDO进行存储。也是正确的。
//rdata
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
rdata <= 8'd0 ;
end else begin
if (clk_25M == 1'b1 && clk_12M == 1'b0) begin
if(swith[15] == 1'b1 && write_cnt > 8'd10 && write_cnt <= 8'd18) begin
rdata <= {rdata[6:0],SDO} ;
end else begin
rdata <= 8'd0 ;
end
end
end
end
最后得出的结论就是,用系统时钟clk分频出来的SCLK对write_cnt 进行读取是存在问题的。