Jump to content

My first foray into VHDL

Recommended Posts

I've been fascinated with the idea of modding our Intellivisions to get a little more out of them. To this end, I started playing with an idea: what if we had a board that could sit between the STIC and the rest of the Inty that could provide extra GRAM, and what if it could be enabled or disabled in software? So as an experiment I wrote a VHDL for one. This is the very first time I ever tried coding VHDL, so I have no idea if it will work or if it would fry an Inty, but I figured I'd post it here in case there are people more knowledgeable about it.


It works by intercepting CPU writes to four "unused" STIC registers at 0x33 through 0x36: if you write "eXtR" to them it switches into extended-GRAM mode and if you write "nOrM" to them it switches back to standard mode. In extended-GRAM mode it intercepts the signals coming from BAR', DTB', and DWS' and determines (based on the last address it saw on the STIC bus) whether to pass them along to to the GROM chip or not. If the address was outside the normal GRAM range (but within the extended GRAM range), it addresses separate RAM instead. The RAM would lie on the same bus as existing GRAM, with this chip choosing either normal GROM/GRAM or extended GRAM as appropriate. The idea is to allow 256 GRAM cards when not in foreground/background mode.


  • Like 5
Link to comment
Share on other sites

I didn't know what vhdl is. So this file can be used to program a small fpga chip? Should there be some documentation, like about connections?


One question, if you don't have a way to turn extra gram on and its on all the time, how many existing Intellivision games would be effected? I know worm whomper and space patrol patrol are effected.


Next is a modification to enable double resolution (8x16) background cards.

Link to comment
Share on other sites

That's the idea: to program an FPGA This is designed so that the extra GRAM is off by default. You have to write a magic series of bytes to memory to enable it, and another magic series of bytes to disable it. Resetting the Inty always turns the extra GRAM off.

Link to comment
Share on other sites



I've bounced similar ideas in my head but never executed any of them and never looked into VHDL for them (I usually considered microcontrollers).


If you want to experiment with the design further, here are some ideas and suggestions:

  1. I recommend using fewer registers. I am suspecting that other unrelated hardware projects might also want to use the "unused" registers for their own purposes. The current design uses 4 registers when only 1 is necessary. With only 1 register, the CPU would make 4 writes to the same location and the VHDL chip would have a tiny state machine that it expects to see 'e' 'X' 't' and 'R' in that specific order. Maybe add a timeout (ex: if N clock cycles go by without seeing 4 bytes, then reset back to the initial state where 'e' is expected).
  2. Have you considered overriding the GROM (i.e. replace it with 64 writable cards)? This way, someone can replace the default font or add another 64 cards to the extended 256. Ideally, enabling the replacement-GROM would be independent of enabling the extended-GRAM. Unlike the cartridge port via forcing BC0-2 to NOP, I am not certain there is a good way to disable the existing GROM chip unless your VHDL chip is designed to attach to the STIC chip's BC0-2 lines. Note: the top few GROM cards actually contain EXEC code instead of images. The CPU might have to copy these special GROM cards to the replacement-GROM cards to maintain compatibility (if that EXEC code is needed by the game).
  3. How about adding more than 256 GRAM cards via bankswapping? For example, provide 1024 GRAM cards that are in banks 0, 1, 2, and 3. Writing eXtR3 would activated bank #3 of 256 GRAM cards.
    1. For an even more advanced type of bankswapping where there are a HUGE number of banks (ex: 128 banks of 256 GRAM cards for a total of 32768 GRAM cards) make bank 0 special such that it indexes into other banks. When bank 0 is active, reads work normally by returning the pixels for the GRAM card (so they are displayed correctly) but writes to a GRAM card's 1st byte would set which bank it refers to and writes to the 2nd byte would set which card within that bank it refers to. The idea that the CPU would spend a lot of time initially generating and loading animation sequences into the various banks when the game starts and then activate bank 0. Afterwards, the CPU would only need to do 1 or 2 one-byte writes (instead of 8 ) to change a card. For example, the animation sequence for player 1's sprite is loaded into the GRAM cards in bank 64. The game writes 64 into the 1st byte of bank 0's GRAM card for player 1's sprite at initialization time and then writes into the 2nd byte the index of the card in bank 64 that the bank 0 player 1 card refers to. If there is a lot of animations going on, then this would enable GRAM processing by the CPU to be sped up by a factor of 8. Admittedly, this is more complicated to implement in VHDL and would require a lot more GRAM.
Link to comment
Share on other sites

Your post got me thinking, and I made some changes. Now, writing "eXtR" to 0x33 will kick it into enhanced mode, and there is a timeout of 128 STIC cycles (3.5 MHz) allowed between each of the four writes. Once in enhanced mode, three commands are available. Each of them involves a write to 0x33:


- Writing 0x00 (CMD_PASSTHROUGH) will kick it back to normal (passthrough) mode

- Writing 0x01 (CMD_LORES) will cause it to display "standard" 8x8 characters

- Writing 0x02 (CMD_HIRES) will cause it to display 8x16 character cells (GRAM only)


In high-resolution mode, then GRAM will be mapped into two banks of 64 characters:
- bank 1: even pixels at 800..9FF, odd pixels at A00..BFF
- bank 2: even pixels at C00..DFF, odd pixels at E00..FFF

When using this mode, characters 00..3F point to bank 1 and characters 80..BF point to bank 2. Character codes 40..7F will display only the odd pixels of bank 1 and codes C0..FF will display only the odd pixels of bank 2 (repeated).


So basically, you should only use character codes 00..3F and 80..BF when in high-resolution mode. Changing the memory mapping is tricky because this design doesn't change any of the address/data lines on the STIC bus. That would require it knowing which direction the bus is currently in and it would have to listen to the bus both going to and coming from the STIC.


It's very possible that this needs more work with respect to timing and edge-triggering, but I'm not knowledgeable enough about the Inty...


Edited by JohnPCAE
Link to comment
Share on other sites

On a somewhat-related note, I had a thought about the five color outputs from the STIC. The STIC sends them to the color chip at a rate of about 3.5MHz (i.e. for each color pixel), of which there are 160 per scan line. The color chip, however, outputs information to the RF modulator at four times that rate. What would happen if a board used a PLL circuit to either double or quadruple the clock frequency from the STIC, intercepted the outputs from the STIC to the color chip, and either passed them through as-is or modified them beforehand? Specifically, if the inputs to the color chip changed at either double or quadruple the normal rate, would that allow more than 16 colors?


For chips that receive clock inputs, this wouldn't be the case, but the color chip doesn't take a normal clock input: it takes an input from the crystal and generates a clock for everything else. It might use that clock to latch inputs from the STIC or it might simply put whatever comes in through a series of logic gates to generate an output (basically it's just a translation table). One interesting test might be to take a bare color chip, give it power and ground, but no crystal attached, and see if its outputs changed when its inputs were.

Edited by JohnPCAE
Link to comment
Share on other sites

I designed a little circuit that someone can use to test to see if "hicolor" mode is possible on an NTSC Inty.


How it works:


It looks at the CLK output from the color chip and the V5 input to it. When both are low, it forces the V1 input to the color chip to low. I also added a little jumper so you can use a switch or pushbutton to enable or disable the effect.


It uses the low portion of CLK so that the changes to V1 will occur (at least should occur) during timeslices 3 and 4 of each pixel. It makes sure that V5 is low to ensure that it doesn't interfere with sync, retrace, color burst, etc.


Since it forces V1 low, it means that only odd-numbered colors will change (Blue, Tan, Green, White, Cyan, Brown, Light Blue, Purple) if "hicolor" mode is possible.


If the color chip latches its inputs on a rising clock edge, no colors should change, but if it doesn't (i.e. if it always looks at the current inputs), then you should see colors change when enabling the circuit.


Anyone willing to test it?


Note: This circuit is more complicated than it needs to be -- I did it this way both to minimize the number of chips involved and to use chips that most people might have (hex inverter, quad NAND).



Link to comment
Share on other sites

I did a little experimenting to see what is possible. I took a spare Inty II and did a composite mod to make it easier to test, then I did a small test with the STIC. I put it on a breadboard, routed wires from the mainboard to its pins, then used a high-speed AND gate to intercept the output to V1. I simply ANDed it with the clock signal, which would force V1 low half of the time. If the color chip always read its inputs on each color timeslice it would affect not only the color output, but would also throw off the monitor sync. Unfortunately, there was no change in output. I even put an oscilloscope on clock, incoming V1, and outgoing V1 to make sure that the signals were changing as I had planned. From what I saw, it appears that the color chip is most likely latching V1-V5 on each rising clock edge.


I haven't tested this yet, but according to the datasheet it looks like it might be possible to tease a 17th color out of it by asserting TEST (V1..V5 all set to 1). Maybe I'll give it a try and see what happens.

Link to comment
Share on other sites

Well, I don't have an FPGA kit, but that doesn't mean that I can't experiment. To make things easier, I designed a board I call the STIXperimenter. It's a simple board that lets you intercept STIC signals. Basically, you would unsocket the STIC and put it on the board, and connect the board to the Inty via risers, cables, or whatever suits your fancy. The interface to the mainboard has the same pin layout and pitch as the STIC itself to make this easy. For signals that you wouldn't want to intercept, basically you just jumper the "to STIC" and "to M/B" pin pairs.


There are also pins to tap the STIC's VCC and VSS pins to send power to any components you're testing alongside the STIC.


The ZIP file includes an Eagle schematic and board, as well as a small Eagle library I created for the STIC itself.



Edited by JohnPCAE
Link to comment
Share on other sites

That's a great idea ! And a good usage of my sleepy Xilinx boards...

Please post you new designs, I'll take a look !

It looks like a CoolRunner II CPLD has just enough I/O pins to do the trick. The hard part would be level-shifting all of them to/from 5V.

Edited by JohnPCAE
Link to comment
Share on other sites

Just a little update. I posted my STIXperimenter board to OSH Park at https://oshpark.com/profiles/Hustin13, and I created another one called IntyAVTap. The latter board lets you inject A/V into the Inty 1/2's external audio and/or video pins (JP2 on the board is where you would solder in an edge connector to accept a cart). It also exposes signals that would be needed for timing synchronization and protects them with diodes and low-pass RC filters. I'm looking at using an IDT7208 asynchronous FIFO chip and an Arduino to experiment with piping in video overlay the way the original Keyboard Component did. The FIFO chip is deep enough to store an entire frame of 320x192x2 graphics, which would make the Arduino's job a lot easier (as it wouldn't have to throttle down during a frame).

Link to comment
Share on other sites

In case anyone is interested, while I've been waiting for my PCB's and parts I decided to spend the afternoon trying to characterize initial NTSC STIC timing. I wrote an Arduino sketch that twiddles RSTIN and clock to the STIC and measures various output pins. Below are the timing results that I got. This is a list of all events where SR1, SR2, or ~MSYNC transitioned, as well as the first 6 iterations where I toggle RSTIN.

  count |     clk      T1      T2     SR1     SR2  ~MSYNC   RSTIN
      0 |       0       0       0       1       0       0       1
      1 |       1       0       0       1       0       0       1
      2 |       0       0       0       1       0       0       0
      3 |       1       1       0       1       0       0       0
      4 |       0       1       0       1       0       0       0
      5 |       1       0       1       1       0       0       0
    130 |       0       1       0       1       1       0       1
    632 |       0       0       1       1       0       0       1
    964 |       0       0       1       1       1       0       1
   7752 |       0       1       0       1       0       0       1
   8260 |       0       0       1       1       1       0       1
  15224 |       0       0       1       1       0       0       1
  15560 |       0       0       1       1       1       0       1
  22520 |       0       0       1       1       0       0       1
  22854 |       0       1       0       1       1       0       1
  29816 |       0       0       1       1       0       0       1
  30152 |       0       0       1       1       1       0       1
  37112 |       0       0       1       1       0       0       1
  37450 |       0       1       0       1       1       0       1
  44408 |       0       0       1       1       0       0       1
  44744 |       0       0       1       1       1       0       1
  51704 |       0       0       1       1       0       0       1
  52040 |       0       0       1       1       1       0       1
  52040 |       0       1       0       1       0       0       1
  52042 |       0       1       0       1       1       0       1
  59000 |       0       0       1       1       0       0       1
  59338 |       0       1       0       1       1       0       1
  66296 |       0       0       1       1       0       0       1
  66632 |       0       0       1       1       1       0       1
  73592 |       0       0       1       1       0       0       1
  73930 |       0       1       0       1       1       0       1
  80888 |       0       0       1       1       0       0       1
  81224 |       0       0       1       1       1       0       1
  81224 |       0       1       0       1       0       0       1
  81226 |       0       1       0       1       1       0       1
  88184 |       0       0       1       1       0       0       1
  88520 |       0       0       1       1       1       0       1
  95480 |       0       0       1       1       0       0       1
  95816 |       0       0       1       1       1       0       1
  95816 |       0       1       0       1       0       0       1
  95818 |       0       1       0       1       1       0       1
  96800 |       0       1       0       0       1       0       1
 118980 |       0       1       0       0       1       1       1
 120056 |       0       1       0       1       1       1       1
 216272 |       0       1       0       0       1       1       1
 239528 |       0       1       0       1       1       1       1
 335744 |       0       1       0       0       1       1       1
 359000 |       0       1       0       1       1       1       1
 455216 |       0       1       0       0       1       1       1
 478472 |       0       1       0       1       1       1       1
 574688 |       0       1       0       0       1       1       1
 597944 |       0       1       0       1       1       1       1
 694160 |       0       1       0       0       1       1       1
events: 53

One thing of note is that speed was a factor: if you drive the STIC too slowly, the SR1 and SR2 outputs behave very differently. To this end I had to record events as they happen and log them at the end. I also had to use nonstandard code to write and read the Arduino pins to maximize speed.


EDIT: from repeated runs, it looks like the time that SR2 transitions can vary widely before the edge transition at 96800, but SR1 timing appears to be consistent. Odd.

Edited by JohnPCAE
Link to comment
Share on other sites

Still waiting on parts and PCB's, so I measured some more timing goodies in the meantime.


1 frame = 59736 cycles = 262 scanlines * 228 cycles/scanline

SR1 = high for 211 scanlines per frame (STIC time)
SR1 = low for 51 scanlines per frame (CPU time)

CPU time: 51 scanlines
STIC time: 211 scanlines

Per scanline:

blanking ON for 38 cycles = 38 pixels
blanking OFF for 190 cycles = 190 pixels

STIC time begins/ends 22.5 cycles (45 edge transitions) after blanking is ON:

0 Blanking ON
22.5 STIC time begin/end
38 Blanking OFF


This is for a STIC right after startup, i.e. delay registers are set to 0.

Edited by JohnPCAE
Link to comment
Share on other sites

  • 2 weeks later...

My A/V tap boards arrived today, so I'll probably be building them this weekend. In the meantime, I've been finalizing my schematic for the Inty II power supply. I found some problems with the last schematic, but this one should finally be correct. Just for kicks I also updated the board layout to make it more robust.


I also learned something very interesting: the PSU in the Inty II is VERY similar to the PSU in the Acorn Electron (http://chrisacorns.computinghistory.org.uk/docs/Acorn/Manuals/Acorn_ElectronSM.pdf). It turns out that both were made by ASTEC. Many of the components even have the same values. The two main differences are that the Inty needs multiple outputs from the transformer and it has a different control circuit for turning power on and off.


Attached is the (hopefully final) version of my Inty II PSU schematic and board, as well as a couple pictures of the Acorn Electron PSU. One thing of note is that they also share the same power regulator (X44C758, which is how I ran across it in the first place).




Link to comment
Share on other sites

Found a really good picture of the Acorn PSU that shows the SCR (marked 0100 -- it looks like a transistor but isn't). It's the same as component IC1 in the Inty II PSU. I'm still really annoyed that I can't positively identify it. If I update the schematic one last time it will be if I manage to identify it.


Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...