当前位置:网站首页>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
边栏推荐
- 华为开源:聚焦开源基础软件,共建健康繁荣生态
- 【LeetCode】232.用栈实现队列
- 图文手把手教程--ESP32 OTA空中升级(VSCODE+IDF)
- Jina 实例秀|基于神经搜索的网络安全威胁检测(一)
- Google Earth Engine APP——实现ui.Select() 的设定和条件判断
- 【LeetCode】899.有序队列
- Win11 file types, how to change?Win11 modify the file suffix
- 《迁移学习导论》第2版,升级内容抢先看!
- Graphical Hands-on Tutorial--ESP32 OTA Over-the-Air Upgrade (VSCODE+IDF)
- cubemx stm32 afm3000模块 气体流量传感器 驱动代码
猜你喜欢
随机推荐
【LeetCode】701.二叉搜索树中的插入操作
Four ways to traverse a Map
What is the principle of thermal imaging temperature measurement?Do you know?
手搓一个“七夕限定”,用3D Engine 5分钟实现烟花绽放效果
知网网站地址更换
ThreadLocal详细分析
audio_policy_configuration.xml配置文件详解
什么是终端特权管理
从零开始Blazor Server(7)--使用Furion权限验证
ORA-00054 资源正忙
深度强化学习与APS的一些感想
cubemx stm32 afm3000模块 气体流量传感器 驱动代码
深度学习100例 —— 卷积神经网络(CNN)天气识别
ORB-SLAM3中的优化
华为云安全云脑,让企业云化运营更放心
美摄问答室|美映 VS 美摄云剪辑
WPF 截图控件之画笔(八)「仿微信」
【LeetCode】653. 两数之和 IV - 输入 BST
Meishe Q&A Room | Meiying VS Meishe Cloud Editing
STM32入门开发 制作红外线遥控器(智能居家-万能遥控器)