文章目录
1.设计
多通道数据整形器 (MCDF,multi-channel data formatter),它可以将上行(uplink)多个通道数据经过内部的 FIFO,最终以数据包(data packet)的形式送出。
版本迭代
1.1SV/UVM版


1.1.1slave

valid是由外部driver拉高发送给slave的信号,表示输入data准备完成
ready是由内部slave发送给外部driver的信号,表示可以写入data
1.1.2formater

req是formater发送给外部接收端的发送请求
grant是由外部接收端拉高发送给formater的信号,表示外部允许接收数据了
其他信号是由formater发送给外部的信号
1.1.3register

寄存器决定了是读(从formater端)还是写(从slave端)
决定了三个slave中的哪一个
1.2APB版

1.2.1slave

1.2.2formater

1.2.3register

3.验证
3.1SV-MCDT
由tb模块设置发送的channel的id和data给mcdt dut
mcdtdut在tb中连接了mcdt_data_o
在dut内部连接了arbiter的arb_data_o 在arbiter内部连接了arb_data_r
由一个case决定arb_data_r是哪个channel的data
个人存在的疑问? 为什么ch的fifo余量总是在20和19之间,在未读出数据且写入两个数据的情况下余量仍是19,不会跳转到18? 为什么mcdt的out data总是两拍有效,在channel fifo中读出2个数
每一个channel发送更多的(100个)数据(tb模块)
function void set_name(string s);
task chnl_write(input logic[31:0] data); chnl_idle(); endtask
task chnl_idle();
logic [31:0] chnl0_arr[]; //创建32位的动态数组 logic [31:0] chnl1_arr[]; logic [31:0]chnl2_arr[]; initial begin chnl0_arr = new[100]; //每个数组例化100个 chnl1_arr = new[100]; chnl2_arr = new[100]; foreach(chnl0_arr[i]) begin chnl0_arr[i] = 'h00C0_00000 + i; //为100个数赋值 chnl1_arr[i] = 'h00C1_00000 + i; chnl2_arr[i] = 'h00C2_00000 + i; end end initial begin chnl0_init.set_name("chnl0_init"); chnl1_init.set_name("chnl0_init"); chnl2_init.set_name("chnl0_init"); foreach(chnl0_arr[i]) chnl0_init.chnl_write(chnl0_arr[i]); //每一个数重复一次chnl_write操作 foreach(chnl1_arr[i]) chnl1_init.chnl_write(chnl1_arr[i]); foreach(chnl2_arr[i])chnl2_init.chnl_write(chnl2_arr[i]); end
三个channel同时发送数据(tb模块)
//用fork join实现 fork foreach(chnl0_arr[i]) chnl0_init.chnl_write(chnl0_arr[i]); foreach(chnl1_arr[i])chnl1_init.chnl_write(chnl1_arr[i]); foreach(chnl2_arr[i])chnl2_init.chnl_write(chnl2_arr[i]); join
波形图
mcdt的out data变成了三个channel各读一个的顺序
三个test 分别为chnl_basic_test,chnl_burst_test,chnl_fifo_full_test
测试了多个数据传输,改变idle_cycles,以及fifo余量为0的时候结束test
数据类chnl_trans不再只局限于包含一个数据,而是多个数据
之前class chnl_trans; int data;
现在class chnl_trans; rand bit[31:0] data[]; //动态数组 rand int ch_id; rand int pkt_id; //第几个数据包,即第几个trans rand int data_nidles; //data之间空闲间隔周期 rand int pkt_nidles; //数据包之间空闲间隔周期
命令行指令
vsim -novopt -solvefaildebug -sv_seed 0 +TESTNAME=chnl_basic_test work.tb3_ref
不同的test需要对chnl_generator的随机变量做出不同的控制,继而进一步控制其内部随机的chnl_trans对象。也就是说,随机化也是可以分层次的,例如在test层可以随机化generator层,而依靠generator被随机化的成员变量,再来利用它们进一步随机化generator中的chnl_trans对象
chnl_basic_test 对chnl_generator的随机变量做出不同的控制
assert(gen[0].randomize() with {ntrans==100; data_nidles==0; pkt_nidles==1; data_size==8;}) assert(gen[1].randomize() with {ntrans==50; data_nidles inside {[1:2]}; pkt_nidles inside {[3:5]}; data_size==16;}) assert(gen[2].randomize() with {ntrans==80; data_nidles inside {[0:1]}; pkt_nidles inside {[1:2]}; data_size==32;})
gen 随机化结果
![]()
![]()
在gen调用send_trans,进一步控制其内部随机的chnl_trans对象task run(); repeat(ntrans) send_trans(); endtask
chnl_trans随机化结果
![]()
![]()
ntrans=100+50+80=230
req+rsp=230*2=460=obj_id
3.2SV-MCDF

命令行指令
vsim -novopt -classdebug -solvefaildebug -sv_seed 0 +TESTNAME=mcdf_data_consistence_basic_test -l mcdf_data_consistence_basic_test.log work.tb
chnl_pkg和reg_pkg和lab3一样,由test随机gen,gen随机trans
reg_pkgclass reg_trans; rand bit[7:0] addr; rand bit[1:0] cmd; rand bit[31:0] data; //cmd_data_in[31:6保留位,5:3数据包长度,2:1优先级,0通道使能信号] //5:3数据包长度 → 0对应4,1对应8,2对应16,3对应32,其他都是32 //cmd_data_out[31:8保留位,7:0FIFO的可写余量] bit rsp; constraint cstr { soft cmd inside {`WRITE, `READ, `IDLE}; //决定状态是读/写/idle soft addr inside {`SLV0_RW_ADDR, `SLV1_RW_ADDR, `SLV2_RW_ADDR, `SLV0_R_ADDR,`SLV1_R_ADDR, `SLV2_R_ADDR}; //决定是6个寄存器里哪个地址 // 0x00,04,08; 0x10,14,18 addr[7:4]==0 && cmd==`WRITE -> soft data[31:6]==0; //如果地址是 0x0? 的同时为写状态,把保留位设置为1 soft addr[7:5]==0; addr[4]==1 -> soft cmd == `READ; //如果地址是0x1?,为只读寄存器,约束cmd的状态只能为读 };
我的理解是一开始会给3个读写寄存器通过data分别配置
比如channel1经过fmt的数据包长度是8,channel2则是16,channel3是32
波形图
之后chnl_pkg生成数据,和lab3一样
按照reg的配置fmt输出
波形图
命令行指令
1.
仿真
vsim -novopt -classdebug -solvefaildebug -sv_seed 0 +TESTNAME=mcdf_data_consistence_basic_test -l mcdf_data_consistence_basic_test.log work.tb
保存波形
log -r /*
运行
run -all
2.
收集覆盖率
vsim -i -classdebug -solvefaildebug -coverage -coverstore H:\mcdf\SV-MCDF\lab5\cover -sv_seed random +TESTNAME=mcdf_data_consistence_basic_test -l mcdf_data_consistence_basic_tast.log work.tb
运行
run -all
直接查看覆盖率
代码覆盖率
功能覆盖率
退出仿真生成.data文件
quit -sim
合并覆盖率
把所有test跑一次后merge,覆盖率提升
vcover merge -out merged_coverage.ucdb H:\mcdf\SV-MCDF\lab5\cover
更新了mcdf_coverage,6个covergroup和测试功能点一一对应
![]()
遇到编译问题
Modelsim找不到头文件 Cannot find `include file “xxxxxx” in directories:
3.3UVM-MCDF
UVM入门实验0
UVM入门实验1
一、工厂的注册、创建和覆盖机制
二、域的自动化和uvm_object的常用方法
三、phase机制
四、config机制
五、消息管理
UVM验证环境测试的开始、环境构建的过程、连接以及结束的控制。
TLM通信
UVM仿真控制
之前的test
mcdf_base_test的run_phase运行了do_reg,do_formatter,do_data
do_reg,do_formatter,do_data为空定义task run_phase(uvm_phase phase); this.do_reg(); this.do_formatter(); this.do_data(); endtask
还定义了idle_reg,write_reg和read_reg
在子类test 即mcdf_data_consistence_basic_test中在do_reg配置了3个channel输出的格式
调用的是basetest中write_reg、read_reg task
do_formatter、do_data同样配置
现在的test
mcdf_base_test运行了run_top_virtual_sequence
run_top_virtual_sequence为空定义task run_phase(uvm_phase phase); this.run_top_virtual_sequence(); endtask
在子类test即mcdf_data_consistence_basic_test中重新定义run_top_virtual_sequence
包括了例化vseq(mcdf_data_consistence_basic_virtual_sequence),并且挂载到vsqr
(1)其中vsqr为
例化了所有sqr
(2)其中mcdf_base_virtual_sequence为
(2.1)例化了所有seq,包括了reg、channel、formater的seq
其中idle_reg_sequence、write_reg_sequence、read_reg_sequence在reg_pkg中定义
(2.2)task body中运行了do_reg,do_formatter,do_data
do_reg,do_formatter,do_data为空定义
在子类vseq即mcdf_data_consistence_basic_virtual_sequence中重新定义do_reg,do_formatter,do_data
在do_reg配置了3个channel输出的格式,调用的是reg_pkg中的idle_reg_sequence、write_reg_sequence、read_reg_sequence
do_formatter、do_data同样配置
寄存器模型mcdf_rgm_pkg
之前是reg_pkg的agent里的seq随机化产生cmd、addr和data发送给dut的reg
现在新加入了寄存器模型,由寄存器模型产生数据(cmd、addr和data)发送给reg_pkg的sequencer,但是需要adapter去转换uvm_reg_bus_op和reg_trans
rgm、adapter和predictor在mcdf_env里例化,显式调用build
adapter在上图看似例化在map中,实际上只是在env中的connect phase中map连接了adapter的句柄,又连接reg agent的sequencer
涉及到前门访问和后门访问,期待值、镜像值和硬件实际值
predictor是显式预测,连接到adapter和map
最后使用的是内建build in sequence
在sequence里的do_reg里配置
在vsqr和vseq里例化rgm
把其他测试也修改为寄存器模型访问
3.4APB-MCDF
register master agent由于总线更新为APB,需要开发完整的APB master agent。