当前位置:网站首页>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
边栏推荐
- 怎么禁止textarea拉伸
- 临床研究方法学,到现场,到数据真实发生的地方 | 对话数智 x 张维拓
- Graphic and text hands-on tutorial--ESP32 MQTT docking EMQX local server (VSCODE+ESP-IDF)
- 图文手把手教程--ESP32 OTA空中升级(VSCODE+IDF)
- MATLAB程序设计与应用 3.1 特殊矩阵
- Super Learning Method
- 昨夜梦佳人,七夕试伊妆丨基于ModelArts实现AI妆容迁移丨【玩转华为云】
- 8月活动|51CTO十七周年庆,发博文得茶具/笔记本/T恤等礼品!
- Advanced transcriptome analysis and R data visualization hot registration (2022.10)
- 线程必备内容
猜你喜欢
A topic of map
《迁移学习导论》第2版,升级内容抢先看!
【LeetCode】700.二叉搜索树
【Idea系列】idea配置
Camunda overall architecture and related concepts
Digital management insight into retail and e-commerce operations - retail password
粤黔协作,山海同心!578种贵州特色农产品走进粤港澳大湾区
AWS Lambda相关概念与实现思路
Mysql高级篇学习总结13:多表连接查询语句优化方法(带join语句)
华为开源:聚焦开源基础软件,共建健康繁荣生态
随机推荐
RL78开发环境
解决:WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING
datax oracle to oracle离线json文件
职责链模式(responsibilitychain)
Use pytest hook function to realize automatic test result push enterprise WeChat
STM32前言知识总结
Camunda overall architecture and related concepts
【LeetCode】98.验证二叉搜索树
Graphical Hands-on Tutorial--ESP32 OTA Over-the-Air Upgrade (VSCODE+IDF)
音频编辑 合唱
Jina 实例秀|基于神经搜索的网络安全威胁检测(一)
JUC(1)线程和进程、并发和并行、线程的状态、lock锁、生产者和消费者问题
linux下数据库初始化密码
datax oracle to oracle incremental synchronization
ORB-SLAM3中的优化
知网网站地址更换
123
Win11怎么重装显卡驱动程序?Win11显卡驱动怎么卸载重装?
LeetCode第三题(Longest Substring Without Repeating Characters)三部曲之三
Difference between ArrayList and LinkedList