基于FPGA+MIG+AXI4实现DDR3 SDRAM读写操作(附代码)

本文详细介绍了如何基于FPGA、MIG核和AXI4总线协议实现DDR3 SDRAM的读写操作。内容包括图像数据源的生成、图像数据写入和读出DDR3的步骤,以及相关模块的设计,如AXI Master和frame_write。文章强调了MIG核的配置,包括DDR3 SDRAM的参数设置和AXI接口的配置,最后提到了图像数据的读取和显示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

温馨提示:在阅读本文之前需具备DDR3 SDRAM(详见https://blog.csdn.net/xingchenfeiying/article/details/123439177?utm_source=app&app_version=5.1.1&utm_source=app)和AXI4总线协议(详见https://blog.csdn.net/xingchenfeiying/article/details/123460900?utm_source=app&app_version=5.1.1&utm_source=app)相关知识,结合Modelsim仿真工程更利于了解内在联系(详见基于FPGA+MIG+AXI4实现DDR3 SDRAM读写操作仿真(附代码+各模块仿真时序图)_春风细雨无声的博客-CSDN博客)。

EDA工具:Vivado 2018.3

FPGA型号:Kintex-7

DDR3 SDRAM型号:MT41K256M16HA-107        

        首先,先看看设计的逻辑顶层:整个工程可以分为获取图像数据源、图像数据写入DDR3、图像数据读出DDR3和图像显示。接下来将针对每一部分手把手进行“文字+图片+代码”方式详细说明。

一、图像数据源

        为方便测试分析验证,工程中使用的图像源为640×512×16bit的模拟假图像,由逻辑代码按照时序要求产生场同步信号、行有效信号和图像数据。

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;


-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;



entity img_data_gen is
	generic(
			IMG_WIDTH 	: integer := 640;
			IMG_HIGH	: integer := 512
	
	);
    port ( 
			clk 		: in 		std_logic;
			rst 		: in 		std_logic;
			
			fval 		: buffer 	std_logic;
			lval 		: inout 	std_logic;
			dval 		: out 		std_logic;
			pixel_clk 	: out 		std_logic;
			pixel_data 	: inout 	std_logic_vector(13 downto 0)
	);
end img_data_gen;

architecture Behavioral of img_data_gen is

	signal fval_cnt			: std_logic_vector(7  downto 0) := (others => '0');
	signal v_cnt			: std_logic_vector(9  downto 0) := (others => '0');
	signal h_cnt			: std_logic_vector(9  downto 0) := (others => '0');
	signal frame_cnt		: std_logic_vector(18 downto 0) := (others => '0');
	signal lval_start_flag 	: std_logic := '0';
	signal lval_dly1 		: std_logic := '0';
	signal lval_dly2 		: std_logic := '0';
	signal lval_rise 		: std_logic := '0';
	signal lval_down 		: std_logic := '0';
	signal fval_dly1 		: std_logic := '0';
	signal fval_rise 		: std_logic := '0';
	signal img_shift 		: std_logic := '0';


begin


	process(clk,rst)
	begin
		if rst = '1' then
			lval_start_flag <= '0';
		elsif rising_edge (clk) then
			if frame_cnt >= 3 and frame_cnt <= 332794 then
				lval_start_flag <= '1';
			else
				lval_start_flag <= '0';
			end if;
		end if;
	end process;

	process(clk,rst)
	begin
		if rst = '1' or fval = '0' then
			v_cnt <= (others => '0');
		elsif rising_edge (clk) then
			if lval_start_flag = '1' and v_cnt <= 648 then
				v_cnt <= v_cnt + 1;
			elsif v_cnt = 649  then					
				v_cnt <= (others => '0');			
			end if;
		end if;
	end process;
	
	process(clk,rst)
	begin
		if rst = '1' then
			lval <= '0';
		elsif rising_edge (clk) then
			if v_cnt >= 1 and v_cnt <= IMG_WIDTH  then						
				lval <= '1';
			else
				lval <= '0';												
			end if;
		end if;
	end process;
	

	process(clk,rst)
	begin
		if rst = '1' then
			lval_dly1 	<= '0';
			lval_dly2 	<= '0';
		elsif rising_edge (clk) then
			lval_dly1	<= lval;
		    lval_dly2   <= lval_dly1;	
		end if;
	end process;
	
	lval_rise <= lval_dly1 and (not lval_dly2);
	lval_down <= (not lval_dly1) and lval_dly2;

	process(clk,rst)
	begin
		if rst = '1' or fval = '0' then
			h_cnt <= (others => '0');
		elsif rising_edge (clk) then
			if lval_rise = '1' then
				h_cnt <= h_cnt + 1;
				if h_cnt = 512 then
					h_cnt <= (others => '0');
				end if;
			else
				h_cnt <= h_cnt;
			end if;
		end if;
	end process;
	

	
	process(clk,rst)										--产生一张静态图像
	begin
		if rst = '1' then
			pixel_data <= (others => '0');		
		elsif rising_edge (clk) then
			if lval = '1' then
				pixel_data <= pixel_data + 1;			
			else
				pixel_data <= (others => '0');			
			end if;
		end if;
	end process;


--------------------------------------------生成场同步信号--------------------------------	
	process(clk,rst)
	begin
		if rst = '1' then
			frame_cnt <= (others => '0');
		elsif rising_edge (clk) then
			frame_cnt <= frame_cnt + 1;
			if frame_cnt = 400000 then			
				frame_cnt <= (others => '0');
			end if;
		end if;
	end process;
			  
	process(clk,rst)
	begin
		if rst = '1' then
			fval <= '0';
		elsif rising_edge (clk) then
			if frame_cnt >= 0 and frame_cnt <= 332794 then		
				fval <= '1';
			else
				fval <= '0';
			end if;
		end if;
	end process;
	
---------------------------------------场同步信号计数--------------------------------
	

	process(clk,rst)
	begin
		if rst = '1' then
			fval_dly1 <= '0';
		elsif rising_edge (clk) then
			fval_dly1 <= fval;
		end if;
	end process;
	
	fval_rise <= fval and (not fval_dly1);	
	
	process(clk,rst)
	begin
		if rst = '1' then
			fval_cnt <= (others => '0');
		elsif rising_edge (clk) then
			if fval_rise = '1' then
				fval_cnt <= fval_cnt + 1;
			elsif fval_cnt = 200 then
				fval_cnt <= (others => '0');
			else
				fval_cnt <= fval_cnt;
			end if;
		end if;
	end process;
	
	process(clk,rst)
	begin
		if rst = '1' then
			
		elsif rising_edge (clk) then
			if fval_cnt>= 0 and  fval_cnt< 100 then
				img_shift <= '0';
			elsif fval_cnt >= 100 and fval_cnt <= 200 then
				img_shift <= '1';
			end if;
		end if;
	end process;
	
----------------------------------------生成像素时钟------------------------------
	pixel_clk <= clk;
	
	dval <= lval;

end Behavioral;

二、图像数据写入DDR3

        有了图像数据源之后,就需要将图像数据存放进DDR3 SDRAM中。那么,怎么存?DDR3 SDRAM是独立于FPGA的一种外部存储器,存放数据肯定需要有接口与FPGA进行数据交互。问题在于:接口是什么?有哪些信号?FPGA逻辑怎么来控制?

        其实,直接通过逻辑代码来控制DDR3 SDRAM读写是相当有难度的,但好在Xilinx官方提供了IP核(即MIG)方便设计人员使用,大大降低了开发难度。接下来,深入探讨一下MIG核具体调用和配置。

2.1 MIG核配置

        在建立好工程后,按如下步骤进行 DDR 控制器 IP 的创建和配置。
        1、搜索查找 DDR 控制器 IP。
        Xilinx 的 DDR 控制器的名称简写为 MIG(Memory Interface Generator), 在 Vivado 左侧
窗口点击 IP Catalog,然后在 IP Catalog 窗口直接搜索关键字“mig” ,就可以很容易的找到Memory Interface Generator(MIG 7 Series)。如下图所示。

        直接双击鼠标左键或通过鼠标右键选项中选择 Customize IP 并点击。 如下图所示,可进入到 IP 配置界面。

        2、 MIG IP 的配置。
        进入IP配置界面后,第一个界面是 Memory Interface Generator 介绍页面, 如下图所示。
默认的器件家族(FPGA Family)、器件 型号(FPGA Part)、速度等级(Speed Grade)、综合
工具(Synthesis Tool)和设计输入语言(Design Entry)都和创建工程是保持一致。

        点击 Next 到 MIG Output Options 配置页面中, 如下图所示。 勾选“Create Design”,默
认名称(Component Name)为“mig_7series_0”,用户可对其进行修改,这里改为“m

在进行Artix FPGADDR3 SDRAM高效读写操作设计时,MIG(Memory Interface Generator)生成的AXI4接口控制器扮演着关键角色。为了获得深入理解并掌握这一技术,推荐查阅《Artix FPGA DDR控制器MIG实战:AXI4 MSXBO_FDMA教程》。 参考资源链接:[Artix FPGA DDR控制器MIG实战:AXI4 MSXBO_FDMA教程](https://wenku.csdn.net/doc/3v7b3fz3q8?spm=1055.2569.3001.10343) 此教程将指导你完成基于AXI4接口的MSXBO_FDMA控制器的集成和配置,确保你能够充分理解如何操作DDR3 SDRAM。首先,你需要熟悉MIG工具在Vivado中的使用,它能够自动为DDR3 SDRAM生成时序准确的接口逻辑。 通过MIG生成的AXI4 IP核,你需要进行适当的参数配置以匹配你的DDR3 SDRAM的规格。设置好后,利用VIVADO设计套件中的Xilinx AXI4协议标准来编写控制逻辑。这里,MSXBO_FDMA控制器作为中间件,简化了数据输的过程,无需编写额外的驱动程序。 在实际项目中,你需要根据MSXBO_FDMA控制器的要求,编写相应的读写操作代码,并通过AXI4接口将控制信号发送到MIG生成的控制器。确保正确配置读写事务,并在硬件上进行验证,以检查读写操作的时序和性能。 此外,推荐你充分利用教程中提供的视频缓存方案示例,深入理解如何优化读写操作以提高数据吞吐率。这些方案能够帮助你在不同的应用中调整和优化DDR3 SDRAM的性能。 掌握这些技能后,你将能够更高效地利用FPGA进行DDR3 SDRAM的读写控制,而《Artix FPGA DDR控制器MIG实战:AXI4 MSXBO_FDMA教程》将是你不可或缺的参考资料。这份指南不仅涵盖基本概念,还深入到具体项目实施的每一个细节,使你在实战中游刃有余。 参考资源链接:[Artix FPGA DDR控制器MIG实战:AXI4 MSXBO_FDMA教程](https://wenku.csdn.net/doc/3v7b3fz3q8?spm=1055.2569.3001.10343)
评论 37
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值