• Please review our updated Terms and Rules here

A Homebrew Z8002

Hi Bill,
Intriguing. One other thing I'm curious about. Why are you addressing the OUTB via the R6 register? Didn't direct addressing work the same way as INB? The code is correct in both cases.
 
I can do OUT 81h,R5 correctly, however OUTB 81h,RL5 does not work, but OUTB @R6,RL5 works correctly. So I’m now switched to IN and OUT via a register.
Now I’ve overcame the IN/OUT hurdle, I’ve a working serial loader in CPLD ROM that loads and runs a 256-byte program in RAM. Now I can run programs without repeatedly reprogramming the CPLD. Ran and passed memory diagnostics, so I’m ready to write a monitor.
Bill
 
Something doesn't add up here. The instructions OUT 81h,R5; OUTB @R6,RL5 work, but OUTB 81h, RL5 does not. I suspect that the same effect applies to the IN instruction? Does the CPLD have any connection to the A0 line for I/O operations?
 
Last edited:
I am finding it difficult to understand that Zilog would release a device that had a fairly fundamental bug in the I/O instructions. There are not too many of them, so the validation suite should cover them all (plus all of their addressing modes). I am, therefore, suspecting a timing-related issue (the two addressing modes having slightly different timings).

I am, however, having a little bit of trouble understanding your CPLD logic and assembler code.

The assembler code is not 'spinning' on the UART status bits (a - to make sure the receiver has received a character and b - to make sure the transmitter is free). I understand that you have the software delay before inputting and outputting the data byte - but (for real practical purposes) the UART status bits should be used.

I am also trying to understand the logic around the UART receiver with the DataReady looped back to the RdData pin and the subsequent D flip-flop on the data output from the UART.

Just trying to understand your design...

Did you actually see the correct address and status going out on the Z8k's AD and control buses at the appropriate time?

Dave
 
I don't understand why my 1979-dated Z8002 is behaving like that, either. During my working career, I've worked with pre-production engineering samples with a long list of errata, but this flaw seems too serious to be released even as engineering sample.

I've tried many differnt ways of accessing the serial receive including memory mapped the receiver but IO map the transmitter. That arrangement actually worked well enough for me to go ahead and wire up the RAM. I was resigned to memory mapped serial port as the permanent solution until I stumbled across the indirect register access method. According to the databook, the CPLD can be reprogrammed 100 times. I have easily exceeded that limit trying different ways of working with the serial port!

CPLD latches AD[0] to produce A[0] and uses it to control upper and lower chip selects of RAM. A[0] is not involved with serial port interface.

I've tried both 3.68MHz clock and 1.84MHz clock for Z8002 and didn't see any difference.

I didn't "spin" on UART status bit because IN instruction is not working using direct addressing, so I can't read the status bit with IN instruction. When I did memory map of the receiver, I was able to spin correctly on UART status bit when UART status is accessed as memory.

The DataReady looped back to RdData is for moving data from serial port's internal register to data buffer thus reset the serial receiver state machine to accept next serial input. This implements the "double buffer" of serial receiver. I have used this particular serial port design for 5-6 years for different processors, so I'm fairly confident the serial Rx and Tx are working properly, but anything can go wrong, as any practicing engineer knows.

I've revised the CPLD design to correct a problem with RAM access. The current CPLD design has a serial loader in ROM that loads and runs 256-byte program in RAM. It is working well using register-indirect access of the serial port.
Bill
 

Attachments

  • Serial Loader ROM inside CPLD.jpeg
    Serial Loader ROM inside CPLD.jpeg
    106.3 KB · Views: 5
Dave,
Since you’ve expressed interests in the CPLD design, here is the entire design hierarchy.
Bill

Edit, Can’t attach the verilog file for CPLD ROM, so here is listing for ROMserload.v
——————————————————
module ROMserload(
input [5:1]addr,
output reg [15:0]ROMdata);
always @(*)
begin
//embedded Z8002 instructions in ROM
case(addr)
5'b00000: ROMdata = 16'h0000; //
5'b00001: ROMdata = 16'h4000;
5'b00010: ROMdata = 16'h0006; //
5'b00011: ROMdata = 16'h2105; //
5'b00100: ROMdata = 16'h0081; //
5'b00101: ROMdata = 16'h2104; //
5'b00110: ROMdata = 16'h0083; //
5'b00111: ROMdata = 16'h2106; //
5'b01000: ROMdata = 16'h0100; //
5'b01001: ROMdata = 16'hc93e; //
5'b01010: ROMdata = 16'h3e59; //
5'b01011: ROMdata = 16'h3c49; //
5'b01100: ROMdata = 16'ha710; //
5'b01101: ROMdata = 16'he6fd; //
5'b01110: ROMdata = 16'h3c59; //
5'b01111: ROMdata = 16'h2e69; //

5'b10000: ROMdata = 16'ha8e0; //
5'b10001: ROMdata = 16'heef9;
5'b10010: ROMdata = 16'h5e08; //
5'b10011: ROMdata = 16'h0100; //
5'b10100: ROMdata = 16'h0000; //
5'b10101: ROMdata = 16'h0000; //
5'b10110: ROMdata = 16'h0000; //
5'b10111: ROMdata = 16'h0000; //
5'b11000: ROMdata = 16'h0000; //
5'b11001: ROMdata = 16'h0000; //
5'b11010: ROMdata = 16'h0000; //
5'b11011: ROMdata = 16'h0000; //
5'b11100: ROMdata = 16'h0000; //
5'b11101: ROMdata = 16'h0000; //
5'b11110: ROMdata = 16'h0000; //
5'b11111: ROMdata = 16'h0000; //

endcase
end
 

Attachments

Last edited:
I also find it unlikely that such glaring errors would still be present a year and a half after these processors were launched on the market, especially since you have them from different production periods. A reasonable compromise is to run the boot programme and any tests that do not require reprogramming the CPLD. I find this topic intriguing because I expected to have more problems with the processor I am using, which is an illegal copy (apart from the heat dissipation issue, the UB8002 gets very hot, and I had to use a heat sink), but it works according to Zilog's documentation.
 
I'll take a look when I get a bit of spare time (or I get bored at work)!

I have a Z8001 somewhere - I might breadboard something up (if I can find it) when I am on holiday. However, I do have a more pressing software job to do. Fortunately, I am using the 'free' Arduino cloud-based IDE, so I am limited to 25 compilations per day. That forces me to do something else (like gardening :)!).

Since your bootloader works using register indirect I/O addressing - you should be able to boot a test program using direct I/O addressing from your host to test why this mode is not working. It is good that mapping the UART as memory did seem to work as anticipated, because that rules out the CPLD UART.

I see now what you are doing with the latch on the receive side of the UART.

It would be interesting to see what the AD and status lines look like during an INB with a direct address operand. Either the address output, status output or data input must be going wrong.

Just thinking outside of the box. At what point in time (relative to changing the control word from $0400 to $4000) did we check the INB instruction? My understanding is that if the control word does not have the bit 14 set, the instruction may 'fault' and, therefore not transact on the bus.

Dave
 
Last edited:
Just looking at the differences between the Z8001 and the Z8002 (apart from the obvious).

It looks to me as long as bit 15 of the initial Flag and Control Word (FCW) loaded from the reset area is clear (SEG=0) then the Z8001 should behave like a Z8002.

I remember reading that a Z8001 (in non-segmented mode) can execute the unmodified software of a Z8002 (found it, see below). However, when looking at the reset vector, I am not seeing the same address for the FCW. Unless I am missing something?

1755692338620.png

Dave
 
I’ve found out early on that IN and OUT instructions are privileged instructions so they need to be executed in system mode. So the processor status word was initialized to $4000 very early on. I think I may had a listing showing processor status word initialized to $400 by mistake, but because I manually copied raw instructions from program listing to verilog ROM file in CPLD, that mistake was detected and corrected while copying. So the ROM verilog file never had $400 for processor status word.

I’m able to serially load and run programs in RAM, so I have tried both register indirect and direct I/O accesses. The results were consistent with what I’ve encountered when the programs were in ROM. Another word, register indirect I/O works, but direct I/O doesn’t when programs are running in RAM.

This prototype board is soldered point-to-point. It is sufficiently complex that mistakes can be embedded in layers of wirings. The earlier prototype was also hand soldered point-to-point and has exhibited strange problems, but it was a significantly different design. Now I’ve had success with register indirect I/O, I will go back to the earlier prototype and see whether these strange problems were due to direct I/O, or perhaps something else. Maybe the earlier prototype can offer a clue to solve this problem.

Bill
 

Attachments

  • DSC_78530818.jpeg
    DSC_78530818.jpeg
    1.4 MB · Views: 5
This is the earlier prototype for Z8002 that was mentioned in this thread:


I've updated the design and tried the simple echo ROM code with direct I/O access for the serial port. It doesn't work. Then I changed to register indirect I/O access for the serial port and it works. So it behaved same as the other prototype. I'm still puzzled...

My plan now is enable the DRAM, install the serial bootstrap in CPLD ROM, load and run memory test for DRAM, enable the CF interface and install the CF bootstrap in CPLD ROM. Let see how far I can go with that plan.
Bill
 

Attachments

  • DSC_78550820.jpeg
    DSC_78550820.jpeg
    1.2 MB · Views: 4
  • DSC_78540820.jpeg
    DSC_78540820.jpeg
    1.2 MB · Views: 4
Juggling 2 prototypes are too much distraction, so I'm returning to the prototype used in the original post. It is a simpler design with static RAM, and it has sufficient prototype area to add additional logic.

I have added 8 LED driven by a latch in CPLD to help with debugging. The IO address for LED latch is 0x85 such that writing a byte value to 0x85 causes the value to be displayed on 8 LED. Another added feature is paging out CPLD ROM and replacing with RAM so the entire memory space is RAM after the ROM is paged out. The IO address for paging out ROM is 0x87 where any write to 0x87 causes the ROM to be paged out. Attached are updated board schematic and CPLD schematic.

Right now I have a simple serial loader in CPLD's ROM which can load an Intel Hex loader which, in turn, can load program in Intel Hex format. I've successfully loaded and ran a BASIC program translated from Z80 to Z8002. It ran the ubiquious ASCII mandelbrot in 5 minutes and 18 seconds. Other than the bugs associated with IN instruction using direct-access mode, my Z8002 seems to work OK with other Z8002 instructions.
Bill
 

Attachments

Congratulations on getting the device working. I have a question: what is the power consumption of this SBC and how hot does your processor get? I haven't managed to get a Zilog CPU yet and am still testing on a clone (I've already ordered one from China, but who knows what they'll send ;).
I also have a puzzle to solve, with the programme behaving differently depending on the location of the SCC initialisation procedure, and I want to compare this with Zilog. I do not want to use my Toshiba TMPZ8004 processors for this purpose, because they require a pull-up resistor to the /ABORT line, which is not present in the Z8002, and these processors with virtual memory support probably have newer masks. I am still puzzled by the question: why were Z8004 processors released if they could not work with MMU? I do not understand this move by Zilog.
 
Power consumption at 5V is 300mA while running ASCII Mandelbrot in BASIC. The power is roughly even divided between CPLD and Z8002. After 10 minutes of running Mandelbrot, the Z8002 is 44 degrees C and CPLD 46C. They are warm to the touch, but not burning.
I noticed “align 2” is used frequently in BASIC code. Have you tried align directive to put you code on different byte boundary?
Bill
 
Next function I want to add is a CF interface to support CP/M. I have designed a solderless breadboard-to-2mm-CF adapter so I’ll use it to interface to CF on my prototype.

I plan to change CPLD ROM so it loads and runs 512 bytes bootstrap code from master boot record of the CF disk which, in turn, loads either a monitor or an OS like CP/M.
Bill
 

Attachments

  • IMG_5698.jpeg
    IMG_5698.jpeg
    315.9 KB · Views: 3
  • IMG_5701.jpeg
    IMG_5701.jpeg
    390.2 KB · Views: 3
  • IMG_5702.jpeg
    IMG_5702.jpeg
    1 MB · Views: 3
The ‘align 2’ directive aligns successive program blocks to even addresses. In my case, the code (which always meets the evenness condition) and the SCC initialisation array consist of even elements. Something else must be happening here. I hope that the expected Zilog CPU will behave differently, because unfortunately my design is so packed that I do not have room to check it with a logic analyser. I have another option, which is to build a second prototype without using the DIN41612 connector and soldering a goldpin connector in its place, which will give me reliable access to most signals. I am in the process of building an analyser that has a greater number of inputs at the expense of resolution, which is not required in this case. My commercial 16-input model is a bit too small to analyse this type of processor, and those with more inputs exceed my amateur budget. Link to the project - https://github.com/gusmanb/logicanalyzer (0402 components pose a challenge for traditional soldering methods, but instead, these analysers can be connected together to obtain a greater number of inputs).

I am very curious about your progress with CF, as I have not yet begun preparations to implement this solution in my project (for obvious reasons described earlier).
 
The CF interface is at top right of the picture. Embarrassingly, I have to wire the circuit twice because I’ve accidentally cut the VCC wire to a RAM the first time. The board actually kinda work with RAM power cut, but will not pass diagnostic, so of course I thought the newly added CF circuit was to blame. Torn everything down only to find the cut RAM wire! At least wiring up CF interface the second time around is much faster.

I worried quite a bit about signal integrity of 16-bit CF interface, so all 16 data lines are sourced terminated with 100 ohm resistor. CF read line has the 100ohm/100pF filter, and I’ll start with slowest Cisco 64MB disk. CPLD for CF addition is done; CPLD resource utilization is 86%; it powered up without smoke and passed diagnostic. I’m ready to write CF test software. Fingers and toes crossed!
Bill
 

Attachments

  • IMG_5703.jpeg
    IMG_5703.jpeg
    2.5 MB · Views: 5
Making pretty good progress, then the power went out. I sure hope I’ve saved the file! I have a CF diagnostic that reads each sector twice and compare the two reads to make sure they are the same, then repeat for next sector. This is to check for signal integrity issue with reading 16-bit wide data from a fast CF disk. It works. Next was to write known patterns to multiple sectors and read verify, but the power went out.

Right now there are 6 utility trucks clustered around an electrical pole. This looks serious…
 
Power was restored while I slept. The power glitches have caused my lab computer not to boot, so I have to run system restore. Fortunately I’ve not lost data.

I now have a CF write/verify diagnostic that writes 16K of pseudo random numbers into 32 CF sectors then read verify the correct data are in the CF. I believe the CF interface is working correctly. I now have the necessary hardware to port CP/M to Z8002. I’ll publish the board schematic and CPLD schematic in next post.
Bill
 
Back
Top