当前位置: 首页 > news >正文

DDR4系列之ECC功能(六)

一、 概述
在之前我们讲到使用两个ddr4内存实现数据的流水操作的功能特性和适用情况,本章节将工程示例模块列出,并给出模块接口说明和示例代码。
二、 示例流程框架
在这里插入图片描述
三、 test_ddr4_0模块说明
在这里插入图片描述
模块功能描述:
test_ddr4_0模块作用是产生读写ddr0的命令,
写命令:
写命令需要产生wr_start、awaddr_in、awlen_in、wdata_in。每当写突发完成一次,就产生一拍wr_start,并且需要计算awaddr_in的值,awlen_in保持255的值,每次突发256个数据。Wdata_in根据wready和wvalid的握手,Wdata_in生成递增数。共产生100次写突发。
读命令:
为了使读出的数据有效,使用写地址计数减去读地址计数,地址计数不小于’h4000时,可以请求读ddr4,每次固定读取’d256长度。读地址为araddr_cnt。
示例代码:

reg [31:0] clk_cnt;
reg wr_end_flag;
reg send_valid;
reg [7:0] wr_end_flag_cnt;

assign fifo_wr_en = rd_en;
assign fifo_wr_data = rd_data;

always @(posedge clk ) begin
if (rst) begin
clk_cnt <= 0;
end
else if (clk_cnt == 'h1000) begin
clk_cnt <= clk_cnt;
end
else if (clk_cnt <= ('h1000-1)) begin
clk_cnt <= clk_cnt + 1;
end
end

always @(posedge clk ) begin
if (rst) begin
wr_start <= 0;
end
else if (send_valid && wr_end_flag ) begin
wr_start <= 1;
end
else if (clk_cnt == ('h1000-1)) begin
wr_start <= 1;
end
else begin
wr_start <= 0;
end
end

always @(posedge clk ) begin
if (rst) begin
awaddr_in <= 0;
end
else if (send_valid && wr_end_flag) begin
awaddr_in <= awaddr_cnt;
end
else if (clk_cnt == ('h1000-1)) begin
awaddr_in <= 'h0;
end
end

always @(posedge clk ) begin
if (rst) begin
awlen_in <= 0;
end
else if (send_valid && wr_end_flag) begin
awlen_in <= 'd255;
end
else if (clk_cnt == ('h1000-1)) begin
awlen_in <= 'd255;
end
end

always @(posedge clk ) begin
if (rst) begin
wdata_in <= 'h0;
end
else if (wready && wvalid) begin
wdata_in <= wdata_in + 'd1;
//wdata_in <= {512{1’b1}};
end
end
reg wr_busy_r;
always @(posedge clk ) begin
wr_busy_r <= wr_busy;
end

always @(posedge clk ) begin
if (rst) begin
wr_end_flag <= 0;
end
else if (wr_busy_r == 1 && wr_busy == 0) begin
wr_end_flag <= 1;
end
else begin
wr_end_flag <= 0;
end
end

always @(posedge clk ) begin
if (rst) begin
send_valid <= 0;
end
else if (wr_end_flag_cnt == 'd99 && wr_busy_r == 1 && wr_busy == 0) begin
send_valid <= 0;
end
else if (clk_cnt == ('h1000-1)) begin
send_valid <= 1;
end
end
always @(posedge clk ) begin
if (rst) begin
wr_end_flag_cnt <= 0;
end
else if (send_valid && wr_end_flag_cnt == 'd99 && wr_end_flag) begin
wr_end_flag_cnt <= 0;
end
else if (send_valid && wr_end_flag) begin
wr_end_flag_cnt <= wr_end_flag_cnt + 1;
end
end

//rd

reg [32:0] able_rd_addrcnt;
always @(posedge clk ) begin
if (rst) begin
able_rd_addrcnt <= 0;
end
else begin
able_rd_addrcnt <= awaddr_cnt - araddr_cnt;
end
end
always @(posedge clk ) begin
if (rst) begin
rd_start <= 0;
end
else if (rd_start == 0 && rd_busy == 0 && able_rd_addrcnt>='h4000 && fifo_alfull == 0) begin
rd_start <= 1;
end
else begin
rd_start <= 0;
end
end

always @(posedge clk ) begin
if (rst) begin
araddr_in <= 0;
end
else if (rd_start == 0 && rd_busy == 0 && able_rd_addrcnt>='h4000 && fifo_alfull == 0) begin
araddr_in <= araddr_cnt;
end
end

always @(posedge clk ) begin
if (rst) begin
arlen_in <= 0;
end
else if (rd_start == 0 && rd_busy == 0 && able_rd_addrcnt>='h4000 && fifo_alfull == 0) begin
arlen_in <= 'd255;
end
end

四、 flow_ctrl模块说明
flow_ctrl模块的作用是对数据做一个缓存。使用fifo将数据缓存。并给出可以读写数据的标志。因为每次读写的长度固定为256。所以当fifo中至少有256个数据后才能将数据读出写给ddr4。当fifo至少有256个空闲深度才能将数据从ddr4读出放到fifo中。

模块代码:
module flow_ctrl(
input wire clk,
input wire rst,

output 		reg 				fifo_alfull,
output 		wire 				fifo_alempty, 				
input 			wire 				fifo_wr_en,
input 			wire 	[511:0] 		fifo_wr_data,input 			wire 				fifo_rd_en,
output 		wire 	[511:0] 		fifo_rd_data
);

wire [10:0] data_count;

fifo_data_512x1024 fifo_data_512x1024 (
.clk (clk), // input wire clk
.din (fifo_wr_data), // input wire [511 : 0] din
.wr_en (fifo_wr_en), // input wire wr_en
.rd_en (fifo_rd_en), // input wire rd_en
.dout (fifo_rd_data), // output wire [511 : 0] dout
.full (full), // output wire full
.almost_full (almost_full), // output wire almost_full
.empty (empty), // output wire empty
.almost_empty (almost_empty), // output wire almost_empty
.data_count (data_count) // output wire [10 : 0] data_count
);

always @(posedge clk ) begin
if (rst) begin
fifo_alfull <= 0;
end
else if (data_count >= 'd768) begin
fifo_alfull <= 1;
end
else begin
fifo_alfull <= 0;
end
end

assign fifo_alempty = (data_count < 'd256) ? 1 :0;
endmodule

五、 test_ddr4_72width_1模块说明
模块功能描述:
test_ddr4_0模块作用是产生读写ddr0的命令,
写命令:
写命令需要产生wr_start、awaddr_in、awlen_in、wdata_in。每当写突发完成一次,就产生一拍wr_start,并且需要计算awaddr_in的值,awlen_in保持255的值,每次突发256个数据。Wdata_in根据wready和wvalid的握手,Wdata_in生成递增数。共产生100次写突发。
读命令:
为了使读出的数据有效,使用写地址计数减去读地址计数,地址计数不小于’h4000时,可以请求读ddr4,每次固定读取’d256长度。读地址为araddr_cnt。
示例代码:

reg [31:0] clk_cnt;
reg wr_end_flag;
reg send_valid;
reg [7:0] wr_end_flag_cnt;

assign fifo_wr_en = rd_en;
assign fifo_wr_data = rd_data;

always @(posedge clk ) begin
if (rst) begin
clk_cnt <= 0;
end
else if (clk_cnt == 'h1000) begin
clk_cnt <= clk_cnt;
end
else if (clk_cnt <= ('h1000-1)) begin
clk_cnt <= clk_cnt + 1;
end
end

always @(posedge clk ) begin
if (rst) begin
wr_start <= 0;
end
else if (send_valid && wr_end_flag ) begin
wr_start <= 1;
end
else if (clk_cnt == ('h1000-1)) begin
wr_start <= 1;
end
else begin
wr_start <= 0;
end
end

always @(posedge clk ) begin
if (rst) begin
awaddr_in <= 0;
end
else if (send_valid && wr_end_flag) begin
awaddr_in <= awaddr_cnt;
end
else if (clk_cnt == ('h1000-1)) begin
awaddr_in <= 'h0;
end
end

always @(posedge clk ) begin
if (rst) begin
awlen_in <= 0;
end
else if (send_valid && wr_end_flag) begin
awlen_in <= 'd255;
end
else if (clk_cnt == ('h1000-1)) begin
awlen_in <= 'd255;
end
end

always @(posedge clk ) begin
if (rst) begin
wdata_in <= 'h0;
end
else if (wready && wvalid) begin
wdata_in <= wdata_in + 'd1;
//wdata_in <= {512{1’b1}};
end
end
reg wr_busy_r;
always @(posedge clk ) begin
wr_busy_r <= wr_busy;
end

always @(posedge clk ) begin
if (rst) begin
wr_end_flag <= 0;
end
else if (wr_busy_r == 1 && wr_busy == 0) begin
wr_end_flag <= 1;
end
else begin
wr_end_flag <= 0;
end
end

always @(posedge clk ) begin
if (rst) begin
send_valid <= 0;
end
else if (wr_end_flag_cnt == 'd99 && wr_busy_r == 1 && wr_busy == 0) begin
send_valid <= 0;
end
else if (clk_cnt == ('h1000-1)) begin
send_valid <= 1;
end
end
always @(posedge clk ) begin
if (rst) begin
wr_end_flag_cnt <= 0;
end
else if (send_valid && wr_end_flag_cnt == 'd99 && wr_end_flag) begin
wr_end_flag_cnt <= 0;
end
else if (send_valid && wr_end_flag) begin
wr_end_flag_cnt <= wr_end_flag_cnt + 1;
end
end

//rd

reg [32:0] able_rd_addrcnt;
always @(posedge clk ) begin
if (rst) begin
able_rd_addrcnt <= 0;
end
else begin
able_rd_addrcnt <= awaddr_cnt - araddr_cnt;
end
end
always @(posedge clk ) begin
if (rst) begin
rd_start <= 0;
end
else if (rd_start == 0 && rd_busy == 0 && able_rd_addrcnt>='h4000 && fifo_alfull == 0) begin
rd_start <= 1;
end
else begin
rd_start <= 0;
end
end

always @(posedge clk ) begin
if (rst) begin
araddr_in <= 0;
end
else if (rd_start == 0 && rd_busy == 0 && able_rd_addrcnt>='h4000 && fifo_alfull == 0) begin
araddr_in <= araddr_cnt;
end
end

always @(posedge clk ) begin
if (rst) begin
arlen_in <= 0;
end
else if (rd_start == 0 && rd_busy == 0 && able_rd_addrcnt>='h4000 && fifo_alfull == 0) begin
arlen_in <= 'd255;
end
end

四、 flow_ctrl模块说明
flow_ctrl模块的作用是对数据做一个缓存。使用fifo将数据缓存。并给出可以读写数据的标志。因为每次读写的长度固定为256。所以当fifo中至少有256个数据后才能将数据读出写给ddr4。当fifo至少有256个空闲深度才能将数据从ddr4读出放到fifo中。

模块代码:
module flow_ctrl(
input wire clk,
input wire rst,

output 		reg 				fifo_alfull,
output 		wire 				fifo_alempty, 				
input 			wire 				fifo_wr_en,
input 			wire 	[511:0] 		fifo_wr_data,input 			wire 				fifo_rd_en,
output 		wire 	[511:0] 		fifo_rd_data
);

wire [10:0] data_count;

fifo_data_512x1024 fifo_data_512x1024 (
.clk (clk), // input wire clk
.din (fifo_wr_data), // input wire [511 : 0] din
.wr_en (fifo_wr_en), // input wire wr_en
.rd_en (fifo_rd_en), // input wire rd_en
.dout (fifo_rd_data), // output wire [511 : 0] dout
.full (full), // output wire full
.almost_full (almost_full), // output wire almost_full
.empty (empty), // output wire empty
.almost_empty (almost_empty), // output wire almost_empty
.data_count (data_count) // output wire [10 : 0] data_count
);

always @(posedge clk ) begin
if (rst) begin
fifo_alfull <= 0;
end
else if (data_count >= 'd768) begin
fifo_alfull <= 1;
end
else begin
fifo_alfull <= 0;
end
end

assign fifo_alempty = (data_count < 'd256) ? 1 :0;
endmodule

五、 test_ddr4_72width_1模块说明

请添加图片描述
请添加图片描述
模块功能:
此模块用来对ddr1产生读写命令。
1、写命令:
当fifo不空时,产生写ddr1命令,写ddr1突发长度为256,awlen_in的值为’d255。写突发地址(awaddr_in)根据写地址计数(wr_start)给出下一次写突发的起始地址(awaddr_in)。
写ddr数据为fifo的读数据,wready与wvalid握手作为fifo读使能。
2、读命令:
使用写地址计数-读地址计数。当差值大于等于’h4000时,可以产生ddr1的读命令,突发长度为256,将ddr1的读地址计数作为ddr1的读地址。

模块代码示例:
always @(posedge clk ) begin
if (rst) begin
wr_start <= 0;
end
else if (wr_busy == 0 && wr_start ==0 && fifo_alempty == 0) begin
wr_start <= 1;
end
else begin
wr_start <= 0;
end
end

always @(posedge clk ) begin
if (rst) begin
awaddr_in <= 0;
end
else if (wr_busy == 0 && wr_start ==0 && fifo_alempty == 0) begin
awaddr_in <= awaddr_cnt;
end
end

always @(posedge clk ) begin
if (rst) begin
awlen_in <= 0;
end
else if (wr_busy == 0 && wr_start ==0 && fifo_alempty == 0) begin
awlen_in <= 'd255;
end
end
assign fifo_rd_en = wready & wvalid;
assign wdata_in = fifo_rd_data;
reg wr_busy_r;
always @(posedge clk ) begin
wr_busy_r <= wr_busy;
end

reg [32:0] able_rd_addrcnt;
always @(posedge clk ) begin
if (rst) begin
able_rd_addrcnt <= 0;
end
else begin
able_rd_addrcnt <= awaddr_cnt - araddr_cnt;
end
end
always @(posedge clk ) begin
if (rst) begin
rd_start <= 0;
end
else if (rd_start == 0 && rd_busy == 0 && able_rd_addrcnt>='h4000 ) begin
rd_start <= 1;
end
else begin
rd_start <= 0;
end
end

always @(posedge clk ) begin
if (rst) begin
araddr_in <= 0;
end
else if (rd_start == 0 && rd_busy == 0 && able_rd_addrcnt>='h4000 ) begin
araddr_in <= araddr_cnt;
end
end

always @(posedge clk ) begin
if (rst) begin
arlen_in <= 0;
end
else if (rd_start == 0 && rd_busy == 0 && able_rd_addrcnt>='h4000 ) begin
arlen_in <= 'd255;
end
end

六、 章节概括
这一章讲述了ddr流水的两个控制ddr4的命令模块。通过将数据写入ddr0,从ddr0读出数据缓存到fifo,再从fifo取出数据写进ddr1,最后再从ddr1中读出数据。从而实现双ddr的流水控制。后面章节来进行仿真说明。
本文章由威三学社出品
对课程感兴趣可以私信联系

http://www.dtcms.com/a/609796.html

相关文章:

  • [Linux——Lesson25.线程:生产与消费者模型]
  • JavaScript while 循环
  • OceanBase分区基础知识
  • 网站如何做备份wordpress文章列分页
  • 制作一个网站需要多久wordpress地址怎么打开
  • vscode如何使用git
  • 建好网站后如何向里面加东西威海那家做网站好
  • 银河麒麟桌面操作系统的安装部署与常规使用
  • 【软考 CPU主频】外频、倍频
  • NebulaChat项目构建笔记
  • Socket:TCP/UDP通信详解
  • QT opencv实现高拍仪场景识别物体轮廓的案例详解
  • 广水住房和城乡建设部网站舟山网站建设开发
  • 深度学习打卡第R4周:LSTM-火灾温度预测
  • 最好的营销策划公司做seo网站优化价格
  • 通过Rust高性能异步网络服务器的实现看Rust语言的核心优势
  • 第36节:AI集成与3D场景中的智能NPC
  • 一个基于 LayUI + .NET 开源、轻量的医院住院管理系统
  • StarRocks 4.0:让 Apache Iceberg 数据真正 Query-Ready
  • 网站建设 自己的服务器爬虫python入门
  • android抽屉DrawerLayout在2025的沉浸式兼容
  • 美颜SDK性能优化实战:GPU加速与AI人脸美型的融合开发
  • AndroidStudio历史版本下载
  • Mac抹除重装卡在激活锁?两步快速解锁
  • Java语言是编译型还是解释型| 探究Java的运行机制与性能优化
  • 网站发语音功能如何做广州比较好的网站建设公司
  • 公司网站域名更改怎么做建设行业协会网站发展的建议
  • 【ZeroRange WebRTC】Kinesis Video Streams WebRTC Data Plane WebSocket API 深度解析
  • Docker核心概念、常用命令与实战指南
  • 交换机安全基线整改方式-华为S5700系列