之前一讲,我们是用了简单的TB的写法,产生的是固定的抖动。
下面我们要用到随机函数、task任务、repeat函数来生成随机的抖动仿真
https://blog.youkuaiyun.com/ciscomonkey/article/details/86485111
一、关键字的用法
1、random的用法
$ random这一系列函数可以产生一个有符号的32bit随机整数。一般的用法是$ random %b, 其中b>0; 这样就会生成一个范围在(-b+1):(b-1)中的随机数。
如果只得到正数的随机数,可采用{$random}%b来产生。
比如我们可以用于随机时间: {$random}%20_000_000 表示的是20_000_000以内的随机数。
2、task的用法
task和function综合出来的电路都是组合电路,如果你想在task和function来写时序功能,那你需要的是module而不是这两个。
task <任务名>
<端口及其数据类型声明语句>
<组合语句1>
<组合语句2>
<组合语句n>
endtask
任务的调用的语法如下:
<任务名>(顶层端口1,顶层端口2,。。。顶层端口n)
task只综合组合逻辑部分。
实际例子如下:
//任务task使用示例
module test
(
input [3:0] A, B,
input CIN,
output [3:0] S,
output COUT
);
reg [1:0] S0, S1, S2, S3;
task ADD;
input A, B, CIN;
output [1:0] C;
reg [1:0] C;
reg S, COUT;
begin
S = A ^ B ^ CIN;
COUT = (A&B) | (A&CIN) | (B&CIN);
C = {COUT, S};
end
endtask
always @(A or B or CIN)
begin
ADD (A[0], B[0], CIN, S0);
ADD (A[1], B[1], S0[1], S1);
ADD (A[2], B[2], S1[1], S2);
ADD (A[3], B[3], S2[1], S3);
S = {S3[0], S2[0], S1[0], S0[0]};
COUT = S3[1];
end
endmodule
3、repeat的用法
表示重复执行的次数,不可以综合
语法结构
repeat(常数)
begin
...
end
二、按键随机抖动仿真(testbench训练)
运用上面讲述的三个函数,进行仿真,也就是说,我们随机的隔一段时间,就把key翻转一次,一共执行key翻转50次的65535ns随机变量的抖动,来模拟的抖动,那么我的最大抖动时间就是random的最大数*50(假设每次都随机数去取了最大数)
`timescale 1ns/1ns
`define clk_period 20
module key_filter_tb;
reg clk;
reg rst_n;
reg key;
wire key_flag;
wire key_state;
key_filter key_filter(
.clk(clk),
.rst_n(rst_n),
.key(key),
.key_flag(key_flag),
.key_state(key_state)
);
initial begin
rst_n = 1'b0;
#(`clk_period*10) rst_n = 1'b1;
#(`clk_period*10 + 1);
press_key(39999999,49999999);
press_key(59999999,49999999);
press_key(159999999,99999999);
end
initial clk = 1;
always#(`clk_period/2) clk = ~clk;
reg [15:0]myrand;
task press_key;
input [31:0]press_time;
input [31:0]release_time;
begin
repeat(50)begin
myrand = {$random}%65536;
#myrand key = ~key;
end
key = 0;
#press_time;
repeat(50)begin
myrand = {$random}%65536;
#myrand key = ~key;
end
key = 1;
#release_time;
end
endtask
endmodule