Another Bootstrap for a ROM less system

For discussing the 65xx hardware itself or electronics projects.
User avatar
cbscpe
Posts: 491
Joined: 13 Oct 2013
Location: Switzerland
Contact:

Another Bootstrap for a ROM less system

Post by cbscpe »

Hi,

several times there have been topics regarding bootstrapping a 6502 (or other systems) and the issues regarding slow ROMs in fast systems. Currently I have solved that using a DP-RAM that is used to bootstrap the 6502 and at the same time is the frame buffer for the VGA output.

But now I wanted to make a system without a video controller and with much less components. So I came up with the following solution.
bootstrap-design.pdf
CPU, Memory, Decoder and AVR
(24.75 KiB) Downloaded 251 times
Note that this is only a concept. Before I jump into this I first wanted to check if this really is feasible or if there is something that is obviously wrong or will not work.

The memory decoder is a simple decoder that supports two memory maps selected with IML (short form for Initial Machine Load). When IML is Low addresses $0000 to e.g. $BFFF will select the RAM for read and writes, addresses $C000..$C0FF decode to one of the IO select signals and for addresses $C100..$FFFF selects the RAM only for read accesses. When IML is High the RAM is only selected for write cycles, but not only for $0000..$BFFF but as well for $C100..$FFFF. Bootstrap is achieved via the AVR that controls RESET and PHI and during startup makes the 6502 think that he reads a ROM image, when in fact the AVR just emits the bytes that would be expected.

Here is the AVR code I have written so far for that purpose.

Code: Select all

;
;	Inject a ROM loader loop
;
;
;	0300-   A9 00       LDA   #$00
;	0302-   8D AA AA    STA   $AAAA
;	0305-   4C 00 03    JMP   $0300
;

.def	zero	r2
.def	ff	r3
.def	temp	r17


.equ	LDA	0xA9
.equ	STA	0x8D
.equ	JMP	0x4C
.equ	PHI2	3			
.equ	RESET	1
.equ	IML	2			; Initial machine load
.equ	ROMSTART	0xD000		; Or whereever the 6502 ROM starts
;--------------------------------------------------------------------------
;
;	Initialization of AVR
;
reset:
	clr	zero
	ldi	temp, 0xff
	mov	ff, temp

	ldi
	cbi	PORTB, PHI2
	sbi	DDRB, PHI2		; PHI2 is output

	cbi	DDRB, RESET
	cbi	PORTB, RESET		; Let the pull-up do it's job

	sbi	DDRD, IML
	ldi	zl, low(2*romimage)
	ldi	zh, high(2*romimgea)
	ldi	xl, low(ROMSTART)
	ldi	xh, high(ROMSTART)
	
	sbi	PORTD, IML		; Activate boot mode decoder
;--------------------------------------------------------------------------
;
;
;
	sbi	DDRB, RESET		; Activate Reset

	sbi	PORTB, PHI2		; Generate some PHI2 cycles
	nop				; Need at least 2 cycles
	nop
	nop
	cbi	PORTB, PHI2
	nop
	nop
	nop
	sbi	PORTB, PHI2
	nop
	nop
	nop
	cbi	PORTB, PHI2
	nop
	nop
	nop
	sbi	PORTB, PHI2
	nop
	nop
	nop
	cbi	PORTB, PHI2
	nop
	nop
	nop
	sbi	PORTB, PHI2
	nop
	nop
	nop
	cbi	PORTB, PHI2
	nop
	nop
	nop
	sbi	PORTB, PHI2
	cbi	DDRB, RESET		; Release Reset, when a positive
	nop				; Edge is detected the 6502 will
	nop				; start a reset cycle
	nop
;--------------------------------------------------------------------------
;
;	The eight reset cycles
;
	cbi	PORTB, PHI2		; Cycle 0
	nop
	nop
	nop
	sbi	PORTB, PHI2
	nop
	nop
	nop
	
	cbi	PORTB, PHI2		; Cycle 1
	nop
	nop
	nop
	sbi	PORTB, PHI2
	nop
	nop
	nop

	cbi	PORTB, PHI2		; Cycle 2
	nop
	nop
	nop
	sbi	PORTB, PHI2
	nop
	nop
	nop

	cbi	PORTB, PHI2		; Cycle 3
	nop
	nop
	nop
	sbi	PORTB, PHI2
	nop
	nop
	nop

	cbi	PORTB, PHI2		; Cycle 4
	nop
	nop
	nop
	sbi	PORTB, PHI2
	nop
	nop
	nop

	cbi	PORTB, PHI2		; Cycle 5
	nop
	nop
	nop
	sbi	PORTB, PHI2
	nop
	nop
	nop

	jmp	setv			; Cycle 6 and 7 read the reset
					; vector value which is the same
					; as the JMP will loop to, so use 
					; this code.
;--------------------------------------------------------------------------
;
;	Generate one cycle: Opcode LDA immediate
;
;	
	cbi	PORTB, PHI2		;	PHI2 = Low
	out	DDRC, zero		;	Disable buffer
	out	DDRD, zero		;
;
	ldi	temp, LDA		;	Get Opcode
	out	PORTC, temp		;	Set Buffer
	cbi	PORTD, 6		;	and
	sbi	PORTD, 7		; 	Set PORT bits
	sbi	PORTB, PHI2		;	PHI2 = High
	out	DDRC, ff		; 	Enable buffer
	out	DDRD, ff
	nop				; 	Give CPU some time
	nop
	nop
;--------------------------------------------------------------------------
;
;	Generate one cycle: Immediate Value
;
	cbi	PORTB, PHI2		;	PHI2 = Low
	out	DDRC, zero		;	Disable buffer
	out	DDRD, zero		;
;	
	
	lpm	temp, Z+		;	Get immediate value
	out	PORTC, temp		;	Set Buffer
	cbi	PORTD, 6		;	and
	sbrc	temp, 6
	sbi	PORTD, 6
	cbi	PORTD, 7		
	sbrc	temp, 7
	sbi	PORTD, 7		; 	Set PORT Bits
	sbi	PORTB, PHI2		;	PHI2 = High
	out	DDRC, ff		;	Enable Buffer
	out	DDRD, ff
	nop				; 	Give CPU some time
	nop
	nop

;--------------------------------------------------------------------------
;
;	Generate one cycle: Opcode STA absolute
;
;	
	cbi	PORTB, PHI2		;	PHI2 = Low
	out	DDRC, zero		;	Disable buffer
	out	DDRD, zero		;
;
	ldi	temp, STA		;	Get Opcode
	out	PORTC, temp		;	Set Buffer
	cbi	PORTD, 6		;	and
	sbi	PORTD, 7		; 	Set PORT bits
	sbi	PORTB, PHI2		;	PHI2 = High
	out	DDRC, ff		; 	Enable buffer
	out	DDRD, ff
	nop				; 	Give CPU some time
	nop
	nop
;--------------------------------------------------------------------------
;
;	Generate one cycle: low byte address
;
	cbi	PORTB, PHI2		;	PHI2 = Low
	out	DDRC, zero		;	Disable buffer
	out	DDRD, zero		;
;	
	
	out	PORTC, xl		;	Get Low Byte
	cbi	PORTD, 6		;	and
	sbrc	xl, 6
	sbi	PORTD, 6
	cbi	PORTD, 7		
	sbrc	xl, 7
	sbi	PORTD, 7		; 	Set PORT Bits
	sbi	PORTB, PHI2		;	PHI2 = High
	out	DDRC, ff		;	Enable Buffer
	out	DDRD, ff
	nop				; 	Give CPU some time
	nop
	nop
;--------------------------------------------------------------------------
;
;	Generate one cycle: high byte address
;
	cbi	PORTB, PHI2		;	PHI2 = Low
	out	DDRC, zero		;	Disable buffer
	out	DDRD, zero		;
;	
	
	out	PORTC, xh		;	Get Low Byte
	cbi	PORTD, 6		;	and
	sbrc	xh, 6
	sbi	PORTD, 6
	cbi	PORTD, 7		
	sbrc	xh, 7
	sbi	PORTD, 7		; 	Set PORT Bits
	sbi	PORTB, PHI2		;	PHI2 = High
	out	DDRC, ff		;	Enable Buffer
	out	DDRD, ff
	nop				; 	Give CPU some time
	nop
	nop
	
;--------------------------------------------------------------------------
;
;	Generate one cycle: write byte to SRAM
;
	cbi	PORTB, PHI2		;	PHI2 = Low
	out	DDRC, zero		;	Disable buffer
	out	DDRD, zero		;
	nop
	nop
	nop
	nop
	sbi	PORTB, PHI2		;	PHI2 = High
	nop				; 	Give CPU some time
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	adiw	xh:xl, 1
	breq	done			;	Stop after writing to $FFFF
;--------------------------------------------------------------------------
;
;	Generate one cycle: Opcode JMP absolute
;
;	
	cbi	PORTB, PHI2		;	PHI2 = Low
	out	DDRC, zero		;	Disable buffer
	out	DDRD, zero		;
;
	ldi	temp, JMP		;	Get Opcode
	out	PORTC, temp		;	Set Buffer
	sbi	PORTD, 6		;	and
	cbi	PORTD, 7		; 	Set PORT bits
	sbi	PORTB, PHI2		;	PHI2 = High
	out	DDRC, ff		; 	Enable buffer
	out	DDRD, ff
	nop				; 	Give CPU some time
	nop
	nop
;--------------------------------------------------------------------------
;
;	Generate one cycle: low byte address of $0300
;
setv:
	cbi	PORTB, PHI2		;	PHI2 = Low
	out	DDRC, zero		;	Disable buffer
	out	DDRD, zero		;
;	
	
	out	PORTC, zero
	cbi	PORTD, 6
	cbi	PORTD, 7
	sbi	PORTB, PHI2		;	PHI2 = High
	out	DDRC, ff		;	Enable Buffer
	out	DDRD, ff
	nop				; 	Give CPU some time
	nop
	nop
;--------------------------------------------------------------------------
;
;	Generate one cycle: high byte address of $0300
;
	cbi	PORTB, PHI2		;	PHI2 = Low
	out	DDRC, zero		;	Disable buffer
	out	DDRD, zero		;
;	
	ldi	temp, 0x03	
	out	PORTC, temp		;	Get Low Byte
	cbi	PORTD, 6		;	and
	cbi	PORTD, 7		
	sbi	PORTB, PHI2		;	PHI2 = High
	out	DDRC, ff		;	Enable Buffer
	out	DDRD, ff
	nop				; 	Give CPU some time
	nop
	nop
	jmp	loop
;--------------------------------------------------------------------------
;
;	Finished loading bootrom
;
done	cbi	PORTB, PHI2		;

;--------------------------------------------------------------------------
;
;	Now the upper memory should be filled with the ROM image
;
;

	cbi	PORTD, IML		; Activate normal memory decocder
	sbi	DDRD, RESET		; Assert RESET
;
;	Now we can programm Timer 2 to act as source for PHI2
;	the maximum clock frequency we can achieve is AVRCLK/2
;	a modern AVR supports a clock up to 20MHz, you can easily over
;	clock it to 25MHz other options would use an external clock
;	that would have to be multiplexed by the GAL using IML as select
;
;
;	Timer is started in CTC mode with TOP=OCR2A and no prescaler
;	this gives an output of AVRCLK/2 as PHI2 for the 6502
;
	out	OCR2A, zero
	ldi	temp, (COM2A1<<0) | (COCM2A0<<1) | (COM2B1<<0) | (COCM2B0<<1) | (WGM21<<1) | (WGM20<<0)
	out	TCCR2A, temp
	ldi	temp, (WGM22<<0) | (CS22<<0) | (CS21<<0) | (CS20<<1)
	out	TCCR2B, temp
;
;	Now the real reset starts, so we need to wait at least 2 PHI2 cycles 
;	before we de-assert RESET
;
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	cbi	DDRD, RESET		; De-Assert RESET
;
;	Now the 6502 executes the normal RESET with the vector in the loaded
;	ROM Image.
;
	....				; And the AVR can do what ever we
	....				; want him to do.

The trick here is not to control the address bus. Instead after a reset of the AVR we control the PHI2 via Software and put out the bytes the 6502 would read when we really had a ROM. The ROM we present is rather small, it is a RESET vector and 3 instructions that just write immediate data to the memory in a loop. As the RAM is write enabled this loop can now load a ROM image. After the image is loaded IML is de-asserted and the 6502 is RESET and start the ROM with it's own reset vector
User avatar
BigEd
Posts: 11463
Joined: 11 Dec 2008
Location: England
Contact:

Re: Another Bootstrap for a ROM less system

Post by BigEd »

I think the broad idea is sound - and simple - and a good idea. But I haven't reviewed your code or anything.
User avatar
Michael
Posts: 633
Joined: 13 Feb 2013
Location: Michigan, USA

Re: Another Bootstrap for a ROM less system

Post by Michael »

cbscpe wrote:
Note that this is only a concept. Before I jump into this I first wanted to check if this really is feasible or if there is something that is obviously wrong or will not work.
You should be able to get this to work. It seems similar to the "blind loader" method I implement using a PIC in my designs (which include the address decoder function in the PIC as well).

I've included example loader code below which copies a pseudo ROM image from PIC flash memory at $E000..$FFFF to 65C02 RAM memory at $E000..$FFFF.

Good luck on your project, Sir.

Cheerful regards, Mike

Code: Select all

  /*                                                                *
   *  R65C02 Reset Sequence (decoder off), FFFC = ioloc             *
   *                                                                */
     reset_pin = 0;             // reset lo
     cyc_rd(); cyc_rd();        // 2 clocks
     reset_pin = 1;             // reset hi
     cyc_rd();                  // clock 1
     cyc_rd();                  // clock 2
     cyc_rd();                  // clock 3
     cyc_rd();                  // clock 4
     cyc_rd();                  // clock 5
     cyc_wr(io_lo);             // clock 6, Rd FFFC = ioloc lo
     cyc_wr(io_hi);             // clock 7, Rd FFFD = ioloc hi
  /*                                                                *
   *  copy code to RAM (decoder on)                                 *
   *                                                                */
     tblptrl = 0x00;            // point to rom image
     tblptrh = 0xE0;            // at E000..FFFF (8K)
     tblptru = 0x00;            //
     do                         // copy rom image to ram
     { loader(0xA9);            // R DF00 A9, LDA #$nn
       asm tblrd*               //
       loader(tablat);          // R DF01 nn
       loader(0x8D);            // R DF02 8D, STA $hhll
       loader(tblptrl);         // R DF03 ll, aaaa%256
       loader(tblptrh);         // R DF04 hh, aaaa/256
       loader(tblptrh);         // W hhll nn, write op
       loader(0x4C);            // R DF05 4C, JMP ioloc
       loader(io_lo);           // R DF06 00
       loader(io_hi);           // R DF07 DF
       tblptrl++;               // bump pointer
       if(tblptrl == 0)         //
       { tblptrh++;             //
         put232('.');           //
       }                        //
     } while(tblptrh);          // until rollover from 0xFFFF
     crlf();                    //
  /*                                                                *
   *  complete the reset (jmp (fffc)), run 6502 code                *
   *                                                                */
     loader(0x6C);              // R DF00 6C, JMP ($FFFC)
     loader(0xFC);              // R DF01 FC
     loader(0xFF);              // R DF02 FF
     loader(0xFF);              // R DF02 FF (extra cycle)
     loader(0xFF);              // R FFFC ll
     loader(0xFF);              // R FFFD hh
Attachments
Pocket 65C02 SBC20 (small).png
User avatar
cbscpe
Posts: 491
Joined: 13 Oct 2013
Location: Switzerland
Contact:

Re: Another Bootstrap for a ROM less system

Post by cbscpe »

Hi Michael,

thanks for confirming that it works (as can be seen by your project). That's good to know that you already managed to put it into practice. In the meantime I thought about two extensions to my initial design. First I will add a 3-state buffer between the AVR and the data-bus, to avoid conflicts at the falling edge of PHI2 when the AVR is still driving the bus and the 65816 will emit the bank address (the goal is to use it with 65816 of course) and the second change will be that I will connect VP to one of the AVRs input so instead of counting the number of cycles after reset is de-asserted I just wait until VP is asserted (even the number of cycles after a reset is known and fixed) to start sending bytes.

Cheers

Peter
User avatar
Dr Jefyll
Posts: 3525
Joined: 11 Dec 2009
Location: Ontario, Canada
Contact:

Re: Another Bootstrap for a ROM less system

Post by Dr Jefyll »

Hi Peter. Just checking that I've got this right... :)
cbscpe wrote:
When IML is Low addresses $0000 to e.g. $BFFF will select the RAM for read and writes, addresses $C000..$C0FF decode to one of the IO select signals and for addresses $C100..$FFFF selects the RAM only for read accesses. When IML is High the RAM is only selected for write cycles, but not only for $0000..$BFFF but as well for $C100..$FFFF.
So, you have two memory address areas, one that's below the IO in page $C0 and one that's above. When IML is high (active), all writes by the 65xx go to RAM. (And I suppose all reads come from the AVR.) Then, after boot-up, IML will be low. Both the upper and lower RAM areas can be read by the 65xx. The lower area can also be written but writes to the upper area do nothing -- that area is protected. (Nice touch!)
cbscpe wrote:
I will add a 3-state buffer between the AVR and the data-bus, to avoid conflicts at the falling edge of PHI2
'816 does present a bit of a challenge, but IMO the buffer you mention can be avoided. It's to our advantage that the AVR pins that drive the data bus can be switched off (tri-stated or placed in input mode).

Instead of using a 3-state buffer to connect the AVR pins to the 65xx data bus, one alternative is to use eight resistors (about 5k ohms, say) instead. The resistors are smaller, cheaper and they require no control signals. They'll prevent conflicts (bus contention) from causing any harmful effects. (They will also cause delay as each byte from the AVR propagates onto the 65xx data bus. But probably your boot-up loop doesn't require extreme speed anyway.)

Another alternative involves connecting the AVR pins directly to the 65xx data bus. For each byte, the AVR outputs the data then tri-states the pins just before it sets PHI2 low -- and the delay between those two events ought to be kept short. Capacitance on the data bus will cause it to maintain its value for several microseconds at least (and probably hundreds or thousands of microseconds). This is assuming all MOS or CMOS inputs on the bus, and no significant DC leakage from other sources.

cheers,
Jeff
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html
User avatar
Michael
Posts: 633
Joined: 13 Feb 2013
Location: Michigan, USA

Re: Another Bootstrap for a ROM less system

Post by Michael »

Peter, a couple questions, please?

(1) Does your IML logic in the GAL provide a way to turn off the RAM when your AVR is pushing instructions and operands onto the data bus? This is the only thing I see missing in your description of boot-loader operation. You need to turn off RAM when you push the reset vector bytes and you need to turn off RAM during the 'read' clock cycles in your boot-loader loop.

(2) What's the purpose of the of /RES signal input on the GAL (forgive me, I'm not familiar with GALs)?

BTW, I agree with Jeff that you can probably do without a buffer IC.

Cheerful regards, Mike
User avatar
cbscpe
Posts: 491
Joined: 13 Oct 2013
Location: Switzerland
Contact:

Re: Another Bootstrap for a ROM less system

Post by cbscpe »

Jeff you got that right. However I will leave the tri-state buffer (74HCT541) because I plan to use the AVR as a PS/2 interface once he did the job of loading the ROM Image. Also I'm not convinced that even a fast AVR can cope with the times required by a W65C816, and the tricks you mention only work in theory and on a perchance base. I don't like that, even so I had sometimes circuits working by magic because of these effects and found out only later when analyzing them after they worked they only work by chance and not by design. As for your question Michael, here is what I first planned to do as a GAL

Code: Select all

GAL22V10 
AVRIMLV0


IML   A15   A14   A13   A12   A11   A10   A9    A8    A7    A6    GND
RW    PHI2 /IOA  /IOB  /IOC  /RAM  /BYTE /RD   /WR   /VP    nc    VCC

IOA		=  A15 *  A14 * /A13 * /A12 * /A11 * /A10 * /A9  * /A8  * /A7  * /A6 * /IML

IOB		=  A15 *  A14 * /A13 * /A12 * /A11 * /A10 * /A9  * /A8  * /A7  *  A6 * /IML
		+  A15 *  A14 * /A13 * /A12 * /A11 * /A10 * /A9  * /A8  *  A7  * /A6 * /IML

IOC		=  A15 *  A14 * /A13 * /A12 * /A11 * /A10 * /A9  * /A8  *  A7  *  A6 * /IML


RD		=  RW  *  PHI2

BYTE	=  RW  *  PHI2 * IML

WR		= /RW  *  PHI2

RAM		=  IML * /RW
		+ /IML * /A15
		+ /IML *  A15 * /A14
		+ /IML *  A15 *  A14 * /A13 *  /A12                      *  A8  *  RW
		+ /IML *  A15 *  A14 * /A13 *  /A12               *  A9         *  RW
		+ /IML *  A15 *  A14 * /A13 *  /A12        *  A10               *  RW      
		+ /IML *  A15 *  A14 * /A13 *  /A12 *  A11                      *  RW
		+ /IML *  A15 *  A14        *   A12                             *  RW
		+ /IML *  A15 *  A14 *  A13                                     *  RW

VP		=  A15 *  A14 *  A13 *  A12 *  A11 *  A10 *  A9  *  A8  *  A7  *  A6

DESCRIPTION

The final details are not done yet, but that's what I'm thinking about. So when IML is active writes and only writes always go to the RAM and reads always go to the byte buffer (/BYTE will connect to /OE of the 74HCT541). IO selects will never be asserted during IML. And you are completely right Michael, in that design /RES does not have to go to the GAL. It's not used in the decoder. Another PIN saved, always handy when starting a design. Thanks for the input.

Again as for the buffer IC, in the AVR code I initially posted I was making use of disabling the outputs (clearing bits in DDRC and DDRD), but the bad thing is that the ATMega328P has no 8-bit port available, so you need to use at least two instructions to disable the PINs on two ports. You may say the ATMega328P has full port B and D but unfortunately PB6&7 are the crystal pins, and I want to use a crystal, and PD0&1 are the USART which I need to be able to download a new ROM image to the flash. I Agree that when using a larger ATMega chip then turning PHI2 off and disabling the outputs in the next cycle using a "out PORTA, zero" should work well. But anyhow, now I will polish the design and code and then build the prototype on a breadboard.

When you think that the equation of IOB is strange, this is on purpose, the 65xx peripherals all have two select pins, one active low that will go to IOB and one active high which will be connected to one of the address lines A4,5,6,7

cheers
Peter
User avatar
Dr Jefyll
Posts: 3525
Joined: 11 Dec 2009
Location: Ontario, Canada
Contact:

Re: Another Bootstrap for a ROM less system

Post by Dr Jefyll »

Quote:
I had sometimes circuits working by magic because of these effects and found out only later when analyzing them after they worked they only work by chance and not by design.
Yes, I've had that happen, too, and I don't like it. It's alarming -- and embarrassing! :D -- that an error escaped my attention. Then the system was able to function anyway thanks to bus capacitance. But, because it wasn't part of the plan, I never calculated the bus-capacitance effect to ensure it would be adequate. That's not a mistake that'll happen when you use the effect deliberately. It can be calculated and it can be adequate -- an engineering option like any other.

The way I would approach this is as a matter of time, resistance and capacitance. The capacitance per bus line depends on the devices connected, and datasheets reveal this figure on a per-chip basis -- you just total 'em up. For the R part of the equation you need to choose a resistance that represents the worst leakage you believe you'll encounter, such as from moisture or contamination on the PCB. [Edit: input leakage on the ICs needs to be considered too.] Then, considering the applicable logic thresholds, you can calculate how long a value can sit on the bus, not being driven by anything, before leakage causes it to become indeterminate.

If 1 Megohm is deemed to be tolerable as the acceptable leakage resistance (to ground or supply), then based on a rough calculation I expect the data bus on your project will hold a value somewhere around 5 microseconds. The AVR can probably switch over in a fraction of that time, so tolerating 1 Megohm is easy -- and that's the worst-case scenario we chose; if there's less leakage the margin increases further. I admit that relying on an arbitrarily-chosen leakage tolerance may seem odd, but I believe it is part of a sound procedure. Comments are welcome, of course. (Oops -- hope you don't mind, Peter. If necessary a new thread can be created.)

-- Jeff
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html
User avatar
cbscpe
Posts: 491
Joined: 13 Oct 2013
Location: Switzerland
Contact:

Re: Another Bootstrap for a ROM less system

Post by cbscpe »

Ok, I got your point. Now then: the AVR will be clocked with 25MHz (or perhaps even with 30MHz I'll see, how fast the ATMega328P will do at 5.5V), the sequence of "out DDRy, zero" and "out PINx, PHI2", will result in a delay of 40ns respectively 33ns between the outputs going tri-state and PHI2 going low (in my instructions example PHI2 will contain the bit mask that corresponds to the PIN used on Port x for PHI2, modern AVR toggle the output when writing a 1 to the PIN register, this is the fastest 1-cycle trick to change a single bit on a port, and zero of course is the name of the register that has my constant 0x00). So when disabling the output first and then driving PHI2 low we need to have enough capacitance to drive the data-pins via the RC construct. R should be not to low to avoid excess power consumption during operation, I would say 10kohm should do it and when using all CMOS ports this will drive the pins easily to full VCC or GND. So for an acceptable in/decrease of 1V and a delay of 40ns I would need approx 22pF connected to the AVR pins. So your Idea seems feasible and the capacitance load for the AVR pins is not beyond the specs.

With this I have saved a 74HCT541, but on the other hand I need 8 resistors and 8 capacitors. Not a good trade-in for a digital circuit I would say.

But, I have another idea, why not use a D-Flip-Flop (74AC74) and delay the change of PHI2 by one AVR Clock-Cycle? So I first change PHI2 and then disable the output. The ATMega328P can be configured to have a full-swing XCO output which can be used as clock input to the FF and the PHI2 output of the AVR will connect to the D-Input of the FF. Then the falling edge and the disabling of the AVR outputs, as seen by the W65C816, happens at the same time.
User avatar
Dr Jefyll
Posts: 3525
Joined: 11 Dec 2009
Location: Ontario, Canada
Contact:

Re: Another Bootstrap for a ROM less system

Post by Dr Jefyll »

cbscpe wrote:
the sequence of "out DDRy, zero" and "out PINx, PHI2", will result in a delay of 40ns respectively 33ns between the outputs going tri-state and PHI2 going low [...]
OK, that's excellent.
Quote:
With this I have saved a 74HCT541, but on the other hand I need 8 resistors and 8 capacitors
Sorry for the confusion. At first I proposed two solutions, one of which involved adding resistors. In the subsequent post I abandoned that because it's better with no resistors. Neither solution involves adding capacitors, because there's enough capacitance already. I haven't checked the figures, but the CPU, the AVR and the RAM contribute roughly 5 pF each, so we have about 15 pF working in our favor. With this solution the AVR pins attach directly to the 65xx data bus.

At the instant of the "out DDRy, zero" we know all the 8 data lines will be valid -- either high or low. IOW on each line, the 15 pF will be either charged to Vcc or discharged to 0. After the "out DDRy, zero," each line will tend to REMAIN charged or discharged. They remain until something eventually disturbs them, and the "something" is the leakage resistance i mentioned. Minimal leakage means minimal disturbance.

In the theoretical case of zero leakage a capacitor will remain charged for all of eternity. But we only need it to remain for 40 ns. :)
Quote:
I have another idea, why not use a D-Flip-Flop (74AC74) and delay the change of PHI2 by one AVR Clock-Cycle? [...] Then the falling edge and the disabling of the AVR outputs, as seen by the W65C816, happens at the same time.
It's a clever idea, and it does reducing the duration of the "floating" period from 40 ns to approximately zero. But is that a benefit? What it translates to is better ability to tolerate leakage due to contamination on the board -- and that's already adequately satisfied, I would say. The situation would be different if you had some TTL loads on the bus, because they don't have super-high input impedance like that on MOS and CMOS devices.

BTW you need to check that the AVR really does present a high impedance when its outputs are switched off. IOW make sure they haven't "helpfully" included a pullup resistor internally on each port pin. We don't want that, although for some applications it's an advantage.
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html
User avatar
cbscpe
Posts: 491
Joined: 13 Oct 2013
Location: Switzerland
Contact:

Re: Another Bootstrap for a ROM less system

Post by cbscpe »

Hi Jeff,

ok now I get a clearer picture of what you meant. As for the AVR pins, when set as input (DDRD.n=0) they have a very high impedance. I already have started the prototype
Almost finished breadboard layout
Almost finished breadboard layout
What is missing are the various pull-ups (IRQ, RES, NMI ...) and a final check and then I will power it up.
User avatar
cbscpe
Posts: 491
Joined: 13 Oct 2013
Location: Switzerland
Contact:

Re: Another Bootstrap for a ROM less system

Post by cbscpe »

Hi,

here is an update to the project. First I have implemented a first version of the hardware. Here es the schematic. There is one difference, I use a W65C816 and not a R65C02 as in the schematic, the problem is I did not update my library to have a W65C816, but I think it is obvious what is different.
bootstrap-design.pdf
Currently implemented HW on breadboard
(27.36 KiB) Downloaded 118 times
Outputs controlled by the AVR are PHI2, RES and IML. The AVR also can read the status of VPA, VDA, VPB and RW. I have written a small interactive test program for the AVR so I can step through 6502 cycles. The test program is a "rewrite" of the logic of the Apple II monitor, so the syntax is the same. The following commands for the 6502 cycleing are implemented

Code: Select all

1R   Assert Reset (Pull it Low)
0R   De-assert Reset (Pull it high, respectively turn the output pin to input and let the pull-up resistor do its work
P     Toggle PHI2
I      Toggle IML
nnW Execute a cycle where nn is the byte to put onto the databus
S      Show status of VPA, VDA, VPB and RW
I have attached the source code
AVRIML.asm
AVR Source Code
(16.68 KiB) Downloaded 102 times
So a typical sequence to init the 6502 would use the following commands, I have shown here a session with each step and instruction entered as a line

Code: Select all

*1rwwwww0r

*wswswswswsws
VPA:0, VDA:0,VPB:1,R/W:1
VPA:1, VDA:1,VPB:1,R/W:1
VPA:0, VDA:0,VPB:1,R/W:1
VPA:0, VDA:1,VPB:1,R/W:1
VPA:0, VDA:1,VPB:1,R/W:1
VPA:0, VDA:1,VPB:1,R/W:1

*1rwwwww0r

*wswswswswswsws
VPA:0, VDA:0,VPB:1,R/W:0
VPA:1, VDA:1,VPB:1,R/W:1
VPA:0, VDA:0,VPB:1,R/W:1
VPA:0, VDA:1,VPB:1,R/W:1
VPA:0, VDA:1,VPB:1,R/W:1
VPA:0, VDA:1,VPB:1,R/W:1
VPA:0, VDA:1,VPB:0,R/W:1

*0ws3ws
VPA:0, VDA:1,VPB:0,R/W:1
VPA:1, VDA:1,VPB:1,R/W:1

*a9ws00ws
VPA:1, VDA:0,VPB:1,R/W:1
VPA:1, VDA:1,VPB:1,R/W:1

*8dwsaawsaaws00ws
VPA:1, VDA:0,VPB:1,R/W:1
VPA:1, VDA:0,VPB:1,R/W:1
VPA:0, VDA:1,VPB:1,R/W:0
VPA:1, VDA:1,VPB:1,R/W:1

*4cws00ws03ws
VPA:1, VDA:0,VPB:1,R/W:1
VPA:1, VDA:0,VPB:1,R/W:1
VPA:1, VDA:1,VPB:1,R/W:1

*
Note that the S(tatus) command displays the status of the signals after the cycle as endend. That is PHI2 is normally LOW and W first places the byte to the buffer and then creates a short positive pulse on PHI2 for approx 300ns.

As you can see VPB is pulled low also for fetching the reset vector. So that means after a reset I can just emit PHI2 cycles until VPB is LOW and then I know the 6502 wants to read the reset vector and then start the Initial Machine Load as was the reason for the project.

Cheers

Peter
User avatar
Michael
Posts: 633
Joined: 13 Feb 2013
Location: Michigan, USA

Re: Another Bootstrap for a ROM less system

Post by Michael »

Hi Peter,

Why is R/W low during the first cycle after the second reset?
User avatar
cbscpe
Posts: 491
Joined: 13 Oct 2013
Location: Switzerland
Contact:

Re: Another Bootstrap for a ROM less system

Post by cbscpe »

Good question, I don't know and I was also surprised. It happens from time to time. It appaers also that it is 6 cycles before the 65816 reads the vector and not 5 as I thought, although I think I've seen also a discussion where they count 6. Perhaps it is because I deassert reset when PHI2 is low. It could also be a flaw in my software of the AVR. I will investigate that and also another problem I have observed sporadically. But first I will to add code that loads a simple HELLO WORLD program, I also have a ACIA on my breadboard.
User avatar
BigEd
Posts: 11463
Joined: 11 Dec 2008
Location: England
Contact:

Re: Another Bootstrap for a ROM less system

Post by BigEd »

If you see something which sometimes happens and sometimes doesn't, I think probably you are not holding reset for long enough.
Post Reply