先总结实验任务的代码,再来总结一些拓展思考
目录
一、构造一个从路由器输出端进行取样的监视器(Monitor)?
任务一:创建顶层测试环境(Top-Level Test Environment)
三、运行Driver和Monitor程序,检验Checker能否正确比数 ?
一、构造一个从路由器输出端进行取样的监视器(Monitor)?
任务一:创建顶层测试环境(Top-Level Test Environment)
1.编辑已存在的test.sv文件,给pkt2cmp_payload[$]序列添加一个全局声明(global-declaration),位宽为8bit(logic[7:0])。这个序列将会被用来存储来自于DUT的取样数据。
2.为了能够进行自我核对,修改程序使recv()和send()可以并行进行,并在其后添加一个自我核对程序check()。
任务二:发展一个监视器(Monitor)
1.声明一个recv()命令。
2.在recv()体中调用get_payload()来获取有效负载。(在目前这是这是recv()程序中的唯一内容,在后面的实验中我们会在添加一些内容。)
3.声明get_payload()任务。
4.在get_payload()中,删除掉pkt2cmp_payload[$]的内容。(删掉来自之前数据包的可能剩余物是十分有必要的)
5.继续在get_payload()之中,等待输出端frame信号的下降沿。
(整个fork就一个意思:就是为了等待frame的下降沿,而为了防止等不到而一直卡在这,要做一个处理,并行触发1000次时钟,并且join_any是里面的并行语句只要有一个完成就推出继续执行下面的语句,故如果没有frame下降沿,1000次时钟触发结束就打印错误信息,frame信号超时,并结束仿真,$finish就是结束仿真,$stop是暂停仿真)
6.通过在路由器的输出端口取样来继续完善get_payload():
a)保持循环直到frame信号被检测到。
b)在循环中,至少8个时钟周期内聚合起一个字节(8bit)的数据。接着将每一个8位数据存储到pkt2cmp_payload[$]序列中去。
7.如果payload没有连成一个byte,就打印错误信息并终止仿真。
问题回答:
问题1: for循环里的为什么是 i=i 不是 i++ ?
因为为了采集的数据是准确的,故这里不直接 让 i++ , 而是在循环里限制条件后再加
问题2: datum[ i++] 又是什么意思?
这里就是限制条件,等到rtr_io.cb.valido_n[da] 处于低电平时才让 i+1 并进行数据采集,保证采集的数据准确
问题3: if 条件表达式里为什么是(i==8)?
等待最后一个byte的最后一位传输成时,i++,此时 i = 8
问题4: 这里的 return 的含义?
退出整个forever循环
问题5:出现的 2个 pkt2cmp_payload.push_back(datum); 重复吗?见下面的总结
总结:
在前n-1个byte 采集中代码执行顺序为:
因为数据没有传输完,故 frameo_n 一直处于低电平,故前面的 if 语句不会执行,每传输完一个字节都会跳出for循环顺序执行后面的语句:也就是第2个数据采集语句:
pkt2cmp_payload.push_back(datum);
把数据采集到 pkt2cmp_payload中 。
在最后一个byte传输中,代码执行顺序为:
先进行前7位循环,
当最后一位传输完 frameo_n 会被拉高,进入到 if 条件中,执行第1个数据采集语句:
pkt2cmp_payload.push_back(datum);
把数据采集到 pkt2cmp_payload中 ,并 return 退出整个forever 循环,根本不会执行后面的第二个相同的语句,故不会冲突。
二、构造一个可以验证路由器输出的比较器(Checker)?
任务三:发展比较器(Checker)
这一步是为了发展一个核对器从而去检查路由器的输出。
1.创建一个compare() 函数,它可以返回一个bit的值并且可以进行数据比较。
再给自己留一个问题,这里为什么使用 ref ?
2.在compare()中,比较payload[$]序列(用来参考的数据)和pkt2cmp_payload[$]序列取样的数据)中存储的数据来验证接收到的payload是否正确。
a)如果payload[$]序列和pkt2cmp_payload[$]序列的长度不匹配的话,设置描述该错误的语句,并返回0值结束该子程序。
b)如果在payload[$]序列和pkt2cmp_payload[$]序列的数据不匹配,设置描述该错误的语句,并返回0值和结束该子程序。(你可以用“==”来直接比较两个序列)。
c)如果在payload[$]序列和pkt2cmp_payload[$]序列中的数据是完全一致的,设置描述比较成功的语句,并返回1值和结束该子程序。
function bit compare(ref string message)
if(payload.size() != pkt2cmp_payload.size()) begin
message = "Payload size Mismatch:\n";
message = { message, $sformatf("payload.size() = %0d, pkt2cmp_payload.size() = %0d\n", payload.size(), pkt2cmp_payload.size()) };
return (0);
end
if(payload != pkt2cmp_payload) begin
message = "Payload Content Mismatch:\n";
message = { message, $sformatf("Packet Sent: %p\nPkt Received: %p", payload, pkt2cmp_payload) };
return (0);
end
message = "Successfully Compared";
return(1);
endfunction: compare
3.创建check() 任务。
4.在check() 体中,声明一个string(字符串)变量和一个计数器。
5.在check() 体内,调用compare函数来核对接收到的数据。
a)如果一个错误被发现了,则打印错误信息并终止仿真。
b)如果核对是成功的,则打印一个信息来表明比较成功和查到的数据包的数量。
6.保存并关闭test.v文件。
代码如下(示例):
task check();
string message;
static int pkts_checked = 0;
if(!compare(message)) begin
$display("\n%m\n[ERROR]%t Packet #%0d %s\n" , $realtime, pkts_checked, message);
$finish;
end
$display("[NOTE]%t Packet #%0d %s", $realtime, pkts_checked++, message);
endtask: check
endprogram: test
三、运行Driver和Monitor程序,检验Checker能否正确比数 ?
任务四:编译和仿真(略)
任务五:测试所有端口
1.修改你的测试程序来随机产生sa(源地址)和da(目标地址)。
2.将你的Testbench拓展到可以发送2000个数据包。
打印信息:
当 run_for_n_packets = 21;