FPGAs In C With Cynth

Programming an FPGA with Verilog looks a lot like programming. But it isn’t, at least not in the traditional sense. There have been several systems that aim to take C code and convert it into a hardware description language. One of these, cynth, is simple to use and available on GitHub. You will need to install scala and a build system called sbt, if you want to try it.

There are limitations, of course. If you want a preprocessor, you’ll have to run it separately. You can’t use global variables, multiplication, floats, and many other pieces of C. The compiler generates a Verilog file for each C function.

A traditional C program executes one thing at a time unless you use special techniques on a multiprocessor. Even then, there is some practical limit to how many CPUs you will likely control. An FPGA, on the other hand, allows you to implement things that occur in parallel. For example, consider this:

while (1)

The out1 value is going to change a little bit before the value in out2. If you had a bunch of these, say up to out999, the delay could be significant. Equivalent Verilog code might look like:

always @(posedge clk)

This looks almost the same, but the outputs will change at the same time no matter how many there are. What’s more is that all the other things you can’t see will also happen at the same time. Just like a hardware AND gate doesn’t “scan” its inputs, an FPGA processes all of its inputs and generates outputs.

In the case of cynth, each C function creates a Verilog module that has the same arguments as the function along with another argument to stand in for the return value, if any. There will also be inputs for the system clock, a reset signal, and three control signals. One is an input that enables the processing. There are two outputs. One indicates the function is available to enable and another indicates a result is available.

The example provided with the code is a Cylon eye pattern that drives four LEDs. There are two external functions that are created with pure Verilog. The write_leds function drives the LEDs and a sleep function produces a delay.

The C code is a straightforward function named roving:

 while (1)
 if (dir && c == 8)
 dir = 0;
 else if (!dir && c == 1)
 dir = 1;
 if (dir)
 c <<= 1;
 c >>= 1;
 sleep(1000); // 1s

The corresponding Verilog files perform the same function as you can verify using a Verilog emulator.

If you want to dig into the generated code, you can find out more about Verilog with some projects. If C isn’t your thing, you could always try Python.

30 thoughts on “FPGAs In C With Cynth

  1. I remember looong time ago with some Altera synthesizing tools, they way you program (specially asignations) could produce different internal resource allocations ( latches, gates, metal vias, etc ) for almost similar results. I remember a teacher telling a story about he was contracted to optimize a design (firmware update) that was “bigger” than the chip in the already dispatched hardware. Dad end, he was able to shrink the design (gates fit) but there is no more available metal vias

  2. I am hoping that things like this cynth (cerilog?) encourages more people into HDLs.

    I personally chose VHDL because it was far less ‘program like’ compared to Verilog.

    Other than that I don’t get what this is good for? If you need a sequential process then you just use a micro-controller. If you need more speed and parallelism then you use FPGA.

    I could understand a HDL that had doted object notation (OOP) like JavaScript but only with objects, events, instances and perhaps inheritance.

    Really, HDL’s like VHDL and Verilog are *NOT* anything like a programming language. They’re a synthesis model.

    HDL should take off at some stage. It’s the cost and power consumption that makes it less competitive for most tasks. But for some tasks FPGA is perfect and a very good skill to have.

    If you have to do things at a very high speed you can use a very fast micro but often a very fast micro isn’t an advantage for the other tasks. OR you could use just a normal micro and drop in some FPGA/CPLD only for the high speed function.

    1. I personally use Verilog and sometime VHDL. But I can see the appeal to a developer who just wants to accelerate some function and doesn’t want to grapple with a new language. The real question is how the compiler converts your code into logic and does that suit your purpose or not.

    2. Might I suggest Chisel3 or SpinalHDL? Learn a little bit of Scala, pick up a tool that allows Bantamweight FPGA devs to hit like Heavyweights. It’s because of those two that you have RISC-V in hand and approachable.

  3. I remember using Handel-C years ago, The conclusion I came to is that it was a pretty poor concept, because it encourages you to think like a C programmer: linearly. That’s the *exact* opposite of how you need to be thinking when designing an FPGA.

    HDLs looking nothing like a normal programming language helps give the necessary headspace to avoid falling into comfortable and familiar traps.

    1. I’m a beginner with HDLs but all the books I’ve read stress that mistakes happen when the HDL is mistaken for a programming language. So to me, writing in C goes against this advice.

    2. My most elaborate models are co-developed in JavaScript (fast quick-and-dirty scripting) and VHDL.
      Very high-level synthesisers have been available for more than 15 years, that take a high-level description of a system (a pipeline for computing DSP terms for example) and provide various implementations to test speed/size/cost trade-offs. OK they are not cheap nor free but they existalready.

      Everybody is trying to reinvent the wheel instead of making the existing ones better

      OK, trying to make VHDL better is worse than dying in a swimming pool filled only with ducks : it’s ridiculous, painful and looooong. I tried in vain but I’m not well placed to change anything. But VHDL is already fucking powerful and despite its weird shortcomings, we can do mind-blowing things if we take the time to look at it.

      Take a deep look at GHDL and have fun with the hacks I added ( http://ygdes.com/GHDL/ ) then try to simulate the same systems with Verilog with code that is as elegant and flexible.

    3. Agreed there, I’m working at a place working on Golang to Verilog (and then some quality of life stuff like easy deployment to an FPGA hosted by AWS, because getting to Verilog is only half the battle). Golang’s got great features for parallelism, like one character change to make a function run in parallel and channels for communication. Makes way more sense than C imo but then I’m biased.

    4. Depends solely on what you’re calling comfortable and familiar traps. If you’re talking about viewing the system as software, if I’m using CLaSH (Synthesizeable HDL and HLS subset of Haskell- and it’s a REAL one.) I wouldn’t be falling into those “familiar” traps. HDL is both async and sync at the same time….so you can very much “fall into those traps” with Verilog and VHDL, but you’ve got the tedium that is worse that coding COBOL in the mix doing it.

      In the end, you MUST think in terms of sychnronous and asynchronous action, with it being predominately async, regardless of what you use.

      The notion of C/C++/etc. HLS is…heh…painful to contemplate because it’s flip-flopped and you end up with inefficient results from that process. (We won’t get into the fact that none of the FPGA vendors have managed to do very well with SystemVerilog or the test/system aspects of VHDL to date…why would you trust them with HLS? X-D)

  4. At least if you are installing scala/sbt, try chisel or spinalHDL instead. Far more elegant and modern, still a true HDL like verilog/VHDL.
    SpinalHDL seems the most promising of both (best feature set, true library), but chisel has more support.

      1. Seconded with SpinalHDL. “Support” is a relative concept. Chris is in the Gitter chat rooms for SpinalHDL and VexRiscv and there’s several other people (Myself included) in there most of the time as well. Chisel3’s got Berkeley working with it and enhancing it, but it’s slightly harder to use with some sharp edges that might bite you.

  5. I don’t think either C or Python is a good fit for FPGA’s its a completely different kind of programming, more akin to describing the output you want, making it *look* like C or Python is just going to make it much harder for beginners…

    1. It also encourages thinking in the same procedural mindset as C/Python, rather than the reactive & concurrent way that FPGAs actually work.

      VHDL and it’s butched Ada syntax aren’t that hard to learn.

    2. It also encourages thinking in the same procedural mindset as C/Python, rather than the reactive & concurrent way that FPGAs actually work.

      VHDL and it’s butched Ada syntax aren’t that hard to learn.

  6. “The out1 value is going to change a little bit before the value in out2.”

    If you use modern C compiler with optimizations enabled then there is no guarantee for that.

    1. Well, sure, but they will not happen simultaneously, in any event, unless you’ve done something with multiple processors and then your code doesn’t look like that anyway.

    1. Confusing people?

      Seriously, I have used both Verilog and VHDL extensively. I greatly prefer Verilog.

      VHDL does have some advantages — no such thing as a blocking statement in synthesizable code, none of this “reg vs. wire” nonsense (which goes away in SystemVerilog), no need for timescales, etc.

      However, Verilog is just much friendlier, especially since you don’t have to bother with separate entities and architectures. If you want to add a port, you only have to add it in ONE place (imagine that). I also prefer “7:0” instead of “7 downto 0” as it is much less typing.

      1. VHDL is a definitive language and Verilog is not. That is why we have System Verilog now. In VHDL definitions have to be completely definitive so there cannot be any ambiguity. In Verilog you can write code that is ambiguous. Ambiguous code is not possible in VHDL.

        So verilog is fine in a short test cycle like FPGA but I doubt very much that any, except the very most experienced with Verilog, would send it off to ASIC fab.

        You mentioned some aspects of VHDL that are quite annoying but it is still the case that VHDL is in use more than Verilog. In any case VHDL can be converted to Verilog but it isn’t always so easy going in the other direction.

        Each to their own I spose. I like VHDL because I have been around long enough that I find it easy to think in gates and register so it’s easier to image propagation delays and the effects on a clock hierarchy.

    1. Honestly, having played with and used SystemC. I think this project would be better if it supported the SystemC additions.

      Even Xilinix has there own proprietary C synthesis setup. They call it Vivado High-Level Synthesis, it supports C, C++, and SystemC.

  7. I haven’t tried out this particular tool for turning C into gates, but…. I’m going to throw in my $.02, because I heard the same arguments for VHDL/Verilog vs. full-custom transistor level design during my early years in the industry. I’ve worked on many chips where no two transistors were created equal and a lot of time and effort went into getting these relatively simple chips out the door. They looked, quite literally like works of art. We used to think that no automatic tool could do a better job of packing gates into place better than a real person.

    Well, we were right and wrong.

    We could pack gates by hand better, but the people using automated tools could get to market using Design Compiler a hell of a lot quicker with more functionality.

    Its not about shaving area, because gates are fast and cheap for most applications. Its all about getting more features integrated, tested, and working faster.

    These days — I use SystemC every day in my job, with behavioral Synthesis (Cadence’s Stratus tools) to produce RTL for FPGA’s and ASIC’s. While the syntax is C++, you do wind up writing code for synthesis like you’re writing hardware — there’s threads and library modules to support specific I/O timing behaviors. The tools do a pretty decent job of producing RTL. I implemented a USB Host stack in a few thousand lines of SystemC and converted it to gates. It works. I can maintain it. Its reasonably easy to read and maintain. I’ve learned to code the SystemC so that it produces good gates for the types of designs I do. My synthesizable code looks different than my non-synthesizable code. I’ve found that its pretty easy to pick up someone else’s code and make large changes with a small amount of learning and editing.

    I would recommend taking a look at what’s out there. The Xilinx tools, in particular, are set up to smoothly integrate block-level C/SystemC designs into a larger system that’s mixed with VHDL and Verilog.

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.