如何搭建SoC项目的基本Testbench(eetop)

合集下载

数字逻辑testbench描述

数字逻辑testbench描述
Rst = 1;
end
1 initial 2 begin 3 进程语句; 4 end
always块可用来模拟抽象的电路,包括:用以指定与不同结构之间的传播延 迟等同的时序结构;或等待指定事件的时序结构。敏感列表有时可忽略。 initail块仅在仿真之初执行,常用于设置变量的初始值。
⚫ 基本的Testbench结构
1 always块和initial块 ➢ 当always块用来描述组合逻辑时,应当使用阻塞赋值。例如
信号或变量定义声明 使用initial或always语句来产生激励波形 实例化设计模块 监控和比较输出响应
endmodule
⚫ 基本的Testbench结构
例:
1 `timescale 1ns/1ns 2 3 module logic_gates_tb; 4 5 reg i_a; 6 reg i_b; 7 wire o_and; 8 wire o_or; 9 wire o_not; 10 11 initial 12 begin 13 i_a = 0; 14 #40 i_a = 1; 15 #40 i_a = 0; 16 #40 i_a = 1; 17 #40 i_a = 0; 18 end
6 end
⚫ 产生激励的一些描述方式
2 产生复位信号的几种方式
➢ 异步复位
➢ 同步复位
1 initial
2 begin
3
Rst = 1;
4
#100;
5
Rst = 0;
6
#500;
7
Rst = 1;
8 end
1 2 3 4 5 6 7 8
initial
begin
Rst = 1; @(negedge clk); Rst = 0; #30; @(negedge clk);

如何编写testbench的总结

如何编写testbench的总结

空间管理您的位置: 中国电子顶级开发网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台 »多云转晴 »日志欢迎大家和我讨论Xilinx FPGA方面的问题如何编写testbench的总结(非常实用的总结)(转)上一篇 / 下一篇 2011-09-19 21:08:27 / 个人分类:FPGA知识查看( 23717 ) / 评论( 0 ) / 评分( 0/ 0) 1.激励的设置相应于被测试模块的输入激励设置为reg型,输出相应设置为wire类型,双向端口inout在测试中需要进行处理。

方法1:为双向端口设置中间变量inout_reg作为该inout的输出寄存,inout口在testbench中要定义为w ire型变量,然后用输出使能控制传输方向。

eg:inout [0:0] bi_dir_port;wire [0:0] bi_dir_port;reg [0:0] bi_dir_port_reg;reg bi_dir_port_oe;assign bi_dir_port=bi_dir_port_oe?bi_dir_port_reg:1'bz;用bi_dir_port_oe控制端口数据方向,并利用中间变量寄存器改变其值。

等于两个模块之间用inout双向口互连。

往端口写(就是往模块里面输入)方法2:使用force和release语句,这种方法不能准确反映双向端口的信号变化,但这种方法可以反映块内信号的变化。

具体如示:module test();wire data_inout;reg data_reg;reg link;#xx; //延时force data_inout=1'bx; //强制作为输入端口...............#xx;release data_inout; //释放输入端口endmodule从文本文件中读取和写入向量1)读取文本文件:用$readmemb系统任务从文本文件中读取二进制向量(可以包含输入激励和输出期望值)。

关于使用ModelSim中创建testbench方法

关于使用ModelSim中创建testbench方法

关于使用ModelSim中创建testbench方法
ModelSim中自动创建TestBench的方法
1. 创建工程,将需要仿真的模块加入工程,编译
2. File -> Open,使用ModelSim自带的文本编辑器打开被仿真模块
3. Source -> Show Language Templates
4. 在显示的Language Templates栏目中选择“Create Testbench”
5. 软件自动弹出的"Create Testbench Wizzard”窗口中,在"work"下选择待仿真模块,按照提示走完,即
自动生成
对于初学者来说写Testbench测试文件还是比较困难的,但Modelsim和quartus ii都提供了模板,下面就如何使用Modelsim提供的模板进行操作。

Modelsim提供了很多Testbench模板,我们直接拿过来用可以减少工作量。

对源文件编译完后,鼠标光标移到代码编辑窗后才会在菜单栏看到source选项,点Source->Show Language Templates然后会出现一个加载工程,接着你会发现在刚才的文档编辑窗口左边出现了一个Language Templates窗口,展开Verilog项,双击Creat Testbench会出现一个创建向导,展开工作目录添加目标文件,点击next,弹出testbench配置窗口,默认就行了,然后点击finish。

一个Testbench模板就诞生了,我们就可以在此编辑窗中添加激励代码了。

本次操作软件版本为modelsim alter starter edition 6.6d.。

Testbench基本入门

Testbench基本入门

Testbench入门1 编写testbench目的编写testbench的主要目的是为了对使用硬件描述语言(HDL)设计的电路进行仿真验证,测试设计电路的功能、部分性能是否与预期的目标相符。

编写testbench进行测试的过程如下:1)产生模拟激励(波形);2)将产生的激励加入到被测试模块并观察其输出响应;3)将输出响应与期望进行比较,从而判断设计的正确性。

2 基本的testbench结构module test_bench;// 通常testbench没有输入与输出端口信号或变量定义声明使用initial或always语句来产生激励波形例化设计模块监控和比较输出响应endmodule简单的testbench的结构通常需要建立一个顶层文件,顶层文件没有输入和输出端口。

在顶层文件里,把被测模块和激励产生模块实例化进来,并且把被测模块的端口与激励模块的端口进行对应连接,使得激励可以输入到被测模块。

端口连接的方式有名称和位置关联两种方式,我们常常使用“名称关联”方式。

3 产生激励的一些描写方式3.1 产生时钟的几种方式1)使用initial方式产生占空比50﹪的时钟initialbeginCLK = 0;#delay;forever#(period/2) CLK = ~CLK;end注意:一定要给时钟赋初始值,因为信号的缺省值为z,如果不赋初值,则反相后还是z,时钟就一直处于高阻z状态。

产生的时钟信号如下图所示:2)使用always方式initialCLK = 0;always#(period/2) CLK = ~CLK;3)使用repeat产生确定数目的时钟脉冲initialbeginCLK = 0;repeat(6)#(period/2) CLK = ~CLK;end该例使用repeat产生3个时钟脉冲,产生的波形如下:4)产生占空比非50﹪的时钟initialCLK = 0;alwaysbegin#3 CLK = ~CLK;#2 CLK = ~CLK;end3.2 产生复位信号的几种形式1)异步复位initialbeginRst = 1;#100;Rst = 0;#500;Rst = 1;end2)同步复位1initialbeginRst = 1;@(negedge CLK); // 等待时钟下降沿Rst = 0;#30;@(negedge CLK); // 等待时钟下降沿Rst = 1;end2)同步复位2initialbeginRst = 1;@(negedge CLK); // 等待时钟下降沿repeat (3) @(negedge CLK); // 经过3个时钟下降沿Rst = 1;end4 testbench实例4.1 2-4解码器实例module dec2x4(A, B, Enable, Z);input A, B, Enable;output[3:0] Z;reg [3:0] Z_o;assign Z = Z_o;always@(A or B or Enable)beginif(Enable == 1'b0)Z_o = 4'b1111;elsecase({A, B})2'b00: Z_o = 4'b1110;2'b01: Z_o = 4'b1101;2'b10: Z_o = 4'b1011;2'b11: Z_o = 4'b0111;default: Z_o = 4'b1111;endcaseendendmodule测试模块测试模块::`timescale 1ns/100psmodule testbench;reg a, b, en;wire [3:0] z;//例化被测试模块dec2x4 DUT(.A(a),.B(b),.Enable(en),.Z(z));//产生输入激励initialbeginen = 0;a = 0;b = 0;#10 en = 1;#10 b = 1;#10 a = 1;#10 b = 0;#10 a = 0;#10 $stop;end//显示输出结果always@(en or a or b or z)begin$display("At time %t, input is %b%b%b, output is %b", $time, a, b, en, z);endendmodule下面是测试模块执行时产生的输出和功能仿真波形:4.2 时序检测器下面是一个时序检测器的验证实例。

北大数字集成电路课件--15_Verilog-testbench的写法

北大数字集成电路课件--15_Verilog-testbench的写法
数字集成电路设计入门 --从HDL到版图
于敦山
北大微电子学系
Bench使用简介 第十五章 Verilog Test Bench使用简介
学习内容: 学习内容: • 用一个复杂的 用一个复杂的test bench复习设计的组织与仿真 复习设计的组织与仿真 • 建立 建立test bench通常使用的编码风格及方法 通常使用的编码风格及方法
数组激励
• 从数组产生激励有以下特性: 从数组产生激励有以下特性: 在每次反复中, 在每次反复中,修改同一组激励变量 激励数组可以直接从文件中读取
module array_ tb; reg [7: 0] data_ bus, stim_ array[ 0: 15]; // 数 组 integer i; DUT u1 (results, stimulus); initial begin // 从数组读入数据 #20 stimulus = stim_array[0]; #30 stimulus = stim_array[15]; // 线激励 #20 stimulus = stim_array[1]; for (i = 14; i > 1; i = i - 1) // 循环 #50 stimulus = stim_array[i] ; #30 $finish; end endmodule
在上面的例子中,公共参数在一个独立的文件中定义。 在上面的例子中,公共参数在一个独立的文件中定义。此文件在不同 的仿真中可被不同的测试文件调用。 的仿真中可被不同的测试文件调用。
施加激励
种方法。一些常用的方法有: 产生激励并加到设计有很多 种方法。一些常用的方法有: • 从一个 从一个initial块中施加线激励 块中施加线激励 • 从一个循环或 从一个循环或always块施加激励 块施加激励 • 从一个向量或整数数组施加激励 • 记录一个仿真过程,然后在另一个仿真中回放施加激励 记录一个仿真过程,

如何写testbench

如何写testbench

如何编写testbench今天,我来带领大家写一个简单的testbench ,顺便讲解如何写好一个testbench 以及写testbench 时应该注意的地方。

在讲解testbench 之前,我们先看一下前面的那个AND_2程序的仿真图,如下:如上图中所标,在1处,B 已经为低电平了,但是输出C 仍然为高电平,这样求与运算就会出错。

在2处,A 和B 都是低电平了,C 仍然为高电平,直到下次出现时钟的上升沿为止,为什么会这样呢?编译的时候并没有报错,呵呵,出了怪事了啊!其实编译器只能检查处语法错误,无法检测到逻辑错误,这个图给出的结果和我们程序所表达的结果一样,但是这并不是我们所要的求与运算,我们想要的是A 和B 同时为高电平时,C 才输出高电平。

我们把程序的敏感列表改为:always@(posedge clk or negedge rst or A or B)就可以了,把A 的电平改变和B的电平改变都加进敏感列表,激励不变,所得到的仿真图:这才是我们所要的求与运算!好了,现在开始讲如何写testbench 。

Testbench 不像RTL 级代码,可以用高级行为语句,不用考虑其可综合性,这样就能写出高效的检测代码。

在语法上,testbench 和可综合代码一样,都是类C 结构。

好了,我们开始吧!1,建立工程等,与之前的一样,但是在创建文件的时候,我们一次创建两个。

取名分别为ParallelSerial_Mult 和ParallelSerial_Mult_test。

创建完成后,如下图:这两个代码分别如下:moduleParallelSerial_Mult(Clk,Rst,MultiplicandIn,MultiplierIn,Load,Product,Out_en);parameter N=8;parameter CYCLES=3;input Clk,Rst,Load;input[N-1:0]MultiplicandIn,MultiplierIn;output[2*N-1:0]Product;output Out_en;reg[2*N-1:0]Product;wire Out_en;reg[N-1:0]Multiplicand;reg[2*N-1:0]NextProduct;reg[CYCLES:0]Count;reg Busy;wire[N-1:0]Sum;wire Carry;assign{Carry,Sum}=Multiplicand+Product[2*N-1:N];assign Out_en=Count[CYCLES];always@(posedge Clk or negedge Rst)if(!Rst)beginMultiplicand<=0;Count<=0;Product<=0;Busy<=0;endelsebeginProduct<=NextProduct;if(Load)beginMultiplicand<=MultiplicandIn;Count<=0;Busy<=1'b1;endelsebeginif(Busy)Count<=Count+1'b1;if(Count[CYCLES])beginCount<=0;Busy<=1'b0;endendendalways@(Load or MultiplierIn or Product or Count[CYCLES]or Carry or Sum) casex({Product[0],Count[CYCLES],Load})3'bxx1:NextProduct={{N{1'b0}},MultiplierIn[N-1:0]};3'b100:NextProduct={Carry,Sum,Product[N-1:1]};3'b000:NextProduct={1'b0,Product[2*N-1:1]};default:NextProduct=Product;endcaseendmodule这个代码是书中第120页的8位乘法器。

简单的Testbench设计

简单的Testbench设计

//被测设计的输入信号,对应测试脚本的输出信号(注意要定义成 reg) reg clk; reg rst_n; //被测设计的输出信号,对应测试脚本的输入信号(注意要定义成 wire) wire led; //例化待测模块 Led led_test
简单的 Testbench nch 是一种验证的手段。首先,任何设计都是会有输入输出的。 但是在软环境中没有激励输入,也不会对你设计的输出正确性进行评估。那 幺此时便有一种,模拟实际环境的输入激励和输出校验的一种“虚拟平台”的 产生。在这个平台上你可以对你的设计从软件层面上进行分析和校验,这个 就是 testbench 的含义。 简单的 Testbench 设计 //timescale 仿真时间单位/时间精度(时间精度不能比时间单位还要 大) timescale 1ns/1ps //定义一个无输入无输出的 Moudle module Led_clg_tst();
( .clk(clk), .rst_n(rst_n), .led(led) ); //使用 Initail 生成 rst_n 激励 initial begin //监控 Led 信号变化
monitor(monitor(time,”led value= %b\n”,led); end //使用 alwasys 模拟产生 25M 的时钟信号 always #20 clk = ~clk; endmodule

vivado testbench 语法

vivado testbench 语法

在 Vivado中,编写 Testbench 是进行数字电路仿真和验证的重要步骤。

以下是 Vivado Testbench 的一些语法要点:1. 语言选择:Vivado支持使用 SystemVerilog 或 Verilog 作为 Testbench 的语言。

你可以根据需要选择其中之一进行编写。

2. 模块实例化:Testbench 通常包含一个顶层模块来实例化待测试的模块。

你需要创建一个模块,并使用待测试模块的端口信号进行实例化。

3. 时钟和复位:在 Testbench 中,你通常需要生成时钟信号和复位信号,并将其应用于待测试模块的输入端口。

你可以使用 `fork...join` 结构和 `repeat` 或 `forever` 循环来生成时钟信号。

4. 输入模拟:在 Testbench 中,你需要为待测试模块的输入端口提供合适的模拟数据。

你可以使用 `#` 操作符来延迟信号的更新,以模拟不同的输入情况。

5. 断言和检查:在 Testbench 中,你可以使用断言语句来验证待测试模块的行为是否符合预期。

Vivado 支持使用 `assert` 和 `assume` 等关键字来定义断言。

6. 输出比较:在仿真结束后,你可以比较待测试模块的输出信号与预期结果进行验证。

你可以使用 `$display` 或 `$monitor` 等系统任务来显示输出信号的值。

7. 仿真控制:你可以使用 `initial` 块或 `always` 块来控制 Testbench 的仿真行为。

你可以使用 `#` 操作符来延迟仿真时间或 `disable` 关键字来停止仿真。

8. 仿真时长:在 Vivado 中,你可以使用 `run` 或 `run XXns` 命令来指定仿真运行的时长。

默认情况下,仿真会一直运行直到遇到 `$finish` 或 `$stop` 系统任务。

以上是 Vivado Testbench 的一些语法要点。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

先啰嗦几句。

其实老早就想写这个帖子,自己犯懒一直木有写。

前阵子写了一个初版,然后发给了几个做验证的朋友看了看,普遍反映没看明白. 说是我写的东西和我搭的环境结合的太过紧密了,不结合代码,理解的不透彻。

可惜代码是公司的,我不能把代码发出来。

我后来写了一个带很多代码截屏的版本,但是很抱歉没法发到论坛上来。

我个人觉得下面的文字已经能表达我的想法和思想了,希望能对帖的有一点帮助吧。

---------------------------------------------写这个文档的目的是让大家对搭建SoC项目的Testbench有一个比较清晰的认识,可以根据这个文档来一步一步的搭建起一个SoC项目的基本的testbench。

本文档重点是指导大家搭建基本环境,以及能解决搭建Testbench过程中容易遗漏的问题或者容易遇到的“地雷”。

我搭的SoC项目的testbench会有一些相对特殊的点:1)要有嵌入式的软件。

这里包括两部分,一是初始化的bootloader(一般是固化在rom或者存放在外部的flash里),一是boot起来以后放在外部易失性存储介质上的应用层的程序。

2)正常启动起来(一级boot可以切到应用程序了)以后,为了简化流程,我们要使用ISS的环境。

--- 这是比较特殊的一个点3)环境主要脚本的维护和修改。

主要是单个仿真和批量仿真(regression)核心脚本4)为了优化仿真和编译速度,我们要能把不用的模块dummy掉。

5)文件列表的处理6)SoC软件与Testbench都能访问的“共享空间”的处理7)公用函数的准备,比如根据CPU看到的地址空间直接访问外部DRAM的数组,进行初始化写、数据写和数据读操作。

8)环境变量的维护。

9)Define文件的维护10)DDRC的替换(一个是AXI_SLV_VIP的替换,一个是简单AXI_SLV模型的替换)磨刀不误砍柴工,把需要的东西提前准备好,搭建Testbench就像搭积木一样简单快速了。

环境变量维护使用module工具来维护整个项目的环境变量。

目的是为了让项目上的工程师都使用统一的环境(主要是工具版本和环境变量)。

核心脚本的维护两个脚本:run_sim 和regress。

run_sim负责提交单个仿真任务,regress负责提交批量仿真任务。

两个脚本已经使用了很多项目了,脚本的具体说明我以后专门开专题讲。

在这里只提醒一下,run_sim脚本通常需要根据不同的项目做微小的改变。

run_sim和regress都是比较大的perl脚本程序,大致描述一下功能。

run_sim脚本功能1)为每个仿真产生仿真目录。

仿真的目录里应该包括文件列表(硬件和软件)、编译和仿真命令(注意包括嵌入式软件的MakeFile)、提前建立需要的子目录、和单个仿真对应的文件链接(比如维护的C的测试主函数、扩展的随机类的SV文件、一级bootloader文件的链接)、define文件、本仿真的重构命令(这是一个容易忽略的,一旦你跑regression的时候某个仿真失败,你又不想在出错的目录下重新仿真,用这个重构命令文件就可以直接提交)。

2)各种option的维护。

比如不同仿真需要不同的define、编译和运行option、dump波形的scope以及层次regress脚本功能regress脚本比较简单,要吃一个由很多run_sim仿真命令组成的命令集文件。

用regress 脚本把这些仿真命令提交到工作站上去。

需要注意的是:有时候可能会有一些公共的option 或者define,比如打开coverage收集、某个define要应用到整个regression里。

所以regress脚本要能支持对所有run_sim命令添加option的功能。

产生dummy文件使用gen_dummy_file脚本来产生dummy文件。

设计工程师可能也要维护一个module_dummy.v的文件用于做integeration,验证工程师产生的dummy文件记得名字不要和设计自己维护的文件重复了。

为什么不使用设计维护的文件?因为一个是设计维护的文件在integration以后很可能就不再维护了;另一个是设计维护的文件可能output全是assign成0的,但是对于模块输出的pready\CEN等信号最好assign成1,否则可能导致问题(例如:sram使能信号CEN赋成0,可能导致后面的sram模型认为有读写行为;pready信号赋成0,可能导致SoC软件跑起来的时候对该模块寄存器操作的时候挂死apb总线)。

这个脚本并不好写。

因为verilog语法支持的模块声明实在是太多了,导致脚本很容易顾此失彼。

举例来说几个复杂的地方:module声明后面可以跟parameter的就很复杂Module test #(parameter a = 1,Parameter b = 2,C = 3,D = 4 );这些parameter很可能要用在端口位宽的声明里。

更为麻烦的是parameter里可能会有function的使用。

而function有可能是以define的形式写到代码中。

这样就很难用parse RTL的方法来解决。

再比如:端口声明里出现ifdef else endif这种编译宏的处理也比较麻烦。

也可以使用simulator或者debug工具提供的用户接口来编写tcl程序来获取各个端口的name、width信息。

但是不同仿真(define不同)可能导致端口宽度和端口不一致,结果要针对不同define来维护不同的dummy也比较麻烦。

总之,产生dummy文件以后一定要记得检查一下。

Dummy文件可以有效缩短编译的时间。

文件列表处理的维护上述几个事情是应该提前准备好的,接下来我们要开始编译RTL了。

Integration好的文件列表,首先要先编译该文件列表。

有可能遇到的问题是加密文件的种类,有可能文件列表里的加密文件和你用的仿真器不一致。

然后结合前面产生好的dummy文件,我们要处理出一个简化设计的mini-文件列表,一般里面只包括初始化必须的模块(Clkrst、PAD、CPU、总线拓扑、内存控制器),也就是把video系统、外围接口、存储系统这些模块统统dummy掉。

产生mini-文件列表可以用脚本来维护一个配置文件,在该配置文件中指明如何删改原有文件列表。

注意最终使用的文件列表里的文件路径应该是绝对路径。

使用绝对路径的好处在于可以让run_sim脚本指定仿真在任何目录下进行(比如regression 要提交到别的硬盘上去跑,那么就必须使用绝对路径了)。

注意绝对路径里不要用$macro的结构,别人有可能用你的文件列表跑仿真或者debug,而别人的$macro很可能与你的不同,导致出问题。

文件列表的产生有一个地方需要注意:通常来说一个文件(比如a.v)在一个文件列表里只允许出现一次。

否则可能会有重复module 的编译错误。

但是有时候集成比较特殊(比如FPGA版本),为了改动的时候少调整code,会使用ifdef-elsif-else-endif这种结构来对同一个文件的module定义不同的module-name。

比如文件a.v的内容如下:`ifdef FPGA1module v_fpga1 (`elsif FPGA2module v_fpga2 (`elsif FPGA3module v_fpga3 (`elsemodule v (`endif那么在文件列表里就会是下面这种结构:fpga1_def.va.vfpga1_undef.vfpga2_def.va.vfpga2_undef.v……请注意文件列表处理脚本,有可能会有“去重”的处理。

这个时候要去掉文件列表处理脚本的“去重”功能。

编译过mini-文件列表以后就可以开始真正的准备写testbench顶层模块了。

Define文件的维护我们在搭建testbench过程中的interface、env、svtb等可能需要xmr(cross module reference)访问信号,这时候维护一个公共的define文件很重要。

该define文件中应该包括1)各个主要模块的xmr路径define ,记得按照ASIC/ FPGA/模块级来分别区分define2)地址空间上模型数组的路径。

比如dram模型里数组的xmr路径、sram里memory数组的xmr 路径3)共享空间的部分地址的define,比如我们的软件打印的实现所用到的共享空间的define 4)Dram基本define共享空间SoC项目Testbench中的“共享空间”,是指的软件(嵌入式C程序)和Testbench(SV程序)都可以看到的空间。

一般来说Testbench可以看到所有的内容,而软件只能看到CPU 地址空间(寄存器、SRAM、ROM、Dram、外部IO空间等)。

共享空间需要的地址范围不算小(可能需要几十KB,所以一般是放在CPU可见的SRAM和Dram里),对于ISS会有所不同(后面会说明)。

公共函数的维护项目上大家都可能使用到的函数即为“公共函数”。

我个人认为最重要的是对CPU地址空间的访问(我们是xmr_read_mem和xmr_write_mem)。

以及基于这几个函数(task)实现的文件存取等函数。

在实现xmr_read_mem和xmr_write_mem task(或function)的时候,主要模型数组的宽度会导致根据模型数组下标访问的地址的不同。

比如,加入位宽是128bit,那么一个memory就对应着4个32bit的word。

----- 各个项目会有所不同。

另外,对于Dram的处理是最复杂的,尤其是Dram是支持bank地址和Row地址 remap的,所以要特别注意remap时候的地址和bank信号、row地址信号的对应关系。

-----这个工作是可以继承前面项目的。

Xmr函数需要考虑“用SRAMC或者AXI_SLV_VIP替换DDRC”情况下的实现。

简单说一下vip_slave_write32函数的实现。

这个函数调的底层函数是:env.axi_slave_subenv.do_write32(addr, data);但是该函数在tb其他组件可能看不到,但是program可以看到。

所以在program里做一个函数来调底层的env.axi_slave_subenv.do_write32然后把program的这个do_write32用DPI export出去。

在tb上维护一个xmr.c的c程序,里面实现vip_slave_write32。

在xmr_wr_mem32里调用的就是这个vip_slave_write32.使用xmr_wr_mem32 和 xmr_rd_mem32可以比较容易的实现:1)装入初始化程序 --- 一级bootloader要装入到rom中,应用程序要装入到dram中。

相关文档
最新文档