当前位置:网站首页>Xilinx VIVADO 中 DDR3(Naive)的使用(2)读写设计
Xilinx VIVADO 中 DDR3(Naive)的使用(2)读写设计
2022-08-04 11:04:00 【chylinne】
1、概述
本文基于 Xilinx VIVADO 2018.3 调用的 DDR3 IP 核(Memory Interface Generator, MIG 7 Series),针对 Xilinx 定义的 app 接口(Naive),设计读写模块状态机,并用 Verilog 进行实现。
2、读写状态机设计
我们设计的读写测试模块预期要实现的功能:
(1)写入一定量的数据(可设置,默认 512 个)到 DDR3,写入地址从 0 开始。
(2)从地址 0 开始读取之前写入 DDR3 的数据,同时判断读、写数据是否一致。
(3)循环上两个步骤,即写、读、写、读 ......
因此,状态机很简单,我们可以设置如下 4 个状态,其状态转移规则如上图所示。
IDLE:初始状态,等 MIG IP 核初始化完成后跳转到写数据状态 WRITE。
WRITE:写数据状态,在这个状态向 MIG IP 核写入一定量的数据(测试为 512 个)。当写入最后一个数据时,同步跳转到等待状态 WAIT。
WAIT:过渡状态,仅维持一个时钟周期。
READ:读数据状态,在这个状态从 MIG IP 核读取一定量的数据(测试为 512 个)。当读取最后一个数据时,同步跳转到初始状态 IDLE。开始新一轮的写、读过程。
上一篇文章说到,在 Xilinx 定义的 app 接口(Naive)模式下,DDR3 写数据的时候有三种场景,本次测试使用写命令与写数据发生在同一时钟周期这一场景,这样代码编写会简单很多,但相应的会牺牲一点点效率(不会造成多大的影响)。
3、代码实现
完整的读写模块测试代码如下:
module ddr3_rw # (
parameter integer WR_LEN = 512,
parameter integer DATA_WIDTH = 128, //8 times 16 equals 128 bits
parameter integer ADDR_WIDTH = 28
)(
input ui_clk,
input ui_clk_sync_rst ,
input init_calib_complete,
input app_rdy,
input app_wdf_rdy,
input app_rd_data_valid,
input [DATA_WIDTH - 1:0] app_rd_data,
output reg [ADDR_WIDTH - 1:0] app_addr,
output app_en,
output app_wdf_wren,
output app_wdf_end,
output [2:0] app_cmd,
output reg [DATA_WIDTH - 1:0] app_wdf_data,
output reg error_flag
);
localparam IDLE = 4'b0001;
localparam WRITE = 4'b0010;
localparam WAIT = 4'b0100;
localparam READ = 4'b1000;
reg [3:0] cur_state;
reg [3:0] next_state;
reg [ADDR_WIDTH - 1:0] rd_addr_cnt;
reg [ADDR_WIDTH - 1:0] wr_addr_cnt;
reg [ADDR_WIDTH - 1:0] rd_cnt;
wire error;
wire rst_n;
wire wr_proc;
wire wr_last;
wire rd_addr_last;
assign rst_n = ~ui_clk_sync_rst;
assign app_en = app_rdy && ((cur_state == WRITE && app_wdf_rdy) || cur_state == READ);
assign app_wdf_wren = (cur_state == WRITE) && wr_proc;
assign app_wdf_end = app_wdf_wren;
assign app_cmd = (cur_state == READ) ? 3'd1 :3'd0;
assign wr_proc = ~app_cmd && app_rdy && app_wdf_rdy;
assign wr_last = app_wdf_wren && (wr_addr_cnt == WR_LEN - 1) ;
assign rd_addr_last = (rd_addr_cnt == WR_LEN - 1) && app_rdy && app_cmd;
always @(posedge ui_clk or negedge rst_n)
begin
if(~rst_n)
cur_state <= IDLE;
else
cur_state <= next_state;
end
always @(*)
begin
if(~rst_n)
next_state = IDLE;
else
case(cur_state)
IDLE:
if(init_calib_complete)
next_state = WRITE;
else
next_state = IDLE;
WRITE:
if(wr_last)
next_state = WAIT;
else
next_state = WRITE;
WAIT:
next_state = READ;
READ:
if(rd_addr_last)
next_state = IDLE;
else
next_state = READ;
default:;
endcase
end
always @(posedge ui_clk or negedge rst_n)
begin
if(~rst_n)
begin
app_wdf_data <= 0;
wr_addr_cnt <= 0;
rd_addr_cnt <= 0;
app_addr <= 0;
end
else
case(cur_state)
IDLE:begin
app_wdf_data <= 0;
wr_addr_cnt <= 0;
rd_addr_cnt <= 0;
app_addr <= 0;
end
WRITE:begin
if(wr_proc)begin
app_wdf_data <= app_wdf_data + 1;
wr_addr_cnt <= wr_addr_cnt + 1;
app_addr <= app_addr + 8;
end
else begin
app_wdf_data <= app_wdf_data;
wr_addr_cnt <= wr_addr_cnt;
app_addr <= app_addr;
end
end
WAIT:begin
rd_addr_cnt <= 0;
app_addr <= 0;
end
READ:begin
if(app_rdy)begin
rd_addr_cnt <= rd_addr_cnt + 1'd1;
app_addr <= app_addr + 8;
end
else begin
rd_addr_cnt <= rd_addr_cnt;
app_addr <= app_addr;
end
end
default:begin
app_wdf_data <= 0;
wr_addr_cnt <= 0;
rd_addr_cnt <= 0;
app_addr <= 0;
end
endcase
end
assign error = (app_rd_data_valid && (rd_cnt!=app_rd_data));
always @(posedge ui_clk or negedge rst_n)
begin
if(~rst_n)
error_flag <= 0;
else if(error)
error_flag <= 1;
end
always @(posedge ui_clk or negedge rst_n)
begin
if(~rst_n)
rd_cnt <= 0;
else if(app_rd_data_valid && rd_cnt == WR_LEN - 1)
rd_cnt <= 0;
else if (app_rd_data_valid )
rd_cnt <= rd_cnt + 1;
end
endmodule
边栏推荐
猜你喜欢
3-5年以上的功能测试如何进阶自动化?
什么是终端特权管理
中介者模式(Mediator)
秒云成功入选《2022爱分析 · 银行数字化厂商全景报告》,智能运维能力获认可
热成像测温的原理是什么呢?你知道吗?
Events in August | 51CTO's 17th Anniversary Celebration, post a blog post to get gifts such as tea sets/notebooks/T-shirts!
化繁为简!阿里新产亿级流量系统设计核心原理高级笔记(终极版)
cubemx stm32 afm3000模块 气体流量传感器 驱动代码
再次搞定 Ali 云函数计算 FC
What is the terminal privilege management
随机推荐
MySQL 45 讲 | 11 怎么给字符串字段加索引?
Graphic and text hands-on tutorial--ESP32 MQTT docking EMQX local server (VSCODE+ESP-IDF)
Rust 入门指南 (用 WASM 开发第一个 Web 页面)
Oracle中对临时表空间执行shrink操作
【LeetCode】653. 两数之和 IV - 输入 BST
八、MFC对话框
Difference between ArrayList and LinkedList
数字知识库及考学一体化平台
Jina 实例秀|基于神经搜索的网络安全威胁检测(一)
map的一道题目<单词识别>
ROI LTV CPA ECPM体系讲解
winform 在Datatable插入一笔数据
RL78开发环境
华为云安全云脑,让企业云化运营更放心
Jina 实例秀|七夕神器!比你更懂你女友的AI口红推荐
遍历Map的四种方法
OD-Model【5】:YOLOv1
A topic of map
热成像测温的原理是什么呢?你知道吗?
章节小测一