在之前的文章中介绍了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文件
- 在整个仿真工程中, 用户需要修改一下几个参数:
INPUT_DATA_RADIX 是用来确定输出文件格式的(16进制,10进制,2进制), 是用户告诉仿真工程,输出什么样的格式的COE,MIF 文件。
INPUT_DATA_WID 是用来确定输入, 输出文件的数据宽度。
INPUT_DATA_DEEP 是告诉仿真工程,最终输出文件有多少个数据。
- 静态数组的代码如下:
|
1 2 3 4 5 6 7 8 |
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
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
`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文件,内容如下:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 |
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文件内容如下:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 |
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):
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
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
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
`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文件如下:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
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 文件如下:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
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]