基于FPGA的SPI
0赞spi最早由motorola提出
是一个种duplex、synchronous、serial通信方式
主要管脚信号:
mosi: master output, slave input
miso: master input, slave output
sclk: serial clock
ss_n: select signal
两个关键控制位
CPOL----SPI Clock Polarity Bit
SPI modules must have the identical CPOL value.
1 == Active-low clocks selected, in idle state SCLK is high.
0 ==Active-high clocks selected, in idle state SCLK is low.
CPHA ---- Slave Select Output Enable
1 == Sampling of data occurs at even edges(2,4,6...) of the SCLK clock.
0 ==Sampling of data occurs at odd edges(1,3,5...) of the SCLK clock.
// 计数
always @( posedge clk_80M or posedge rst )
begin
if ( rst == 1'b1 )
cnt_bit <= 4'd7;
else
begin
if ( ss_n_s == 1'b1 )
cnt_bit <= 4'd7;
else if ( ( sclk_s == 1'b0 ) & ( sclk_t == 1'b1 ))//( ( sclk_s == 1'b0 ) & ( sclk_t == 1'b1 ))
begin
if ( cnt_bit > 0 )
cnt_bit <= cnt_bit - 1'b1;
else
cnt_bit <= 4'd7;
end
end
end
/**************** SPI receiver *********************/
always @( posedge clk_80M or posedge rst )
begin
if ( rst == 1'b1 )
begin
shift_in <= 7'd0;
byte_in <= 8'd0;
end
else
begin
if ( ss_n_s == 1'b1 )
shift_in <= 7'd0;
else if ( ( sclk_s == 1'b0 ) & ( sclk_t == 1'b1 ))//( ( sclk_s == 1'b1 ) & ( sclk_t == 1'b0 ))
begin
if( cnt_bit > 0 )
shift_in <= { shift_in[5:0], mosi_s };
else
byte_in <= { shift_in, mosi_s };
end
end
end
/**************** SPI transmitter *****************/
always @( posedge clk_80M or posedge rst )
begin
if ( rst == 1'b1 )
load <= 1'b0;
else
begin
if ( ( sclk_s == 1'b1 ) & ( sclk_t == 1'b0 ) )//( ( sclk_s == 1'b1 ) & ( sclk_t == 1'b0 ) )
begin
if ( cnt_bit == 0 )
load <= 1'b1;
else
load <= 1'b0;
end
end
end
// transmitting shift register - output section
always @( posedge clk_80M or posedge rst )
begin
if ( rst == 1'b1 )
shift_out <= 7'd0;
else
begin
if ( ss_n_s == 1'b1 )
shift_out <= byte_out;
else if ( ( ss_n_s == 1'b0 ) & ( ss_n_t == 1'b1 ) )
shift_out <= byte_out;
else if ( ( sclk_s == 1'b0 ) & ( sclk_t == 1'b1 ) ) //rising edge send data
begin
if ( load == 1'b1 )
shift_out <= byte_out;
else
shift_out <= { shift_out[6:0], 1'b0 };
end
end
end
always @( posedge clk_80M or posedge rst )
begin
if ( rst == 1'b1 )
miso <= 1'b0;
else
begin
if ( ss_n_s == 1'b1 )
i_miso <= 1'b0;
else if ( ( sclk_s == 1'b1 ) & ( sclk_t == 1'b0 ) )//( ( sclk_s == 1'b1 ) & ( sclk_t == 1'b0 ) )
miso <= shift_out[7];
end
end
//若为master,则需产生SCLK,以及ss_n
//----- generate sclk ----------
always @( posedge clk or posedge rst )
begin
if( rst )
sclk <= 1'b0;
else if( !ss_n )
begin
if( sclk_cnt == SCLK_CNT_NUM )
sclk <= ~sclk;
end
else
sclk <= 1'b0;
end
always @( posedge clk or posedge rst )
begin
if( rst )
sclk_cnt <= 8'd0;
else if( !ss_n )
begin
if( sclk_cnt == SCLK_CNT_NUM )
sclk_cnt <= 8'd0;
else
sclk_cnt <= sclk_cnt + 1'b1;
end
else
sclk_cnt <= 8'd0;
end
// --------- generate ss_n---------------
always @( posedge clk or posedge rst )
begin
if( rst )
begin
wr_ss_n <= 1'b1;
end
else if( send_addr_en && ( !send_addr_en_q ))
begin
wr_ss_n <= 1'b0;
end
else if( send_addr_done )
begin
wr_ss_n <= 1'b1;
end
end
后续发送及接受数据额外添加~
CPOL = 1'b0; CPHA = 1'b1;
上升沿发送数据,下降沿采样,
同时主机在下降沿时移位。