6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Tue May 14, 2024 2:51 am

All times are UTC




Post new topic Reply to topic  [ 36 posts ]  Go to page Previous  1, 2, 3  Next
Author Message
PostPosted: Tue Oct 17, 2023 5:06 am 
Offline

Joined: Wed Aug 21, 2019 6:10 pm
Posts: 217
Proxy wrote:
... but even when you do choose the SPI EEROM, you could still hook it's pins to a VIA or similar to allow the CPU to access the ROM and program itself. ...


Yes, when you have a two stage bootloader approach, you get host reprogramming of the serial FlashROM for free. That can be an appealing option ... for instance, it is appealing for a Forth system, as extending the Forth compiler into the program you want then saving the image is a classical approach to Forth programming.

________________________
gfoot wrote:
... Jeff posted an example circuit to drive such EEPROMs here, which I think he's tested: viewtopic.php?p=76975#p76975 He had to use a delay circuit to send the right signal to the EEPROMs - I think some other brands of EEPROM wouldn't require that though. ...


IIUC, Jeff has a really parsimonious way to generate the data input ... generate a single downward pulse from resisters and a capacitor that is 6 clocks long, so the command byte is $03 and the address is $FFFFFF. Then since the ROM is being read, the following data values fed to the SI pin don't matter, so they can stay $FF.

Now, if in this context the data is read into daisychained A0-A5 address and D0-D7 data shift registers, the contents of the serial ROM (plus /BE to the CPU and pull up resisters on A6-A15) takes care of address generation. If the serial shift registers are cleared at the beginning of each pair of bytes, a high bit in the address byte data can mark the end of a pair of bytes which can directly trigger the data write state machine.

And the SO pin of the Flash ROM is high impedance while the command and address are being fed into the Serial ROM. So if there is a pulldown resister to ground on the Serial ROM SO line, the ADDR/DATA shift registers will be fed $0000 until SO starts to be driven by data. That means there will be no frame marker, and the write cycle will not be triggered, so the data write USR's can just run free on the serial clock tied to the serial ROM.

The same start pulse that starts the counter can be tied to the USR /clear pins, so they will have $0000 at the outset, and the Address USR Q7 output will simply stay low until a complete valid address and data have been loaded into the shift registers. So there is no need to count through the 32 cycles it takes to finish loading the command and address and start reading data.

I'm not a hardware hand, so I'd be nervous doing the write generation Jeff's way. I think I would count them, even if it adds another glue logic IC in the form of a presettable countdown counter, plus a gate from a quad OR. Input the serial clock and the Q4 of the presettable countdown timer into the OR gate and use that as the countdown clock. /PRELOAD loads a value less than $8, so it brings Q4 low, passing the clock through to the counter, until the counter wraps around to $F, bringing Q4 high, halting the timer until the next /PRELOAD. Q4 connects to the serial ROM SI as the command and address data..

Finally, for sanity, the byte at effective address $FFFFFF, the top of the final page in the final block, is written as $00, so the first marked address byte is at $000000, and the final block never need be re-written when loading a new first stage bootload routine. The payload for the full 64 bytes to $FFC0-$FFFF is 130 bytes ... an address/framing byte for each data byte, and a final $C000 to carry the end of payload bit6 high. And since each data byte travels with its own address, there is no need for padding in the payload.


Top
 Profile  
Reply with quote  
PostPosted: Thu Oct 19, 2023 12:24 am 
Offline

Joined: Wed Aug 21, 2019 6:10 pm
Posts: 217
Looking at a loadable 4bit binary counter again, it seems like a 74193 is most of the state machine needed to write a byte loaded into a part of USR's (that is, 74299). If $B is loaded into the counter, then QA, which is driving /RAM_WR, and QB, which is driving /RAM_CS as well as /AL_USR_OE1 and /DATA_USR_OE1, both start high. On the next clock pulse, they both go low. On the next clock pulse, the /RAM_WR goes high, completing the write, with /AL_USR_OE1 still low for the data hold when the ram is written. The next clock cycle raises /RAM_CS and the /AL_USR_OE1, and the next clock cycle brings the counter to $FF, so the /COUNT_OC overflow carry is pulsed. That pulse is used to clear the USR's, which then clears the framing bit in COUNT2_Q7, ending the state.

So the counter clock runs while the framing bit is high, which can be done by an AND of the framing bit with the system clock. So that adds a quad (positive) 2-input AND like a 7408 to the parts list.

COUNT2_UP := AND(AL_USR_Q7,PHI2)

IIUC, the /COUNT2_LOAD acts as a transparent latch does, so the framing bit can be used to drive the load ... it will be low the entire time that the counter is not running, but the load value is static.

COUNT2_A := COUNT2_C := COUNT2_D := VCC
COUNT2_B := GND

/COUNT2_LOAD := AL_USR_Q7

The carry overflow has to reset the USR's to clear the framing bit and bring an end to the write data state. And the USR's also have to be cleared when /Reset is pulsed. From the 299 datasheet, that is an active low master reset:

/AL_USR_MR := /DATA_USR_MR := AND(/COUNT2_CO,/RESET_INPUT)

An /S /R flip flop "SR1" can provide the bus release needed for the 1st stage bootloader by driving 6502_BE low, with the bus returned when bit 6 if the address/framing byte is high. A dual /S /R flip flop is handy because the other can be used by the Flash Read Command state machine (and if a dual flip flop of the correct family is not in stock, it can always be replaced by a 7400 wired correctly). Two gates of a hex , plus the two remaining gates of the AND can be used to filter for the Flash SCLK, so it only runs when in the BOOT period, which is when the /SR2_Q is high, and only runs when the FRAME bit is low:

/SR2_R := /RESET_INPUT
/SR2_S := NOT(/AL_USR_IO6)

/FRAME := NOT(AL_USR_Q7)

BOOT_SCLK := AND(PHI2,/SR2_Q)
FLASH_SCLK := AND(BOOT_SCLK,/FRAME)

Using a /S /R flip flop to drive the Flash SI to write the Read command and address means that the counter can be left to run freely, as additional /BO pulses will be ignored. A countdown from 5 started when the FLASH_SCLK starts running will generate the /BO pulse after the 6th SCLK pulse:

/COUNT1_LOAD := /RESET_INPUT
COUNT1_DOWN := FLASH_SCLK
COUNT1_A := COUNT1_C := VCC
COUNT1_B := COUNT1_D := GND
/SR1_R := /RESET_INPUT
/SR1_S := /COUNT1_BO
SR1_Q =: FLASH_SI

So:
  • The (debounced) /RESET_INPUT clears the USR's, which brings the FRAME bit low. It also resets the /BE master flip flop and the FLASH_SI flip flop, which places 0 on the FLASH_SI pin and starts the FLASH_SCLK running.
  • After six FLASH_SCLK pulses, COUNT1 pulses its /borrow pin, which sets the FLASH_SI flipflop high, generating the $03h READ command and the $FFFFFF data address.
  • While the read command and address has been written to the FLASH, FLASH_SO has been pulled down by ground through a resister, so AL_USR_Q7 remains low, so the FLASH_SCLK and USR's keep running. This continues through the first byte of data of $00 at the (likely mirrored) $FFFFFF address, which then wraps around to $000000, where pairs of frame/address and data bytes, %10aaaaaa %dddddddd are located.
  • After sixteen cycles of loading serial data, AL_USR_Q7 goes high when the frame bit is shifted in. This pauses the FLASH_SCLK and starts the COUNT2 count-up clock. The loaded value drives the write cycle, with USR outputs enable, on the COUNT_QA and COUNT_QB pins. When the counter reaches $F, the /CO pulse clears the USR's, dropping AL_USR_Q7, halting the COUNT clock and starting the FLASH_SCLK again
  • This continues until the final address frame byte of %11xxxxxx %xxxxxxxx, so reasonably $FF, which /Sets the master flipflop, drives BE up, and halts the FLASH_SCLK until the next /RESET_INPUT.

Or at least, something along those lines. For instance, if gate latencies means that the timing of the /CO pulse for the Read command is early or late, that can be fixed by shifting the COUNT1_A-D inputs until it hits at the right cycle.

So:
  • One FlashROM
  • Two 74x299 tri-state Universal Shift Registers
  • Two 74x193 counters
  • A 74x279 dual /S /R flip flop, or 74x00 quad NAND
  • A 74x08 quad, 2-input AND
  • One hex inverter or a 74x00 and heaps of pullup/pulldown resisters

If 5v, the USR's need to accept TTL levels for a 3.3V FlashROM SO signal, and a voltage bridge for the FlashROM SCLK, SI and /SELECT.

A CPLD would of course be more compact. This would be at least a couple of breadboards if breadboarding -- if done to replace the ROM in the single broadboard 6507/RIOT SBC, it would make it a three or four breadboard SBC -- but if done with SMB, maybe it's compact enough.


Last edited by BruceRMcF on Thu Oct 19, 2023 12:50 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  
PostPosted: Thu Oct 19, 2023 3:13 am 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3354
Location: Ontario, Canada
BruceRMcF wrote:
gfoot wrote:
... Jeff posted an example circuit to drive such EEPROMs here, which I think he's tested: viewtopic.php?p=76975#p76975 He had to use a delay circuit to send the right signal to the EEPROMs - I think some other brands of EEPROM wouldn't require that though. ...

IIUC, Jeff has a really parsimonious way to generate the data input ... generate a single downward pulse from resisters and a capacitor that is 6 clocks long, so the command byte is $03 and the address is $FFFFFF. Then since the ROM is being read, the following data values fed to the SI pin don't matter, so they can stay $FF.

Yup. As you say, Bruce, the following data values fed to the SI pin don't matter, which makes our job easier -- we can cheerfully ignore them. :) But the resistors and capacitor seen in the diagram I posted aren't responsible for generating the bits of the opcode that's sent serially to the EEPROM. The job of the RC is to repetitively restart the entire sequence in order to simulate the never-ending output of a video-sync generator IC.

BruceRMcF wrote:
I think I would count them, even if it adds another glue logic IC
Yup again. And they are "counted," by a 14-pin IC that's actually a shift register. Here's a more minimal version of that diagram, with the repetitive-restart facility removed. ETA: the R and C that remain simply provide a delay after power-up, following which the bits of the opcode begin getting counted out.

-- Jeff


Attachments:
simple sequencer.png
simple sequencer.png [ 20.63 KiB | Viewed 40130 times ]

_________________
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html
Top
 Profile  
Reply with quote  
PostPosted: Thu Oct 19, 2023 5:31 am 
Offline

Joined: Wed Aug 21, 2019 6:10 pm
Posts: 217
Dr Jefyll wrote:
... Yup again. And they are "counted," by a 14-pin IC that's actually a shift register. Here's a more minimal version of that diagram, with the repetitive-restart facility removed. ETA: the R and C that remain simply provide a delay after power-up, following which the bits of the opcode begin getting counted out.


Thanks heaps ... like I said, I'm not really a hardware hand.

So a 74x165 could be loaded with $03 and have PSR_DS tied to ground, and we get the command byte wired in, followed by $000000 as the address

Above, the complementary output of the "master" /S /R flip flop, /SR2_Q, would work for the 74x165 asynchronous parallel load..

Using AND filtering on the system clock means it idles low, so this is a Mode 3 SCLK. So it might be more stable to feed.the PSR with the inverse of the flash SCLK, so the PSR shifts up in the clock phase after FLASH_SI has read the bit.

PSR_CP := NOT(FLASH_SCLK)
/PSR_CE := GND
PSR_Q7 =: FLASH_SI
/PSR_PL := /SR2_Q
PSR_DS := GND (pin 10)
PSR_D0 := PSR_D1 := VCC (pins 11, 12)
PSR_D2 := PSR_D3 := GND (pins 13, 14)
PSR_D4 := PSR_D5 :=.PSR_D6 := PSR_D7 := GND (pins 3-6)


Top
 Profile  
Reply with quote  
PostPosted: Thu Oct 26, 2023 5:43 am 
Offline

Joined: Mon Jan 19, 2004 12:49 pm
Posts: 684
Location: Potsdam, DE
Grrr... race hazards. I have a lovely little design for automatically generating all the signals required to extract data from a serial eeprom, except that it doesn't work if the reset rising edge is too close to the clock signal. Damn.

Rethinking is in order...

Neil


Top
 Profile  
Reply with quote  
PostPosted: Thu Oct 26, 2023 11:27 am 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
Synchronise the reset signal with a clocked flipflop?


Top
 Profile  
Reply with quote  
PostPosted: Thu Oct 26, 2023 7:54 pm 
Offline

Joined: Mon Jan 19, 2004 12:49 pm
Posts: 684
Location: Potsdam, DE
That's what I'm doing, but I think I need to add an extra stage. A high is clocked through a D-type once the async clear is released; sometimes it doesn't come out on the right clock phase.

I'll keep at it; there may be a better way to sort this.

Neil


Top
 Profile  
Reply with quote  
PostPosted: Thu Oct 26, 2023 9:15 pm 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
Wouldn't it be simpler to just connect the reset signal to the D input, and then make sure you have an appropriate polarity of clock to the flipflop?


Top
 Profile  
Reply with quote  
PostPosted: Fri Oct 27, 2023 7:01 am 
Offline

Joined: Mon Jan 19, 2004 12:49 pm
Posts: 684
Location: Potsdam, DE
I need an output which is triggered by a power-on reset (hence asynchronous) which changes state and then allows a clock signal rising edge after a delay:
Attachment:
good_reset.png
good_reset.png [ 15.71 KiB | Viewed 39875 times ]

But occasionally I get this:
Attachment:
bad_reset.png
bad_reset.png [ 14.72 KiB | Viewed 39875 times ]

Which is one clock late... to further complicate things I need to be able to reset the output controlled by a signal generated later.

I'm using a d-type as an SR and moving the output into another d-type which is clocked; I think what is happening is that if the clock arrives at just the wrong time in the second d-type it can pick up the wrong edge.

The critical signals at this point are C D and nS.

Neil


Top
 Profile  
Reply with quote  
PostPosted: Fri Oct 27, 2023 3:38 pm 
Offline

Joined: Wed Aug 21, 2019 6:10 pm
Posts: 217
I'm wondering whether you can filter the /Reset signal so that the drop is asynchronous, but the release is synchronous with the falling edge of the clock?

Off the top of my head, with a 7400, maybe it's something like:

NAND_1A := PHI2
NAND_1B := VCC
NAND_1Y =: /PHI2

NAND_4A := /PWR_RESET
NAND_4B := /PHI2
NAND_4Y =: NAND_3A ; = /SET

Now the /SET line is pulled low every time PHI2 goes low, but only when /PWR_RESET is high.

NAND_2A := NAND_3Y ; = Q
NAND_2B := /PWR_RESET ; = /RESET
NAND_2Y =: NAND_3B ; = /Q

NAND_3A := NAND_4Y ; = /SET
NAND_3B := NAND_2Y ; =/Q
NAND_3Y =: NAND_2A ; = Q

This is off the top of my head during office hours, so maybe thinking it through tonight will tell me I missed something obvious, but if that logic is right, Q (NAND_3Y) is supposed to be the "filtered" /RESET signal that always rises at the start of Phase1 of the clock (after gate delays), so there's always a (phase - gate delays) gap between the rising of /RESET and the start of the second phase of the clock cycle. Note that Q is four gate delays deep, so care is needed regarding the gate delay is on the family 74x00 quad nand used. Also note that is a /S /R flip flop, not a JK one, so the Q output may be unstable for one gate delay after /PWR_RESET drops ... if that gives occasional transients which give problems, experimenting with a pullup or pulldown resister on Q might be needed to see what avoids the transients.

Also, I don't know how you debounce /PWR_RESET, but if it is debounced with a couple of Schottky inverters in series, perhaps also might reduce problems with transients.


Top
 Profile  
Reply with quote  
PostPosted: Fri Oct 27, 2023 8:17 pm 
Offline

Joined: Mon Jan 19, 2004 12:49 pm
Posts: 684
Location: Potsdam, DE
At the moment it's just on Logisim, so it ought to be a proper unbouncy signal. In the real world, CR most likely. Or maybe a power supply monitor chip.


Top
 Profile  
Reply with quote  
PostPosted: Sat Oct 28, 2023 8:34 am 
Offline

Joined: Mon Jan 19, 2004 12:49 pm
Posts: 684
Location: Potsdam, DE
Aha, we're getting nearer. An extra sample stage in the state machine clocked on the antiphase gives me a consistent half-clock delay at both ends of the cycle which is just what I need; it doesn't matter then where the async reset rises (low-going reset pulse at this stage; this will change later).

There's a minor issue that a reset during the process running locks it up unrecoverably, but I see a way to avoid that...

Attachment:
working state machine.png
working state machine.png [ 31.35 KiB | Viewed 39748 times ]


Neil


Top
 Profile  
Reply with quote  
PostPosted: Sat Oct 28, 2023 12:48 pm 
Offline

Joined: Mon Jan 19, 2004 12:49 pm
Posts: 684
Location: Potsdam, DE
Sorted it, I think. This logic generates the necessary timing and control signals to read a standard up-to 64kB flash/eeprom into memory, including the address generation and an (unshown) hc164-type serial-to-parallel converter.

Both the counters are negative edge triggered (e.g. 393); the top one generates the 0x03 'read' signal followed by three 0x00 (two address bytes, one dummy) and then repeats. After the flash is reading, it ignores further commands so no worries there. It also generates a RnW pulse on the high part of the eighth clock pulse. Its last job is to enable the address counter via the AND gate and the rightmost two flip-flops. If we assume eight clocks to the tick, that first occurs on the fourth tick.

The other counter generates the addresses, having been held in reset until the fourth tick.

A high-going reset pulse resets most of the flip-flops (let's call them 1-5 from the left). At the end of the reset pulse, the next clock latches Q(2) high. That resets Q(3) immediately, and half a clock later nS is clocked low. Q(4) is already low from the reset, and this is confirmed by the rising edge of Q(2) - perhaps only one of those is needed, but I don't think it hurts.

On the fourth tick, Q4 is set which enables both the address counter and the clock signal to the flash. Thereafter, every eight clocks, the address counter is incremented and in the half clock before it does, it generates the RnW pulse. When a suitable power-of-two address is reached (I got bored waiting so this one only goes up to two :mrgreen: ) then the high-going next bit triggers a reset to flip-flop(5) and simultaneously sets Q(1). Half a clock later, the nS line goes high and normality is restored.

Attachment:
autospi.png
autospi.png [ 155.44 KiB | Viewed 39722 times ]


Next step is to see how few chips I can do this with in discrete logic. The intent is to download into a 65c02 memory space meaning I can use the nS signal to hold the BS and RESET lines low during the transfer. Note that the d-types here differ from a 74hc74 by having active high set and reset inputs; a certain amount of inversion will be required.

I intend to connect to the busses via 47k resistors which should be plenty low enough to provide the necessary drive current for the ram but high enough to provide isolation against the address counter which will remain at 0x0000.

Neil


Top
 Profile  
Reply with quote  
PostPosted: Sat Oct 28, 2023 3:46 pm 
Offline

Joined: Wed Aug 21, 2019 6:10 pm
Posts: 217
Regarding using a similar approach for a two stage bootloader, if 64 bytes is enough for a first stage bootloader from $FFC0 to $FFFF, then a toggle flip flop plus a pair of 4bit binary counters might count serial bits on the first three bits of the first counter, generating a write pulse on the clock phase following all three high, with the remaining counter outputs and the toggle on A0-A5, through resisters, and A6-A15 pulled high through pullup resisters.


Top
 Profile  
Reply with quote  
PostPosted: Sat Oct 28, 2023 6:33 pm 
Offline

Joined: Mon Jan 19, 2004 12:49 pm
Posts: 684
Location: Potsdam, DE
I didn't do it that way - I keep the address counter separate from the read generator so that there isn't a permanent offset of three bytes. I want a one-one relationship between the contents of the flash and the eventual contents of the ram.

But yes, you could do it that way as long as your flash loader is aware of that offset.

I'm aiming for a 16k load (0xc000 to 0xfff) using a 32k eeprom.

Neil


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 36 posts ]  Go to page Previous  1, 2, 3  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 8 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: