Z80 Test Code

Discussion in 'Computing and Networks' started by nDever, Mar 3, 2011.

  1. nDever

    Thread Starter Active Member

    Jan 13, 2011
    154
    4
    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.

    Code ( (Unknown Language)):
    1.  
    2. ld sp, 65535d
    3.  
    4. initiate:    ld a, 10000000b
    5.               out (03d), a
    6.  
    7. start:    ld a, 00000001b
    8.            out (0b), a
    9.            call delay1
    10.            ld a, 00000000b
    11.            out (0b), a
    12.            call delay1
    13.            jp start
    14.  
    15. delay1:    ld b, 10d
    16. delay2:    ld c, 255d
    17. delay3:    ld d, 255d
    18. delay4:    dec d
    19.               jp nz, delay4
    20.               dec c
    21.               jp nz, delay3
    22.               dec b
    23.               jp nz, delay2
    24.               ret
    25.  
     
    Last edited: Mar 7, 2011
  2. blueroomelectronics

    AAC Fanatic!

    Jul 22, 2007
    1,758
    98
    You really should build a time machine and set it for 1978
    [​IMG]
     
  3. t06afre

    AAC Fanatic!

    May 11, 2009
    5,939
    1,222
    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/
     
    nDever likes this.
  4. mjhilger

    Member

    Feb 28, 2011
    119
    16
    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.
     
    nDever likes this.
  5. nDever

    Thread Starter Active Member

    Jan 13, 2011
    154
    4
    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.
     
  6. SM5JAB

    New Member

    Oct 1, 2007
    5
    1
    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
     
    nDever likes this.
  7. nDever

    Thread Starter Active Member

    Jan 13, 2011
    154
    4
    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.
     
  8. mjhilger

    Member

    Feb 28, 2011
    119
    16
    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.
     
  9. nDever

    Thread Starter Active Member

    Jan 13, 2011
    154
    4
    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?
     
  10. mjhilger

    Member

    Feb 28, 2011
    119
    16
    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.
     
  11. t06afre

    AAC Fanatic!

    May 11, 2009
    5,939
    1,222
    What have you done with the unused pins on the ROM and RAM chips. Have you tied them to low level voltage?
     
  12. nDever

    Thread Starter Active Member

    Jan 13, 2011
    154
    4
    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.
     
  13. t06afre

    AAC Fanatic!

    May 11, 2009
    5,939
    1,222
    But the code in your first postings. How do you run that...:confused:
     
  14. nDever

    Thread Starter Active Member

    Jan 13, 2011
    154
    4
    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.
     
  15. t06afre

    AAC Fanatic!

    May 11, 2009
    5,939
    1,222
    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:confused:... 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
     
  16. nDever

    Thread Starter Active Member

    Jan 13, 2011
    154
    4
    This, I did not know.
    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.
    Code ( (Unknown Language)):
    1.  
    2. org 0b
    3.  
    4. initiate:    ld a, 10000000b
    5.         out (03d), a
    6.  
    7. one:    ld a, 00000001b
    8.     out (0b), a
    9.     jp delay1
    10.  
    11. zero:    ld a, 00000000b
    12.     out (0b), a
    13.     jp delay1
    14.  
    15. delay1:    ld b, 10d
    16. delay2: ld c, 255d
    17. delay3:    dec c
    18.     jp nz, delay3
    19.     dec b
    20.     jp nz, delay2
    21.  
    22.     cp 0d
    23.     jp nz, zero
    24.     jp one
    25.  
     
    Last edited: Mar 10, 2011
Loading...