原文网站: verilog 仿真工程应用-生成coe/mif 文件 – 芯片天地
在使用xilinx 芯片时, 我们会使用到xilinx 公司提供的IP 核, 比如rom , 单端口ram, 双端口ram等等。 在这些存储器件中,有时我们希望预存储一些数据(对存储单沿进行初始化)。这时,我们就会需要coe文件了。 另外,如果使用altera 公司的fpga, 同样也会遇到这样的问题。虽然quartus 本身就提供一种方法制作mif文件,但本文中,我们可以利用verilog 仿真文件制作自己所需要的coe文件或者mif 文件。
在我们学习verilog 仿真时,不但能对我们的fpga 工程进行仿真, 同时,也可以利用我们所学习的verilog 仿真知识(文件操作)制作一些文件。
利用静态数组方式,生成coe,mif文件
在整个仿真工程中, 用户需要修改一下几个参数:
- localparam INPUT_DATA_RADIX = 16; // 16, 10 , 2
- localparam INPUT_DATA_WID = 8;
- localparam INPUT_DATA_DEEP = 256;
INPUT_DATA_RADIX 是用来确定输出文件格式的(16进制,10进制,2进制), 是用户告诉仿真工程,输出什么样的格式的coe,mif 文件。
INPUT_DATA_WID 是用来确定输入, 输出文件的数据宽度。
INPUT_DATA_DEEP 是告诉仿真工程,最终输出文件有多少个数据。
reg [INPUT_DATA_WID - 1:0] input_data [0:INPUT_DATA_DEEP - 1]; integer i; initial begin for(i = 0; i < INPUT_DATA_DEEP; i = i + 1) begin input_data = i; end end
这里是用户自定义的静态数组,用户可以根据自己的需要更改input_data 数组里面的内容。这里我们只是简单的提供一个例子,方便大家使用。
仿真代码如下:
例1
`timescale 1ns / 1ps
module sim_top(
);
// ====================== user parameter setting =======================
localparam INPUT_DATA_RADIX = 16; // 16, 10 , 2
localparam INPUT_DATA_WID = 8;
localparam INPUT_DATA_DEEP = 256;
// data need to convert
reg [INPUT_DATA_WID - 1:0] input_data [0:INPUT_DATA_DEEP - 1];
integer i;
initial
begin
for(i = 0; i < INPUT_DATA_DEEP; i = i + 1)
begin
input_data = i;
end
end
// =====================================================================
reg stop_flag = 0;
localparam FILE_COE = "../../../test.coe";
localparam FILE_MIF = "../../../test.mif";
integer n;
integer fd_coe;
integer fd_mif;
initial begin
n = 0;
fd_coe = $fopen(FILE_COE, "w");
if(fd_coe == 0)
begin
$display("$open coe file failed") ;
$stop;
end
$display("\n ============= coe file opened... ============= ") ;
// =====================================================================
// coe file
$fwrite(fd_coe,"memory_initialization_radix = %0d;\n",INPUT_DATA_RADIX);
$fwrite(fd_coe,"memory_initialization_vector = ");
#10;
for (n = 0; n < INPUT_DATA_DEEP; n = n + 1)
begin
if( INPUT_DATA_RADIX == 16)
$fwrite(fd_coe,"\n%h", input_data[n]);
if( INPUT_DATA_RADIX == 2)
$fwrite(fd_coe,"\n%b", input_data[n]);
#10;
end
$fwrite(fd_coe,";");
#10;
$fclose(fd_coe) ;
$display("\n ============= coe file closed... ============= ") ;
// =====================================================================
// =====================================================================
// mif file
$display("\n ============= mif file opened... ============= ") ;
fd_mif = $fopen(FILE_MIF, "w");
if(fd_mif == 0)
begin
$display("$open mif file failed") ;
$stop;
end
$fwrite(fd_mif,"WIDTH=%0d;\n",INPUT_DATA_WID);
$fwrite(fd_mif,"DEPTH=%0d;\n\n",INPUT_DATA_DEEP);
$fwrite(fd_mif,"ADDRESS_RADIX=UNS;\n");
if( INPUT_DATA_RADIX == 16)
$fwrite(fd_mif,"DATA_RADIX=HEX;\n\n");
if( INPUT_DATA_RADIX == 10)
$fwrite(fd_mif,"DATA_RADIX=DEC;\n\n");
if( INPUT_DATA_RADIX == 2)
$fwrite(fd_mif,"DATA_RADIX=BIN;\n\n");
$fwrite(fd_mif,"CONTENT BEGIN\n");
#10;
for (n = 0; n < INPUT_DATA_DEEP; n = n + 1)
begin
if( INPUT_DATA_RADIX == 16)
$fwrite(fd_mif,"%0d : %h;\n", n, input_data[n]);
if( INPUT_DATA_RADIX == 10)
$fwrite(fd_mif,"%0d : %0d;\n", n, input_data[n]);
if( INPUT_DATA_RADIX == 2)
$fwrite(fd_mif,"%0d : %b;\n", n, input_data[n]);
#10;
end
$fwrite(fd_mif,"END;\n");
#10;
$fclose(fd_mif) ;
$display("\n ============= mif file closed... ============= ") ;
// =====================================================================
stop_flag = 1;
#100;
$stop;
end
endmodule
利用现有的文件,生成coe,mif文件
有时,我们会利用其他工程或者软件的输出结果, 作为coe,mif 文件的输入。这时,就需要打开文本、2进制的文件,读取这些文件的内容, 利用仿真工程生成相应的coe,mif文件。
例2
文本输入文件如下(test.txt):
01
02
03
04
05
06
07
08
09
0a
0b
0c
0d
0e
0f
10
11
12
注:INPUT_DATA_RADIX = 16 时,文本文件中必须使用0-9 a-f 来表示; INPUT_DATA_RADIX = 10 时,文本文件中必须使用0-9 表示; INPUT_DATA_RADIX = 2 时,文本文件中必须使用0-1 来表示。
例如当INPUT_DATA_RADIX = 2 ,INPUT_DATA_WID = 8 时,文本文件必须是:
01010011
01111001
二进制输入文件(test.bin)
`timescale 1ns / 1ps
module sim_top(
);
// ====================== user parameter setting =======================
localparam INPUT_DATA_RADIX = 16; // 16, 10 , 2
localparam INPUT_DATA_WID = 8;
localparam INPUT_DATA_DEEP = 256;
// data need to convert
reg [INPUT_DATA_WID - 1:0] input_data [0:INPUT_DATA_DEEP - 1];
integer i;
initial
begin
for(i = 0; i < INPUT_DATA_DEEP; i = i + 1)
begin
input_data = i;
end
end
// =====================================================================
reg stop_flag = 0;
localparam FILE_COE = "../../../test.coe";
localparam FILE_MIF = "../../../test.mif";
localparam DATA_TXT = "../../../test.txt";
localparam DATA_BIN = "../../../test.bin";
integer n;
integer fd_coe;
integer fd_mif;
integer fd_txt;
integer fd_bin;
reg [7:0] mem;
reg [7:0] mem_array[0:3];
initial begin
n = 0;
fd_coe = $fopen(FILE_COE, "w");
if(fd_coe == 0)
begin
$display("$open coe file failed") ;
$stop;
end
fd_txt = $fopen(DATA_TXT, "r");
if(fd_txt == 0)
begin
$display("$open txt file failed") ;
$stop;
end
$display("\n ============= coe file opened... ============= ") ;
// =====================================================================
// coe file
$fwrite(fd_coe,"memory_initialization_radix = %0d;\n",INPUT_DATA_RADIX);
$fwrite(fd_coe,"memory_initialization_vector = \n");
#10;
while ($feof(fd_txt) != 1)
begin
$fgets(mem,fd_txt);
if( INPUT_DATA_RADIX == 16)
$fwrite(fd_coe,"%s", mem);
if( INPUT_DATA_RADIX == 10)
$fwrite(fd_coe,"%s", mem);
if( INPUT_DATA_RADIX == 2)
$fwrite(fd_coe,"%s", mem);
#10;
end
$fwrite(fd_coe,";");
#10;
$fclose(fd_coe) ;
$display("\n ============= coe file closed... ============= ") ;
// =====================================================================
// =====================================================================
// mif file
$display("\n ============= mif file opened... ============= ") ;
fd_mif = $fopen(FILE_MIF, "w");
if(fd_mif == 0)
begin
$display("$open mif file failed") ;
$stop;
end
fd_bin = $fopen(DATA_BIN, "rb");
if(fd_bin == 0)
begin
$display("$open bin file failed") ;
$stop;
end
$fwrite(fd_mif,"WIDTH=%0d;\n",INPUT_DATA_WID);
$fwrite(fd_mif,"DEPTH=%0d;\n\n",INPUT_DATA_DEEP);
$fwrite(fd_mif,"ADDRESS_RADIX=UNS;\n");
if( INPUT_DATA_RADIX == 16)
$fwrite(fd_mif,"DATA_RADIX=HEX;\n\n");
if( INPUT_DATA_RADIX == 10)
$fwrite(fd_mif,"DATA_RADIX=DEC;\n\n");
if( INPUT_DATA_RADIX == 2)
$fwrite(fd_mif,"DATA_RADIX=BIN;\n\n");
$fwrite(fd_mif,"CONTENT BEGIN\n");
#10;
$fread(mem, fd_bin);
#10;
while ($feof(fd_bin) != 1)
begin
// $fread(mem_array, fd_bin, 0, 4);
if( INPUT_DATA_RADIX == 16)
// $fwrite(fd_mif,"%0d : %02h%02h%02h%02h;\n", n, mem_array[0],mem_array[1],mem_array[2],mem_array[3]);
$fwrite(fd_mif,"%0d : %02h;\n", n, mem);
if( INPUT_DATA_RADIX == 10)
$fwrite(fd_mif,"%0d : %0d;\n", n, mem);
if( INPUT_DATA_RADIX == 2)
$fwrite(fd_mif,"%0d : %08b;\n", n, mem);
n = n + 1;
$fread(mem, fd_bin);
#10;
end
if( n < INPUT_DATA_DEEP);
$fwrite(fd_mif,"[%0d..%0d] : 0;\n", n, INPUT_DATA_DEEP - 1);
$fwrite(fd_mif,"END;\n");
#10;
$fclose(fd_mif) ;
$display("\n ============= mif file closed... ============= ") ;
// =====================================================================
stop_flag = 1;
#100;
$stop;
end
endmodule
仿真输出的test.coe文件如下:
memory_initialization_radix = 16;
memory_initialization_vector =
01
02
03
04
05
06
07
08
09
0a
0b
0c
0d
0e
0f
10
11
12 ;
仿真输出的test.mif 文件如下:
WIDTH=8;
DEPTH=256;
ADDRESS_RADIX=UNS;
DATA_RADIX=HEX;
CONTENT BEGIN
0 : 00;
1 : 01;
2 : 02;
3 : 03;
4 : 04;
5 : 05;
6 : 06;
7 : 07;
8 : 08;
9 : 09;
10 : 0a;
11 : 0b;
12 : 0c;
13 : 0d;
14 : 0e;
15 : 0f;
16 : 10;
17 : 11;
18 : 12;
19 : 13;
20 : 14;
21 : 15;
22 : 16;
23 : 17;
24 : 18;
25 : 19;
26 : 1a;
27 : 1b;
28 : 1c;
29 : 1d;
30 : 1e;
31 : 1f;
32 : 20;
33 : 21;
34 : 22;
35 : 23;
36 : 24;
37 : 25;
38 : 26;
39 : 27;
40 : 28;
41 : 29;
42 : 2a;
43 : 2b;
44 : 2c;
45 : 2d;
46 : 2e;
47 : 2f;
[48..255] : 0;
END;