Xilinx FPGA平台DDR3设计保姆式教程(4)DDR3读写测试

实验任务:

将输入数据(data_in)存入ddr,然后读出,验证输入输出数据是否相等。


汇总篇:

Xilinx FPGA平台DDR3设计保姆式教程(汇总篇)——看这一篇就够了


目录

一、前言

二、系统方案

2.1方案设计

2.1.1输入接口时序图

2.2状态机设计

2.2.1独热码

2.2.2状态机流程图

 2.2.3三段式状态机

2.3app接口设计

三、仿真结果



一、前言

接上一篇(3)MIG的使用教程

MIG配置如下:

  1. 系统时钟sys_clk = 200Mhz
  2. 系统复位sys_rst 低有效
  3. 模式:4:1
  4. 位宽: 16bit

注:由于选择的DDR3的突然长度为8,所以mig的数据位宽=16*8=128bit,对应到代码即app_wdf_data[127:0]  ,  app_rd_data[127:0]。

二、系统方案

2.1方案设计

实验任务:

将数据(data_in),存入ddr,然后读出,验证输入输出数据是否相等。

实验目的:

初步掌握DDR读写设计。

Xilinx FPGA平台DDR3设计保姆式教程(4)DDR3读写测试_第1张图片

为什么要先过FIFO再写入DDR?

因为DDR接口对用户而言并不是一直有效,只有等DDR“有效”时(app_rdy = 1 && app_wdf_rdy = 1),才能进行写入。

2.1.1输入接口时序图

Xilinx FPGA平台DDR3设计保姆式教程(4)DDR3读写测试_第2张图片

输入数据为1-50共50个数据,以vld_in信号表征输入数据有效。

2.2状态机设计

2.2.1独热码

localparam		S0_IDLE		=	6'b000001;	//初始化状态,DDR初始化成功就跳转S1
localparam		S1_WAIT		=	6'b000010;	//等待状态,等FIFO缓存好数据就跳转S2
localparam		S2_WRITE	=	6'b000100;	//写DDR状态,FIFO数据写完就跳转到S3
localparam		S3_WR_DONE	=	6'b001000;	//写完成状态,给出读地址初始值就跳到S4
localparam		S4_READ		=	6'b010000;	//读DDR状态,读到相应长度的数量就跳到S5
localparam		S5_RD_DONE	=	6'b100000;	//读完成状态,跳回IDLE

2.2.2状态机流程图

 Xilinx FPGA平台DDR3设计保姆式教程(4)DDR3读写测试_第3张图片

 2.2.3三段式状态机

always @(posedge	sys_clk	or	posedge	sys_rst)begin
	if(sys_rst == 1'b1)
		current_state	<=	S0_IDLE;
	else
		current_state	<=	next_state;
end
always @(*)begin
	case(current_state)
		S0_IDLE	   	:	
			if(init_calib_complete == 1'b1)
				next_state		<=		S1_WAIT;
			else
				next_state		<=		S0_IDLE;
        S1_WAIT	   	:
			if(eof == 1'b1)
				next_state		<=		S2_WRITE;
			else
				next_state		<=		S1_WAIT;
        S2_WRITE   	:
			if(ififo_empty == 1'b1)
				next_state		<=		S3_WR_DONE;
			else
				next_state		<=		S2_WRITE;
        S3_WR_DONE	:
				next_state		<=		S4_READ;
		S4_READ		:
			if(cnt_read == cnt_length)
				next_state		<=		S5_RD_DONE;
			else
				next_state		<=		S4_READ;
        S5_RD_DONE	:
				next_state		<=		S0_IDLE;
		default		:
				next_state		<=		S0_IDLE;
		endcase
end
always @(posedge	sys_clk	or	posedge	sys_rst)begin
	if(sys_rst == 1'b1)begin
		cnt_length				<=		32'b0;
		cnt_read				<=		32'b0;
		cnt_write				<=		32'b0;
		app_addr				<=		29'b0;
		end
	else case(current_state)
		S0_IDLE	:	;	
		S1_WAIT	:	;
		S2_WRITE:
			if(app_rdy && app_wdf_rdy && app_en)begin
				app_addr		<=		app_addr	+ 	'd8; //BL =8;
				cnt_write		<=		cnt_write	+	'd1;
				end
			else begin
				app_addr		<=		app_addr; 
				cnt_write		<=		cnt_write;
				end
		S3_WR_DONE	:begin
				cnt_length		<=		cnt_write;
				app_addr		<=		29'b0;	//读初始地址
				end
		S4_READ	:
			if(app_rdy && app_en)begin
				app_addr		<=		app_addr	+	'd8;
				cnt_read		<=		cnt_read	+	'd1;
				end
			else begin
				app_addr		<=		app_addr;
				cnt_read		<=		cnt_read;
				end
		S5_RD_DONE	:begin
				cnt_length		<=		32'b0;
				cnt_read		<=		32'b0;
				cnt_write		<=		32'b0;
				end
		default	:	;
		endcase
end

代码很简单,对应流程图跳转,此处不再啰嗦 。

2.3app接口设计

assign	app_wdf_mask 	=	16'b0;	//掩码置0,表示传输的全部为有效数据
assign	ififo_rden		=	(current_state == S2_WRITE)&& app_rdy && app_wdf_rdy;
assign	app_en			=	((current_state == S2_WRITE)&&(ififo_vld)) || (current_state == S4_READ);
assign	app_cmd			=	(current_state == S4_READ) ? 3'b001 : 3'b000;
assign	app_wdf_wren	=	ififo_vld;
assign	app_wdf_end		=	ififo_vld;
assign	app_wdf_data	=	ififo_rdata;

三、仿真结果

因为DDR仿真,需要用到ddr3_model和其他文件,单开一篇来讲解。

这里只看仿真结果。

输入:

Xilinx FPGA平台DDR3设计保姆式教程(4)DDR3读写测试_第4张图片

 输出:

Xilinx FPGA平台DDR3设计保姆式教程(4)DDR3读写测试_第5张图片

 

输入数据: 1-50;

输出数据: 1-50;

DDR读写测试成功!

Xilinx FPGA平台DDR3设计保姆式教程(4)DDR3读写测试_第6张图片

你可能感兴趣的:(FPGA接口篇,fpga,ddr)