搜索
bottom↓
回复: 0

《ATK-DFPGL22G之FPGA开发指南_V1.0》第二十章 IP核之FIFO实验

[复制链接]

出0入234汤圆

发表于 2023-1-31 09:34:47 | 显示全部楼层 |阅读模式
本帖最后由 正点原子 于 2023-1-31 09:33 编辑

1)实验平台:正点原子紫光PGL22G开发板
2)购买链接:https://item.taobao.com/item.htm?&id=692368045899
3)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-340253-1-1.html
4)正点原子官方B站:https://space.bilibili.com/394620890
5)正点原子FPGA交流群:435699340 lQLPJxaFi2zaB4UWWrDAMgIsFEW2pwLb3abnwDMA_90_22.png
lQDPJxaFi2nfFizMjM0CbLCPlxn_FVheIQLb3aGrwFQA_620_140.jpg

lQLPJxaFi2nfFhLMkM0BXrDNvOUyeU_FPgLb3aGvQNIA_350_144.png


第二十章 IP核之FIFO实验

FIFO的英文全称是First In First Out,即先进先出。FPGA使用的FIFO一般指的是对数据的存储具有先进先出特性的一个缓存器,常被用于数据的缓存,或者高速异步数据的交互也即所谓的跨时钟域信号传递。它与FPGA内部的RAM和ROM的区别是没有外部读写地址线,采取顺序写入数据,顺序读出数据的方式,使用起来简单方便,由此带来的缺点就是不能像RAM和ROM那样可以由地址线决定读取或写入某个指定的地址。本章我们将对PDS软件生成的FIFO IP核进行读写测试,来向大家介绍Pango FIFO IP核的使用方法。
本章包括以下几个部分:
20.1FIFO IP核简介
20.2实验任务
20.3硬件设计
20.4程序设计
20.5下载验证


20.1FIFO IP核简介

根据FIFO工作的时钟域,可以将FIFO分为同步FIFO和异步FIFO。同步FIFO是指读时钟和写时钟为同一个时钟,在时钟沿来临时同时发生读写操作。异步FIFO是指读写时钟不一致,读写时钟是互相独立的。Pango的FIFO IP核可以被配置为同步FIFO或异步FIFO,其信号框图如下图所示。从图中可以了解到,当被配置为同步FIFO时,只使用wr_clk,所有的输入输出信号都同步于wr_clk信号。而当被配置为异步FIFO时,写端口和读端口分别有独立的时钟,所有与写相关的信号都是同步于写时钟wr_clk,所有与读相关的信号都是同步于读时钟rd_clk。
IP核之FIFO实验613.png
图 20.1.1 Pango的FIFO IP核的信号框图

对于FIFO需要了解一些常见参数:
FIFO的宽度:FIFO一次读写操作的数据位N。
FIFO的深度:FIFO可以存储多少个宽度为N位的数据。
将空标志:almost_empty。FIFO即将被读空。
空标志:rd_empty。FIFO已空时由FIFO的状态电路送出的一个信号,以阻止FIFO的读操作继续从FIFO中读出数据而造成无效数据的读出。
将满标志:almost_full。FIFO即将被写满。
满标志:wr_full。FIFO已满或将要写满时由FIFO的状态电路送出的一个信号,以阻止FIFO的写操作继续向FIFO中写数据而造成溢出。
读时钟:读FIFO时所遵循的时钟,在每个时钟的上升沿触发。
写时钟:写FIFO时所遵循的时钟,在每个时钟的上升沿触发。
这里请注意,“almost_empty”和“almost_full”这两个信号分别被看作“empty”和“full”的警告信号,他们相对于真正的空(empty)和满(full)都会提前一个时钟周期拉高。
对于FIFO的基本知识先了解这些就足够了,可能有人会好奇为什么会有同步FIFO和异步FIFO,它们各自的用途是什么。之所以有同步FIFO和异步FIFO是因为各自的作用不同。同步FIFO常用于同步时钟的数据缓存,异步FIFO常用于跨时钟域的数据信号的传递,例如时钟域A下的数据data1传递给异步时钟域B,当data1为连续变化信号时,如果直接传递给时钟域B则可能会导致收非所送的情况,即在采集过程中会出现包括亚稳态问题在内的一系列问题,使用异步FIFO能够将不同时钟域中的数据同步到所需的时钟域中。
20.2实验任务
本节的实验任务是使用Pango生成FIFO IP核,并实现以下功能:当FIFO为空时,向FIFO中写入数据,写入的数据量和FIFO深度一致,即FIFO被写满;然后从FIFO中读出数据,直到FIFO被读空为止,以此向大家详细介绍一下FIFO IP核的使用方法。
20.3硬件设计
本章实验只用到了输入的时钟信号和按键复位信号,没有用到其它硬件外设。
本实验中,各端口信号的管脚分配如下表所示。
表 20.3.1 IP实验管脚分配
lQLPJxqNaW0UsMhHzQJFsHBl1hi4iHNbA9L6DLgAVQA_581_71.png

对应的FDC约束语句如下所示:
define_attribute {p:sys_clk} {PAP_IO_DIRECTION} {INPUT}
define_attribute {p:sys_clk} {PAP_IO_LOC} {B5}
define_attribute {p:sys_clk} {PAP_IO_VCCIO} {3.3}
define_attribute {p:sys_clk} {PAP_IO_STANDARD} {LVCMOS12}
define_attribute {p:sys_clk} {PAP_IO_NONE} {TRUE}
define_attribute {p:sys_rst_n} {PAP_IO_DIRECTION} {INPUT}
define_attribute {p:sys_rst_n} {PAP_IO_LOC} {G5}
define_attribute {p:sys_rst_n} {PAP_IO_VCCIO} {1.5}
define_attribute {p:sys_rst_n} {PAP_IO_STANDARD} {LVCMOS12}
define_attribute {p:sys_rst_n} {PAP_IO_NONE} {TRUE}
20.4程序设计
根据实验任务要求和模块化设计的思想,我们需要如下4个模块:fifo IP核、写fifo模块、读fifo模块以及顶层例化模块实现前三个模块的信号交互。由于FIFO多用于跨时钟域信号的处理,所以本实验我们使用异步FIFO来向大家详细介绍双时钟FIFO IP核的创建和使用。为了方便大家理解,这里我们将读/写时钟都用系统时钟来驱动。系统的功能框图如下图所示:
IP核之FIFO实验2483.png
图 20.4.1 系统框图

首先在PDS软件中创建一个名为ip_fifo的工程,工程创建完成后,在PDS软件的上方的菜单栏中“Tools”栏中单击“IP Compiler”按钮后弹出的“IP Compiler”窗口如图 20.4.3所示。
IP核之FIFO实验2674.png
图 20.4.2 点击“IP Compiler”

IP核之FIFO实验2744.png
图 20.4.3 “IP Compiler”窗口

本实验使用的IP核路径是Module→Memory→DRM→DRM Base FIFO,如下图所示。
IP核之FIFO实验2865.png
图 20.4.4 DRM Base FIFO IP

点击上图中红框中的IP后如下图所示:
IP核之FIFO实验2955.png
图 20.4.5 DRM Base FIFO详情页面

Pathname:新建IP核在工程所在路径,这里保持默认即可。
Instance Name:在这里给新建的FIFO IP命名,我们这里命名为“fifo_generator_0”。
接下来的IP框里面的内容是该IP的基础信息,例如名称、版本号与所属公司(Pango)。Part框中的信息为工程所使用的芯片的详细信息“PGL22G-6CMBG324”。
点击上图中的“Customize”按钮进入“Customize IP”窗口对FIFO IP的参数进行配置,“Customize IP”窗口界面如下图所示:图中的“Add IP”弹窗点击“Yes”后进入“Customize IP”界面进行异步FIFO的参数配置,“Customize IP”界面如图 20.4.7所示。
IP核之FIFO实验3386.png
图 20.4.6 “Add IP”弹窗

IP核之FIFO实验3451.png
图 20.4.7 "Customize IP"界面

本实验我们主要进行如下配置:
IP核之FIFO实验3537.png
图 20.4.8 DRM Base FIFO参数配置界

Customize IP界面主要包括如下选项:
DRM Resource Usage:选项主要说明DRM资源使用情况。该选项下的“DRM Resource Type”是
DRM资源类型,可以设置“AUTO”、“DRM9K”、“DRM18K”三种模式。三种模式可以根据你需要地址宽度与数据宽度来来设置,一般我们设置为“AUTO”模式。
Write/Read Port Use Same Data Widt:配置读写端口是否使用混合位宽模式(注:混合位宽时,关闭Address Strobe功能),本实验勾选该选项,使用混合位宽模式,只需要配置写入端口的地址位宽与数据位宽,读端口的地址位宽与数据位宽会与写入端口保持一致。
FIFO Type: FIFO可以配置的类型有两种,"ASYN_FIFO"异步FIFO和"SYNC_FIFO"同步FIFO,本实验配置的是异步FIFO类型。
Enable Byte Write:配置是否使能Byte Write功能,其含义是Byte写使能,也就是以字节为单位写入数据;Byte Write使能时,同时需要配置字节(Byte)的位宽(Byte Size)与字节个数(Byte Numbers),Byte Size可选择8或者9;Byte Numbers即配置所使用的Byte个数(注:Byte Write使能时,关闭Address Strobe功能。)举例说明:输入数据为32-bit,字节的位宽(Byte Size)设置为8bit,那么就需要4-bit Byte写使能信号,这个使能信号与输入数据各位的对应关系如下图所示。从图中不难看出,当we[3]有效时,只会将输入数据的高8-bit写入到目标地址;当we[0]有效时,只会将输入数据的低8-bit写入到目标地址。其实,也就是根据写使能来更新指定地址上原始数据的某些位,本实验不需要使能Byte Write功能即不需要勾选该配置。
lQLPJwLAtMRuUsgrzQKJsJ-xt_SQLNEwA9L6LKFAKwA_649_43.png
图 20.4.9 Byte写使能与输入数据的对应关系

Write Port:对写入端口进行配置。Address Width配置地址位宽,Data Width配置数据位宽。地址位宽合法配置范围为5~20,数据位宽合法配置范围为1~1152,但是所占用的DRM9K或者DRM18K个数必须小于总资源个数。本实验我们配置的地址位宽为5,数据位宽为8位。
Read Port:对读出端口进行配置。Address Width配置地址位宽,Data Width配置数据位宽。地址位宽合法配置范围为5~20,数据位宽合法配置范围为1~1152,但是所占用的DRM9K或者DRM18K个数必须小于总资源个数。本实验我们配置使用了混合位宽模式,所以读端口的地址位宽与数据位宽会直接与写端口的配置保持一致。
Enable Almost Full Water Level:配置是否使能wr_water_level信号,使能wr_water_level信号可以对写端口数据进行计数,本实验配置使能写端口计数。
Enable Almost Empty Water Level:配置是否使能wr_empty_level信号,使能wr_empty_level信号可以对读端口数据进行计数,本实验配置使能读端口计数。
Almost Full Numbers:配置FIFO Almost Full个数,设置为该选项后面的允许的最大值。
Almost Empty Numbers:配置FIFO Almost Empty个数,设置为该选项后面的允许的最小值。
Enable rd_oce Signal:配置是否使能rd_oce(输出寄存器选项)信号,输出寄存使能信号为高时对应地址有效,读数据会寄存输出,若输出寄存使能信号为低时对应地址无效,读数据保持。并且使能rd_oce信号时,默认且必须使能读端口输出寄存“Enable Output Register”,本实验不需要使能读信号,所以不勾选该选项。
Enable Output Register:输出寄存器选项。如果勾选了“Enable rd_oce Signal”信号,输出寄存器默认是选中状态,作用是打开DRM内部位于输出数据总线之后的输出流水线寄存器,虽然在一般设计中为了改善时序性能会保持此选项的默认勾选状态,但是这会使得BRM输出的数据延迟一拍,这不利于我们在调试窗口中直观清晰地观察信号;而且在本实验中我们仅仅是把BRM的数据输出总线连接到了调试的探针端口上来进行观察,除此之外数据输出总线没有别的负载,不会带来难以满足的时序路径,因此这里取消勾选。
Enable Clock Polarity Invert for Output Register:配置是否使能读端口输出时钟极性反向,使能读端口输出时钟极性反向时,默认且必须使能读端口输出寄存(Enable Output Register),这里不需要使能读端口输出时钟极即不需要勾选该配置。
Enable Low Power Mode:配置是否使能低功耗模式,本实验不需要配置成低功耗模式,即不勾选使能低功耗模式。
Reset Type:配置复位方式:"ASYNC"异步复位,"SYNC"同步复位,"Sync_Internally "异步复位同步释放,本实验选择异步复位(低有效)。
至此本实验所需要的异步FIFO IP已配置完成,接下来点击“Customize IP”窗口左上角的“Generate”在弹出的“Question”对话框选择“OK”即可,如下图所示。
IP核之FIFO实验6004.png
图 20.4.10 点击“OK”

点击“OK”后打印如下左图信息,至此FIFO IP核配置成功,并生成fifo_generator_0_tmpl.v文件。例化FIFO IP时可以使用下图中fifo_generator_0_tmpl.v文件红框中的代码。
IP核之FIFO实验6176.png
图 20.4.11 FIFO IP创建成功

然后如下图所示,关闭“Customize IP”页面与“IP Compiler”页面。
IP核之FIFO实验6287.png
图 20.4.12 关闭创建IP的窗口

之后我们就可以在“Sources”窗口的“Designs”一栏中出现了该IP核“fifo_generator_0”如下图所示。
IP核之FIFO实验6416.png
图 20.4.13 FIFO IP核

我们创建一个verilog源文件,其名称为ip_fifo.v,作为顶层模块,其代码如下:
1  module ip_fifo(
2      input    sys_clk ,  // 时钟信号
3      input    sys_rst_n  // 复位信号
4  );
5  
6  //wire define
7  wire         fifo_wr_en         ;    // FIFO写使能信号
8  wire         fifo_rd_en         ;    // FIFO读使能信号
9  wire  [7:0]  fifo_din           ;    // 写入到FIFO的数据
10 wire  [7:0]  fifo_dout          ;    // 从FIFO读出的数据
11 wire         almost_full        ;    // FIFO将满信号
12 wire         almost_empty       ;    // FIFO将空信号
13 wire         fifo_full          ;    // FIFO满信号
14 wire         fifo_empty         ;    // FIFO空信号
15 wire  [7:0]  fifo_wr_data_count ;    // FIFO写时钟域的数据计数
16 wire  [7:0]  fifo_rd_data_count ;    // FIFO读时钟域的数据计数
17
18 //*****************************************************
19 //**                    main code
20 //*****************************************************
21
22 reg          almost_empty_d0  ;    //almost_empty 延迟一拍
23 reg          almost_empty_d1  ;    //almost_empty 延迟两拍
24 reg          almost_empty_syn ;    //almost_empty 延迟三拍
25                                   
26 reg          almost_full_d0   ;    //almost_full 延迟一拍
27 reg          almost_full_d1   ;    //almost_full 延迟两拍
28 reg          almost_full_syn  ;    //almost_full 延迟三拍
29
30 //因为 almost_empty 信号是属于FIFO读时钟域的
31 //所以要将其同步到写时钟域中
32 always@( posedge sys_clk ) begin
33  if( !sys_rst_n ) begin
34      almost_empty_d0  <= 1'b0 ;
35      almost_empty_syn <= 1'b0 ;
36      almost_empty_d1  <= 1'b0 ;
37  end
38  else begin
39      almost_empty_d0  <= almost_empty ;
40      almost_empty_d1  <= almost_empty_d0 ;
41      almost_empty_syn <= almost_empty_d1 ;
42  end
43 end
44
45 //因为 almost_full 信号是属于FIFO读时钟域的
46 //所以要将其同步到写时钟域中
47 always@( posedge sys_clk ) begin
48  if( !sys_rst_n ) begin
49      almost_full_d0  <= 1'b0 ;
50      almost_full_syn <= 1'b0 ;
51      almost_full_d1  <= 1'b0 ;
52  end
53  else begin
54      almost_full_d0  <= almost_full ;
55      almost_full_d1  <= almost_full_d0 ;
56      almost_full_syn <= almost_full_d1 ;
57  end
58 end
59
60 fifo_generator_0 u_fifo_generator_0 (
61     .wr_clk            (sys_clk           ),    // input
62     .wr_rst            (~sys_rst_n        ),    // input
63     .wr_en             (fifo_wr_en        ),    // input
64     .wr_data           (fifo_din          ),    // input [7:0]
65     .wr_full           (fifo_full         ),    // output
66     .wr_water_level    (fifo_wr_data_count),    // output [8:0]
67     .almost_full       (almost_full       ),    // output
68     .rd_clk            (sys_clk           ),    // input
69     .rd_rst            (~sys_rst_n        ),    // input
70     .rd_en             (fifo_rd_en        ),    // input
71     .rd_data           (fifo_dout         ),    // output [7:0]
72     .rd_empty          (fifo_empty        ),    // output
73     .rd_water_level    (fifo_rd_data_count),    // output [8:0]
74     .almost_empty      (almost_empty      )     // output
75 );
76
77 //例化写FIFO模块
78 fifo_wr  u_fifo_wr(
79     .clk            ( sys_clk          ),    // 写时钟
80     .rst_n          ( sys_rst_n        ),    // 复位信号
81
82     .fifo_wr_en     ( fifo_wr_en       ),    // fifo写请求
83     .fifo_wr_data   ( fifo_din         ),    // 写入FIFO的数据
84     .almost_empty   ( almost_empty_syn ),    // fifo空信号
85     .almost_full    ( almost_full_syn  )     // fifo满信号
86 );
87
88 //例化读FIFO模块
89 fifo_rd  u_fifo_rd(
90     .clk            ( sys_clk          ),    // 读时钟
91     .rst_n          ( sys_rst_n        ),    // 复位信号
92                                             
93     .fifo_rd_en     ( fifo_rd_en       ),    // fifo读请求
94     .fifo_dout      ( fifo_dout        ),    // 从FIFO输出的数据
95     .almost_empty   ( almost_empty_syn ),    // fifo空信号
96     .almost_full    ( almost_full_syn  )     // fifo满信号
97 );
98
99 endmodule
顶层模块主要是对FIFO IP核、写FIFO模块、读FIFO模块进行例化。
写FIFO模块fifo_wr.v源文件的代码如下:
1  module fifo_wr(
2      //mudule clock
3      input                  clk         ,    // 时钟信号
4      input                  rst_n       ,    // 复位信号
5      //FIFO interface      
6      input                  almost_empty,    // FIFO将空信号
7      input                  almost_full ,    // FIFO将满信号
8      output    reg          fifo_wr_en  ,    // FIFO写使能
9      output    reg  [7:0]   fifo_wr_data     // 写入FIFO的数据
10 );
11
12 //reg define
13 reg  [1:0]  state      ; //动作状态
14 reg  [3:0]  dly_cnt    ; //延迟计数器
15 //*****************************************************
16 //**                    main code
17 //*****************************************************
18 //向FIFO中写入数据
19 always @(posedge clk ) begin
20     if(!rst_n) begin
21         fifo_wr_en   <= 1'b0;
22         fifo_wr_data <= 8'd0;
23         state        <= 2'd0;
24         dly_cnt      <= 4'd0;
25     end
26     else begin
27         case(state)
28             2'd0: begin
29                 if(almost_empty) begin  //如果检测到FIFO将被读空
30                     state <= 2'd1;        //就进入延时状态
31                 end
32                 else
33                     state <= state;
34             end
35          2'd1: begin
36              if(dly_cnt == 10) begin  //延时10拍
37                                          //原因是FIFO IP核内部状态信号的更新存在延时
38                                          //延迟10拍以等待状态信号更新完毕                  
39                     dly_cnt    <= 4'd0;
40                  state      <= 2'd2;     //开始写操作
41                  fifo_wr_en <= 1'b1;     //打开写使能               
42              end
43              else begin
44                  dly_cnt <= dly_cnt + 4'd1;              
45              end
46             end            
47          2'd2: begin
48                 if(almost_full) begin        //等待FIFO将被写满
49                     fifo_wr_en   <= 1'b0;  //关闭写使能
50                     fifo_wr_data <= 8'd0;
51                     state        <= 2'd0;  //回到第一个状态
52                 end
53                 else begin                 //如果FIFO没有被写满
54                     fifo_wr_en   <= 1'b1;  //则持续打开写使能
55                     fifo_wr_data <= fifo_wr_data + 1'd1;  //且写数据值持续累加
56                 end
57             end
58          default : state <= 2'd0;
59         endcase
60     end
61 end
62
63 endmodule
fifo_wr模块的核心部分是一个不断进行状态循环的小状态机,如果检测到FIFO为空,则先延时10拍,这里注意,由于FIFO的内部信号的更新比实际的数据读/写操作有所延时,所以延时10拍的目的是等待FIFO的空/满状态信号、数据计数信号等信号的更新完毕之后再进行FIFO写操作,如果写满,则回到状态0,即等待FIFO被读空,以进行下一轮的写操作。
读FIFO模块fifo_rd.v源文件的代码如下:
1  module fifo_rd(
2      //system clock
3      input               clk         ,    // 时钟信号
4      input               rst_n       ,    // 复位信号
5      //FIFO interface
6      input        [7:0]  fifo_dout   ,    // 从FIFO读出的数据
7      input               almost_full ,    // FIFO将满信号
8      input               almost_empty,    // FIFO将空信号
9      output  reg         fifo_rd_en       // FIFO读使能
10 );
11
12 //reg define
13 reg  [1:0]  state           ;    // 动作状态
14 reg         almost_full_d0  ;    // fifo_full 延迟一拍
15 reg         almost_full_syn ;    // fifo_full 延迟两拍
16 reg  [3:0]  dly_cnt         ;    //延迟计数器
17
18 //*****************************************************
19 //**                    main code
20 //*****************************************************
21
22 //因为 fifo_full 信号是属于FIFO写时钟域的
23 //所以要将其同步到读时钟域中
24 always@( posedge clk ) begin
25  if( !rst_n ) begin
26      almost_full_d0  <= 1'b0 ;
27      almost_full_syn <= 1'b0 ;
28  end
29  else begin
30      almost_full_d0  <= almost_full ;
31      almost_full_syn <= almost_full_d0 ;
32  end
33 end
34
35 //读出FIFO的数据
36 always @(posedge clk ) begin
37     if(!rst_n) begin
38         fifo_rd_en <= 1'b0;
39      state      <= 2'd0;
40      dly_cnt    <= 4'd0;
41     end
42     else begin
43         case(state)
44             2'd0: begin
45                 if(almost_full_syn)      //如果检测到FIFO将被写满
46                     state <= 2'd1;       //就进入延时状态
47                 else
48                     state <= state;
49             end
50          2'd1: begin
51                 if(dly_cnt == 4'd10) begin  //延时10拍
52                                          //原因是FIFO IP核内部状态信号的更新存在延时
53                                          //延迟10拍以等待状态信号更新完毕
54                     dly_cnt <= 4'd0;
55                  state   <= 2'd2;        //开始读操作
56              end
57              else
58                  dly_cnt <= dly_cnt + 4'd1;
59             end
60          2'd2: begin
61                 if(almost_empty) begin     //等待FIFO将被读空
62                     fifo_rd_en <= 1'b0;    //关闭读使能
63                     state      <= 2'd0;    //回到第一个状态
64                 end
65                 else                       //如果FIFO没有被读空
66                     fifo_rd_en <= 1'b1;    //则持续打开读使能
67             end
68          default : state <= 2'd0;
69         endcase
70     end
71 end
72
73 endmodule
读模块的代码结构与写模块几乎一样,也是使用一个不断进行状态循环的小的状态机来控制操作过程,读者参考着代码应该很容易能够理解,这里就不再赘述。
我们对代码进行仿真,TestBench中只要送出时钟的复位信号即可。TB文件如下:
1  module tb_ip_fifo;
2  
3  reg  grs_n;
4  //GTP_GRS I_GTP_GRS(
5      GTP_GRS GRS_INST(
6      .GRS_N (grs_n)
7      );
8      
9      initial begin
10     grs_n = 1'b0;
11     #5000 grs_n = 1'b1;
12     end
13     
14     // Inputs
15     reg sys_clk;
16     reg sys_rst_n;
17     
18     // Instantiate the Unit Under Test (UUT)
19     ip_fifo  u_ip_fifo (
20         .sys_clk         (sys_clk),
21         .sys_rst_n       (sys_rst_n)
22     );
23     
24     //Genarate the clk
25     parameter PERIOD = 20;
26     always begin
27         sys_clk = 1'b0;
28         #(PERIOD/2) sys_clk = 1'b1;
29         #(PERIOD/2);
30     end   
31   
32     initial begin
33         // Initialize Inputs
34         sys_rst_n = 0;
35         // Wait 100 ns for global reset to finish
36         #100  ;
37         sys_rst_n = 1;
38         // Add stimulus here
39         
40     end
41
42 endmodule
写满后转为读的仿真波形图如下图所示:
IP核之FIFO实验16272.png
图 20.4.14仿真波形1

由波形图可知,当写满255个数据后,fifo_full满信号就会拉高。经过延时之后,fifo_rd_en写使能信号拉高,经过一拍之后就开始将fifo中的数据送到fifo_dout端口上。
写满后转为读的仿真波形图如下图所示:
IP核之FIFO实验16444.png
图 20.4.15 仿真波形2

由波形图可知,当读完255个数据后,fifo_empty空信号就会拉高。经过延时之后,fifo_wr_en写使能信号拉高,经过一拍之后就开始向fifo中继续写入数据。
20.5下载验证
新建DebugCore,将fifo_wr_en、fifo_rd_en、fifo_din、fifo_dout、almost_full、almost_empty、fifo_full、fifo_empty、fifo_wr_data_count和fifo_rd_data_count这十个信号添加至观察列表中,新建DebugCore核的方法这里不再赘述。
编译工程并生成比特流.sbit文件后,此时将下载器一端连接电脑,另一端与开发板上的JTAG下载口连接,连接电源线,并打开开发板的电源开关。
点击PDS工具栏的下载按钮,在弹出的Fabric Configuration界面中双击“Boundary Scan”,我们将生成好的sbit流文件下载到开发板中去。
IP核之FIFO实验16921.png
图 20.5.1 将探针信号添加到波形窗口中

同时我们在窗口将“fifo_rd_en”信号设置为上升沿触发。
单击左上角的触发按钮,如下图所示:
IP核之FIFO实验17039.png
图 20.5.2 触发按钮

在Fabric Debugger中观察的波形如下图所示:
IP核之FIFO实验17127.png
图 20.5.3 捕获得到的波形图

从捕获得到的波形图中可以看出,其逻辑行为与仿真波形图中的一致,证明我们的代码正确地实现了预期的功能。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-29 16:54

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表