]> git.zerfleddert.de Git - fpga-games/blame - galaxian/romgen/romgen.cpp
cleanup rom usage
[fpga-games] / galaxian / romgen / romgen.cpp
CommitLineData
782690d0
MG
1#include <stdio.h>\r
2#include <stdlib.h>\r
3#include <string>\r
4#include <math.h>\r
5#include <iostream>\r
6using namespace std;\r
7\r
8#define MAX_ROM_SIZE 0x4000\r
9\r
10int main(int argc, char* argv[])\r
11\r
12{\r
13 cerr << "romgen by MikeJ version 3.00\n";\r
14 // read file\r
15\r
16 string buffer;\r
17 FILE *fin;\r
18\r
19 if(argc < 5)\r
20 {\r
21 cerr << "\nUsage: romgen <input file> <entity name> <number of address bits>\n";\r
22 cerr << " <format> {registered} {enable}\n";\r
23 cerr << "\n";\r
24 cerr << "Now uses bit_vector generics for compatibilty with Xilinx UniSim library\n";\r
25 cerr << "\n";\r
26 cerr << "for the format paramater use :\n";\r
27 cerr << " a - rtl model rom array \n";\r
28 cerr << " c - rtl model case statement \n";\r
29 cerr << " b - Xilinx block ram4 (registered output always)\n";\r
30 cerr << " l - Xilinx block ram16 (registered output always)\n";\r
31 cerr << " d - Xilinx distributed ram [not supported yet]\n";\r
32 cerr << "\n";\r
33 cerr << "for the registered paramater (optional) use :\n";\r
34 cerr << " r - registered output (combinatorial otherwise) \n";\r
35 cerr << "\n";\r
36 cerr << "for the enable paramater (optional) use :\n";\r
37 cerr << " e - clock enable generated \n";\r
38 cerr << "\n";\r
39 cerr << "note, generated roms are always 8 bits wide\n";\r
40 cerr << " max 12 address bits for block ram4s\n";\r
41 cerr << " max 14 address bits for block ram16s\n";\r
42 cerr << "for example romgen fred.bin fred_rom 12 c r\n\n";\r
43 return -1;\r
44 }\r
45\r
46 fin = fopen(argv[1],"rb");\r
47 if (fin == NULL) {\r
48 cerr << "ERROR : Could not open input file " << argv[1] <<"\n";\r
49 return -1;\r
50 }\r
51\r
52 char rom_type = 0;\r
53 char option_1 = 0;\r
54 char option_2 = 0;\r
55 sscanf(argv[4],"%c",&rom_type);\r
56 if (argc > 5) sscanf(argv[5],"%c",&option_1);\r
57 if (argc > 6) sscanf(argv[6],"%c",&option_2);\r
58\r
59 bool format_case = false;\r
60 bool format_array = false;\r
61 bool format_block = false;\r
62 bool format_dist = false;\r
63 bool format_clock = false;\r
64 bool format_ram16 = false;\r
65 bool format_ena = false;\r
66\r
67 cerr << "INFO : creating entity : " << argv[2] << "\n";\r
68\r
69 if (option_1 != 0) {\r
70 if ((option_1 == 'r') || (option_1 == 'R')) \r
71 format_clock = true;\r
72 else if ((option_1 == 'e') || (option_1 == 'E'))\r
73 format_ena = true;\r
74 else {\r
75 cerr << "ERROR : output option not supported\n";\r
76 return -1;\r
77 }\r
78 }\r
79\r
80 // lazy ...\r
81 if (option_2 != 0) {\r
82 if ((option_2 == 'r') || (option_2 == 'R'))\r
83 format_clock = true;\r
84 else if ((option_2 == 'e') || (option_2 == 'E'))\r
85 format_ena = true;\r
86 else {\r
87 cerr << "ERROR : output option not supported\n";\r
88 return -1;\r
89 }\r
90 }\r
91\r
92 if ((rom_type == 'c') || (rom_type == 'C')) {\r
93 cerr << "INFO : rtl model, case statement \n"; format_case = true; }\r
94 else if ((rom_type == 'a') || (rom_type == 'A')) {\r
95 cerr << "INFO : rtl model, rom array \n"; format_array = true; }\r
96 else if ((rom_type == 'b') || (rom_type == 'B')) {\r
97 cerr << "INFO : block4 ram, registered \n"; format_block = true; format_clock = true; }\r
98 else if ((rom_type == 'l') || (rom_type == 'L')) {\r
99 cerr << "INFO : block16 ram, registered \n"; format_block = true; format_clock = true; format_ram16 = true; }\r
100 //else if ((rom_type == 'd') || (rom_type == 'D')) {\r
101 // cerr << "INFO : distributed ram, combinatorial; \n"; format_dist = true; }\r
102 else {\r
103 cerr << "ERROR : format not supported\n";\r
104 return -1;\r
105 }\r
106 if (format_clock == true)\r
107 cerr << "INFO : registered output\n\n";\r
108 else\r
109 cerr << "INFO : combinatorial output\n\n";\r
110\r
111\r
112 // calc number of address bits required\r
113 int addr_bits;\r
114 int max_addr_bits = 16;\r
115 int rom_inits = 16;\r
116\r
117 if (format_block == true) {\r
118 if (format_ram16 == true) {\r
119 max_addr_bits = 14;\r
120 rom_inits = 64;\r
121 }\r
122 else\r
123 max_addr_bits = 12;\r
124 }\r
125\r
126 sscanf(argv[3],"%d",&addr_bits);\r
127 if (addr_bits < 1 || addr_bits > max_addr_bits) {\r
128 cerr << "ERROR : illegal rom size, number of address bits must be between 1 and " << max_addr_bits << "\n";\r
129 return -1;\r
130 }\r
131 // ram b16s\r
132 // for 14 bits use ram_b16_s1 x data_width\r
133 // for 13 bits use ram_b16_s2 x data_width/2\r
134 // for 12 bits use ram_b16_s4 x data_width/4\r
135 // for<=11 bits use ram_b16_s8 x data_width/8\r
136\r
137 // ram b4s\r
138 // for 12 bits use ram_b4_s1 x data_width\r
139 // for 11 bits use ram_b4_s2 x data_width/2\r
140 // for 10 bits use ram_b4_s4 x data_width/4\r
141 // for <=9 bits use ram_b4_s8 x data_width/8\r
142 int rom_size = (int) pow(2,addr_bits);\r
143\r
144 int number_of_block_rams = 1;\r
145 int block_ram_width = 8;\r
146 int block_ram_pwidth = 0;\r
147 int block_ram_abits = 9;\r
148\r
149 if (format_ram16 == true) {\r
150 block_ram_abits = 11; // default\r
151 block_ram_pwidth = 1;\r
152 // ram16s\r
153 switch (addr_bits) {\r
154 case 14 : number_of_block_rams = 8; block_ram_width = 1; block_ram_pwidth = 0; block_ram_abits = 14; break;\r
155 case 13 : number_of_block_rams = 4; block_ram_width = 2; block_ram_pwidth = 0; block_ram_abits = 13; break;\r
156 case 12 : number_of_block_rams = 2; block_ram_width = 4; block_ram_pwidth = 0; block_ram_abits = 12; break;\r
157 default : ;\r
158 }\r
159 }\r
160 else {\r
161 // ram4s\r
162 switch (addr_bits) {\r
163 case 12 : number_of_block_rams = 8; block_ram_width = 1; block_ram_abits = 12; break;\r
164 case 11 : number_of_block_rams = 4; block_ram_width = 2; block_ram_abits = 11; break;\r
165 case 10 : number_of_block_rams = 2; block_ram_width = 4; block_ram_abits = 10; break;\r
166 default : ;\r
167 }\r
168 }\r
169\r
170 //printf("block ram w : %d ",block_ram_width);\r
171 //printf("block ram n : %d ",number_of_block_rams);\r
172\r
173\r
174 // process\r
175 int mem[MAX_ROM_SIZE];\r
176 string line;\r
177\r
178 int i,j,k;\r
179\r
180\r
181 int addr = 0;\r
182 int offset = 0;\r
183 int mask = 0;\r
184 unsigned int data = 0;\r
185\r
186 // clear mem\r
187 for (i = 0; i < MAX_ROM_SIZE; i++) mem[i] = 0;\r
188\r
189 // process file\r
190 data = getc(fin);\r
191 while (!feof(fin) && (addr < rom_size)) {\r
192 if (addr >= MAX_ROM_SIZE) {\r
193 cerr << "ERROR : file too large\n";\r
194 return -1;\r
195 }\r
196\r
197 mem[addr] = data;\r
198 // debug\r
199 //if (addr % 16 == 0) printf("%04x : ",addr);\r
200 //printf("%02x ",data);\r
201 //if (addr % 16 == 15) printf("\n");\r
202 // end debug\r
203 addr ++;\r
204 data = getc(fin);\r
205 }\r
206 fclose(fin);\r
207\r
208\r
209 printf("-- generated with romgen v3.0 by MikeJ\n");\r
210 printf("library ieee;\n");\r
211 printf(" use ieee.std_logic_1164.all;\n");\r
212 printf(" use ieee.std_logic_unsigned.all;\n");\r
213 printf(" use ieee.numeric_std.all;\n");\r
214 printf("\n");\r
215 printf("library UNISIM;\n");\r
216 printf(" use UNISIM.Vcomponents.all;\n");\r
217 printf("\n");\r
218 printf("entity %s is\n",argv[2]);\r
219 printf(" port (\n");\r
220 if (format_clock == true) printf(" CLK : in std_logic;\n");\r
221 if (format_ena == true) printf(" ENA : in std_logic;\n");\r
222 printf(" ADDR : in std_logic_vector(%d downto 0);\n",addr_bits - 1);\r
223 printf(" DATA : out std_logic_vector(7 downto 0)\n");\r
224 printf(" );\n");\r
225 printf("end;\n");\r
226 printf("\n");\r
227 printf("architecture RTL of %s is\n",argv[2]);\r
228 printf("\n");\r
229\r
230 // if blockram\r
231 //{{{\r
232 if (format_block == true) {\r
233 printf(" function romgen_str2bv (str : string) return bit_vector is\n");\r
234 printf(" variable result : bit_vector (str'length*4-1 downto 0);\n");\r
235 printf(" begin\n");\r
236 printf(" for i in 0 to str'length-1 loop\n");\r
237 printf(" case str(str'high-i) is\n");\r
238 for (i = 0; i<16; i++)\r
239 printf(" when '%01X' => result(i*4+3 downto i*4) := x\042%01X\042;\n",i,i);\r
240 printf(" when others => null;\n");\r
241 printf(" end case;\n");\r
242 printf(" end loop;\n");\r
243 printf(" return result;\n");\r
244 printf(" end romgen_str2bv;\n");\r
245 printf("\n");\r
246\r
247 // xilinx block ram component\r
248 if (block_ram_pwidth != 0) {\r
249 for (i = 0; i< 8; i++)\r
250 printf(" attribute INITP_%02X : string;\n",i);\r
251 printf("\n");\r
252 }\r
253\r
254 for (i = 0; i< rom_inits; i++)\r
255 printf(" attribute INIT_%02X : string;\n",i);\r
256 printf("\n");\r
257\r
258 if (format_ram16 == true)\r
259 printf(" component RAMB16_S%d\n",block_ram_width + block_ram_pwidth);\r
260 else\r
261 printf(" component RAMB4_S%d\n",block_ram_width);\r
262\r
263 printf(" --pragma translate_off\n");\r
264 printf(" generic (\n");\r
265 if (block_ram_pwidth != 0) {\r
266 for (i = 0; i< 8; i++) {\r
267 printf(" INITP_%02X : bit_vector (255 downto 0) := x\0420000000000000000000000000000000000000000000000000000000000000000\042",i);\r
268 printf(";\n");\r
269 }\r
270 printf("\n");\r
271 }\r
272\r
273 for (i = 0; i< rom_inits; i++) {\r
274 printf(" INIT_%02X : bit_vector (255 downto 0) := x\0420000000000000000000000000000000000000000000000000000000000000000\042",i);\r
275 if (i< (rom_inits - 1)) printf(";");\r
276 printf("\n");\r
277 }\r
278 printf(" );\n");\r
279 printf(" --pragma translate_on\n");\r
280 printf(" port (\n");\r
281 printf(" DO : out std_logic_vector (%d downto 0);\n",block_ram_width -1);\r
282 if (block_ram_pwidth != 0)\r
283 printf(" DOP : out std_logic_vector (%d downto 0);\n",block_ram_pwidth -1);\r
284 printf(" ADDR : in std_logic_vector (%d downto 0);\n",block_ram_abits -1);\r
285 printf(" CLK : in std_logic;\n");\r
286 printf(" DI : in std_logic_vector (%d downto 0);\n",block_ram_width -1);\r
287 if (block_ram_pwidth != 0)\r
288 printf(" DIP : in std_logic_vector (%d downto 0);\n",block_ram_pwidth -1);\r
289 printf(" EN : in std_logic;\n");\r
290 if (format_ram16 == true)\r
291 printf(" SSR : in std_logic;\n");\r
292 else\r
293 printf(" RST : in std_logic;\n");\r
294 printf(" WE : in std_logic \n");\r
295 printf(" );\n");\r
296 printf(" end component;\n");\r
297 printf("\n");\r
298 printf(" signal rom_addr : std_logic_vector(%d downto 0);\n",block_ram_abits - 1);\r
299 printf("\n");\r
300 }\r
301 //}}}\r
302 //{{{\r
303 if (format_array == true) {\r
304 printf("\n");\r
305 printf(" type ROM_ARRAY is array(0 to %d) of std_logic_vector(7 downto 0);\n",rom_size - 1);\r
306 printf(" constant ROM : ROM_ARRAY := (\n");\r
307 for (i = 0; i < rom_size; i ++ ) {\r
308 if (i % 8 == 0) printf(" ");\r
309 printf("x\042%02X\042",mem[i]);\r
310 if (i < (rom_size - 1)) printf(",");\r
311 if (i == (rom_size - 1)) printf(" ");\r
312 if (i % 8 == 7) printf(" -- 0x%04X\n",i - 7);\r
313 }\r
314 printf(" );\n");\r
315 printf("\n");\r
316 } // end array\r
317 //}}}\r
318 //{{{\r
319 if (format_case == true) {\r
320 printf(" signal rom_addr : std_logic_vector(11 downto 0);\n");\r
321 printf("\n");\r
322 }\r
323 //}}}\r
324\r
325 printf("begin\n");\r
326 printf("\n");\r
327 //\r
328 if ((format_block == true) || (format_case == true)) {\r
329 printf(" p_addr : process(ADDR)\n");\r
330 printf(" begin\n");\r
331 printf(" rom_addr <= (others => '0');\n");\r
332 printf(" rom_addr(%d downto 0) <= ADDR;\n",addr_bits - 1);\r
333 printf(" end process;\n");\r
334 printf("\n");\r
335 }\r
336 //\r
337 //{{{\r
338 if (format_block == true) {\r
339 for (k = 0; k < number_of_block_rams; k ++){\r
340 printf(" rom%d : if true generate\n",k);\r
341\r
342 for (j = 0; j < rom_inits; j++) {\r
343 printf(" attribute INIT_%02X of inst : label is \042",j);\r
344 switch (block_ram_width) {\r
345\r
346 case 1 : // width 1\r
347 mask = 0x1 << (k);\r
348 for (i = 0; i < 256; i+=8) {\r
349 data = ((mem[(j*256) + (255 - i)] & mask) >> k);\r
350 data <<= 1;\r
351 data += ((mem[(j*256) + (254 - i)] & mask) >> k);\r
352 data <<= 1;\r
353 data += ((mem[(j*256) + (253 - i)] & mask) >> k);\r
354 data <<= 1;\r
355 data += ((mem[(j*256) + (252 - i)] & mask) >> k);\r
356 data <<= 1;\r
357 data += ((mem[(j*256) + (251 - i)] & mask) >> k);\r
358 data <<= 1;\r
359 data += ((mem[(j*256) + (250 - i)] & mask) >> k);\r
360 data <<= 1;\r
361 data += ((mem[(j*256) + (249 - i)] & mask) >> k);\r
362 data <<= 1;\r
363 data += ((mem[(j*256) + (248 - i)] & mask) >> k);\r
364 printf("%02X",data);\r
365 }\r
366 break;\r
367\r
368 case 2 : // width 2\r
369 mask = 0x3 << (k * 2);\r
370 for (i = 0; i < 128; i+=4) {\r
371 data = ((mem[(j*128) + (127 - i)] & mask) >> k * 2);\r
372 data <<= 2;\r
373 data += ((mem[(j*128) + (126 - i)] & mask) >> k * 2);\r
374 data <<= 2;\r
375 data += ((mem[(j*128) + (125 - i)] & mask) >> k * 2);\r
376 data <<= 2;\r
377 data += ((mem[(j*128) + (124 - i)] & mask) >> k * 2);\r
378 printf("%02X",data);\r
379 }\r
380 break;\r
381\r
382 case 4 : // width 4\r
383 mask = 0xF << (k * 4);\r
384 for (i = 0; i < 64; i+=2) {\r
385 data = ((mem[(j*64) + (63 - i)] & mask) >> k * 4);\r
386 data <<= 4;\r
387 data += ((mem[(j*64) + (62 - i)] & mask) >> k * 4);\r
388\r
389 printf("%02X",data);\r
390 }\r
391 break;\r
392\r
393\r
394 case 8 : // width 8\r
395 for (i = 0; i < 32; i++) {\r
396 data = ((mem[(j*32) + (31 - i)]));\r
397 printf("%02X",data);\r
398 }\r
399 break;\r
400 } // end switch\r
401\r
402 printf("\042;\n");\r
403 }\r
404\r
405 printf(" begin\n");\r
406 if (format_ram16 == true)\r
407 printf(" inst : RAMB16_S%d\n",block_ram_width + block_ram_pwidth);\r
408 else\r
409 printf(" inst : RAMB4_S%d\n",block_ram_width);\r
410\r
411 printf(" --pragma translate_off\n");\r
412 printf(" generic map (\n");\r
413\r
414 if (block_ram_pwidth != 0) {\r
415 for (i = 0; i< 8; i++) {\r
416 printf(" INITP_%02X => x\0420000000000000000000000000000000000000000000000000000000000000000\042",i);\r
417 printf(",\n");\r
418 }\r
419 printf("\n");\r
420 }\r
421\r
422 for (i = 0; i< rom_inits; i++) {\r
423 printf(" INIT_%02X => romgen_str2bv(inst'INIT_%02X)",i,i);\r
424 if (i< (rom_inits - 1)) printf(",");\r
425 printf("\n");\r
426 }\r
427 printf(" )\n");\r
428 printf(" --pragma translate_on\n");\r
429 printf(" port map (\n");\r
430 printf(" DO => DATA(%d downto %d),\n",((k+1) * block_ram_width)-1,k*block_ram_width);\r
431 if (block_ram_pwidth != 0)\r
432 printf(" DOP => open,\n");\r
433 printf(" ADDR => rom_addr,\n");\r
434 printf(" CLK => CLK,\n");\r
435 printf(" DI => \042");\r
436 for (i = 0; i < block_ram_width -1; i++) printf("0");\r
437 printf("0\042,\n");\r
438 if (block_ram_pwidth != 0) {\r
439 printf(" DIP => \042");\r
440 for (i = 0; i < block_ram_pwidth -1; i++) printf("0");\r
441 printf("0\042,\n");\r
442 }\r
443 if (format_ena == true)\r
444 printf(" EN => ENA,\n");\r
445 else\r
446 printf(" EN => '1',\n");\r
447 //\r
448 if (format_ram16 == true)\r
449 printf(" SSR => '0',\n");\r
450 else\r
451 printf(" RST => '0',\n");\r
452 printf(" WE => '0'\n");\r
453 printf(" );\n");\r
454 printf(" end generate;\n");\r
455 }\r
456 } // end block ram\r
457 //}}}\r
458\r
459 //{{{\r
460 if (format_array == true) {\r
461 if (format_clock == true)\r
462 printf(" p_rom : process\n");\r
463 else\r
464 printf(" p_rom : process(ADDR)\n");\r
465 printf(" begin\n");\r
466 if (format_clock == true)\r
467 printf(" wait until rising_edge(CLK);\n");\r
468 if (format_ena == true)\r
469 printf(" if (ENA = '1') then\n ");\r
470 printf(" DATA <= ROM(to_integer(unsigned(ADDR)));\n");\r
471 if (format_ena == true)\r
472 printf(" end if;\n");\r
473 printf(" end process;\n");\r
474 //}}}\r
475 } // end array\r
476\r
477 //{{{\r
478 if (format_case == true) {\r
479 if (format_clock == true)\r
480 printf(" p_rom : process\n");\r
481 else\r
482 printf(" p_rom : process(rom_addr)\n");\r
483 printf(" begin\n");\r
484 if (format_clock == true)\r
485 printf(" wait until rising_edge(CLK);\n");\r
486 if (format_ena == true)\r
487 printf(" if (ENA = '1') then\n");\r
488\r
489 printf(" DATA <= (others => '0');\n");\r
490 printf(" case rom_addr is\n");\r
491 for (i = 0; i < rom_size; i ++ ) {\r
492 printf(" when x\042%03X\042 => DATA <= x\042%02X\042;\n",i,mem[i]);\r
493 }\r
494 printf(" when others => DATA <= (others => '0');\n");\r
495 printf(" end case;\n");\r
496 if (format_ena == true)\r
497 printf(" end if;\n");\r
498 printf(" end process;\n");\r
499 //}}}\r
500 } // end case\r
501 printf("end RTL;\n");\r
502\r
503 return 0;\r
504}\r
Impressum, Datenschutz