• 电力电子转战数字IC20220629day35——路科实验2b


    目录

    tb3代码改造

    tb3代码

    tb4改造思路:

    tb4结构示意图

     tb4代码

     basic_test

     burst_test

     full_test


     首先复习一下类的知识点

    CSDNhttps://mp.csdn.net/mp_blog/creation/editor/125286941CSDNhttps://mp.csdn.net/mp_blog/creation/editor/125254965

    tb3代码改造

    • 接口和时钟块不变
    • 变量限定为local
    • 端口列表的接口放下来用virtual
    • 初始化用new函数
    • 类里面的变量都是动态变量,不用加automatic了
    • 用到的方法和变量都加上this表示这个当前类的,防止同名问题
    • 用函数将接口给到initiator中
    • 单独的一个类ch_trans来封装发送出去的数据,输送数据的task的输入变成这个类的句柄,而不是原来的标量data,里面的data需要加上句柄索引
    • 队列从存放数据变为存放句柄
    • 生成数据的函数最终返回句柄t
    • 例化initiator时不用再加入接口参数,例化generator不用括号
    • 在initial块中对三个通道的initiator和generator进行初始化和连接到接口上,在三个test中就不用了再做这一步骤了(原本是每个test都需要调用函数来进行初始化)

    tb3代码

    1. `timescale 1ns/1ps
    2. //*********************用类class来改造**************************//
    3. //**********************接口和时钟块不变****************************//
    4. interface interface_chen (input clk, input rstn);
    5. logic [31:0] channel_data;
    6. logic channel_valid;
    7. logic channel_ready;
    8. logic [ 7:0] slave_margin;
    9. clocking drv_clk @(posedge clk);
    10. default input #1ns output #1ns;
    11. input channel_ready, slave_margin;//采样
    12. output channel_data, channel_valid;//驱动
    13. endclocking
    14. endinterface
    15. //**************************************************//
    16. class ch_trans;
    17. int data;
    18. int id;
    19. int num;
    20. endclass
    21. //**************************************************//
    22. class initiator_chen;
    23. virtual interface_chen intf;//virtual表示在子类中会被调用到,声明类的成员变量接口指针必须用virtual
    24. local int idle_cycle;
    25. local string name;
    26. function new(string name="initiator_chen");//这里其实就是初始化
    27. this.name=name;
    28. this.idle_cycle=1;
    29. endfunction
    30. //类里面所有变量都是动态变量,不需要加automatic了
    31. function void set_idle_cycle(int n);
    32. this.idle_cycle=n;
    33. endfunction
    34. function void set_name(string s);
    35. this.name=s;
    36. endfunction
    37. //这里替代的是三个接口的例化
    38. function void set_interface(virtual interface_chen intf);
    39. if(intf==null)
    40. $error("null, need to be intantiated.");
    41. else this.intf=intf;
    42. endfunction
    43. task chnl_write (input ch_trans t);//数据封装在ch_trans里面,这个类的句柄声明为t
    44. @(posedge intf.clk);
    45. intf.drv_clk.channel_valid<=1'b1;
    46. intf.drv_clk.channel_data<=t.data;//data要加t.引用
    47. @(negedge intf.clk);
    48. wait(intf.channel_ready==1'b1);
    49. $display("%t channel initial [%s] sent data %x", $time, name, t.data);
    50. repeat (this.idle_cycle) channel_idle();
    51. endtask
    52. task channel_idle();
    53. @(posedge intf.clk);
    54. intf.drv_clk.channel_valid<=1'b0;
    55. intf.drv_clk.channel_data<=1'b0;
    56. endtask
    57. endclass
    58. //**************************************************//
    59. class generator_chen;
    60. ch_trans trans[$];//存放ch_trans句柄的队列
    61. ch_trans t;//声明句柄
    62. int num;
    63. int id;
    64. function new(int n);//替代原来的初始化函数,完成初始化
    65. this.id=n;
    66. this.num=0;
    67. endfunction
    68. //替代生成数据的func get_data
    69. function ch_trans get_trans();//类的句柄函数
    70. t=new();//对类进行例化,创建一个名为t的ch_trans对象
    71. t.data='h00C0_00000+(this.id<<16)+this.num;
    72. t.id=this.id;//把gen的id赋给ch_trans的id
    73. t.num=this.num;
    74. this.num++;
    75. this.trans.push_back(t);
    76. return t;
    77. endfunction
    78. endclass
    79. //**************************************************//
    80. module tb1_chen();//由于tb对接的是mcdt,所以还是用mcdt定义的那些信号名,输入换成reg,输出换成wire
    81. logic clk;
    82. logic rstn;
    83. logic [31:0] mcdt_data_output;
    84. logic mcdt_valid;
    85. logic [1:0] mcdt_id;
    86. //**************mcdt-接口-generator************************//
    87. interface_chen ch1_intf(.*);//必须用接口名才不会报错,不能用intf
    88. interface_chen ch2_intf(.*);
    89. interface_chen ch3_intf(.*);
    90. //将接口分成3份。分别对应mcdt的信号
    91. mcdt_chen dut(//括号里面的信号变成接口里面的
    92. .clk(clk)
    93. ,.rstn(rstn)
    94. ,.channel1_data(ch1_intf.channel_data)//信号改为接口中的名称
    95. ,.channel1_valid(ch1_intf.channel_valid)
    96. ,.slave1_margin(ch1_intf.slave_margin)
    97. ,.channell_ready(ch1_intf.channel_ready)
    98. ,.channel2_data(ch2_intf.channel_data)
    99. ,.channel2_valid(ch2_intf.channel_valid)
    100. ,.channel2_ready(ch2_intf.channel_ready)
    101. ,.slave2_margin(ch2_intf.slave_margin)
    102. ,.channel3_data(ch3_intf.channel_data)
    103. ,.channel3_valid(ch3_intf.channel_valid)
    104. ,.channel3_ready(ch3_intf.channel_ready)
    105. ,.slave3_margin(ch3_intf.slave_margin)
    106. ,.mcdt_data_output(mcdt_data_output)
    107. ,.mcdt_valid(mcdt_valid)
    108. ,.mcdt_id(mcdt_id)
    109. );
    110. //*****************clk和rstn******************************//
    111. task clk_gen(input int T);
    112. clk <= 0;
    113. forever begin
    114. #(T/2) clk<= !clk;
    115. end
    116. endtask
    117. initial begin
    118. clk_gen(10);
    119. end
    120. task rstn_gen();
    121. #10 rstn <= 0;
    122. repeat(20) @(posedge clk);
    123. rstn <= 1;
    124. endtask
    125. initial begin
    126. rstn_gen();
    127. end
    128. //**************************************************//
    129. generator_chen ch1_gen;
    130. generator_chen ch2_gen;
    131. generator_chen ch3_gen;
    132. //将generator分成3份。分别对应mcdt的信号
    133. initiator_chen ch1_init;
    134. initiator_chen ch2_init;
    135. initiator_chen ch3_init;
    136. //将initiator分成3份
    137. //*******************以上不变*********************//
    138. initial begin
    139. //命名和初始化3个通道,test里面的都可以删掉了
    140. ch1_init=new("ch1_init");
    141. ch2_init=new("ch2_init");
    142. ch3_init=new("ch3_init");
    143. ch1_gen=new(1);
    144. ch2_gen=new(2);
    145. ch3_gen=new(3);
    146. //接口给到initiator,连接了
    147. ch1_init.set_interface(ch1_intf);
    148. ch2_init.set_interface(ch2_intf);
    149. ch3_init.set_interface(ch3_intf);
    150. $display("********all of tests have been finished***********");
    151. //basic_test();
    152. //burst_test();
    153. full_test();
    154. $finish();
    155. end
    156. //*****************************3个test**********************************//
    157. //1. idle_cycle在1-3之间,每个通道发送200个数据,都完成后就结束
    158. task automatic basic_test();
    159. //设置idle_cycle
    160. ch1_init.set_idle_cycle($urandom_range(1,3));
    161. ch2_init.set_idle_cycle($urandom_range(1,3));
    162. ch3_init.set_idle_cycle($urandom_range(1,3));
    163. $display("basic_test initialized components");
    164. wait (rstn===1'b1);
    165. repeat(5) @(posedge clk);
    166. $display("basic_test started testing dut");
    167. fork
    168. repeat(100) ch1_init.chnl_write(ch1_gen.get_trans());
    169. repeat(100) ch2_init.chnl_write(ch2_gen.get_trans());
    170. repeat(100) ch3_init.chnl_write(ch3_gen.get_trans());
    171. join
    172. fork
    173. wait(ch1_init.intf.slave_margin=='hff);
    174. wait(ch2_init.intf.slave_margin=='hff);
    175. wait(ch3_init.intf.slave_margin=='hff);
    176. join
    177. $display("finished");
    178. endtask
    179. //2.idle为0,每个通道发送500个数据
    180. task automatic burst_test();
    181. //设置idle_cycle
    182. ch1_init.set_idle_cycle(0);
    183. ch2_init.set_idle_cycle(0);
    184. ch3_init.set_idle_cycle(0);
    185. $display("burst_test initialized components");
    186. fork
    187. repeat(500) ch1_init.chnl_write(ch1_gen.get_trans());
    188. repeat(500) ch2_init.chnl_write(ch2_gen.get_trans());
    189. repeat(500) ch3_init.chnl_write(ch3_gen.get_trans());
    190. join
    191. fork
    192. wait(ch1_init.intf.slave_margin=='hff);//256-200=56转换成十六进制?
    193. wait(ch2_init.intf.slave_margin=='hff);//但其实是说直到空了,也就是全部数据都读完
    194. wait(ch3_init.intf.slave_margin=='hff);
    195. join
    196. $display("finished");
    197. endtask
    198. //3. 所有通道都装满的时候停止,不需要同时达到
    199. task automatic full_test();
    200. //设置idle_cycle
    201. ch1_init.set_idle_cycle(0);
    202. ch2_init.set_idle_cycle(0);
    203. ch3_init.set_idle_cycle(0);
    204. $display("full_test initialized components");
    205. fork: fork_all_run
    206. forever ch1_init.chnl_write(ch1_gen.get_trans());
    207. forever ch2_init.chnl_write(ch2_gen.get_trans());
    208. forever ch3_init.chnl_write(ch3_gen.get_trans());
    209. join_none//这个fj执行的时候下面的fj也开始执行
    210. $display("running, waiting full");
    211. fork
    212. wait(ch1_init.intf.slave_margin=='h0);//满了就执行下面的,不用等其他的满
    213. wait(ch2_init.intf.slave_margin=='h0);
    214. wait(ch3_init.intf.slave_margin=='h0);
    215. join
    216. $display("full");
    217. disable fork_all_run;//让none那个停下来,别写入数据了
    218. fork
    219. ch1_init.channel_idle();
    220. ch2_init.channel_idle();
    221. ch3_init.channel_idle();
    222. join
    223. $display("waiting all data transferred");
    224. $display("finished");
    225. endtask
    226. endmodule

     编译和仿真都可以了。

     复习一下package的知识点

    CSDNhttps://mp.csdn.net/mp_blog/creation/editor/125289909要求4是加入包以及用类的继承来做3个test

    tb4改造思路:

    • 所有的class都封装在package里面,包括trans, gen,init,agent,root_test,basic_test,burst_test, full_test
    • trans, initiator, generator不用变动
    • agent中包含init和gen的句柄,标志数据个数的变量ntrans,通过将接口代入set_interface和initiator连接,将ntrans作为参数和generator连接,分别是发送和产生数据。
    • 将3个test中相同的部分放到root_test中,包括设置数据个数ntrans和名字name,声明3个agent句柄,例化每个agent,运行起来run,需要将接口连接到3个句柄上
    • 3个test作为子类继承root_test
    • 3个test只需要设置ntrans和name和idle_cycle即可,并分别给到父类中的new函数。
    • 第3个test还是需要用fork_join_none继续写
    • 以上就是包的内容
    • 在tb这个module中,依然是例化mcdt+产生时钟信号+产生复位信号+例化接口。
    • 在tb这个module中,要先用import引入所有类(module是硬件盒子),然后才能声明3个test的句柄,并例化。然后将3个接口作为参数给到3个句柄中的set_interface,由于3个test中没有这个函数,所以往父类root_test中寻找,给到agent的set_interface,再给到initiator的set_interface,由此完成了信号的层层传递。
    • 最后调用3个句柄中的run,也就是各自test中的run,跑起来了

    tb4结构示意图

     

     tb4代码

    1. `timescale 1ns/1ps
    2. //*********************用包package来改造**************************//
    3. //**********************接口和时钟块不变****************************//
    4. interface interface_chen (input clk, input rstn);
    5. logic [31:0] channel_data;
    6. logic channel_valid;
    7. logic channel_ready;
    8. logic [ 7:0] slave_margin;
    9. clocking drv_clk @(posedge clk);
    10. default input #1ns output #1ns;
    11. input channel_ready, slave_margin;//采样
    12. output channel_data, channel_valid;//驱动
    13. endclocking
    14. endinterface
    15. //**************************************************//
    16. package ch_pkg;
    17. //**************************************************//
    18. class ch_trans;
    19. int data;
    20. int id;
    21. int num;
    22. endclass
    23. //**************************************************//
    24. class initiator_chen;
    25. virtual interface_chen intf;//virtual表示在子类中会被调用到,声明类的成员变量接口指针必须用virtual
    26. local int idle_cycle;
    27. local string name;
    28. function new(string name="initiator_chen");//这里其实就是初始化
    29. this.name=name;
    30. this.idle_cycle=1;
    31. endfunction
    32. //类里面所有变量都是动态变量,不需要加automatic了
    33. function void set_idle_cycle(int n);
    34. this.idle_cycle=n;
    35. endfunction
    36. function void set_name(string s);
    37. this.name=s;
    38. endfunction
    39. //这里替代的是三个接口的例化
    40. function void set_interface(virtual interface_chen intf);
    41. if(intf==null)
    42. $error("null, need to be intantiated.");
    43. else this.intf=intf;
    44. endfunction
    45. task chnl_write (input ch_trans t);//数据封装在ch_trans里面,这个类的句柄声明为t
    46. @(posedge intf.clk);
    47. intf.drv_clk.channel_valid<=1'b1;
    48. intf.drv_clk.channel_data<=t.data;//data要加t.引用
    49. @(negedge intf.clk);
    50. wait(intf.channel_ready==1'b1);
    51. $display("%t channel initial [%s] sent data %x", $time, name, t.data);
    52. repeat (this.idle_cycle) channel_idle();
    53. endtask
    54. task channel_idle();
    55. @(posedge intf.clk);
    56. intf.drv_clk.channel_valid<=1'b0;
    57. intf.drv_clk.channel_data<=1'b0;
    58. endtask
    59. endclass
    60. //**************************************************//
    61. class generator_chen;
    62. ch_trans trans[$];//存放ch_trans句柄的队列
    63. ch_trans t;//声明句柄
    64. int num;
    65. int id;
    66. function new(int n);//替代原来的初始化函数,完成初始化
    67. this.id=n;
    68. this.num=0;
    69. endfunction
    70. //替代生成数据的func get_data
    71. function ch_trans get_trans();//类的句柄函数
    72. ch_trans t=new();//对类进行例化,创建一个名为t的ch_trans对象
    73. t.data='h00C0_00000+(this.id<<16)+this.num;
    74. t.id=this.id;//把gen的id赋给ch_trans的id
    75. t.num=this.num;
    76. this.num++;
    77. this.trans.push_back(t);
    78. return t;
    79. endfunction
    80. endclass
    81. //**************************************************//
    82. class ch_agent;
    83. generator_chen gen;
    84. initiator_chen init;
    85. local int ntrans;
    86. virtual interface_chen aintf;
    87. function new(string name="ch_agent", int id=0, int ntrans=1);
    88. this.gen=new(id);
    89. this.init=new(name);
    90. this.ntrans=ntrans;
    91. endfunction
    92. function void set_n_trans(int n);
    93. this.ntrans=n;
    94. endfunction
    95. function void set_interface(virtual interface_chen aintf);
    96. this.aintf=aintf;
    97. init.set_interface(aintf);
    98. endfunction
    99. task run();
    100. repeat(this.ntrans) this.init.chnl_write(this.gen.get_trans);
    101. this.init.channel_idle();
    102. endtask
    103. endclass
    104. //**************************************************//
    105. class root_test;
    106. ch_agent agent[3];//声明3个agent数组
    107. protected string name;
    108. function new(int ntrans=100, string name ="ch_root_test");
    109. foreach(agent[i]) begin
    110. this.agent[i]=new($sformatf("ch_agent%0d",i),i,ntrans);
    111. end
    112. this.name=name;
    113. $display("%s instantiate objects",this.name);
    114. endfunction
    115. task run();
    116. $display("%s started testing dut", this.name);
    117. fork
    118. agent[0].run();
    119. agent[1].run();
    120. agent[2].run();
    121. join
    122. $display("%s waiting", this.name);
    123. fork
    124. wait(agent[0].aintf.slave_margin=='hff);
    125. wait(agent[1].aintf.slave_margin=='hff);
    126. wait(agent[2].aintf.slave_margin=='hff);
    127. join
    128. $display("%s finished all data", this.name);
    129. endtask
    130. function void set_interface(virtual interface_chen ch1_aintf
    131. ,virtual interface_chen ch2_aintf
    132. ,virtual interface_chen ch3_aintf);
    133. agent[0].set_interface(ch1_aintf);
    134. agent[1].set_interface(ch2_aintf);
    135. agent[2].set_interface(ch3_aintf);
    136. endfunction
    137. endclass
    138. class basic_test extends root_test;
    139. function new(int ntrans=200, string name="basic_test");
    140. super.new(ntrans, name);
    141. foreach(agent[i]) begin
    142. this.agent[i].init.set_idle_cycle($urandom_range(1,3));
    143. end
    144. $display("%s configured objects", this.name);
    145. endfunction
    146. endclass: basic_test
    147. class burst_test extends root_test;
    148. function new(int ntrans=500, string name="burst_test");
    149. super.new(ntrans,name);
    150. foreach(agent[i]) begin
    151. this.agent[i].init.set_idle_cycle(0);
    152. end
    153. $display("%s configured objects", this.name);
    154. endfunction
    155. endclass: burst_test
    156. class full_test extends root_test;
    157. function new(int ntrans=1000000, string name="full_test");
    158. super.new(ntrans, name);
    159. foreach(agent[i]) begin
    160. this.agent[i].init.set_idle_cycle(0);
    161. end
    162. $display("%s configured objects", this.name);
    163. endfunction
    164. task run();
    165. $display("%s started testing dut", this.name);
    166. fork :fork_all_run
    167. agent[0].run();
    168. agent[1].run();
    169. agent[2].run();
    170. join_none
    171. $display("%s 3agents running, waiting full", this.name);
    172. fork
    173. wait(agent[0].aintf.slave_margin=='h0);
    174. wait(agent[1].aintf.slave_margin=='h0);
    175. wait(agent[2].aintf.slave_margin=='h0);
    176. join
    177. $display("%s full, stop", this.name);
    178. disable fork_all_run;
    179. $display("%s all idle", this.name);
    180. fork
    181. agent[0].init.channel_idle();
    182. agent[1].init.channel_idle();
    183. agent[1].init.channel_idle();
    184. join
    185. $display("%s waiting", this.name);
    186. fork
    187. wait(agent[0].aintf.slave_margin=='hff);
    188. wait(agent[1].aintf.slave_margin=='hff);
    189. wait(agent[2].aintf.slave_margin=='hff);
    190. join
    191. $display("%s finished all data", this.name);
    192. endtask
    193. endclass: full_test
    194. endpackage :ch_pkg
    195. //**************************************************//
    196. module tb1_chen();//
    197. logic clk;
    198. logic rstn;
    199. logic [31:0] mcdt_data_output;
    200. logic mcdt_valid;
    201. logic [1:0] mcdt_id;
    202. mcdt_chen dut(//括号里面的信号变成接口里面的
    203. .clk(clk)
    204. ,.rstn(rstn)
    205. ,.channel1_data(ch1_intf.channel_data)//信号改为接口中的名称
    206. ,.channel1_valid(ch1_intf.channel_valid)
    207. ,.slave1_margin(ch1_intf.slave_margin)
    208. ,.channell_ready(ch1_intf.channel_ready)
    209. ,.channel2_data(ch2_intf.channel_data)
    210. ,.channel2_valid(ch2_intf.channel_valid)
    211. ,.channel2_ready(ch2_intf.channel_ready)
    212. ,.slave2_margin(ch2_intf.slave_margin)
    213. ,.channel3_data(ch3_intf.channel_data)
    214. ,.channel3_valid(ch3_intf.channel_valid)
    215. ,.channel3_ready(ch3_intf.channel_ready)
    216. ,.slave3_margin(ch3_intf.slave_margin)
    217. ,.mcdt_data_output(mcdt_data_output)
    218. ,.mcdt_valid(mcdt_valid)
    219. ,.mcdt_id(mcdt_id)
    220. );
    221. //*****************clk和rstn******************************//
    222. task clk_gen(input int T);
    223. clk <= 0;
    224. forever begin
    225. #(T/2) clk<= !clk;
    226. end
    227. endtask
    228. initial begin
    229. clk_gen(10);
    230. end
    231. task rstn_gen();
    232. #10 rstn <= 0;
    233. repeat(20) @(posedge clk);
    234. rstn <= 1;
    235. endtask
    236. initial begin
    237. rstn_gen();
    238. end
    239. import ch_pkg::*;//引入包中所有的类
    240. //**************************************************//
    241. basic_test b1;//句柄
    242. burst_test b2;
    243. full_test b3;
    244. //**************mcdt-接口-generator************************//
    245. interface_chen ch1_intf(.*);
    246. interface_chen ch2_intf(.*);
    247. interface_chen ch3_intf(.*);
    248. //将接口分成3份。分别对应mcdt的信号
    249. initial begin
    250. b1=new();
    251. b2=new();
    252. b3=new();
    253. //对3个test例化,创建对象
    254. b1.set_interface(ch1_intf, ch2_intf, ch3_intf);
    255. b2.set_interface(ch1_intf, ch2_intf, ch3_intf);
    256. b3.set_interface(ch1_intf, ch2_intf, ch3_intf);
    257. b1.run();
    258. b2.run();
    259. b3.run();
    260. $display("********all of tests have been finished***********");
    261. $finish();
    262. end
    263. endmodule

     basic_test

     

     burst_test

     

     full_test

    对这个单独测试,里面agent[ ]有个写成011,需要改成012.

     

     先装满,后清空

     

  • 相关阅读:
    第九章:最新版零基础学习 PYTHON 教程—Python 元组(第五节 -清除元组的5种方式方法)
    在C++中什么是异常处理以及如何使用try-catch块
    【Quark RISC-V】流水线CPU设计(3)数据相关与流水线冒险
    基于springboot的通知反馈系统
    DockerFile的使用
    新型智慧公厕建设:引领公厕行业的未来!
    Selenium模拟浏览器访问
    掌动智能:UI自动化测试工具产品功能和优势
    Go语言结构体
    【考研数学】线性代数第六章 —— 二次型(3,正定矩阵与正定二次型)
  • 原文地址:https://blog.csdn.net/weixin_39668316/article/details/125514830