Hackaday Prize Entry: The Cheapest Logic Analyzer

There are piles of old 128MB and 256MB sticks of RAM sitting around in supply closets and in parts bins. For his Hackaday Prize project, [esot.eric] is turning these obsolete sticks of RAM into something useful – a big, fast logic analyzer. It’s cheap, and simple enough that it can be built on a breadboard.

If using old SDRAM in strange configurations seems familiar, you’re correct. This project is based on [esot.eric]’s earlier AVR logic analyzer project that used a slow AVR to measure 32 channels of logic at 30 megasamples per second. The only way this build was possible was by hacking an old stick of RAM to ‘free run’, automatically logging data to the RAM and reading it out with an AVR later.

This project expands on the earlier projects by using bigger sticks of RAM faster, with the ultimate goal being a 32-bit, 133MS/s logic analyzer that is more of a peripheral than a single, monolithic project. With a Raspberry Pi Zero, a stick of RAM, and a few miscellaneous logic chips, this project can become anything from a logic analyzer to a data logger to an oscilloscope. It’s weird, yes, but the parts to make this very handy tool can be found in any hackerspace or workshop, making it a great trick for the enterprising hardware hacker.

25 thoughts on “Hackaday Prize Entry: The Cheapest Logic Analyzer

  1. I had a quick look around here and there are about 50 old RAM SIMM’s / DIMM’s but not one of then is SDRAM. There is nothing older that DDR(1).

    I would assume that same can be done with newer RAM? Like DDR1 / DDR2?

    1. Oh my, wasn’t expecting this post… Thanks @Benchoff!
      I have looked into DDR a bit… There’re many hurdles, the largest as far as “free running” goes is that DDR++ only has burst-lengths of 8 “columns” which only equates to 4 clock/instruction cycles… It’s hard, but not impossible to fit many free-running instructions (like “read the next 8 columns”) in so few cycles. It’s *plausible*, and was kept in my plans throughout the first sdramThing…
      …until sdramThingZero, which requires use of the “Clock-Enable” line, which is only available with the necessary functionality on SDRAM (not DDR). Too bad :/
      One plausibility, in that case, would be to have a dedicated controller (an AVR?) between the DDR and the “host”… something to ponder, but not part of this design, which is intended to be as “transparent” as possible (logic-gates, passives, no dedicated controller besides the “host”).
      There’s also an alleged requirement of no less than a stable 85MHz that could be a hurdle…
      There’s also the weird logic and clock voltages, but that’s another thing entirely.
      (You have DDR SIMMs?!)

      1. My mistake. The “old pc ram” box is marked SIMM / DIMM DRAM. It’s probably been a very long time since it had any SIMMs in it.

        I had a bit of a read up on old PC RAM and I was surprised to see that the SIMM DRAM was about 70-80ns. You would be better of with a modern SRAM that are about 5-10ns.

        So yeah, SDRAM is the sweet spot between slow on one side and complex addressing on the other.

        Great project.

  2. I might actually try this someday!
    I have many older memory modules and figured that I could make a delay line for something. You guys are doing all the hard work for me. ;)

    Why didn’t [esot.eric] harvest a memory card slot from a motherboard?

  3. 133 MS/s isn’t really accurate. At least at the end of every row, you would need to terminate the current write burst, pre-charge (auto), reissue a command, and start a new burst capture. During those clocks, you are not capturing data unless you use a second stick of RAM and interleave. It’s a novel idea (and even better hack), but why not just use a small CPLD+SDRAM? That’s exactly what logic analyzers such as the DSLogic do.

    1. Indeed, that *would* be the case (terminate, burst, reissue, …) but with “free-running” that’s not the case.

      Here’s a quick overview (I know my posts/descriptions are overly-wordy):
      You take half the RAM and fill it with commands to be fed back to itself (to both halves).
      The commands, typically, are precharge previous bank, activate next bank, burst-read next bank. I call ’em “PAR.” If commands are sent at the right times, a burst of one page of data can be *immediately* followed by a burst from another page of data (in another, recently-activated bank). Commands can be issued to one bank *while* bursts are active on another bank, so back-to-back is no problemo (except, as I described, it might get exceedingly difficult when your bursts are small, as in only 4 clock cycles for DDR, which is largely why I’ve been sticking with SDRAM).

      Using one half of the RAM to “free-run” the commands allows the RAM to run at its full speed regardless of how slow your connection to your ‘host’ (Single-board computer, 8bit microcontroller, Parallel Port, whatnot) may be… That half of the RAM is, then, basically like a dedicated SDRAM-controller.

      As far as CPLD’s/FPGA’s, that question comes often, and again, this project is about transparancy/availability. No dedicated controllers, no architecture-specific firmware… Just simple logic chips and some passives… (well, and the SDRAM DIMM and a clock-source, etc).

      And then, despite the lack of any dedicated controller, this thing could be connected to your Commodore-64 and programmed in BASIC for all it cares, and still sample at the full 133MHz (if your wiring’s good ‘nough).

      1. PAR for free-running, PAW(rite) for sampling ;)
        The first half, filled with the commands, I call the “free-runner” the second half I call the “side-kick”. The side-kick stores the sampled-data. The “free-runner” is kinda like an FPGA-based SDRAM controller, it has to first be *loaded* with its “firmware”, then it does its thing.

        I suppose the “firmware” could be a binary-blob, but it’s much more understandable if it’s looked at at the higher-level, and then can be implemented from any programming-language…

        This is from memory, it might be slightly off…
        For each 1024-column page:
        At column 0: precharge the previous page’s bank.
        At column (1024 – CASlatency): begin burst-read at the next page’s bank (free-runner only, for sTZero)
        At column (1024 – CASlatency – ActivationDelay): Activate the next page in the next bank
        At column 1023: begin burst-write at the next page’s column 0 (side-kick only)
        Other columns filled with NOP

        (Interestingly, the act of activating/precharging a page results in its being inherently refreshed, and refreshing needn’t happen *nearly* as often as the manufacturers claim. So running a full sample-routine to fill the entire sidekick’s memory is enough “activity” to keep its entire memory refreshed during that time. And, then, by blocking the “side-kick’s” Chip-Select during the burst-write command, the free-runner can run continuously doing nothing but activating/precharging all pages in both the free-runner and the sidekick, which acts, again, like a continuous refresh, while never having to explicitly use a refresh command).

      2. That half of the RAM is, then, basically like a dedicated SDRAM-controller.

        Or like an old school state machine as when we built them using EPROMS and an 8 bit register feeding back the state, wasting most of the memory space. But this time is wasting almost *all* the space on the 50% of the control part! ;)

    1. yup yup! If you look at sdramThing4.5 and earlier, it outputs the entire waveform necessary to draw/refresh a frame on an LCD, in FPD-Link (7-bit serial, 4 signal lines). Load a different waveform, tie the bits to a DAC if you so-desire. Bam! Debated whether that functionality would be useful for sTZero… In the interest of fewer parts I’ve curbed the idea, but it could definitely be done.

Leave a Reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

This site uses Akismet to reduce spam. Learn how your comment data is processed.