AX7020 学习笔记(二)持续更新中

常用ip核

3.双端RAM

双端RAM IP核介绍

1.单端口RAM(Single-Port RAM)

在这里插入图片描述

  • 允许一个端口对存储进行读写访问

  • 只要一组数据总线、地址总线、时钟信号以及读写使能信号。

2.伪双端口RAM(Simple Dual-Port RAM)

在这里插入图片描述

  • 提供A和B两个端口,端口A只能进行写访问,端口B只能进行读访问。

  • 有两组数据总线、地址总线、时钟信号以及读写使能信号。

3.真双端口RAM(True Dual-Port RAM)

在这里插入图片描述

  • 提供A和B两个端口,两个端口均可进行读写访问。

  • 有两组数据总线、地址总线、时钟信号以及读写使能信号。

实验目标

本章实验任务是将 Xilinx BMG IP 核配置成一个单端口的 RAM 并对其进行读写操作,然后通过仿真观察波形是否正确,最后将设计下载到 FPGA 开发板中,并通过在线调试工具对实验结果进行验证。

IP核配置

在这里插入图片描述

在这里插入图片描述

时序图讲解

同单端口

顶层模块设计

在这里插入图片描述

代码编写
.v文件

在这里插入图片描述

在这里插入图片描述

testbench

在这里插入图片描述

ILA(集成逻辑分析仪) IP核

在这里插入图片描述

上板验证

在这里插入图片描述

4.FIFO

FIFO IP核介绍

在这里插入图片描述

几个重要参数

1.FIFO的数据位宽

2.FIFO的数据容量

3.将空标志(空标志前一个时钟周期)与空标志

4.将满标志(满标志前一个时钟周期)与满标志

5.读写时钟

6.可配置满阈值、满信号、空阈值、空信号

实验任务

本节的实验任务是使用 Vivado 生成一个异步 FIFO,并实现以下功能:当 FIFO 为空时,向 FIFO 中写入数据,直至将 FIFO 写满后停止写操作;当 FIFO 为满时,从 FIFO 中读出数据,直到 FIFO 被读空后停止读操作,以此向大家详细介绍一下 FIFO IP 核的使用方法。

FIFO IP核配置

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

时序讲解

在这里插入图片描述

1.初始状态时empty被拉高表示FIFO为空,如果此时发起读操作,我们得到的是无效数据

2.we_en(写使能拉高后)开始向FIFO发出写操作,当FIFO中有了数据,empty就被拉低,当读写速率相同时,状态标志位不变

3.当只不读时,FIFO存在两个或两个以上的数据,almost_empty(将空)信号也会被拉低,写满后再发出请求将因为无法写入而丢失

在这里插入图片描述

由上图可总结出以下几点注意事项:

1、建议在安全电路下的异步 FIFO 的复位信号(RST)至少要保持八个时钟周期(以慢时钟为准)的有效。

2、在 RST 上升沿时期,经过 7 个 WR_CLK(写时钟)周期后 WR_RST_BUSY(写复位忙)信号拉高,FULL(满)信号拉高,此时的 WR_EN(写使能)信号应该拉低。

3、在 RST 上升沿时期,经过 7 个 RD_CLK(读时钟)周期后 RD_RST_BUSY(读复位忙)信号拉高,EMPTY(空)信号拉高,此时的 RD_EN(读使能)信号应该拉低,而且此时的数据输出端口均为无效。

4、图中建议我们至少在复位结束后,经过 60 个时钟周期(以慢时钟为准)后再对 FIFO 进行写操作,在实际应用中我们以读写复位的忙信号来判断是否对 FIFO 进行写操作也是可以的。

在这里插入图片描述

当 wr_en(写使能)信号使能时,会在 wr_clk(写时钟)的下一个上升沿上发生写操作,由于 FIFO 未满,因此 wr_ack(写应答)信号处于有效状态,表示写入操作成功。当只能再执行一次写操作时,almost_full(将满)信号会被拉高,此时若再进行一次写操作,full(满)信号就会被拉高,表示 FIFO 已被写满,在有数据被读出前,无法再写入数据了。如果在 full 信号拉高后执意要进行写操作,wr_ack 就会被拉低,表示此次数据写入失败,同时 overflow(满溢出)信号就会被拉高,表示 FIFO 存在溢出现象。

在这里插入图片描述

只要 FIFO 中存有数据,empty(空)信号就会一直为低电平,表明 FIFO 中有数据可以进行读取。当rd_en(读使能)信号使能时,会在 rd_clk(读时钟)的下一个上升沿上发生读操作,FIFO 会在 dout(数据输出线)上输出数据,并拉高 valid(读有效)信号,表示读操作成功。当 FIFO 中还剩最后一个数据时,almost_empty(将空)信号会被拉高,此时若再进行一次读操作,empty(空)信号就会被拉高,表示 FIFO已被读空,在 FIFO 中有存储数据前,读请求将被忽视。如果在 empty 信号拉高后执意要进行读操作,valid就会被拉低,表示此次数据读出失败,同时 underflow(空溢出)信号就会被拉高,表示 FIFO 中已经没有可被读取的数据了。

顶层模块设计

在这里插入图片描述

代码编写
module ip_fifo(
    input sys_clk    ,
    input sys_rst_n
);

//wire define
wire        clk_50m      ;
wire        clk_100m     ;
wire        locked       ;
wire        rst_n        ;
wire        wr_rst_busy  ;
wire        rd_rst_busy  ;
wire        fifo_wr_en   ;

wire        fifo_rd_en   ;
wire  [7:0] fifo_wr_data ;
wire  [7:0] fifo_rd_data ;
wire        almost_full  ;
wire        almost_empty ;
wire        full         ;
wire        empty        ;
wire  [7:0] wr_data_count;
wire  [7:0] rd_data_count;

//********************************
//**        main code
//********************************

//通过系统复位时钟来产生一个新的复位信号
assign  rst_n = sys_rst_n & locked;

//例化PLL IP核
clk_wiz_0   clk_wiz_0(
    //Clock out ports
    .clk_out1(clk_50m   ),
    .clk_out2(clk_100m  ),
    //State and control signals
    .locked  (locked    ),
    //Clock in ports
    .clk_in1 (sys_clk   )
);

//例化FIFO IP 核
fifo_generator_0 fifo_generator_0(
    .rst          (~rst_n       ),
    .wr_clk       (clk_50m      ),
    .rd_clk       (clk_100m     ),
    .wr_en        (fifo_wr_en   ),
    .rd_en        (fifo_rd_en   ),
    .din          (fifo_wr_data ),
    .dout         (fifo_rd_data ),
    .almost_full  (almost_full  ),
    .almost_empty (almost_empty ),
    .full         (full         ),
    .empty        (empty        ),
    .wr_data_count(wr_data_count),
    .rd_data_count(rd_data_count),
    .wr_rst_busy  (wr_rst_busy  ),
    .rd_rst_busy  (rd_rst_busy  )
);

//列化写FIFO
fifo_wr u_fifo_wr(
    .wr_clk         (clk_50m     ),
    .rst_n          (rst_n       ),
    .wr_rst_busy    (wr_rst_busy ),
    .fifo_wr_en     (fifo_wr_en  ),
    .fifo_wr_data   (fifo_wr_data),
    .empty          (empty       ),
    .almost_full    (almost_full )
);

//例化读FIFO
fifo_rd u_fifo_rd(
    .rd_clk         (clk_100m    ),
    .rst_n          (rst_n       ),
    .rd_rst_busy    (rd_rst_busy ),
    .fifo_rd_en     (fifo_rd_en  ),
    .fifo_rd_data   (fifo_rd_data),
    .almost_empty   (almost_empty),
    .full           (full        )
);

//写时钟域下ila
ila_0 u_ila_wr(
    .clk        (clk_50m        ),
    
    .probe0     (fifo_wr_en     ),
    .probe1     (fifo_wr_data   ),
    .probe2     (almost_full    ),
    .probe3     (full           ),
    .probe4     (wr_data_count  )
);
//读时钟域下ila
ila_1 u_ila_rd(
    .clk        (clk_100m       ),
    
    .probe0     (fifo_rd_en     ),
    .probe1     (fifo_rd_data   ),
    .probe2     (almost_empty   ),
    .probe3     (empty          ),
    .probe4     (rd_data_count  )
);
endmodule

在这里插入图片描述

module fifo_wr(
    //module clock
    input               wr_clk      ,
    input               rst_n       ,
    //FIFO  interface
    input               wr_rst_busy ,
    input               empty       ,
    input               almost_full ,
    output reg          fifo_wr_en  ,
    output reg [7:0]    fifo_wr_data
);

//reg define
reg     empty_d0;
reg     empty_d1;

//***********************************
//**            main code
//***********************************

//因为empty信号属于是FIFO读时钟域的
//所以对empty打两拍同步到写时钟域下
always @(posedge wr_clk or negedge rst_n)begin
    if (!rst_n)begin
        empty_d0 <= 1'b0;
        empty_d1 <= 1'b0;
    end
    else begin
        empty_d0 <= empty;
        empty_d1 <= empty_d0;
    end
end

//对fifo_wr_en赋值,当FIFO位空时开始写入,写满后停止写
always @(posedge wr_clk or negedge rst_n)begin
    if(!rst_n)
        fifo_wr_en <= 1'b0;
    else if (!wr_rst_busy)begin
        if (empty_d1)
            fifo_wr_en <= 1'b1;
        else if (almost_full)
            fifo_wr_en <= 1'b0;
    end
    else
        fifo_wr_en <= 1'b0;
end

//对fifo_wr_data赋值0~254
always @(posedge wr_clk or negedge rst_n)begin
    if (!rst_n)
        fifo_wr_data <= 8'b0;
    else if (fifo_wr_en && fifo_wr_data < 8'd254)
        fifo_wr_data <= fifo_wr_data + 8'b1;
    else
        fifo_wr_data <= 8'b0;
end

endmodule

在这里插入图片描述

module fifo_rd(
    //system clock
    input           rd_clk      ,
    input           rst_n       ,
    //FIFO  interface
    input           rd_rst_busy ,
    input     [7:0] fifo_rd_data,
    input           full        ,
    input           almost_empty,
    output reg      fifo_rd_en
);

//reg define
reg         full_d0;
reg         full_d1;

//********************************
//**        main code
//********************************

//因为full信号属于是FIFO写时钟域的
//所以对full打两派同步到读时钟域下
always @(posedge rd_clk or negedge rst_n)begin
    if (!rst_n)begin
        full_d0 <= 1'b0;
        full_d1 <= 1'b0;
    end
    else begin
        full_d0 <= full;
        full_d1 <= full_d0;
    end
end

//对fifo_rd_en进行赋值,FIFO写满之后开始读,读空之后停止
always @(posedge rd_clk or negedge rst_n)begin
    if (!rst_n)
        fifo_rd_en <= 1'b0;
    else if (!rd_rst_busy)begin
        if (full_d1)
            fifo_rd_en <= 1'b1;
        else if (almost_empty)
             fifo_rd_en <= 1'b0;
        end
        else
            fifo_rd_en <= 1'b0;
end

endmodule

`timescale 1ns/1ps

module tb_ip_fifo();

//parameter define
parameter CLK_PERIOD = 20;

//reg define
reg     sys_clk;
reg     sys_rst_n;

//信号初始化
initial begin
    sys_clk = 1'b0;
    sys_rst_n = 1'b0;
    #200    ;
    sys_rst_n = 1'b1;
    //模拟按下复位键
    #10000  ;
    sys_rst_n = 0;
    #160    ;
    sys_rst_n = 1;
end

//产生时钟
always #(CLK_PERIOD/2) sys_clk = ~sys_clk;

ip_fifo u_ip_fifo(
    .sys_clk    (sys_clk    ),
    .sys_rst_n  (sys_rst_n  )
);
endmodule
仿真验证

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

最后添加ila下板调试即可
在这里插入图片描述

  • 18
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值