Let's start at the very beginning...
Re: Let's start at the very beginning...
(Although full-fat BBC Basic is 16k, there are certainly ways of trimming off some bytes, for example to make room for a mini-MOS and still fitting in 16k. See the topic Heresy! Hacking chunks out of 6502 Basic ROMs over on stardot.)
Once you've got solid state storage, you can load an application such as Basic into RAM at boot time for no real penalty.
Once you've got solid state storage, you can load an application such as Basic into RAM at boot time for no real penalty.
- BigDumbDinosaur
- Posts: 9425
- Joined: 28 May 2009
- Location: Midwestern USA (JB Pritzker’s dystopia)
- Contact:
Re: Let's start at the very beginning...
DRG wrote:
My (ultimate) ambition would to be to run BBC Basic on my 65C02 SBC...
That would be a worthwhile goal—as 8-bit interpreters go, it was significantly better than the Micro-Soft equivalent.
Quote:
Ah, yes. WinCUPL, 22V10s and positive/negative logic - nothing there to bamboozle an electronics tyro, no? So, I already was aware of the concept of active low chip select logic and that was my intention in writing my GAL code i.e. for the pin to output a logic low for the device for the appropriate memory address. However, I wasn't aware that the way one writes the code can make a difference to the code - I assumed anything equivalent would be assembled into identical code in the GAL for example...
...would be the same.
Code: Select all
Pin 1 = !WE
WE = CLK & !RW
and
Pin 1 = WE
!WE = CLK & !RWThe two approaches seem the same. However, the second rendition when compiled into a JEDEC file, will be implemented with “double negative” logic on the right-hand side of the equation, effectively:
Code: Select all
WE = !(CLK & !RW)Declaring WE as active-low, as in your first equation, uses no extra logic—it merely “connects” an inverter in between the internal gates that implement the logic and the output pin. In the realm of a GAL, that inverter costs nothing in terms of logic resources and has negligible effect on prop time.
Quote:
Taking on board some earlier comments, I will also remove my zero page VIA and settle for a more conventional memory map.
Good choice, in my opinion. Rarely does mapping I/O hardware into page zero gain anything. Device drivers tend to spend much more time manipulating data, pointers, indices, etc., than touching hardware. It is the pointers and indices that should be in zero page.
Quote:
Finally, "increases PT usage" - at the risk of looking silly, what's PT?
Product Term. In the realm of programmable logic, a product term is a resource, i.e., internal gate, that is able to implement a logic expression. The term comes from Boolean algebra, in which a product term is effectively a logic expression, e.g., A AND B, which would be written as A ∧ B in Boolean notation.
A limited number of PTs are available per pin in a GAL. If you try to create too complex an equation for an output, or if the way the equation is written can’t be sufficiently minimized, the compiler will stop and report too many product terms, or something similar, when it tries to compile the equation. Using inverted logic for address decoding that ultimately drives what is supposed to be an active-low output complicates the minimization process, possibly leading to a design that won’t compile.
See the attached CUPL manual, which among other things, mentions why inverted logic is not recommended.
x86? We ain't got no x86. We don't NEED no stinking x86!
Re: Let's start at the very beginning...
I think I have taken into account what advice has been posted in this thread and attempted to write my WinCUPL file so to not have any double-negative or inverted logic. I want all chip selects to be active-low. My cupl code is based on my understanding that the command RAM = Address:[000x..BFFx] will set the variable RAM to a logical 1 if the current address falls in the range 0000 - BFFF. I want the RAM CS to be zero if this is the case, so use the "!" prefix to negate to a 0.
48K RAM, 16K ROM.
It compiles with zero errors or warnings. Here it is for comment...
Dave.
48K RAM, 16K ROM.
It compiles with zero errors or warnings. Here it is for comment...
Code: Select all
Device p22v10;
/* Pin Map
--------
CLK |1 24| Vcc
RW |2 23| WEB
A15 |3 22| OEB
A14 |4 21| RAM_CSB
A13 |5 20| ROM_CSB
A12 |6 19| IO_0_CSB
A11 |7 18| IO_1_CSB
A10 |8 17| IO_2_CSB
A9 |9 16| IO_3_CSB
A8 |10 15| A4
A7 |11 14| A5
Gnd |12 13| A6
--------
*/
/*
=======================================
Inputs: All are signals from the 65C02
=======================================
*/
Pin 1 = CLK;
Pin 2 = RW;
Pin [3..11] = [A15..7];
Pin [13..15] = [A6..4];
/*
=================================================
Outputs: define outputs - all are positive logic
=================================================
*/
Pin 23 = WEB; /* to RAM and ROM chips */
Pin 22 = OEB; /* to RAM and ROM chips */
Pin 21 = RAM_CSB; /* to RAM /CS pin */
Pin 20 = ROM_CSB; /* to ROM /CS pin */
Pin 19 = IO_0_CSB; /* to IO_0 CS pin */
Pin 18 = IO_1_CSB; /* to IO_1 CS pin */
Pin 17 = IO_2_CSB; /* to IO_2 CS pin */
Pin 16 = IO_3_CSB; /* to IO_3 CS pin */
/*
===============
Local variables
===============
*/
FIELD Address = [A15..4];
RAM = Address:[000x..BFFx];
ROM0 = Address:[C00x..FDFx];
IO_0 = Address:[FE0x..FE0x];
IO_1 = Address:[FE1x..FE1x];
IO_2 = Address:[FE2x..FE2x];
IO_3 = Address:[FE3x..FE3x];
ROM1 = Address:[FF0x..FFFx];
/*
===============
Logic equations
===============
*/
WEB = !(CLK & !RW);
OEB = !(CLK & RW);
RAM_CSB = !RAM;
ROM_CSB = !(ROM0 # ROM1);
IO_0_CSB = !IO_0;
IO_1_CSB = !IO_1;
IO_2_CSB = !IO_2;
IO_3_CSB = !IO_3;- BigDumbDinosaur
- Posts: 9425
- Joined: 28 May 2009
- Location: Midwestern USA (JB Pritzker’s dystopia)
- Contact:
Re: Let's start at the very beginning...
DRG wrote:
My cupl code is based on my understanding that the command RAM = Address:[000x..BFFx] will set the variable RAM to a logical 1 if the current address falls in the range 0000 - BFFF.
Basically, that is correct, but in logic design, think in terms of “true” or “false”, not “1” or “0”.
Quote:
I want the RAM CS to be zero if this is the case, so use the "!" prefix to negate to a 0.
No, sir. When you define a pin that is active-low, you negate its definition, not the equation that drives it. By negating the pin definition, the effect will be pin goes low when expression is true. That uses fewer PTs than does inverting the equation.
Code: Select all
Pin 21 = RAM_CSB;
RAM = Address:[000x..BFFx];
RAM_CSB = !RAM;The above is inefficient and in addition to wasting PTs by inverting the RAM expression, wastes PTs with unnecessary address decoding granularity. In the address range assigned to RAM, only bits 15-12 are relevant, since the highest possible RAM address will be $BFFF and the lowest possible address will be $0000. Knowing that, and also desiring to reduce clutter in the CUPL source file, I’d do it thusly:
Code: Select all
Pin 21 = !RAM_CSB; /* define this pin as active-low output */
RAM_CSB = Address:[0xxx..Bxxx]; /* select RAM if address is below $C000 */In the above, I define the RAM_CSB output as active-low and use the address field evaluation to directly control the RAM chip select—no intermediate variable needed. The resulting equation is positive logic and the fact that RAM_CSB is defined as active-low means it will be high when Address:[0xxx..Bxxx] evaluates false. Conversely, RAM_CSB will be low when Address:[0xxx..Bxxx] evaluates true.
Intermediate variables only become useful when the same expression is used in multiple equations. The Address:[000x..BFFx] evaluation is only used once in your design, so there is no value in assigning it to an intermediate variable.
Quote:
It compiles with zero errors or warnings.
I loaded your code into WinCUPL and tried to compile it. Compilation failed with an excessive product terms diagnostic for the ROM chip select output equation. Here’s the verbatim diagnostic:
- The number of product terms needed to implement the logic expression for the given variable exceeds the capacity of the output pin for which it was declared.
Have you left something out?
x86? We ain't got no x86. We don't NEED no stinking x86!
Re: Let's start at the very beginning...
Thanks so much for that input, BDD - that's taught me quite a bit.
I have reworked it as below and, again, it compiles without errors or warnings. This time I have also attached the PLD file so it's easier to verify. Are there compiler specific setting that need to be made in WinCUPL? - I have not changed the default ones that it was installed with.
I have reworked it as below and, again, it compiles without errors or warnings. This time I have also attached the PLD file so it's easier to verify. Are there compiler specific setting that need to be made in WinCUPL? - I have not changed the default ones that it was installed with.
Code: Select all
Name DRG65C02 Address Decoder;
Partno DRG65C02;
Revision 02;
Date 22/11/2024;
Designer DRG;
Company ;
Location Edenfield, Lancs. UK;
Assembly None;
Device p22v10;
/* Pin Map
--------
CLK |1 24| Vcc
RW |2 23| WEB
A15 |3 22| OEB
A14 |4 21| RAM_CSB
A13 |5 20| ROM_CSB
A12 |6 19| IO_0_CSB
A11 |7 18| IO_1_CSB
A10 |8 17| IO_2_CSB
A9 |9 16| IO_3_CSB
A8 |10 15| A4
A7 |11 14| A5
Gnd |12 13| A6
--------
*/
/*
=======================================
Inputs: All are signals from the 65C02
=======================================
*/
Pin 1 = CLK;
Pin 2 = RW;
Pin [3..11] = [A15..7];
Pin [13..15] = [A6..4];
/*
=================================================
Outputs: define outputs - all are positive logic
=================================================
*/
Pin 23 = !WEB; /* to RAM and ROM chips */
Pin 22 = !OEB; /* to RAM and ROM chips */
Pin 21 = !RAM_CSB; /* to RAM /CS pin */
Pin 20 = !ROM_CSB; /* to ROM /CS pin */
Pin 19 = !IO_0_CSB; /* to IO_0 CS pin */
Pin 18 = !IO_1_CSB; /* to IO_1 CS pin */
Pin 17 = !IO_2_CSB; /* to IO_2 CS pin */
Pin 16 = !IO_3_CSB; /* to IO_3 CS pin */
/*
===============
Local variables
===============
*/
FIELD Address = [A15..4];
ROM0 = Address:[C0xx..FDxx];
ROM1 = Address:[FFxx..FFxx];
/*
===============
Logic equations
===============
*/
WEB = CLK & !RW;
OEB = CLK & RW;
RAM_CSB = Address:[0xxx..Bxxx];
ROM_CSB = ROM0 # ROM1;
IO_0_CSB = Address:[FE0x..FE0x];
IO_1_CSB = Address:[FE1x..FE1x];
IO_2_CSB = Address:[FE2x..FE2x];
IO_3_CSB = Address:[FE3x..FE3x];- Attachments
-
- 65C02_V2.PLD.txt
- (1.81 KiB) Downloaded 23 times
Re: Let's start at the very beginning...
BigEd wrote:
(Although full-fat BBC Basic is 16k, there are certainly ways of trimming off some bytes, for example to make room for a mini-MOS and still fitting in 16k. See the topic Heresy! Hacking chunks out of 6502 Basic ROMs over on stardot.)
Here are examples with a mini-MOS for the BenEater and Grant Searle SBCs.
--
JGH - http://mdfs.net
JGH - http://mdfs.net
Re: Let's start at the very beginning...
Since inexpensive RAM and ROM are 64K or bigger, it makes sense to copy contents of ROM into RAM at reset and switch out ROM, so you wind up with a RAM only system. An inexpensive fast 45nS ROM is W27C512 and an inexpensive fast RAM is W24512.
Bill
Bill
Re: Let's start at the very beginning...
plasmo wrote:
Since inexpensive RAM and ROM are 64K or bigger, it makes sense to copy contents of ROM into RAM at reset and switch out ROM, so you wind up with a RAM only system. An inexpensive fast 45nS ROM is W27C512 and an inexpensive fast RAM is W24512.
Bill
Bill
I like the idea but think that is too advanced for me at the moment.
Re: Let's start at the very beginning...
A true ROM-less design uses DMA to fill RAM or boot strap from serial/parallel/IDE. It can be fairly complicated, although PROG65 boots from FT245 and only has 2 TTL logic. Most of my 6502 designs have small ROM in either CPLD or 22V10 to load system RAM and then page out the small ROM. I do have couple designs that have traditional ROM. Here is one that’s a very simple 6502 design (no glue logic) that boots from ROM, copy to RAM and page out ROM.
https://www.retrobrewcomputers.org/doku ... 6502r1home
Bill
PS, here is a rather long discussion about it on 6502.org viewtopic.php?f=4&t=6455
https://www.retrobrewcomputers.org/doku ... 6502r1home
Bill
PS, here is a rather long discussion about it on 6502.org viewtopic.php?f=4&t=6455
Re: Let's start at the very beginning...
Why is it advantageous to copy ROM content to RAM and then page out ROM for an all-RAM system?
I can think of a couple of possible reasons
- the ROM is slower, or the slightly more complex decode is slower, and so once the all-RAM setup is in place the clock speed can be increased
- once the software has been copied from ROM to RAM it's possible to patch it, or for it to include some self-patching code.
Is there another reason?
I can think of a couple of possible reasons
- the ROM is slower, or the slightly more complex decode is slower, and so once the all-RAM setup is in place the clock speed can be increased
- once the software has been copied from ROM to RAM it's possible to patch it, or for it to include some self-patching code.
Is there another reason?
Re: Let's start at the very beginning...
In 8080/8085/Z80 systems (Yes! Heresy!) there is often a need to use the restart vectors at 0x00, 0x08, 0x10... 0x38 for different purposes in a running program - for example, MS basic and CP/M used the vectors for completely different things. But irrespective, the reset vector is always 0x00, so ideally you want ROM there - at least to start.
Once your initial reset is complete, if you've changed from ROM to RAM, you can change the vectors at will. So you might arrange things such that the reset switches in the ROM at 0x0000 to perform the reset; code then sequentially reads the ROM and writes back to the same address; hidden magic ensures that the RAM is written (obviously the ROM can't be!) and once that's complete a switch selects RAM for reading rather than ROM.
A similar system (and need) might be envisaged for maximum flexibility from a 6502 system, but in this case the reset and interrupt vectors are at the top of memory rather than the bottom.
Note that this doesn't require any change in data or address lines; only read/write, chip select, and output enable need some thought.
Neil
Once your initial reset is complete, if you've changed from ROM to RAM, you can change the vectors at will. So you might arrange things such that the reset switches in the ROM at 0x0000 to perform the reset; code then sequentially reads the ROM and writes back to the same address; hidden magic ensures that the RAM is written (obviously the ROM can't be!) and once that's complete a switch selects RAM for reading rather than ROM.
A similar system (and need) might be envisaged for maximum flexibility from a 6502 system, but in this case the reset and interrupt vectors are at the top of memory rather than the bottom.
Note that this doesn't require any change in data or address lines; only read/write, chip select, and output enable need some thought.
Neil
- BigDumbDinosaur
- Posts: 9425
- Joined: 28 May 2009
- Location: Midwestern USA (JB Pritzker’s dystopia)
- Contact:
Re: Let's start at the very beginning...
DRG wrote:
Thanks so much for that input, BDD - that's taught me quite a bit.
I have reworked it as below and, again, it compiles without errors or warnings. This time I have also attached the PLD file so it's easier to verify. Are there compiler specific setting that need to be made in WinCUPL? - I have not changed the default ones that it was installed with.
I have reworked it as below and, again, it compiles without errors or warnings. This time I have also attached the PLD file so it's easier to verify. Are there compiler specific setting that need to be made in WinCUPL? - I have not changed the default ones that it was installed with.
My bad!
As for your revisions, please see attached. I slightly revised your revisions, especially with regards to the ROM chip-select equation. Also, assuming you are using the ATF22V10C, the device mnemonic for that part is g22v10, not p22v10. The latter is for compiling to make the 22V10C look like its ancestral PAL device. Since this is a new design, no reason to do so. Refer to page 9, section 10, of the Atmel data sheet for more info.
BTW, just an opinion, but I think your address decoding is excessively granular. As you have it, a total of 16 I/O devices can fit into the I/O page ($FExx). However, such an arrangement is physically impossible with a 22V10, due to insufficient output-capable pins.
I would reduce the granularity by two bits (get rid of A4 and A5), which will give you two more pins for other purposes. Such a change would allocate enough decoded address space in the I/O page for the four I/O devices you have, and give you the option of using one of the freed-up pins to enable a wait-state when ROM or slow I/O is selected.
plasmo wrote:
Since inexpensive RAM and ROM are 64K or bigger, it makes sense to copy contents of ROM into RAM at reset and switch out ROM, so you wind up with a RAM only system.
The other pin could be used to control ROM/RAM shadowing, similar to what Bill (plasmo) mentions. A trivial change to the logic would make it possible for a write to the ROM address space to “bleed through” into RAM (although having I/O where you have it, smack dab in the middle of ROM address space, complicates things). That way, your reset code could copy ROM into (shadow) RAM, and then switch off the ROM. With that done, there would be no need for a wait-state to access the firmware. Your non-wait-stated Ø2 clock “ceiling” would be determined by the speed of the RAM you use—SRAM down to 10ns is available. Since the GAL is generating the /RD and /WD signals, it would also be trivial to arrange for shadow RAM write-protection once ROM has been switched out.
————————————————————————————————————
Edit: I originally posted the wrong copy of the PLD file. The correct version is attached.
Last edited by BigDumbDinosaur on Sat Nov 23, 2024 8:57 am, edited 2 times in total.
x86? We ain't got no x86. We don't NEED no stinking x86!
- GARTHWILSON
- Forum Moderator
- Posts: 8773
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Re: Let's start at the very beginning...
BigEd wrote:
Why is it advantageous to copy ROM content to RAM and then page out ROM for an all-RAM system?
I can think of a couple of possible reasons
- the ROM is slower, or the slightly more complex decode is slower, and so once the all-RAM setup is in place the clock speed can be increased
- once the software has been copied from ROM to RAM it's possible to patch it, or for it to include some self-patching code.
Is there another reason?
I can think of a couple of possible reasons
- the ROM is slower, or the slightly more complex decode is slower, and so once the all-RAM setup is in place the clock speed can be increased
- once the software has been copied from ROM to RAM it's possible to patch it, or for it to include some self-patching code.
Is there another reason?
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
Re: Let's start at the very beginning...
Many good reasons for RAM-only system have already being mentioned in last few posts. Other reasons for RAM-only are interrupt vectors can be changed, and updated ROM software can be patched/tested without reprogramming ROM.
Re: Let's start at the very beginning...
OK, well, the good thing is I understood everything you said in your post, BDD, regarding the GAL & address decoding. Oh, and thank you for taking the time to do those revisions.
In terms of granularity, I have no issue with doing this if I still have 4 I/Os. Also, I am not wedded to I/O being in page FE. But it does beg the question where is best to map I/O (and I'm guessing there is no universal answer but... depends). Hence, I can move it to page 02 if that makes it easier in terms of system configuration.
On the matter of copying ROM to RAM, however, and in borrowing from JFK - the greater my knowledge increases, the more my ignorance unfolds. RAM & ROM would occupy the same memory addresses but can be switched allowing ROM to occupy the space first and then RAM to take this space in the final configuration. This leads me to ask some questions:-
On the matter of copying ROM to RAM, however, and in borrowing from JFK - the greater my knowledge increases, the more my ignorance unfolds. RAM & ROM would occupy the same memory addresses but can be switched allowing ROM to occupy the space first and then RAM to take this space in the final configuration. This leads me to ask some questions:-
- what is doing the switching out if they occupy the same space i.e. is what is controlling the chip selects?
- the reason for doing this is to dispense with "slow" ROM - so how do you work with ROM initially with a slow clock speed and then increase the clock when it's RAM only? Is this what wait-states are for and can be programmed into the 22V10C?
- in the context for posts in this thread, is there a difference between "shadow" RAM and "banked" RAM?