Menu Close

Verilog 文件操作综合应用-生成coe/mif 文件

在之前的文章中介绍了Verilog文件操作函数,本文对已经学习过的文件操作函数进行综合训练,并生成FPGA开发中2种最常用的文件(COE和MIF)。在使用Xilinx 芯片时, 我们会使用到xilinx 公司提供的IP 核, 比如ROM , 单端口RAM, 双端口RAM等等。 在这些存储器件中,有时我们希望预存储一些数据(对存储器进行初始化)。这时,我们就会需要COE (coefficient)文件了。 另外,如果使用Altera 公司的FPGA, 同样也会遇到这样的问题。虽然Quartus 本身就提供一种方法制作MIF(Memory Initialization File)文件,但本文中,我们可以利用Verilog 仿真文件制作自己所需要的COE文件或者MIF 文件。这里谈到的COE,MIF文件是指扩展名为coe, mif的文件。

在我们学习Verilog 仿真时,不但能对我们的FPGA 工程进行仿真, 同时也可以利用我们所学习的Verilog 仿真知识(文件操作)制作一些文件。这些文件不仅可以在仿真中使用,甚至生成的文件可以应用到综合中。

1 利用静态数组方式,生成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 ] = i; 
    end 
end

上面的代码是用户自定义的静态数组,用户可以根据自己的需要更改input_data 数组里面的内容。为了方便讲解,这里提供了一个简单的例子进行测试。文件的操作一般在仿真文件中实现,Verilog代码如例1:

例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 ] = 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]);
        if( INPUT_DATA_RADIX == 10)
            $fwrite(fd_coe,"\n%d", 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文件,内容如下:

memory_initialization_radix = 16;
memory_initialization_vector = 

00
01
02
03
04
05
06
07
08
09
0a
0b
0c
0d
0e
0f
10
11
12
13
14
15
16
17
18
19
1a
1b
1c
1d
1e
1f
20
21
22
23
24
25
26
27
28
29
2a
2b
2c
2d
2e
2f
30
31
32
33
34
35
36
37
38
39
3a
3b
3c
3d
3e
3f
40
41
42
43
44
45
46
47
48
49
4a
4b
4c
4d
4e
4f
50
51
52
53
54
55
56
57
58
59
5a
5b
5c
5d
5e
5f
60
61
62
63
64
65
66
67
68
69
6a
6b
6c
6d
6e
6f
70
71
72
73
74
75
76
77
78
79
7a
7b
7c
7d
7e
7f
80
81
82
83
84
85
86
87
88
89
8a
8b
8c
8d
8e
8f
90
91
92
93
94
95
96
97
98
99
9a
9b
9c
9d
9e
9f
a0
a1
a2
a3
a4
a5
a6
a7
a8
a9
aa
ab
ac
ad
ae
af
b0
b1
b2
b3
b4
b5
b6
b7
b8
b9
ba
bb
bc
bd
be
bf
c0
c1
c2
c3
c4
c5
c6
c7
c8
c9
ca
cb
cc
cd
ce
cf
d0
d1
d2
d3
d4
d5
d6
d7
d8
d9
da
db
dc
dd
de
df
e0
e1
e2
e3
e4
e5
e6
e7
e8
e9
ea
eb
ec
ed
ee
ef
f0
f1
f2
f3
f4
f5
f6
f7
f8
f9
fa
fb
fc
fd
fe
ff;

 

生成的MIF文件内容如下:

WIDTH=8;
DEPTH=256;

ADDRESS_RADIX=UNS;
DATA_RADIX=HEX;

CONTENT BEGIN
0 : 0;
1 : 1;
2 : 2;
3 : 3;
4 : 4;
5 : 5;
6 : 6;
7 : 7;
8 : 8;
9 : 9;
10 : a;
11 : b;
12 : c;
13 : d;
14 : e;
15 : f;
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 : 30;
49 : 31;
50 : 32;
51 : 33;
52 : 34;
53 : 35;
54 : 36;
55 : 37;
56 : 38;
57 : 39;
58 : 3a;
59 : 3b;
60 : 3c;
61 : 3d;
62 : 3e;
63 : 3f;
64 : 40;
65 : 41;
66 : 42;
67 : 43;
68 : 44;
69 : 45;
70 : 46;
71 : 47;
72 : 48;
73 : 49;
74 : 4a;
75 : 4b;
76 : 4c;
77 : 4d;
78 : 4e;
79 : 4f;
80 : 50;
81 : 51;
82 : 52;
83 : 53;
84 : 54;
85 : 55;
86 : 56;
87 : 57;
88 : 58;
89 : 59;
90 : 5a;
91 : 5b;
92 : 5c;
93 : 5d;
94 : 5e;
95 : 5f;
96 : 60;
97 : 61;
98 : 62;
99 : 63;
100 : 64;
101 : 65;
102 : 66;
103 : 67;
104 : 68;
105 : 69;
106 : 6a;
107 : 6b;
108 : 6c;
109 : 6d;
110 : 6e;
111 : 6f;
112 : 70;
113 : 71;
114 : 72;
115 : 73;
116 : 74;
117 : 75;
118 : 76;
119 : 77;
120 : 78;
121 : 79;
122 : 7a;
123 : 7b;
124 : 7c;
125 : 7d;
126 : 7e;
127 : 7f;
128 : 80;
129 : 81;
130 : 82;
131 : 83;
132 : 84;
133 : 85;
134 : 86;
135 : 87;
136 : 88;
137 : 89;
138 : 8a;
139 : 8b;
140 : 8c;
141 : 8d;
142 : 8e;
143 : 8f;
144 : 90;
145 : 91;
146 : 92;
147 : 93;
148 : 94;
149 : 95;
150 : 96;
151 : 97;
152 : 98;
153 : 99;
154 : 9a;
155 : 9b;
156 : 9c;
157 : 9d;
158 : 9e;
159 : 9f;
160 : a0;
161 : a1;
162 : a2;
163 : a3;
164 : a4;
165 : a5;
166 : a6;
167 : a7;
168 : a8;
169 : a9;
170 : aa;
171 : ab;
172 : ac;
173 : ad;
174 : ae;
175 : af;
176 : b0;
177 : b1;
178 : b2;
179 : b3;
180 : b4;
181 : b5;
182 : b6;
183 : b7;
184 : b8;
185 : b9;
186 : ba;
187 : bb;
188 : bc;
189 : bd;
190 : be;
191 : bf;
192 : c0;
193 : c1;
194 : c2;
195 : c3;
196 : c4;
197 : c5;
198 : c6;
199 : c7;
200 : c8;
201 : c9;
202 : ca;
203 : cb;
204 : cc;
205 : cd;
206 : ce;
207 : cf;
208 : d0;
209 : d1;
210 : d2;
211 : d3;
212 : d4;
213 : d5;
214 : d6;
215 : d7;
216 : d8;
217 : d9;
218 : da;
219 : db;
220 : dc;
221 : dd;
222 : de;
223 : df;
224 : e0;
225 : e1;
226 : e2;
227 : e3;
228 : e4;
229 : e5;
230 : e6;
231 : e7;
232 : e8;
233 : e9;
234 : ea;
235 : eb;
236 : ec;
237 : ed;
238 : ee;
239 : ef;
240 : f0;
241 : f1;
242 : f2;
243 : f3;
244 : f4;
245 : f5;
246 : f6;
247 : f7;
248 : f8;
249 : f9;
250 : fa;
251 : fb;
252 : fc;
253 : fd;
254 : fe;
255 : ff;
END;

 

练习题1:

使用Verilog的文件操作生成深度为360,精度为16bit的 正弦波数据,同时保存成coe和mif文件。

2 利用现有的文件,生成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) ,内容如图1 所示:

图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;

// =====================================================================
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") ;
        $fclose(fd_coe);
        $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") ;
        $fclose(fd_mif); 
        $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
        if( INPUT_DATA_RADIX == 16)
            $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 : 01;
1 : 02;
2 : 03;
3 : 04;
4 : 05;
5 : 06;
6 : 07;
7 : 08;
8 : 09;
9 : 0a;
10 : 0b;
11 : 0c;
12 : 0d;
13 : 0e;
14 : 0f;
15 : 10;
16 : 11;
17 : 12;
18 : 13;
19 : 14;
20 : 15;
21 : 16;
22 : 17;
23 : 18;
24 : 19;
25 : 1a;
26 : 1b;
27 : 1c;
28 : 1d;
29 : 1e;
30 : 1f;
31 : 20;
32 : 21;
33 : 22;
34 : 23;
35 : 24;
36 : 25;
37 : 26;
38 : 27;
39 : 28;
40 : 29;
41 : 2a;
42 : 2b;
43 : 2c;
44 : 2d;
45 : 2e;
46 : 2f;
47 : 30;
[48..255] : 0;
END;

 

 

练习题2: 使用$fscanf 函数替代 $fgets 函数,实现文本文件读取,并生成COE 文件。

 

上面给大家提供2个例子,演示如何使用Verilog 文件操作函数,生成COE或者MIF文件。真实使用环境中,可能会生成三角函数,可以用在DSP,或者科学计算当中,也可以生成图像数据文件,比如.bmp 文件,.jpg文件等用于图像处理 等等。

 

 

工程代码(vivado_2018.2)

[content_control]

verilog_coe_mif.zip

[/content_control]

 

 

 

 

Posted in FPGA, FPGA 教材教案, Verilog, Verilog, 教材与教案, 文章

发表回复

相关链接