查看: 959|回复: 0

【ZYNQ Ultrascale+ MPSOC FPGA教程】第六章 FPGA片内RAM读写测试实验

[复制链接]
  • TA的每日心情
    开心
    2021-1-12 14:00
  • 签到天数: 1 天

    连续签到: 1 天

    [LV.1]初来乍到

    发表于 2021-1-12 13:48:34 | 显示全部楼层 |阅读模式
    分享到:
    原创声明:
    本原创教程由芯驿电子科技(上海)有限公司(ALINX)创作,版权归本公司所有,如需转载,需授权并注明出处。
    适用于板卡型号:
    AXU2CGA/AXU2CGB/AXU3EG/AXU4EV-E/AXU4EV-P/AXU5EV-E/AXU5EV-P /AXU9EG/AXU15EG
    实验Vivado工程为“ram_test”。
    RAM是FPGA中常用的基础模块,可广泛用于缓存数据的情况,同样它也是ROM,FIFO的基础。本实验将为大家介绍如何使用FPGA内部的RAM以及程序对该RAM的数据读写操作。
    1.实验原理
    Xilinx在VIVADO里为我们已经提供了RAM的IP核, 我们只需通过IP核例化一个RAM,根据RAM的读写时序来写入和读取RAM中存储的数据。实验中会通过VIVADO集成的在线逻辑分析仪ila,我们可以观察RAM的读写时序和从RAM中读取的数据。
    2.创建Vivado工程
    在添加RAM IP之前先新建一个ram_test的工程, 然后在工程中添加RAM IP,方法如下:
    2.1 点击下图中IP Catalog,在右侧弹出的界面中搜索ram,找到Block Memory Generator,双击打开。
    2.2 将Component Name改为ram_ip,在Basic栏目下,将Memory Type改为Simple Dual Prot RAM,也就是伪双口RAM。一般来讲"Simple Dual Port RAM"是最常用的,因为它是两个端口,输入和输出信号独立。
    2.3 切换到Port A Options栏目下,将RAM位宽Port A Width改为16,也就是数据宽度。将RAM深度Port A Depth改为512,深度指的是RAM里可以存放多少个数据。使能管脚Enable Port Type改为Always Enable。
    2.4 切换到Port B Options栏目下,将RAM位宽Port B Width改为16,使能管脚Enable Port Type改为Always Enable,当然也可以Use ENB Pin,相当于读使能信号。而Primitives Output Register取消勾选,其功能是在输出数据加上寄存器,可以有效改善时序,但读出的数据会落后地址两个周期。很多情况下,不使能这项功能,保持数据落后地址一个周期。
    2.5 在Other Options栏目中,这里不像ROM那样需要初始化RAM的数据,我们可以在程序中写入,所以配置默认即可,直接点击OK。
    2.6 点击“Generate”生成RAM IP。
    3. RAM的端口定义和时序
    Simple Dual Port RAM 模块端口的说明如下:
    信号名称方向说明
    clkain端口A时钟输入
    weain端口A使能
    addrain端口A地址输入
    dinain端口A数据输入
    clkbin端口B时钟输入
    addrbin端口B地址输入
    doutbout端口B数据输输出
    RAM的数据写入和读出都是按时钟的上升沿操作的,端口A数据写入的时候需要置高wea信号,同时提供地址和要写入的数据。下图为输入写入到RAM的时序图。
    RAM写时序
    而端口B是不能写入数据的,只能从RAM中读出数据,只要提供地址就可以了,一般情况下可以在下一个周期采集到有效的数据。
    RAM读时序
    4. 测试程序编写
    下面进行RAM的测试程序的编写,由于测试RAM的功能,我们向RAM的端口A写入一串连续的数据,只写一次,并从端口B中读出,使用逻辑分析仪查看数据。代码如下
    `timescale1ns/1ps//////////////////////////////////////////////////////////////////////////////////module ram_test(                        input clk,                        //25MHz时钟                        input rst_n                //复位信号,低电平有效                        );//-----------------------------------------------------------reg                [8:0]                w_addr;                        //RAM PORTA写地址reg                [15:0]                w_data;                        //RAM PORTA写数据reg                        wea;                //RAM PORTA使能reg                [8:0]                r_addr;                        //RAM PORTB读地址wire        [15:0]                r_data;                        //RAM PORTB读数据//产生RAM PORTB读地址always@(posedge clk ornegedge rst_n)beginif(!rst_n)        r_addr <=9'd0;elseif(|w_addr)                        //w_addr位或,不等于0    r_addr <= r_addr+1'b1;else        r_addr <=9'd0;        end//产生RAM PORTA写使能信号always@(posedge clk ornegedge rst_n)begin        if(!rst_n)          wea <=#11'b0;elsebeginif(&w_addr)//w_addr的bit位全为1,共写入512个数据,写入完成        wea <=#11'b0;else        wea        <=#11'b1;//ram写使能endend//产生RAM PORTA写入的地址及数据always@(posedge clk ornegedge rst_n)begin        if(!rst_n)begin          w_addr <=9'd0;          w_data <=16'd1;endelsebeginif(wea)        //ram写使能有效        begin                if(&w_addr)//w_addr的bit位全为1,共写入512个数据,写入完成                begin                        w_addr <= w_addr ;//将地址和数据的值保持住,只写一次RAM                        w_data <= w_data ;                end                else                begin                        w_addr <= w_addr +1'b1;                        w_data <= w_data +1'b1;                end        endendend//-----------------------------------------------------------//实例化RAM        ram_ip ram_ip_inst (.clka      (clk          ),// input clka.wea       (wea          ),// input [0 : 0] wea.addra     (w_addr       ),// input [8 : 0] addra.dina      (w_data       ),// input [15 : 0] dina.clkb      (clk          ),// input clkb.addrb     (r_addr       ),// input [8 : 0] addrb.doutb     (r_data       )// output [15 : 0] doutb);//实例化ila逻辑分析仪ila_0 ila_0_inst (        .clk        (clk        ),        .probe0        (r_data        ),        .probe1        (r_addr        ));        endmodule
    为了能实时看到RAM中读取的数据值,我们这里添加了ila工具来观察RAM PORTB的数据信号和地址信号。关于如何生成ila大家请参考”PL的”Hello World”LED实验”。
    程序结构如下:
    绑定引脚
    ##################Compress Bitstream############################
    set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design]set_property PACKAGE_PIN AB11 [get_ports clk]set_property IOSTANDARD LVCMOS33 [get_ports clk]create_clock -period 40.000 -name clk -waveform {0.000 20.000} [get_ports clk]set_property PACKAGE_PIN AA13 [get_ports rst_n]set_property IOSTANDARD LVCMOS33 [get_ports rst_n]
    5. 仿真
    仿真方法参考”PL的”Hello World”LED实验”,仿真结果如下,从图中可以看出地址1写入的数据是0002,在下个周期,也就是时刻2,有效数据读出。
    6. 板上验证
    生成bitstream,并下载bit文件到FPGA。接下来我们通过ila来观察一下从RAM中读出的数据是否为我们初始化的数据。
    在Waveform的窗口设置r_addr地址为0作为触发条件,我们可以看到r_addr在不断的从0累加到1ff, 随着r_addr的变化, r_data也在变化, r_data的数据正是我们写入到RAM中的512个数据,这里需要注意,r_addr出现新地址时,r_data对应的数据要延时两个时钟周期才会出现,数据比地址出现晚两个时钟周期,与仿真结果一致。

    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /2 下一条



    手机版|小黑屋|与非网

    GMT+8, 2024-4-19 13:22 , Processed in 0.107260 second(s), 15 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2020, Tencent Cloud.