[米联客-安路飞龙DR1-FPSOC] FPGA基础篇连载-16 SPI LOOP环路实验

软件版本:Anlogic -TD5.9.1-DR1_ES1.1

操作系统:WIN10 64bit

硬件平台:适用安路(Anlogic)FPGA

实验平台:米联客-MLK-L1-CZ06-DR1M90G开发板

板卡获取平台:https://milianke.tmall.com/

登录"米联客"FPGA社区 http://www.uisrc.com 视频课程、答疑解惑!

 

1概述

在前面完成了SPI发送驱动程序、SPI接收驱动程序设计,本文对前面的SPI收发驱动做一个环路测试,通过仿真,以及在线仿真的方式验证SPI的收发应用。

本文将在前面课程的基础上完成,包括采用前面课程编写SPI发送驱动和接收驱动。

在完成本实验前,请确保已经完成前面的实验,包括已经掌握以下能力:

1:完成了TD软件安装

2:完成了modelsim安装以及TD库的编译

3:掌握了TD仿真环境的设置

4:掌握了modesim通过do文件启动仿真

 

实验目的:

1:实现UART串口发送控制器的设计

2:实现主程序中调用串口发送控制器发送字符"HELLO FPGA"

3:实用modelsim完成仿真验证

4:编译并且实用chipwatcher观察芯片内部信号

1.1SPI收发环路简介

主机在通过MOSI数据线发送数据的同时,从机也会通过MISO 将数据传输给主机(收发同时进行)。数据通常先移出最高位,传输可能会持续任意数量的时钟周期。传输完成后,主设备拉高SS片选信号并停止传输信号。

1.2硬件电路分析

CEPcamera expand peripheral),CEP2.4间距排针,20pin 差分等长走线具有14个可用IOCEP-GPIO 接口中的IO可以用于完成本实验。进行SPI通信时,短接SPI发送模块和接收模块的SCLK,短接SPI发送模块的MOSI和接收模块的MISO,形成一条通路。

2 SPI环路程序设计

2.1系统框图

本次实验包含三个模块,SPI发送驱动模块、SPI接收驱动模块、顶层模块。以下给出系统框图,关于接收和发送模块的详细描述请看前面的实验,我们主要看顶层模块关于发送状态机的部分。芯片内部接收驱动接收到的有效信号通过在线逻辑分析仪在线观察结果。

发送状态机;

在所有模块开始运行之前先进行复位延时,计数结束后再进入到发送状态机部分。延时完成后进入状态0spi总线不忙时拉高ss片选信号,spi_ss_i信号用于控制spi接收模块的数据的启动接收和停止接收,并进入状态1;拉低ss片选信号,启动SPI接收模块,进入状态2;拉高req信号,启动SPI发送模块,发送第一个测试数据spi_tx_data=1,此时SPI接收模块同时接收SPI发送驱动发送的数据O_spi_mosi,并进入状态3;如果spi总线忙,清除spi_tx_req,并重新进入状态0等待spi总线不忙时开启下一次的传输;如果总线不忙,进入状态0开启下一次传输。

2.2 驱动源码

在本实验中,TX发送状态机中增加spi_ss控制,该信号用于spi接收模块的数据的启动接收和停止接收控制

 

 

3 FPGA工程

  1 `timescale 1ns / 1ps//仿真时钟刻度和精度
  2 module spi_master#
  3 (
  4 parameter CLK_DIV = 10        
  5 )
  6 (
  7 input  I_sysclk,                                                     //系统时钟
  8 input  I_rstn,                                                       //全局复位       
  9 output O_spi_sclk,                                                   //SPI MASTER输出时钟
 10 input  I_spi_sclk,                                                   //SPI Slave 输入时钟
 11 output O_spi_mosi,                                                   //SPI MASTER输出数据
 12 input  I_spi_miso                                                    //SPI Slave 输入数据
 13 ); 
 14 
 15 wire        spi_busy;
 16 reg         spi_tx_req;
 17 reg [7:0]   spi_tx_data;
 18 reg [1:0]   M_S;
 19 
 20 reg         spi_ss_i;/*synthesis keep*/
 21 wire        spi_rvalid;/*synthesis keep*/
 22 wire[7:0]   spi_rdata;/*synthesis keep*/
 23 
 24 reg [10:0]  delay_cnt;
 25 wire        delay_done;
 26 
 27 assign delay_done = delay_cnt[10];                         //复位延时计数
 28 always @(posedge I_sysclk or negedge I_rstn) begin       //异步复位
 29     if(!I_rstn) 
 30         delay_cnt <=0;                                       //复位来的是,时钟清零
 31     else if(delay_cnt[10] == 1'b0)                      //当delay_cnt[10]等于1时,计数清零,不满足就自+1
 32         delay_cnt <= delay_cnt + 1'b1;
 33     else 
 34         delay_cnt <= 0;                                 //达到预期值,计数清零
 35 end
 36 
 37 always @(posedge I_sysclk or negedge I_rstn) begin         //spi发送状态机
 38     if(!I_rstn) begin
 39         spi_ss_i    <= 1'b1;
 40         spi_tx_req  <= 1'b0;
 41         spi_tx_data <= 8'd0;
 42         M_S         <= 2'd0;
 43     end
 44     else begin
 45         case(M_S)
 46         0:if(delay_done&&(!spi_busy))begin          //延时完成且SPI传输非忙
 47             spi_ss_i <= 1'b1;                        //拉高spi_ss_i信号,启动spi接收模块的数据的接收
 48             M_S <= 2'd1;                              //从初始状态转入状态1
 49         end
 50         1:if(delay_done&&(!spi_busy))begin          
 51             spi_ss_i <= 1'b0;                        //启动后,将  spi_ss_i信号复原
 52             M_S <= 2'd2;
 53         end
 54         2:if(delay_done&&(!spi_busy))begin          //总线不忙启动传输
 55            spi_tx_req  <= 1'b1;                       //req信号拉高,准备发送
 56            spi_tx_data <= spi_tx_data + 1'b1;        //测试数据
 57            M_S <= 2'd3;
 58         end
 59         3:if(spi_busy)begin                           //如果spi总线忙,清除spi_tx_req
 60            spi_tx_req  <= 1'b0;
 61            M_S <= 2'd0;
 62         end
 63         default:M_S <= 2'd0;
 64         endcase
 65     end
 66 end   
 67 //spi master tx控制器例化
 68 uimspi_tx#
 69 (
 70 .CLK_DIV(CLK_DIV),
 71 .CPOL(1'b0),
 72 .CPHA(1'b0)
 73 )
 74 uimspi_tx_inst(
 75 .I_clk(I_sysclk),
 76 .I_rstn(I_rstn),
 77 .O_spi_mosi(O_spi_mosi),
 78 .O_spi_sclk(O_spi_sclk),
 79 .I_spi_tx_req(spi_tx_req),
 80 .I_spi_tx_data(spi_tx_data),
 81 .O_spi_busy(spi_busy)
 82  );
 83 //spi rx控制器例化
 84 uispi_rx#
 85 (
 86 .BITS_LEN(8),
 87 .CPOL(1'b0),
 88 .CPHA(1'b0) 
 89 )
 90 uispi_rx_inst(
 91 .I_clk(I_sysclk),
 92 .I_rstn(I_rstn),
 93 .I_spi_clk(I_spi_sclk),
 94 .I_spi_rx(I_spi_miso),
 95 .I_spi_ss(spi_ss_i),
 96 .O_spi_rvalid(spi_rvalid),
 97 .O_spi_rdata(spi_rdata)
 98 );
 99 
100 endmodule

 

 

 

fpga工程的创建过程不再重复,如有不清楚的请看前面实验,具体的FPGA型号以对应的开发板上芯片为准

米联客的代码管理规范,在对应的FPGA工程路径下创建uisrc路径,并且创建以下文件夹

01_rtl:放用户编写的rtl代码

02_sim:仿真文件或者工程

03_ip:放使用到的ip文件

04_pin:fpgapin脚约束文件或者时序约束文件

05_boot:放编译好的bit或者bin文件(一般为空)

06_doc:放本一些相关文档(一般为空)

4 Modelsim仿真

4.1准备工作

Modelsim仿真的创建过程不再重复,如有不清楚的请看前面实验

 

仿真测试文件源码如下:

 

 1 `timescale 1ns / 1ps//定义仿真时间刻度/精度
 2 module master_spi_tb;
 3 localparam      CLK_TIME   =  'd20;//时钟周期,以ns为单位
 4 reg I_sysclk;
 5 reg I_rstn;  
 6 wire O_spi_sclk;
 7 wire I_spi_sclk;
 8 wire O_spi_mosi;
 9 wire I_spi_miso;
10 
11 assign I_spi_miso = O_spi_mosi;//模拟数据回环
12 assign I_spi_sclk = O_spi_sclk;//模拟时钟回环
13 //例化顶层模块
14 spi_master#
15 (
16 .CLK_DIV(100)    
17 )
18 spi_master_inst(
19 .I_sysclk(I_sysclk),
20 .I_rstn(I_rstn),
21 .O_spi_sclk(O_spi_sclk),
22 .O_spi_mosi(O_spi_mosi),
23 .I_spi_sclk(I_spi_sclk),
24 .I_spi_miso(I_spi_miso)
25 );
26 initial begin
27 //初始化REG寄存器
28     I_sysclk= 1'b0;//系统时钟
29     I_rstn = 1'b0;//复位
30     #100;
31     I_rstn = 1'b1;
32 end
33 always #(CLK_TIME/2) I_sysclk = ~I_sysclk;     //产生主时钟
34 endmodule

 

 

 

 

4.2启动modelsim仿真

启动后,右击需要观察的信号,添加到波形窗口

以下启动modelsim仿真,可以放大箭头所指位置,查看接收数据和发送数据是否一致,本实验只测试CHPA=0 CPOL=0的情况。

5上板验证

5.1 chipwatcher设置

关于chipwatcher的设置,可以参考前面的实验,这里只做关键内容介绍。为了在线逻辑分析仪不去优化一些信号可以实用:

reg spi_ss_i;/*synthesis keep*/

wire spi_rvalid;/*synthesis keep*/

wire[7:0] spi_rdata;/*synthesis keep*/

设置好后需要保持,然后重新编译

5.2硬件连接

(该教程为通用型教程,教程中仅展示一款示例开发板的连接方式,具体连接方式以所购买的开发板型号以及结合配套代码管脚约束为准。)

请确保下载器和开发板已经正确连接,并且开发板已经上电(注意JTAG端子不支持热插拔,而USB接口支持,所以在不通电的情况下接通好JTAG后,再插入USB到电脑,之后再上电,以免造成JTAG IO损坏)

    外部环路需要实用跳线帽,CEP-GPIO接口中的IO可以用于完成本实验

5.3在线调试结果

Chipwatcher的如果调用这里不再重复,如果有不清楚的可以阅读前面文章中的实验。

需要观察的信号如下,设置spi_valid为高电平的时候触发采集:

可以看到接收到的数据和发送的数据一致

posted @ 2024-07-29 16:07  米联客(milianke)  阅读(2)  评论(0编辑  收藏  举报