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

【EDA软件】【联合Modelsim 同步FIFO仿真】

1. 背景

使用者完成功能RTL代码开发,需要进行功能仿真。RTL代码中可能使用了IP,使用者不知道这些IP的仿真库文件。

2. 分析

不同的FPGA厂商都各自不同的仿真库文件,并且不同系列型号仿真库文件也不同,而且IP也可能需要*.vp(HME是这种文件类型)文件。

关于HME的EDA如何联合Modelsim进行仿真,请查阅此【EDA软件】【联合Modelsim仿真使用方法】_eda仿真-CSDN博客帖子。

3. 同步FIFO仿真

步骤如下:

a. 为了方便快速仿真,使用了HME自有内部晶振、PLL和POR IP,以此IP产生时钟和复位,供TestBench使用;

b. 选择FIFO IP,生成RTL代码;

c. 自己编写简单同步FIFO;

d. TestBench编写激励,例化HME的FIFO IP文件,以及RM FIFO文件,如下图。

e. 使用Modelsim仿真,查看并对比波形。

图1

3.1 EDA产生基本IP

oscillator_v1:是EDA工具自带80MHz的晶振IP;

pll_v1:是EDA工具自带的PLL IP;因为使用了oscillator_v1,PLL的输入时钟需要设置为80MHz,输出个数和频率可以自行设置。该举例是1个输出的100MHz频率;

por_v1_1:是EDA工具自带的POR IP。

以上三个IP的使用,可以查阅HME的相关资料。另外本次举例是选用HME H7系列。

3.2 EDA生成同步FIFO

图2

a. 选中同步FIFO;

b. 设置地址位宽以及数据宽度;

c. First word fall through:预读功能,举例不选。

图3

d. 端口的选择,举例仅使用上下溢出;

图4

e. 读写清除、操作、阈值设置、读写计数,举例仅操作。

生成后EDA界面如图5.

图5

3.3 编写RM的同步FIFO代码

RM 的FIFO分为三部分:

rm_sync_fifo.v:同步FIFO的接口,内部实现FIFO CTRL、SDPRAM的例化;

module rm_sync_fifo #(parameter       DATA_WIDTH   = 32   ,parameter       ADDR_WIDTH   = 10   ,parameter       ALFULL_THD   = ((ADDR_WIDTH << 1) - 10),parameter       ALEMPTY_THD  =  10
)
(input                           clk             ,input                           rst_n           ,input                           wen             ,input                           ren             ,input        [DATA_WIDTH-1:0]   wdata           ,output  wire [DATA_WIDTH-1:0]   rdata           ,output  wire                    rempty          ,output  wire                    wfull           ,output  wire                    overflow        ,output  wire                    underflow       ,output  wire                    almost_full     ,output  wire                    almost_empty
);wire                            wr_en           ;
wire    [ADDR_WIDTH-1:0]        wr_addr         ;
wire    [DATA_WIDTH-1:0]        wr_data         ;
wire                            rd_en           ;
wire    [ADDR_WIDTH-1:0]        rd_addr         ;
wire    [DATA_WIDTH-1:0]        rd_data         ;rm_sync_fifo_ctrl  #(.DATA_WIDTH         (   DATA_WIDTH  ),.ADDR_WIDTH         (   ADDR_WIDTH  ),.ALFULL_THD         (   ALFULL_THD  ),.ALEMPTY_THD        (   ALEMPTY_THD )
)
u_rm_sync_fifo_ctrl (.clk                (   clk         ), // i.rst_n              (   rst_n       ), // i.wren               (   wen         ), // i.rden               (   ren         ), // i.wdata              (   wdata       ), // i.rdata              (   rdata       ), // o.rempty             (   rempty      ), // o.wfull              (   wfull       ), // o.overflow           (   overflow    ), // o.underflow          (   underflow   ), // o.almost_full        (   almost_full ), // o.almost_empty       (   almost_empty), // o.wr_en              (   wr_en       ), // o.wr_addr            (   wr_addr     ), // o.wr_data            (   wr_data     ), // o.rd_en              (   rd_en       ), // o.rd_addr            (   rd_addr     ), // o.rd_data            (   rd_data     )  // i
);rm_sdpram #(.DATA_WIDTH         (   DATA_WIDTH  ),.ADDR_WIDTH         (   ADDR_WIDTH  )
)
u_rm_sdpram (.wr_clk             (   clk         ), // i.wr_rst_n           (   rst_n       ), // i.wr_en              (   wr_en       ), // i.wr_addr            (   wr_addr     ), // i.wr_data            (   wr_data     ), // i.rd_clk             (   clk         ), // i.rd_rst_n           (   rst_n       ), // i.rd_en              (   rd_en       ), // i.rd_addr            (   rd_addr     ), // i.rd_data            (   rd_data     )  // o
);endmodule

rm_sync_fifo_ctrl.v:FIFO CTRL实现读写地址、空满信号;

module rm_sync_fifo_ctrl #(parameter       DATA_WIDTH   = 32   ,parameter       ADDR_WIDTH   = 10   ,parameter       ALFULL_THD   = ((ADDR_WIDTH << 1) - 10),parameter       ALEMPTY_THD  =  10
)
(input                               clk             ,input                               rst_n           ,input                               wren            ,input                               rden            ,input           [DATA_WIDTH-1:0]    wdata           ,output  wire    [DATA_WIDTH-1:0]    rdata           ,output  wire                        rempty          ,output  wire                        wfull           ,output  wire                        overflow        ,output  wire                        underflow       ,output  wire                        almost_full     ,output  wire                        almost_empty    ,output  wire                        wr_en           ,output  reg     [ADDR_WIDTH-1:0]    wr_addr         ,output  wire    [DATA_WIDTH-1:0]    wr_data         ,output  wire                        rd_en           ,output  reg     [ADDR_WIDTH-1:0]    rd_addr         ,input   wire    [DATA_WIDTH-1:0]    rd_data
);localparam DEPTH = (1 << ADDR_WIDTH);
reg     [ADDR_WIDTH-1:0]    cnt         ;
reg     [ADDR_WIDTH  :0]    wr_cnt      ;
reg     [ADDR_WIDTH  :0]    rd_cnt      ;
reg     [ADDR_WIDTH-1:0]    fifo_cnt      ;assign  wr_en = wren & (!wfull);
assign  rd_en = rden & (!rempty);
assign  wr_data = wdata;
assign  rdata = rd_data;always @ (posedge clk or negedge rst_n) beginif (!rst_n) beginwr_addr <= {ADDR_WIDTH{1'b0}};endelse if (wr_en) beginwr_addr <= wr_addr + 1'b1;endelse;
endalways @ (posedge clk or negedge rst_n) beginif (!rst_n) beginrd_addr <= {ADDR_WIDTH{1'b0}};endelse if (rd_en) beginrd_addr <= rd_addr + 1'b1;endelse;
endalways @ (posedge clk or negedge rst_n) beginif (!rst_n) beginwr_cnt <= {(ADDR_WIDTH+1){1'b0}};endelse if (wr_en) beginwr_cnt <= wr_cnt + 1'b1;endelse;
endalways @ (posedge clk or negedge rst_n) beginif (!rst_n) beginrd_cnt <= {(ADDR_WIDTH+1){1'b0}};endelse if (rd_en) beginrd_cnt <= rd_cnt + 1'b1;endelse;
endalways @ (posedge clk or negedge rst_n) beginif (!rst_n) begincnt <= {ADDR_WIDTH{1'b0}};endelse begincase ({wr_en,rd_en})2'b10: cnt <= cnt + 1'b1;2'b01: cnt <= cnt - 1'b1;default:;endcaseend
endassign wfull = (cnt == DEPTH) ? 1'b1 : 1'b0;
assign rempty = (cnt == {ADDR_WIDTH{1'b0}}) ? 1'b1 : 1'b0;
assign overflow = (wr_cnt > rd_cnt) ? 1'b1 : 1'b0;
assign underflow = (rd_cnt > wr_cnt) ? 1'b1 : 1'b0;assign almost_full = 1'b0;
assign almost_empty = 1'b0;endmodule

rm_sdpram.v:寄存器搭建的RAM

module rm_sdpram #(parameter       DATA_WIDTH   = 32   ,parameter       ADDR_WIDTH   = 10   ,parameter       FISRT_WORD_EN = 1
)
(input                                   wr_clk      ,input                                   wr_rst_n    ,input                                   wr_en       ,input           [ADDR_WIDTH-1:0]        wr_addr     ,input           [DATA_WIDTH-1:0]        wr_data     ,input                                   rd_clk      ,input                                   rd_rst_n    ,input                                   rd_en       ,input           [ADDR_WIDTH-1:0]        rd_addr     ,output  reg     [DATA_WIDTH-1:0]        rd_data
);localparam DEPTH = (1 << ADDR_WIDTH);reg     [DATA_WIDTH-1:0]    memory [DEPTH-1:0];always @ (posedge wr_clk or negedge wr_rst_n) begin : WRITE_DATAinteger i;if (!wr_rst_n) beginfor (i = 0; i < DEPTH; i = i + 1) begin : INIT_MEMmemory[i] <= {DATA_WIDTH{1'b0}};endendelse if (wr_en == 1'b1) beginmemory[wr_addr] <= wr_data;endelse;
endalways @ (posedge rd_clk or negedge rd_rst_n) begin : READ_DATAif (!rd_rst_n) beginrd_data <= {DATA_WIDTH{1'b0}};endelse if (rd_en == 1'b1) beginrd_data <= memory[rd_addr];endelse;
endendmodule

此处使用了UVM中RM(Reference Model:参考模型)思想,使用者也可以不用跳过此步,使用TestBench例化同步FIFO IP。

3.4 TestBench编码

tb_top.v

module tb_top ();wire            inner_osc_clk       ;
wire            clk                 ;
wire            rst_n               ;reg     [9:0]   cnt                 ;
reg             fifo_wen            ;
reg     [31:0]  fifo_wdata          ;
reg             fifo_ren            ;
wire    [31:0]  fifo_rdata          ;
wire            fifo_rempty         ;
wire            fifo_wfull          ;wire    [31:0]  rm_fifo_rdata       ;
wire            rm_fifo_rempty      ;
wire            rm_fifo_wfull       ;oscillator_v1 u_oscillator_v1(.clkout     (  inner_osc_clk    )
);pll_v1 u_pll_v1(.clkin0     (   inner_osc_clk   ), // i.locked     (   pll_locked      ), // o.clkout0    (   fpga_clk        )  // o
);por_v1_1 u_por_v1_1(.O          (   por_locked      )
);assign  sys_rst_n = pll_locked & por_locked;assign  clk = fpga_clk;
assign  rst_n = sys_rst_n;always @ (posedge clk or negedge rst_n) beginif (~rst_n) begincnt <= 10'd0;endelse begincnt <= cnt + 1'd1;end
endalways @ (posedge clk or negedge rst_n) beginif (~rst_n) beginfifo_wen <= 1'b0;endelse if ((~fifo_wfull) && ((cnt[1:0] == 2'd0))) beginfifo_wen <= 1'b1;endelse beginfifo_wen <= 1'b0;end
endalways @ (posedge clk or negedge rst_n) beginif (~rst_n) beginfifo_wdata <= 32'b0;endelse if (fifo_wen == 1'b1) beginfifo_wdata <= fifo_wdata + 1'b1;endelse;
endalways @ (posedge clk or negedge rst_n) beginif (~rst_n) beginfifo_ren <= 1'b0;endelse if ((~fifo_rempty) && (cnt[1:0] == 2'd3)) beginfifo_ren <= 1'b1;endelse beginfifo_ren <= 1'b0;end
endfifo_v2 u_fifo_v2 (.clk            (   clk             ), // i.rst_n          (   rst_n           ), // i.wdata          (   fifo_wdata      ), // i.rdata          (   fifo_rdata      ), // o.wen            (   fifo_wen        ), // i.ren            (   fifo_ren        ), // i.overflow       (                   ), // o.underflow      (                   ), // o.almost_full    (                   ), // o.almost_empty   (                   ), // o.rempty         (   fifo_rempty     ), // o.wfull          (   fifo_wfull      )  // o
);rm_sync_fifo u_rm_sync_fifo (.clk            (   clk             ), // i.rst_n          (   rst_n           ), // i.wdata          (   fifo_wdata      ), // i.rdata          (   rm_fifo_rdata   ), // o.wen            (   fifo_wen        ), // i.ren            (   fifo_ren        ), // i.overflow       (                   ), // o.underflow      (                   ), // o.almost_full    (                   ), // o.almost_empty   (                   ), // o.rempty         (   rm_fifo_rempty  ), // o.wfull          (   rm_fifo_wfull   )  // o
);endmodule

3.5 仿真工程

复用FPGA工程目录,添加sim和sim_src文件夹,如图6。

图6

sim文件夹存放仿真脚本,如图7;

图7

关于以上文件的内容可以参考【EDA软件】【联合Modelsim仿真使用方法】_eda仿真-CSDN博客帖子。

重点描述dut_files.list

D:/02_Fuxi/2024-12-31-win64-rel-10/data/lib/p0_sim.v
../src/ip/pll_v1.v
../src/ip/por_v1_1.v
../src/ip/oscillator_v1.v
../src/ip/fifo_v2_emb_v1.v
../src/ip/fifo_v2.v
../ip_core/fifo_v2/sim/P0/src/hme_ip_syn_fifo_v2_0.vp

文件1行:p0_sim.v文件是基本的仿真库文件;

文件2~6行的文件是EDA 产生IP的文件;

文件7行:同步FIFO必须的hme_ip_syn_fifo_v2_0.vp文件,如果使用异步FIFO,需要使用hme_ip_asyn_fifo_v2_0.vp文件。注意H7对应的路径是P0。

sim_src文件夹存放RM代码和激励文件,如图8。

图8

3.6 仿真结果

点击run_sim.bat,查看运行结果,如图9。

图9

4. 缺点

该举例最终通过"肉眼"比较波形判断是否正确,这种方法是不可取的。使用者要是熟练使用UVM,可以使用UVM,这边便于查看结果。

本举例目的使用HME平台代码仿真时,同步FIFO IP所需要的必须文件。


文章转载自:
http://bestrid.zzgtdz.cn
http://airdrop.zzgtdz.cn
http://burrstone.zzgtdz.cn
http://chromaticity.zzgtdz.cn
http://acanthus.zzgtdz.cn
http://arthropathy.zzgtdz.cn
http://biocenose.zzgtdz.cn
http://antrustion.zzgtdz.cn
http://ablaut.zzgtdz.cn
http://antilyssic.zzgtdz.cn
http://ariel.zzgtdz.cn
http://alfred.zzgtdz.cn
http://atrophied.zzgtdz.cn
http://bacteriolytic.zzgtdz.cn
http://agatha.zzgtdz.cn
http://burladero.zzgtdz.cn
http://bretzel.zzgtdz.cn
http://checkless.zzgtdz.cn
http://blat.zzgtdz.cn
http://biochrome.zzgtdz.cn
http://abye.zzgtdz.cn
http://adequately.zzgtdz.cn
http://ceremoniously.zzgtdz.cn
http://autocephaly.zzgtdz.cn
http://cajeput.zzgtdz.cn
http://bonza.zzgtdz.cn
http://caseophile.zzgtdz.cn
http://chitlin.zzgtdz.cn
http://adurol.zzgtdz.cn
http://bedspring.zzgtdz.cn
http://www.dtcms.com/a/261759.html

相关文章:

  • GitHub 趋势日报(2025年06月27日)
  • 雷卯针对灵眸科技EASY EAI nano RV1126 开发板防雷防静电方案
  • 复杂驱动开发-TLE9471的休眠流程与定时唤醒
  • DMA之 Trigger input和 Trigger Output 概念
  • 具身智能系列教程——(一)具身智能研究与发展
  • 户外人像要怎么拍 ?
  • 【Docker基础】Docker容器管理:docker top及其参数详解
  • electron中显示echarts
  • 【NLP】自然语言项目设计03
  • 关于ubuntu 20.04系统安装分区和重复登录无法加载桌面的问题解决
  • 【数据标注】事件标注1
  • Vue工程化实现约定式路由自动注册
  • Go开发工程师-Golang基础知识篇
  • 数据结构:最小生成树—Prim(普里姆)与Kruskal(克鲁斯卡尔)算法
  • 什么是哈希链(Hash Chain)?
  • Redis 实现分布式锁
  • 分布式集群压测
  • 第8章-财务数据
  • VR训练美国服务器:高性能解决方案与优化指南
  • 培养你的眼力 - 摄影构图
  • Python 中 `for` 循环与 `while` 循环的性能差异:深度剖析
  • 思维提升篇-数学抽象与计算机实现
  • 从零开始构建RAG(检索增强生成)
  • C# 委托(为委托添加方法和从委托移除方法)
  • Excel限制编辑:保护表格的实用功能
  • 【C#】使用电脑的GPU与CPU的区别
  • 鸿蒙5:其他布局容器
  • 【Redis原理】Redis分布式缓存——主从复制、哨兵机制与Redis Cluster
  • deepin 25 交换 caps lctl
  • Lua现学现卖