6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sun Nov 24, 2024 12:38 pm

All times are UTC




Post new topic Reply to topic  [ 52 posts ]  Go to page 1, 2, 3, 4  Next
Author Message
 Post subject: Use GAL as a small eprom
PostPosted: Sat Jul 25, 2015 2:16 pm 
Offline

Joined: Mon Jul 20, 2015 6:34 pm
Posts: 62
I think it would be possible to use them as a small eprom. What would be the size of eprom we could get programming say a GAL22V10D?


Top
 Profile  
Reply with quote  
PostPosted: Sat Jul 25, 2015 2:50 pm 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3367
Location: Ontario, Canada
i_r_on wrote:
What would be the size of eprom we could get programming say a GAL22V10D?
It depends on the data that'll be stored. Worst case is when the data tends toward random, and only a handful of bytes can be stored. Best case is when the data has redundancy -- a pattern that can be described by a simple equation. Then the simulated EPROM capacity multiplies several-fold. Can you post a GAL22V10D datasheet for us?

_________________
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: Sat Jul 25, 2015 3:14 pm 
Offline

Joined: Mon Jul 20, 2015 6:34 pm
Posts: 62
That's what I expected actually.

Here is one,
http://www.latticesemi.com/~/media/Latt ... aSheet.PDF

The idea came from bootloading 6502 actually. What I want to store is around 43 bytes of 6502 code. It would be requiring 6 inputs and needs only 8 outputs. We can maybe cheat with remaining inputs and outputs using external circuitry. And how about using 2 instead of 1? Or is there out there a much capable one from Atmel's inventory?


Top
 Profile  
Reply with quote  
PostPosted: Sat Jul 25, 2015 4:16 pm 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3367
Location: Ontario, Canada
i_r_on wrote:
What I want to store is around 43 bytes of 6502 code. It would be requiring 6 inputs and needs only 8 outputs.
One approach is to treat each of the 8 outputs driving the 65xx bus (d7 - d0) as its own combinatorial equation. The datasheet says,

    "In combinatorial mode the pin associated with an individual OLMC is driven by the output of the sum term gate. Logic polarity of the output signal at the pin may be selected by specifying that the output buffer drive either true (active high) or inverted (active low)."

So, taking d0 for an example, and considering the code you intend to store, you assign a product term for every address in which d0 must equal one. And you're allowed about ten product terms -- these are the inputs to the sum term gate.

Assuming a 50:50 distribution of ones and zeroes, a 20-byte EPROM can be simulated. That is, ten addresses trigger a product term and thus the sum term gate, sending d0 high. The other ten addresses produce no response (defaulting to zero on d0).

It's to your advantage if the distribution of ones and zeroes deviates from 50:50. For example if you wanted to raise the capacity to 64 address locations, and your code is such that only ten locations contain a one, it will fit (because ten is how many terms we can afford). If the distribution bias is in the other direction, and only ten locations contain a zero, again it will fit. As noted, Logic polarity of the output signal can be inverted, changing the default to one.

Other approaches could offer other opportunities, for example by exploiting relations between the d7 - d0 bits rather than treating each one individually.

cheers,
Jeff

_________________
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: Sat Jul 25, 2015 4:40 pm 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3367
Location: Ontario, Canada
For interest's sake, here is a topic mentioning some diode-matrix ROMs, which embody the same logic explained above.

Also, FWIW here's a datasheet for a 70's-vintage 32-byte PROM which nowadays is still available here and there. They're power-hungry but the small package outline (16-pin DIP) can be an advantage. (IIRC Jameco carries the open-collector version, whose part number ends in 188 rather than 288.) Other numbering schemes exist; for example 82S23 and 82S123 (the formed being the OC version).


Attachments:
74S288.pdf [111.53 KiB]
Downloaded 192 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: Sat Jul 25, 2015 4:56 pm 
Offline

Joined: Mon Jul 20, 2015 6:34 pm
Posts: 62
Dr Jefyll wrote:
It's to your advantage if the distribution of ones and zeroes deviates from 50:50. For example if you wanted to raise the capacity to 64 address locations, and your code is such that only ten locations contain a one, it will fit (because ten is how many terms we can afford). If the distribution bias is in the other direction, and only ten locations contain a zero, again it will fit. As noted, Logic polarity of the output signal can be inverted, changing the default to one.

Other approaches could offer other opportunities, for example by exploiting relations between the d7 - d0 bits rather than treating each one individually.

cheers,
Jeff


Thanks for explaining,

Not a good distribution for my data I guess, shrinked the code down to 38 bytes... If it was a little bit less like around 32 bytes. It might be possible to deviate the code to get the right distribution I guess.

Code:
A9 1010 1001
00 0000 0000
A8 1010 1000
A2 1010 1010
08 0000 1000
58 1001 1000
B8 1011 1000
50 0101 0000
FE 1111 1110
4C 0100 1100
00 0000 0000
00 0000 0000
78 0111 1000
18 0001 1000
90 1001 0000
02 0000 0010
78 0111 0000
38 0011 1000
2A 0010 1010
CA 1100 1010
D0 1101 0000
08 0000 1000
A2 1010 0010
08 0000 1000
99 1001 1001
00 0000 0000
00 0000 0000
A9 1010 1001
00 0000 0000
C8 1100 1000
58 0101 1000
40 0100 0000
E6 1110 0110
FF 1111 1111
DA 1101 1010
FF 1111 1111
EA 1110 1010
FF 1111 1111

D7 : 1:19,0:19 - Not ok
D6 : 1:16,0:22 - Not ok
D5 : 1:16,0:22 - Not ok
D4 : 1:16,0:22 - Not ok
D3 : 1:24,0:12 - Not ok
D2 : 1:6, 0:32 - Ok
D1 : 1:12,0:26 - Not ok
D0 : 1:6, 0:32 - Ok


How about shrinking the code down to 32 bytes and use both itself and complements of address inputs? Would it make any difference?


Top
 Profile  
Reply with quote  
PostPosted: Sat Jul 25, 2015 5:25 pm 
Offline

Joined: Mon Jul 20, 2015 6:34 pm
Posts: 62
Dr Jefyll wrote:
Also, FWIW here's a datasheet for a 70's-vintage 32-byte PROM which nowadays is still available here and there. They're power-hungry but the small package outline (16-pin DIP) can be an advantage. (IIRC Jameco carries the open-collector version, whose part number ends in 188 rather than 288.) Other numbering schemes exist; for example 82S23 and 82S123 (the formed being the OC version).


1-2$ each not a bad candidate. But I guess I need to shrink the code down to 32 bytes with some magic :) I already deleted stack pointer initialization and interrupt disable and clear decimal since they don't make sense in my code. I found the part locally by the way. Unfortunately my programmer (minipro tl866cs) doesn't support it. I might find someone to program it though.

Out of topic but I have another question to whole. Is 6502 starts with all registers zeroed out? If yes then I can shrink the code further down to 35 bytes then I can search for magic to remove 3 bytes more :)


Top
 Profile  
Reply with quote  
PostPosted: Sat Jul 25, 2015 5:36 pm 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3367
Location: Ontario, Canada
Quote:
use both itself and complements of address inputs
They're already in use. In the approach explained, each product term is responsible for recognizing a single address. A single address is one which is distinct from all others, so, recognizing a single address requires that all the address lines must be tested to confirm that each one is high or low as appropriate. The true or complement of each address line is fed to the AND which expresses the product term. (Maybe someone could help me explain. I find this stuff too gnarly to describe easily & succinctly!)

Glad you like the 32-by-8 PROM -- I used to use those for address decoders! Who is your local supplier, and do they have the '288?

May we see the assembler source for your boot code? It's always fun tryna save just one more byte... :)

_________________
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: Sat Jul 25, 2015 5:56 pm 
Offline

Joined: Mon Jul 20, 2015 6:34 pm
Posts: 62
Ok I got it. We already have the facility to get the inverted value of address lines and we already use them in the or operation.

Here is where I'll get 74S288 : http://www.ersinelektronik.com/74S288-S ... -7995.html
It's $1 plus VAT.

Here is the code, already reduced 1 byte more.

Code:
BOOTLOADER = $00


   *=$FFDA
RESETROUTINE
   LDA #$00   ; If default state is 0 this can be omitted
   TAY      ; Init index (If default state is 0 this can be omitted)
   LDX #$08   ; Init bit counting
   CLI
   CLV
   
WAITBOOTLOADER
   BVC WAITBOOTLOADER
   
   JMP $0000

; NMI ROUTINE
; It does the transfer of 0 bits.
; A, X and Y is freely used and not pushed into the stack
; Since foreground task doesn't use any of them and just
; idly wait for the overflow flag from controlling micro.

NMIROUTINE
   ;SEI ;Since it's edge triggered, not needed. Also IRQ will not be triggered at the same time.
   CLC   
   BCC COMMONPART
   
; IRQ Routine
; It does the transfer of 1 bits.
; A, X and Y is freely used and not pushed into the stack
; Since foreground task doesn't use any of them and just
; idly wait for the overflow flag from micro.
; Also these registers are shared with the NMI routine since
; they are used for same purposes.
; And the routine is exactly same with the NMI routine except
; it sets carry before rotating current byte instead of clearing.
IRQROUTINE      
   SEI
   SEC
COMMONPART:   
   ROL
   DEX
   BNE FINISH    ; 1 bit (0) transferred in, exit.
   LDX #$08   
   STA BOOTLOADER, Y   ; Finish one byte of transfer 
   LDA #$00
   INY   
FINISH
   CLI
   RTI

      
      
   .ORG $FFFA
   
   .DW NMIROUTINE
   .DW RESETROUTINE
   .DW IRQROUTINE
   
   


Top
 Profile  
Reply with quote  
PostPosted: Sat Jul 25, 2015 7:21 pm 
Offline

Joined: Sun Jun 29, 2014 5:42 am
Posts: 352
I don't think the accumulator actually need to be initialized to zero, as you are ROLing it 8 times anyway.

Also, I think you can dispense with the SEI and CLI, as interrupts are disabled by defaults as part of processing the interrupt.

I think this allows you to save a further 5 bytes.

Dave


Top
 Profile  
Reply with quote  
PostPosted: Sat Jul 25, 2015 7:27 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8514
Location: Midwestern USA
i_r_on wrote:
Out of topic but I have another question to whole. Is 6502 starts with all registers zeroed out? If yes then I can shrink the code further down to 35 bytes then I can search for magic to remove 3 bytes more :)

None of the "user" registers (.A, .X and .Y) are conditioned at power-on, so their content will be undefined. This is also true of SP (stack pointer).

In the NMOS 6502, the only bit in the status register that is specifically conditioned is I (interrupt disable), which will be set. In the 65C02, the D (decimal mode) bit will be cleared, as well as the I bit being set.

The 65C816 has a slightly more complicated behavior at power-on (more registers than the 65C02), but can be thought of as a 65C02 when considering the initial state of the registers.

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Sat Jul 25, 2015 7:30 pm 
Offline

Joined: Sun Jun 29, 2014 5:42 am
Posts: 352
Another thought...

The number of product terms a data bit requires might actually be less than the number of 1's (or 0's if inverted).

Consider the start of your data:
A9 1010 1001
00 0000 0000
A8 1010 1000
A2 1010 1010

Look at bit D7, and notice that it's one at addresses 2 and 3, so this would take just one product term in the GAL, as bit A0 could be omitted.

I would hope that what ever GAL design software you are using would do a decent job of such product term optimization.

Failing that, you could resort to Karnaugh Maps.

Here's on online optimizer:
http://www.32x8.com/var5.html

Dave


Top
 Profile  
Reply with quote  
PostPosted: Sat Jul 25, 2015 7:34 pm 
Offline

Joined: Mon Jul 20, 2015 6:34 pm
Posts: 62
hoglet wrote:
I don't think the accumulator actually need to be initialized to zero, as you are ROLing it 8 times anyway.


Good point, I can't believe how I missed that

hoglet wrote:
Also, I think you can dispense with the SEI and CLI, as interrupts are disabled by defaults as part of processing the interrupt.

I think this allows you to save a further 5 bytes.

Dave


Actually I knew that but why I still left it there I don't know. Thanks for pointing that out.
Actually 3 since I still need to initialize Y register to zero.

2 bytes to go, current size is 34 bytes.

edit: Oops sorry, I just missed reinitialization in interrupt routine... it's now 32 bytes, thanks!


Top
 Profile  
Reply with quote  
PostPosted: Sat Jul 25, 2015 7:41 pm 
Offline

Joined: Sun Jun 29, 2014 5:42 am
Posts: 352
As an example, I tried D7 in your original byte listing
http://www.32x8.com/var6.html

It reduces to:

D7 = A + B.C.D.F + B.C.D.E + B.D.E.F + C.D.E.F + B.D.E.F + B.C.D.F + B.C.D.E.F + B.C.D.E.F

(A = A5)
(B = A4)
(C = A3)
(D = A2)
(E = A1)
(F = A0)

i.e. only 8 product terms, which would fit in the GAL fine.

Dave


Top
 Profile  
Reply with quote  
PostPosted: Sat Jul 25, 2015 7:52 pm 
Offline

Joined: Mon Jul 20, 2015 6:34 pm
Posts: 62
Final code is below, I also saved 1 byte by swapping X and Y's function. STA doesn't have zero page indirect with Y register.

Code:
STA BOOTLOADER, Y -> $99 $00 $00
STA BOOTLOADER, X -> $95 $00


Code:
BOOTLOADER = $00


   *=$FFE0
RESETROUTINE
   LDX #$00   ; Init byte storing index
   LDY #$08   ; Init bit counting
   CLI
   CLV
   
WAITBOOTLOADER
   BVC WAITBOOTLOADER
   
   JMP $0000

; NMI ROUTINE
; It does the transfer of 0 bits.
; A, X and Y is freely used and not pushed into the stack
; Since foreground task doesn't use any of them and just
; idly wait for the overflow flag from controlling micro.

NMIROUTINE
   CLC   
   BCC COMMONPART
   
; IRQ Routine
; It does the transfer of 1 bits.
; A, X and Y is freely used and not pushed into the stack
; Since foreground task doesn't use any of them and just
; idly wait for the overflow flag from micro.
; Also these registers are shared with the NMI routine since
; they are used for same purposes.
; And the routine is exactly same with the NMI routine except
; it sets carry before rotating current byte instead of clearing.
IRQROUTINE   
   SEC   
COMMONPART:   
   ROL   
   DEY   
   BNE FINISH    ; 1 bit (0) transferred in, exit.
   LDY #$08   
   STA BOOTLOADER, X   ; Finish one byte of transfer 
   INX   
FINISH
   RTI

      
      
   .ORG $FFFA
   
   .DW NMIROUTINE
   .DW RESETROUTINE
   .DW IRQROUTINE
   


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

All times are UTC


Who is online

Users browsing this forum: No registered users and 5 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: