1 $display
这个函数系统任务的作用是用来在控制台输出信息。
1) 直接显示字符串
$display("!!! Start Simulation !!!");
2) 显示data_display 的16进制 ,10进制
$display("data_display = %h hex %d decimal", 100, 100);
3) 显示data_display 的8进制 2进制
$display("data_display = %o otal %b binary",100, 100);
4) 主要展示换行操作
$display("data_display = %d otal next line \n %b binary", 100, 100);
5) 显示系统仿真时间
$display("simulation time is %t",$time);
具体代码如下:
-
reg flag;
-
//--------------------------------------------------------------------------------
-
//****************************** 系统显示 $display *******************************
-
reg [
31:
0] data_display;
-
-
initial
-
begin
-
data_display =
32'd100;
-
flag =
0;
-
$display(
"!!! Start Simulation !!!");
-
#
10;
-
//显示16进制 10进制
-
$display(
"data_display = %h hex %d decimal",
100,
100);
-
#
10;
-
//显示8进制 2进制
-
$display(
"data_display = %o otal %b binary",
100,
100);
-
#
10;
-
//ASCII码
-
$display(
"data_display has %c ascii character value",
64);
-
#
10;
-
//显示10进制 换行 2进制
-
$display(
"data_display = %d otal next line \n %b binary",
100,
100);
-
#
10
-
//显示系统仿真时间
-
$display(
"simulation time is %t",$time);
-
flag =
1;
-
end
结果显示:
在第五行展示了换行功能;为了验证系统仿真时间,笔者这边用flag参数拉高来测试时间,时间结果如下图显示,和显示时间一致;
2 $fopen
用法:<文件句柄>=$fopen("<文件名>");
句柄就是任务$fopen返回的多通道描述符,默认为32位,最低位(第0位)默认被设置1,默认开放标准输出通道,即transcript窗口。
每一次使用$fopen函数后都打开了一个新的通道,并且返回了一个设置为1的位相对应。默认应该是0001,以上每调用分别设置为0010 ,0100,1000(只考虑最低四位)。
3 $fscanf
函数功能,读取txt(.dat)文件数据,具体代码如下:
-
//****************************** 读文件 $fscanf *******************************
-
//宏定义,定义数据长度
-
`define DATA_LENGTH
8
-
//定义RAM大小
-
reg
signed [
15:
0] Sig0 [`DATA_LENGTH
-1:
0];
-
reg [
15:
0] Sig1 [`DATA_LENGTH
-1:
0];
-
-
//定义句柄
-
integer data_file0;
-
integer data_file1;
-
-
integer i;
-
-
-
//读取函数
-
initial
-
begin
-
#
200;
-
//打开句柄
-
data_file0 = $fopen(
"file/rd_data0_fpga.txt",
"r");
-
data_file1 = $fopen(
"file/rd_data1_fpga.txt",
"r");
-
for(i =
0;i < `DATA_LENGTH; i = i +
1)
-
begin
-
$
fscanf(data_file0,
"%d",Sig0[i]);
//读取十进制
-
$
fscanf(data_file1,
"%h",Sig1[i]);
//读取十六进制
-
end
-
$fclose(data_file0);
关闭这个句柄
-
$fclose(data_file1);
关闭这个句柄
-
end
结果显示如下:
红色(蓝色)箭头右边modesim中是读取的数据,txt中是原始数据;
4 $fwrite ($fdisplay)
函数功能,将数据写入到txt文件中(与fscanf正好相反) 。
$fwrite和$fdisplay的区别,$fwrite写下一个数不会自动转行,可以加\n来转行,$fdisplay则会自动转行。这里只介绍$fwrite了,$fdisplay和$fwrite基本一样的写法。
代码如下:
-
//****** $fwrite 写下一个数不会自动转行,所以要加\n
-
//将读取的Sig0,Sig1重新写进两个新的txt中
-
//定义句柄
-
integer data_wr0;
-
integer data_wr1;
-
integer m;
-
//读取函数
-
initial
-
begin
-
#
400;
-
-
//打开句柄
-
data_wr0 = $fopen(
"file/wr_data1_fpga.txt",
"w");
-
data_wr1 = $fopen(
"file/wr_data2_fpga.txt",
"w");
-
-
for(m =
0;m < `DATA_LENGTH; m = m +
1)
-
begin
-
@(clk);
-
$fwrite(data_wr0,
"%d\n",Sig0[m]);
//向txt写十进制 写下一个数不会自动转行,所以要加\n
-
$fwrite(data_wr1,
"%h\n",Sig1[m]);
//向txt写十六进制 写下一个数不会自动转行,所以要加\n
-
end
-
-
//关闭这个句柄
-
$fclose(data_wr0);
-
$fclose(data_wr1);
-
end
结果展示:
左边箭头所指的数据是待写入txt的数据,右边竖线部分是实际写入到txt的数据。
注意!!! 笔者刚发现一个规律,就是定义(reg signed [15:0] Sig;)这个信号的时候,
如果写成: $fclose(data_wr0,"%d\n",Sig[15:0]); 则在txt中输出的是无符号数;
反之,写成: $fclose(data_wr0,"%d\n",Sig); 则在txt中输出的是有符号数;
5 $fclose
fclose(<FileHandle>);关闭文件,<File Handle>为所获得的句柄。
6 $fread
读取文件:$freadinteger file_id;
file_id = $fread(“file_path/file_name”, “r”);
7 $random
$rabdom 这个系统函数提供了一个产生随机数的手段。当函数被调用时返回一个32bit的随机数。它是一个带符号的整形数。$random一般的用法是:$ramdom% b ,其中 b>0.它给出了一个范围在(-b+1):(b-1)中的随机数。
代码如下:
-
//***************************** 随机数 $random *******************************
-
//宏定义,定义数据长度
-
`define RANDOM_LENGTH
68
-
-
reg
signed [
15:
0] rand1;
-
reg
signed [
15:
0] rand2;
-
reg
signed [
15:
0] rand3;
-
-
reg [
15:
0] cnt_correct1;
-
reg [
15:
0] cnt_correct2;
-
reg [
15:
0] cnt_correct3;
-
-
reg
signed [
15:
0] min;
-
reg
signed [
15:
0] max;
-
-
integer k;
-
-
initial
-
begin
-
k =
0;
-
min =
10;
//只能是正的
-
max =
20;
-
rand1 =
0;rand2 =
0;rand3 =
0;
-
cnt_correct1 =
0;cnt_correct2 =
0;cnt_correct3 =
0;
-
-
#
800;
-
for(k =
0;k < `RANDOM_LENGTH; k = k +
1)
-
begin
-
@(clk);
-
//给出了一个范围在-59到59之间的随机数
-
rand1 = $random %
60;
-
//通过位并接操作产生一个值在0到59之间的数
-
rand2 = {$random} %
60;
-
//产生一个在min, max之间随机数的例子:
-
rand3 = min+{$random}%(max-min+
1);
-
-
// 测试程序
-
if((rand1 <
60)&&(rand1 >
-60))
-
cnt_correct1 = cnt_correct1 +
1;
-
if((rand2 <
60)&&(rand2 >=
0))
-
cnt_correct2 = cnt_correct2 +
1;
-
if((rand3 <= max)&&(rand3 >= min))
-
cnt_correct3 = cnt_correct3 +
1;
-
end
-
end
结果展示:
7 $stop
暂停仿真。
8 示例
1 下面是一些常见的应用:
2 1、读写文件
3 `timescale 1 ns/1 ns
4 module FileIO_tb;
5 integer fp_r, fp_w, cnt;
6 reg [7:0] reg1, reg2, reg3;
7 initial begin
8 fp_r = $fopen("data_in.txt", "r");
9 fp_w = $fopen("data_out.txt", "w");
10
11 while(!$feof(fp_r)) begin
12 cnt = $fscanf(fp_r, "%d %d %d", reg1, reg2, reg3);
13 $display("%d %d %d", reg1, reg2, reg3);
14 $fwrite(fp_w, "%d %d %d\n", reg3, reg2, reg1);
15 end
16
17 $fclose(fp_r);
18 $fclose(fp_w);
19 end
20 endmodule
21 2、
22 integer file, char;
23 reg eof;
24 initial begin
25 file = $fopenr("myfile.txt");
26 eof = 0;
27 while (eof == 0) begin
28 char = $fgetc(file);
29 eof = $feof (file);
30 $display ("%s", char);
31 end
32 end
33 3、文件处理定位
34 `define SEEK_SET 0
35 `define SEEK_CUR 1
36 `define SEEK_END 2
37 integer file, offset, position, r;
38 r = $fseek(file, 0, `SEEK_SET);
39 r = $fseek(file, 0, `SEEK_CUR);
40 r = $fseek(file, 0, `SEEK_END);
41 r = $fseek(file, position, `SEEK_SET);
42 4、
43 integer r, file, start, count;
44 reg [15:0] mem[0:10], r16;
45 r = $fread(file, mem[0], start, count);
46 r = $fread(file, r16);
47 5、
48 integer file, position;
49 position = $ftell(file);
50 6、
51 integer file, r, a, b;
52 reg [80*8:1] string;
53 file = $fopenw("output.log");
54 r = $sformat(string, "Formatted %d %x", a, b);
55 r = $sprintf(string, "Formatted %d %x", a, b);
56 r = $fprintf(file, "Formatted %d %x", a, b);
57 7、
58 integer file, r;
59 file = $fopenw("output.log");
60 r = $fflush(file);
61 8、
62 // This is a pattern file - read_pattern.pat
63 // time bin dec hex
64 10: 001 1 1
65 20.0: 010 20 020
66 50.02: 111 5 FFF
67 62.345: 100 4 DEADBEEF
68 75.789: XXX 2 ZzZzZzZz
69 `timescale 1ns / 10 ps
70 `define EOF 32'hFFFF_FFFF
71 `define NULL 0
72 `define MAX_LINE_LENGTH 1000
73
74 module read_pattern;
75 integer file, c, r;
76 reg [3:0] bin;
77 reg [31:0] dec, hex;
78 real real_time;
79 reg [8*`MAX_LINE_LENGTH:0] line;
80
81 initial
82 begin : file_block
83 $timeformat(-9, 3, "ns", 6);
84 $display("time bin decimal hex");
85 file = $fopenr("read_pattern.pat");
86 if (file == `NULL) // If error opening file
87 disable file_block; // Just quit
88
89 c = $fgetc(file);
90 while (c != `EOF)
91 begin
92
93 if (c == "/")
94 r = $fgets(line, `MAX_LINE_LENGTH, file);
95 else
96 begin
97 // Push the character back to the file then read the next time
98 r = $ungetc(c, file);
99 r = $fscanf(file," %f:\n", real_time);
100
101 // Wait until the absolute time in the file, then read stimulus
102 if ($realtime > real_time)
103 $display("Error - absolute time in file is out of order - %t",
104 real_time);
105 else
106 #(real_time - $realtime)
107 r = $fscanf(file," %b %d %h\n",bin,dec,hex);
108 end // if c else
109 c = $fgetc(file);
110 end // while not EOF
111
112 r = $fcloser(file);
113 end // initial
114
115 // Display changes to the signals
116 always @(bin or dec or hex)
117 $display("%t %b %d %h", $realtime, bin, dec, hex);
118
119 endmodule // read_pattern
120 9、自动比较输出结果
121 `define EOF 32'hFFFF_FFFF
122 `define NULL 0
123 `define MAX_LINE_LENGTH 1000
124 module compare;
125 integer file, r;
126 reg a, b, expect, clock;
127 wire out;
128 reg [`MAX_LINE_LENGTH*8:1];
129 parameter cycle = 20;
130
131 initial
132 begin : file_block
133 $display("Time Stim Expect Output");
134 clock = 0;
135
136 file = $fopenr("compare.pat");
137 if (file == `NULL)
138 disable file_block;
139
140 r = $fgets(line, MAX_LINE_LENGTH, file); // Skip comments
141 r = $fgets(line, MAX_LINE_LENGTH, file);
142
143 while (!$feof(file))
144 begin
145 // Wait until rising clock, read stimulus
146 @(posedge clock)
147 r = $fscanf(file, " %b %b %b\n", a, b, expect);
148
149 // Wait just before the end of cycle to do compare
150 #(cycle - 1)
151 $display("%d %b %b %b %b", $stime, a, b, expect, out);
152 $strobe_compare(expect, out);
153 end // while not EOF
154
155 r = $fcloser(file);
156 $stop;
157 end // initial
158
159 always #(cycle / 2) clock = !clock; // Clock generator
160
161 and #4 (out, a, b); // Circuit under test
162 endmodule // compare
163 10、从文件中读数据到mem(这个好像一般人用的最多了)
164 `define EOF 32'HFFFF_FFFF
165 `define MEM_SIZE 200_000
166 module load_mem;
167 integer file, i;
168 reg [7:0] mem[0:`MEM_SIZE];
169 reg [80*8:1] file_name;
170 initial
171 begin
172 file_name = "data.bin";
173 file = $fopenr(file_name);
174 i = $fread(file, mem[0]);
175 $display("Loaded %0d entries \n", i);
176 i = $fcloser(file);
177 $stop;
178 end endmodule // load_mem