当前位置:网站首页>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边栏推荐
- 临床研究方法学,到现场,到数据真实发生的地方 | 对话数智 x 张维拓
- ECCV 2022 | 清华&腾讯AI Lab提出REALY: 重新思考3D人脸重建的评估方法
- Win11怎么重装显卡驱动程序?Win11显卡驱动怎么卸载重装?
- 【Idea series】idea configuration
- 使用.NET简单实现一个Redis的高性能克隆版(二)
- helm安装
- RL78 development environment
- Graphical Hands-on Tutorial--ESP32 OTA Over-the-Air Upgrade (VSCODE+IDF)
- 遍历Map的四种方法
- JUC (1) threads and processes, concurrency and parallelism, thread state, locks, producers and consumers
猜你喜欢

技术干货 | 用零信任保护代码安全

强烈推荐一款优秀且通用的后台管理系统

【励志】复盘的重要性

Win11怎么重装显卡驱动程序?Win11显卡驱动怎么卸载重装?

cubemx stm32 afm3000 module gas flow sensor driver code

AWS Lambda related concepts and implementation approach

Jenkins使用手册(1) —— 软件安装

Camunda overall architecture and related concepts

Introduction to Mysql storage engine

C语言*小白的探险历程
随机推荐
STM32前言知识总结
Jenkins使用手册(1) —— 软件安装
什么是 DevOps?看这一篇就够了!
自己实现一个枚举validation校验器
Difference between ArrayList and LinkedList
【Inspirational】The importance of review
【LeetCode】1403.非递增顺序的最小子序列
【黄啊码】MySQL入门—2、使用数据定义语言(DDL)操作数据库
ROI LTV CPA ECPM体系讲解
datax oracle to oracle incremental synchronization
Business collocations
tp5+微信小程序 分片上传
【LeetCode】899.有序队列
Using .NET to simply implement a high-performance clone of Redis (2)
Advanced transcriptome analysis and R data visualization hot registration (2022.10)
解决:WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING
美摄问答室|美映 VS 美摄云剪辑
mae,mse,rmse分别利用sklearn和numpy实现
[easyUI]修改datagrid表格中的值
【LeetCode】700.二叉搜索树
