ZYNQ-RAM

RAM是FPGA中常用的基础模块,可广泛应用于缓存数据。本实验主要介绍RAM的读写操作。

Xilinx在VIVADO已经提供RAM的IP核,通过IP核例化一个RAM,根据RAM的的读写时序来写入和读取RAM中存储的数据。通过在线逻辑分析仪Ila,观察RAM的读写时序和RAM中读取的数据。

1、创建Vivado工程

新建ram_tst工程,然后再工程添加RAM IP,具体步骤如下:

1)点击IP catalog ,在右侧弹出界面搜索 RAM,找到Block Mmemory Generator,双击打开

ZYNQ-RAM_第1张图片

2)将Component Name 改为 ram_ip ,在Basic 栏目下,将Memory Type 改为 Simple dual prot RAM 也就是伪双口 RAM. 一般情况, Simple dual prot RAM最常用,因为它是两个端口,输入和输出相互独立。

ZYNQ-RAM_第2张图片

3)切换到port A Option ,将RAM位宽 Port A Width 改为16,也就是数据宽度,将RAM深度Port A  Depth 改为512,深度指RAM里可以存放多少个数据。使能管脚,Enable port Type 改为Always Enable

ZYNQ-RAM_第3张图片 

4) 切换到port B Option ,将RAM位宽 Port B Width 改为16,。使能管脚,Enable port Type 改为Always Enable,也可以 Use ENB Pin ,相当于读使能信号,而Primitives Output Register 取消勾选,其功能在输出数据加上寄存器,可以有效改善时序,但是读出的数据会落后地址两个周期,很多情况都是,不使用这项功能,保持数据落后地址一个周期。

ZYNQ-RAM_第4张图片

5)在Other Options 栏目中,这里不像ROM那样需要初始化RAM 的数据,可以在程序中写入,配置默认即可,直接点击OK.

ZYNQ-RAM_第5张图片

6)点击“Generate” ,生成RAM IP

ZYNQ-RAM_第6张图片

2、RAM的端口说明和时序

Simple Dual Port RAM模块,端口说明:

ZYNQ-RAM_第7张图片

RAM的数据写入和读出都是按时钟的上升沿操作,端口A数据写入的时候需要置高wea信号,同时提供地址和要写入的数据。

ZYNQ-RAM_第8张图片

                                                    RAM写时序

 而端口B是不能写入数据,只能从RAM中读取数据,只需要提供地址就可以,一般情况可以在下一个周期采集到有效的数据。

ZYNQ-RAM_第9张图片

3)程序

module ram_test(
    input clk,
    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 读地址
reg [15:0] r_data;//RAM PORTB 读数据
//产生RAM PORTB 读地址
always @ (posedge or negedge rst_n)
begin
    if(!rst_n)
     r_addr <= 9'd0;
    else if (|w_addr)           //w_addr位或,不等于0
     r_addr <= r_addr + 1'b1;
    else
     r_addr <= 9'd0;
end
//产生RAM PORTA 写使能信号
always @ (posedge clk or negedge rst_n)
begin
    if(!rst_n)
        wea <= 1'b0;
    else 
    begin
        if(&w_addr)   //w_addr 的bit位全为1,共写入512个数据,写入完成
        wea <= 1'b0;
        else
        wea <= 1'b1;  //RAM写使能
    end
end
//产生RAM PORTA写入的地址及数据
always @ (posedge clk or negedge rst_n)
begin
    if(!rst_n)
    begin
        w_addr <= 9'd0;
        w_data <= 16'd1;
    end
    else
    begin
    if(wea)                //写使能
    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
     end
    end
end
//--------------------------------------------
//实例化·RAM
ram_ip ram_ip_inst(
      .clka   (clk     ),
      .wea    (wea     ),
      .addra  (w_addr  ),
      .dina   (w_data  ),
      .clk    (clk     ),
      .addrb  (r_addr  ),
      .doutb  (r_data  ),
);
//实例化ila逻辑分析仪
ila_0 ila_0 inst(
      .clk  (clk),
      .probe0 (r_data),
      .probe1 (r_addr),

);

4)引脚绑定

ZYNQ-RAM_第10张图片

5)仿真结果

 ZYNQ-RAM_第11张图片

6)板上验证

通过ila,观察RAM中读出的数据是否为我们初始化的数据。在Waveform的窗口设置r_addr地址为0作为触发条件,可以看到r_addr不断累加到1ff,随着r-addr的变化,r_data也在变,r_data的数据正是写入到RAM中的512个数据。r_addr出现新地址时,r_data对应的数据要延时两个时钟周期才会出现,数据比地址出现晚两个时钟出现,与仿真结果一致。

ZYNQ-RAM_第12张图片 

 

 

 

 

 

你可能感兴趣的:(fpga开发)