task rx_data_task;
input [12:0] RXD;
reg [3:0] i;
begin
for (i=0;i<=13;i=i+1) begin
repeat (2603) @(posedge clk);
rx = RXD[i];
end
end
endtask
1、首先要说的是verilog中task的写法;
第一点:task定义的时候有封号,但是无括号,但是调用的时候有封号且必须有括弧,括弧要放入task的输入,没有则不放入任何值,这样括弧就好记住了。
第二点:for 循环中的变量需用reg申明类型,而不能用int。
第三点:此处的task是uart接收数据的激励,每一位数据持续2603个clk周期。dut中每隔2603个clk默认一位数据。或者没有计数到2603时,相邻数据有变化也认为是一位数据的结束。
所以此tb 中repeat(N),当N小于2603时;若相邻的下一位数据与前一数据不同,则dut 提前检测到数据的变化自动识别一位数据的结束;若相邻的下一位数据与前一位数据相同,则dut通过计数到2603来判定一位数据的结束。分析可知N小于2603时没有什么问题。
但是当N大于2603时;若相邻的下一位数据与前一数据不同,则dut 提前计数到2603,来判定一位数据的结束,计数器清零。不久后面又检测到数据变化,计数器又自动清零,但是,由于还不会产生采样的使能信号,所以不会存在采样值;这样的激励也是OK的。若相邻的下一位数据与前一位数据相同,则dut 提前计数到2603,来判定一位数据的结束,计数器清零。不久后面真正的数据到来时,也不会有任何的变化,数据也接收正确。只不过对下下一位数据有稍微多产生了点延迟,分析可知N大于2603时没有什么问题。
接收13个数据:
for (i=0;i<=13;i=i+1) begin
repeat (2603) @(posedge clk);
rx = RXD[i];
end
这种写法当i=0到i等于1之前,rx的值是未定的所以i<=13才能保证真的是有13个数据要接受。自己当时一直写成:
for (i=0;i<=12;i=i+1) begin
repeat (2603) @(posedge clk);
rx = RXD[i];
end
仿真发现总是差一位,最后才发现!
当然写成如下的就更加好了:
for (i=0;i<=12;i=i+1) begin
rx = RXD[i];
repeat (2603) @(posedge clk);
end
这样子i=0的过程就是对应第一个数据,不会有任何歧义了。