这段时间有个项目需要用到紫光的DDR3以及HSSTHP两个IP,这几天在整DDR3的仿真。经过我几天的努力终于能看到IP的ddr_init_done拉高了。紫光PDS软件直接生成的modelsim 可运行tcl文件有很多问题,这里对需要修改的地方做个总结
我的软件环境如下:
Pango Design Suite 2024.2-SP1.2-ads
Modelsim SE-64 10.6d
文章目录
- 1、简介
- 2、创建tb文件
- 1 打开工程后,工程架构如下
- 2 创建tb文件
- 3 将文件添加到工程
- 4 pds软件运行一次仿真
- 3 修改tcl脚本
1、简介
我这里不会介绍如何通过PDS软件编译modelsim的仿真库,这个很简单,同学们可自行网上查询,也可直接参考下面文章
【紫光同创国产FPGA教程】——PDS与Modelsim联合仿真教程
本次我使用的工程是正点原子的达芬奇Pro Logos2的37_top_ddr3_rw实验做说明。
2、创建tb文件
1 打开工程后,工程架构如下
2 创建tb文件
参考ddr3_test_top_tb.v的方式复制ddr3的模型以及参数到自己的tb文件内,可直接复制
`timescale1ns/10fs module tb_top;`include"ddr3_parameters.vh"// Parametersparameter CA_FIRST_DLY=0.15;parameter CA_GROUP_TO_GROUP_DLY=0.05;localparam real CLKIN_FREQ=50.0;parameter PLL_REFCLK_IN_PERIOD=1000/CLKIN_FREQ;parameter MEM_DQ_WIDTH=32;parameter MEM_DQS_WIDTH=MEM_DQ_WIDTH/8;parameter MEM_ROW_WIDTH=14;//Portsreg sys_clk='d0;reg sys_rst_n='d0;wire[1:0]led;wire mem_rst_n;wire mem_ck;wire mem_ck_n;wire mem_cke;wire mem_cs_n;wire mem_ras_n;wire mem_cas_n;wire mem_we_n;wire mem_odt;wire[MEM_ROW_WIDTH-1:0]mem_a;wire[2:0]mem_ba;wire[MEM_DQS_WIDTH-1:0]mem_dqs;wire[MEM_DQS_WIDTH-1:0]mem_dqs_n;wire[MEM_DQ_WIDTH-1:0]mem_dq;wire[MEM_DQS_WIDTH-1:0]mem_dm;wire[ADDR_BITS-1:0]mem_addr;ddr3_rw_topddr3_rw_top_inst(.sys_clk(sys_clk),.sys_rst_n(sys_rst_n),.led(led),.mem_rst_n(mem_rst_n),.mem_ck(mem_ck),.mem_ck_n(mem_ck_n),.mem_cke(mem_cke),.mem_ras_n(mem_ras_n),.mem_cas_n(mem_cas_n),.mem_we_n(mem_we_n),.mem_odt(mem_odt),.mem_a(mem_a),.mem_ba(mem_ba),.mem_dqs(mem_dqs),.mem_dqs_n(mem_dqs_n),.mem_dq(mem_dq),.mem_cs_n(mem_cs_n),.mem_dm(mem_dm));always #10sys_clk=!sys_clk;wire[MEM_DQS_WIDTH+1:0]mem_ck_dly;wire[MEM_DQS_WIDTH+1:0]mem_ck_n_dly;wire[(MEM_DQS_WIDTH+2)*ADDR_BITS:0]mem_addr_dly;wire[MEM_DQS_WIDTH+1:0]mem_cke_dly;wire[MEM_DQS_WIDTH+1:0]mem_odt_dly;wire[MEM_DQS_WIDTH+1:0]mem_ras_n_dly;wire[MEM_DQS_WIDTH+1:0]mem_cas_n_dly;wire[MEM_DQS_WIDTH+1:0]mem_we_n_dly;wire[MEM_DQS_WIDTH*3+6:0]mem_ba_dly;wire[MEM_DQS_WIDTH+1:0]mem_cs_n_dly;wire[MEM_DQS_WIDTH+1:0]mem_rst_n_dly;assign #CA_FIRST_DLY mem_ck_dly[1:0]={mem_ck,mem_ck};assign #CA_FIRST_DLY mem_ck_n_dly[1:0]={mem_ck_n,mem_ck_n};assign #CA_FIRST_DLY mem_addr_dly[ADDR_BITS*2-1:0]={mem_addr,mem_addr};assign #CA_FIRST_DLY mem_cke_dly[1:0]={mem_cke,mem_cke};assign #CA_FIRST_DLY mem_odt_dly[1:0]={mem_odt,mem_odt};assign #CA_FIRST_DLY mem_ras_n_dly[1:0]={mem_ras_n,mem_ras_n};assign #CA_FIRST_DLY mem_cas_n_dly[1:0]={mem_cas_n,mem_cas_n};assign #CA_FIRST_DLY mem_we_n_dly[1:0]={mem_we_n,mem_we_n};assign #CA_FIRST_DLY mem_ba_dly[5:0]={mem_ba,mem_ba};assign #CA_FIRST_DLY mem_cs_n_dly[1:0]={mem_cs_n,mem_cs_n};assign #CA_FIRST_DLY mem_rst_n_dly[1:0]={mem_rst_n,mem_rst_n};assign mem_addr={{(ADDR_BITS-MEM_ROW_WIDTH){1'b0}},{mem_a}};genvar gen_mem;generatefor(gen_mem=0;gen_mem<(MEM_DQS_WIDTH/2);gen_mem=gen_mem+1)begin:i_mem assign #CA_GROUP_TO_GROUP_DLY mem_addr_dly[(ADDR_BITS*(gen_mem+1)+ADDR_BITS)*2-1:(ADDR_BITS*(gen_mem+1))*2]=mem_addr_dly[(ADDR_BITS*gen_mem+ADDR_BITS)*2-1:(ADDR_BITS*gen_mem)*2];assign #CA_GROUP_TO_GROUP_DLY mem_cke_dly[2*gen_mem+3:2*gen_mem+2]=mem_cke_dly[2*gen_mem+1:2*gen_mem];assign #CA_GROUP_TO_GROUP_DLY mem_odt_dly[2*gen_mem+3:2*gen_mem+2]=mem_odt_dly[2*gen_mem+1:2*gen_mem];assign #CA_GROUP_TO_GROUP_DLY mem_ras_n_dly[2*gen_mem+3:2*gen_mem+2]=mem_ras_n_dly[2*gen_mem+1:2*gen_mem];assign #CA_GROUP_TO_GROUP_DLY mem_cas_n_dly[2*gen_mem+3:2*gen_mem+2]=mem_cas_n_dly[2*gen_mem+1:2*gen_mem];assign #CA_GROUP_TO_GROUP_DLY mem_we_n_dly[2*gen_mem+3:2*gen_mem+2]=mem_we_n_dly[2*gen_mem+1:2*gen_mem];assign #CA_GROUP_TO_GROUP_DLY mem_ba_dly[(gen_mem+1)*6+5:(gen_mem+1)*6]=mem_ba_dly[gen_mem*6+5:gen_mem*6];assign #CA_GROUP_TO_GROUP_DLY mem_cs_n_dly[2*gen_mem+3:2*gen_mem+2]=mem_cs_n_dly[2*gen_mem+1:2*gen_mem];assign #CA_GROUP_TO_GROUP_DLY mem_rst_n_dly[2*gen_mem+3:2*gen_mem+2]=mem_rst_n_dly[2*gen_mem+1:2*gen_mem];assign #CA_GROUP_TO_GROUP_DLY mem_ck_dly[2*gen_mem+3:2*gen_mem+2]=mem_ck_dly[2*gen_mem+1:2*gen_mem];assign #CA_GROUP_TO_GROUP_DLY mem_ck_n_dly[2*gen_mem+3:2*gen_mem+2]=mem_ck_n_dly[2*gen_mem+1:2*gen_mem];ddr3mem_core(.rst_n(mem_rst_n_dly[2*gen_mem+1:2*gen_mem]),.ck(mem_ck_dly[2*gen_mem+1:2*gen_mem]),.ck_n(mem_ck_n_dly[2*gen_mem+1:2*gen_mem]),.cs_n(mem_cs_n_dly[2*gen_mem+1:2*gen_mem]),.ras_n(mem_ras_n_dly[2*gen_mem+1:2*gen_mem]),.cas_n(mem_cas_n_dly[2*gen_mem+1:2*gen_mem]),.we_n(mem_we_n_dly[2*gen_mem+1:2*gen_mem]),.addr(mem_addr_dly[(ADDR_BITS*gen_mem+ADDR_BITS)*2-1:ADDR_BITS*gen_mem*2]),.ba(mem_ba_dly[gen_mem*6+5:gen_mem*6]),.odt(mem_odt_dly[2*gen_mem+1:2*gen_mem]),.cke(mem_cke_dly[2*gen_mem+1:2*gen_mem]),.dq(mem_dq[16*gen_mem+15:16*gen_mem]),.dqs(mem_dqs[2*gen_mem+1:2*gen_mem]),.dqs_n(mem_dqs_n[2*gen_mem+1:2*gen_mem]),.dm_tdqs(mem_dm[2*gen_mem+1:2*gen_mem]),.tdqs_n());end endgenerate initial begin sys_rst_n=1'b0;#100sys_rst_n=1'b1;end reg grs_n;//GTP_GRS I_GTP_GRS(GTP_GRSGRS_INST(.GRS_N(grs_n));initial begin grs_n=1'b0;#5grs_n=1'b1;end endmodule仿真需要用到ddr3.v和ddr3_paramters.vh文件,将这两个文件复制到你创建的tb路径下。
打开ddr3.v文件,将115行修改成`include “ddr3_parameters.vh”
3 将文件添加到工程
4 pds软件运行一次仿真
先设置modelsim的路径以及仿真库路径
再执行仿真,这一步仿真肯定会出错,这步是为了让软件生成一个tcl脚本,后面我们对脚本进行修改。
3 修改tcl脚本
脚本路径如下,我们主要关注run_behav_compile.tcl和run_behav_simulate.tcl
这里我不直接解决所有问题,一个个解决问题,方便告诉你为什么会报这个错误。
上图那个错误是由于没有进行宏定义,导致没有创建这个参数引起的错误,看案例工程的ctrl_phy_sim.tcl和sim_file_list.f可以知道vlog了以下宏
这里我们打开run_behav_compile.tcl,进行下面修改
重新运行仿真
好家伙,错误更多了。不要怕,我们接着分析。
这是由于这些文件受到了保护,所以没办法仿真,那官方例程又为什么能仿真呢,我们对比下
好嘛!原来是自动生成的路径引用错误,把rtl修改成sim_lib后重新运行仿真,注意不要漏了哦。
你会惊喜的发现,ddr_init_done拉高了