# Z80 Test Code

Thread Starter

#### nDever

Joined Jan 13, 2011
153
Hey Guys,

I have a basic Z80 system built (http://z80.info/gfx/z80test.gif) NOTE: I do not have the UART or the MAX232 port. I have a series of 8 lights attached to Port A on a PIO and I have a bit of test code that is supposed to pulse the first LED on and off in a steady interval. When I start the system, the first LED glows but stays lit. According to the code I wrote, I think that the program is calling the delay1 subroutine but is not returning. I set the stack pointer to point to the top of memory which is in my RAM's address space and I have thoroughly examined the hardware configuration and everything is connected correctly.

Rich (BB code):
ld sp, 65535d

initiate:    ld a, 10000000b
out (03d), a

start:    ld a, 00000001b
out (0b), a
call delay1
ld a, 00000000b
out (0b), a
call delay1
jp start

delay1:    ld b, 10d
delay2:    ld c, 255d
delay3:    ld d, 255d
delay4:    dec d
jp nz, delay4
dec c
jp nz, delay3
dec b
jp nz, delay2
ret

Last edited:

#### blueroomelectronics

Joined Jul 22, 2007
1,757
You really should build a time machine and set it for 1978

#### t06afre

Joined May 11, 2009
5,934
What you need is a simulator software. It is pointless to just do some coding and then hope it will works. It never does I think you can find something here. http://www.z80.info/

#### mjhilger

Joined Feb 28, 2011
118
If you have access to a scope (digital) you should try to determine if the address lines seem to be progressing through your program as you expect. This might mean resetting it numerous times to capture one address line at a time, see if it appears to hit the addresses you think it should hit. Are you sure the NMI and INT pins are in an inactive state? I love Z80's for what they were in their time, but one cheap part from microchip can run rings around the thing with many many advantages. As I sit here at my desk I can touch my homemade UV eraser I used endlessly to prepare an eprom to load for the next attempt.

If I suspected that the processor was not running the program as I expected, I reverted back to as basic a form as I could and wrote a program that just began and looped back on itself at first, so 1 instruction JMP 0. You can use an old analog scope to see if all the address and data lines look correct and looping as you expect. If that works go a couple more maybe stretch it out with a few NOP's then the JMP 0 to determine if that seems right. I'm betting you will find either NMI or an INT that is causing a vector problem, or you have a problem with a line on your addr or data bus. Once you get past that point, you should be able to run your program.

Also, check the dump of your assembly to make sure the assembler got the numbers right, I don't know which one you are using and depending on the defaults, 3d could be interperted as hex 3d not 3 decimal. It has been 25+ years since I have programmed a PIO, but check the init. Like I said, you should find some way to look at the address bus to determine if it is looping where you expect. Even a hand logic probe can be very useful if you set your program to hit particular addresses such that you know only one or two lines should be toggeling. If you don't have access to some tool that will allow you to verify the state of the hardware, it can be very difficult to debug unless you are sure of your program and hardware.

Hope something I said has helped.

Thread Starter

#### nDever

Joined Jan 13, 2011
153
If you have access to a scope (digital) you should try to determine if the address lines seem to be progressing through your program as you expect. This might mean resetting it numerous times to capture one address line at a time, see if it appears to hit the addresses you think it should hit. Are you sure the NMI and INT pins are in an inactive state? I love Z80's for what they were in their time, but one cheap part from microchip can run rings around the thing with many many advantages. As I sit here at my desk I can touch my homemade UV eraser I used endlessly to prepare an eprom to load for the next attempt.

If I suspected that the processor was not running the program as I expected, I reverted back to as basic a form as I could and wrote a program that just began and looped back on itself at first, so 1 instruction JMP 0. You can use an old analog scope to see if all the address and data lines look correct and looping as you expect. If that works go a couple more maybe stretch it out with a few NOP's then the JMP 0 to determine if that seems right. I'm betting you will find either NMI or an INT that is causing a vector problem, or you have a problem with a line on your addr or data bus. Once you get past that point, you should be able to run your program.

Also, check the dump of your assembly to make sure the assembler got the numbers right, I don't know which one you are using and depending on the defaults, 3d could be interperted as hex 3d not 3 decimal. It has been 25+ years since I have programmed a PIO, but check the init. Like I said, you should find some way to look at the address bus to determine if it is looping where you expect. Even a hand logic probe can be very useful if you set your program to hit particular addresses such that you know only one or two lines should be toggeling. If you don't have access to some tool that will allow you to verify the state of the hardware, it can be very difficult to debug unless you are sure of your program and hardware.

Hope something I said has helped.
Upon close examination with my analog scope, I found that the CPU is asserting strange addresses upon resetting the system. The upper-half of the address pins are pulsing faster than A0. This is most likely the cause of the error in the program. I am not sure why it is emitting these addresses, but my suspicion is that my reset signal needs to be debounced. On the high-going edge of the reset, the voltage level may be fluctuating, causing the signal to go low for an extremely short time and when you give the CPU a reset period that is shorter than its clock, this is what happens. I do not have a 74C14 Schmitt trigger but I do have some NPNs and I have been trying to construct an effective trigger. So far, with no success.

#### SM5JAB

Joined Oct 1, 2007
5
As mjhilger writes: Make sure the /NMI is tied high, or you will get spurious interrupts. There is an internal refresh counter in a Z80 and the counter value will appear at adress pins sometime. Is it this you see as some adressbits alternating more rapidly?

A reset of a 10k resistor and 1uF cap would be enough. I have seen many a construction with no 74LS14 (schmitt-trigger) at the reset. So unless you are very unlucky this isn't it.

You are not running the processor out of spec regarding the clock-frequnecy are you?

loved the Z80. It was the processor I learnt assembly programming on. But nowadays a PIC from Microchip or ATmega from Atmel is far easier

/Micke

Thread Starter

#### nDever

Joined Jan 13, 2011
153
As mjhilger writes: Make sure the /NMI is tied high, or you will get spurious interrupts. There is an internal refresh counter in a Z80 and the counter value will appear at adress pins sometime. Is it this you see as some adressbits alternating more rapidly?

A reset of a 10k resistor and 1uF cap would be enough. I have seen many a construction with no 74LS14 (schmitt-trigger) at the reset. So unless you are very unlucky this isn't it.

You are not running the processor out of spec regarding the clock-frequnecy are you?

loved the Z80. It was the processor I learnt assembly programming on. But nowadays a PIC from Microchip or ATmega from Atmel is far easier

/Micke
I do have NMI and INT tied high as well as the 10k resistor and .1uF cap for the reset.

A0 is the first image and A7 is the second. These were both taken at boot-up. The system is clocked at about 3.5MHz.

#### Attachments

• 149.7 KB Views: 48
• 149.6 KB Views: 42

#### mjhilger

Joined Feb 28, 2011
118
I just realized that you said you set the sp to your ROM space - ERROR!!!
When you use a call instruction the current address is loaded onto the stack; when the steps hit the ret, it pops the address back off the stack. You should load the sp to point into your RAM area probably 0x100 from its end address.

I have intentionally pointed the stack in the ROM to run init diags, but you have to hand code the location into the ROM. It can be a great tool to run RAM diags in the startup, but probably not what you intended.

Move your sp into the RAM and try again. Or you could simply jmp to your delay routine and jmp back to your main. Because of your program you would have to have 2 delay routines to jump back to the correct address, but it would allow you to bypass the ram requirement totally.

Thread Starter

#### nDever

Joined Jan 13, 2011
153
I just realized that you said you set the sp to your ROM space - ERROR!!!
When you use a call instruction the current address is loaded onto the stack; when the steps hit the ret, it pops the address back off the stack. You should load the sp to point into your RAM area probably 0x100 from its end address.

I have intentionally pointed the stack in the ROM to run init diags, but you have to hand code the location into the ROM. It can be a great tool to run RAM diags in the startup, but probably not what you intended.

Move your sp into the RAM and try again. Or you could simply jmp to your delay routine and jmp back to your main. Because of your program you would have to have 2 delay routines to jump back to the correct address, but it would allow you to bypass the ram requirement totally.
Actually, I made an error. FFFFh is in my RAM space. I meant to type RAM but I typed ROM instead. Did you see my scope images? I think the program does not execute correctly because during the first opcode fetch after boot-up, the CPU sends out odd addresses. The first seven bits are fine but from the eighth to the sixteenth, they are oscillating with one half the period of A0. Do you think this could cause a problem? What is your opinion?

#### mjhilger

Joined Feb 28, 2011
118
RAM - OK!
I don't remember what happens on reset to the addr lines specifically, you need to qualify the first fetch with RD to know when the addr lines are valid with your read. Those are some really clean traces, I remember them being not so square on any of mine - maybe your slower speed is the reason. Qualify the addr with the /RD and go from there. Could be just its internal init before the begining of execution. I don't remember exactally. Most of the Z80 designs I worked with and designed some of them were using a hitachi 64180 - it was a suped up Z80 with some of the perpherials built into the chip - UART, DMA - I don't remember all but those for sure. While it ran the same code, I'm not sure about the addr lines, I only used a real Z80 on a handful of projects my senior year in college. The first place I worked we exclusively used the 64180 because of the savings in real estate. Debugging is the same though.

#### t06afre

Joined May 11, 2009
5,934
What have you done with the unused pins on the ROM and RAM chips. Have you tied them to low level voltage?

Thread Starter

#### nDever

Joined Jan 13, 2011
153
In my current circuit there is no memory; I am only testing the Z80. I am forcing NOPs by tying the data pins low with 100 ohm resistors.

#### t06afre

Joined May 11, 2009
5,934
In my current circuit there is no memory; I am only testing the Z80. I am forcing NOPs by tying the data pins low with 100 ohm resistors.
But the code in your first postings. How do you run that...

Thread Starter

#### nDever

Joined Jan 13, 2011
153
But the code in your first postings. How do you run that...
I apologize, after I posted that, I started to do some hardware debugging. After I debugged the hardware, I ran the same code without using calls but jumps instead. I still get the same results. It must be the software.

#### t06afre

Joined May 11, 2009
5,934
I apologize, after I posted that, I started to do some hardware debugging. After I debugged the hardware, I ran the same code without using calls but jumps instead. I still get the same results. It must be the software.
I remember I was doing a hobby project ones. I was using vero-board. And somehow I manage to mirror the data buss. So bit 7 become bit 0. It took me a week to find out of it... I remember the address buss went nuts.
By the way. In your code you have no org statements. Some Z80 assemblers start the code from 0x100h if no org statements are present. Also do you have a simulator to debug your code

Thread Starter

#### nDever

Joined Jan 13, 2011
153
Some Z80 assemblers start the code from 0x100h if no org statements are present.
This, I did not know.
Also do you have a simulator to debug your code
Not yet, do you know of any? Could you send me a link?
Here is the updated code that is supposed to blink the LED.
Rich (BB code):
org 0b

initiate:    ld a, 10000000b
out (03d), a

one:    ld a, 00000001b
out (0b), a
jp delay1

zero:    ld a, 00000000b
out (0b), a
jp delay1

delay1:    ld b, 10d
delay2: ld c, 255d
delay3:    dec c
jp nz, delay3
dec b
jp nz, delay2

cp 0d
jp nz, zero
jp one

Last edited:
Similar threads