Simple 6502 Breadboard VGA - 640x480 8-colour upgrade details

Поделиться
HTML-код
  • Опубликовано: 27 окт 2024
  • Following on from my last video, here are the details of the upgrade from 640x480 monochrome to 640x480x3bpp.

Комментарии • 47

  • @mheermance
    @mheermance 3 года назад +6

    This project gives me a new respect for video hardware. Especially multiple video mode hardware that effectively rewires itself based upon control register values.

    • @GeorgeFoot
      @GeorgeFoot  3 года назад +1

      "Video ULA - BeebWiki" beebwiki.mdfs.net/Video_ULA

    • @GeorgeFoot
      @GeorgeFoot  3 года назад +1

      This is the thing that originally got me interested in digital electronics and making my own video output hardware. Despite understanding it well from the software side, I'd never understood why the BBC had such a weird video memory layout, but all of a sudden it all made sense, and there's a beautiful simplicity to it - it feels like they did just enough in the hardware to support a range of modes with minimal amounts of logic. The video ULA is basically just a clock divider, a shift register, and some logic gates, on one IC.
      There's also some additional circuit to calculate video RAM base addresses, and of course the CRTC does all the counting, sync generation, and address generation.

  • @thorpejsf
    @thorpejsf 2 года назад +1

    This has been a really excellent series of videos. I've been inspired to graphics in my own 6809E/6309E-based home-brew project as a result. I've also been using this project as an opportunity to learn Verilog. The basic approach I'm using is similar to yours -- driving everything from the 25.175MHz VGA pixel clock. So my "CAV" (clock and video) block takes the 25.175MHz oscillator input, divides it by 4, which is in turn again sub-divided and phase shifted to generate the Q and E clocks used by the 6809E at 1.573MHz, and also outputs a buffered copy of the VGA pixel clock. It internally tracks Hpos and Vpos and outputs HBLANK, /HSYNC, VBLANK, and /VSYNC, in addition to a "pixel index", which is simply a counter that only increments when not in either of the blanking intervals and resets at the beginning of the frame, and can be used to generate a video RAM address. HBLANK and VBLANK can be used to force the VGA R/G/B signals low during the blanking intervals, and edge-detector circuits can generate interrupts for the CPU if you're so inclined. I may switch the polarity of /HSYNC and /VSYNC, instead using them to drive MOSFETs to drive those VGA signals low, rather than driving them from the FPGA / CPLD directly.

  • @ewalk153
    @ewalk153 3 года назад +2

    I’ve just ordered the parts from the BOM to start following along, starting with the first VGA design. I can’t wait for your next update.

    • @GeorgeFoot
      @GeorgeFoot  3 года назад

      Great! I ought to make an updated parts list for the later videos. I'll probably consolidate things soon and that could be a good time to do it.

  • @bytesandbikes
    @bytesandbikes 3 года назад +1

    This is seriously impressive for a breadboard system!

  • @djc1402
    @djc1402 3 года назад +3

    Using a ROM to generate the HSync, VSync and Counter resets is what I've always done on my VGA setup. For VGA 648x480 you can divide by 16 and so use 4 less bits from the counters and use a smaller and slower ROM for those signals. That means you can use more bits from the RAM for colour information too. I also use a ROM bit to make sure that the output is always blanked in the non-visible part by sending that to the OE pins of the output registers (if they are 3-State), that means it doesn't matter if there is junk in the non visible area. I'm looking forward to see what you do with it in the future.

    • @GeorgeFoot
      @GeorgeFoot  3 года назад +1

      Yes that's interesting, as there'd be plenty of free bits in the ROM, one could be used to mark the visible area. It would be important for hardware scrolling.
      I was also considering using separate counters for pixel data, I'm not sure if that has many advantages though.

    • @djc1402
      @djc1402 3 года назад +1

      @@GeorgeFoot My next design will use separate counters for the pixel data as I'm going to try a resolution of 200 by 150 which would normally be over the 32k maximum address space my CPU can use, but if I use separate counters for pixels it will be 200x150 = 32000 bytes, just under the maximum. It does however mean that calculating the pixel address in the CPU is more complex as I will have to do a multiply by 200 to Y and add X rather than use Y as the top 7 bits and X as the bottom 8 bits of the pixel address.

    • @GeorgeFoot
      @GeorgeFoot  3 года назад

      @@djc1402 The BBC Micro used a x640 lookup table for this purpose. Maybe you could also consider a hardware lookup of some kind. Or something a bit like my bank register but with a built-in multiply.
      One of my plans for making life easier for the 6502 is actually to make the video memory not be memory mapped, but instead use a register to define what location should be written next. It means before each random access you need to set the register up, but that's really no more work than calculating the address already is, and the 6502 is pretty poor at 16-20 bit maths.

  • @kvadratbitter
    @kvadratbitter 2 года назад +1

    Really impressive work so far! Binge watching your videos at the moment.
    12:53 I haven’t watched all your videos yet so don’t know if you’ve done this already, but if not it would be very interesting to hear more about your investigation!
    Edit; I see now it was literally the next video… 🤦‍♂️ well, merry Christmas!

    • @GeorgeFoot
      @GeorgeFoot  2 года назад

      Merry Christmas to you too!

    • @kvadratbitter
      @kvadratbitter Год назад

      @@GeorgeFoot Heh, one year later I’m randomly watching this video again and got very surprised to see my comment here.
      Well, it deserves saying again: great job, and merry Christmas! 😅

  • @bioman1hazard607
    @bioman1hazard607 2 года назад

    You should send ben eater this vid, I'd love to hear his commentary on this upgrade

  • @zment
    @zment 3 года назад +1

    Ooh this is so good!

  • @mattingram5811
    @mattingram5811 3 года назад +2

    Another excellent video! Thanks George. I have already ordered parts Will you be posting the schematics and source?

    • @GeorgeFoot
      @GeorgeFoot  3 года назад

      Thanks Matt!
      I've uploaded schematics and source code to github before ( github.com/gfoot/simplevga6502 ) but it's a little out of date at the moment, I need to update it one day. Note that there's a separate branch for the 640x480 path - the main branch stops at 320x240 because that's really quite a good compromise for a 6502 and made sense to keep separate as its own thing.

  • @thorpejsf
    @thorpejsf 2 года назад

    I was thinking about dynamic color palettes a bit. From my (admittedly very basic) understanding of how they work, a simple RAMDAC should be pretty straightforward to build, and shouldn't introduce that much additional complexity into the circuit (I think just one layer of indirection right at the VGA output - pixel value serves as the color lookup table index, and the value in the SRAM at that location drives the resistor ladder). The VRAM layout I'm currently using uses 8 bits per pixel (because I'm lazy), but only the bottom 6 bits are used (2 bits per color) for 64 colors. The upper 2 bits could be used to select one of 4 alternate palettes of 64 colors, but those colors themselves could be pretty rich ... even if you used 24-bit CLUT entries, that's less than 1K of additional SRAM (4 * 64 * 3 ==> 768). With careful color palette management, this could make blinking the ghosts in Pac-Man a matter of writing just a handful of bytes during the VBLANK interval.
    Sorry for rambling on in the comments... but it's fun when the ideas flow :-)

    • @GeorgeFoot
      @GeorgeFoot  2 года назад +1

      It certainly is! It sounds good in principle, the main challenge I think is the speed of the palette RAM especially if you want the CPU to be able to update it dynamically. Most of my designs only perform one fetch from RAM for several VGA pixels, reducing the required RAM bandwidth and leaving time for CPU writes. I guess for the palette RAM you could limit writes to the vertical blanking interval and run it flat out the rest of the time.

    • @thorpejsf
      @thorpejsf 2 года назад

      @@GeorgeFoot Yah, the palette RAM access is the trick, isn't it. In addition to needing to be fast enough, it either needs to be wide (32-bits) or you need multiple small parts. But a simple state machine could be implemented that takes "color index, color_b2, color_b1, color_b0" and then writes it into the palette RAM. Dual-ported RAM could make it even easier, no need for external circuitry to arbitrate writes from the CPU (might make the more expensive part worth it!)

    • @GeorgeFoot
      @GeorgeFoot  2 года назад

      @@thorpejsf Yes I think dual port RAM kind of spoils the fun! After replying earlier, I started wondering if you could use the main video ram to store updated palette data, and then read it out during the blanking interval when this RAM is otherwise idle. The CPU already has the ability to write to it. It could even be possible to reuse connections from the video RAM data lines to the palette RAM address lines, saving a lot of multiplexers or transceivers.

    • @thorpejsf
      @thorpejsf 2 года назад

      @@GeorgeFoot Storing the palette updates in the extra VRAM is a great idea. I’ve also been thinking about keeping sprite data in the extra VRAM, but palette is only 1K total, so…

    • @thorpejsf
      @thorpejsf 2 года назад

      @@GeorgeFoot IDT 71256SA12TPG part is bread-boardable, fast (12ns), and inexpensive ($8USD from Mouser)…

  • @Aruneh
    @Aruneh 3 года назад +3

    Excellent! I guess this is too slow for games with scrolling?

    • @GeorgeFoot
      @GeorgeFoot  3 года назад

      Yes, you wouldn't want to try to scroll the screen in software. The 6502 takes around 5 cycles to write a byte, let alone calculate what data to write, so I'd guess this could probably clear the screen to a constant colour about 5 times per second, not fast enough. Generally games of the era didn't rewrite the whole screen every frame, they updated specific parts, and for scrolling they used hardware scrolling which just adds a constant to the VRAM addresses. You then need to paint a stripe down one side of the screen. And of course they stuck to lower resolutions than this.

  • @PebblesChan
    @PebblesChan 3 года назад +1

    George, why not treat yourself with get yourself some handy (but obsolete) 74265 quad complementary output elements for your breadboarding experiments. They’re great for removing unwanted glitches. Alternatively you can use more modern (but obsolete) SPLD and CPLDs if they’re fast enough.

    • @GeorgeFoot
      @GeorgeFoot  3 года назад

      I can't find a datasheet for 74ls265 or similar, what do they do? I have some PLDs that I might use in future, just need to find the right use case!

    • @davethedaemon9024
      @davethedaemon9024 3 года назад

      @@GeorgeFoot I found a reference to a TI SN74265. 4 buffers each with one input and two complementary outputs - a non-inverting W and an inverting Y where both typically switch within 0.5ns of each other.

    • @PebblesChan
      @PebblesChan 3 года назад +1

      It's not available in the LS family just TTL family www.jameco.com/Jameco/Products/ProdDS/2298775.pdf

    • @davethedaemon9024
      @davethedaemon9024 3 года назад

      @@PebblesChan - I think you're right. AliExpress claims to have it. But I've gotten mislabled/knockoff items from them before.
      www.aliexpress.com/item/33009970579.html

    • @GeorgeFoot
      @GeorgeFoot  3 года назад

      Ah right, it looks useful for longer distance communication I think, I'd prefer to stick to CMOS parts though.

  • @Kitulous
    @Kitulous 3 года назад

    omg you're extremely underrated

    • @GeorgeFoot
      @GeorgeFoot  3 года назад +1

      Haha, thanks, glad you like it!

  • @reinoud6377
    @reinoud6377 3 года назад +1

    Are planning to create a pcb?

    • @GeorgeFoot
      @GeorgeFoot  3 года назад

      I think I will at some point. I have to decide what to put on it. Maybe VGA for example.

  • @EnsignRho
    @EnsignRho 3 года назад +1

    Why don't you create a stand-alone video subsystem that is entirely autonomous, and then create a way to receive reads / writes from the 6502 when requested?

    • @GeorgeFoot
      @GeorgeFoot  3 года назад +1

      The two are already quite separate, the only real links are that the CPU clock comes from the video circuit (so it's always in sync) and the address and data bus are wired through to enable writes to video memory.
      I am probably going to separate it even more soon though, as you suggest, as part of changing the interface to speed up graphics operations. Although the current interface is very wide, the 6502 is not able to make efficient use of it. So this will probably also make it a more pluggable system, with a more register/command oriented interface rather than memory mapping.

    • @EnsignRho
      @EnsignRho 3 года назад

      @@GeorgeFoot What about using a memory mapping mode enabled by a write to a specific port, one that lets you pattern the BitBlt'ing you need to do reads and writes on the main bus. Example: read from ram, then write into larger video memory. The mapping switches over the target, bypassing ram and selecting video memory. It then resets after the write.
      A few ports to control which "bank" (which upper bits) and you'll be at 80s level EGA video cards. Almost. :-) Still need 256 colors to be decently usable.
      Basic flow:
      1) Write to port to enable this mode
      2) Enter tight loop where you read, copy, read, copy, etc....
      Every read toggles the map
      Every write also.
      3) Write to port when finished to return to normal mode.
      That would be for data exchanged on the CPU / main bus.
      The GPU would have its own bus for rendering higher resolutions at higher dot / pixel clocks. So long as you use SRAM, should be completely doable.
      Depending on which value you wrote, the mappings could be different based on the needs of your tight loops:
      read ram: write video
      read, read ram; write video
      read, read, read ram; write video
      etc
      Just some thoughts. Feel free to disregard all of them. :-)

    • @GeorgeFoot
      @GeorgeFoot  3 года назад

      @@EnsignRho I'm not sure what you mean by "toggling the map"? I am interested, just don't quite understand what you're suggesting.
      The trouble with any form of memory mapping with a 6502 is that it really sucks at it - indirect indexed operations are really slow. For bulk transfers I want to just write to one address and have the video hardware track and increment the target address itself. This will give a huge speed improvement and reduces the interface width considerably - it becomes more like a command buffer FIFO, or maybe a set of registers.
      Other options there are having it also able to expand bit patterns out into multiple byte writes with a fixed colour (great for drawing text, for example) and having it internally copy multiple bytes from one VRAM location to another, like EGA sort of does. I also have a fairly simple circuit lined up to allow writing only some bits within a byte of VRAM, to support single pixel writes in packed pixel layouts. A lot of this is uncoincidentally a lot like the various read and write modes in EGA, which I guess were there for a reason!
      So I'm not sure exactly what I'll do yet, but hopefully I'll get time soon to explain my thoughts properly in a video. Work is really busy at the moment though!

    • @EnsignRho
      @EnsignRho 3 года назад

      @@GeorgeFoot Can I contact you by email?

    • @GeorgeFoot
      @GeorgeFoot  3 года назад

      @@EnsignRho Sure if you like, my gmail address is just my full name with a dot.

  • @canaDavid1
    @canaDavid1 3 года назад

    2:30 how des he do that?(with the labels)

    • @GeorgeFoot
      @GeorgeFoot  3 года назад

      After placing a label, pressing Insert will duplicate it below with the number incremented. I think there are options somewhere to control the gap and the increment, but the defaults are fine for me.
      The same key works for wires and bus connections, maybe other things too.

    • @canaDavid1
      @canaDavid1 3 года назад

      @@GeorgeFoot thanks! This will really speed up my workflow!