您好,欢迎访问三七文档
当前位置:首页 > 电子/通信 > 电子设计/PCB > verilog系统任务之读写文件
verilog系统任务之读写文件1.$fopen打开文件用法1.$fopen(文件名);用法2.文件句柄=$fopen(文件名);注意:用$fopen打开文件会将原来的文件清空,若要读数据就用$readmemb,$readmemh就可以了,这个语句不会清空原来文件中的数据。用$fopen的情况是为了取得句柄,即文件地址,也就是写文件时用$fdisplay(desc,display1);时才用。用法1自然无须多解释,对于用法2,句柄就是任务$fopen返回的多通道描述符,默认为32位,最低位(第0位)默认被设置1,默认开放标准输出通道,即transcript窗口。moduledisp;integerhandle1,handle2,handle3;initialbeginhandle1=$fopen(file1.dat);handle2=$fopen(file2.dat);handle3=$fopen(file3.dat);$display(%h%h%h,handle1,handle2,handle3);endendmodule输出handle1=32‘h0000_0002handle2=32'h0000_0004handle3=32'h0000_0008即对每一次使用$fopen函数后都打开了一个新的通道,并且返回了一个设置为1的位相对应。默认应该是0001,以上每调用分别设置为0010,0100,1000(只考虑最低四位)。这个句柄对我们非常有用,因为在写文件时会用到。2.写文件我们用到系统任务$fdisplay,$fwrite.两者用法相似,前者写完就会自动换行,后者不会换行。用法:$fdisplay(文件描述符(句柄,用于确定是写哪一个文件),p1,p2(写入内容));描述符是很有意思的(默认为32位),如上我们知道,文件句柄最多只能有一个1,但是描述符可以是有多个1,哪一个位上有1,就同时在这些位对应的输出文件上写文件。因此可以同时写多个文件。只考虑后四位情况:1,0001时,只进行在transcript对话框中的输出,2,0101时,即对file2文件写又在transcript框输出、3,1111时,对全部文件写,同时在transcript框输出。由于每个句柄只有一个位置上是1,因此我们想在哪些文件中同时输出我们就可以用以下语句来写desc=handleI|handleK|handleM|handleN|1(一般与1或,最低位置1再transcript框输出。)一个例子如下:moduledisp;integerhandle1,handle2,handle3;integerdesc1,desc2,desc3;initialbeginhandle1=$fopen(file1.dat);handle2=$fopen(file2.dat);handle3=$fopen(file3.dat);$display(%h%h%h,handle1,handle2,handle3);desc1=handle1|1;$fwrite(desc1,display1);$fmoniter(desc1,display1);$fstrobe(desc1,display1);desc2=handle2|handle1|1;$fdisplay(desc2,display2);desc3=handle3|1;$fdisplay(32'd15,display3);endendmodule$monitor系统任务提供了监控和输出参数列表中的表达式和变量值的功能,其参数列表中输出控制格式字符串和输出表列的规则和$display一样,当启动一个带有一个或多个参数的$monitor任务时,每当参数列表中的变量或表达式的值发生变化时整个参数列表中变量或表达式的值都将输出显示。如果同一时刻有两个或多个表达式的值发生变化,只输出一次。参数可以是$time,用于标明变化时刻。如$monitor($time,,rxd=%btxd=%b,rxd,txd);这里的“,,”用来表示空格参数在输出时显示为空格$monitor的打开和关闭分别用$monitoron和$monitoroff表示,用来控制任务的启动和停止,使得很容易控制任务何时发生,何时结束。$monitor用于initial块中,只要不调用$monitoroff,该任务就可以不间断的对所设定信号进行监视。例子如下(对一个4位加法计数器counter信号进行监控):`timescale1ns/1nsmodulemoni_test();reg[3:0]counter;regclk;regrst;initialbeginrst=0;#10rst=1;$monitor($time,,counter=%d,counter);$monitoron;endinitialbeginclk=0;forever#5clk=~clk;endalways@(negedgerstorposedgeclk)if(!rst)counter=4'd0;elsecounter=counter+1;endmodule主要观察transcript对话框,可见每经过10ns,counter就会变化一次,此时参量时间也会输出。注意1.仅监测$time是不会每次都输出的,必须是除了时间之外的参量变化才可以做到参量变化就输出2.,,符号输出的是一个空格符,输出结果中得到了验证。转载自:系统函数$fopen用于打开一个文件,并还回一个整数指针.然后,$fdisplay就可以使用这个文件指针在文件中写入信息,写完后,则可以使用$fclose系统关闭这个文件例如:integerwrite_out_file;//定义一个文件指针integerwrite_out_file=$fopen(write_out_file.txt);$fdisplay(write_out_file,@%h\n%h,addr,data);$fclose(write_out_file);以上语法是将addr,data分别显示在"@%h\n%h"中的2个%h的位置,并写入write_out_file文件指针所指向的write_out_file.txt中.从文件中读取数据,可以用$readmemb$readmemh从文件中读入数据,该文件格式是一定的.reg[7:0]data[47:0];$readmemh(file_name.txt,data);就是将file_name.txt中的数据读入到data数组中,然后就可以使用这些数据了.还有一种方式可以把指定的数据放入指定的存储器地址单元内,就是在存放数据的文本文件内,给相应的数据规定其内存地址,形式如下:@address_in_hexadecimaldata@2f20两个系统任务可以在仿真的任何时刻被执行使用,其使用格式共有以下六种:1)$readmemb(数据文件名,存贮器名);2)$readmemb(数据文件名,存贮器名,起始地址);3)$readmemb(数据文件名,存贮器名,起始地址,结束地址);4)$readmemh(数据文件名,存贮器名);5)$readmemh(数据文件名,存贮器名,起始地址);6)$readmemh(数据文件名,存贮器名,起始地址,结束地址);在这两个系统任务中,被读取的数据文件的内容只能包含:空白位置(空格,换行,制表格(tab)和form-feeds),注释行(//形式的和形式的都允许),二进制或十六进制的数字。数字中不能包含位宽说明和格式说明,对于$readmemb系统任务,每个数字必须是二进制数字,对于$readmemh系统任务,每个数字必须是十六进制数字。数字中不定值x或X,高阻值z或Z,和下划线(_)的使用方法及代表的意义与一般VerilogHDL程序中的用法及意义是一样的。另外数字必须用空白位置或注释行来分隔开。在下面的讨论中,地址一词指对存贮器(memory)建模的数组的寻址指针。当数据文件被读取时,每一个被读取的数字都被存放到地址连续的存贮器单元中去。存贮器单元的存放地址范围由系统任务声明语句中的起始地址和结束地址来说明,每个数据的存放地址在数据文件中进行说明。当地址出现在数据文件中,其格式为字符“@”后跟上十六进制数。如:@hh...h对于这个十六进制的地址数中,允许大写和小写的数字。在字符“@”和数字之间不允许存在空白位置。可以在数据文件里出现多个地址。当系统任务遇到一个地址说明时,系统任务将该地址后的数据存放到存贮器中相应的地址单元中去。对于上面六种系统任务格式,需补充说明以下五点:1)如果系统任务声明语句中和数据文件里都没有进行地址说明,则缺省的存放起始地址为该存贮器定义语句中的起始地址。数据文件里的数据被连续存放到该存贮器中,直到该存贮器单元存满为止或数据文件里的数据存完。2)如果系统任务中说明了存放的起始地址,没有说明存放的结束地址,则数据从起始地址开始存放,存放到该存贮器定义语句中的结束地址为止。3)如果在系统任务声明语句中,起始地址和结束地址都进行了说明,则数据文件里的数据按该起始地址开始存放到存贮器单元中,直到该结束地址,而不考虑该存贮器的定义语句中的起始地址和结束地址。4)如果地址信息在系统任务和数据文件里都进行了说明,那么数据文件里的地址必须在系统任务中地址参数声明的范围之内。否则将提示错误信息,并且装载数据到存贮器中的操作被中断。5)如果数据文件里的数据个数和系统任务中起始地址及结束地址暗示的数据个数不同的话,也要提示错误信息。下面举例说明:先定义一个有256个地址的字节存贮器mem:reg[7:0]mem[1:256];下面给出的系统任务以各自不同的方式装载数据到存贮器mem中。initial$readmemh(mem.data,mem);initial$readmemh(mem.data,mem,16);initial$readmemh(mem.data,mem,128,1);第一条语句在仿真时刻为0时,将装载数据到以地址是1的存贮器单元为起始存放单元的存贮器中去。第二条语句将装载数据到以单元地址是16的存贮器单元为起始存放单元的存贮器中去,一直到地址是256的单元为止。第三条语句将从地址是128的单元开始装载数据,一直到地址为1的单元。在第三种情况中,当装载完毕,系统要检查在数据文件里是否有128个数据,如果没有,系统将提示错误信息。"引用参考"1.打开文件integerfile_id;file_id=fopen(file_path/file_name);2.写入文件//$fmonitor只要有变化就一直记录$fmonitor(file_id,%format_char,parameter);eg:$fmonitor(file_id,%m:%tin1=%do1=%h,$time,in1,o1);//$fwrite需要触发条件才记录$fwrite(file_id,%format_char,parameter);//$fdisplay需要触发条件才记录$fdisplay(file_id,%format_char,parameter);$fstrobe();3.读取文件integerfile_id;file_id=$fread(file_path/file_name,r);4.关闭文件$fclose(fjile_id);5.由文件设定存储器初值$readmemh(file_name,memory_name);//初始化数据为十六进制$readmemb(file_name,memory_name);//初始化数据为二进制转:提供了丰富的系统函数,这为Testbench的编写提供了
本文标题:verilog系统任务之读写文件
链接地址:https://www.777doc.com/doc-2866157 .html