6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Thu Nov 21, 2024 10:12 pm

All times are UTC




Post new topic Reply to topic  [ 21 posts ]  Go to page Previous  1, 2
Author Message
PostPosted: Thu Nov 30, 2023 2:09 pm 
Offline
User avatar

Joined: Fri Feb 17, 2023 11:59 pm
Posts: 163
Location: Lviv, Ukraine
gfoot wrote:
Nice. My current SD solution is an ATF22V10 driving two shift registers (one in, one out) with an additional 74HC139 - it provides a read/write I/O address and a status I/O address, and writing the status address sets CS high or low. I can share the design more if you like, perhaps you can get the ATF750 to do all of it in one chip. It is quite pleasant to use from code.

I tried adding CPOL & CPHA into my ATF750 that can be configured by writing to A0=1, but alas - the clock is the bottleneck.

CPOL works, since SCK is a simple XOR (PHI2 ^ CPOL). So we can have dynamically configurable mode 0 or mode 2 that can be changed during runtime.

CPHA is trickier though: changing it requires changing the clock edge of shift register. This is unfortunately not doable with ATF750, since .CLK may only have a single term or products. This makes XORing the shift register clock impossible (since A^B is !A&B#A&!B). Mode 3 might also be non-trivial to implement without major changes, because shift register's .CLK edge needs to be different for loading data (PHI2 falls) & shifting data (PHI2 rises).

I'll leave it at SPI mode 0 for now, since I only need it for SD card anyway.

_________________
/Andrew

deck65 - 6502 slab with screen and keyboard | ПК-88 - SBC based on KM1810VM88 (Ukrainian i8088 clone) | leo80 - simple Z80 SBC
nice65 - 6502 assembly linter | My parts, footprints & 3D models for KiCad/FreeCAD


Top
 Profile  
Reply with quote  
PostPosted: Thu Nov 30, 2023 3:34 pm 
Offline
User avatar

Joined: Fri Feb 17, 2023 11:59 pm
Posts: 163
Location: Lviv, Ukraine
Here's my final version that supports setting CPOL by writing to A0=1 (write 0x02 for mode 2, 0x00 for mode 0, the latter is the default), and also should work with non-6502 buses (e. g. x86, where /WR is asserted for more than 1 cycle).
I also had to move D0..D7 to the middle of outputs, since in GALs pins that are closed to edges of the chip can have less terms (same as in GALxVy devices).

This timing diagram demonstrates writing the byte, then setting CPOL to 1, then writing another byte.
Attachment:
timing.png
timing.png [ 402.49 KiB | Viewed 3273 times ]

GREEN is driven lines, YELLOW is actual outputs, BLUE is tested outputs. Sorry @BDD - WinCUPL only allows me to customize the colors... Hopefully you can still see all those lines since the background is black. Here's a b&w image just in case:
Attachment:
timing_bw.png
timing_bw.png [ 235.43 KiB | Viewed 3273 times ]

Dim lines are tested outputs.

Here, /EN is constantly asserted for better comprehension of what's happening inside the registers. In actual system, D0..D7 will be tri-stated most of the time, since they are only driven when /EN and /RD are asserted.

Important: setting CPOL (writing to A0=1) clobbers data register state, so when using CPI mode 2, make sure to write CPOL before writing the data.


Attachments:
File comment: WinCUPL .PLD & .SI files.
spi.zip [1.84 KiB]
Downloaded 83 times

_________________
/Andrew

deck65 - 6502 slab with screen and keyboard | ПК-88 - SBC based on KM1810VM88 (Ukrainian i8088 clone) | leo80 - simple Z80 SBC
nice65 - 6502 assembly linter | My parts, footprints & 3D models for KiCad/FreeCAD
Top
 Profile  
Reply with quote  
PostPosted: Thu Nov 30, 2023 3:59 pm 
Offline

Joined: Wed Aug 21, 2019 6:10 pm
Posts: 217
For the '299 USR, not latching puts you on the knife edge, where the USR and the SPI bus device must shift at the same time. Otherwise, if the USR shifts before the SPI Bus Device, MISO will be available from the bus and MOSI must be latched ... if the USR shifts after the SPI Bus Device, MOSI will be available from the bus and MISO must be latched.

I think the ideal SPLD SPI chip for a 65xx bus would be internally a Mode 3 SCLK and would be quite like a USR except that it latched MISO (DS0) and MOSI (Q7) on the downward clock tick, and had CS1, /CS2 and R/W, and did the logic internally to convert an internal Mode 3 SCLK into the desired SCLK for the SPI bus.

I think starting with Mode 3 USR SCLK and either passing it on as a Mode 3 SPI_SCLK or converting it to Mode 0 SPI_SCLK may be easier direction. In the Mode 0 conversion, that requires masking the high internal SCLK and putting a low idle SCLK on the SPI bus, removing the mask when the Mode 3 SCLK goes low for the first time, and then restoring the mask after the final upward transition of the Mode 3 internal SCLK.

So get the SPI_SCLK by filtering the Internal_SCLK using an AND gate that has inputs of a Mode 3 SCLK and a state. For Mode 0, the State is /reset to 0 before pulling down the /Select line, which which holds the idle clock low. The /set input to the state is the Mode 3 SCLK, so that when the Mode 3 SCLK goes low for its Phi1 clock phase, the State line goes high. However, now the Mode 3 SCLK input to the AND gate is low, so the Mode 0 SCLK output remains low until the first upward transition of the Internal SCLK. After 8 bits, the Mode 3 SCLK ends high, and then the read of the input byte can reset the Mode 0.

So when running Mode 0, it is necessary to read the MISO byte even if the MISO byte is not used, but the whole process of write, NOP, NOP, NOP, read will be 14 clock cycles, which is such a big win over bit-banging that I would not begrudge it the 4 clock overhead for redundant reads.

The /SELECT_RD line can be OR'd with a Mode select input as the /reset input to the /s /r state latch, and if you want a Mode 0 SCLK, you pull the Mode Select input low and do a dummy read of MISO before you pull /SPI_SELECT low. If you want a Mode 3 SCLK, you pull the Mode Select input high, and do a dummy write of MOSI before you pull /SPI_SELECT low.

If it is possible to refrain from doing a read during the SPI SCLK cycle, that means that the state machine can be a simple /S /R latch from cross connecting two NAND gates. I guess that means you either only use the SPI bus during NMI interrupt handling or never use the SPI bus during NMI interrupt handling.

If you generate Mode 0 from Mode 3 by filtering the serial clock to bring it low for idle, that means the clock polarity and phase are both inverted at the same time. So if you want a two line, four mode SCLK mode select, use SPI_PHASE as the Mode Select input, and use SPI_POLARITY to selectively invert the result of the above circuit: XOR(SPI_2MODE,XOR(SPI_POLARITY,SPI_PHASE)), so that when SPI_POLARITY and SPI_PHASE are equal, the SPI_2MODE serial clock is left alone, and when they are different, the SPI_2MODE serial clock is inverted.

Note that with the USR, you don't need to generate the /SELECT_RD line for the USR from /Select and /RD, since you can simply connect /SELECT to /OE1 and /RD to /OE2 for the read select itself. So the mode 0 /reset input can be a three input OR gate, OR(/SELECT,/RD,Mode), if preferred to the two stage OR(Mode,OR(/Select,/RD)).


Top
 Profile  
Reply with quote  
PostPosted: Mon Feb 05, 2024 10:12 pm 
Offline

Joined: Fri Jun 11, 2021 1:18 pm
Posts: 1
Hello all, I come to the post late, but wanted to share my success in putting together a simple compromise solution for SPI for 65X systems. I found the 74HC299 chip interesting but also too troublesome with the modes it had to be forced to for shifting, writing, and reading, it would have required either PLDs or a lot of extra logic chips with the timing being thrown off. Instead, I went with the solution of using the 74HC165 and 74HC595 to implement the shift registers for MOSI and MISO. For clocking, I considered many options and even designed a state machine with configuration register to use different speeds divided from PHI2, but I wanted it to be simple and not use too much space. So I resigned to doing the clocking in software but with using a 74HC74 flip-flop to control the clock, with software control I can lower the speed by adding NOPs in between the clocking. The other flip-flop will enable the CS from the 74HC137 decoder latch thus providing a simple chip select for 8 SPI devices, and the flip-flop will be disabled on reset to prevent spurious reads and writes. This solution I feel is a great compromise between using a full featured 65SPI CPLD(which I’m still working out how to program those ATF1504s!) and bit-banging SPI using a 65C22. There are no programmable logic parts, just 5 74hc chips comprising the SPI module. I know this only works for SPI mode 0, but honestly I’ve only ever encountered SPI peripheral devices that use mode 0, so I figured it was still worth it. I have tested this solution on my 65C02 board I designed and successfully used it to store data on a SPI RAM chip(23lc1024), so I know it works, in the future I hope to integrate into future versions of my BMBX 65X computer series. Maybe I’ll even use it for UART with a MAX3100

Example code:
sta SPI_DATA

stz SPI_SHIFT ; SCLK up
stz SPI_SHIFT ; SCLK down
... 7 more times

lda SPI_DATA

Let me know what y’all think!


Attachments:
File comment: circuit diagram, meant to be connected directly to 6502 data bus
Simple_SPI_Module.png
Simple_SPI_Module.png [ 38.57 KiB | Viewed 2516 times ]
Top
 Profile  
Reply with quote  
PostPosted: Tue Feb 06, 2024 12:41 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8543
Location: Southern California
Welcome.  I tried my hand at converting to black-on-white for our members who have visual trouble with the colors:
Attachment:
Simple_SPI_ModuleBW.gif
Simple_SPI_ModuleBW.gif [ 10.49 KiB | Viewed 2458 times ]

_________________
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?


Top
 Profile  
Reply with quote  
PostPosted: Wed Feb 07, 2024 4:53 am 
Offline

Joined: Wed Aug 21, 2019 6:10 pm
Posts: 217
d0gbertthegreat wrote:
... ... I know this only works for SPI mode 0, but honestly I’ve only ever encountered SPI peripheral devices that use mode 0, so I figured it was still worth it. ...


My targets were a MAX3100, which is Mode0, and an SPI RTC that is Mode1/Mode3. That's why I was looking at a circuit with a MODE0 latch that is reset by a separate signal and set by the MODE3_SCLK. Feeding that through an AND gate with a Mode3_SCLK basically clips the first half cycle from the MODE3 clock cycle, giving 7 and a half MODE0 clock cycles, and resetting the MODE0 latch at the end of the process completes the final half cycle for MODE0.

A programming advantage is that if the SPI routine always does the Mode0 reset before selecting a device and at the end of each byte, then you can simply run a MODE0_SCLK line to Mode0 device(s) and a MODE3_SCLK line to Mode3 device(s), and don't need to handle Mode selection in software.

An advantage with your circuit is that the MODE0 reset signal could be generated by "LDA SHIFT_SPI", using the presently unused D7 of your 74x138, so no additional decoding logic is needed.

Finally, note that if this is for access to a known set of SPI interfaced chips that are fast enough for the chip select cycle to work as a half clock phase, the circuit can be simplified by using the SHIFT_SPI write select as a direct Mode3_SCLK. Then:

Code:
SPI_TRX:
    STA SPI_DATA
    STZ SPI_SHIFT
    STZ SPI_SHIFT
    STZ SPI_SHIFT
    STZ SPI_SHIFT
    STZ SPI_SHIFT
    STZ SPI_SHIFT
    STZ SPI_SHIFT
    STZ SPI_SHIFT
    LDA SPI_SHIFT
    LDA SPI_DATA
    RTS


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

All times are UTC


Who is online

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