第四章 关于仿真对象和激励文件
有关仿真对象和激励文件的“缘”真是长长的一条直线 ... 仿真对象就是我们用Quartus II 之类软件建立的模块。反之激励文件是仿真用“刺激”和“反应”的环境。实际上,仿真对象没有什么好谈,要谈就要谈激励文件。激励文件对“行为”在网上确实存在许多版本,但是大伙一致认为激励文件就是“验证”的作用。
关于上述的内容笔者真的把脑袋翻转了一次又一次,几乎翻转了1080°。笔者已经重申过很多次,网上的一套关于激励文件的认知,笔者没有反对,笔者只是保持保留的态度而已。最近,笔者在黑金社区上收集看到网友的一个回复,笔者将大概的陈述出来:
“我朋友说我还在用Modelsim观看波形图 ... 说我落伍了!既然不使用一些高级功能。”
这个回复真的很有趣,首先笔者不做评价,笔者尝试从这段内容中提取一些信息来迎合这章笔记的讨论方向。很多学习仿真的朋友,在它们眼里只是看到波形图,但是它们却看不到波形图指向的内容,亦即模块表达出来的信息,他们无法把“模块的内容和激励的内容”仔细的联系起来。造就这个问题的主要凶手就是,它们把建模和仿真看成是两个平台的东西。
说起来心情真的有点“无奈”,如果可以从不同角度去看东西,就会看到一些容易被疏忽的信息。就此说白了,就是看不懂波形图所指向的内容,学习者才会追求工具。笔者以前也在这方面犯下不少问题 ..... 嗯~这个话题不谈了,感觉很沉闷。
在这里,读者有两个选择:就是遵守网上的一套方法,把它们看成两个不同世界的东西。还是遵守笔者的想法,把它们看成是同在一个世界的东西。如果读者选择后者,那么接下来的内容才有浏览的意义,否则就是在浪费时间而已。
笔者把激励看成两个部分“刺激”和“反应”。“刺激”就是用来激化“仿真对象”,当仿真对象受到刺激,它就会“吐出反应”。如上图所示(从之前的笔记载过来的图,算是很老的作品了),在图中看到的箭头就是“刺激”和“反应”。在 .v 文件左边作为 => 的箭头就是刺激;在.v文件左边作为 <=的箭头是反应,但是作为刺激的条件;在.v文件右边作为 =>的箭头也是反应的一种,但是是作为输出。全部的过程都成为激励,更贴切点就是“激励环境”。
在前面笔者已经说过,如果读者把“仿真和建模”看成是同一个世界的东西,自然而然我们就能把建模的方法引入仿真。如是这样的话,激励文件的写法和建模时没有什么两样。笔者在这里要求读者尝试想象一下,如果读者有一个模块要烧下FPGA测试,单单赤裸裸的模块是没有什么作用。
我们需要再建立一个顶层模块(测试模块)作为刺激的作用,打个比方如串口发送模块:
module tx_module_test()
(
input CLK, // 顶层输出输入声明
input RSTn.
......
);
/***********************/
tx_module U1 // 测试模块实例化
(
.Start_Sig( isStart ), // 映射出测试模块的引口
.Done_Sig( TX_Done_Sig ),
.TX_Data( rData )
......
);
/***********************/
......
always @ ( posedge CLK or negedge )
......
case(i) // 测试动作
0:
if( TX_Done_Sig ) begin isStart <= 1'b0; i <= i + 1'b1; end
else begin isStart <= 1'b1; rData <= 8'hff; end
......
endcase
/**************************/
......
endmodule
如果把以上的想法用在仿真上(在这里仿真对象是串口发送模块):
timescale 1ps/1ps //仿真用的时间刻度(单位)声明
module tx_module_simulation(); // 激励环境
reg CLK; // 仿真用顶层输入输出声明
reg RSTn;
reg Start_Sig;
reg [7:0]rData;
wire TX_Done_Sig;
.....
/**************************/
tx_module U1 // 仿真对象实例化
(
.Start_Sig( Start_Sig ),
.Done_Sig( TX_Done_Sig ),
.TX_Data( rData ),
......
);
/***************************/
initial // 虚拟时钟产生
begin
RSTn = 0; #1000 RSTn = 1;
CLK = 1; forever CLK = ~CLK;
end
/***************************/
always @ ( posedge or negedge )
if( !RSTn )
begin
Start_Sig <= 1'b0;
rData <= 8'd0;
......
end
else
case( i ) //激励动作
0:
if( TX_ Done_Sig ) begin Start_Sig <= 1'b0; i <= i + 1'b1; end
else begin Start_Sig <= 1'b1; rData <= 8'hff; end
......
endcase
endmodule
读者如果对比上面两段代码,是不是可以看出其中共同点呢?这就是笔者所谓“把两个东西看成同一个世界”的含义。在这里笔者就点到即止就好了,详细的内容在时序篇的后半部分有许多实例,笔者就不一一重复了。
可能读者又要问:“这样做有什么好处?”。好处太多了,其中的重点就是读者可以很有效的联系仿真对象和激励文件的内容。可能笔者这样说感觉会比较抽象,但是读者可以尝试这样想象“在这里已经没有仿真和建模之分,余下只有考验Verilog HDL的基本功”。当读者了解到这个道理,波形图再也不是单纯的波形图而已,而是“模块的活动内容”或者“模块和激励之间的沟通记录”。
这也是很多学习仿真的朋友很难理解的一个重点,理解这个重点会使他们明白“追求高级工具是浮云(神马都是浮云)”。
好了这一章笔记差不多要しまい了,笔者在这里再强调一下:上述的内容只是笔者一厢情愿的想法而已,笔者不反对网上早已存有的学习方法,而是保留而已。在笔者眼中,故要学习Verilog HDL语言,那么ModelsimAltera(仿真)就要用于 Verilog HDL语言的角度。把仿真和建模两者联系起来,会产生不一样的效果。
结果,能不能接受就见仁见智了。
用户414138 2012-5-10 17:25
我试过在测试文件中建模,效果很好,虽然现在还不能完全理解它的好处,但是有一个好处是很明显的,就是 在“测试文件中建模”比“写一个测试模块”测试,改动起来要省事的多,就不用从新编译整个工程了。不好意思目前的看法比较浅显,您的笔记我很受用,希望能继续加油!支持ak~~~~~~!!!