Shop OBEX P1 Docs P2 Docs Learn Events
Propeller as EEPROM emulator and Peripheral Chip for z80? - Page 2 — Parallax Forums

Propeller as EEPROM emulator and Peripheral Chip for z80?

2

Comments

  • cavelambcavelamb Posts: 720
    edited 2013-08-25 21:08
    Dr_Acula wrote: »
    My bad on the 168 - it looks like an 8 on the compressed image on the website but yes on the pdf it is a 165. I fixed it on my post above.



    Good question! I think there are many solutions. One I'd like to test out (boards on the way) is to use a low value resistor. High enough that the propeller can force the pin to a certain state but low enough that it doesn't upset normal Z80 operation. I'm guessing something like about 220 ohms. So there is a 220 ohm resistor on the Z80 /WR and /RD pins and so the Z80 is trying to drive /RD low and /WR high but the propeller forces the voltage at the memory chip to /RD high and /WR low. The ram /OE should not matter as the ram needs to be enabled either way.

    Untested as yet but I'm hopeful that two resistors will save using a chip.

    /OE enables means the RAM will be writing to the data bus.
    Good way to let the smoke out of the RAM chip!
    AS6C4008-read.JPG
    640 x 460 - 86K
  • kwinnkwinn Posts: 8,697
    edited 2013-08-25 21:22
    /BUSREQ tristates all the Z80 bus pins so an external device can control the bus. No idea why he does that though. Slowing (diddling) the CLK signal only changes the timing, so that may be used to slow the Z80 so that the bootstrap program can be written to the ram chip.
  • kwinnkwinn Posts: 8,697
    edited 2013-08-25 21:30
    cavelamb wrote: »
    /OE enables means the RAM will be writing to the data bus.
    Good way to let the smoke out of the RAM chip!

    /OE (Output Enable) on the ram chip is normally connected to the Z80 /RD signal so with resistors on the Z80 /RD and /WR pins it should be ok as long as the current drive rating of the Z80 pins are not exceeded.
  • kwinnkwinn Posts: 8,697
    edited 2013-08-25 21:36
    @Dr_Acula

    Perhaps you mean the /CS since the /OE pin of the ram is normally connected to the /RD signal from the Z80. With only one ram chip the /CS can be tied low so the ram is always enabled.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2013-08-25 21:42
    Perhaps you mean the /CS since the /OE pin of the ram is normally connected to the /RD signal from the Z80. With only one ram chip the /CS can be tied low so the ram is always enabled.
    - yes sorry I meant /CS

    So the ram chip is enabled by the Z80 but the propeller takes control of both read and write.
  • cavelambcavelamb Posts: 720
    edited 2013-08-25 22:02
    kwinn wrote: »
    /BUSREQ tristates all the Z80 bus pins so an external device can control the bus. No idea why he does that though. Slowing (diddling) the CLK signal only changes the timing, so that may be used to slow the Z80 so that the bootstrap program can be written to the ram chip.

    Error on the schematic?
    Or maybe he didn't want to leave it floating and really did tie it to /RESET?
    I couldn't find any mention of /BUSREQ in the Z80CTRL.SPIN file...
    But it does name P9 as Z80 /RESET.

    And the '165 is there to read the IORQ port address.
    He's using all 256 port addresses for CP/M service requests!
    That's going to be slower than what I had in mind, but drops A0 (and saves that pin).

    But if /BUSREQ is asserted there will be nothing on the port address lines to shift into the Prop???
    I still don't see the CLK signal trick.
    It is used as the Z80 CLK - AND - the clk signal to the shift register - at the same time.
    It's a mystery!

    [one[hopefully last] edit tonight?]

    /BUSREQ would clear the data bus so that the Prop can write to RAM?
    (kwinn got it)



    When all else fails, read the source code!

    ' Z80 pin masks
      c_CpuIoReqMsk    =     1 << CPU_IOREQ_PIN      ' Mask to read Z80 IO request line (/IOREQ)
      c_CpuResetMsk    =     1 << CPU_RESET_PIN      ' Mask to set Z80 reset line (/RESET)
      c_CpuClkMsk      =     1 << CPU_CLK_PIN        ' Mask to set Z80 clock line (CLK), also tied to LOAD/SHIFT pin on 74HC165
      c_CpuRdMsk       =     1 << CPU_RD_PIN         ' Mask to read/set Z80 data read line (/RD)
      c_CpuWtMsk       =     1 << CPU_WT_PIN         ' Mask to read/set Z80 data write line (/WT)
      c_CpuEnMsk       =     1 << CPU_EN_PIN         ' Mask to set enable pin for RD/WT line buffer (74LV367)
      c_CpuAdrDataMsk  =     1 << CPU_ADRQ_PIN       ' Mask to read port address value from parallel to serial IC (74HC165)
      c_CpuAdrClkMsk   =     1 << CPU_ADRCLK_PIN     ' Mask to set port address clock on parallel to serial IC (74HC165)
      
      
      And down in the DAT section...
      
      Z80_BootNext          waitpne CpuRdMsk, CpuRdMsk      ' Wait for Z80 RD line to go low
                            mov     FRQB, #0                ' Stop Z80 clock accumulation
                            ' We have a read request, Z80 has a valid address and /MEMREQ signal.
                            ' Z80 is in read mode so data lines are inputs.
                            ' Save boot loader byte
                            rdbyte  T1, T3          'read next boot loader byte
                            add     T3, #1
                            'Place the data on the Z80/Ram data buss (P0..P7) 
                            andn    OUTA, #255
                            or      OUTA, T1
                            or      DIRA, #255      'Set data lines as outputs
                            'Data is output to ram, Z80 hold address and ram chip enable.
    '                        nop                     'wait for ram to ready
                            'activate write line on ram
                            andn    OUTA, CpuWtMsk
    '                        nop                     'wait for ram to ready
                            'Disable ram write signal
                            or      OUTA, CpuWtMsk
                            'Now feed the Z80 a NOP opcode ( nop = 0 )
                            andn    OUTA, #255
                            'Run Z80 until RD line is high
                            mov     FRQB, CpuClockFreq      'Run the Z80
                            waitpeq CpuRdMsk, CpuRdMsk      'Wait for RD line to go high
                            'Set the Data buss to inputs
                            andn    DIRA, #255      'Set data lines as inputs
                            djnz    T4, #Z80_BootNext
                            'Boot loader is copied to Z80 ram, rest CPU and we are ready to run
                            call    #Z80_Reset                 
    Z80_Boot_ret            ret 
    
  • kwinnkwinn Posts: 8,697
    edited 2013-08-25 22:02
    The Z80 does not really have a /CS signal. In the early days the ram chips were pretty small so /CS was generated using some of the address msb's and /MREQ. Typically this was done with a '155, '138, or '139. It's been so long since I've done anything with the Z80 that I forgot about the /MREQ and /IORQ signals. You will need to use /MREQ for the ram /CS, and /IORQ for I/O port requests.
  • kwinnkwinn Posts: 8,697
    edited 2013-08-25 22:13
    cavelamb wrote: »
    Error on the schematic?

    Or maybe he didn't want to leave it floating and really did tie it to /RESET?

    I couldn't find any mention of /BUSREQ in the Z80CTRL.SPIN file...
    But it does name P9 as Z80 /RESET.

    I am leaning towards it being an error. It has been a long time since I did any prototyping with the Z80, but IIRC the /BUSREQ was normally pulled up to Vcc so that external hardware could take over the bus if needed, and it was high otherwise. One piece of test equipment I lugged around let me plug a couple of ribbon cables into the CPU board and examine all the eprom and ram, read the status of input ports, and write data to output ports by pulling the /BUSREQ low.
  • msrobotsmsrobots Posts: 3,709
    edited 2013-08-25 23:22
    @kwinn ... exactly!

    Enjoy!

    Mike
  • kwinnkwinn Posts: 8,697
    edited 2013-08-26 00:15
    cavelamb wrote: »
    Error on the schematic?
    .............................................................

    /BUSREQ would clear the data bus so that the Prop can write to RAM?
    (kwinn got it)

    Missed this last bit earlier. No, you would not want to use /BUSREQ for writing to the ram. When it is pulled low the Z80 CPU sets its address, data, and control signals to the high-impedance state with the rising edge of the next clock pulse. That means the address bits are floating instead of providing a valid ram address for the prop to write to.

    After looking at the schematic and the propeller software for the Mini80 I think it will take a bit of study to see what is actually done. There seem to be a few errors and omissions in the schematic. I think the minimal system Dr_Acula wants is possible, and the Mini80 is close, but it needs a bit of work to get there.
  • lanternfishlanternfish Posts: 366
    edited 2013-08-26 01:41
    cavelamb wrote: »
    ... But why the serial out fromn that shift register be tied to Z80 /M1 ???

    I'd not even hazard a wild guess.

    Well, I'll volunteer to be the sacrificial lamb and try to contact him. :)

    Re the '165 I am not sure either why P10 is tied to both the /CK of the Z80 and the Serial In of the '165. From the '165 datasheet
  • kwinnkwinn Posts: 8,697
    edited 2013-08-26 08:01
    @ cave lamb and lanternfish

    Tying /CK to the '165 serial in let's you get a ninth bit shifted in. If P10 is also connected there it is probably a mistake. The resolution of the schematic makes it very hard to read so it may be necessary to use the software to verify the pinouts.
  • cavelambcavelamb Posts: 720
    edited 2013-08-26 08:59
    kwinn wrote: »
    @ cave lamb and lanternfish

    Tying /CK to the '165 serial in let's you get a ninth bit shifted in. If P10 is also connected there it is probably a mistake. The resolution of the schematic makes it very hard to read so it may be necessary to use the software to verify the pinouts.

    kwinn, there is a PDF version of the schematic hidden there.
    http://www.shaels.net/index.php/mini80/mini80-general/119-mini8o-overview
    Click on the pic of the schematic and it will offer it up.

    All the source code is in the zip file at
    http://www.shaels.net/index.php/mini80/downloads/121-mini80-prototype-project-files-2013-03-23
  • lanternfishlanternfish Posts: 366
    edited 2013-08-26 16:20
    @cavelamb: That is a better version of the schematic and clears up the P10 discrepancy.
  • kwinnkwinn Posts: 8,697
    edited 2013-08-26 22:28
    cavelamb, thanks for bringing that PDF to my attention. I tried downloading it before but all I got was some PCB pads scattered over the page. Switched from Firefox to Chrome and downloaded a good copy. Another puzzle to figure out!

    After a careful look at the schematic I think it is possible to build the simple circuit Dr_Acula suggested as long as his idea of using resistors for the read and write signals works.

    By removing the '165 and '367 from the circuit P13, P14, and P15 are freed up. That means the prop can no longer input A0 – A7 and the /M1 state from the Z80.

    The /M1 signal is used to indicate an instruction fetch. Since the prop will be looking at the /RD signal and feeding NOP instructions to the Z80 while it loads the boot program I do not think it is needed. Every memory read will be an instruction fetch. If it turns out /M1 is needed then P13 can be used and the number of prop ports reduced to 2.

    I would suggest using P13, P14, and P15 to read A5, A6, and A7 of the Z80 address bus to decode them as 4 I/O ports occupying the range of hex 80 to FF, leaving the 128 addresses from hex 00 to 7F for the Z80.

    The rest of the pin assignments could stay pretty much as they are so:

    P0 - P7 D0 – D7 of the Z80 and ram chip.
    P8 – Z80 /IORQ
    P9 – Z80 /RESET
    P10 – Z80 CLOCK
    P11 – Z80 /RD, RAM /OE
    P12 – Z80 /WR, RAM /WE
  • lanternfishlanternfish Posts: 366
    edited 2013-08-27 01:31
    From my reading of the spin files the '165 forms an I/o port decoder. I say this with the authority of someone who is out of their depth :innocent:
  • Heater.Heater. Posts: 21,230
    edited 2013-08-27 02:21
    I can't help thinking that one should use a couple of diodes and a resistor to combine the /RD, /WR signals from Z80 and Prop. Perhaps with pull ups if required.

    Good old fashioned "diode logic": http://en.wikipedia.org/wiki/Diode_logic

    This might not be as minimalist as having the devices fight over those signals through a resistor but it makes me feel better and at least is not another chip that needs two power lines and decoupling caps.
  • Toby SeckshundToby Seckshund Posts: 2,027
    edited 2013-08-27 06:16
    Heater.

    How about becoming "minimalist-ist" about the number of silicon junctions?

    On such a competition, I wonder what the ratio of the Prop's transistor count to the Z80's?
  • cavelambcavelamb Posts: 720
    edited 2013-08-27 09:56
    kwinn wrote: »
    cavelamb, thanks for bringing that PDF to my attention. I tried downloading it before but all I got was some PCB pads scattered over the page. Switched from Firefox to Chrome and downloaded a good copy. Another puzzle to figure out!

    After a careful look at the schematic I think it is possible to build the simple circuit Dr_Acula suggested as long as his idea of using resistors for the read and write signals works.

    By removing the '165 and '367 from the circuit P13, P14, and P15 are freed up. That means the prop can no longer input A0 – A7 and the /M1 state from the Z80.

    The /M1 signal is used to indicate an instruction fetch. Since the prop will be looking at the /RD signal and feeding NOP instructions to the Z80 while it loads the boot program I do not think it is needed. Every memory read will be an instruction fetch. If it turns out /M1 is needed then P13 can be used and the number of prop ports reduced to 2.

    I would suggest using P13, P14, and P15 to read A5, A6, and A7 of the Z80 address bus to decode them as 4 I/O ports occupying the range of hex 80 to FF, leaving the 128 addresses from hex 00 to 7F for the Z80.

    The rest of the pin assignments could stay pretty much as they are so:

    P0 - P7 D0 – D7 of the Z80 and ram chip.
    P8 – Z80 /IORQ
    P9 – Z80 /RESET
    P10 – Z80 CLOCK
    P11 – Z80 /RD, RAM /OE
    P12 – Z80 /WR, RAM /WE

    /IORQ and /M1 together indicate an interrupt response.
    I thought That might be why the 9th bit was tied to /M1.
    It would be a way to differentiate between an Input/output
    cycle or an interrupt cycle.
    But it looks like interrupts are NOT use. (?)
    At least as far as I can read PASM...
    But that would be why the 9th bit is be fed to the '165.

    Z80-Interupt.JPG


    No, all the code does is read 8 bits (??) as the IORQ port address.


    For I/O operations the Z80 puts the desired port address on the low 8 address lines.
    It looks like this mechanism is how the PROP reads the desired port address from the Z80
    without having to dedicate 8 Prop pins to the low 8 address lines.

    kwinn:
    Decoding 128 port address space only takes one address line.
    (well, as long as we are only using the traditional 256 port address system :) )

    I've been saying A0, but you are right; A7 would be a better choice.
    A0 would divide the IO space into even and odd -adequate for a minimal system,
    but would not preserve any IO space for the Z80 to use for anything else.

    A7 would divide IO space into upper and lower 128 ports, and I now realize that
    as long as the Prop will decode those internally (via software no less!) then the
    rest are still safe for the Z80 to use itslef. All that would take is a minor modificatin
    to the Mini-80 driver to allow the IORQ cycle to run unhindered (for those addresses).
    And no external decoder would be needed.

    But it IS necessary for the Prop to be able to read those low 8 address lines -
    somehow -
    to know what port is being addressed.

    Keep the '165.

    As for "feeding No-Ops", the Minio-80 doesn't do that.
    It simply stops the Z80 clock.
    It uses counter A in NCO mode to do that.
    Slick and simple at the same time.
    Elegant...

    For instance:
    Z80_Reset               mov     CTRB, #0                ' Disable counter B, no output on CPU_CLK_PIN               
                            mov     PHSB, #0
                            mov     FRQB, #0                ' Stop clock accumulation
                            mov     CTRB, #0                ' Disable counter A, no output on CPU_ADRCLK_PIN
                            ' Z80 clock is stopped, setup base pin directions
                            mov     OUTA, #0
                            mov     DIRA, BaseDirRegMsk
                            ' CPU reset is active, clock is low, and the RD/WT line buffer is enabled.
                            ' Run the clock for at least 8 to 10 CPU clock cycles before RESET is disabled
                            mov     T1, #10
                            mov     T2, CNT
                            add     T2, #32
                            'Set Z80 clock line high
    '                        or      DIRA, CpuClkMsk
    Z80_ResetLoop           or      OUTA, CpuClkMsk
                            waitcnt T2, #32
                            'Set Z80 clock line low
                            andn    OUTA, CpuClkMsk
                            waitcnt T2, #32
                            'See if we need more clock pulses
                            djnz    T1, #Z80_ResetLoop
                            'Release rest line, there is a 10k pullup on reset so just disable as output                        
                            or      OUTA, CpuResetMsk
                            andn    DIRA, CpuResetMsk
                            'Z80 has been reset, ready clock but do not start, then return
                            mov     CTRB, CpuClockMode      ' Set counter B to NCO mode, output on CPU_CLK_PIN
                            mov     FRQA, #0
                            mov     PHSA, #0
                            mov     CTRA, AdrClockMode      ' Set counter A to NCO mode, output on CPU_ADRCLK_PIN
    Z80_Reset_ret           ret
    

    Guys, the hardware for this project is fairly trivial.
    The software is not!
    640 x 300 - 87K
  • cavelambcavelamb Posts: 720
    edited 2013-08-27 10:04
    Re the '165 I am not sure either why P10 is tied to both the /CK of the Z80 and the Serial In of the '165. From the '165 datasheet

    Sorry all.
    I will try to not post technical stuff after midnight....
  • Toby SeckshundToby Seckshund Posts: 2,027
    edited 2013-08-27 14:16
    In my feeble mind I had something about ROMless booting, I thought that it was the NOP stuffings - but now I wonder if it was something like this that was niggling at me (fogged by the apple juice).


    http://www.jdm.homepage.dk/z80boot.htm


    Alan
  • lanternfishlanternfish Posts: 366
    edited 2013-08-27 15:29
    I was re-reading the Zilog Z80 User's Manual when I stumbled across this:
    When the clock input to the CMOS Z80 CPU is stopped at either a High or
    Low level, the CMOS Z80 CPU stops its operation and maintains all
    registers and control signals. However, ICC2 (standby supply current) is
    guaranteed only when the system clock is stopped at a Low level during T4

    of the machine cycle following the execution of the HALT instruction.

    And then:
    The system clock must be supplied to the CMOS Z80 CPU to release the
    power-down state. When the system clock is supplied to the CLK input, the
    CMOS Z80 CPU restarts operations from the point at which the powerdown
    state was implemented. The timing diagrams for the release from
    power-down mode are featured in Figure 13 , 14 and 15.
    When the HALT instruction is executed to enter the power-down state, the
    CMOS Z80 CPU also enters the HALT state. An interrupt signal (either
    NMI or ANT) or a RESET signal must be applied to the CPU after the
    system clock is supplied in order to release the power-down state.

    Obviously the Mini80 works but I cannot see any code that allows for this. Or is there?

    EDIT: I see it now at the bottom of the code in post #50
  • Heater.Heater. Posts: 21,230
    edited 2013-08-27 20:22
    cavelamb,
    As for "feeding No-Ops", the Minio-80 doesn't do that.
    It simply stops the Z80 clock.

    That can't be right. The mini80 page clearly describes the boot sequence:

    1. Pull Z80 reset line low.

    2. Generate enough clock pulse to allow Z80 core to fully reset then set
    reset line high.

    3. Set the tri-state buffer enable pin high to tri-state Z80 read and
    write lines (/RD, /WT).

    4. Provide clock pulses to the Z80 until the Z80 indicates a read operation.

    5. Place the desire data on to the data buss, then pulse the RAM /WT pin low to write the memory location, Z80 provides address and RAM chip select.

    6. Place the 8 bit Z80 op-code NOP (0) on the data buss.

    7. Provide clock pulses to the Z80 until the Z80 indicates the read operation
    completed (/RD = high).

    8. Repeat steps 4..7 until the required boot code is copied to RAM, each
    cycle the Z80 will increment its memory address starting at address zero.

    9. Pull Z80 reset line low.

    10. Generate enough clock pulse to allow Z80 core to fully reset then set
    reset line high.

    11. Set the tri-state buffer enable pin low to enable Z80 read and write
    lines (/RD, /WT).

    12. Set the Propeller chip counter to clock the CPU at required frequency.

    Given that the address bus is not connected to the Prop the Z80 has to provide all the addresses required to write the boot code. In order to step sequentially through those addresses it has to being seing a NOP from each location.

    Step 5 writes the data to RAM and step 6 puts a NOP on the data bus for the Z80 to read thus advancing it to the next address.

    Or are you saying the mini80 Prop code does not do that?
  • kwinnkwinn Posts: 8,697
    edited 2013-08-27 20:28
    Heater. wrote: »
    I can't help thinking that one should use a couple of diodes and a resistor to combine the /RD, /WR signals from Z80 and Prop. Perhaps with pull ups if required.

    Good old fashioned "diode logic": http://en.wikipedia.org/wiki/Diode_logic


    This might not be as minimalist as having the devices fight over those signals through a resistor but it makes me feel better and at least is not another chip that needs two power lines and decoupling caps.

    That would need 4 diodes, 2 pullup resistors, and 2 current limiting resistors to avoid any possible problems. Two series resistors do the same thing.
  • kwinnkwinn Posts: 8,697
    edited 2013-08-27 21:46
    cavelamb wrote: »
    /IORQ and /M1 together indicate an interrupt response.
    I thought That might be why the 9th bit was tied to /M1.
    It would be a way to differentiate between an Input/output
    cycle or an interrupt cycle.
    But it looks like interrupts are NOT use. (?)
    At least as far as I can read PASM...
    But that would be why the 9th bit is be fed to the '165.

    Z80-Interupt.JPG


    No, all the code does is read 8 bits (??) as the IORQ port address.

    The '165 loads A0 to A7 (the I/O port address for I/O operations) in and and then shifts it in to the prop. As each bit is shifted out of the '165 the state of /M1 is shifted in, until all 8 bits of the '165 contain the state of the M1 pin. The next shift will then shift the M1 state in to the Prop.

    Quote from the Z80 manual on /M1 “M1 - Machine Cycle One (output, active Low). M1, together with MREQ, indicates that the current machine cycle is the opcode fetch cycle of an instruction execution. M1 together with IORQ, indicates an interrupt acknowledge cycle.

    For I/O operations the Z80 puts the desired port address on the low 8 address lines.
    It looks like this mechanism is how the PROP reads the desired port address from the Z80
    without having to dedicate 8 Prop pins to the low 8 address lines.

    Exactly.
    kwinn:
    Decoding 128 port address space only takes one address line.
    (well, as long as we are only using the traditional 256 port address system :) )

    I've been saying A0, but you are right; A7 would be a better choice.
    A0 would divide the IO space into even and odd -adequate for a minimal system,
    but would not preserve any IO space for the Z80 to use for anything else.

    A7 would divide IO space into upper and lower 128 ports, and I now realize that
    as long as the Prop will decode those internally (via software no less!) then the
    rest are still safe for the Z80 to use itslef. All that would take is a minor modificatin
    to the Mini-80 driver to allow the IORQ cycle to run unhindered (for those addresses).
    And no external decoder would be needed.

    Correct again. A7 high (along with /IORQ) indicates that this is an address for I/O hardware attached to the Prop. The other two bits I suggested be used allow us to select one of four I/O devices. That would allow us to choose between the SD card, serial connection (Prop plug), and two other devices.
    But it IS necessary for the Prop to be able to read those low 8 address lines -
    somehow -
    to know what port is being addressed.

    Keep the '165.

    Not necessarily. If you can not add more I/O hardware to the Prop you do not need more than four port addresses. Yes, it wastes a lot of potential I/O ports (only 4 of 128 possible ports used), but that simplifies the hardware and still leaves the Z80 with a possible 128 more ports.
    As for "feeding No-Ops", the Mini-80 doesn't do that.
    It simply stops the Z80 clock.
    It uses counter A in NCO mode to do that.
    Slick and simple at the same time.
    Elegant...

    Yes, it is quite elegant, and it does feed no-op's to the Z80 in order to have it generate sequential addresses for writing the bootstrap program into the ram. I have not had time to analyze and comment the code but the basic sequence is as described in the Min80 Docs

    1. Pull Z80 reset line low.
    2. Generate enough clock pulse to allow Z80 core to fully reset then set reset line high.
    3. Set the tri-state buffer enable pin high to tri-state Z80 read and write lines (/RD, /WT).
    4. Provide clock pulses to the Z80 until the Z80 indicates a read operation.
    5. Place the desire data on to the data buss, then pulse the RAM /WT pin low to write the memory location, Z80 provides address and RAM chip select.
    6. Place the 8 bit Z80 op-code NOP (0) on the data buss.
    7. Provide clock pulses to the Z80 until the Z80 indicates the read operation completed (/RD = high).
    8. Repeat steps 4..7 until the required boot code is copied to RAM, each cycle the Z80 will increment its memory*address starting at address zero.
    9. Pull Z80 reset line low.
    10. Generate enough clock pulse to allow Z80 core to fully reset then set reset line high.
    11. Set the tri-state buffer enable pin*low to*enable Z80 read and write lines (/RD, /WT).
    12. Set the Propeller chip counter to clock the CPU at required frequency.
    At this point the boot loader*has completed and the Z80 will begin to execute the code loaded in to*the RAM memory starting at memory address zero.

    Line 5 writes the data from the prop to the ram. Line 6 then puts the NOP instruction on the data bus and feeds it to the Z80.
    Guys, the hardware for this project is fairly trivial.
    The software is not!

    Very true, but the software is already written. While modifying it is not trivial, the changes needed to accommodate removing the '165 and '367 are not that great.
  • ShaelShael Posts: 17
    edited 2013-08-28 03:30
    Just wanted to say thanks for pointing out the mistake I made on the Mini80 project schematic.

    The P9 line is used to control the Z80 /RESET pin and should not be connected to the /BUSREQ pin. I do not use the /BUSREQ signal other then to pull it to a high level using a 10k resistor to disable it. I have updated the WEB site to reflect the changes.

    It has been interesting to follow the forum posts, I went thru many of the same design considerations when I developed the Mini80.

    FYI:

    The M1 signal is not currently used and does not need to be connected to the 165 shift register. I may use it in the future to decode IRQ vector requests from the Z80.

    The P10 line has dual uses; primaraly it is used to clock the Z80, P10 is also used to control the Z80 I/O address loading for the 74hc165. P10 must be in the low state to load the Z80 address, then changed to the high state to shift out the address to the Prop chip.
  • Toby SeckshundToby Seckshund Posts: 2,027
    edited 2013-08-28 04:19
    The slight schematic error was easily sorted out by reading your code comments.

    Unfortunately I run Firefox, and so the .pdf version is just a bunch of pads and circles :-(

    ADDIT I have downloaded the .pdf and opened it with Reader and that is all OK (even if the latest version of reader seems painfully slow)
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2013-08-28 05:05
    It works!

    Some of this code is not needed - even the debugging back to the propeller terminal (F12) is not needed as this is debugging with a logic probe, one instruction at a time. So it will work without the .sio and .str objects
    CON
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
      _baudRateSpeed = 115200 ' Teraterm does not work at this speed. Use hyperterminal or proptool terminal
      _receiverPin = 31
      _transmitterPin = 30
    
    OBJ
      delay: "Timing"                                       ' for millisecond delays
      sio  : "pcFullDuplexSerial2FC"                        ' serial port
      str  : "ASCII0_STREngine"                             ' strings
    
    VAR
    
    PUB Main
       sio.AddPort(0, _receiverPin, _transmitterPin, -1, -1, 0, 0, _baudRateSpeed)
       sio.start
       Z80Boot
       'repeat
       '  PrintString(string("Test"))
    
       repeat  ' endless loop
    
    PUB Z80Boot | i
       ' P0-7 is Z80 data bus 0-7
       ' P8 = Z80 /IORQ
       ' P9 = Z80 /WR
       ' P10 = Z80 /RD
       ' P11 = Z80 Clk
       ' P12 = Z80 A0
       ' P13 = Z80 /RESET
       Z80ResetLow                                          ' set reset low
       Z80Clock(5)                                          ' clock several times to register the reset
       Z80ResetHigh                                         ' set reset high
       Z80WaitForRdLow                                      ' clock until rd goes low, at this point address should be 00000000_00000000
       repeat i from 0 to 2
          Z80WriteByteToRam(byte[@Z80BootProgram][i])       ' move a byte into ram
          Z80DataBusNOP                                     ' sets data bus to zero, Z80 reads this as a NOP and proceeds to next instruciton
          Z80Clock(2)                                       ' two clocks
          Z80WaitForRdLow                                   ' wait until reads next value
       Z80ResetLow                                          ' reset the Z80 ready to run the program
       Z80Clock(5)                                          ' wait till responds
       Z80ResetHigh                                         ' reset high
       Z80Clock(12)                                         'run the little program, test pin status with different number of clock pulses
       repeat  ' do nothing
    
          
    DAT
       Z80BootProgram
            byte $3E,$41,$76 '
       ' ld a,65
       ' halt
       ' end    ' write this in the N8VEM program, compile, read with hexedit 
    
    PUB Z80Clock(n)
        DIRA |= %00000000_00000000_00001000_00000000        ' enable the clock pin as an output\
        repeat n
          OUTA |= %00000000_00000000_00001000_00000000        ' clock high
          delay.pause1ms(10)                                ' delay if needed
          OUTA &= %11111111_11111111_11110111_11111111        ' clock low
          delay.pause1ms(10)                                ' delay
    
    PUB Z80ResetLow
       DIRA &= %11111111_11111111_11000000_00000000         ' data bus and /iorq /wr /rd clk A0 and /reset all HiZ (pulled high with 10k)
       DIRA |= %00000000_00000000_00100000_00000000         ' reset pin = output
       OUTA &= %11111111_11111111_11011111_11111111         ' set reset pin low   
    
    PUB Z80ResetHigh
       DIRA |= %00000000_00000000_00100000_00000000         ' reset pin = output
       OUTA |= %00000000_00000000_00100000_00000000         ' set reset pin high
    
    PUB Z80WaitForRdLow                                     ' keep clocking until the /rd pin goes low
       repeat while (INA & %00000000_00000000_00000100_00000000)
         Z80Clock(1)
    
    PUB Z80WriteByteToRam(n)
        n &= %00000000_00000000_00000000_11111111           ' mask off all but lower 8 bits
        DIRA |= %00000000_00000000_00000110_11111111        ' set P0-P7 as outputs and also /RD and /WR as outputs
        OUTA &= %11111111_11111111_11111111_00000000        ' mask outa lower 8 bits to zero
        OUTA |= n                                           ' combine with the data byte
        OUTA &= %11111111_11111111_11111101_11111111        ' force /WR low
        OUTA |= %00000000_00000000_00000100_00000000        ' force /RD high
        delay.pause1ms(10)                                  ' delay, make as short as possible
        OUTA |= %00000000_00000000_00000010_00000000        ' write high
        DIRA &= %11111111_11111111_11111001_00000000         'set /rd /wr and the data bits to inputs (highZ)
    
    PUB Z80DataBusNOP                                       ' put zero (NOP) on data bus
        DIRA |= %00000000_00000000_00000000_11111111        ' set data bus to outputs
        OUTA &= %11111111_11111111_11111111_00000000        ' set data bus to zero                            
    
    
    PUB PrintStringCR(pstring)' sends pstring to the vga and serial port
         PrintString(pstring)                               ' print the string  
         crlf
    
    PUB PrintString(pstring)' sends pstring to the serial port with no CRLF
        sio.str(0,pstring)                                 ' send to com port
    
    PUB PrintChar(c) ' sends c to vga and serial port
          sio.tx(0,c)                                         ' send to com port
        
    PUB CRLF
        PrintChar(13)                                        ' send to vga
        PrintChar(10)                                        ' send to vga
    
    PUB PrintDecimal(number)                                ' print the decimal value, useful for debuggin
         PrintString(str.integerToDecimal(number, 10))   
    
    

    Attached photo of the board and schematic.

    For the schematic (and as shown in the photo), lots of things can be omitted. The 5V regulator is not needed. Leave out the VGA display, audio, keyboard, TV and SD card. Leave out the MCP23008 (used for selecting memory banks). You could even leave out the propeller eeprom and test with just F10 if you want.

    So chips are a Z80 and a memory chip, regulator and a download circuit. The pullups are important.

    No problems it seems with the Z80 running at 3V3. It runs cold.

    The clever bit is the two 220 ohm resistors which enable the propeller to force memory /rd and /wr pins into different states without upsetting the Z80.

    So - this loads a tiny 3 byte program into the Z80, and then steps through and runs it.

    I have tested each step with a logic probe and it seems to work just fine.

    Program is all in spin at the moment and there are lots of delays. Things like the clock can be moved into pasm later.

    This circuit is simple enough to be breadboarded. It uses even less components if you have a propplug.

    With six Z80 pins under propeller control (reset, rd, wr, iorq, A0, clock) that should be enough for a fast comms protocol.

    And great to see Shael here - so many brilliant ideas in that Mini80 board!
  • cavelambcavelamb Posts: 720
    edited 2013-08-28 05:45
    Shael wrote: »
    Just wanted to say thanks for pointing out the mistake I made on the Mini80 project schematic.

    The P9 line is used to control the Z80 /RESET pin and should not be connected to the /BUSREQ pin. I do not use the /BUSREQ signal other then to pull it to a high level using a 10k resistor to disable it. I have updated the WEB site to reflect the changes.

    It has been interesting to follow the forum posts, I went thru many of the same design considerations when I developed the Mini80.

    FYI:

    The M1 signal is not currently used and does not need to be connected to the 165 shift register. I may use it in the future to decode IRQ vector requests from the Z80.

    The P10 line has dual uses; primaraly it is used to clock the Z80, P10 is also used to control the Z80 I/O address loading for the 74hc165. P10 must be in the low state to load the Z80 address, then changed to the high state to shift out the address to the Prop chip.

    Shael!

    Hey, nice to see you here.
    And thank you so much for sharing your work.
    Awesome stuff!
  • roglohrogloh Posts: 5,808
    edited 2013-08-28 07:05
    Seems I should also be posting my results here but I have updated the other Z80 thread with more info. Good to hear your board is working Dr_Acula!
Sign In or Register to comment.