View unanswered posts | View active topics It is currently Fri Mar 29, 2024 8:49 am



Reply to topic  [ 15 posts ] 
 Attempting to build a Z80 SBC (many images) 
Author Message
User avatar

Joined: Sun May 28, 2023 12:11 am
Posts: 10
Location: Lviv, Ukraine
I've mostly been building 6502-based SBCs so I have some prior experience with 6502. Recently, I decided to try building one with Z80 for fun (CMOS TMPZ84C00, found one for ~$1 locally).

I went through Z80 datasheet and some resources on the internet. Here's what I came up with.

Design considerations:
- $0000-$7FFF - ROM
- $8000-$FFFF - RAM
- 8 LEDs for visual output
- Using perfboard for this, so trying to keep it small & simple - will be adding more fancy things later (LCD, UART, etc).
- Simple 8-bit output through '273 flip-flop.
- No input or interrupts for now.
- I used AS6C4008 in schematic since it's included in Kicad parts by default. I have various SRAM chips available. Same with W27C512 EPROM.

This is my first time doing anything with Z80, so please let me know if something seems terribly off.

Attachment:
v1.jpg
v1.jpg [ 394.27 KiB | Viewed 30260 times ]

Attachment:
File comment: Grayscale version
v1_bw.jpg
v1_bw.jpg [ 275.43 KiB | Viewed 30260 times ]


Any feedback is greatly appreciated!


Last edited by and3rson on Wed Jul 19, 2023 12:13 pm, edited 1 time in total.



Mon Jul 17, 2023 12:28 pm
Profile WWW
User avatar

Joined: Sun May 28, 2023 12:11 am
Posts: 10
Location: Lviv, Ukraine
I think I found a minor issue that would bite me once I add interrupts.

I forgot that /IORQ goes low when an IRQ is being handled. This means accidental writes will happen to my '273 during interrupts.

Seems like the easiest way to handle this is to gate /IORQ with /M1 (since /M1 is asserted during IRQ vector access) by introducing /IOEN, so that it's asserted when /IORQ is low AND /M1 is high. Then I can safely use /IOEN instead of /IORQ for my I/O:

Attachment:
v1_ioen.png
v1_ioen.png [ 47.94 KiB | Viewed 30239 times ]


Tue Jul 18, 2023 10:14 am
Profile WWW
User avatar

Joined: Sun May 28, 2023 12:11 am
Posts: 10
Location: Lviv, Ukraine
After some considerations, I've decided to add simple input through 8-section DIP switch & '244 tri-state buffer.

I also replaced my 10-gate NAND address decoding with a single ATF16V8: it leaves more space on my PCB and allows me to reconfigure address decoding logic after I have my PCB printed, since I'm pretty sure there are some oversights in my design and I'll likely need to change something there. PLD will make it much easier.

Attachment:
v1a.jpg
v1a.jpg [ 303.96 KiB | Viewed 30225 times ]

Attachment:
v1a_bw.jpg
v1a_bw.jpg [ 222.41 KiB | Viewed 30225 times ]

Attachment:
v1a_pcb.png
v1a_pcb.png [ 41.6 KiB | Viewed 30225 times ]

Attachment:
v1a_3d.jpg
v1a_3d.jpg [ 96.26 KiB | Viewed 30225 times ]


Wed Jul 19, 2023 12:07 pm
Profile WWW
User avatar

Joined: Sun May 28, 2023 12:11 am
Posts: 10
Location: Lviv, Ukraine
Ha, I totally forgot to tie unused RAM & ROM address lines low.
Having fixed that, I feel like this is the optimal version. Will be ordering a PCB tomorrow, hopefully I'll have it ready for testing by weekend!

Attachment:
v1b_pcb.png
v1b_pcb.png [ 48.3 KiB | Viewed 30222 times ]

Attachment:
v1b_3d.jpg
v1b_3d.jpg [ 109.34 KiB | Viewed 30222 times ]


Wed Jul 19, 2023 8:02 pm
Profile WWW

Joined: Wed Jan 09, 2013 6:54 pm
Posts: 1780
looks nice!


Thu Jul 20, 2023 7:13 am
Profile

Joined: Sat Feb 02, 2013 9:40 am
Posts: 2095
Location: Canada
Looks great. I suggest if there is a next version to provide some pins with the address, data, and control signals present. It would make it easier to expand the I/O.

_________________
Robert Finch http://www.finitron.ca


Tue Jul 25, 2023 2:31 am
Profile WWW
User avatar

Joined: Sun May 28, 2023 12:11 am
Posts: 10
Location: Lviv, Ukraine
robfinch wrote:
Looks great. I suggest if there is a next version to provide some pins with the address, data, and control signals present. It would make it easier to expand the I/O.

Absolutely. I'm planning to use Z84C20 PIO or even 65C22 VIA in next build. The purpose of this board was to see it I can handle Z80 and to get a very basic board working with least mistakes - i. e. to make sure there are no oversights with address decoding and clock, and possibly with more stuff I haven't thought about.

Attachment:
v1_ready.jpg
v1_ready.jpg [ 174.29 KiB | Viewed 30177 times ]


I used a very simple program for my initial smoke test to see if CPU works at all and if my address decoding does handle RAM/ROM/IO properly.
Code:
    org 0

; reset
reset:
    jp main

; irq
    block 0x38-$
irq:
    reti

; nmi
    block 0x66-$
nmi:
    reti

; main
main:
    in a, (0x00)        ; Read from DIP switches
    out (0x01), a       ; Write to LEDs
    jp main

Luckily, this build seems to work just fine! I'm surprised to have it at the first try. I guess my 6502 "experience" helped me somewhat. :D

Attachment:
v1_io.jpg
v1_io.jpg [ 43.92 KiB | Viewed 30177 times ]


Tue Jul 25, 2023 10:17 am
Profile WWW
User avatar

Joined: Sun May 28, 2023 12:11 am
Posts: 10
Location: Lviv, Ukraine
Turns out I actually do have an issue: RAM doesn't seem to behave.

It seems like data is simply not written to RAM. Furthermore, reading from RAM makes D0 read random values: the LED is constantly blinking.
It feels like data bus is floating during RAM reads.

Attachment:
v1_ram_issue1.jpg
v1_ram_issue1.jpg [ 76.73 KiB | Viewed 30168 times ]


I've seen somewhere that Z80 has very weak address lines. But the rest of the chips work just fine: some of my programs that use ROM & IO ('244, & '273), without RAM - work fine

Attachment:
bus_excerpt.jpg
bus_excerpt.jpg [ 44.36 KiB | Viewed 30167 times ]


I'm wondering if the issue could be with /RD line not strong enough to enable RAM most of the time, and thus I could get floating data. All my chip-enabling lines are driven with ATF16V8B, I've used it in combo with AS6C4008 in the past without any issues. The lines that go from my Z80 to RAM are data bus, address bus, /RD, and /WD. Only RAM/EN (/CE) is controlled by ATF16V8.

Do I need some buffers on address bus? Is Z80 not strong enough to control my RAM? I wish I had a good oscilloscope...

Edit: found this thread - https://www.retrobrewcomputers.org/foru ... &#msg_6676, and as per their response seems like the safest way to go is indeed to have 3x '244 (address bus + control) & 1 '245 (data bus).

Edit 2: I'm also suspecting that the cheapo Z84C0020PEC chips that I've got might in fact be re-labeled NMOS versions... :D


Tue Jul 25, 2023 8:33 pm
Profile WWW
User avatar

Joined: Sun May 28, 2023 12:11 am
Posts: 10
Location: Lviv, Ukraine
Here's what I think should work for me:

Attachment:
v2_buffers.jpg
v2_buffers.jpg [ 1.46 MiB | Viewed 30160 times ]


- Data bus goes through '245, output during non-read cycles and input during read cycles (using /RD instead of /WR because Z80 drives data bus during T2 without asserting /WR).
- Address bus goes through '244, constantly enabled (I'm OK with having my Z80 constantly controlling the address bus - I don't plan to do any DMA or bus sharing).
- /RD and /WR are buffered through another '244, with additional version of /WR for chips that might require a non-zero bus hold time. AS6C4008 has a requirement for data hold time of 0, but I want to be on the safe side. I initially thought about 74LS14, but it's much slower than '244.
- I'm ignoring /BUSACK, /WAIT, & /HALT since I don't use them.

Once again, DipTrace does a wonderful job auto-routing all my mess:
Attachment:
v2_pcb_a.jpg
v2_pcb_a.jpg [ 230 KiB | Viewed 30159 times ]


Unfortunately, too little space is left for PIO. Will have to figure something out.


Tue Jul 25, 2023 10:03 pm
Profile WWW

Joined: Wed Jan 09, 2013 6:54 pm
Posts: 1780
Hmm, a difficult one to debug - not easy even to see whether the write is bad, or the readback.

But I feel it unlikely that the problem is a lack of drive, or a need for buffers. It feels more likely to me to be a timing problem, or possibly a logic problem, such that the situation during a write (or a read) isn't quite what you think it is. (Could even be a noise problem, perhaps.)

Can you successfully write and read back to a peripheral chip?

Can you share the datasheet of your RAM?


Wed Jul 26, 2023 11:59 am
Profile
User avatar

Joined: Sun May 28, 2023 12:11 am
Posts: 10
Location: Lviv, Ukraine
BigEd wrote:
Hmm, a difficult one to debug - not easy even to see whether the write is bad, or the readback.

But I feel it unlikely that the problem is a lack of drive, or a need for buffers. It feels more likely to me to be a timing problem, or possibly a logic problem, such that the situation during a write (or a read) isn't quite what you think it is. (Could even be a noise problem, perhaps.)

Can you successfully write and read back to a peripheral chip?

Can you share the datasheet of your RAM?


Yeah, it's hard to probe my data lines because they seem to be heavily impacted by analyzer's capacitance.

I've tested with AS6C1008-55PCN - https://eu.mouser.com/datasheet/2/12/AS ... 511508.pdf - not 4008 as I previously thought.

I/O seems to work just fine: '244 correctly reads DIP switches when reading port 0, and '245 correctly latches all writes to port 1. Memory decoding with ATF16V8B also seems to yield correct chip selects, tested with a digital analyzer, and also wrote a simple test for my TL866 II Plus:
Code:
# addr.pld

GAL16V8
Addr

CLK  /MREQ  A0    A15  /IORQ /M1    NC    NC    NC    GND
/OE  /ROM  /RAM  /IO   /IN   /OUT  /LCDEN NC    NC    VCC

; ROM = $0000..$7FFF
ROM   = /A15  *  MREQ
; RAM = $8000..$FFFF, avoid refresh cycles
RAM   =  A15  *  MREQ *  /M1

; Qualify I/O with /M1 to avoid accidental I/O writes during interrupts
IO    =  IORQ * /M1

; Port 0 - input
IN    = /A0   *  IO
; Port 1 - output
OUT   =  A0   *  IO

DESCRIPTION
Address decoder for Leo80


Code:
# addr.toml (converted to .lgc using jedec2hex.py tool):
[[ics]]
name = "Addr-AFT16V8B"
pins = 20
vcc = 5.0
vectors = [
    "1XXXXXX00G0XXXXXXXXV",

    # /MREQ, /IORQ, /M1 all high
    "110011X00G0HHHHHXXXV",

    # /ROM
    "100011X00G0LHHHHXXXV",
    # /RAM
    "100111X00G0HLHHHXXXV",

    # /IN
    "110001X00G0HHLLHXXXV",
    # /IN, but M1 is low
    "110000X00G0HHHHHXXXV",
    # /OUT
    "111001X00G0HHLHLXXXV",
    # /OUT, but M1 is low
    "111000X00G0HHHHHXXXV",
]


My code:
Code:
; Reset/IRQ/NMI omitted for brevity

; Read 1-byte offset from 8 DIP switches and set LEDs to value from RAM on address (0x8000 + offset)
loop:
    ; Read DIP switches
    in a, (0x00)
    xor a, 0xFF  ; Flip values for convenience (my DIP switches are pulled up, so the value is inverted)
    ; Load A from 0x8000 + A
    ld l, a
    ld h, 0x80
    ld a, (hl)
    ; Set LEDs
    out (0x01), a

    ; Wait ~0.6s
    ld hl, 0xFFFF
    ld a, 0
    jp softim  ; Cannot use call/ret due to RAM issues


; CPU sleep code from internet
softim:
    inc a ;at least one pass
    ld b, a ;through outer loop
    ld a, 0 ;dummy instructions
    jp softm2 ;to kill time
softm1:
    jr softm2 ;delay 16 T states
softm2:
    nop
softm3:
    dec hl ;decrement low order
    ld a,l
    or h ;hl = 0?
    jp nz, softm1 ;no, look again
    dec b ;b = zero?
    jr nz, softm3 ;no, repeat outer loop
    ; ret ;yes, return
    jp loop  ; Cannot use call/ret due to RAM issues



Also, 0.1uF caps are placed near every ICs. ROM also works perfectly: it's just the RAM that's behaving strangely.

I made a huge mistake not adding pin headers for bus & control lines: it would have made debugging much easier, especially for this first build.

Data line "seems" to be stable during writes to RAM - at least I can see the proper bits on data line.

I wonder if there's a simple way to differentiate whether it's a bad read, a bad write, or both: the only way I can think of is to halt the CPU and read from RAM using another device without powering it off.

Maybe you're right and I'm missing some obvious timing violation in my chip selection scheme... I still am not used to understanding some obscure parameters in datasheet timing tables. :[

EDIT: I've noticed that it's only D0 and D7 that feel to be floating during RAM reads: D1-D6 always yield logical 1, no matter which RAM address I'm reading, but D0 & D7 are flickering when I touch them.
EDIT 2: When adding 0.1s~0.5s busy loops, D0 blinks almost as if like it's toggled during every read. The blinking stops (becomes 0) when I touch it with my finger, tweezers, or attempt to probe it. However, this happens only when reading even addresses.
EDIT 3: D0 blinking behavior seems almost unchanged when I remove my RAM whatsoever.
EDIT 4: I tried 2 different 1008 RAMs, both reproduce all those issues.


Wed Jul 26, 2023 1:04 pm
Profile WWW

Joined: Thu Jul 27, 2023 8:21 am
Posts: 2
It looks like you're qualifying your RAM access with M1, that's probably not a good idea.That's the CPU indicator that an opcode fetch is in process, it won't be active in a data read.

If you want to block refresh cycles from hitting memory then you need to have RFSH connected to the GAL. RFSH and M1 aren't mutually exclusive.

However with RD and WR connected to you RAM, there won't be any actual access, just a small increase in current as the RAM comes out of standby for the 2 refresh cycles when the chip enable is active.


Thu Jul 27, 2023 8:37 am
Profile
User avatar

Joined: Sun May 28, 2023 12:11 am
Posts: 10
Location: Lviv, Ukraine
Martin A wrote:
It looks like you're qualifying your RAM access with M1, that's probably not a good idea.That's the CPU indicator that an opcode fetch is in process, it won't be active in a data read.

If you want to block refresh cycles from hitting memory then you need to have RFSH connected to the GAL. RFSH and M1 aren't mutually exclusive.

However with RD and WR connected to you RAM, there won't be any actual access, just a small increase in current as the RAM comes out of standby for the 2 refresh cycles when the chip enable is active.


Thanks - it totally flew over my head that I actually should not disable RAM when /M1 is asserted if I want to run code from RAM.

Another update: I found the problem... I'm using AS6C1008, but my schematic is AS6C4008. For compatibility with 1008, I used to pull A15-A18 high in the past.
However, in this build, I tied them low... While forgetting that in 1008, pin 30 is actually CE2 (active high)!
So I literally hard-wired RAM to be always off...

I'll break the trace to pin 30, tie it high and see if it does the trick. :D Will post shortly.

EDIT: Yep, that was it. :D


Last edited by and3rson on Thu Jul 27, 2023 11:14 am, edited 1 time in total.



Thu Jul 27, 2023 10:36 am
Profile WWW

Joined: Thu Jul 27, 2023 8:21 am
Posts: 2
If you want to check your CPU really is CMOS, there's a way to do it in code.

Opcode ED 71 is officially undocumented. It's where OUT (C),(HL) would have been if it existed. On an NMOS CPU the effect is OUT (C),0. On the CMOS CPU it's effect is OUT (C),FF.

Source:https://groups.google.com/g/comp.os.cpm/c/HfSTFpaIkuU/m/KotvMWu3bZoJ

So if you load BC with the port address of the LEDs and follow that by the illegal opcode, you'll know from the state of the LEDs which type of CPU it is.


Thu Jul 27, 2023 11:08 am
Profile
User avatar

Joined: Sun May 28, 2023 12:11 am
Posts: 10
Location: Lviv, Ukraine
Martin A wrote:
If you want to check your CPU really is CMOS, there's a way to do it in code.

Opcode ED 71 is officially undocumented. It's where OUT (C),(HL) would have been if it existed. On an NMOS CPU the effect is OUT (C),0. On the CMOS CPU it's effect is OUT (C),FF.

Source:https://groups.google.com/g/comp.os.cpm/c/HfSTFpaIkuU/m/KotvMWu3bZoJ

So if you load BC with the port address of the LEDs and follow that by the illegal opcode, you'll know from the state of the LEDs which type of CPU it is.


Interesting! I just tested and it wrote 0xFF, so my CPU is indeed CMOS. Thanks for a neat trick!


Thu Jul 27, 2023 11:18 am
Profile WWW
Display posts from previous:  Sort by  
Reply to topic   [ 15 posts ] 

Who is online

Users browsing this forum: No registered users and 6 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:  
cron
Powered by phpBB® Forum Software © phpBB Group
Designed by ST Software