Xilinx MicroBlaze软核驱动DDR4

Xilinx MicroBlaze软核驱动DDR4

说明:通过Vivado生成MicroBlaze工程导入SDK实现DDR4的读写。
环境:Vivado2018.3。
IP核:MicroBlaze。
参考手册:
pg150:UltraScale Architecture-Based FPGAs Memory IP v1.4
基础知识:Xilinx MicroBlaze软核驱动DDR3(最好先看一下)

工程下载


1.MicroBlaze设计流程

新建Vivado工程…
在这里插入图片描述
在这里插入图片描述

1.2 DDR Block Design 流程

Creat Block Design:
在这里插入图片描述
添加Microblaze核:
在这里插入图片描述
Run Block Automation:
在这里插入图片描述
在这里插入图片描述
添加Uartlite核:
在这里插入图片描述
双击更改波特率为115200
在这里插入图片描述
添加DDR4 IP:
在这里插入图片描述
双击配置DDR4 IP
在这里插入图片描述
根据自己DDR选择型号
在这里插入图片描述

即MIG对DDR接口的速率为1200M*2=2400M(双沿)。
MIG输出到app接口上的时钟ui_clk为1200M/4=300M。
UI时钟频率ui_clk为DDR时钟频率的1/4,也就是一个用户时钟周期(两个边沿)对应8个DDR时钟边沿。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
Run Connection Automation:
在这里插入图片描述
在这里插入图片描述
对生成的网络进行一下修改:
1、时钟
双击
在这里插入图片描述
根据自己输入系统时钟,选择时钟频率和差分还是单端模式:
在这里插入图片描述
在这里插入图片描述
去除reset和locked选项:
在这里插入图片描述

删除多余的端口重新Run Connection Automation
2、复位
将DDR复位信号和rst_clk_wizIP的复位删除,引入常量IP将其连接
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

进行设计检查:
在这里插入图片描述
Great HDL Wrapper:
在这里插入图片描述
在这里插入图片描述
约束:
对管脚以及DDR端口进行约束
在这里插入图片描述注意:DDR4的diff_clock_rtl_1这个时钟输入为100MHz的差分时钟输入,根据自己的板子
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
生成bit流文件
导入SDK,记得包含bit文件:
在这里插入图片描述

2.SDK工程

新建一个hello word 工程
在这里插入图片描述

在.hdf文件中查看DDR3的地址范围位为0x8000_0000-0x9FFF_FFFF
寻址空间为1FFF_FFFF即536870912Byte=512MB。
在这里插入图片描述
将数据0-99写入DDR,并读出。
介入以下测试代码:

#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "xparameters.h"
#include "xgpio.h"

int main()
{
    
    
	u32 i;
	u32 j;
	u32 DDR_BUFF[100];
    init_platform();

    u32 *DDR_ADDR;
    u32 *LED_ADDR;
    DDR_ADDR = (u32 *)0x80000000;
    LED_ADDR = (u32 *)0x40000000;

	for(i=0;i<100;i++)
	{
    
    
		*(DDR_ADDR+i) = i;
	}
	for(i=0;i<100;i++)
	{
    
    
		DDR_BUFF[i] = *(DDR_ADDR+i) ;
	}

    cleanup_platform();
    return 0;
}


调试:先进行调试设置
在这里插入图片描述
在这里插入图片描述
结果:
在这里插入图片描述

2.1 不断电重新读数据

关闭写操作,未断电在改地址进行读数据

#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "xparameters.h"
#include "xgpio.h"

int main()
{
    
    
	u32 i;
	u32 j;
	u32 DDR_BUFF[100];
    init_platform();

    u32 *DDR_ADDR;
    u32 *LED_ADDR;
    DDR_ADDR = (u32 *)0x80000000;
    LED_ADDR = (u32 *)0x40000000;


//		for(i=0;i<100;i++)
//		{
    
    
//			*(DDR_ADDR+i) = i;
//		}
		for(i=0;i<100;i++)
		{
    
    
			DDR_BUFF[i] = *(DDR_ADDR+i) ;
		}

    cleanup_platform();
    return 0;
}

结果
在这里插入图片描述
注意 cleanup_platform();函数会释放内存,断点设置在此函数前面,或者不用此函数。

★★★如有错误欢迎指导!!!

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_40147893/article/details/115382474