Showing posts with label FPGA. Show all posts
Showing posts with label FPGA. Show all posts

Monday, February 26, 2024

Internal data bus pre-charging

I "discovered" an interesting feature in the i4004 internal data bus management this weekend. Maybe the rest of you already discovered this, but it's new to me.

With the Scrachpad Register board working with my test program, I decided to mate it with the Instruction Pointer board I built in 2012. One of my goals was to see if the CLK1 and CLK2 circuits would ring, or if the rise and fall times are slow enough to avoid problems. To my great relief, I see no significant undershoot or overshoot on these circuits, and no ringing at all. Whew!

However, my logic analyzer showed some suspicious timing on the internal data bus. At first it wasn't clear to me what was happening, so I probed around a bit with my oscilloscope. As I was making notes of my observations I realized what was happening, and this also explained a bit of circuitry in the original chip I didn't previously understand.

Sunday, July 19, 2020

More latching mux timing problems

As I mentioned in the previous post, my timing problems seemed to be related to the timing between the output of a mux and the latch intended to capture the output of the mux. Here's a simpler example.

This is the mux in the instruction pointer that determines whether the Effective Address Counter or the Refresh Counter is used to select the active DRAM row. Counting from the top left, the first two signals are the mux selector inputs: the subcycle X12 and X32 signals. The middle pair are the Refresh Counter outputs, and the right-most pair are the Effective Address Counter outputs.

During subcycles X12 and X22, a DRAM row is read and written back unmodified to refresh the row. Thus the Refresh Counter outputs are selected to drive the DRAM row decoder at the beginning of subcycle X12. For the rest of the instruction cycle the Effective Address counter needs to drive the DRAM row decoder, so it is selected at the beginning of subcycle X32.

Rather than have the selected counter actively drive the decoder continuously, this is a latching mux: when the selector signals are inactive, the previously-selected counter outputs are latched.

Friday, July 17, 2020

Latch timing failure

I think I found the problem in the i4004 CPU instruction pointer incrementer. And it doesn't bode well for the latch-based implementation.

Here's the problem. The instruction pointer DRAM is configured as four rows of 12 bits, each row representing one of the four instruction pointers. The normal cycle is:
  1. Pre-charge the DRAM column sense lines.
  2. Read all 12 bits of the active IP into a 12-bit register.
  3. Gate the low-order 4 bits onto the data bus.
  4. Add 1 to the low 4 bits, saving the carry out.
  5. Update the low 4 bits of the register.
  6. Gate the middle 4 bits onto the data bus.
  7. Add the carry to the middle 4 bits, saving the carry out.
  8. Update the middle 4 bits of the register.
  9. Gate the high 4 bits onto the data bus.
  10. Add the carry to the high 4 bits.
  11. Update the high 4 bits of the register.
  12. Write the 12-bit register back to the active IP.
Here's what Step 5 looks like in behavioral simulation. On the bottom we have the least significant bit output of the adder. The short (400ns) pulse in the middle is the write enable for the low 4 bits of the 12-bit register. Above that is the LSB of the 12-bit register itself.

Next let's look at the post-map simulation with the same arrangement of signals. The LSB of the adder becomes a 1 much later than in the behavioral simulation, and goes back to a 0 much sooner. How much sooner?

Here's the same post-map simulation, zoomed in at the falling edge of the write-enable. The adder output falls 25ps (that's picoseconds, or 0.000000000025 seconds) before the gate enable goes inactive, but that's long enough for the latch to capture a zero rather than a one. Bummer.

The problem appears to be in the way I've coded the 12-bit temporary register. This register (really charges on MOSFET inverter gates in a real i4004 CPU) is written from three non-overlapping sources. Because of the way the circuitry is implemented, any of these three can set the register content without conflict.

In an FPGA, this is implemented using a mux to select an input source and a storage element to retain the value. Since I coded the input selection logic as implemented in the real i4004 CPU, the mux selectors and the latch gate are driven by the same signals. In this case, though, the mux output is changing 25 picoseconds before the latch gate has gone inactive, and the latch captures the wrong value. This is why most modern logic uses clocked flip-flops rather than latches.

The challenge I face is to separate the mux selectors from the latch gates such that the mux outputs are stable before and after the latch is enabled. This is turning out to be non-trivial.

Wednesday, July 15, 2020

Fixing combinational loops

As part of the conversion from edge-clocked flip-flops to transparent data latches I re-coded my i4004 counter module. This resulted in several warnings about combinational loops, but those warnings were buried in a sea of warnings about my use of data latches. It seemed to work well enough when implemented for the Spartan-3E, and I assumed it would work well enough on the Spartan-6.

I was wrong.

Monday, June 29, 2020

Wire, Tri, and Wor

Earlier today I cleaned up the VFD driver and the keypad remapping code so it was consistent with the rest of this project's code, and updated the top module for my P170-DH rebuild. Behavioral simulations ran fine, and synthesis and implementation gave only the expected warnings, so I decided to load it into the hardware and see how it ran.

At first I was pretty happy. The VFD displayed a single zero in the right-most digit, with the decimal point illuminated to just the right of the zero. The VFD driver reads the WR register, which is stored in RAM 0 register 1, via a dual-port interface to the RAM. Since an i4002 RAM clears itself to zeros while the reset input is asserted, this is what it should display. Unfortunately, that was the last part that worked as expected.

Wednesday, May 13, 2020

An MCS-4 Digital Clock

Who needs yet another digital clock? Haven't we all done this before?


I did something like this in PIC-16 assembly language when I first connected my Microchip PICDEM-2 reference board to an LCD in 1999. (Anyone need a UV EPROM eraser?) I did it again in Verilog when I bought this Digilent Spartan-3E Starter board in 2009. But this digital clock is special: it's written in Intel MCS-4 Assembly language, and it's running on my emulation of an Intel 4004 CPU.

Tuesday, April 28, 2020

Choosing the right FPGA for the wrong reasons

I finished changing my i4004 emulation from using edge-clocked flip-flops to level-sensitive data latches. I haven't even tried simulating it yet, but just for fun I ran it through the Xilinx toolchain to see what sort of resources it required. As I suspected it's quite small, occupying all or part of 9% of the available slices in the Spartan-6 LX9 FPGA.

With that in mind, I got to wondering if this would have fit into a Lattice iCE40. I'd touched on this a few years ago in the post Packing worms into a can, but I don't think I ever tried running the i4004 CPU emulation through the Lattice iCEcube2 toolchain. Today I did, and the results of that were eye-opening in ways I didn't expect.

Friday, April 17, 2020

i4002 RAM emulation development

Most of my recent tinkering with my Verilog implementation of the Busicom 141-PF calculator has been focused on the i4002 RAM chip bus interface logic. Because the i4004 was limited to a 4-bit data bus by Intel management, the i4002 (and i4001 ROM) have to pay more attention to the bus traffic than one might expect, which complicates the bus interface.

For example, the way the i4002 distinguishes a register write from a register read is by monitoring the data bus during the M2 cycle and decoding the OPA portion instruction being fetched from the i4001 ROM. This isn't terribly complex logic but it requires a thorough understanding of the operation of the data bus, as this is not explained in the datasheets.

Wednesday, April 8, 2020

Load testing the AC Mains supply

In the previous post AC Mains power supply I asked, "I wonder what will happen when I fire up the VFD filament and +30V supplies, plus a complex FPGA design?" Well, there's no time like the present to find out.

What I did was to take the printer test I described in the post Testing the printer interface and added the VFD display test I described in the post Proof of Life. The two don't interact so this was easy to do.

With the bench output supply set to 7.5VDC, the board draws about 124mA. This varies depending on how many digits and segments of digits are illuminated.

Monday, April 6, 2020

Testing the printer interface

In November I tested a prototype of my FPGA interface to the M32-TL printer using the Lattice iCEblink40-HX1K and a circuit assembled on solderless breadboard, described here. Since this worked well I was pretty sure this would also work on the P170-DH replacement board. But there is always a chance something didn't get laid out correctly, or something I overlooked.

When I put the replacement PCB into the P170-DH shell last month, I decided I really didn't want to be taking the board out again if I could help it. All the logic is on the exposed side of the board, and removing it requires removing 20 small screws. So I also connected the AC mains transformer and the printer. After proving out the keyclick sounder, the last untested subsystem was the printer interface.

Saturday, January 18, 2020

Emulating old tech in an FPGA

When I started this project I had a couple of goals. The first was to learn about CPLDs and FPGAs, and how they were programmed using HDLs like Verilog and VHDL. My second was to understand how the i4004 CPU functioned internally, and recreate one in an FPGA. Somehow this second goal morphed into a third goal, which was to build an i4004 CPU from discrete components.

But my prime focus has always been on the learning, not on producing a result.

Monday, January 6, 2020

The best laid plans

When I decided to add an external interface using PS/2 compatible 6-pin mini-DIN connectors, one of the ideas was to be able to interface it with my Digilent Spartan-3E Starter board (on sale now, btw) which has a PS/2 connector. Rather than connect it to the FPGA with resistors, I decided to use SN74LVC1T45 level translators in a configuration taken from the Digilent PmodLVLSHFT level-shifter:
One of eight channels of the PmonLVLSHFT circuit

Friday, January 3, 2020

Proof of Life

I got tired of taking baby steps. Here is the VFD in operation on the replacement PCB:


Supplied with 5 VDC, the board draws about 205 mA in this configuration. The digit values are hard-coded, and I haven't coded the RAM-based implementation described in the previous post.

The odd brightness variation is a beat frequency between the VFD's refresh rate (5.85 ms or ~171 Hz) and my phone's camera. It's not visible to the naked eye.

Sunday, November 10, 2019

FPGA Power-On and External Reset

As I whittle down the list of things that need fixing before sending my PCB out for fabrication, I came to the question of how to make sure the FPGA resets cleanly on power-on, and how to force a reset externally.

The Xilinx Spartan 6 avoids many of the requirements for strict power-on sequencing by including an internal power-on reset circuit. This holds the reset of the FPGA circuitry in reset until all three power buses (Vccint, Vccaux, and Vcco2) reach operating levels. However, this requires the power supplies to meet certain ramp timing: the supplies must ramp up monotonically and must reach operating levels in 0.20 to 50.0 milliseconds.

Monday, October 14, 2019

EP-102 to M-32TL Glue logic

I decided to spend some time this weekend moving the interface to the Epson M-32TL printer forward.

The Busicom 141-PF calculator had a Shinshu Seiki (the predecessor of Epson) Model 102 drum printer. A drum printer has a cylinder (or drum) with rows of characters embossed across its width. The drum spins at relatively high speed, while a set of hammers on the other side of the paper presses the paper against the drum's surface at the right moment to print the desired characters. A full revolution of the drum is required to print all the characters on the line.

Here's a picture of a Shinshu Seiki Model 102 printer:


Since this printer can print 18 columns, it has 18 separate print hammers. Thus the i4004 software generates 18 signals in parallel using a pair of i4003 shift registers to activate the correct hammers at the correct time.

The Epson M-32TL printer, on the other hand, prints one character at a time by moving the print mechanism across the paper from right to left. Obviously some translation is required.

Tuesday, May 2, 2017

Interfacing a VFD with the Busicom emulation

Hey! Something related to the Intel 4004 for a change!

The Busicom 141-PF calculator didn't have an electronic display; its only output mechanisms were the printer and three lamps that indicated an overflow condition, a negative result, and a value stored in memory. Here's a photo of the keyboard of the 141-PF; you can see the indicator lamps along the top edge to the left of the power switch:


The Canon P170-DH calculator I selected as my base for this reconstruction has a Vacuum Fluorescent Display tube that can display 12 numeric digits plus "E", "M", and a minus sign in place of a 13th digit. Aside from not being able to display all 14 digits the 141-PF supported, this is a pretty close match. But how to make use of the display?

Some good news re Lattice

After bad-mouthing Lattice for dropping support for the USB programming interface to their iCEblink40 demo card, I got down to the business of coding my VFD Driver test board test driver.

For those who are insistent about using open-source code to the exclusion of all commercial products, there is an open-source toolchain for the iCE40 series of FPGA: Project IceStorm. That's really cool. If I was looking for an interesting hobby project this might be one, but I already have way too many irons in the fire as it is. Thus I'm using the Lattice-provided IceCube2 development environment.

IceCube2 is a fairly simple wrapper around your choice of two synthesis tools: the Lattice Synthesis Engine (LSE) and Synopsys Synplify Pro. LSE is part of the basic (free) license, while it appears that Synplify requires an extra-cost license. A "performance limited" version of Aldec Active-HDL is provided for simulation and debugging. Active-HDL is a major player in the Verilog/VHDL simulation market, and even the cripple-ware version appears to be on par with Xilinx Isim.

Normally I'd be saying "But Active-HDL won't run under Linux!" at this point, but I found a listing for it in the WineHQ database that gives it a Platinum rating. For non-geeks that means it appears to run very well under the Windows emulation environment in Linux.

I haven't tried to synthesize anything yet, but I may reconsider whether I want to put a Spartan-6 LX4 or an iCE40-HX4K in my calculator rebuild.

Friday, April 28, 2017

LatticeSemi Brokenness

While I'm ragging on vendors for their stupidity, let me turn my attention to Lattice Semiconductor and their broken support for their own demonstration boards.

I've previously written about the Lattice iCEblink40-HX1K demo board. This little board sells for $40 and has several Pmod compatible interface ports. When I designed my VFD Driver test board I decided to use this demo board (which I already own) to drive it. Now that the test boards are in fab I thought I'd load the latest iCEcube2 development environment and get started on some Verilog.

I'd forgotten that the last time I tried to program this board I failed to get their programming software to talk to the board, despite it having a USB programming interface on the board. This time I read the documentation more closely, and discovered that they dropped support for the on-board programming interface in 2014. Seriously? They expect you to buy one of their programming "cables" (pod) for $162.50 to program a $40 experimenter's board?

Searching the 'net I found two documented solutions. One is to load an older version of the development environment. The other is to use a set of completely open-source tools to synthesize, place-and-route, and program the chip. I'm going to use the former for simplicity.

A third possibility may be to use the Adept programming software from Digilent, as it seems Lattice used their tech for the programming interface on the iCEblink40 series of demo boards.

The newer iCEstick and iCE40-HX8K breakout board uses a non-proprietary FT-2232H for the USB interface, and doesn't suffer from this stupidity. If you want to play with a Lattice demo board, avoid the iCEblink40 series!

Monday, May 23, 2016

Choosing an FPGA for board six

I've been thinking a lot about a sixth board to support an FPGA to assist in debugging and emulating the rest of a complete system (like a Busicom calculator). I'll still put a connector on the I/O & Timing board so the CPU can be interfaced directly to external logic, but having the ability to access inter-board signals and emulate missing parts of the CPU seems worth the effort.

When I first started this project, I used a Xilinx Spartan-3E FPGA development board for this, but it only provided 40 I/O signals. I thought about building my own board with the same FPGA, but it seemed a bit pricey and complicated to interface (three supply voltages with rigid power-up timings, etc). Thus I looked around and found the Lattice iCE40-HX series.

In the years since I started this project, the FPGA world has changed. Xilinx came out with their Spartan-6 series, which can run with two voltage supplies without stringent order or rise-time criteria. The parts have also become denser and cheaper ($16 vs $22). The iCE40-HX4K is still a bit less than half that price ($7), but when considering the cost of the PCB and the components required to support the FPGA (voltage regulators, SPI Flash ROM, level-shifting FETs) the difference in the cost of the FPGAs is noise.

I've decided to use the Xilinx Spartan-6 LX9 (144-pin TQFP) rather than the iCE40-HX4K. Why? In a word: Tools. I'm much more familiar with the Xilinx tool chain, and the iSIM simulator runs under Linux. The Aldec simulator provided by Lattice is a fine tool, but it only runs under Windows.

I need to finish pinning out all four remaining boards before I lay out the debug board, but I'm almost finished creating the Eagle library parts I'll use, and have most of the other components selected.

Saturday, April 2, 2016

EP-102 emulation

One of my goals, like so many i4004 hobbyists, is to recreate the Busicom 141-PF calculator. This was a printing calculator, using one of the earliest small digital printers from the company that became Epson. Some have done it with a compatible printer while others have used microprocessors to scan the hammer driver outputs and convert the results to ASCII.

I'm a professional software engineer, and have been writing software since learning Fortran in 1977. While I've written a fair amount of code for hobby projects it's not something that excites me anymore. Verilog and VHDL, on the other hand, are interesting to me because they require a different mindset and I love learning new things.

So I set out to develop an EP-102 emulator that would print on the Epson M-32TL printer in the Canon P170-DH calculator that I planned to cannibalize. Since I've been unable to find a datasheet for the M-32TL, I decided to put that off a bit and generate ASCII output on a serial interface. I can also emulate the keyboard with a serial interface, allowing me to run the real 141-PF firmware in an FPGA emulating the entire system while using a PC for input and output.

There are a lot of UART implementations available in VHDL and Verilog, but I wanted to write my own. Since I'm not looking for a full 16550 emulation it only took a few evenings to code and debug, including testing it on a Spartan-6 reference board. I'd hoped to test it on the Lattice iCE40-HX8 breakout board, but I'm having a minor but blocking issue with USB configurations (udev rules to disconnect one of the FT2232H interfaces from the serial driver, if you're curious).

Then I turned to emulating the EP-102. This is a tiny drum printer with 18 columns and 13 sectors per column. From the left, the first 15 columns can print the digits 0 to 9, a decimal separator (period or "full-stop"), or a "minus" sign. The 16th column is non-printing, and the 17th and 18th columns have various special characters. (This raises a problem with my plan to use the P170-DH, as it has a 12-digit printer. Maybe I'll replace the 12-digit VFD with a 20-character LCD or LED instead.)

When Tim McNerney analyzed the 141-PF for the i4004's 35th Anniversary he included notes on the operation of the EP-102. From these I constructed a Verilog module that looks like an EP-102 on one side and outputs a stream of ASCII characters when the "paper" is advanced on the other. This took another few evenings. I still have a bug in the synchronization of the sector timing (e.g. when I try to print 1s ASCII 2s are generated) but it's getting close.

I'm thinking it might be fun to create a "141-PF on a board" using the iCE40-HX8K breakout board, so I decided to build it for the iCE40 to see how big it is. Including the EP-102 emulation, UART transmitter, and a simple test "top" module I'm using 458 of the 7680 logic cells, or about 6%. To create a full system I'll need to add a 4004 CPU, 5 4001 ROMs, 2 i4002 RAMs, 3 4003 shift registers, the UART receiver, and the as-yet unwritten ASCII-to-keyboard converter. Will it fit? Stay tuned!