ZYNQ之FPGA 片内RAM读写测试实验

文章目录

  • 前言
  • 一、添加RAM IP核
  • 二、编写测试程序
  • 三、添加ILA
  • 四、分配管脚
  • 五、Simulator仿真
  • 六、硬件调试
  • 总结


前言

本实验的主要内容是介绍如何使用 FPGA内部的RAM以及程序对该RAM数据的读写操作。Vivado软件中提供了RAM的IP核 , 我们只需通过IP核例化一个RAM,根据RAM的读写时序来写入和读取RAM中存储的数据。


一、添加RAM IP核

首先创建一个名为ram_test的工程,具体的步骤可以参见:Vivado软件的使用——以led的交替闪烁为例。
新工程到下图所示的界面后点击Finish即可完成工程的创建。
ZYNQ之FPGA 片内RAM读写测试实验_第1张图片
工程创建完成后依次按照下图中的序号找到Block Memory Generator双击打开。
ZYNQ之FPGA 片内RAM读写测试实验_第2张图片
弹出如下对话框,在该界面中修改部分参数。
ZYNQ之FPGA 片内RAM读写测试实验_第3张图片
需要修改Component Name和Memory Type这两个部分,修改后如下图所示。
ZYNQ之FPGA 片内RAM读写测试实验_第4张图片
其中 Memory Type 选择的Simple Dual Prot RAM是伪双口RAM,它是最常用的,因为它有两个端口,输入和输出信号是独立的。
Simple Dual Prot RAM模块端口说明如下表。
ZYNQ之FPGA 片内RAM读写测试实验_第5张图片
RAM 的数据写入和读出都是按时钟的上升沿操作的,端口 A 数据写入的时候需要置高wea信号,同时提供地址和要写入的数据。而端口B是不能写入数据的,只能从 RAM 中读出数据,只要提供地址就可以了,一般情况下在下一个周期就可采集到有效的数据。
切换到Port A Options下依次修改数据宽度、深度以及使能管脚,修改后如下图所示。
ZYNQ之FPGA 片内RAM读写测试实验_第6张图片
接着切换到 Port B Options下,将使能管脚 Enable PortType 改为 Always Enable ,也可不修改保持默认Use ENB Pin ,相当于读使能信号,再把 Primitives Output Register取消勾选,其功能是在输出数据上加寄存器,这可以有效改善时序 ,但读出的数据会落后地址两个周期,因此在很多情况下,不用这项功能,保持读出的数据落后地址一个周期即可。
ZYNQ之FPGA 片内RAM读写测试实验_第7张图片
到这里,需要修改的部分已经完成了,其他各选项下的参数保持默认即可,点击OK按钮,弹出如下对话框。
ZYNQ之FPGA 片内RAM读写测试实验_第8张图片
点击Generate就可以生成RAM IP。


二、编写测试程序

编写测试程序来测试RAM的功能,我们向RAM的端口A写入一串连续的数据,且只写一次,并从端口B中读出,使用逻辑分析仪查看数据。
新建名为ram_test的Verilog文件,依次按照下图中标注的序号进行即可。
ZYNQ之FPGA 片内RAM读写测试实验_第9张图片
在新建好的ram_test.v中写入如下代码。

//该代码由正点原子提供
`timescale 1ns / 1ps

module ram_test(
			input clk,		          	//50MHz时钟
			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 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) 					//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
	 end
  end 
end 

//实例化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部分的代码来自ram_ip中的ram_ip.veo文件,不过需要将括号内的参数做一修改。
ZYNQ之FPGA 片内RAM读写测试实验_第10张图片


三、添加ILA

我们还需要添加ILA,其添加过程可参见:使用Vivado软件进行硬件调试。
探针的数量这里设置为2,即数据和地址两个探针。
ZYNQ之FPGA 片内RAM读写测试实验_第11张图片
这里每个探针的位数按照代码中的分配,r_data是16位,r_addr是9位。
ZYNQ之FPGA 片内RAM读写测试实验_第12张图片
对应的代码如下。

reg		[8:0]  		r_addr;	  	 	//RAM PORTB读地址
wire	[15:0] 		r_data;			//RAM PORTB读数据

点击OK后在弹出的对话框中生成IP,耐心等待其完成!
ZYNQ之FPGA 片内RAM读写测试实验_第13张图片
实例化ila逻辑分析仪部分的代码来自ila_0中的ila_0.veo文件,不过需要将括号内的参数做一修改。
ZYNQ之FPGA 片内RAM读写测试实验_第14张图片


四、分配管脚

本实验中需要分配管脚的只有时钟信号clk(管脚为U18)和复位信号rst_n(管脚为N15),按照下图中的数字顺序即可完成管脚的分配。
ZYNQ之FPGA 片内RAM读写测试实验_第15张图片
管脚分配完成后Ctrl+S保存,名称与工程名保持一致。
ZYNQ之FPGA 片内RAM读写测试实验_第16张图片
管脚分配的信息在下图圈中的文件中。
ZYNQ之FPGA 片内RAM读写测试实验_第17张图片


五、Simulator仿真

Simulator仿真创建文件的过程可参见:Vivado中Simulator仿真软件的使用。
按照下图中的顺序新建TB文件。
ZYNQ之FPGA 片内RAM读写测试实验_第18张图片
在tb_ram_test.v文件中写入如下代码。

//该代码由正点原子提供
`timescale 1ns / 1ps

module vtf_ram_tb;
// Inputs
reg clk;
reg rst_n;

// Instantiate the Unit Under Test (UUT)
ram_test uut (
	.clk	(clk), 		
	.rst_n	(rst_n)
);

initial 
begin
	// Initialize Inputs
	clk = 0;
	rst_n = 0;

	// Wait 100 ns for global reset to finish
	#100;
      rst_n = 1;       
 end
 
always #10 clk = ~ clk;   //20ns一个周期,产生50MHz时钟源
   
endmodule

保存代码后选择SIMULATION下的Run Simulation,选择第一个行为仿真。
将所有代码中定义的信号拖入到波形仿真窗口,设置仿真时间为1000ns,运行后结果如下图所示。
ZYNQ之FPGA 片内RAM读写测试实验_第19张图片
由仿真结果可知,RAM 的数据写入和读出都是按时钟的上升沿操作的,数据写入的时候需要置高wea信号,在下一个周期就可采集到有效的数据。


六、硬件调试

连接开发板,点击Generate Bitstream生成比特流文件,将其下载到开发板上。
ZYNQ之FPGA 片内RAM读写测试实验_第20张图片
下载后弹出如下窗口,设置r_addr的初始数值为000,然后点击运行按钮,得到如下波形,将游标移动到红线附近并放大得到下图。
ZYNQ之FPGA 片内RAM读写测试实验_第21张图片
由上图可以看到 r_addr 不断地从0 累加到 1f f,随着 r_addr 的变化,r_data 也在变化,而r_data的数据正是我们写入到RAM中的 512个数据。
这里需要注意 r_addr出现新地址时, r_data对应的数据要延时两个时钟周期才会出现,数据比地址晚两个时钟周期出现,这与仿真的结果是一致的。


总结

以上就是ZYNQ之FPGA 片内RAM读写测试实验的所有内容了,本实验较为综合,包括了前面介绍过的建工程、编写Verilog代码、例化IP核、仿真和硬件调试等内容,注意这些部分在该流程中的顺序和作用。
本文参考资料:正点原子–course_s1_ZYNQ那些事儿-FPGA实验篇V1.06.pdf

你可能感兴趣的:(zynq,zynq)