Flip-flop frustration - Page 1
Forum section: electronics / beginners

author: netdudeuk
author_rank: Frequent Contributor
timestamp: November 29, 2013, 01:31:16 am
content: HiI've been trying to get something working which I expect the guys on here will have a simple answer to, pleaseI have a Z80 board which I'd like to connect to an AVR chip for I/O purposes.The theory is that a 74LS74 D type flip-flop catches the Z80 IORQ events and pulls down WAIT (with the Q output) while the AVR chip, which had been polling Q, does the I/O work. When the AVR chip has done, it sets the flip-flop output HIGH again, letting the Z80 continue.On startup, the AVR chip drives the Z80 RESET pin low to reset it. It then drives the flip-flop clock LOW and then HIGH. The D input is connected to the positive rail so the Q output should go HIGH.The Z80 IORQ pin is connected to the flip-flop CLR pin. When an I/O instruction is executed, this pin goes low, clearing the flip-flop, which should then cause the WAIT to start. The AVR does what it needs to and then takes the flip-flop CLK pin LOW and HIGH (to set Q high again) and then off we go again, with the AVR watching Q going low again for the next I/O.Does anyone see any flaws in this theory ? Any idea why it doesn't work ? Maybe there's a better way to do it ?Thanks

author: Jebnor
author_rank: Regular Contributor
timestamp: November 29, 2013, 06:26:11 am
content: I think a schematic would be useful. Parsing schematic into language, and vice versa, are error prone.

author: Kremmen
author_rank: Super Contributor
timestamp: November 29, 2013, 06:58:04 am
content: When exactly does the Z80 IORQ pin return to high state?

author: codeboy2k
author_rank: Super Contributor
timestamp: November 29, 2013, 07:23:53 am
content: How exactly doesn't it work, and are you doing an input or an output?So you're using the /IORQ line to clear the DFF and bring the /WAIT line of the Z80 low. So far seems OK.I'm assuming an input cycle, so after the AVR sees Q go low, does it then put data on the Z80 data lines and release the /WAIT (by clocking the DFF) ??Does the AVR wait long enough for the Z80 to latch the data, before changing the lines? the Z80 will latch the data bus for an input cycle on the first falling edge of the Z80 clock after the completion of the wait cycle.Again, how is it failing exactly, with what symptoms? you just said it didn't work but didn't tell us what you were doing or what you expected.

author: netdudeuk
author_rank: Frequent Contributor
timestamp: November 29, 2013, 08:42:05 am
content: Thanks for the answers guys.It was really late (or should that be early ?) when I wrote the message so I didn't get all the detail in.As it happens, I actually had the thing working hours before. I was successfully dumping nibbles of data from the Z80 to the serial console. However, there were two breadboards plus my Z80 card and it stopped working, at all. I had to strip it right back but failed to remember exactly how I'd got it working. I blame the cheap breadboards. The metal inserts seem to lose their springiness really quickly so you end up with unreliable connections. I was at it for the rest of the day and got to the point where the frustration of not getting it right just stopped me from seeing clearly anymore.I have another idea so I'll give that a blast and report back thanks.

author: woodchips
author_rank: Frequent Contributor
timestamp: November 29, 2013, 12:26:08 pm
content: Be a little cautious of the 7474, it is edge triggered and will also happily latch from glitches coming in on the Q outputs. What might be better is to use the set and clear inputs and solidly tie the clock to 0V.

author: netdudeuk
author_rank: Frequent Contributor
timestamp: November 30, 2013, 12:34:57 am
content: All working ok now thanks. It's basically like I said previously but this time I soldered a socket onto some board and soldered all the wires so as to avoid the flaky breadboard and unpredictable results.IORQ resets the flip-flop which takes WAIT lowAVR notices this by monitoring IORQ which stays low once WAIT has been taken low. Previously, the AVR was monitoring Q.AVR does what it needs to do and the sets the flip-flop and the Z80 carries on.D is tied low.At the moment, the I/O handler just sends a message down the serial port and then sets the flip-flop. I was missing some output data from the setup. Scoping the IORQ and WAIT lines, I noticed that the IO requests were erratic even though the Z80 code is just running a series of OUTs. Moving the wires on the AVR down from 8, 9 and 10 to 5, 6 and 7 cleared that up. Looks like there's something happening inside the AVR besides my own stuff (every pin does seem to have million functions).

author: netdudeuk
author_rank: Frequent Contributor
timestamp: December 04, 2013, 02:53:00 pm
content: Hi guysI spoke too soon and have spent days trying to get it right but I'm missing something.I attach the schematic, the Z80 source code, the Arduino main loop and relevant subroutine code and some logic traces.IORQ is ORed with RD to provide IORD and IORQ is ORed with WR to provide IOWR.D and CLK are connected to ground to prevent spurious actions.When an I/O WRITE is performed, the flip-flop should be cleared by IOWR, forcing the Z80 to WAIT until the Arduino code takes SET low, allowing the Z80 to continue.If the flip-flop is not connected to WAIT, I get a very nice clean trace of the two INs and the five OUTs.IORDs are not associated with the flip-flop but I should still be able to detect the five OUTs which I cannot. Of course, if I cannot detect them, I cannot reset the flip-flop to get the Z80 going again after a wait.If the flip-flop is connected to WAIT as it is meant to be, I get the odd results shown in the second trace. While the WAIT process seems to have worked on the first Z80 OUT command, after it has been cleared, subsequent ones seem wrong, not following through with the IOWRs.Please can anyone explain what is going wrong here ?ThanksZ80 source code.org 0in a,(0)in a,(0)out (0),aout (0),aout (0),aout (0),aout (0),ahaltArduino codevoid loop(){while (digitalRead(Z80_IOWR) == HIGH) {};// Deal with the I/O requests herez80_reset_wait();}// Clear the wait conditionvoid z80_reset_wait(){digitalWrite(Z80_WAIT_RESET_PIN, LOW);digitalWrite(Z80_WAIT_RESET_PIN, HIGH);}

author: sync
author_rank: Frequent Contributor
timestamp: December 04, 2013, 03:22:34 pm
content: DigitalRead and DigitalWrite are really slow. When there is another IOWR while the arduino sets the flip-flop it will be missed.

author: netdudeuk
author_rank: Frequent Contributor
timestamp: December 04, 2013, 03:40:00 pm
content: Quote from: sync on December 04, 2013, 03:22:34 pmThanks for the suggestion. However, my theory is that the IOWR operation should be picked up VERY quickly by the flip-flop, putting the Z80 into the wait state, waiting for the Arduino to detect the IOWR operation at it's leisure.

author: sync
author_rank: Frequent Contributor
timestamp: December 04, 2013, 03:47:48 pm
content: Quote from: netdudeuk on December 04, 2013, 03:40:00 pmBut notwhile/S is low. Which take a long time due the slowness of DigitalWrite. How fast is the Z80 clock?

author: netdudeuk
author_rank: Frequent Contributor
timestamp: December 04, 2013, 03:51:23 pm
content: 3.6864MHz

author: sync
author_rank: Frequent Contributor
timestamp: December 04, 2013, 04:08:13 pm
content: I measured your z80_reset_wait() on my arduino. The set pulse is 6.5us long. That's about 24 Z80 clocks. While this duration any new IOWR will be ignored by the flip-flop.Make your measurements again and trace /S too. I think you will see it.

author: netdudeuk
author_rank: Frequent Contributor
timestamp: December 04, 2013, 04:51:25 pm
content: As requested ...Thanks

author: sync
author_rank: Frequent Contributor
timestamp: December 04, 2013, 05:47:37 pm
content: As I suspected the set pulse is too long. With your circuit it must be shorter than two Z80 clocks (~540ns) when two sequent IO cycles occur. It's possible with the arduino when using direct port manipulation. Seehttp://arduino.cc/en/Reference/PortManipulation.Here is an example which makes a 125ns pulse on a 16MHz Uno.Code:noInterrupts(); // disables interruptsPORTD &= ~(1 << 4); // set port D pin 4 lowPORTD |= 1 << 4; // set port D pin 4 highinterrupts(); // enable interruptsWhen a interrupt occurs between the set low and the set high command then the pulse will be longer. Disabling the interrupts prevent this.Edit:Oops. That will not work with your circuit. The pulse must be longer that one Z80 clock so the Z80 can reliably detect the cleared /WAIT. When /S goes high then /WAIT will go low again because /IOWR is still low.That's a drawback of your circuit. Better set the flip-flop on the falling edge of /IOWR.

author: netdudeuk
author_rank: Frequent Contributor
timestamp: December 04, 2013, 06:28:58 pm
content: Let me say that Ireallyappreciate your assistance with this. It's been doing my head inI'd found that your initial suggestion didn't follow through as planned. If I amend the wiring on the board now as you suggested, would itdefinitelywork as originally planned ?Thanks again.

author: sync
author_rank: Frequent Contributor
timestamp: December 04, 2013, 07:07:31 pm
content: When there are no other errors then it will work as planned.Sorry, I can't give you a guarantee. But I think it should work. If not then do the measurements again. This is a timing critical circuit. There are many thing which can go wrong. Your logic analyzer (or scope) is the first debugging tool for such problems.

author: netdudeuk
author_rank: Frequent Contributor
timestamp: December 04, 2013, 07:34:23 pm
content: Understood thanks. I'll put the iron on.Would it be better for the Arduino to be monitoring the Z80 WAIT pin to detect the OUTs, looping around until it sees a LOW ? Or do you think there's a better option ?

author: sync
author_rank: Frequent Contributor
timestamp: December 05, 2013, 01:55:35 pm
content: You can use an interrupt on the arduino to detect a Z80 WAIT. But the interrupt code will be asynchronously executed from the main ardunio code. This is error prone. Stay with looping.

author: netdudeuk
author_rank: Frequent Contributor
timestamp: December 05, 2013, 05:03:12 pm
content: HiSo I followed up your suggestion and now it seems to be working wellThe only thing that's interesting now is why it takes so long to clear up after the first wait. I'm guessing that this is the Arduino catching up from doing the Z80 reset to performing the first iteration of the loop.I've learned a couple of things (like digitalWrite being pants) and the frustration has eased for nowMany thanks for your help.