在之前的文章中介绍了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]
[/content_control]