电力电子转战数字IC20220628day34——路科实验2a

编程入门 行业动态 更新时间:2024-10-09 13:25:36

<a href=https://www.elefans.com/category/jswz/34/1686239.html style=电力电子转战数字IC20220628day34——路科实验2a"/>

电力电子转战数字IC20220628day34——路科实验2a

目录

接口interface

要求1结构示意图

​编辑​编辑 tb1代码

 要求2

tb2代码


 

接口interface

功能:用来设计和验证,在验证时让连接更简洁 

和module相似,可以定义端口,双向信号,可以用initial和always,可以定义function和task

可以在软硬件环境传递,可以作为module的端口列表,可以作为软件方法的形式参数(virtual)

把接口看成一个插排,DUT和TB之间的数据驱动关系都可以用插排完成

要求1结构示意图

 tb1代码

`timescale 1ns/1ps
//**************************************************//
interface interface_chen (input clk, input rstn);
//定义接口,将输入输出变成logic变量,在时钟块里声明输入和输出。
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 //**************************************************//
module initiator_chen(interface_chen intf);//所有的端口都集成在接口中,端口列表直接用接口名,再重新定义个新的短的名字int idle_cycle=1;
function automatic void set_idle_cycle(int n);
idle_cycle=n;
endfunctionstring name;
function automatic void set_name(string s);name=s;
endfunctiontask chnl_write(input logic [31:0] data);@(posedge intf.clk);//clocking替代原来的clkintf.drv_clk.channel_valid<=1'b1;//原来的信号也变成clocking里面的intf.drv_clk.channel_data<=data;@(negedge intf.clk);wait(intf.channel_ready==1'b1);$display("%t channel initial [%s] sent data %x", $time, name, data);repeat (idle_cycle) channel_idle();		
endtasktask channel_idle();@(posedge intf.clk);intf.drv_clk.channel_valid<=1'b0;intf.drv_clk.channel_data<=1'b0;
endtaskendmodule //**************************************************//
module generator_chen;
int channel_arr[$];//队列
int num;
int id;function automatic void initialize(int n);id=n;num=0;
endfunctionfunction automatic int get_data();
int data;
data='h00C0_00000+(id<<16)+num;
num++;
channel_arr.push_back(data);
return data;
endfunctionendmodule//**************************************************//
module tb1_chen();//由于tb对接的是mcdt,所以还是用mcdt定义的那些信号名,输入换成reg,输出换成wirelogic          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)
);//**************************************************//
generator_chen ch1_gen();
generator_chen ch2_gen();
generator_chen ch3_gen();
//将generator分成3份。分别对应mcdt的信号
initiator_chen ch1_init(ch1_intf);
initiator_chen ch2_init(ch2_intf);
initiator_chen ch3_init(ch3_intf);
//将initiator分成3份initial  begin 
//先初始化
ch1_gen.initialize(1);
ch2_gen.initialize(2);
ch3_gen.initialize(3);
//设置名字
ch1_init.set_name("ch1_init");
ch2_init.set_name("ch2_init");
ch3_init.set_name("ch3_init");
//设置idle_cycle
ch1_init.set_idle_cycle(0);
ch2_init.set_idle_cycle(0);
ch3_init.set_idle_cycle(0);
end//*****************clk和rstn******************************//
task clk_gen(input int T);clk <= 0;forever begin#(T/2) clk<= !clk;end
endtaskinitial beginclk_gen(10);
endtask rstn_gen();#10 rstn <= 0;repeat(20) @(posedge clk);rstn <= 1;
endtaskinitial beginrstn_gen();
end//*****************写入数据******************************//
initial begin @(posedge rstn);repeat(5) @(posedge clk);repeat(100) beginch1_init.chnl_write(ch1_gen.get_data());endch1_init.channel_idle();
endinitial begin @(posedge rstn);repeat(5) @(posedge clk);repeat(100) beginch2_init.chnl_write(ch2_gen.get_data());endch2_init.channel_idle();
endinitial begin @(posedge rstn);repeat(5) @(posedge clk);repeat(100) beginch3_init.chnl_write(ch3_gen.get_data());endch3_init.channel_idle();
endendmodule

 结果如图

 

 要求2

 目的是用fork-join同时发送数据

tb2代码

`timescale 1ns/1ps
//**************************************************//
interface interface_chen (input clk, input rstn);
//定义接口,将输入输出变成logic变量,在时钟块里声明输入和输出。
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 //**************************************************//
module initiator_chen(interface_chen intf);//所有的端口都集成在接口中,端口列表直接用接口名,再重新定义个新的短的名字int idle_cycle=1;
function automatic void set_idle_cycle(int n);
idle_cycle=n;
endfunctionstring name;
function automatic void set_name(string s);name=s;
endfunctiontask chnl_write(input logic [31:0] data);@(posedge intf.clk);//clocking替代原来的clkintf.drv_clk.channel_valid<=1'b1;//原来的信号也变成clocking里面的intf.drv_clk.channel_data<=data;@(negedge intf.clk);wait(intf.channel_ready==1'b1);$display("%t channel initial [%s] sent data %x", $time, name, data);repeat (idle_cycle) channel_idle();		
endtasktask channel_idle();@(posedge intf.clk);intf.drv_clk.channel_valid<=1'b0;intf.drv_clk.channel_data<=1'b0;
endtaskendmodule //**************************************************//
module generator_chen;
int channel_arr[$];//队列
int num;
int id;function automatic void initialize(int n);id=n;num=0;
endfunctionfunction automatic int get_data();
int data;
data='h00C0_00000+(id<<16)+num;
num++;
channel_arr.push_back(data);
return data;
endfunctionendmodule//**************************************************//
module tb1_chen();//由于tb对接的是mcdt,所以还是用mcdt定义的那些信号名,输入换成reg,输出换成wirelogic          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
endtaskinitial beginclk_gen(10);
endtask rstn_gen();#10 rstn <= 0;repeat(20) @(posedge clk);rstn <= 1;
endtaskinitial beginrstn_gen();
end//**************************************************//
generator_chen ch1_gen();
generator_chen ch2_gen();
generator_chen ch3_gen();
//将generator分成3份。分别对应mcdt的信号
initiator_chen ch1_init(ch1_intf);
initiator_chen ch2_init(ch2_intf);
initiator_chen ch3_init(ch3_intf);
//将initiator分成3份//1. idle_cycle在1-3之间,每个通道发送200个数据,都完成后就结束
task automatic basic_test();
//还是初始化,改变的地方是set_idle_cycle的参数
//先初始化
ch1_gen.initialize(1);
ch2_gen.initialize(2);
ch3_gen.initialize(3);
//设置名字
ch1_init.set_name("ch1_init");
ch2_init.set_name("ch2_init");
ch3_init.set_name("ch3_init");
//设置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");forkrepeat(100) ch1_init.chnl_write(ch1_gen.get_data());repeat(100) ch2_init.chnl_write(ch2_gen.get_data());repeat(100) ch3_init.chnl_write(ch3_gen.get_data());
joinforkwait(ch1_init.intf.slave_margin=='hf0);wait(ch2_init.intf.slave_margin=='hf0);wait(ch3_init.intf.slave_margin=='hf0);
join
$display("finished");
endtask//2.idle为0,每个通道发送500个数据
task automatic burst_test();
//先初始化
ch1_gen.initialize(1);
ch2_gen.initialize(2);
ch3_gen.initialize(3);
//设置名字
ch1_init.set_name("ch1_init");
ch2_init.set_name("ch2_init");
ch3_init.set_name("ch3_init");
//设置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");
forkrepeat(500) ch1_init.chnl_write(ch1_gen.get_data());repeat(500) ch2_init.chnl_write(ch2_gen.get_data());repeat(500) ch3_init.chnl_write(ch3_gen.get_data());
joinforkwait(ch1_init.intf.slave_margin=='hf0);//256-200=56转换成十六进制?wait(ch2_init.intf.slave_margin=='hf0);//但其实是说直到空了,也就是全部数据都读完wait(ch3_init.intf.slave_margin=='hf0);
join
$display("finished");endtask//3. 所有通道都装满的时候停止,不需要同时达到
task automatic full_test();
//先初始化
ch1_gen.initialize(1);
ch2_gen.initialize(2);
ch3_gen.initialize(3);
//设置名字
ch1_init.set_name("ch1_init");
ch2_init.set_name("ch2_init");
ch3_init.set_name("ch3_init");
//设置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_runforever ch1_init.chnl_write(ch1_gen.get_data());forever ch2_init.chnl_write(ch2_gen.get_data());forever ch3_init.chnl_write(ch3_gen.get_data());
join_none//这个fj执行的时候下面的fj也开始执行
$display("running, waiting full");
forkwait(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那个停下来,别写入数据了forkch1_init.channel_idle();ch2_init.channel_idle();ch3_init.channel_idle();
join
$display("waiting all data transferred");$display("finished");endtaskendmodule 

这里编译成功,但是仿真时不知道怎么调用这三个任务。

嗨,憋着个尿想了一下,直接用个initial块加个延迟时间调用就好了,和前面时钟信号那里一样。

仿真时间不够长,明天再来仿真久一点。

2022年6月28日21:54:28


 可以把数据都送完,但是没有出现finished

原因在于wait那里margin应该是等到为256的时候,也就是fifo里面没有数据了,说明全部数据读完了,改成ff即可

第二个 burst_test也需要做相同的改动

 第三个 一直写入数据,写满为止

更多推荐

电力电子转战数字IC20220628day34——路科实验2a

本文发布于:2024-02-19 15:18:11,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1764563.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:电力电子   数字

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!