qjfun

基于FPGA的SPI

0
阅读(1589)

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;

上升沿发送数据,下降沿采样,

同时主机在下降沿时移位。







Baidu
map