目录

首先复习一下类的知识点
CSDN
https://mp.csdn.net/mp_blog/creation/editor/125286941CSDN
https://mp.csdn.net/mp_blog/creation/editor/125254965

- `timescale 1ns/1ps
- //*********************用类class来改造**************************//
-
- //**********************接口和时钟块不变****************************//
- interface interface_chen (input clk, input rstn);
-
- logic [31:0] channel_data;
- logic channel_valid;
- logic channel_ready;
- logic [ 7:0] slave_margin;
-
- clocking drv_clk @(posedge clk);
- default input #1ns output #1ns;
- input channel_ready, slave_margin;//采样
- output channel_data, channel_valid;//驱动
- endclocking
-
- endinterface
- //**************************************************//
- class ch_trans;
- int data;
- int id;
- int num;
- endclass
- //**************************************************//
- class initiator_chen;
- virtual interface_chen intf;//virtual表示在子类中会被调用到,声明类的成员变量接口指针必须用virtual
-
- local int idle_cycle;
- local string name;
-
- function new(string name="initiator_chen");//这里其实就是初始化
- this.name=name;
- this.idle_cycle=1;
- endfunction
-
- //类里面所有变量都是动态变量,不需要加automatic了
- function void set_idle_cycle(int n);
- this.idle_cycle=n;
- endfunction
-
- function void set_name(string s);
- this.name=s;
- endfunction
- //这里替代的是三个接口的例化
- function void set_interface(virtual interface_chen intf);
- if(intf==null)
- $error("null, need to be intantiated.");
- else this.intf=intf;
- endfunction
-
- task chnl_write (input ch_trans t);//数据封装在ch_trans里面,这个类的句柄声明为t
- @(posedge intf.clk);
- intf.drv_clk.channel_valid<=1'b1;
- intf.drv_clk.channel_data<=t.data;//data要加t.引用
- @(negedge intf.clk);
- wait(intf.channel_ready==1'b1);
- $display("%t channel initial [%s] sent data %x", $time, name, t.data);
- repeat (this.idle_cycle) channel_idle();
- endtask
-
- task channel_idle();
- @(posedge intf.clk);
- intf.drv_clk.channel_valid<=1'b0;
- intf.drv_clk.channel_data<=1'b0;
- endtask
-
-
- endclass
- //**************************************************//
- class generator_chen;
- ch_trans trans[$];//存放ch_trans句柄的队列
- ch_trans t;//声明句柄
- int num;
- int id;
-
- function new(int n);//替代原来的初始化函数,完成初始化
- this.id=n;
- this.num=0;
- endfunction
-
- //替代生成数据的func get_data
- function ch_trans get_trans();//类的句柄函数
- t=new();//对类进行例化,创建一个名为t的ch_trans对象
- t.data='h00C0_00000+(this.id<<16)+this.num;
- t.id=this.id;//把gen的id赋给ch_trans的id
- t.num=this.num;
- this.num++;
- this.trans.push_back(t);
- return t;
- endfunction
-
- endclass
- //**************************************************//
- module tb1_chen();//由于tb对接的是mcdt,所以还是用mcdt定义的那些信号名,输入换成reg,输出换成wire
-
- logic clk;
- logic rstn;
- logic [31:0] mcdt_data_output;
- logic mcdt_valid;
- logic [1:0] mcdt_id;
-
- //**************mcdt-接口-generator************************//
- interface_chen ch1_intf(.*);//必须用接口名才不会报错,不能用intf
- interface_chen ch2_intf(.*);
- interface_chen ch3_intf(.*);
- //将接口分成3份。分别对应mcdt的信号
-
- mcdt_chen dut(//括号里面的信号变成接口里面的
- .clk(clk)
- ,.rstn(rstn)
-
- ,.channel1_data(ch1_intf.channel_data)//信号改为接口中的名称
- ,.channel1_valid(ch1_intf.channel_valid)
- ,.slave1_margin(ch1_intf.slave_margin)
- ,.channell_ready(ch1_intf.channel_ready)
-
-
- ,.channel2_data(ch2_intf.channel_data)
- ,.channel2_valid(ch2_intf.channel_valid)
- ,.channel2_ready(ch2_intf.channel_ready)
- ,.slave2_margin(ch2_intf.slave_margin)
-
-
- ,.channel3_data(ch3_intf.channel_data)
- ,.channel3_valid(ch3_intf.channel_valid)
- ,.channel3_ready(ch3_intf.channel_ready)
- ,.slave3_margin(ch3_intf.slave_margin)
-
-
- ,.mcdt_data_output(mcdt_data_output)
- ,.mcdt_valid(mcdt_valid)
- ,.mcdt_id(mcdt_id)
- );
-
-
- //*****************clk和rstn******************************//
- task clk_gen(input int T);
- clk <= 0;
- forever begin
- #(T/2) clk<= !clk;
- end
- endtask
-
- initial begin
- clk_gen(10);
- end
-
- task rstn_gen();
- #10 rstn <= 0;
- repeat(20) @(posedge clk);
- rstn <= 1;
- endtask
-
- initial begin
- rstn_gen();
- end
-
- //**************************************************//
- generator_chen ch1_gen;
- generator_chen ch2_gen;
- generator_chen ch3_gen;
- //将generator分成3份。分别对应mcdt的信号
- initiator_chen ch1_init;
- initiator_chen ch2_init;
- initiator_chen ch3_init;
- //将initiator分成3份
- //*******************以上不变*********************//
-
- initial begin
- //命名和初始化3个通道,test里面的都可以删掉了
- ch1_init=new("ch1_init");
- ch2_init=new("ch2_init");
- ch3_init=new("ch3_init");
- ch1_gen=new(1);
- ch2_gen=new(2);
- ch3_gen=new(3);
- //接口给到initiator,连接了
- ch1_init.set_interface(ch1_intf);
- ch2_init.set_interface(ch2_intf);
- ch3_init.set_interface(ch3_intf);
- $display("********all of tests have been finished***********");
- //basic_test();
- //burst_test();
- full_test();
- $finish();
- end
-
-
-
-
- //*****************************3个test**********************************//
-
- //1. idle_cycle在1-3之间,每个通道发送200个数据,都完成后就结束
- task automatic basic_test();
-
- //设置idle_cycle
- ch1_init.set_idle_cycle($urandom_range(1,3));
- ch2_init.set_idle_cycle($urandom_range(1,3));
- ch3_init.set_idle_cycle($urandom_range(1,3));
- $display("basic_test initialized components");
-
- wait (rstn===1'b1);
- repeat(5) @(posedge clk);
- $display("basic_test started testing dut");
-
- fork
- repeat(100) ch1_init.chnl_write(ch1_gen.get_trans());
- repeat(100) ch2_init.chnl_write(ch2_gen.get_trans());
- repeat(100) ch3_init.chnl_write(ch3_gen.get_trans());
- join
-
- fork
- wait(ch1_init.intf.slave_margin=='hff);
- wait(ch2_init.intf.slave_margin=='hff);
- wait(ch3_init.intf.slave_margin=='hff);
- join
- $display("finished");
- endtask
-
-
- //2.idle为0,每个通道发送500个数据
- task automatic burst_test();
-
- //设置idle_cycle
- ch1_init.set_idle_cycle(0);
- ch2_init.set_idle_cycle(0);
- ch3_init.set_idle_cycle(0);
- $display("burst_test initialized components");
- fork
- repeat(500) ch1_init.chnl_write(ch1_gen.get_trans());
- repeat(500) ch2_init.chnl_write(ch2_gen.get_trans());
- repeat(500) ch3_init.chnl_write(ch3_gen.get_trans());
- join
-
- fork
- wait(ch1_init.intf.slave_margin=='hff);//256-200=56转换成十六进制?
- wait(ch2_init.intf.slave_margin=='hff);//但其实是说直到空了,也就是全部数据都读完
- wait(ch3_init.intf.slave_margin=='hff);
- join
- $display("finished");
-
- endtask
-
-
- //3. 所有通道都装满的时候停止,不需要同时达到
- task automatic full_test();
- //设置idle_cycle
- ch1_init.set_idle_cycle(0);
- ch2_init.set_idle_cycle(0);
- ch3_init.set_idle_cycle(0);
- $display("full_test initialized components");
-
- fork: fork_all_run
- forever ch1_init.chnl_write(ch1_gen.get_trans());
- forever ch2_init.chnl_write(ch2_gen.get_trans());
- forever ch3_init.chnl_write(ch3_gen.get_trans());
- join_none//这个fj执行的时候下面的fj也开始执行
- $display("running, waiting full");
- fork
- wait(ch1_init.intf.slave_margin=='h0);//满了就执行下面的,不用等其他的满
- wait(ch2_init.intf.slave_margin=='h0);
- wait(ch3_init.intf.slave_margin=='h0);
- join
- $display("full");
- disable fork_all_run;//让none那个停下来,别写入数据了
-
- fork
- ch1_init.channel_idle();
- ch2_init.channel_idle();
- ch3_init.channel_idle();
- join
- $display("waiting all data transferred");
-
- $display("finished");
-
- endtask
-
-
- endmodule
编译和仿真都可以了。


复习一下package的知识点
CSDN
https://mp.csdn.net/mp_blog/creation/editor/125289909要求4是加入包以及用类的继承来做3个test

- `timescale 1ns/1ps
- //*********************用包package来改造**************************//
-
- //**********************接口和时钟块不变****************************//
- interface interface_chen (input clk, input rstn);
-
- logic [31:0] channel_data;
- logic channel_valid;
- logic channel_ready;
- logic [ 7:0] slave_margin;
-
- clocking drv_clk @(posedge clk);
- default input #1ns output #1ns;
- input channel_ready, slave_margin;//采样
- output channel_data, channel_valid;//驱动
- endclocking
-
- endinterface
- //**************************************************//
- package ch_pkg;
- //**************************************************//
- class ch_trans;
- int data;
- int id;
- int num;
- endclass
- //**************************************************//
- class initiator_chen;
- virtual interface_chen intf;//virtual表示在子类中会被调用到,声明类的成员变量接口指针必须用virtual
-
- local int idle_cycle;
- local string name;
-
- function new(string name="initiator_chen");//这里其实就是初始化
- this.name=name;
- this.idle_cycle=1;
- endfunction
-
- //类里面所有变量都是动态变量,不需要加automatic了
- function void set_idle_cycle(int n);
- this.idle_cycle=n;
- endfunction
-
- function void set_name(string s);
- this.name=s;
- endfunction
- //这里替代的是三个接口的例化
- function void set_interface(virtual interface_chen intf);
- if(intf==null)
- $error("null, need to be intantiated.");
- else this.intf=intf;
- endfunction
-
- task chnl_write (input ch_trans t);//数据封装在ch_trans里面,这个类的句柄声明为t
- @(posedge intf.clk);
- intf.drv_clk.channel_valid<=1'b1;
- intf.drv_clk.channel_data<=t.data;//data要加t.引用
- @(negedge intf.clk);
- wait(intf.channel_ready==1'b1);
- $display("%t channel initial [%s] sent data %x", $time, name, t.data);
- repeat (this.idle_cycle) channel_idle();
- endtask
-
- task channel_idle();
- @(posedge intf.clk);
- intf.drv_clk.channel_valid<=1'b0;
- intf.drv_clk.channel_data<=1'b0;
- endtask
-
-
- endclass
- //**************************************************//
- class generator_chen;
- ch_trans trans[$];//存放ch_trans句柄的队列
- ch_trans t;//声明句柄
- int num;
- int id;
-
- function new(int n);//替代原来的初始化函数,完成初始化
- this.id=n;
- this.num=0;
- endfunction
-
- //替代生成数据的func get_data
- function ch_trans get_trans();//类的句柄函数
- ch_trans t=new();//对类进行例化,创建一个名为t的ch_trans对象
- t.data='h00C0_00000+(this.id<<16)+this.num;
- t.id=this.id;//把gen的id赋给ch_trans的id
- t.num=this.num;
- this.num++;
- this.trans.push_back(t);
- return t;
- endfunction
-
- endclass
- //**************************************************//
- class ch_agent;
- generator_chen gen;
- initiator_chen init;
- local int ntrans;
- virtual interface_chen aintf;
-
- function new(string name="ch_agent", int id=0, int ntrans=1);
- this.gen=new(id);
- this.init=new(name);
- this.ntrans=ntrans;
- endfunction
-
- function void set_n_trans(int n);
- this.ntrans=n;
- endfunction
-
- function void set_interface(virtual interface_chen aintf);
- this.aintf=aintf;
- init.set_interface(aintf);
- endfunction
-
- task run();
- repeat(this.ntrans) this.init.chnl_write(this.gen.get_trans);
- this.init.channel_idle();
- endtask
- endclass
- //**************************************************//
- class root_test;
- ch_agent agent[3];//声明3个agent数组
- protected string name;
-
- function new(int ntrans=100, string name ="ch_root_test");
- foreach(agent[i]) begin
- this.agent[i]=new($sformatf("ch_agent%0d",i),i,ntrans);
- end
- this.name=name;
- $display("%s instantiate objects",this.name);
- endfunction
-
- task run();
- $display("%s started testing dut", this.name);
- fork
- agent[0].run();
- agent[1].run();
- agent[2].run();
- join
- $display("%s waiting", this.name);
- fork
- wait(agent[0].aintf.slave_margin=='hff);
- wait(agent[1].aintf.slave_margin=='hff);
- wait(agent[2].aintf.slave_margin=='hff);
- join
- $display("%s finished all data", this.name);
- endtask
-
- function void set_interface(virtual interface_chen ch1_aintf
- ,virtual interface_chen ch2_aintf
- ,virtual interface_chen ch3_aintf);
- agent[0].set_interface(ch1_aintf);
- agent[1].set_interface(ch2_aintf);
- agent[2].set_interface(ch3_aintf);
- endfunction
- endclass
-
- class basic_test extends root_test;
- function new(int ntrans=200, string name="basic_test");
- super.new(ntrans, name);
- foreach(agent[i]) begin
- this.agent[i].init.set_idle_cycle($urandom_range(1,3));
- end
- $display("%s configured objects", this.name);
- endfunction
- endclass: basic_test
-
- class burst_test extends root_test;
- function new(int ntrans=500, string name="burst_test");
- super.new(ntrans,name);
- foreach(agent[i]) begin
- this.agent[i].init.set_idle_cycle(0);
- end
- $display("%s configured objects", this.name);
- endfunction
- endclass: burst_test
-
- class full_test extends root_test;
- function new(int ntrans=1000000, string name="full_test");
- super.new(ntrans, name);
- foreach(agent[i]) begin
- this.agent[i].init.set_idle_cycle(0);
- end
- $display("%s configured objects", this.name);
- endfunction
-
- task run();
- $display("%s started testing dut", this.name);
- fork :fork_all_run
- agent[0].run();
- agent[1].run();
- agent[2].run();
- join_none
-
- $display("%s 3agents running, waiting full", this.name);
-
- fork
- wait(agent[0].aintf.slave_margin=='h0);
- wait(agent[1].aintf.slave_margin=='h0);
- wait(agent[2].aintf.slave_margin=='h0);
- join
-
- $display("%s full, stop", this.name);
- disable fork_all_run;
- $display("%s all idle", this.name);
-
- fork
- agent[0].init.channel_idle();
- agent[1].init.channel_idle();
- agent[1].init.channel_idle();
- join
-
- $display("%s waiting", this.name);
-
- fork
- wait(agent[0].aintf.slave_margin=='hff);
- wait(agent[1].aintf.slave_margin=='hff);
- wait(agent[2].aintf.slave_margin=='hff);
- join
-
- $display("%s finished all data", this.name);
-
- endtask
-
- endclass: full_test
-
- endpackage :ch_pkg
- //**************************************************//
- module tb1_chen();//
-
- logic clk;
- logic rstn;
- logic [31:0] mcdt_data_output;
- logic mcdt_valid;
- logic [1:0] mcdt_id;
-
-
- mcdt_chen dut(//括号里面的信号变成接口里面的
- .clk(clk)
- ,.rstn(rstn)
-
- ,.channel1_data(ch1_intf.channel_data)//信号改为接口中的名称
- ,.channel1_valid(ch1_intf.channel_valid)
- ,.slave1_margin(ch1_intf.slave_margin)
- ,.channell_ready(ch1_intf.channel_ready)
-
-
- ,.channel2_data(ch2_intf.channel_data)
- ,.channel2_valid(ch2_intf.channel_valid)
- ,.channel2_ready(ch2_intf.channel_ready)
- ,.slave2_margin(ch2_intf.slave_margin)
-
-
- ,.channel3_data(ch3_intf.channel_data)
- ,.channel3_valid(ch3_intf.channel_valid)
- ,.channel3_ready(ch3_intf.channel_ready)
- ,.slave3_margin(ch3_intf.slave_margin)
-
-
- ,.mcdt_data_output(mcdt_data_output)
- ,.mcdt_valid(mcdt_valid)
- ,.mcdt_id(mcdt_id)
- );
-
-
- //*****************clk和rstn******************************//
- task clk_gen(input int T);
- clk <= 0;
- forever begin
- #(T/2) clk<= !clk;
- end
- endtask
-
- initial begin
- clk_gen(10);
- end
-
- task rstn_gen();
- #10 rstn <= 0;
- repeat(20) @(posedge clk);
- rstn <= 1;
- endtask
-
- initial begin
- rstn_gen();
- end
-
- import ch_pkg::*;//引入包中所有的类
-
- //**************************************************//
- basic_test b1;//句柄
- burst_test b2;
- full_test b3;
-
-
- //**************mcdt-接口-generator************************//
- interface_chen ch1_intf(.*);
- interface_chen ch2_intf(.*);
- interface_chen ch3_intf(.*);
- //将接口分成3份。分别对应mcdt的信号
-
-
- initial begin
- b1=new();
- b2=new();
- b3=new();
- //对3个test例化,创建对象
- b1.set_interface(ch1_intf, ch2_intf, ch3_intf);
- b2.set_interface(ch1_intf, ch2_intf, ch3_intf);
- b3.set_interface(ch1_intf, ch2_intf, ch3_intf);
-
- b1.run();
- b2.run();
- b3.run();
-
- $display("********all of tests have been finished***********");
- $finish();
- end
-
-
- endmodule




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


先装满,后清空

