单片机与FPGA沟通方式有很多种,只要规定好协议后,做到通信是完成没问题的。
首先先将FPGA的SPI实现…SPI协议不做追溯了。
闲话不多说,先付代码、
module SPILED(
input clk,
input rst_n,
input SCK,
input CS_N,
input MOSI,
output reg MISO,
output reg [7:0]rxd_data,
output rxd_flag,
output reg led0,
output reg led1,
output reg led2,
output reg led3
);
//-----------------capture sck side---------//
reg sck_r0,sck_r1;
wire sck_n,sck_p;
reg [7:0]txd_data;
initial txd_data[7:0] <= 8'd11;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
sck_r0 <= 1'b1; //sck of the idle state is high
sck_r1 <= 1'b1;
end
else
begin
sck_r0 <= SCK;
sck_r1 <= sck_r0;
end
end
assign sck_n = (~sck_r0 & sck_r1)? 1'b1:1'b0; //capture the sck negedge
assign sck_p = (~sck_r1 & sck_r0)? 1'b1:1'b0; //capture the sck posedge
从机如何读数据
//---------------spi_slaver read data---------//
reg rxd_flag_r;
reg [2:0]rxd_state;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
rxd_data <= 1'b0;
rxd_flag_r <= 1'b0;
rxd_state <= 1'b0;
end
else if(sck_n&&!CS_N)
begin
case(rxd_state)
3'd0:begin
rxd_data[7]<=MOSI;
rxd_flag_r <= 1'b0;
rxd_state <= 3'd1;
end
3'd1:begin
rxd_data[6]<=MOSI;
rxd_state <= 3'd2;
end
3'd2:begin
rxd_data[5]<=MOSI;
rxd_state <= 3'd3;
end
3'd3:begin
rxd_data[4]<=MOSI;
rxd_state <= 3'd4;
end
3'd4:begin
rxd_data[3]<=MOSI;
rxd_state <= 3'd5;
end
3'd5:begin
rxd_data[2]<=MOSI;
rxd_state <= 3'd6;
end
3'd6:begin
rxd_data[1]<=MOSI;
rxd_state <= 3'd7;
end
3'd7:begin
rxd_data[0]<=MOSI;
rxd_flag_r <= 1'b1;
rxd_state <= 3'd0;
end
default: ;
endcase
end
end
中间穿插用灯指示一下。
always@(posedge clk )
begin
led0 <= rxd_data[0];
led1 <= rxd_data[1];
led2 <= rxd_data[2];
led3 <= rxd_data[3];
end
从机发送数据
//--------------------capture spi_flag posedge--------------------------------
reg rxd_flag_r0,rxd_flag_r1;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
rxd_flag_r0 <= 1'b0;
rxd_flag_r1 <= 1'b0;
end
else
begin
rxd_flag_r0 <= rxd_flag_r;
rxd_flag_r1 <= rxd_flag_r0;
end
end
assign rxd_flag = (~rxd_flag_r1 & rxd_flag_r0)? 1'b1:1'b0; //capture rxd_flag_r posedge
//---------------------spi_slaver send data---------------------------
reg [2:0] txd_state;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
txd_state <= 1'b0;
end
else if(sck_p && !CS_N)
begin
case(txd_state)
3'd0:begin
MISO <= txd_data[7];
txd_state <= 3'd1;
end
3'd1:begin
MISO <= txd_data[6];
txd_state <= 3'd2;
end
3'd2:begin
MISO <= txd_data[5];
txd_state <= 3'd3;
end
3'd3:begin
MISO <= txd_data[4];
txd_state <= 3'd4;
end
3'd4:begin
MISO <= txd_data[3];
txd_state <= 3'd5;
end
3'd5:begin
MISO <= txd_data[2];
txd_state <= 3'd6;
end
3'd6:begin
MISO <= txd_data[1];
txd_state <= 3'd7;
end
3'd7:begin
MISO <= txd_data[0];
txd_state <= 3'd0;
end
default: ;
endcase
end
end
endmodule
以上都是FPGA端的,当时写的单片机的软件SPI,注意时序边沿对应。当然软件SPI通信效率很低,但是谁让单片机硬件SPI总出错呢。
需要软件SPI的,请私信吧,这里不写了。