├── .gitignore ├── README.md ├── data ├── color_carrier_sine.mif ├── generate_sinetable.py ├── image_rom.mif └── testimage.png ├── demo.jpg ├── quartus └── ntsc_composite.qpf ├── tools ├── imgpacker.pro ├── main.cpp └── process_image.sh └── vhdl ├── image_rom.vhdl ├── ntsc_composite_top_de2.vhdl ├── ntsc_sync_generator.vhdl ├── palette.vhdl └── sine_rom.vhdl /.gitignore: -------------------------------------------------------------------------------- 1 | *.bak 2 | *.rpt 3 | *.done 4 | *.summary 5 | *.pin 6 | *.pof 7 | *.sof 8 | *.jdi 9 | quartus/*tmp* 10 | vhdl/*tmp* 11 | quartus/db/ 12 | quartus/incremental_db/ 13 | *.smsg 14 | *.qdf 15 | *.bin 16 | *.qip 17 | *.cdf 18 | *.dpf 19 | *.qsf 20 | *.ddb 21 | *.cmp 22 | *.pro.user 23 | *.o 24 | Makefile 25 | imgpacker 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | NTSC-composite-encoder 2 | ====================== 3 | 4 | ![Screenshot](https://raw.github.com/elpuri/NTSC-composite-encoder/master/demo.jpg) 5 | 6 | What is it? 7 | ------------- 8 | This is a proof of concept level NTSC composite video encoder written in VHDL. This is by no means perfect, but it's a start. My main motivation for writing this is that I've been lately getting back into FPGA hacking and specifically retro computing (designing my own crappy CPUs and GPUs, emulating consoles, etc). Looking at my stuff being displayed on a shiny flat screen just looks a bit meh. At the risk of sounding like a someone trying to explain why vinyls sound better than CDs, I'm just gonna say a composite signal displayed on a cheap CRT TV just looks right. 9 | 10 | Gotchas 11 | ------- 12 | I tried generating composite color signal few years back without success. Turns out my design was working just fine except one tiny detail. Back then I spent a lot of time googling around looking for reference implementations and reading descriptions of NTSC. Regardless of all the reading I did, I just couldn't get it right. Hopefully the following random bits of information will make things easier for people following my footsteps. I also tried to document the VHDL code really well so that it would be easier to understand what's going on. 13 | 14 | * During my previous attempt to get colors working I thought (due to nice diagrams like this http://m.eet.com/media/1050360/C0195-Figure2.gif) that I had to generate 9 beautiful cycles of color burst starting and ending at the blanking level. To do just that I reset the counter that generated addresses to the sine table at the beginning of the color burst. Nope. You're supposed to keep the counter running and output whatever comes out of the sine table during the color burst period, so that the phase doesn't change (too much) between bursts. Resetting the phase at the beginning of every burst of course messeses things up. Back then I had no clue what a phase locked loop was and how the TV circuitry might use one. Now all of it makes sense. 15 | * I used http://www.kolumbus.fi/pami1/video/pal_ntsc.html to get the timings and information about the vertical synchronization pulses. A great source of information for both PAL and NTSC. http://www.retroleum.co.uk/electronics-articles/pal-tv-timing-and-voltages/ is good too, but for PAL only. 16 | * The key to getting that nice non-interlaced "mode" used by all the lovely HW from late 70s to mid 90s is to always send the same field synchronization pulses (they differ for the two fields). I'm not 100% sure what those equalization pulses are for and if most TVs actually do fine without them. Looking at how for example the TIA used in Atari 2600 works, I don't think it generates them. Maybe they play a part only when doing interlaced video. * 17 | * The absolute voltage levels are not so important and things are relative. Looks like modern TVs are pretty good at adapting to almost any crap you throw at them. For example you can boost the saturation by using a slightly lower than nominal amplitude for the color burst. 18 | * Not low pass filtering the luma component will generate color noise. If you have really sharp edges in your luma signal, you're inadvertently generating harmonics in the higher frequencies which get interpreted as color information by the TV. The same applies for the color information. The phenomenon is explained here http://en.wikipedia.org/wiki/Dot_crawl. Of course if you want yours look gritty like the cheap hardware did back in the day, then forget all this. 19 | 20 | 21 | *) I tried leaving out the equalization pulses and things still work, but not completely without side-effects. At least my test TVs OSD doesn't like it and wobbles up and down one non-interlaced line. 22 | -------------------------------------------------------------------------------- /data/color_carrier_sine.mif: -------------------------------------------------------------------------------- 1 | -- romswak data sine1.bin sine2.bin sine3.bin sine4.bin sine5.bin sine6.bin sine7.bin -o color_carrier_sine.mif -mif -width 9 2 | 3 | DEPTH = 1792; 4 | WIDTH = 9; 5 | ADDRESS_RADIX = DEC; 6 | DATA_RADIX = BIN; 7 | 8 | CONTENT 9 | BEGIN 10 | 0 : 000000000; 11 | 1 : 000000011; 12 | 2 : 000000111; 13 | 3 : 000001011; 14 | 4 : 000001110; 15 | 5 : 000010010; 16 | 6 : 000010110; 17 | 7 : 000011001; 18 | 8 : 000011101; 19 | 9 : 000100000; 20 | 10 : 000100100; 21 | 11 : 000101000; 22 | 12 : 000101011; 23 | 13 : 000101111; 24 | 14 : 000110010; 25 | 15 : 000110101; 26 | 16 : 000111001; 27 | 17 : 000111100; 28 | 18 : 001000000; 29 | 19 : 001000011; 30 | 20 : 001000110; 31 | 21 : 001001001; 32 | 22 : 001001101; 33 | 23 : 001010000; 34 | 24 : 001010011; 35 | 25 : 001010110; 36 | 26 : 001011001; 37 | 27 : 001011100; 38 | 28 : 001011111; 39 | 29 : 001100001; 40 | 30 : 001100100; 41 | 31 : 001100111; 42 | 32 : 001101010; 43 | 33 : 001101100; 44 | 34 : 001101111; 45 | 35 : 001110001; 46 | 36 : 001110011; 47 | 37 : 001110110; 48 | 38 : 001111000; 49 | 39 : 001111010; 50 | 40 : 001111100; 51 | 41 : 001111110; 52 | 42 : 010000000; 53 | 43 : 010000010; 54 | 44 : 010000100; 55 | 45 : 010000101; 56 | 46 : 010000111; 57 | 47 : 010001001; 58 | 48 : 010001010; 59 | 49 : 010001011; 60 | 50 : 010001101; 61 | 51 : 010001110; 62 | 52 : 010001111; 63 | 53 : 010010000; 64 | 54 : 010010001; 65 | 55 : 010010010; 66 | 56 : 010010011; 67 | 57 : 010010011; 68 | 58 : 010010100; 69 | 59 : 010010100; 70 | 60 : 010010101; 71 | 61 : 010010101; 72 | 62 : 010010101; 73 | 63 : 010010101; 74 | 64 : 010010110; 75 | 65 : 010010101; 76 | 66 : 010010101; 77 | 67 : 010010101; 78 | 68 : 010010101; 79 | 69 : 010010100; 80 | 70 : 010010100; 81 | 71 : 010010011; 82 | 72 : 010010011; 83 | 73 : 010010010; 84 | 74 : 010010001; 85 | 75 : 010010000; 86 | 76 : 010001111; 87 | 77 : 010001110; 88 | 78 : 010001101; 89 | 79 : 010001011; 90 | 80 : 010001010; 91 | 81 : 010001001; 92 | 82 : 010000111; 93 | 83 : 010000101; 94 | 84 : 010000100; 95 | 85 : 010000010; 96 | 86 : 010000000; 97 | 87 : 001111110; 98 | 88 : 001111100; 99 | 89 : 001111010; 100 | 90 : 001111000; 101 | 91 : 001110110; 102 | 92 : 001110011; 103 | 93 : 001110001; 104 | 94 : 001101111; 105 | 95 : 001101100; 106 | 96 : 001101010; 107 | 97 : 001100111; 108 | 98 : 001100100; 109 | 99 : 001100001; 110 | 100 : 001011111; 111 | 101 : 001011100; 112 | 102 : 001011001; 113 | 103 : 001010110; 114 | 104 : 001010011; 115 | 105 : 001010000; 116 | 106 : 001001101; 117 | 107 : 001001001; 118 | 108 : 001000110; 119 | 109 : 001000011; 120 | 110 : 001000000; 121 | 111 : 000111100; 122 | 112 : 000111001; 123 | 113 : 000110101; 124 | 114 : 000110010; 125 | 115 : 000101111; 126 | 116 : 000101011; 127 | 117 : 000101000; 128 | 118 : 000100100; 129 | 119 : 000100000; 130 | 120 : 000011101; 131 | 121 : 000011001; 132 | 122 : 000010110; 133 | 123 : 000010010; 134 | 124 : 000001110; 135 | 125 : 000001011; 136 | 126 : 000000111; 137 | 127 : 000000011; 138 | 128 : 000000000; 139 | 129 : 111111100; 140 | 130 : 111111000; 141 | 131 : 111110100; 142 | 132 : 111110001; 143 | 133 : 111101101; 144 | 134 : 111101001; 145 | 135 : 111100110; 146 | 136 : 111100010; 147 | 137 : 111011111; 148 | 138 : 111011011; 149 | 139 : 111010111; 150 | 140 : 111010100; 151 | 141 : 111010000; 152 | 142 : 111001101; 153 | 143 : 111001010; 154 | 144 : 111000110; 155 | 145 : 111000011; 156 | 146 : 110111111; 157 | 147 : 110111100; 158 | 148 : 110111001; 159 | 149 : 110110110; 160 | 150 : 110110010; 161 | 151 : 110101111; 162 | 152 : 110101100; 163 | 153 : 110101001; 164 | 154 : 110100110; 165 | 155 : 110100011; 166 | 156 : 110100000; 167 | 157 : 110011110; 168 | 158 : 110011011; 169 | 159 : 110011000; 170 | 160 : 110010101; 171 | 161 : 110010011; 172 | 162 : 110010000; 173 | 163 : 110001110; 174 | 164 : 110001100; 175 | 165 : 110001001; 176 | 166 : 110000111; 177 | 167 : 110000101; 178 | 168 : 110000011; 179 | 169 : 110000001; 180 | 170 : 101111111; 181 | 171 : 101111101; 182 | 172 : 101111011; 183 | 173 : 101111010; 184 | 174 : 101111000; 185 | 175 : 101110110; 186 | 176 : 101110101; 187 | 177 : 101110100; 188 | 178 : 101110010; 189 | 179 : 101110001; 190 | 180 : 101110000; 191 | 181 : 101101111; 192 | 182 : 101101110; 193 | 183 : 101101101; 194 | 184 : 101101100; 195 | 185 : 101101100; 196 | 186 : 101101011; 197 | 187 : 101101011; 198 | 188 : 101101010; 199 | 189 : 101101010; 200 | 190 : 101101010; 201 | 191 : 101101010; 202 | 192 : 101101010; 203 | 193 : 101101010; 204 | 194 : 101101010; 205 | 195 : 101101010; 206 | 196 : 101101010; 207 | 197 : 101101011; 208 | 198 : 101101011; 209 | 199 : 101101100; 210 | 200 : 101101100; 211 | 201 : 101101101; 212 | 202 : 101101110; 213 | 203 : 101101111; 214 | 204 : 101110000; 215 | 205 : 101110001; 216 | 206 : 101110010; 217 | 207 : 101110100; 218 | 208 : 101110101; 219 | 209 : 101110110; 220 | 210 : 101111000; 221 | 211 : 101111010; 222 | 212 : 101111011; 223 | 213 : 101111101; 224 | 214 : 101111111; 225 | 215 : 110000001; 226 | 216 : 110000011; 227 | 217 : 110000101; 228 | 218 : 110000111; 229 | 219 : 110001001; 230 | 220 : 110001100; 231 | 221 : 110001110; 232 | 222 : 110010000; 233 | 223 : 110010011; 234 | 224 : 110010101; 235 | 225 : 110011000; 236 | 226 : 110011011; 237 | 227 : 110011110; 238 | 228 : 110100000; 239 | 229 : 110100011; 240 | 230 : 110100110; 241 | 231 : 110101001; 242 | 232 : 110101100; 243 | 233 : 110101111; 244 | 234 : 110110010; 245 | 235 : 110110110; 246 | 236 : 110111001; 247 | 237 : 110111100; 248 | 238 : 110111111; 249 | 239 : 111000011; 250 | 240 : 111000110; 251 | 241 : 111001010; 252 | 242 : 111001101; 253 | 243 : 111010000; 254 | 244 : 111010100; 255 | 245 : 111010111; 256 | 246 : 111011011; 257 | 247 : 111011111; 258 | 248 : 111100010; 259 | 249 : 111100110; 260 | 250 : 111101001; 261 | 251 : 111101101; 262 | 252 : 111110001; 263 | 253 : 111110100; 264 | 254 : 111111000; 265 | 255 : 111111100; 266 | 256 : 000000000; 267 | 257 : 000000011; 268 | 258 : 000000110; 269 | 259 : 000001001; 270 | 260 : 000001100; 271 | 261 : 000001111; 272 | 262 : 000010010; 273 | 263 : 000010110; 274 | 264 : 000011001; 275 | 265 : 000011100; 276 | 266 : 000011111; 277 | 267 : 000100010; 278 | 268 : 000100101; 279 | 269 : 000101000; 280 | 270 : 000101011; 281 | 271 : 000101110; 282 | 272 : 000110001; 283 | 273 : 000110100; 284 | 274 : 000110111; 285 | 275 : 000111001; 286 | 276 : 000111100; 287 | 277 : 000111111; 288 | 278 : 001000010; 289 | 279 : 001000101; 290 | 280 : 001000111; 291 | 281 : 001001010; 292 | 282 : 001001100; 293 | 283 : 001001111; 294 | 284 : 001010001; 295 | 285 : 001010100; 296 | 286 : 001010110; 297 | 287 : 001011000; 298 | 288 : 001011011; 299 | 289 : 001011101; 300 | 290 : 001011111; 301 | 291 : 001100001; 302 | 292 : 001100011; 303 | 293 : 001100101; 304 | 294 : 001100111; 305 | 295 : 001101001; 306 | 296 : 001101011; 307 | 297 : 001101100; 308 | 298 : 001101110; 309 | 299 : 001110000; 310 | 300 : 001110001; 311 | 301 : 001110011; 312 | 302 : 001110100; 313 | 303 : 001110101; 314 | 304 : 001110111; 315 | 305 : 001111000; 316 | 306 : 001111001; 317 | 307 : 001111010; 318 | 308 : 001111011; 319 | 309 : 001111100; 320 | 310 : 001111101; 321 | 311 : 001111101; 322 | 312 : 001111110; 323 | 313 : 001111111; 324 | 314 : 001111111; 325 | 315 : 010000000; 326 | 316 : 010000000; 327 | 317 : 010000000; 328 | 318 : 010000000; 329 | 319 : 010000000; 330 | 320 : 010000001; 331 | 321 : 010000000; 332 | 322 : 010000000; 333 | 323 : 010000000; 334 | 324 : 010000000; 335 | 325 : 010000000; 336 | 326 : 001111111; 337 | 327 : 001111111; 338 | 328 : 001111110; 339 | 329 : 001111101; 340 | 330 : 001111101; 341 | 331 : 001111100; 342 | 332 : 001111011; 343 | 333 : 001111010; 344 | 334 : 001111001; 345 | 335 : 001111000; 346 | 336 : 001110111; 347 | 337 : 001110101; 348 | 338 : 001110100; 349 | 339 : 001110011; 350 | 340 : 001110001; 351 | 341 : 001110000; 352 | 342 : 001101110; 353 | 343 : 001101100; 354 | 344 : 001101011; 355 | 345 : 001101001; 356 | 346 : 001100111; 357 | 347 : 001100101; 358 | 348 : 001100011; 359 | 349 : 001100001; 360 | 350 : 001011111; 361 | 351 : 001011101; 362 | 352 : 001011011; 363 | 353 : 001011000; 364 | 354 : 001010110; 365 | 355 : 001010100; 366 | 356 : 001010001; 367 | 357 : 001001111; 368 | 358 : 001001100; 369 | 359 : 001001010; 370 | 360 : 001000111; 371 | 361 : 001000101; 372 | 362 : 001000010; 373 | 363 : 000111111; 374 | 364 : 000111100; 375 | 365 : 000111001; 376 | 366 : 000110111; 377 | 367 : 000110100; 378 | 368 : 000110001; 379 | 369 : 000101110; 380 | 370 : 000101011; 381 | 371 : 000101000; 382 | 372 : 000100101; 383 | 373 : 000100010; 384 | 374 : 000011111; 385 | 375 : 000011100; 386 | 376 : 000011001; 387 | 377 : 000010110; 388 | 378 : 000010010; 389 | 379 : 000001111; 390 | 380 : 000001100; 391 | 381 : 000001001; 392 | 382 : 000000110; 393 | 383 : 000000011; 394 | 384 : 000000000; 395 | 385 : 111111100; 396 | 386 : 111111001; 397 | 387 : 111110110; 398 | 388 : 111110011; 399 | 389 : 111110000; 400 | 390 : 111101101; 401 | 391 : 111101001; 402 | 392 : 111100110; 403 | 393 : 111100011; 404 | 394 : 111100000; 405 | 395 : 111011101; 406 | 396 : 111011010; 407 | 397 : 111010111; 408 | 398 : 111010100; 409 | 399 : 111010001; 410 | 400 : 111001110; 411 | 401 : 111001011; 412 | 402 : 111001000; 413 | 403 : 111000110; 414 | 404 : 111000011; 415 | 405 : 111000000; 416 | 406 : 110111101; 417 | 407 : 110111010; 418 | 408 : 110111000; 419 | 409 : 110110101; 420 | 410 : 110110011; 421 | 411 : 110110000; 422 | 412 : 110101110; 423 | 413 : 110101011; 424 | 414 : 110101001; 425 | 415 : 110100111; 426 | 416 : 110100100; 427 | 417 : 110100010; 428 | 418 : 110100000; 429 | 419 : 110011110; 430 | 420 : 110011100; 431 | 421 : 110011010; 432 | 422 : 110011000; 433 | 423 : 110010110; 434 | 424 : 110010100; 435 | 425 : 110010011; 436 | 426 : 110010001; 437 | 427 : 110001111; 438 | 428 : 110001110; 439 | 429 : 110001100; 440 | 430 : 110001011; 441 | 431 : 110001010; 442 | 432 : 110001000; 443 | 433 : 110000111; 444 | 434 : 110000110; 445 | 435 : 110000101; 446 | 436 : 110000100; 447 | 437 : 110000011; 448 | 438 : 110000010; 449 | 439 : 110000010; 450 | 440 : 110000001; 451 | 441 : 110000000; 452 | 442 : 110000000; 453 | 443 : 101111111; 454 | 444 : 101111111; 455 | 445 : 101111111; 456 | 446 : 101111111; 457 | 447 : 101111111; 458 | 448 : 101111111; 459 | 449 : 101111111; 460 | 450 : 101111111; 461 | 451 : 101111111; 462 | 452 : 101111111; 463 | 453 : 101111111; 464 | 454 : 110000000; 465 | 455 : 110000000; 466 | 456 : 110000001; 467 | 457 : 110000010; 468 | 458 : 110000010; 469 | 459 : 110000011; 470 | 460 : 110000100; 471 | 461 : 110000101; 472 | 462 : 110000110; 473 | 463 : 110000111; 474 | 464 : 110001000; 475 | 465 : 110001010; 476 | 466 : 110001011; 477 | 467 : 110001100; 478 | 468 : 110001110; 479 | 469 : 110001111; 480 | 470 : 110010001; 481 | 471 : 110010011; 482 | 472 : 110010100; 483 | 473 : 110010110; 484 | 474 : 110011000; 485 | 475 : 110011010; 486 | 476 : 110011100; 487 | 477 : 110011110; 488 | 478 : 110100000; 489 | 479 : 110100010; 490 | 480 : 110100100; 491 | 481 : 110100111; 492 | 482 : 110101001; 493 | 483 : 110101011; 494 | 484 : 110101110; 495 | 485 : 110110000; 496 | 486 : 110110011; 497 | 487 : 110110101; 498 | 488 : 110111000; 499 | 489 : 110111010; 500 | 490 : 110111101; 501 | 491 : 111000000; 502 | 492 : 111000011; 503 | 493 : 111000110; 504 | 494 : 111001000; 505 | 495 : 111001011; 506 | 496 : 111001110; 507 | 497 : 111010001; 508 | 498 : 111010100; 509 | 499 : 111010111; 510 | 500 : 111011010; 511 | 501 : 111011101; 512 | 502 : 111100000; 513 | 503 : 111100011; 514 | 504 : 111100110; 515 | 505 : 111101001; 516 | 506 : 111101101; 517 | 507 : 111110000; 518 | 508 : 111110011; 519 | 509 : 111110110; 520 | 510 : 111111001; 521 | 511 : 111111100; 522 | 512 : 000000000; 523 | 513 : 000000010; 524 | 514 : 000000101; 525 | 515 : 000000111; 526 | 516 : 000001010; 527 | 517 : 000001101; 528 | 518 : 000001111; 529 | 519 : 000010010; 530 | 520 : 000010101; 531 | 521 : 000010111; 532 | 522 : 000011010; 533 | 523 : 000011100; 534 | 524 : 000011111; 535 | 525 : 000100001; 536 | 526 : 000100100; 537 | 527 : 000100110; 538 | 528 : 000101001; 539 | 529 : 000101011; 540 | 530 : 000101110; 541 | 531 : 000110000; 542 | 532 : 000110010; 543 | 533 : 000110101; 544 | 534 : 000110111; 545 | 535 : 000111001; 546 | 536 : 000111100; 547 | 537 : 000111110; 548 | 538 : 001000000; 549 | 539 : 001000010; 550 | 540 : 001000100; 551 | 541 : 001000110; 552 | 542 : 001001000; 553 | 543 : 001001010; 554 | 544 : 001001100; 555 | 545 : 001001110; 556 | 546 : 001010000; 557 | 547 : 001010001; 558 | 548 : 001010011; 559 | 549 : 001010101; 560 | 550 : 001010110; 561 | 551 : 001011000; 562 | 552 : 001011001; 563 | 553 : 001011011; 564 | 554 : 001011100; 565 | 555 : 001011101; 566 | 556 : 001011111; 567 | 557 : 001100000; 568 | 558 : 001100001; 569 | 559 : 001100010; 570 | 560 : 001100011; 571 | 561 : 001100100; 572 | 562 : 001100101; 573 | 563 : 001100110; 574 | 564 : 001100111; 575 | 565 : 001101000; 576 | 566 : 001101000; 577 | 567 : 001101001; 578 | 568 : 001101001; 579 | 569 : 001101010; 580 | 570 : 001101010; 581 | 571 : 001101011; 582 | 572 : 001101011; 583 | 573 : 001101011; 584 | 574 : 001101011; 585 | 575 : 001101011; 586 | 576 : 001101100; 587 | 577 : 001101011; 588 | 578 : 001101011; 589 | 579 : 001101011; 590 | 580 : 001101011; 591 | 581 : 001101011; 592 | 582 : 001101010; 593 | 583 : 001101010; 594 | 584 : 001101001; 595 | 585 : 001101001; 596 | 586 : 001101000; 597 | 587 : 001101000; 598 | 588 : 001100111; 599 | 589 : 001100110; 600 | 590 : 001100101; 601 | 591 : 001100100; 602 | 592 : 001100011; 603 | 593 : 001100010; 604 | 594 : 001100001; 605 | 595 : 001100000; 606 | 596 : 001011111; 607 | 597 : 001011101; 608 | 598 : 001011100; 609 | 599 : 001011011; 610 | 600 : 001011001; 611 | 601 : 001011000; 612 | 602 : 001010110; 613 | 603 : 001010101; 614 | 604 : 001010011; 615 | 605 : 001010001; 616 | 606 : 001010000; 617 | 607 : 001001110; 618 | 608 : 001001100; 619 | 609 : 001001010; 620 | 610 : 001001000; 621 | 611 : 001000110; 622 | 612 : 001000100; 623 | 613 : 001000010; 624 | 614 : 001000000; 625 | 615 : 000111110; 626 | 616 : 000111100; 627 | 617 : 000111001; 628 | 618 : 000110111; 629 | 619 : 000110101; 630 | 620 : 000110010; 631 | 621 : 000110000; 632 | 622 : 000101110; 633 | 623 : 000101011; 634 | 624 : 000101001; 635 | 625 : 000100110; 636 | 626 : 000100100; 637 | 627 : 000100001; 638 | 628 : 000011111; 639 | 629 : 000011100; 640 | 630 : 000011010; 641 | 631 : 000010111; 642 | 632 : 000010101; 643 | 633 : 000010010; 644 | 634 : 000001111; 645 | 635 : 000001101; 646 | 636 : 000001010; 647 | 637 : 000000111; 648 | 638 : 000000101; 649 | 639 : 000000010; 650 | 640 : 000000000; 651 | 641 : 111111101; 652 | 642 : 111111010; 653 | 643 : 111111000; 654 | 644 : 111110101; 655 | 645 : 111110010; 656 | 646 : 111110000; 657 | 647 : 111101101; 658 | 648 : 111101010; 659 | 649 : 111101000; 660 | 650 : 111100101; 661 | 651 : 111100011; 662 | 652 : 111100000; 663 | 653 : 111011110; 664 | 654 : 111011011; 665 | 655 : 111011001; 666 | 656 : 111010110; 667 | 657 : 111010100; 668 | 658 : 111010001; 669 | 659 : 111001111; 670 | 660 : 111001101; 671 | 661 : 111001010; 672 | 662 : 111001000; 673 | 663 : 111000110; 674 | 664 : 111000011; 675 | 665 : 111000001; 676 | 666 : 110111111; 677 | 667 : 110111101; 678 | 668 : 110111011; 679 | 669 : 110111001; 680 | 670 : 110110111; 681 | 671 : 110110101; 682 | 672 : 110110011; 683 | 673 : 110110001; 684 | 674 : 110101111; 685 | 675 : 110101110; 686 | 676 : 110101100; 687 | 677 : 110101010; 688 | 678 : 110101001; 689 | 679 : 110100111; 690 | 680 : 110100110; 691 | 681 : 110100100; 692 | 682 : 110100011; 693 | 683 : 110100010; 694 | 684 : 110100000; 695 | 685 : 110011111; 696 | 686 : 110011110; 697 | 687 : 110011101; 698 | 688 : 110011100; 699 | 689 : 110011011; 700 | 690 : 110011010; 701 | 691 : 110011001; 702 | 692 : 110011000; 703 | 693 : 110010111; 704 | 694 : 110010111; 705 | 695 : 110010110; 706 | 696 : 110010110; 707 | 697 : 110010101; 708 | 698 : 110010101; 709 | 699 : 110010100; 710 | 700 : 110010100; 711 | 701 : 110010100; 712 | 702 : 110010100; 713 | 703 : 110010100; 714 | 704 : 110010100; 715 | 705 : 110010100; 716 | 706 : 110010100; 717 | 707 : 110010100; 718 | 708 : 110010100; 719 | 709 : 110010100; 720 | 710 : 110010101; 721 | 711 : 110010101; 722 | 712 : 110010110; 723 | 713 : 110010110; 724 | 714 : 110010111; 725 | 715 : 110010111; 726 | 716 : 110011000; 727 | 717 : 110011001; 728 | 718 : 110011010; 729 | 719 : 110011011; 730 | 720 : 110011100; 731 | 721 : 110011101; 732 | 722 : 110011110; 733 | 723 : 110011111; 734 | 724 : 110100000; 735 | 725 : 110100010; 736 | 726 : 110100011; 737 | 727 : 110100100; 738 | 728 : 110100110; 739 | 729 : 110100111; 740 | 730 : 110101001; 741 | 731 : 110101010; 742 | 732 : 110101100; 743 | 733 : 110101110; 744 | 734 : 110101111; 745 | 735 : 110110001; 746 | 736 : 110110011; 747 | 737 : 110110101; 748 | 738 : 110110111; 749 | 739 : 110111001; 750 | 740 : 110111011; 751 | 741 : 110111101; 752 | 742 : 110111111; 753 | 743 : 111000001; 754 | 744 : 111000011; 755 | 745 : 111000110; 756 | 746 : 111001000; 757 | 747 : 111001010; 758 | 748 : 111001101; 759 | 749 : 111001111; 760 | 750 : 111010001; 761 | 751 : 111010100; 762 | 752 : 111010110; 763 | 753 : 111011001; 764 | 754 : 111011011; 765 | 755 : 111011110; 766 | 756 : 111100000; 767 | 757 : 111100011; 768 | 758 : 111100101; 769 | 759 : 111101000; 770 | 760 : 111101010; 771 | 761 : 111101101; 772 | 762 : 111110000; 773 | 763 : 111110010; 774 | 764 : 111110101; 775 | 765 : 111111000; 776 | 766 : 111111010; 777 | 767 : 111111101; 778 | 768 : 000000000; 779 | 769 : 000000010; 780 | 770 : 000000100; 781 | 771 : 000000110; 782 | 772 : 000001000; 783 | 773 : 000001010; 784 | 774 : 000001100; 785 | 775 : 000001110; 786 | 776 : 000010000; 787 | 777 : 000010011; 788 | 778 : 000010101; 789 | 779 : 000010111; 790 | 780 : 000011001; 791 | 781 : 000011011; 792 | 782 : 000011101; 793 | 783 : 000011111; 794 | 784 : 000100001; 795 | 785 : 000100011; 796 | 786 : 000100101; 797 | 787 : 000100111; 798 | 788 : 000101001; 799 | 789 : 000101010; 800 | 790 : 000101100; 801 | 791 : 000101110; 802 | 792 : 000110000; 803 | 793 : 000110010; 804 | 794 : 000110011; 805 | 795 : 000110101; 806 | 796 : 000110111; 807 | 797 : 000111000; 808 | 798 : 000111010; 809 | 799 : 000111011; 810 | 800 : 000111101; 811 | 801 : 000111111; 812 | 802 : 001000000; 813 | 803 : 001000001; 814 | 804 : 001000011; 815 | 805 : 001000100; 816 | 806 : 001000101; 817 | 807 : 001000111; 818 | 808 : 001001000; 819 | 809 : 001001001; 820 | 810 : 001001010; 821 | 811 : 001001011; 822 | 812 : 001001100; 823 | 813 : 001001101; 824 | 814 : 001001110; 825 | 815 : 001001111; 826 | 816 : 001010000; 827 | 817 : 001010001; 828 | 818 : 001010001; 829 | 819 : 001010010; 830 | 820 : 001010011; 831 | 821 : 001010011; 832 | 822 : 001010100; 833 | 823 : 001010100; 834 | 824 : 001010101; 835 | 825 : 001010101; 836 | 826 : 001010110; 837 | 827 : 001010110; 838 | 828 : 001010110; 839 | 829 : 001010110; 840 | 830 : 001010110; 841 | 831 : 001010110; 842 | 832 : 001010111; 843 | 833 : 001010110; 844 | 834 : 001010110; 845 | 835 : 001010110; 846 | 836 : 001010110; 847 | 837 : 001010110; 848 | 838 : 001010110; 849 | 839 : 001010101; 850 | 840 : 001010101; 851 | 841 : 001010100; 852 | 842 : 001010100; 853 | 843 : 001010011; 854 | 844 : 001010011; 855 | 845 : 001010010; 856 | 846 : 001010001; 857 | 847 : 001010001; 858 | 848 : 001010000; 859 | 849 : 001001111; 860 | 850 : 001001110; 861 | 851 : 001001101; 862 | 852 : 001001100; 863 | 853 : 001001011; 864 | 854 : 001001010; 865 | 855 : 001001001; 866 | 856 : 001001000; 867 | 857 : 001000111; 868 | 858 : 001000101; 869 | 859 : 001000100; 870 | 860 : 001000011; 871 | 861 : 001000001; 872 | 862 : 001000000; 873 | 863 : 000111111; 874 | 864 : 000111101; 875 | 865 : 000111011; 876 | 866 : 000111010; 877 | 867 : 000111000; 878 | 868 : 000110111; 879 | 869 : 000110101; 880 | 870 : 000110011; 881 | 871 : 000110010; 882 | 872 : 000110000; 883 | 873 : 000101110; 884 | 874 : 000101100; 885 | 875 : 000101010; 886 | 876 : 000101001; 887 | 877 : 000100111; 888 | 878 : 000100101; 889 | 879 : 000100011; 890 | 880 : 000100001; 891 | 881 : 000011111; 892 | 882 : 000011101; 893 | 883 : 000011011; 894 | 884 : 000011001; 895 | 885 : 000010111; 896 | 886 : 000010101; 897 | 887 : 000010011; 898 | 888 : 000010000; 899 | 889 : 000001110; 900 | 890 : 000001100; 901 | 891 : 000001010; 902 | 892 : 000001000; 903 | 893 : 000000110; 904 | 894 : 000000100; 905 | 895 : 000000010; 906 | 896 : 000000000; 907 | 897 : 111111101; 908 | 898 : 111111011; 909 | 899 : 111111001; 910 | 900 : 111110111; 911 | 901 : 111110101; 912 | 902 : 111110011; 913 | 903 : 111110001; 914 | 904 : 111101111; 915 | 905 : 111101100; 916 | 906 : 111101010; 917 | 907 : 111101000; 918 | 908 : 111100110; 919 | 909 : 111100100; 920 | 910 : 111100010; 921 | 911 : 111100000; 922 | 912 : 111011110; 923 | 913 : 111011100; 924 | 914 : 111011010; 925 | 915 : 111011000; 926 | 916 : 111010110; 927 | 917 : 111010101; 928 | 918 : 111010011; 929 | 919 : 111010001; 930 | 920 : 111001111; 931 | 921 : 111001101; 932 | 922 : 111001100; 933 | 923 : 111001010; 934 | 924 : 111001000; 935 | 925 : 111000111; 936 | 926 : 111000101; 937 | 927 : 111000100; 938 | 928 : 111000010; 939 | 929 : 111000000; 940 | 930 : 110111111; 941 | 931 : 110111110; 942 | 932 : 110111100; 943 | 933 : 110111011; 944 | 934 : 110111010; 945 | 935 : 110111000; 946 | 936 : 110110111; 947 | 937 : 110110110; 948 | 938 : 110110101; 949 | 939 : 110110100; 950 | 940 : 110110011; 951 | 941 : 110110010; 952 | 942 : 110110001; 953 | 943 : 110110000; 954 | 944 : 110101111; 955 | 945 : 110101110; 956 | 946 : 110101110; 957 | 947 : 110101101; 958 | 948 : 110101100; 959 | 949 : 110101100; 960 | 950 : 110101011; 961 | 951 : 110101011; 962 | 952 : 110101010; 963 | 953 : 110101010; 964 | 954 : 110101001; 965 | 955 : 110101001; 966 | 956 : 110101001; 967 | 957 : 110101001; 968 | 958 : 110101001; 969 | 959 : 110101001; 970 | 960 : 110101001; 971 | 961 : 110101001; 972 | 962 : 110101001; 973 | 963 : 110101001; 974 | 964 : 110101001; 975 | 965 : 110101001; 976 | 966 : 110101001; 977 | 967 : 110101010; 978 | 968 : 110101010; 979 | 969 : 110101011; 980 | 970 : 110101011; 981 | 971 : 110101100; 982 | 972 : 110101100; 983 | 973 : 110101101; 984 | 974 : 110101110; 985 | 975 : 110101110; 986 | 976 : 110101111; 987 | 977 : 110110000; 988 | 978 : 110110001; 989 | 979 : 110110010; 990 | 980 : 110110011; 991 | 981 : 110110100; 992 | 982 : 110110101; 993 | 983 : 110110110; 994 | 984 : 110110111; 995 | 985 : 110111000; 996 | 986 : 110111010; 997 | 987 : 110111011; 998 | 988 : 110111100; 999 | 989 : 110111110; 1000 | 990 : 110111111; 1001 | 991 : 111000000; 1002 | 992 : 111000010; 1003 | 993 : 111000100; 1004 | 994 : 111000101; 1005 | 995 : 111000111; 1006 | 996 : 111001000; 1007 | 997 : 111001010; 1008 | 998 : 111001100; 1009 | 999 : 111001101; 1010 | 1000 : 111001111; 1011 | 1001 : 111010001; 1012 | 1002 : 111010011; 1013 | 1003 : 111010101; 1014 | 1004 : 111010110; 1015 | 1005 : 111011000; 1016 | 1006 : 111011010; 1017 | 1007 : 111011100; 1018 | 1008 : 111011110; 1019 | 1009 : 111100000; 1020 | 1010 : 111100010; 1021 | 1011 : 111100100; 1022 | 1012 : 111100110; 1023 | 1013 : 111101000; 1024 | 1014 : 111101010; 1025 | 1015 : 111101100; 1026 | 1016 : 111101111; 1027 | 1017 : 111110001; 1028 | 1018 : 111110011; 1029 | 1019 : 111110101; 1030 | 1020 : 111110111; 1031 | 1021 : 111111001; 1032 | 1022 : 111111011; 1033 | 1023 : 111111101; 1034 | 1024 : 000000000; 1035 | 1025 : 000000001; 1036 | 1026 : 000000011; 1037 | 1027 : 000000100; 1038 | 1028 : 000000110; 1039 | 1029 : 000001000; 1040 | 1030 : 000001001; 1041 | 1031 : 000001011; 1042 | 1032 : 000001100; 1043 | 1033 : 000001110; 1044 | 1034 : 000010000; 1045 | 1035 : 000010001; 1046 | 1036 : 000010011; 1047 | 1037 : 000010100; 1048 | 1038 : 000010110; 1049 | 1039 : 000010111; 1050 | 1040 : 000011001; 1051 | 1041 : 000011010; 1052 | 1042 : 000011100; 1053 | 1043 : 000011101; 1054 | 1044 : 000011111; 1055 | 1045 : 000100000; 1056 | 1046 : 000100001; 1057 | 1047 : 000100011; 1058 | 1048 : 000100100; 1059 | 1049 : 000100110; 1060 | 1050 : 000100111; 1061 | 1051 : 000101000; 1062 | 1052 : 000101001; 1063 | 1053 : 000101011; 1064 | 1054 : 000101100; 1065 | 1055 : 000101101; 1066 | 1056 : 000101110; 1067 | 1057 : 000101111; 1068 | 1058 : 000110000; 1069 | 1059 : 000110001; 1070 | 1060 : 000110011; 1071 | 1061 : 000110100; 1072 | 1062 : 000110101; 1073 | 1063 : 000110101; 1074 | 1064 : 000110110; 1075 | 1065 : 000110111; 1076 | 1066 : 000111000; 1077 | 1067 : 000111001; 1078 | 1068 : 000111010; 1079 | 1069 : 000111010; 1080 | 1070 : 000111011; 1081 | 1071 : 000111100; 1082 | 1072 : 000111100; 1083 | 1073 : 000111101; 1084 | 1074 : 000111110; 1085 | 1075 : 000111110; 1086 | 1076 : 000111111; 1087 | 1077 : 000111111; 1088 | 1078 : 001000000; 1089 | 1079 : 001000000; 1090 | 1080 : 001000000; 1091 | 1081 : 001000001; 1092 | 1082 : 001000001; 1093 | 1083 : 001000001; 1094 | 1084 : 001000001; 1095 | 1085 : 001000001; 1096 | 1086 : 001000001; 1097 | 1087 : 001000001; 1098 | 1088 : 001000010; 1099 | 1089 : 001000001; 1100 | 1090 : 001000001; 1101 | 1091 : 001000001; 1102 | 1092 : 001000001; 1103 | 1093 : 001000001; 1104 | 1094 : 001000001; 1105 | 1095 : 001000001; 1106 | 1096 : 001000000; 1107 | 1097 : 001000000; 1108 | 1098 : 001000000; 1109 | 1099 : 000111111; 1110 | 1100 : 000111111; 1111 | 1101 : 000111110; 1112 | 1102 : 000111110; 1113 | 1103 : 000111101; 1114 | 1104 : 000111100; 1115 | 1105 : 000111100; 1116 | 1106 : 000111011; 1117 | 1107 : 000111010; 1118 | 1108 : 000111010; 1119 | 1109 : 000111001; 1120 | 1110 : 000111000; 1121 | 1111 : 000110111; 1122 | 1112 : 000110110; 1123 | 1113 : 000110101; 1124 | 1114 : 000110101; 1125 | 1115 : 000110100; 1126 | 1116 : 000110011; 1127 | 1117 : 000110001; 1128 | 1118 : 000110000; 1129 | 1119 : 000101111; 1130 | 1120 : 000101110; 1131 | 1121 : 000101101; 1132 | 1122 : 000101100; 1133 | 1123 : 000101011; 1134 | 1124 : 000101001; 1135 | 1125 : 000101000; 1136 | 1126 : 000100111; 1137 | 1127 : 000100110; 1138 | 1128 : 000100100; 1139 | 1129 : 000100011; 1140 | 1130 : 000100001; 1141 | 1131 : 000100000; 1142 | 1132 : 000011111; 1143 | 1133 : 000011101; 1144 | 1134 : 000011100; 1145 | 1135 : 000011010; 1146 | 1136 : 000011001; 1147 | 1137 : 000010111; 1148 | 1138 : 000010110; 1149 | 1139 : 000010100; 1150 | 1140 : 000010011; 1151 | 1141 : 000010001; 1152 | 1142 : 000010000; 1153 | 1143 : 000001110; 1154 | 1144 : 000001100; 1155 | 1145 : 000001011; 1156 | 1146 : 000001001; 1157 | 1147 : 000001000; 1158 | 1148 : 000000110; 1159 | 1149 : 000000100; 1160 | 1150 : 000000011; 1161 | 1151 : 000000001; 1162 | 1152 : 000000000; 1163 | 1153 : 111111110; 1164 | 1154 : 111111100; 1165 | 1155 : 111111011; 1166 | 1156 : 111111001; 1167 | 1157 : 111110111; 1168 | 1158 : 111110110; 1169 | 1159 : 111110100; 1170 | 1160 : 111110011; 1171 | 1161 : 111110001; 1172 | 1162 : 111101111; 1173 | 1163 : 111101110; 1174 | 1164 : 111101100; 1175 | 1165 : 111101011; 1176 | 1166 : 111101001; 1177 | 1167 : 111101000; 1178 | 1168 : 111100110; 1179 | 1169 : 111100101; 1180 | 1170 : 111100011; 1181 | 1171 : 111100010; 1182 | 1172 : 111100000; 1183 | 1173 : 111011111; 1184 | 1174 : 111011110; 1185 | 1175 : 111011100; 1186 | 1176 : 111011011; 1187 | 1177 : 111011001; 1188 | 1178 : 111011000; 1189 | 1179 : 111010111; 1190 | 1180 : 111010110; 1191 | 1181 : 111010100; 1192 | 1182 : 111010011; 1193 | 1183 : 111010010; 1194 | 1184 : 111010001; 1195 | 1185 : 111010000; 1196 | 1186 : 111001111; 1197 | 1187 : 111001110; 1198 | 1188 : 111001100; 1199 | 1189 : 111001011; 1200 | 1190 : 111001010; 1201 | 1191 : 111001010; 1202 | 1192 : 111001001; 1203 | 1193 : 111001000; 1204 | 1194 : 111000111; 1205 | 1195 : 111000110; 1206 | 1196 : 111000101; 1207 | 1197 : 111000101; 1208 | 1198 : 111000100; 1209 | 1199 : 111000011; 1210 | 1200 : 111000011; 1211 | 1201 : 111000010; 1212 | 1202 : 111000001; 1213 | 1203 : 111000001; 1214 | 1204 : 111000000; 1215 | 1205 : 111000000; 1216 | 1206 : 110111111; 1217 | 1207 : 110111111; 1218 | 1208 : 110111111; 1219 | 1209 : 110111110; 1220 | 1210 : 110111110; 1221 | 1211 : 110111110; 1222 | 1212 : 110111110; 1223 | 1213 : 110111110; 1224 | 1214 : 110111110; 1225 | 1215 : 110111110; 1226 | 1216 : 110111110; 1227 | 1217 : 110111110; 1228 | 1218 : 110111110; 1229 | 1219 : 110111110; 1230 | 1220 : 110111110; 1231 | 1221 : 110111110; 1232 | 1222 : 110111110; 1233 | 1223 : 110111110; 1234 | 1224 : 110111111; 1235 | 1225 : 110111111; 1236 | 1226 : 110111111; 1237 | 1227 : 111000000; 1238 | 1228 : 111000000; 1239 | 1229 : 111000001; 1240 | 1230 : 111000001; 1241 | 1231 : 111000010; 1242 | 1232 : 111000011; 1243 | 1233 : 111000011; 1244 | 1234 : 111000100; 1245 | 1235 : 111000101; 1246 | 1236 : 111000101; 1247 | 1237 : 111000110; 1248 | 1238 : 111000111; 1249 | 1239 : 111001000; 1250 | 1240 : 111001001; 1251 | 1241 : 111001010; 1252 | 1242 : 111001010; 1253 | 1243 : 111001011; 1254 | 1244 : 111001100; 1255 | 1245 : 111001110; 1256 | 1246 : 111001111; 1257 | 1247 : 111010000; 1258 | 1248 : 111010001; 1259 | 1249 : 111010010; 1260 | 1250 : 111010011; 1261 | 1251 : 111010100; 1262 | 1252 : 111010110; 1263 | 1253 : 111010111; 1264 | 1254 : 111011000; 1265 | 1255 : 111011001; 1266 | 1256 : 111011011; 1267 | 1257 : 111011100; 1268 | 1258 : 111011110; 1269 | 1259 : 111011111; 1270 | 1260 : 111100000; 1271 | 1261 : 111100010; 1272 | 1262 : 111100011; 1273 | 1263 : 111100101; 1274 | 1264 : 111100110; 1275 | 1265 : 111101000; 1276 | 1266 : 111101001; 1277 | 1267 : 111101011; 1278 | 1268 : 111101100; 1279 | 1269 : 111101110; 1280 | 1270 : 111101111; 1281 | 1271 : 111110001; 1282 | 1272 : 111110011; 1283 | 1273 : 111110100; 1284 | 1274 : 111110110; 1285 | 1275 : 111110111; 1286 | 1276 : 111111001; 1287 | 1277 : 111111011; 1288 | 1278 : 111111100; 1289 | 1279 : 111111110; 1290 | 1280 : 000000000; 1291 | 1281 : 000000001; 1292 | 1282 : 000000010; 1293 | 1283 : 000000011; 1294 | 1284 : 000000100; 1295 | 1285 : 000000101; 1296 | 1286 : 000000110; 1297 | 1287 : 000000111; 1298 | 1288 : 000001000; 1299 | 1289 : 000001001; 1300 | 1290 : 000001010; 1301 | 1291 : 000001100; 1302 | 1292 : 000001101; 1303 | 1293 : 000001110; 1304 | 1294 : 000001111; 1305 | 1295 : 000010000; 1306 | 1296 : 000010001; 1307 | 1297 : 000010010; 1308 | 1298 : 000010011; 1309 | 1299 : 000010100; 1310 | 1300 : 000010101; 1311 | 1301 : 000010110; 1312 | 1302 : 000010111; 1313 | 1303 : 000011000; 1314 | 1304 : 000011001; 1315 | 1305 : 000011001; 1316 | 1306 : 000011010; 1317 | 1307 : 000011011; 1318 | 1308 : 000011100; 1319 | 1309 : 000011101; 1320 | 1310 : 000011110; 1321 | 1311 : 000011111; 1322 | 1312 : 000011111; 1323 | 1313 : 000100000; 1324 | 1314 : 000100001; 1325 | 1315 : 000100010; 1326 | 1316 : 000100010; 1327 | 1317 : 000100011; 1328 | 1318 : 000100100; 1329 | 1319 : 000100100; 1330 | 1320 : 000100101; 1331 | 1321 : 000100110; 1332 | 1322 : 000100110; 1333 | 1323 : 000100111; 1334 | 1324 : 000100111; 1335 | 1325 : 000101000; 1336 | 1326 : 000101000; 1337 | 1327 : 000101001; 1338 | 1328 : 000101001; 1339 | 1329 : 000101001; 1340 | 1330 : 000101010; 1341 | 1331 : 000101010; 1342 | 1332 : 000101011; 1343 | 1333 : 000101011; 1344 | 1334 : 000101011; 1345 | 1335 : 000101011; 1346 | 1336 : 000101100; 1347 | 1337 : 000101100; 1348 | 1338 : 000101100; 1349 | 1339 : 000101100; 1350 | 1340 : 000101100; 1351 | 1341 : 000101100; 1352 | 1342 : 000101100; 1353 | 1343 : 000101100; 1354 | 1344 : 000101101; 1355 | 1345 : 000101100; 1356 | 1346 : 000101100; 1357 | 1347 : 000101100; 1358 | 1348 : 000101100; 1359 | 1349 : 000101100; 1360 | 1350 : 000101100; 1361 | 1351 : 000101100; 1362 | 1352 : 000101100; 1363 | 1353 : 000101011; 1364 | 1354 : 000101011; 1365 | 1355 : 000101011; 1366 | 1356 : 000101011; 1367 | 1357 : 000101010; 1368 | 1358 : 000101010; 1369 | 1359 : 000101001; 1370 | 1360 : 000101001; 1371 | 1361 : 000101001; 1372 | 1362 : 000101000; 1373 | 1363 : 000101000; 1374 | 1364 : 000100111; 1375 | 1365 : 000100111; 1376 | 1366 : 000100110; 1377 | 1367 : 000100110; 1378 | 1368 : 000100101; 1379 | 1369 : 000100100; 1380 | 1370 : 000100100; 1381 | 1371 : 000100011; 1382 | 1372 : 000100010; 1383 | 1373 : 000100010; 1384 | 1374 : 000100001; 1385 | 1375 : 000100000; 1386 | 1376 : 000011111; 1387 | 1377 : 000011111; 1388 | 1378 : 000011110; 1389 | 1379 : 000011101; 1390 | 1380 : 000011100; 1391 | 1381 : 000011011; 1392 | 1382 : 000011010; 1393 | 1383 : 000011001; 1394 | 1384 : 000011001; 1395 | 1385 : 000011000; 1396 | 1386 : 000010111; 1397 | 1387 : 000010110; 1398 | 1388 : 000010101; 1399 | 1389 : 000010100; 1400 | 1390 : 000010011; 1401 | 1391 : 000010010; 1402 | 1392 : 000010001; 1403 | 1393 : 000010000; 1404 | 1394 : 000001111; 1405 | 1395 : 000001110; 1406 | 1396 : 000001101; 1407 | 1397 : 000001100; 1408 | 1398 : 000001010; 1409 | 1399 : 000001001; 1410 | 1400 : 000001000; 1411 | 1401 : 000000111; 1412 | 1402 : 000000110; 1413 | 1403 : 000000101; 1414 | 1404 : 000000100; 1415 | 1405 : 000000011; 1416 | 1406 : 000000010; 1417 | 1407 : 000000001; 1418 | 1408 : 000000000; 1419 | 1409 : 111111110; 1420 | 1410 : 111111101; 1421 | 1411 : 111111100; 1422 | 1412 : 111111011; 1423 | 1413 : 111111010; 1424 | 1414 : 111111001; 1425 | 1415 : 111111000; 1426 | 1416 : 111110111; 1427 | 1417 : 111110110; 1428 | 1418 : 111110101; 1429 | 1419 : 111110011; 1430 | 1420 : 111110010; 1431 | 1421 : 111110001; 1432 | 1422 : 111110000; 1433 | 1423 : 111101111; 1434 | 1424 : 111101110; 1435 | 1425 : 111101101; 1436 | 1426 : 111101100; 1437 | 1427 : 111101011; 1438 | 1428 : 111101010; 1439 | 1429 : 111101001; 1440 | 1430 : 111101000; 1441 | 1431 : 111100111; 1442 | 1432 : 111100110; 1443 | 1433 : 111100110; 1444 | 1434 : 111100101; 1445 | 1435 : 111100100; 1446 | 1436 : 111100011; 1447 | 1437 : 111100010; 1448 | 1438 : 111100001; 1449 | 1439 : 111100000; 1450 | 1440 : 111100000; 1451 | 1441 : 111011111; 1452 | 1442 : 111011110; 1453 | 1443 : 111011101; 1454 | 1444 : 111011101; 1455 | 1445 : 111011100; 1456 | 1446 : 111011011; 1457 | 1447 : 111011011; 1458 | 1448 : 111011010; 1459 | 1449 : 111011001; 1460 | 1450 : 111011001; 1461 | 1451 : 111011000; 1462 | 1452 : 111011000; 1463 | 1453 : 111010111; 1464 | 1454 : 111010111; 1465 | 1455 : 111010110; 1466 | 1456 : 111010110; 1467 | 1457 : 111010110; 1468 | 1458 : 111010101; 1469 | 1459 : 111010101; 1470 | 1460 : 111010100; 1471 | 1461 : 111010100; 1472 | 1462 : 111010100; 1473 | 1463 : 111010100; 1474 | 1464 : 111010011; 1475 | 1465 : 111010011; 1476 | 1466 : 111010011; 1477 | 1467 : 111010011; 1478 | 1468 : 111010011; 1479 | 1469 : 111010011; 1480 | 1470 : 111010011; 1481 | 1471 : 111010011; 1482 | 1472 : 111010011; 1483 | 1473 : 111010011; 1484 | 1474 : 111010011; 1485 | 1475 : 111010011; 1486 | 1476 : 111010011; 1487 | 1477 : 111010011; 1488 | 1478 : 111010011; 1489 | 1479 : 111010011; 1490 | 1480 : 111010011; 1491 | 1481 : 111010100; 1492 | 1482 : 111010100; 1493 | 1483 : 111010100; 1494 | 1484 : 111010100; 1495 | 1485 : 111010101; 1496 | 1486 : 111010101; 1497 | 1487 : 111010110; 1498 | 1488 : 111010110; 1499 | 1489 : 111010110; 1500 | 1490 : 111010111; 1501 | 1491 : 111010111; 1502 | 1492 : 111011000; 1503 | 1493 : 111011000; 1504 | 1494 : 111011001; 1505 | 1495 : 111011001; 1506 | 1496 : 111011010; 1507 | 1497 : 111011011; 1508 | 1498 : 111011011; 1509 | 1499 : 111011100; 1510 | 1500 : 111011101; 1511 | 1501 : 111011101; 1512 | 1502 : 111011110; 1513 | 1503 : 111011111; 1514 | 1504 : 111100000; 1515 | 1505 : 111100000; 1516 | 1506 : 111100001; 1517 | 1507 : 111100010; 1518 | 1508 : 111100011; 1519 | 1509 : 111100100; 1520 | 1510 : 111100101; 1521 | 1511 : 111100110; 1522 | 1512 : 111100110; 1523 | 1513 : 111100111; 1524 | 1514 : 111101000; 1525 | 1515 : 111101001; 1526 | 1516 : 111101010; 1527 | 1517 : 111101011; 1528 | 1518 : 111101100; 1529 | 1519 : 111101101; 1530 | 1520 : 111101110; 1531 | 1521 : 111101111; 1532 | 1522 : 111110000; 1533 | 1523 : 111110001; 1534 | 1524 : 111110010; 1535 | 1525 : 111110011; 1536 | 1526 : 111110101; 1537 | 1527 : 111110110; 1538 | 1528 : 111110111; 1539 | 1529 : 111111000; 1540 | 1530 : 111111001; 1541 | 1531 : 111111010; 1542 | 1532 : 111111011; 1543 | 1533 : 111111100; 1544 | 1534 : 111111101; 1545 | 1535 : 111111110; 1546 | 1536 : 000000000; 1547 | 1537 : 000000000; 1548 | 1538 : 000000001; 1549 | 1539 : 000000001; 1550 | 1540 : 000000010; 1551 | 1541 : 000000010; 1552 | 1542 : 000000011; 1553 | 1543 : 000000100; 1554 | 1544 : 000000100; 1555 | 1545 : 000000101; 1556 | 1546 : 000000101; 1557 | 1547 : 000000110; 1558 | 1548 : 000000110; 1559 | 1549 : 000000111; 1560 | 1550 : 000001000; 1561 | 1551 : 000001000; 1562 | 1552 : 000001001; 1563 | 1553 : 000001001; 1564 | 1554 : 000001010; 1565 | 1555 : 000001010; 1566 | 1556 : 000001011; 1567 | 1557 : 000001011; 1568 | 1558 : 000001100; 1569 | 1559 : 000001100; 1570 | 1560 : 000001101; 1571 | 1561 : 000001101; 1572 | 1562 : 000001110; 1573 | 1563 : 000001110; 1574 | 1564 : 000001111; 1575 | 1565 : 000001111; 1576 | 1566 : 000010000; 1577 | 1567 : 000010000; 1578 | 1568 : 000010000; 1579 | 1569 : 000010001; 1580 | 1570 : 000010001; 1581 | 1571 : 000010010; 1582 | 1572 : 000010010; 1583 | 1573 : 000010010; 1584 | 1574 : 000010011; 1585 | 1575 : 000010011; 1586 | 1576 : 000010011; 1587 | 1577 : 000010100; 1588 | 1578 : 000010100; 1589 | 1579 : 000010100; 1590 | 1580 : 000010101; 1591 | 1581 : 000010101; 1592 | 1582 : 000010101; 1593 | 1583 : 000010101; 1594 | 1584 : 000010110; 1595 | 1585 : 000010110; 1596 | 1586 : 000010110; 1597 | 1587 : 000010110; 1598 | 1588 : 000010110; 1599 | 1589 : 000010111; 1600 | 1590 : 000010111; 1601 | 1591 : 000010111; 1602 | 1592 : 000010111; 1603 | 1593 : 000010111; 1604 | 1594 : 000010111; 1605 | 1595 : 000010111; 1606 | 1596 : 000010111; 1607 | 1597 : 000010111; 1608 | 1598 : 000010111; 1609 | 1599 : 000010111; 1610 | 1600 : 000011000; 1611 | 1601 : 000010111; 1612 | 1602 : 000010111; 1613 | 1603 : 000010111; 1614 | 1604 : 000010111; 1615 | 1605 : 000010111; 1616 | 1606 : 000010111; 1617 | 1607 : 000010111; 1618 | 1608 : 000010111; 1619 | 1609 : 000010111; 1620 | 1610 : 000010111; 1621 | 1611 : 000010111; 1622 | 1612 : 000010110; 1623 | 1613 : 000010110; 1624 | 1614 : 000010110; 1625 | 1615 : 000010110; 1626 | 1616 : 000010110; 1627 | 1617 : 000010101; 1628 | 1618 : 000010101; 1629 | 1619 : 000010101; 1630 | 1620 : 000010101; 1631 | 1621 : 000010100; 1632 | 1622 : 000010100; 1633 | 1623 : 000010100; 1634 | 1624 : 000010011; 1635 | 1625 : 000010011; 1636 | 1626 : 000010011; 1637 | 1627 : 000010010; 1638 | 1628 : 000010010; 1639 | 1629 : 000010010; 1640 | 1630 : 000010001; 1641 | 1631 : 000010001; 1642 | 1632 : 000010000; 1643 | 1633 : 000010000; 1644 | 1634 : 000010000; 1645 | 1635 : 000001111; 1646 | 1636 : 000001111; 1647 | 1637 : 000001110; 1648 | 1638 : 000001110; 1649 | 1639 : 000001101; 1650 | 1640 : 000001101; 1651 | 1641 : 000001100; 1652 | 1642 : 000001100; 1653 | 1643 : 000001011; 1654 | 1644 : 000001011; 1655 | 1645 : 000001010; 1656 | 1646 : 000001010; 1657 | 1647 : 000001001; 1658 | 1648 : 000001001; 1659 | 1649 : 000001000; 1660 | 1650 : 000001000; 1661 | 1651 : 000000111; 1662 | 1652 : 000000110; 1663 | 1653 : 000000110; 1664 | 1654 : 000000101; 1665 | 1655 : 000000101; 1666 | 1656 : 000000100; 1667 | 1657 : 000000100; 1668 | 1658 : 000000011; 1669 | 1659 : 000000010; 1670 | 1660 : 000000010; 1671 | 1661 : 000000001; 1672 | 1662 : 000000001; 1673 | 1663 : 000000000; 1674 | 1664 : 000000000; 1675 | 1665 : 111111111; 1676 | 1666 : 111111110; 1677 | 1667 : 111111110; 1678 | 1668 : 111111101; 1679 | 1669 : 111111101; 1680 | 1670 : 111111100; 1681 | 1671 : 111111011; 1682 | 1672 : 111111011; 1683 | 1673 : 111111010; 1684 | 1674 : 111111010; 1685 | 1675 : 111111001; 1686 | 1676 : 111111001; 1687 | 1677 : 111111000; 1688 | 1678 : 111110111; 1689 | 1679 : 111110111; 1690 | 1680 : 111110110; 1691 | 1681 : 111110110; 1692 | 1682 : 111110101; 1693 | 1683 : 111110101; 1694 | 1684 : 111110100; 1695 | 1685 : 111110100; 1696 | 1686 : 111110011; 1697 | 1687 : 111110011; 1698 | 1688 : 111110010; 1699 | 1689 : 111110010; 1700 | 1690 : 111110001; 1701 | 1691 : 111110001; 1702 | 1692 : 111110000; 1703 | 1693 : 111110000; 1704 | 1694 : 111101111; 1705 | 1695 : 111101111; 1706 | 1696 : 111101111; 1707 | 1697 : 111101110; 1708 | 1698 : 111101110; 1709 | 1699 : 111101101; 1710 | 1700 : 111101101; 1711 | 1701 : 111101101; 1712 | 1702 : 111101100; 1713 | 1703 : 111101100; 1714 | 1704 : 111101100; 1715 | 1705 : 111101011; 1716 | 1706 : 111101011; 1717 | 1707 : 111101011; 1718 | 1708 : 111101010; 1719 | 1709 : 111101010; 1720 | 1710 : 111101010; 1721 | 1711 : 111101010; 1722 | 1712 : 111101001; 1723 | 1713 : 111101001; 1724 | 1714 : 111101001; 1725 | 1715 : 111101001; 1726 | 1716 : 111101001; 1727 | 1717 : 111101000; 1728 | 1718 : 111101000; 1729 | 1719 : 111101000; 1730 | 1720 : 111101000; 1731 | 1721 : 111101000; 1732 | 1722 : 111101000; 1733 | 1723 : 111101000; 1734 | 1724 : 111101000; 1735 | 1725 : 111101000; 1736 | 1726 : 111101000; 1737 | 1727 : 111101000; 1738 | 1728 : 111101000; 1739 | 1729 : 111101000; 1740 | 1730 : 111101000; 1741 | 1731 : 111101000; 1742 | 1732 : 111101000; 1743 | 1733 : 111101000; 1744 | 1734 : 111101000; 1745 | 1735 : 111101000; 1746 | 1736 : 111101000; 1747 | 1737 : 111101000; 1748 | 1738 : 111101000; 1749 | 1739 : 111101000; 1750 | 1740 : 111101001; 1751 | 1741 : 111101001; 1752 | 1742 : 111101001; 1753 | 1743 : 111101001; 1754 | 1744 : 111101001; 1755 | 1745 : 111101010; 1756 | 1746 : 111101010; 1757 | 1747 : 111101010; 1758 | 1748 : 111101010; 1759 | 1749 : 111101011; 1760 | 1750 : 111101011; 1761 | 1751 : 111101011; 1762 | 1752 : 111101100; 1763 | 1753 : 111101100; 1764 | 1754 : 111101100; 1765 | 1755 : 111101101; 1766 | 1756 : 111101101; 1767 | 1757 : 111101101; 1768 | 1758 : 111101110; 1769 | 1759 : 111101110; 1770 | 1760 : 111101111; 1771 | 1761 : 111101111; 1772 | 1762 : 111101111; 1773 | 1763 : 111110000; 1774 | 1764 : 111110000; 1775 | 1765 : 111110001; 1776 | 1766 : 111110001; 1777 | 1767 : 111110010; 1778 | 1768 : 111110010; 1779 | 1769 : 111110011; 1780 | 1770 : 111110011; 1781 | 1771 : 111110100; 1782 | 1772 : 111110100; 1783 | 1773 : 111110101; 1784 | 1774 : 111110101; 1785 | 1775 : 111110110; 1786 | 1776 : 111110110; 1787 | 1777 : 111110111; 1788 | 1778 : 111110111; 1789 | 1779 : 111111000; 1790 | 1780 : 111111001; 1791 | 1781 : 111111001; 1792 | 1782 : 111111010; 1793 | 1783 : 111111010; 1794 | 1784 : 111111011; 1795 | 1785 : 111111011; 1796 | 1786 : 111111100; 1797 | 1787 : 111111101; 1798 | 1788 : 111111101; 1799 | 1789 : 111111110; 1800 | 1790 : 111111110; 1801 | 1791 : 111111111; 1802 | END; 1803 | -------------------------------------------------------------------------------- /data/generate_sinetable.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import os 4 | 5 | amplitude = 150 6 | length = 256 7 | width = 9 8 | steps = 7 9 | amplitude_step = amplitude / steps 10 | 11 | for i in range(1, steps + 1) : 12 | cmd = "romswak sine -width {0} -length {1} -amplitude {2} -o sine{3}.bin -signed".format(width, length, amplitude, i) 13 | amplitude = int(amplitude - amplitude_step) 14 | print cmd 15 | os.system(cmd) 16 | 17 | makemif = "romswak data " 18 | for i in range(1, steps + 1) : 19 | makemif = makemif + "sine{0}.bin ".format(i) 20 | makemif = makemif + "-o color_carrier_sine.mif -mif -width {0}".format(width) 21 | print makemif 22 | os.system(makemif) 23 | 24 | rm = "rm sine*.bin" 25 | os.system(rm) 26 | 27 | -------------------------------------------------------------------------------- /data/testimage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elpuri/NTSC-composite-encoder/265bad8b2af6c17e97fbf4c14b579f50b01a5f12/data/testimage.png -------------------------------------------------------------------------------- /demo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elpuri/NTSC-composite-encoder/265bad8b2af6c17e97fbf4c14b579f50b01a5f12/demo.jpg -------------------------------------------------------------------------------- /quartus/ntsc_composite.qpf: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------------- # 2 | # 3 | # Copyright (C) 1991-2012 Altera Corporation 4 | # Your use of Altera Corporation's design tools, logic functions 5 | # and other software and tools, and its AMPP partner logic 6 | # functions, and any output files from any of the foregoing 7 | # (including device programming or simulation files), and any 8 | # associated documentation or information are expressly subject 9 | # to the terms and conditions of the Altera Program License 10 | # Subscription Agreement, Altera MegaCore Function License 11 | # Agreement, or other applicable license agreement, including, 12 | # without limitation, that your use is for the sole purpose of 13 | # programming logic devices manufactured by Altera and sold by 14 | # Altera or its authorized distributors. Please refer to the 15 | # applicable agreement for further details. 16 | # 17 | # -------------------------------------------------------------------------- # 18 | # 19 | # Quartus II 32-bit 20 | # Version 12.1 Build 243 01/31/2013 Service Pack 1 SJ Web Edition 21 | # Date created = 16:05:45 February 17, 2014 22 | # 23 | # -------------------------------------------------------------------------- # 24 | 25 | QUARTUS_VERSION = "12.1" 26 | DATE = "16:05:45 February 17, 2014" 27 | 28 | # Revisions 29 | 30 | PROJECT_REVISION = "ntsc_composite_top_de2" 31 | -------------------------------------------------------------------------------- /tools/imgpacker.pro: -------------------------------------------------------------------------------- 1 | #------------------------------------------------- 2 | # 3 | # Project created by QtCreator 2014-02-17T01:09:26 4 | # 5 | #------------------------------------------------- 6 | 7 | QT += core gui 8 | 9 | TARGET = imgpacker 10 | CONFIG += console 11 | CONFIG -= app_bundle 12 | 13 | TEMPLATE = app 14 | 15 | 16 | SOURCES += main.cpp 17 | -------------------------------------------------------------------------------- /tools/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | QString intToBin(int a, int width) { 9 | QString bin; 10 | for (int i = 0; i < width; i++) { 11 | bin.prepend(a & 1 ? "1" : "0"); 12 | a = a >> 1; 13 | } 14 | return bin; 15 | } 16 | 17 | int main(int argc, char *argv[]) 18 | { 19 | QCoreApplication a(argc, argv); 20 | 21 | if (argc < 4) { 22 | qDebug() << "Usage imgpacker "; 23 | return 0; 24 | } 25 | 26 | QImage source(a.arguments().at(1)); 27 | if (source.isNull()) { 28 | qDebug() << "Couldn't open input image" << a.arguments().at(1); 29 | } 30 | 31 | if (source.format() != QImage::Format_Indexed8) { 32 | qDebug() << "Pixel format must be indexed color"; 33 | return 0; 34 | } 35 | 36 | if (source.colorCount() > 16) { 37 | qDebug() << "Color count must be <= 16. The source file has" << source.colorCount() << "colors."; 38 | return 0; 39 | } 40 | 41 | if (source.width() & 1) { 42 | qDebug() << "Image width must be an even number"; 43 | return 0; 44 | } 45 | 46 | QFile target(a.arguments().at(2)); 47 | if (!target.open(QFile::WriteOnly)) { 48 | qDebug() << "Couldn't open target file" << a.arguments().at(2); 49 | return 0; 50 | } 51 | 52 | // Pack two 4-bit pixels into one byte 53 | // Wider word is cheaper on the FPGA when synthesizing the ROM 54 | QByteArray data; 55 | data.reserve(source.width() * source.height() / 2); 56 | for (int y = 0; y < source.height(); y++) { 57 | for (int x = 0; x < source.width(); x += 2) { 58 | unsigned char b = source.pixelIndex(x, y) << 4; 59 | b |= source.pixelIndex(x + 1, y); 60 | data.append(b); 61 | } 62 | } 63 | 64 | target.write(data); 65 | target.close(); 66 | 67 | // Generate palette 68 | QFile paletteFile(a.arguments().at(3)); 69 | if (!paletteFile.open(QFile::WriteOnly)); 70 | 71 | QTextStream output(&paletteFile); 72 | output << "-- Copyright (c) 2014, Juha Turunen" << endl; 73 | output << "-- All rights reserved." << endl; 74 | output << "--" << endl; 75 | output << "-- Redistribution and use in source and binary forms, with or without" << endl; 76 | output << "-- modification, are permitted provided that the following conditions are met: " << endl; 77 | output << "--" << endl; 78 | output << "-- 1. Redistributions of source code must retain the above copyright notice, this" << endl; 79 | output << "-- list of conditions and the following disclaimer. " << endl; 80 | output << "-- 2. Redistributions in binary form must reproduce the above copyright notice," << endl; 81 | output << "-- this list of conditions and the following disclaimer in the documentation" << endl; 82 | output << "-- and/or other materials provided with the distribution. " << endl; 83 | output << "--" << endl; 84 | output << "-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND" << endl; 85 | output << "-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED" << endl; 86 | output << "-- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE" << endl; 87 | output << "-- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR" << endl; 88 | output << "-- ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES" << endl; 89 | output << "-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;" << endl; 90 | output << "-- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND" << endl; 91 | output << "-- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT" << endl; 92 | output << "-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS" << endl; 93 | output << "-- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." << endl; 94 | output << endl; 95 | output << "library IEEE;" << endl; 96 | output << "use IEEE.STD_LOGIC_1164.ALL;" << endl; 97 | output << "use IEEE.STD_LOGIC_ARITH.ALL;" << endl; 98 | output << "use IEEE.STD_LOGIC_UNSIGNED.ALL;" << endl; 99 | output << endl; 100 | output << "entity palette is Port ( " << endl; 101 | output << " index : in std_logic_vector(3 downto 0);" << endl; 102 | output << " luma : out std_logic_vector(10 downto 0);" << endl; 103 | output << " phase : out std_logic_vector(7 downto 0);" << endl; 104 | output << " chroma : out std_logic_vector(2 downto 0)" << endl; 105 | output << " );" << endl; 106 | output << "end palette;" << endl; 107 | output << endl; 108 | output << "architecture Behavioral of palette is" << endl; 109 | output << "begin" << endl; 110 | output << endl; 111 | 112 | output << "\tluma <=" << endl; 113 | QVector colors = source.colorTable(); 114 | int i = 0; 115 | foreach (QRgb color, colors) { 116 | QColor c(color); 117 | float l = c.redF() * 0.299 + c.greenF() * 0.587 + c.blueF() * 0.114; 118 | int luma = 278 + l * 1023; 119 | if (i != colors.count() - 1) 120 | output << "\t\tconv_std_logic_vector(" << luma << ", 11) when index = \"" << intToBin(i, 4) << "\" else" << endl; 121 | else 122 | output << "\t\tconv_std_logic_vector(" << luma << ", 11);" << endl; 123 | i++; 124 | } 125 | 126 | output << endl; 127 | 128 | i = 0; 129 | output << "\tchroma <=" << endl; 130 | 131 | foreach (QRgb color, colors) { 132 | QColor c(color); 133 | QColor hsv = c.toHsv(); 134 | int chroma = (1.0 - c.saturationF()) * 7; 135 | if (c.saturationF() < 0.1) 136 | chroma = 7; 137 | if (i != colors.count() - 1) 138 | output << "\t\t\"" << intToBin(chroma, 3) << "\" when index = \"" << intToBin(i, 4) << "\" else" << endl; 139 | else 140 | output << "\t\t\"" << intToBin(chroma, 3) << "\";" << endl; 141 | i++; 142 | } 143 | 144 | 145 | i = 0; 146 | output << "\tphase <=" << endl; 147 | 148 | foreach (QRgb color, colors) { 149 | QColor c(color); 150 | float hue = c.hslHueF() - 0.166; 151 | if (hue > 0.5) hue -= 1.0; 152 | int phase = hue * 255.0; 153 | 154 | if (i != colors.count() - 1) 155 | output << "\t\t\"" << intToBin(phase, 8) << "\" when index = \"" << intToBin(i, 4) << "\" else" << endl; 156 | else 157 | output << "\t\t\"" << intToBin(phase, 8) << "\";" << endl; 158 | i++; 159 | } 160 | 161 | output << endl; 162 | output << "end Behavioral;" << endl; 163 | 164 | output.flush(); 165 | paletteFile.close(); 166 | } 167 | 168 | -------------------------------------------------------------------------------- /tools/process_image.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ./imgpacker ../data/testimage.png image_rom.bin ../vhdl/palette.vhdl 3 | romswak data image_rom.bin -width 8 -mif -o ../data/image_rom.mif 4 | rm image_rom.bin 5 | -------------------------------------------------------------------------------- /vhdl/image_rom.vhdl: -------------------------------------------------------------------------------- 1 | -- megafunction wizard: %ROM: 1-PORT% 2 | -- GENERATION: STANDARD 3 | -- VERSION: WM1.0 4 | -- MODULE: altsyncram 5 | 6 | -- ============================================================ 7 | -- File Name: image_rom.vhd 8 | -- Megafunction Name(s): 9 | -- altsyncram 10 | -- 11 | -- Simulation Library Files(s): 12 | -- altera_mf 13 | -- ============================================================ 14 | -- ************************************************************ 15 | -- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! 16 | -- 17 | -- 11.0 Build 208 07/03/2011 SP 1 SJ Web Edition 18 | -- ************************************************************ 19 | 20 | 21 | --Copyright (C) 1991-2011 Altera Corporation 22 | --Your use of Altera Corporation's design tools, logic functions 23 | --and other software and tools, and its AMPP partner logic 24 | --functions, and any output files from any of the foregoing 25 | --(including device programming or simulation files), and any 26 | --associated documentation or information are expressly subject 27 | --to the terms and conditions of the Altera Program License 28 | --Subscription Agreement, Altera MegaCore Function License 29 | --Agreement, or other applicable license agreement, including, 30 | --without limitation, that your use is for the sole purpose of 31 | --programming logic devices manufactured by Altera and sold by 32 | --Altera or its authorized distributors. Please refer to the 33 | --applicable agreement for further details. 34 | 35 | 36 | LIBRARY ieee; 37 | USE ieee.std_logic_1164.all; 38 | 39 | LIBRARY altera_mf; 40 | USE altera_mf.all; 41 | 42 | ENTITY image_rom IS 43 | PORT 44 | ( 45 | address : IN STD_LOGIC_VECTOR (15 DOWNTO 0); 46 | clock : IN STD_LOGIC := '1'; 47 | q : OUT STD_LOGIC_VECTOR (7 DOWNTO 0) 48 | ); 49 | END image_rom; 50 | 51 | 52 | ARCHITECTURE SYN OF image_rom IS 53 | 54 | SIGNAL sub_wire0 : STD_LOGIC_VECTOR (7 DOWNTO 0); 55 | 56 | 57 | 58 | COMPONENT altsyncram 59 | GENERIC ( 60 | clock_enable_input_a : STRING; 61 | clock_enable_output_a : STRING; 62 | init_file : STRING; 63 | intended_device_family : STRING; 64 | lpm_hint : STRING; 65 | lpm_type : STRING; 66 | numwords_a : NATURAL; 67 | operation_mode : STRING; 68 | outdata_aclr_a : STRING; 69 | outdata_reg_a : STRING; 70 | widthad_a : NATURAL; 71 | width_a : NATURAL; 72 | width_byteena_a : NATURAL 73 | ); 74 | PORT ( 75 | address_a : IN STD_LOGIC_VECTOR (15 DOWNTO 0); 76 | clock0 : IN STD_LOGIC ; 77 | q_a : OUT STD_LOGIC_VECTOR (7 DOWNTO 0) 78 | ); 79 | END COMPONENT; 80 | 81 | BEGIN 82 | q <= sub_wire0(7 DOWNTO 0); 83 | 84 | altsyncram_component : altsyncram 85 | GENERIC MAP ( 86 | clock_enable_input_a => "BYPASS", 87 | clock_enable_output_a => "BYPASS", 88 | init_file => "../data/image_rom.mif", 89 | intended_device_family => "Cyclone II", 90 | lpm_hint => "ENABLE_RUNTIME_MOD=NO", 91 | lpm_type => "altsyncram", 92 | numwords_a => 39839, 93 | operation_mode => "ROM", 94 | outdata_aclr_a => "NONE", 95 | outdata_reg_a => "UNREGISTERED", 96 | widthad_a => 16, 97 | width_a => 8, 98 | width_byteena_a => 1 99 | ) 100 | PORT MAP ( 101 | address_a => address, 102 | clock0 => clock, 103 | q_a => sub_wire0 104 | ); 105 | 106 | 107 | 108 | END SYN; 109 | 110 | -- ============================================================ 111 | -- CNX file retrieval info 112 | -- ============================================================ 113 | -- Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0" 114 | -- Retrieval info: PRIVATE: AclrAddr NUMERIC "0" 115 | -- Retrieval info: PRIVATE: AclrByte NUMERIC "0" 116 | -- Retrieval info: PRIVATE: AclrOutput NUMERIC "0" 117 | -- Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0" 118 | -- Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8" 119 | -- Retrieval info: PRIVATE: BlankMemory NUMERIC "0" 120 | -- Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0" 121 | -- Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0" 122 | -- Retrieval info: PRIVATE: Clken NUMERIC "0" 123 | -- Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0" 124 | -- Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" 125 | -- Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0" 126 | -- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone II" 127 | -- Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0" 128 | -- Retrieval info: PRIVATE: JTAG_ID STRING "NONE" 129 | -- Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" 130 | -- Retrieval info: PRIVATE: MIFfilename STRING "../../../samuel_packed.mif" 131 | -- Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "39839" 132 | -- Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" 133 | -- Retrieval info: PRIVATE: RegAddr NUMERIC "1" 134 | -- Retrieval info: PRIVATE: RegOutput NUMERIC "0" 135 | -- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" 136 | -- Retrieval info: PRIVATE: SingleClock NUMERIC "1" 137 | -- Retrieval info: PRIVATE: UseDQRAM NUMERIC "0" 138 | -- Retrieval info: PRIVATE: WidthAddr NUMERIC "16" 139 | -- Retrieval info: PRIVATE: WidthData NUMERIC "8" 140 | -- Retrieval info: PRIVATE: rden NUMERIC "0" 141 | -- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all 142 | -- Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS" 143 | -- Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS" 144 | -- Retrieval info: CONSTANT: INIT_FILE STRING "../../../samuel_packed.mif" 145 | -- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone II" 146 | -- Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO" 147 | -- Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" 148 | -- Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "39839" 149 | -- Retrieval info: CONSTANT: OPERATION_MODE STRING "ROM" 150 | -- Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" 151 | -- Retrieval info: CONSTANT: OUTDATA_REG_A STRING "UNREGISTERED" 152 | -- Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "16" 153 | -- Retrieval info: CONSTANT: WIDTH_A NUMERIC "8" 154 | -- Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" 155 | -- Retrieval info: USED_PORT: address 0 0 16 0 INPUT NODEFVAL "address[15..0]" 156 | -- Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock" 157 | -- Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL "q[7..0]" 158 | -- Retrieval info: CONNECT: @address_a 0 0 16 0 address 0 0 16 0 159 | -- Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0 160 | -- Retrieval info: CONNECT: q 0 0 8 0 @q_a 0 0 8 0 161 | -- Retrieval info: GEN_FILE: TYPE_NORMAL image_rom.vhd TRUE 162 | -- Retrieval info: GEN_FILE: TYPE_NORMAL image_rom.inc FALSE 163 | -- Retrieval info: GEN_FILE: TYPE_NORMAL image_rom.cmp TRUE 164 | -- Retrieval info: GEN_FILE: TYPE_NORMAL image_rom.bsf FALSE 165 | -- Retrieval info: GEN_FILE: TYPE_NORMAL image_rom_inst.vhd FALSE 166 | -- Retrieval info: LIB_FILE: altera_mf 167 | -------------------------------------------------------------------------------- /vhdl/ntsc_composite_top_de2.vhdl: -------------------------------------------------------------------------------- 1 | -- Copyright (c) 2014, Juha Turunen 2 | -- All rights reserved. 3 | -- 4 | -- Redistribution and use in source and binary forms, with or without 5 | -- modification, are permitted provided that the following conditions are met: 6 | -- 7 | -- 1. Redistributions of source code must retain the above copyright notice, this 8 | -- list of conditions and the following disclaimer. 9 | -- 2. Redistributions in binary form must reproduce the above copyright notice, 10 | -- this list of conditions and the following disclaimer in the documentation 11 | -- and/or other materials provided with the distribution. 12 | -- 13 | -- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | -- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | -- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | -- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | -- ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | -- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | -- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | -- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | -- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | -- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | 25 | library IEEE; 26 | use IEEE.STD_LOGIC_1164.ALL; 27 | use IEEE.STD_LOGIC_ARITH.ALL; 28 | use IEEE.STD_LOGIC_UNSIGNED.ALL; 29 | 30 | entity ntsc_composite_top_de2 is Port ( 31 | clk_50 : in std_logic; 32 | vga_clk : out std_logic; 33 | vga_g : out std_logic_vector(9 downto 0); 34 | vga_blank : out std_logic; 35 | vga_sync : out std_logic; 36 | btn : in std_logic_vector(3 downto 3) 37 | ); 38 | end ntsc_composite_top_de2; 39 | 40 | architecture Behavioral of ntsc_composite_top_de2 is 41 | 42 | signal reset : std_logic; 43 | signal clkdiv_counter : std_logic_vector(2 downto 0); 44 | signal pixel_clk_ena, half_pixel_clk_ena : std_logic; 45 | 46 | signal x, y : std_logic_vector(8 downto 0); 47 | signal in_sync, in_burst : std_logic; -- '1' if the beam is in sync or color burst regions 48 | signal in_active_video : std_logic; 49 | 50 | -- Color carrier phase accumulator 51 | signal color_carrier_phase, color_carrier_phase_next : std_logic_vector(17 downto 0); 52 | signal color_carrier_phase_modulator, color_carrier_phase_modulated : std_logic_vector(7 downto 0); 53 | signal color_carrier_amplitude, color_carrier_amplitude_clamped : std_logic_vector(2 downto 0); 54 | signal color_carrier_value : std_logic_vector(10 downto 0); 55 | 56 | -- Image rom signals 57 | -- pixel_value holds the upper or lower nybble of image_rom_data depending on the xcounter 58 | signal image_rom_address, image_rom_address_next : std_logic_vector(15 downto 0); 59 | signal image_rom_data : std_logic_vector(7 downto 0); 60 | signal pixel_value : std_logic_vector(3 downto 0); 61 | 62 | -- Used for storing the previous luma value for filtering 63 | signal luma_value_prev, luma_value_prev_next : std_logic_vector(10 downto 0); 64 | signal luma_value, luma_value_filtered, composite_value, 65 | composite_value_subbed, composite_value_clamped : std_logic_vector(10 downto 0); 66 | signal luma_values_added : std_logic_vector(11 downto 0); 67 | 68 | signal sine_rom_addr : std_logic_vector(10 downto 0); 69 | signal sine_rom_data : std_logic_vector(8 downto 0); 70 | 71 | signal pixel_luma : std_logic_vector(10 downto 0); 72 | signal pixel_phase : std_logic_vector(7 downto 0); 73 | signal pixel_chroma : std_logic_vector(2 downto 0); 74 | 75 | begin 76 | 77 | vga_blank <= '1'; 78 | vga_clk <= clk_50; 79 | reset <= not btn(3); 80 | 81 | process(clk_50, reset) 82 | begin 83 | if (reset = '1') then 84 | -- Asynchronous reset 85 | color_carrier_phase <= (others => '0'); 86 | image_rom_address <= (others => '0'); 87 | 88 | elsif (clk_50'event and clk_50 = '1') then 89 | color_carrier_phase <= color_carrier_phase_next; 90 | image_rom_address <= image_rom_address_next; 91 | luma_value_prev <= luma_value_prev_next; 92 | end if; 93 | end process; 94 | 95 | -- Clock divider 96 | process(clk_50, clkdiv_counter) 97 | begin 98 | if clk_50'event and clk_50 = '1' then 99 | clkdiv_counter <= clkdiv_counter + 1; 100 | end if; 101 | 102 | if clkdiv_counter = "000" then 103 | pixel_clk_ena <= '1'; 104 | else 105 | pixel_clk_ena <= '0'; 106 | end if; 107 | 108 | if clkdiv_counter = "000" or clkdiv_counter = "100" then 109 | half_pixel_clk_ena <= '1'; 110 | else 111 | half_pixel_clk_ena <= '0'; 112 | end if; 113 | end process; 114 | 115 | -- Generate image rom address 116 | process (image_rom_address, x, y, pixel_clk_ena) 117 | begin 118 | image_rom_address_next <= image_rom_address; 119 | if (x >= 65 and x < 385 and x(0) = '1' and pixel_clk_ena = '1') then 120 | image_rom_address_next <= image_rom_address + 1; 121 | end if; 122 | 123 | -- Reset the address counter at the first pixel 124 | if (x = 65 and y = 30 and pixel_clk_ena = '1') then 125 | image_rom_address_next <= conv_std_logic_vector(4 * 320 , 16); -- adjust start point a little bit 126 | end if; 127 | end process; 128 | 129 | -- Color carrier generator logic 130 | -- carrier_phase is a 18-bit register representing a fixed point number (8:10) 131 | -- The integer part of the fixed point number is used to address the color carrier sine table. 132 | -- The value added to the phase on every clock cycle is calculated as follows: 133 | -- NTSC color carrier frequency f(ntsc) = 3.579545 MHz, 134 | -- System clock f(sys) = 50 MHz, f(sys_cycle) = 20ns 135 | -- Sine table length l = 256 136 | -- If we incremented the phase register by 1 on every clock cycle, the frequency 137 | -- of the sine wave would be 1 / 2^18 / f(sys_cycle) ~= 190.734863281 Hz 138 | -- Thus to get f(ntsc) we need to increment by 3579545Hz / 190.734863281 Hz = 18767 139 | -- Note that it's very important that the color carrier keeps running freely. The phase must 140 | -- never be reset or the TV won't be able to lock into the color carrier. 141 | color_carrier_phase_next <= color_carrier_phase + 18767; 142 | color_carrier_phase_modulated <= color_carrier_phase(17 downto 10) + color_carrier_phase_modulator; 143 | 144 | -- If we're in the burst region don't modulate the color carrier phase, 145 | -- otherwise modulate with the value coming out of the palette 146 | color_carrier_phase_modulator <= "00000000" when in_burst = '1' else pixel_phase; 147 | 148 | -- "000" equates to the maximum amplitude, higher values diminish and "111" is considered a flat line 149 | -- The inverse relationship is there to avoid having storing the flat line in the sine table ROM. 150 | -- 1->0 2->1 3->2 etc mapping would require extra logic (yes we're not running short on the Cyclone II, but 151 | -- I have principles :P). 152 | -- Adjusting the amplitude of the color burst allows us to control the saturation a bit. Nominally 153 | -- the color burst amplitude should be the maximum one stored in the sine table, but since our DAC's voltage 154 | -- swing is limited and the TV seems to be cool with it, we're making it a bit less than the maximum to 155 | -- make the colors slightly more vibrant without too much luma->chroma bleed. 156 | color_carrier_amplitude <= pixel_chroma when in_active_video = '1' else 157 | "010" when in_burst = '1' else 158 | "111"; 159 | 160 | -- The luma is an 11-bit value, but the sine rom output is a 9-bit signed value, 161 | -- so we need to sign extend the sine ROM output. Also flat line the color carrier, 162 | -- if color_carrier_amplitude = "111" (see above). 163 | color_carrier_value <= sine_rom_data(8) & sine_rom_data(8) & sine_rom_data when color_carrier_amplitude /= "111" else 164 | (others => '0'); 165 | 166 | -- Since the image rom bytes have two pixels in them we need to pick the right nybble for display. 167 | -- The even pixels are in the upper nybble and vice versa. 168 | pixel_value <= image_rom_data(7 downto 4) when x(0) = '0' else image_rom_data(3 downto 0); 169 | 170 | -- When in_active_video is '1' the palette is in full control of the luma and chroma components 171 | in_active_video <= '1' when x >= 70 and x < 385 and y >= 30 and y < 289 else '0'; 172 | 173 | -- Generate the current luma value 174 | -- The blanking (black) level should nominally be 438, but since our DAC's voltage swing is limited 175 | -- and the TV seems to be fine with it, we make it a bit lower to have a bigber voltage swing above it 176 | -- and thus brighter pixels. 177 | luma_value <= conv_std_logic_vector(0, 11) when in_sync = '1' else 178 | conv_std_logic_vector(278, 11) when in_burst = '1' else 179 | pixel_luma when in_active_video = '1' else 180 | conv_std_logic_vector(278, 11); 181 | 182 | -- Sharp transitions in the luma generate harmonic frequencies which bleed into the chroma signal, causing 183 | -- nasty flickering color where there should be none (for exampple in black and white patterns). 184 | -- So instead of __|--- we want ___/---. By using the average of the previous luma value and the current 185 | -- one we do some rudimentary low-pass filtering which helps with the flicker and color bleed. 186 | -- The filtering is done every half pixels so you don't really notice any blurring of the image on a TV. 187 | luma_value_prev_next <= luma_value_prev when half_pixel_clk_ena = '0' else luma_value; 188 | luma_values_added <= ("0" & luma_value_prev) + ("0" & luma_value); -- Add the previous and current luma together... 189 | luma_value_filtered <= luma_values_added(11 downto 1); -- and divide by two 190 | 191 | -- Generate sine table address from the amplitude and the phase 192 | sine_rom_addr <= color_carrier_amplitude & color_carrier_phase_modulated; 193 | 194 | -- Combine the filtered luma and the color carrier signals 195 | composite_value <= luma_value_filtered + color_carrier_value; 196 | 197 | -- Normally the DE2 board's VGA DAC's RGB outputs swing from 0 to 0.7V, because VGA has separate sync 198 | -- wires and thus doesn't need to separate between black and sync levels. The composite white level 199 | -- though is nominally 1.0V (plus the color carrier amplitude). Luckily the DAC has a feature which 200 | -- adds a constant 0.3V voltage to the green output when asserted. Using the SYNC pin on the DAC we 201 | -- can achieve a better 1V swing. We're also cheating a little bit (see explanation above)with the blanking level 202 | -- voltage to have a larger range above the blanking level. So when the composite value is above 1023, we 203 | -- enable the constant (about 428 in terms of our internal signal values) voltage generator and subtract the same 204 | -- amount from our composite_value, before sending it to the DAC. We're also clamping the composite value to 205 | -- 1024 + 428 in case we have a palette entry with high saturation and lightness. Although it's possible 206 | -- to guarantee no clipping when generating individual palette entries, we still might clip because of the 207 | -- luma filterint. Imagine two pixels next to eachother. The first one is completely white (high luma, no chroma) 208 | -- and the second one is a high luma & high saturation one (but still not clipping). Because of the luma filtering 209 | -- during the first half of the first pixel the luma will be between white level and the colored pixel's luma, thus 210 | -- clipping. I'm sure this isn't perfect, but it's better than not clamping and creating false color artifacts due 211 | -- to dropping the MSB of composite_value_subbed. 212 | composite_value_subbed <= composite_value_clamped - 428; 213 | composite_value_clamped <= composite_value when (composite_value <= 1023 + 428) else conv_std_logic_vector(1023 + 428, 11); 214 | vga_g <= composite_value_subbed(9 downto 0) when composite_value(10) = '1' else composite_value(9 downto 0); 215 | vga_sync <= composite_value(10); 216 | 217 | -- Generates the sync and burst enable signals and provides x and y counters 218 | sync_generator : entity work.ntsc_sync_generator port map ( 219 | clk_50 => clk_50, 220 | reset => reset, 221 | pixel_clk_ena => pixel_clk_ena, 222 | x => x, 223 | y => y, 224 | sync => in_sync, 225 | burst => in_burst 226 | ); 227 | 228 | -- ROM that contains 7 full sine waves with diminishing amplitudes. 229 | -- The values are 9-bit signed integers and each full wave is 256 words long. 230 | sinetable : entity work.sine_rom port map ( 231 | address => sine_rom_addr, 232 | clock => clk_50, 233 | q => sine_rom_data 234 | ); 235 | 236 | -- 4-bit pixel value to luma-chroma-phase mapping 237 | palette : entity work.palette port map ( 238 | index => pixel_value, 239 | chroma => pixel_chroma, 240 | luma => pixel_luma, 241 | phase => pixel_phase 242 | ); 243 | 244 | -- Image ROM 245 | image_rom : entity work.image_rom port map ( 246 | clock => clk_50, 247 | address => image_rom_address, 248 | q => image_rom_data 249 | ); 250 | 251 | end Behavioral; 252 | -------------------------------------------------------------------------------- /vhdl/ntsc_sync_generator.vhdl: -------------------------------------------------------------------------------- 1 | -- Copyright (c) 2014, Juha Turunen 2 | -- All rights reserved. 3 | -- 4 | -- Redistribution and use in source and binary forms, with or without 5 | -- modification, are permitted provided that the following conditions are met: 6 | -- 7 | -- 1. Redistributions of source code must retain the above copyright notice, this 8 | -- list of conditions and the following disclaimer. 9 | -- 2. Redistributions in binary form must reproduce the above copyright notice, 10 | -- this list of conditions and the following disclaimer in the documentation 11 | -- and/or other materials provided with the distribution. 12 | -- 13 | -- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | -- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | -- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | -- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | -- ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | -- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | -- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | -- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | -- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | -- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | 25 | library IEEE; 26 | use IEEE.STD_LOGIC_1164.ALL; 27 | use IEEE.STD_LOGIC_ARITH.ALL; 28 | use IEEE.STD_LOGIC_UNSIGNED.ALL; 29 | 30 | entity ntsc_sync_generator is Port ( 31 | clk_50 : in std_logic; 32 | reset : in std_logic; 33 | pixel_clk_ena : in std_logic; 34 | x : out std_logic_vector(8 downto 0); 35 | y : out std_logic_vector(8 downto 0); 36 | sync : out std_logic; -- 1 if sync is active (0V), 0 if not (0,3V) 37 | burst : out std_logic 38 | ); 39 | end ntsc_sync_generator; 40 | 41 | architecture Behavioral of ntsc_sync_generator is 42 | 43 | -- pixel_clk_ena assumed to go high every 160ns 44 | constant front_porch_length : integer := 9; -- 1,4uS 45 | constant back_porch_length : integer := 37; -- 5,9uS 46 | constant sync_length : integer := 30; -- 4,7uS 47 | constant line_length : integer := 396; -- 63,5uS 48 | constant half_line_length : integer := 198; 49 | constant eq_pulse_length : integer := 14; -- 2,3uS 50 | constant field_sync_pulse_length : integer := 170; -- 27,1uS 51 | constant active_video_length : integer := line_length - front_porch_length - 52 | back_porch_length - sync_length; 53 | 54 | constant vblank_start_line : integer := 3; 55 | constant post_eq_start_line : integer := vblank_start_line + 3; 56 | constant active_video_start_line : integer := post_eq_start_line + 3; 57 | constant line_count : integer := 262; 58 | constant vblanking_start_line : integer := 242; 59 | 60 | constant burst_start : integer := 45; 61 | constant burst_length : integer := 17; 62 | 63 | signal hcounter, hcounter_next : std_logic_vector(8 downto 0); 64 | signal vcounter, vcounter_next : std_logic_vector(8 downto 0); 65 | 66 | signal normal_line_sync, eq_line_sync, vblank_line_sync : std_logic; 67 | signal in_eq_line, in_normal_line, in_vblank_line : std_logic; 68 | 69 | signal sync_next, sync_reg : std_logic; 70 | 71 | begin 72 | 73 | -- Update registers with pixel clock 74 | process(clk_50, reset, pixel_clk_ena) 75 | begin 76 | if reset = '1' then 77 | hcounter <= (others=>'0'); 78 | vcounter <= (others=>'0'); 79 | elsif (clk_50'event and clk_50 = '1' and pixel_clk_ena = '1') then 80 | hcounter <= hcounter_next; 81 | vcounter <= vcounter_next; 82 | sync_reg <= sync_next; 83 | end if; 84 | end process; 85 | 86 | -- Counter logic 87 | process(vcounter, hcounter, hcounter_next, vcounter_next) 88 | begin 89 | vcounter_next <= vcounter; 90 | if hcounter < line_length then 91 | hcounter_next <= hcounter + 1; 92 | else 93 | hcounter_next <= (others => '0'); 94 | if vcounter < line_count then 95 | vcounter_next <= vcounter + 1; 96 | else 97 | vcounter_next <= (others => '0'); 98 | end if; 99 | end if; 100 | end process; 101 | 102 | -- Sync signal generation for different line types 103 | -- The different lines look roughly like this: 104 | -- Normal line: -_-AAAAAAAAA (A = active video, _ = sync level) 105 | -- Equalization line: _-----_----- 106 | -- Vertical blanking line: _____-_____- 107 | -- Details: http://martin.hinner.info/vga/pal.html (has info on NTSC regardless of the name) 108 | normal_line_sync <= '1' when hcounter >= front_porch_length and 109 | hcounter < front_porch_length + sync_length else '0'; 110 | 111 | eq_line_sync <= '1' when hcounter < eq_pulse_length or 112 | (hcounter >= half_line_length and 113 | hcounter < half_line_length + eq_pulse_length) else '0'; 114 | 115 | vblank_line_sync <= '1' when hcounter < field_sync_pulse_length or 116 | (hcounter >= half_line_length and 117 | hcounter < half_line_length + field_sync_pulse_length) else '0'; 118 | 119 | -- A multiplexer for choosing the right sync signal depending on the vertical line 120 | -- Lines 0-2 = eq line 121 | -- Lines 3-5 = vblank line 122 | -- Lines 6-8 = eq line 123 | -- Lines 9-261 = normal sync 124 | sync_next <= eq_line_sync when vcounter < vblank_start_line else 125 | vblank_line_sync when vcounter < post_eq_start_line - 1 else 126 | eq_line_sync when vcounter < active_video_start_line else 127 | normal_line_sync; 128 | 129 | -- Indicates whether the beam is in the color burst region and a 0 phase color carrier should be 130 | -- added to the composite signal. 131 | burst <= '1' when (hcounter >= burst_start) and (hcounter < (burst_start + burst_length)) and 132 | (vcounter >= active_video_start_line) and (vcounter < vblanking_start_line) else '0'; 133 | 134 | x <= hcounter; 135 | y <= vcounter; 136 | sync <= sync_reg; 137 | 138 | end Behavioral; 139 | 140 | -------------------------------------------------------------------------------- /vhdl/palette.vhdl: -------------------------------------------------------------------------------- 1 | -- Copyright (c) 2014, Juha Turunen 2 | -- All rights reserved. 3 | -- 4 | -- Redistribution and use in source and binary forms, with or without 5 | -- modification, are permitted provided that the following conditions are met: 6 | -- 7 | -- 1. Redistributions of source code must retain the above copyright notice, this 8 | -- list of conditions and the following disclaimer. 9 | -- 2. Redistributions in binary form must reproduce the above copyright notice, 10 | -- this list of conditions and the following disclaimer in the documentation 11 | -- and/or other materials provided with the distribution. 12 | -- 13 | -- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | -- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | -- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | -- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | -- ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | -- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | -- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | -- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | -- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | -- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | library IEEE; 25 | use IEEE.STD_LOGIC_1164.ALL; 26 | use IEEE.STD_LOGIC_ARITH.ALL; 27 | use IEEE.STD_LOGIC_UNSIGNED.ALL; 28 | 29 | entity palette is Port ( 30 | index : in std_logic_vector(3 downto 0); 31 | luma : out std_logic_vector(10 downto 0); 32 | phase : out std_logic_vector(7 downto 0); 33 | chroma : out std_logic_vector(2 downto 0) 34 | ); 35 | end palette; 36 | 37 | architecture Behavioral of palette is 38 | begin 39 | 40 | luma <= 41 | conv_std_logic_vector(430, 11) when index = "0000" else 42 | conv_std_logic_vector(489, 11) when index = "0001" else 43 | conv_std_logic_vector(598, 11) when index = "0010" else 44 | conv_std_logic_vector(636, 11) when index = "0011" else 45 | conv_std_logic_vector(685, 11) when index = "0100" else 46 | conv_std_logic_vector(790, 11) when index = "0101" else 47 | conv_std_logic_vector(803, 11) when index = "0110" else 48 | conv_std_logic_vector(868, 11) when index = "0111" else 49 | conv_std_logic_vector(835, 11) when index = "1000" else 50 | conv_std_logic_vector(897, 11) when index = "1001" else 51 | conv_std_logic_vector(892, 11) when index = "1010" else 52 | conv_std_logic_vector(858, 11) when index = "1011" else 53 | conv_std_logic_vector(953, 11) when index = "1100" else 54 | conv_std_logic_vector(1044, 11) when index = "1101" else 55 | conv_std_logic_vector(1097, 11) when index = "1110" else 56 | conv_std_logic_vector(1144, 11); 57 | 58 | chroma <= 59 | "100" when index = "0000" else 60 | "001" when index = "0001" else 61 | "010" when index = "0010" else 62 | "100" when index = "0011" else 63 | "101" when index = "0100" else 64 | "010" when index = "0101" else 65 | "001" when index = "0110" else 66 | "100" when index = "0111" else 67 | "101" when index = "1000" else 68 | "011" when index = "1001" else 69 | "100" when index = "1010" else 70 | "011" when index = "1011" else 71 | "110" when index = "1100" else 72 | "101" when index = "1101" else 73 | "100" when index = "1110" else 74 | "101"; 75 | phase <= 76 | "10000100" when index = "0000" else 77 | "10011100" when index = "0001" else 78 | "11010011" when index = "0010" else 79 | "01100000" when index = "0011" else 80 | "11110010" when index = "0100" else 81 | "11010010" when index = "0101" else 82 | "01100101" when index = "0110" else 83 | "10011010" when index = "0111" else 84 | "01000111" when index = "1000" else 85 | "11100111" when index = "1001" else 86 | "11101100" when index = "1010" else 87 | "00110110" when index = "1011" else 88 | "00100111" when index = "1100" else 89 | "00100101" when index = "1101" else 90 | "11101101" when index = "1110" else 91 | "11111100"; 92 | 93 | end Behavioral; 94 | -------------------------------------------------------------------------------- /vhdl/sine_rom.vhdl: -------------------------------------------------------------------------------- 1 | -- megafunction wizard: %ROM: 1-PORT% 2 | -- GENERATION: STANDARD 3 | -- VERSION: WM1.0 4 | -- MODULE: altsyncram 5 | 6 | -- ============================================================ 7 | -- File Name: sine_rom.vhd 8 | -- Megafunction Name(s): 9 | -- altsyncram 10 | -- 11 | -- Simulation Library Files(s): 12 | -- altera_mf 13 | -- ============================================================ 14 | -- ************************************************************ 15 | -- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! 16 | -- 17 | -- 12.1 Build 243 01/31/2013 SP 1 SJ Web Edition 18 | -- ************************************************************ 19 | 20 | 21 | --Copyright (C) 1991-2012 Altera Corporation 22 | --Your use of Altera Corporation's design tools, logic functions 23 | --and other software and tools, and its AMPP partner logic 24 | --functions, and any output files from any of the foregoing 25 | --(including device programming or simulation files), and any 26 | --associated documentation or information are expressly subject 27 | --to the terms and conditions of the Altera Program License 28 | --Subscription Agreement, Altera MegaCore Function License 29 | --Agreement, or other applicable license agreement, including, 30 | --without limitation, that your use is for the sole purpose of 31 | --programming logic devices manufactured by Altera and sold by 32 | --Altera or its authorized distributors. Please refer to the 33 | --applicable agreement for further details. 34 | 35 | 36 | LIBRARY ieee; 37 | USE ieee.std_logic_1164.all; 38 | 39 | LIBRARY altera_mf; 40 | USE altera_mf.all; 41 | 42 | ENTITY sine_rom IS 43 | PORT 44 | ( 45 | address : IN STD_LOGIC_VECTOR (10 DOWNTO 0); 46 | clock : IN STD_LOGIC := '1'; 47 | q : OUT STD_LOGIC_VECTOR (8 DOWNTO 0) 48 | ); 49 | END sine_rom; 50 | 51 | 52 | ARCHITECTURE SYN OF sine_rom IS 53 | 54 | SIGNAL sub_wire0 : STD_LOGIC_VECTOR (8 DOWNTO 0); 55 | 56 | 57 | 58 | COMPONENT altsyncram 59 | GENERIC ( 60 | clock_enable_input_a : STRING; 61 | clock_enable_output_a : STRING; 62 | init_file : STRING; 63 | intended_device_family : STRING; 64 | lpm_hint : STRING; 65 | lpm_type : STRING; 66 | numwords_a : NATURAL; 67 | operation_mode : STRING; 68 | outdata_aclr_a : STRING; 69 | outdata_reg_a : STRING; 70 | widthad_a : NATURAL; 71 | width_a : NATURAL; 72 | width_byteena_a : NATURAL 73 | ); 74 | PORT ( 75 | address_a : IN STD_LOGIC_VECTOR (10 DOWNTO 0); 76 | clock0 : IN STD_LOGIC ; 77 | q_a : OUT STD_LOGIC_VECTOR (8 DOWNTO 0) 78 | ); 79 | END COMPONENT; 80 | 81 | BEGIN 82 | q <= sub_wire0(8 DOWNTO 0); 83 | 84 | altsyncram_component : altsyncram 85 | GENERIC MAP ( 86 | clock_enable_input_a => "BYPASS", 87 | clock_enable_output_a => "BYPASS", 88 | init_file => "../data/color_carrier_sine.mif", 89 | intended_device_family => "Cyclone II", 90 | lpm_hint => "ENABLE_RUNTIME_MOD=NO", 91 | lpm_type => "altsyncram", 92 | numwords_a => 1792, 93 | operation_mode => "ROM", 94 | outdata_aclr_a => "NONE", 95 | outdata_reg_a => "UNREGISTERED", 96 | widthad_a => 11, 97 | width_a => 9, 98 | width_byteena_a => 1 99 | ) 100 | PORT MAP ( 101 | address_a => address, 102 | clock0 => clock, 103 | q_a => sub_wire0 104 | ); 105 | 106 | 107 | 108 | END SYN; 109 | 110 | -- ============================================================ 111 | -- CNX file retrieval info 112 | -- ============================================================ 113 | -- Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0" 114 | -- Retrieval info: PRIVATE: AclrAddr NUMERIC "0" 115 | -- Retrieval info: PRIVATE: AclrByte NUMERIC "0" 116 | -- Retrieval info: PRIVATE: AclrOutput NUMERIC "0" 117 | -- Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0" 118 | -- Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "9" 119 | -- Retrieval info: PRIVATE: BlankMemory NUMERIC "0" 120 | -- Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0" 121 | -- Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0" 122 | -- Retrieval info: PRIVATE: Clken NUMERIC "0" 123 | -- Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0" 124 | -- Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" 125 | -- Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0" 126 | -- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone II" 127 | -- Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0" 128 | -- Retrieval info: PRIVATE: JTAG_ID STRING "NONE" 129 | -- Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" 130 | -- Retrieval info: PRIVATE: MIFfilename STRING "sinetable.mif" 131 | -- Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "1792" 132 | -- Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" 133 | -- Retrieval info: PRIVATE: RegAddr NUMERIC "1" 134 | -- Retrieval info: PRIVATE: RegOutput NUMERIC "0" 135 | -- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" 136 | -- Retrieval info: PRIVATE: SingleClock NUMERIC "1" 137 | -- Retrieval info: PRIVATE: UseDQRAM NUMERIC "0" 138 | -- Retrieval info: PRIVATE: WidthAddr NUMERIC "11" 139 | -- Retrieval info: PRIVATE: WidthData NUMERIC "9" 140 | -- Retrieval info: PRIVATE: rden NUMERIC "0" 141 | -- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all 142 | -- Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS" 143 | -- Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS" 144 | -- Retrieval info: CONSTANT: INIT_FILE STRING "sinetable.mif" 145 | -- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone II" 146 | -- Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO" 147 | -- Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" 148 | -- Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "1792" 149 | -- Retrieval info: CONSTANT: OPERATION_MODE STRING "ROM" 150 | -- Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" 151 | -- Retrieval info: CONSTANT: OUTDATA_REG_A STRING "UNREGISTERED" 152 | -- Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "11" 153 | -- Retrieval info: CONSTANT: WIDTH_A NUMERIC "9" 154 | -- Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" 155 | -- Retrieval info: USED_PORT: address 0 0 11 0 INPUT NODEFVAL "address[10..0]" 156 | -- Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock" 157 | -- Retrieval info: USED_PORT: q 0 0 9 0 OUTPUT NODEFVAL "q[8..0]" 158 | -- Retrieval info: CONNECT: @address_a 0 0 11 0 address 0 0 11 0 159 | -- Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0 160 | -- Retrieval info: CONNECT: q 0 0 9 0 @q_a 0 0 9 0 161 | -- Retrieval info: GEN_FILE: TYPE_NORMAL sine_rom.vhd TRUE 162 | -- Retrieval info: GEN_FILE: TYPE_NORMAL sine_rom.inc FALSE 163 | -- Retrieval info: GEN_FILE: TYPE_NORMAL sine_rom.cmp TRUE 164 | -- Retrieval info: GEN_FILE: TYPE_NORMAL sine_rom.bsf FALSE 165 | -- Retrieval info: GEN_FILE: TYPE_NORMAL sine_rom_inst.vhd FALSE 166 | -- Retrieval info: LIB_FILE: altera_mf 167 | --------------------------------------------------------------------------------