0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

FPGA设计案例:数据缓存模块设计与验证实验

电子设计 来源:csdn 作者:没落骑士 2020-12-28 13:06 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

本文设计思想采用明德扬至简设计法。上一篇博文中定制了自定义MAC IP的结构,在用户侧需要位宽转换及数据缓存。本文以TX方向为例,设计并验证发送缓存模块。这里定义该模块可缓存4个最大长度数据包,用户根据需求改动即可。

该模块核心是利用异步FIFO进行跨时钟域处理,位宽转换由VerilogHDL实现。需要注意的是用户数据包位宽32bit,因此包尾可能有无效字节,而转换为8bit位宽数据帧后是要丢弃无效字节的。内部逻辑非常简单,直接上代码:
`timescale 1ns / 1ps

// Description: MAC IP TX方向用户数据缓存及位宽转换模块
// 整体功能:将TX方向用户32bit位宽的数据包转换成8bit位宽数据包
//用户侧时钟100MHZ,MAC侧125MHZ
//缓存深度:保证能缓存4个最长数据包,TX方向用户数据包包括
//目的MAC地址 源MAC地址 类型/长度 数据 最长1514byte

module tx_buffer#(parameter DATA_W = 32)//位宽不能改动
(

//全局信号
input rst_n,//保证拉低三个时钟周期,否则FIF可能不会正确复位

//用户侧信号
input user_clk,
input [DATA_W-1:0] din,
input din_vld,
input din_sop,
input din_eop,
input [2-1:0] din_mod,
output rdy,

//MAC侧信号
input eth_tx_clk,
output reg [8-1:0] dout,
output reg dout_sop,
output reg dout_eop,
output reg dout_vld
);

reg wr_en = 0;
reg [DATA_W+4-1:0] fifo_din = 0;
reg [ (2-1):0] rd_cnt = 0 ;
wire add_rd_cnt ;
wire end_rd_cnt ;
wire rd_en;
wire [DATA_W+4-1:0] fifo_dout;
wire rst;
reg [ (2-1):0] rst_cnt =0 ;
wire add_rst_cnt ;
wire end_rst_cnt ;
reg rst_flag = 0;
wire [11 : 0] wr_data_count;
wire empty;
wire full;

/****************************************写侧*************************************************/
always @(posedge user_clk or negedge rst_n)begin
if(rst_n==1'b0)begin
wr_en end
else if(rdy)
wr_en end

always @(posedge user_clk or negedge rst_n)begin
if(rst_n==1'b0)begin
fifo_din end
else begin//[35] din_sop [34] din_eop [33:32] din_mod [31:0] din
fifo_din end
end

assign rdy = wr_data_count

/****************************************读侧*************************************************/

always @(posedge eth_tx_clk or negedge rst_n) begin
if (rst_n==0) begin
rd_cnt end
else if(add_rd_cnt) begin
if(end_rd_cnt)
rd_cnt else
rd_cnt end
end
assign add_rd_cnt = (!empty);
assign end_rd_cnt = add_rd_cnt && rd_cnt == (4)-1 ;

assign rd_en = end_rd_cnt;

always @(posedge eth_tx_clk or negedge rst_n)begin
if(rst_n==1'b0)begin
dout end
else if(add_rd_cnt)begin
dout end
end

always @(posedge eth_tx_clk or negedge rst_n)begin
if(rst_n==1'b0)begin
dout_vld end
else if(add_rd_cnt && ((rd_cnt dout_vld end
else
dout_vld end

always @(posedge eth_tx_clk or negedge rst_n)begin
if(rst_n==1'b0)begin
dout_sop end
else if(add_rd_cnt && rd_cnt == 0 && fifo_dout[35])begin
dout_sop end
else
dout_sop end

always @(posedge eth_tx_clk or negedge rst_n)begin
if(rst_n==1'b0)begin
dout_eop end
else if(add_rd_cnt && rd_cnt == 3 - fifo_dout[33:32] && fifo_dout[34])begin
dout_eop end
else
dout_eop end

/******************************FIFO复位逻辑****************************************/
assign rst = !rst_n || rst_flag;

always @(posedge user_clk or negedge rst_n)begin
if(!rst_n)begin
rst_flag end
else if(end_rst_cnt)
rst_flag end

always @(posedge user_clk or negedge rst_n) begin
if (rst_n==0) begin
rst_cnt end
else if(add_rst_cnt) begin
if(end_rst_cnt)
rst_cnt else
rst_cnt end
end
assign add_rst_cnt = (rst_flag);
assign end_rst_cnt = add_rst_cnt && rst_cnt == (3)-1 ;

//FIFO位宽32bit 一帧数据最长1514byte,即379个16bit数据
//FIFO深度:379*4 = 1516 需要2048
//异步FIFO例化
fifo_generator_0 fifo (
.rst(rst), // input wire rst
.wr_clk(user_clk), // input wire wr_clk 100MHZ
.rd_clk(eth_tx_clk), // input wire rd_clk 125MHZ
.din(fifo_din), // input wire [33 : 0] din
.wr_en(wr_en), // input wire wr_en
.rd_en(rd_en), // input wire rd_en
.dout(fifo_dout), // output wire [33 : 0] dout
.full(full), // output wire full
.empty(empty), // output wire empty
.wr_data_count(wr_data_count) // output wire [11 : 0] wr_data_count
);

endmodule

tx_buffer

接下来是验证部分,也就是本文的重点。以下的testbench包含了最基本的测试思想:发送测试激励给UUT,将UUT输出与黄金参考值进行比较,通过记分牌输出比较结果。
`timescale 1ns / 1ps

module tx_buffer_tb( );

parameter USER_CLK_CYC = 10,
ETH_CLK_CYC = 8,
RST_TIM = 3;

parameter SIM_TIM = 10_000;

reg user_clk;
reg rst_n;
reg [32-1:0] din;
reg din_vld,din_sop,din_eop;
reg [2-1:0] din_mod;
wire rdy;
reg eth_tx_clk;
wire [8-1:0] dout;
wire dout_sop,dout_eop,dout_vld;
reg [8-1:0] dout_buf [0:1024-1];
reg [16-1:0] len [0:100-1];
reg [2-1:0] mod [0:100-1];
reg err_flag = 0;

tx_buffer#(.DATA_W(32))//位宽不能改动
dut
(

//全局信号
.rst_n (rst_n) ,//保证拉低三个时钟周期,否则FIF可能不会正确复位
.user_clk (user_clk) ,
.din (din) ,
.din_vld (din_vld) ,
.din_sop (din_sop) ,
.din_eop (din_eop) ,
.din_mod (din_mod) ,
.rdy (rdy) ,
.eth_tx_clk (eth_tx_clk) ,
.dout (dout) ,
.dout_sop (dout_sop) ,
.dout_eop (dout_eop) ,
.dout_vld (dout_vld)
);

/***********************************时钟******************************************/
initial begin
user_clk = 1;
forever #(USER_CLK_CYC/2) user_clk = ~user_clk;
end

initial begin
eth_tx_clk = 1;
forever #(ETH_CLK_CYC/2) eth_tx_clk = ~eth_tx_clk;
end
/***********************************复位逻辑******************************************/
initial begin
rst_n = 1;
#1;
rst_n = 0;
#(RST_TIM*USER_CLK_CYC);
rst_n = 1;
end

/***********************************输入激励******************************************/
integer gen_time = 0;
initial begin
#1;
packet_initial;
#(RST_TIM*USER_CLK_CYC);
packet_gen(20,2);
#(USER_CLK_CYC*10);
packet_gen(30,1);
end

/***********************************输出缓存与检测******************************************/
integer j = 0;
integer chk_time = 0;
initial begin
forever begin
@(posedge eth_tx_clk)
if(dout_vld)begin
if(dout_sop)begin
dout_buf[0] = dout;
j = 1;
end
else if(dout_eop)begin
dout_buf[j] = dout;
j = j+1;
packet_check;
end
else begin
dout_buf[j] = dout;
j = j+1;
end
end
end
end

/***********************************score board******************************************/
integer fid;
initial begin
fid = $fopen("test.txt");
$fdisplay(fid," Start testing /n");
#SIM_TIM;
if(err_flag)
$fdisplay(fid,"Check is failed/n");
else
$fdisplay(fid,"Check is successful/n");
$fdisplay(fid," Testing is finished /n");
$fclose(fid);
$stop;
end

/***********************************子任务******************************************/
//包生成子任务
task packet_gen;
input [16-1:0] length;
input [2-1:0] invalid_byte;
integer i;
begin
len[gen_time] = length;
mod[gen_time] = invalid_byte;

for(i = 1;i if(rdy == 1)begin
din_vld = 1;
if(i==1)
din_sop = 1;
else if(i == length)begin
din_eop = 1;
din_mod = invalid_byte;
end
else begin
din_sop = 0;
din_eop = 0;
din_mod = 0;
end
din = i ;
end

else begin
din_sop = din_sop;
din_eop = din_eop;
din_vld = 0;
din_mod = din_mod;
din = din;
i = i - 1;
end

#(USER_CLK_CYC*1);
end
packet_initial;
gen_time = gen_time + 1;
end
endtask

task packet_initial;
begin
din_sop = 0;
din_eop = 0;
din_vld = 0;
din = 0;
din_mod = 0;
end
endtask

//包检测子任务
task packet_check;
integer k;
integer num,packet_len;
begin
num = 1;
$fdisplay(fid,"%dth:Packet checking.../n",chk_time);
packet_len = 4*len[chk_time]-mod[chk_time];
if(j != packet_len)begin
$fdisplay(fid,"Length of the packet is wrong./n");
err_flag = 1;
disable packet_check;
end

for(k=0;k
if(k%4 == 3)begin
if(dout_buf[k] != num)begin
$fdisplay(fid,"Data of the packet is wrong!/n");
err_flag = 1;
end
num = num+1;
end
else if(dout_buf[k] != 0)begin
$fdisplay(fid,"Data of the packet is wrong,it should be zero!/n");
err_flag = 1;
end
end
chk_time = chk_time + 1;
end
endtask

endmodule

tx_buffer_tb

可见主要是task编写及文件读写操作帮了大忙,如果都用眼睛看波形来验证设计正确性,真的是要搞到眼瞎。为保证测试完备性,测试包生成task可通过输入接口产生不同长度和无效字节数的递增数据包。testbench中每检测到输出包尾指示信号eop即调用packet_check task对数值进行检测。本文的testbench结构较具通用性,可以用来验证任意对数据包进行处理的逻辑单元。

之前Modelsim独立仿真带有IP核的Vivado工程时经常报错,只好使用Vivado自带的仿真工具。一直很头痛这个问题,这次终于有了进展!首先按照常规流程使用Vivado调用Modelsim进行行为仿真,启动后会在工程目录下产生些有用的文件,帮助我们脱离Vivado进行独立仿真。

在新建Modelsim工程时,在红框内选择Vivado工程中
.sim -> sim_1 -> behav下的modelsim.ini文件。之后添加文件包括:待测试设计文件、testbench以及IP核可综合文件。第三个文件在
.srcs -> sources_1 -> ip -> -> synth下。

o4YBAF9uIlCAEUzAAACig9pDNm4320.png

现在可以顺利启动仿真了。我们来看下仿真结果:

文件中信息打印情况:

从波形和打印信息的结果来看,基本可以证明数据缓存及位宽转换模块逻辑功能无误。为充分验证要进一步给出覆盖率较高的测试数据集,后期通过编写do文件批量仿真实现。在FPGAIC设计中,验证占据大半开发周期,可见VerilogHDL的非综合子集也是至关重要的,今后会多总结高效的验证方法!

编辑:hfy


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • FPGA
    +关注

    关注

    1656

    文章

    22299

    浏览量

    630578
  • 数据缓存
    +关注

    关注

    0

    文章

    25

    浏览量

    7386
  • VerilogHDL
    +关注

    关注

    2

    文章

    39

    浏览量

    19804
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    基于FPGA的高效内存到串行数据传输模块设计

    本文介绍了一个基于FPGA的内存到串行数据传输模块,该模块设计用来高效地处理存储器中的数据并传输至串行接口。项目中自定义的“datamove
    的头像 发表于 11-12 14:31 3972次阅读
    基于<b class='flag-5'>FPGA</b>的高效内存到串行<b class='flag-5'>数据</b>传输<b class='flag-5'>模块</b>设计

    FPGA原型验证实战:如何应对外设连接问题

    在芯片设计验证中,我们常常面临一些外设连接问题:速度不匹配,或者硬件不支持。例如运行在硬件仿真器或FPGA原型平台上的设计,其时钟频率通常只有几十MHz,甚至低至1MHz以下;而真实世界中的外设
    的头像 发表于 10-22 10:28 273次阅读
    <b class='flag-5'>FPGA</b>原型<b class='flag-5'>验证实</b>战:如何应对外设连接问题

    高性能缓存设计:如何解决缓存伪共享问题

    缓存行,引发无效化风暴,使看似无关的变量操作拖慢整体效率。本文从缓存结构原理出发,通过实验代码复现伪共享问题(耗时从3709ms优化至473ms),解析其底层机制;同时深入剖析高性能缓存
    的头像 发表于 07-01 15:01 517次阅读
    高性能<b class='flag-5'>缓存</b>设计:如何解决<b class='flag-5'>缓存</b>伪共享问题

    MCU缓存设计

    MCU 设计通过优化指令与数据的访问效率,显著提升系统性能并降低功耗,其核心架构与实现策略如下: 一、缓存类型与结构 指令缓存(I-Cache)与数据
    的头像 发表于 05-07 15:29 853次阅读

    FPGA EDA软件的位流验证

    位流验证,对于芯片研发是一个非常重要的测试手段,对于纯软件开发人员,最难理解的就是位流验证。在FPGA芯片研发中,位流验证是在做什么,在哪些阶段需要做位流
    的头像 发表于 04-25 09:42 2098次阅读
    <b class='flag-5'>FPGA</b> EDA软件的位流<b class='flag-5'>验证</b>

    FPGA开发任务

    流,增加FEC校验,源时钟同步,对数据编码,输出差分数字信号,通过连接器连接光电模块,驱动光电模块传输数据。 2)光电模块输出差分数字信号,
    发表于 04-22 18:46

    紫光同创FPGA教程:呼吸灯——盘古系列PGX-Nano开发板实验例程

    用于数据缓存、DAC用于模拟信号测试验证、esp32模组进行WIFI和蓝牙透传;预留丰富的扩展IO用于用户验证、测试外接模块电路功能,一组串
    的头像 发表于 04-14 09:59 1164次阅读
    紫光同创<b class='flag-5'>FPGA</b>教程:呼吸灯——盘古系列PGX-Nano开发板<b class='flag-5'>实验</b>例程

    捕捉光的量子态:单光子信号验证实验揭秘

    传统实验设备的性能局限,打通量子理论教学与实验验证的“最后一公里”,构建直观可靠的单光子观测系统,成为推动量子技术普及的关键环节!某量子测控公司是一家专注于量子教
    的头像 发表于 04-02 17:26 905次阅读
    捕捉光的量子态:单光子信号<b class='flag-5'>验证实验</b>揭秘

    FPGA图像处理基础----实现缓存卷积窗口

    素行进行缓存与变换。由于在图像处理过程中,经常会使用到卷积,因此需要对图像进行开窗,然后将开窗得到的局部图像与卷积核进行卷积,从而完成处理。   图像数据一般按照一定的格式和时序进行传输,在我进行实验的时候,处理图像时,让其以V
    的头像 发表于 02-07 10:43 1439次阅读
    <b class='flag-5'>FPGA</b>图像处理基础----实现<b class='flag-5'>缓存</b>卷积窗口

    亚太区首座功率半导体动态可靠度验证实验室即将建立

    近日,艾默生测试与测量业务集团(前身为NI)与半导体封装测试解决方案的专业品牌蔚华科技携手宣布,双方将共同建设亚太区首座功率半导体动态可靠度验证实验室。这一举措旨在满足亚太地区日益增长的功率半导体
    的头像 发表于 01-15 16:48 1070次阅读

    蔚华科技与恩艾共建亚太首座功率半导体验证实验

    半导体封装测试领域的知名品牌蔚华科技(TWSE: 3055)与经销合作伙伴恩艾(由艾默生与NI联合运营)近日宣布了一项重大合作计划。双方将携手在亚太地区建立首座功率半导体动态可靠度验证实验室,旨在
    的头像 发表于 01-14 14:34 860次阅读

    基于Agilex 5 FPGA模块系统介绍

    基于Agilex 5 FPGA模块系统(SoM)是一种由英特尔的合作伙伴提供的生产就绪型解决方案,专门针对嵌入式应用。采用先进的Agilex 5 FPGA的SoM可以满足边缘应用日益增长的需求
    的头像 发表于 12-19 17:10 1213次阅读
    基于Agilex 5 <b class='flag-5'>FPGA</b>的<b class='flag-5'>模块</b>系统介绍

    缓存对大数据处理的影响分析

    缓存对大数据处理的影响显著且重要,主要体现在以下几个方面: 一、提高数据访问速度 在大数据环境中,数据存储通常采用分布式存储系统,
    的头像 发表于 12-18 09:45 1127次阅读

    HTTP缓存头的使用 本地缓存与远程缓存的区别

    :资源的特定版本标识,用于验证资源是否被修改。 Last-Modified :资源最后修改时间,用于验证资源是否被修改。 Vary :告诉缓存服务
    的头像 发表于 12-18 09:41 824次阅读

    缓存技术在软件开发中的应用

    在现代软件开发中,随着数据量的爆炸性增长和用户对响应速度的高要求,缓存技术成为了提升系统性能的重要手段。缓存技术通过将数据存储在离用户更近的位置,减少
    的头像 发表于 12-18 09:32 1150次阅读