用户工具

站点工具


基于spi总线的arm与fpga通信实验

差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
后一修订版
前一修订版
基于spi总线的arm与fpga通信实验 [2020/07/02 18:24]
zgf [五、 实验步骤]
基于spi总线的arm与fpga通信实验 [2022/03/22 10:29] (当前版本)
sean
行 2: 行 2:
 |技术支持电话|**0379-69926675-801**||| |技术支持电话|**0379-69926675-801**|||
 |技术支持邮件|Gingko@vip.163.com||| |技术支持邮件|Gingko@vip.163.com|||
-|技术论坛|http://​www.eeschool.org||| 
 ^  版本 ​ ^  日期 ​ ^  作者 ​ ^  修改内容 ​ ^ ^  版本 ​ ^  日期 ​ ^  作者 ​ ^  修改内容 ​ ^
 |  V1.0  |  2020-07-02 ​ |  gingko ​ |  初次建立 ​ |  |  V1.0  |  2020-07-02 ​ |  gingko ​ |  初次建立 ​ | 
行 39: 行 38:
   * SPI总线四种工作方式 SPI 模块为了和外设进行数据交换,根据外设工作要求,其输出串行同步时钟极性和相位可以进行配置,时钟极性(CPOL)对传输协议没有重大的影响。如果 CPOL=0,串行同步时钟的空闲状态为低电平;如果CPOL=1,串行同步时钟的空闲状态为高电平。时钟相位(CPHA)能够配置用于选择两种不同的传输协议之一进行数据传输。如果CPHA=0,在串行同步时钟的第一个跳变沿(上升或下降)数据被采样;如果CPHA=1,在串行同步时钟的第二个跳变沿(上升或下降)数据被采样。SPI主模块和与之通信的外设备时钟相位和极性应该一致。如图13-1所示   * SPI总线四种工作方式 SPI 模块为了和外设进行数据交换,根据外设工作要求,其输出串行同步时钟极性和相位可以进行配置,时钟极性(CPOL)对传输协议没有重大的影响。如果 CPOL=0,串行同步时钟的空闲状态为低电平;如果CPOL=1,串行同步时钟的空闲状态为高电平。时钟相位(CPHA)能够配置用于选择两种不同的传输协议之一进行数据传输。如果CPHA=0,在串行同步时钟的第一个跳变沿(上升或下降)数据被采样;如果CPHA=1,在串行同步时钟的第二个跳变沿(上升或下降)数据被采样。SPI主模块和与之通信的外设备时钟相位和极性应该一致。如图13-1所示
    
-图13-1+{{ :​icore4:​icore4_fpga_13_1.png?​direct |图13-1}}
 === 3.SPI通信指令表 === === 3.SPI通信指令表 ===
  
行 59: 行 58:
 === 4、本实验实现方式 === === 4、本实验实现方式 ===
   * 通过FPGA建立的SPI模块对外提供的SCLK、CS、MOSI、MISO接口与STM32的SPI相连接,Commix串口精灵与STM32通过串口连接,实现三者之间的通信。本实验中,Commix串口精灵向STM32发送数据,STM32的RXD端口接收数据,然后,通过TXD端口把数据发送至FPGA,STM32起到一个桥梁作用。程序运行后,FPGA定时向STM32发送数据,经过STM32发送至串口精灵显示出来。下图为实验原理图。   * 通过FPGA建立的SPI模块对外提供的SCLK、CS、MOSI、MISO接口与STM32的SPI相连接,Commix串口精灵与STM32通过串口连接,实现三者之间的通信。本实验中,Commix串口精灵向STM32发送数据,STM32的RXD端口接收数据,然后,通过TXD端口把数据发送至FPGA,STM32起到一个桥梁作用。程序运行后,FPGA定时向STM32发送数据,经过STM32发送至串口精灵显示出来。下图为实验原理图。
- +{{ :​icore4:​icore4_fpga_13_2.png?​direct&​700 |实验原理图}} ​
 ==== 四、 代码讲解 ==== ==== 四、 代码讲解 ====
   * 本实验基于ARM+FPGA构架,通过ARM首先发送查询ID指令,然后依次通过指令设置写数据的长度、写数据地址、读数据的长度、读数据的地址,然后对比写入数据和读出数据是否一致判断数据是否写入成功,从而基于SPI总线实现ARM与FPGA之间的通信。   * 本实验基于ARM+FPGA构架,通过ARM首先发送查询ID指令,然后依次通过指令设置写数据的长度、写数据地址、读数据的长度、读数据的地址,然后对比写入数据和读出数据是否一致判断数据是否写入成功,从而基于SPI总线实现ARM与FPGA之间的通信。
-  * 1、实现ARM与FPGA通信,对FPGA而言,其关键就在于SPI时序的模拟,实现SPI数据的接收与发送,实现数据与传输信号之间的串并转换。FPGA首先接收ARM指令,然后解析指令,存储相应的信息与数据,并根据指令需求将相应的指令数据放到SIMO总线上,等待ARM读取,从而实现两者之间的数据交互。SPI时序的硬件语言描述如下:+  * 实现ARM与FPGA通信,对FPGA而言,其关键就在于SPI时序的模拟,实现SPI数据的接收与发送,实现数据与传输信号之间的串并转换。FPGA首先接收ARM指令,然后解析指令,存储相应的信息与数据,并根据指令需求将相应的指令数据放到SIMO总线上,等待ARM读取,从而实现两者之间的数据交互。SPI时序的硬件语言描述如下:
 <code verilog> <code verilog>
 ////////////////​按字节接收SPI发送过来的数据//////////////​ ////////////////​按字节接收SPI发送过来的数据//////////////​
行 72: 行 71:
 always@(posedge spi_clk or negedge rst_n) always@(posedge spi_clk or negedge rst_n)
  if(!rst_n)  if(!rst_n)
- begin +     ​begin 
- i <= 4'​d0;​ + i <= 4'​d0;​ 
- temp_data <= 40'​d0;​ + temp_data <= 40'​d0;​ 
- data <= 40'​d0;​ + data <= 40'​d0;​ 
- data_in <= 8'​d0;​ + data_in <= 8'​d0;​ 
- end+     ​end
  else case(i) ​  //​从高位开始接收数据,每8个spi_clk时钟接收一个Byte  else case(i) ​  //​从高位开始接收数据,每8个spi_clk时钟接收一个Byte
  4'​d0:​  4'​d0:​
- begin +     ​begin 
- i <= i + 1'​d1;​ + i <= i + 1'​d1;​ 
- data_in <= {data_in[6:​0],​spi_mosi};​ + data_in <= {data_in[6:​0],​spi_mosi};​ 
- temp_data <= {temp_data[31:​0],​data_in};​ + temp_data <= {temp_data[31:​0],​data_in};​ 
- if(data_in == 8'​d13) + if(data_in == 8'​d13) 
- begin +     ​begin 
- data <= temp_data;​ +         ​data <= temp_data;​ 
- end +     ​end 
- else  + else  
- begin +     ​begin 
- data <= data; + data <= data; 
- end+     ​end
  end  end
  4'​d1,​4'​d2,​4'​d3,​4'​d4,​4'​d5,​4'​d6:​  4'​d1,​4'​d2,​4'​d3,​4'​d4,​4'​d5,​4'​d6:​
  begin  begin
- i <= i + 1'​d1;​ +     ​i <= i + 1'​d1;​ 
- data_in <= {data_in[6:​0],​spi_mosi};​+     ​data_in <= {data_in[6:​0],​spi_mosi};​
  end  end
  4'​d7:​begin  4'​d7:​begin
- i <= 4'​d0;​ +     ​i <= 4'​d0;​ 
- data_in <= {data_in[6:​0],​spi_mosi};​+     ​data_in <= {data_in[6:​0],​spi_mosi};​
  end  end
  default: i <= 4'd0;  default: i <= 4'd0;
行 110: 行 109:
 always@(posedge clk_25m or negedge rst_n) always@(posedge clk_25m or negedge rst_n)
  if(!rst_n)  if(!rst_n)
- begin +     ​begin 
- led <= 3'​b101;​ + led <= 3'​b101;​ 
- end+     ​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;​ //蓝灯亮
   
 assign {led_red,​led_green,​led_blue} = led; assign {led_red,​led_green,​led_blue} = led;
行 126: 行 125:
  always@(posedge clk_25m or negedge rst_n)  always@(posedge clk_25m or negedge rst_n)
  if(!rst_n)  if(!rst_n)
- begin +     ​begin 
- spi_clk_r <= 1'​d1;​ + spi_clk_r <= 1'​d1;​ 
- end+     ​end
  else ​  else ​
  spi_clk_r <= spi_clk; ​  spi_clk_r <= spi_clk; ​
行 140: 行 139:
  if(!rst_n)  if(!rst_n)
  begin  begin
- data_out <= hello; +     ​data_out <= hello; 
- spi_out <= 1'​d0;​ +     ​spi_out <= 1'​d0;​ 
- j <= 6'd0;+     ​j <= 6'd0;
  end  end
  else case(j) ​ //​连续40个spi_clk_r时钟发送“hello”字符串  else case(j) ​ //​连续40个spi_clk_r时钟发送“hello”字符串
  6'​d0:​  6'​d0:​
- begin +     ​begin 
- {spi_out,​data_out[39:​1]} <= data_out; + {spi_out,​data_out[39:​1]} <= data_out; 
- j <= j + 1'​d1;​ + j <= j + 1'​d1;​ 
- end+     ​end
  6'​d39:​  6'​d39:​
- begin +     ​begin 
- {spi_out,​data_out[39:​1]} <= data_out; + {spi_out,​data_out[39:​1]} <= data_out; 
- data_out <= hello; + data_out <= hello; 
- j <= 6'​d0;​ + j <= 6'​d0;​ 
- end+     ​end
  default:  default:
- begin +     ​begin 
- {spi_out,​data_out[39:​1]} <= data_out; + {spi_out,​data_out[39:​1]} <= data_out; 
- j <= j + 1'​d1;​ + j <= j + 1'​d1;​ 
- end+     ​end
  endcase  endcase
 </​code>​ </​code>​
行 171: 行 170:
 图13-2 图13-2
 5、打开串口精灵,找到对应口打开,如下图。\\ ​ 5、打开串口精灵,找到对应口打开,如下图。\\ ​
-  +{{ :​icore4:​icore4_fpga_13_3.png?​direct |图13-3}}
-图13-3+
 6、打开KeilMDK开发环境,并打开实验工程。\\ ​ 6、打开KeilMDK开发环境,并打开实验工程。\\ ​
 7、将ARM程序下载至iCore4。\\ ​ 7、将ARM程序下载至iCore4。\\ ​
基于spi总线的arm与fpga通信实验.1593685452.txt.gz · 最后更改: 2020/07/02 18:24 由 zgf