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

温馨提示:在阅读本文之前需具备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和图像显示。接下来将针对每一部分手把手进行“文字+图片+代码”方式详细说明。

基于FPGA+MIG+AXI4实现DDR3 SDRAM读写操作(附代码)_第1张图片

一、图像数据源

        为方便测试分析验证,工程中使用的图像源为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)。如下图所示。

基于FPGA+MIG+AXI4实现DDR3 SDRAM读写操作(附代码)_第2张图片

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

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

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