赞
踩
AXI-EMC IP是一个可以可以支持各种内存型号的控制器,利用这个IP可以非常方便地模拟各种类型的内存或者FLASH接口实现数据的交互和通信。以下是AXI-EMC IP的功能特性:
1、支持AXI4 Slave Memory Map接口,数据宽度为32位和64位
2、支持写入/读取寄存器的可选AXI4-Lite Slave数据宽度为32位
3、支持AXI4增量和包传输
4、支持AXI4窄带和非对齐传输
5、最多支持四个外部存储器组
6、支持具有可配置字节奇偶校验和流水线级的同步SRAM
7、支持的内存类型
° 同步SRAM
° 异步SRAM
° 线性闪存(或并行NOR闪存)
° PSRAM(或蜂窝RAM)
8、提供配置寄存器,动态更改PSRAM和Micron®闪存的访问机制
9、为同步SRAM存储器提供奇偶校验错误状态寄存器
本课程中,利用EMC实现异步SRAM的功能,实现数据的读写操作。
以下是搭建好的FPGA BD工程,搭建工程如果不熟悉的用户请参考“CH01 HelloWold/DDR/网口测试及固化”这一节课。
在本课程中主要用到了AXI_EMC这个IP,下面我们看下这个IP的设置,双击这个IP
下图中的的位宽设置为32bit其他参数默认,其中Base Address 和High Address 是AXI_EMC IP在ZYNQ 4GB地址空间中的分配的地址。
下图中,设置Memory Type 为Async SRAM ,也就是异步SRAM。这种SRAM读写起来比较方便。位宽设置为32bit。Timing Parameters是AXI系统时钟为100M的情况下的时间参数,如果采用其他时钟可能要修改时间参数。
下图设置为默认
下图是信息总汇
以下是AXI_EMC IP在ZYNQ 4GB地址空间中的分配的地址
修改调用BD工程的顶层代码,增加异步SRAM的读写接口,控制逻辑。在以下FPGA代码中,我们的SDK代码会写入4个数据,之后再读出来。
module system_top(
inout [14:0]DDR_addr,
inout [2:0]DDR_ba,
inout DDR_cas_n,
inout DDR_ck_n,
inout DDR_ck_p,
inout DDR_cke,
inout DDR_cs_n,
inout [3:0]DDR_dm,
inout [31:0]DDR_dq,
inout [3:0]DDR_dqs_n,
inout [3:0]DDR_dqs_p,
inout DDR_odt,
inout DDR_ras_n,
inout DDR_reset_n,
inout DDR_we_n,
inout FIXED_IO_ddr_vrn,
inout FIXED_IO_ddr_vrp,
inout [53:0]FIXED_IO_mio,
inout FIXED_IO_ps_clk,
inout FIXED_IO_ps_porb,
inout FIXED_IO_ps_srstb
);
wire clk_100m;
wire [31:0]mem_a;
wire [0 :0]mem_cen;
reg [31:0]mem_dq_i;
wire [31:0]mem_dq_o;
wire [0 :0]mem_oen;
wire mem_wen;
//*************************************************************************
reg [31:0] data_reg1;
reg [31:0] data_reg2;
reg [31:0] data_reg3;
reg [31:0] data_reg4;
always @ (posedge clk_100m)
if(mem_wen==1'b0)begin
case(mem_a)
16'h0:begin
data_reg1<=mem_dq_o;
end
16'h1:begin
data_reg2<=mem_dq_o;
end
16'h3:begin
data_reg3<=mem_dq_o;
end
16'h4:begin
data_reg4<=mem_dq_o;
end
default : begin
end
endcase
end
always @ (posedge clk_100m)
if(mem_oen==1'b0)begin
case(mem_a)
16'h0:begin
mem_dq_i<=data_reg1;
end
16'h1:begin
mem_dq_i<=data_reg2;
end
16'h3:begin
mem_dq_i<=data_reg3;
end
16'h4:begin
mem_dq_i<=data_reg4;
end
default : begin
end
endcase
end
//*************************************************************************
wire [131:0] probe0;
ila_core ila_core_uut (
.clk(clk_100m), // input wire clk
.probe0(probe0) // input wire [99:0] probe0
);
assign probe0[31:0]=mem_a;
assign probe0[63:32]=mem_dq_o;
assign probe0[95:64]=mem_dq_i;
assign probe0[96]=mem_cen;
assign probe0[97]=mem_oen;
assign probe0[98]=mem_wen;
system system_i
(.DDR_addr(DDR_addr),
.DDR_ba(DDR_ba),
.DDR_cas_n(DDR_cas_n),
.DDR_ck_n(DDR_ck_n),
.DDR_ck_p(DDR_ck_p),
.DDR_cke(DDR_cke),
.DDR_cs_n(DDR_cs_n),
.DDR_dm(DDR_dm),
.DDR_dq(DDR_dq),
.DDR_dqs_n(DDR_dqs_n),
.DDR_dqs_p(DDR_dqs_p),
.DDR_odt(DDR_odt),
.DDR_ras_n(DDR_ras_n),
.DDR_reset_n(DDR_reset_n),
.DDR_we_n(DDR_we_n),
.FIXED_IO_ddr_vrn(FIXED_IO_ddr_vrn),
.FIXED_IO_ddr_vrp(FIXED_IO_ddr_vrp),
.FIXED_IO_mio(FIXED_IO_mio),
.FIXED_IO_ps_clk(FIXED_IO_ps_clk),
.FIXED_IO_ps_porb(FIXED_IO_ps_porb),
.FIXED_IO_ps_srstb(FIXED_IO_ps_srstb),
.clk_100m(clk_100m),
.mem_a(mem_a),
.mem_cen(mem_cen),
.mem_dq_i(mem_dq_i),
.mem_dq_o(mem_dq_o),
.mem_oen(mem_oen),
.mem_wen(mem_wen));
20.4 SDK代码
/*
* main.c
*
* Created on: 2019年5月21日
* Author: Administrator
*/
#include <stdio.h>
#include "sleep.h"
u32 data[4];
u32 i;
int main()
{
for(i=0;i<4;i++)
{
Xil_Out32(XPAR_EMC_0_S_AXI_MEM0_BASEADDR+i*4,i);
}
sleep(1);
for(i=0;i<4;i++)
{
data[i]=Xil_In32(XPAR_EMC_0_S_AXI_MEM0_BASEADDR+i*4);
}
for(i=0;i<4;i++)
xil_printf("read %d = %d\n\r", i,data[i]);
return 0;
}
以上代码中先写入4个数据,之后在读出来,这里需要注意,ZYNQ是32bit的数据总线所以地址每次要增加4.
写波形
读波形
串口打印输出
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。