这里会显示出您选择的修订版和当前版本之间的差别。
两侧同时换到之前的修订记录 前一修订版 后一修订版 | 前一修订版 | ||
icore3_fpga_16 [2020/01/21 15:31] zgf |
icore3_fpga_16 [2022/03/18 15:44] (当前版本) sean |
||
---|---|---|---|
行 1: | 行 1: | ||
+ | | **银杏科技有限公司旗下技术文档发布平台** |||| | ||
+ | |技术支持电话|**0379-69926675-801**||| | ||
+ | |技术支持邮件|Gingko@vip.163.com||| | ||
+ | ^ 版本 ^ 日期 ^ 作者 ^ 修改内容 ^ | ||
+ | | V1.0 | 2019-12-25 | gingko | 初次建立 | | ||
+ | |||
+ | |||
===== 实验十六:基于SPI总线的ARM+FPGA通信实验 ===== | ===== 实验十六:基于SPI总线的ARM+FPGA通信实验 ===== | ||
行 6: | 行 13: | ||
- 学习基于SPI总线的ARM+FPGA数据传输应用。 | - 学习基于SPI总线的ARM+FPGA数据传输应用。 | ||
==== 二、实验设备及平台 ==== | ==== 二、实验设备及平台 ==== | ||
- | - iCore3 双核心板( FPGA型号为EP4CE10F17,ARM型号为STM32F407IGT6)。 | + | - iCore3 双核心板( FPGA型号为EP4CE10F17,ARM型号为STM32F407IGT6)。[[https://item.taobao.com/item.htm?spm=a1z10.1-c.w4024-251734887.3.5923532fXD2RIN&id=524229438677&scene=taobao_shop|点击购买]] |
- | - Blaster(或相同功能的)仿真器和USB线缆。 | + | - Blaster(或相同功能的)仿真器和USB线缆。[[https://item.taobao.com/item.htm?spm=a1z10.5-c.w4002-251734908.13.20822b61MmPeNN&id=554869837940|点击购买]] |
- Micro USB线缆。 | - Micro USB线缆。 | ||
-QuartusII开发软件(本实验中使用的是13.1版本)。 | -QuartusII开发软件(本实验中使用的是13.1版本)。 | ||
行 20: | 行 27: | ||
* 本实验中SPI通信双方只有ARM和FPGA,因此信号按照单个主器件/单个从器件的方式连接,既MOSI引脚连接在一起,MISO引脚连接在一起。通过这种方式,主器件和从器件之间以串行方式传输数据(最高有效位在前)。下图为信号连接图: | * 本实验中SPI通信双方只有ARM和FPGA,因此信号按照单个主器件/单个从器件的方式连接,既MOSI引脚连接在一起,MISO引脚连接在一起。通过这种方式,主器件和从器件之间以串行方式传输数据(最高有效位在前)。下图为信号连接图: | ||
- | {{ :icore3:icore3_fpga_16_1.png?direct |图1 信号连接图}} | + | {{ :icore3:icore3_fpga_16_1.png?direct&700 |图1 信号连接图}} |
==== 四、代码讲解 ==== | ==== 四、代码讲解 ==== | ||
行 29: | 行 36: | ||
* 由ARM提供的数据和SCLK是同步的,那么FPGA接收数据的触发信号可以选用SCLK。阅读过STM32F407手册能够发现,它的SPI总线发送数据时,是先发送高位,再发送低位的。因此,FPGA接收到的数据也是先接收到高位数据,再接收到低位数据。这里可以采用位移操作,将数据依次存入寄存器的相应位。代码实现如下所示。 | * 由ARM提供的数据和SCLK是同步的,那么FPGA接收数据的触发信号可以选用SCLK。阅读过STM32F407手册能够发现,它的SPI总线发送数据时,是先发送高位,再发送低位的。因此,FPGA接收到的数据也是先接收到高位数据,再接收到低位数据。这里可以采用位移操作,将数据依次存入寄存器的相应位。代码实现如下所示。 | ||
<code verilog> | <code verilog> | ||
- | always@(posedge spi_clk or negedge rst_n) | + | always@(posedge spi_clk or negedge rst_n) |
if(!rst_n) | if(!rst_n) | ||
data_in<=40'd0; | data_in<=40'd0; | ||
行 39: | 行 46: | ||
* 为了验证SPI通信的正确性,可以通过点亮LED来具象化实验效果。iCore3板卡上FPGA连接有三色LED。那么,可以通过发送“ledr、ledg、ledb”指令,点亮LED相应色彩,进行程序正确性的验证。由于这些指令是ASCII码格式,而SPI传输的是二进制模式,所以FPGA进行接收指令判断时,对比的为指令的二进制值。为了判断数据是否接收完毕,代码中做了“回车”指令检测,既检测到“回车”指令的ASCII码之后,判断为数据接收完毕,然后将接收数据“回车”指令之前的数据和LED点亮指令做对比,从而控制三色LED的显示。代码实现如下: | * 为了验证SPI通信的正确性,可以通过点亮LED来具象化实验效果。iCore3板卡上FPGA连接有三色LED。那么,可以通过发送“ledr、ledg、ledb”指令,点亮LED相应色彩,进行程序正确性的验证。由于这些指令是ASCII码格式,而SPI传输的是二进制模式,所以FPGA进行接收指令判断时,对比的为指令的二进制值。为了判断数据是否接收完毕,代码中做了“回车”指令检测,既检测到“回车”指令的ASCII码之后,判断为数据接收完毕,然后将接收数据“回车”指令之前的数据和LED点亮指令做对比,从而控制三色LED的显示。代码实现如下: | ||
<code verilog> | <code verilog> | ||
- | always@(posedge spi_clk or negedge rst_n) | + | always@(posedge spi_clk or negedge rst_n) |
- | if(!rst_n) | + | if(!rst_n) |
data<=32'd0; | data<=32'd0; | ||
- | else if(data_in[7:0] == 8'd13)//“回车”键对应的ASCII码的值为8‘d13 | + | else if(data_in[7:0] == 8'd13)//“回车”键对应的ASCII码的值为8‘d13 |
data<=data_in>>8;//取回车键之前的值 | data<=data_in>>8;//取回车键之前的值 | ||
- | else | + | else |
data<=data; | data<=data; | ||
- | //--------------------------data----------------------------// | + | //对比接收数据// |
- | /*对比接收数据*/ | + | |
reg [2:0]led; | reg [2:0]led; | ||
- | always@(posedge CLK_25M or negedge rst_n) | + | always@(posedge CLK_25M or negedge rst_n) |
if(!rst_n) | if(!rst_n) | ||
- | begin | + | led <= 3'b111; |
- | led <= 3'b111; | + | |
- | end | + | |
else if (data == ledr) | else if (data == ledr) | ||
- | led <= 3'b011; //红灯亮 | + | led <= 3'b011; //红灯亮 |
else if (data == ledg) | else if (data == ledg) | ||
- | led <= 3'b101; //绿灯亮 | + | led <= 3'b101; //绿灯亮 |
else if (data == ledb) | else if (data == ledb) | ||
- | led <= 3'b110; //蓝灯亮 | + | led <= 3'b110; //蓝灯亮 |
+ | </code> | ||
=== 2.FPGA发送数据。 === | === 2.FPGA发送数据。 === | ||
- | * FPGA发送数据的时候,ARM是接收方,但是发送时钟还是有ARM提供,即CS信号为低时,FPGA按照SCLK的时序发送数据,实验中,FPGA发送至ARM的内容是字符串“hello”对应ASCII码的二进制数。按照SPI总线定义,先发送高位,再发送低位。代码如下: | + | * FPGA发送数据的时候,ARM是接收方,但是发送时钟还是由ARM提供,即CS信号为低时,FPGA按照SCLK的时序发送数据,实验中,FPGA发送至ARM的内容是字符串“hello”对应ASCII码的二进制数。按照SPI总线定义,先发送高位,再发送低位。代码如下: |
<code verilog> | <code verilog> | ||
always@(negedge spi_clk or negedge rst_n) | always@(negedge spi_clk or negedge rst_n) | ||
if(!rst_n) | if(!rst_n) | ||
begin | begin | ||
- | spi_miso<=1; | + | spi_miso<=1; |
- | data_out<=hello; | + | data_out<=hello; |
end | end | ||
else if(!spi_cs ) | else if(!spi_cs ) | ||
begin | begin | ||
- | spi_miso <= data_out[39]; //将最高位通过SPI总线发送出去 | + | spi_miso <= data_out[39]; //将最高位通过SPI总线发送出去 |
- | data_out<=data_out<<1; | + | data_out<=data_out<<1; |
end | end | ||
else | else | ||
begin | begin | ||
- | spi_miso<=1'b1; | + | spi_miso<=1'b1; |
- | data_out<=hello; | + | data_out<=hello; |
end | end | ||
+ | </code> | ||
==== 五、操作流程和测试结果 ==== | ==== 五、操作流程和测试结果 ==== | ||