Compiling C# Programs into FPGA Circuits: Factorial Example


This blog article gives a practical introduction to how C# programs can be compiled into FPGA circuits using the Kiwi system developed by myself and David Greaves at the University of Cambridge Computer Lab. Our starting point will be a C# program developed inside Visual Studio 2010 for computing factorial:

image

This program can be compiled and executed inside Visual Studio to report the factorial of 5 (i.e. 120).

image

However, using our Kiwi system this program can also be converted into a Verilog circuit. The program is decorated with some custom attributes which specify which static method should be turned into hardware; the number of bits used to represent input and output ports and how the circuit should behave relative to a circuit clock.

The generated Verilog netlist can be simulated using a Verilog simulator. The Modelsim simulator output produced by simulating this circuit with an input of 5 for the factorial circuit is shown below. After a few clock cycles the result 120 is produced and the done output bit goes high.

kiwi_fac_modelsim

Or if you like you can run the simulation on the command line:

image

The generated Verilog can be used as input to the Xilinx design tools to generate a programming bit-stream to program an FPGA. The screen-shot below also includes a top-level module which instantiates some debugging input and sets the default input to the factorial circuit to be 5.

image

The generated programming bit-stream can then be run on a real FPGA board. I used a Xilinx ML605 which has a Xilinx Virtex-6 XC6VLX240T-1FG1156 FPGA on it:

image 

I can check the functionality of the circuit by running a software logic analyzer on my PC which reports the value of internal signals of the circuit running on the FPGA.

kiwi_fac_chipscope

The logic analyzer shows that this circuit indeed computes the factorial of 5 to be 120 after 4 clock cycles. This circuit is running at 100MHz.

You can get a warm and fuzzy feeling by looking at the floor-plan of the generated circuit (light blue specks on the middle left hand side) which also includes the debug circuitry required to support the logic analyzer:

image

This lower-level view shows the actual routing tracks for the wires.

image

Comments (12)

  1. mg says:

    This is really interesting. What about hw-sw codesing? Can code be automatically partitioned?

  2. Satnam_Singh says:

    A veyr good question! We've considered cross boundary method calls which get implemented with FIFOs (using Xilinx's FSL link) where the software runs on a Microblaze processor and the hardware speaks to the processor using a protocol devised by Xilinx. However, we do not have anythying stable implemented right now.

  3. ben says:

    what are your thoughts on c to fpga software?  

    I know there's a few open source projects, but also commerical ones that have been around for  a while (impulse-c, catalyticinc/Celoxica,  en.wikipedia.org/…/C_to_HDL )

    Any experience with these?

  4. Sameer says:

    This is really interesting.

    Was there any performance overhead for using C#?

    Is it possible to make use of .net libraries on FPGA using kiwi?

  5. Satnam_Singh says:

    @Ben: I have experience of several "C to gates" tools but one of the many issues I have with them is their awkward support for capturing the inherently parallel nature of circuits. Often parallel circuit behaviour (timing) is captured with ad hoc language extensions and then you need to use a special language and compiler and tools. With Kiwi we decided to adopt the principle of not implementing  a new language: we simply use the existing .NET libraries for concurrency to *model* parallel circuit behaviour. Now you can use a regular C# compiler to compile and simulate your design although you will need the Kiwi C# compiler (hopefully released soon-ish) to generate Verilog.

  6. Satnam_Singh says:

    @Sameer: you can use any library methods that conform to the constraints for what we can synthesize into circuits. So currently things like static methods that behave in a C-like manner are supported although we plan to wider the language coverage to a wider class of operations and to dynamic memory allocation (by Microsoft website has a couple of papers that describe how to compile malloc/free to gates).

  7. Sean_Nguyen says:

    Hi Satnam,

    Where can I find the kivi tool software?  Does your tools support Altera FPGA Stratix board?  I'm really interested about convert C#… What the different your C# to Verilog?  Is this optimized code?

    Thanks,

    Sean

  8. I think you've done really great job here guys.

    Thank you very much

  9. Emmanuel says:

    Thanks for your great works……  can you write C#  technical analysis codes  for financial market and compile it with KIWI for FPGA Hardware ?

    Bravo !!!!!!!!!!!.

  10. salman says:

    sir!

    i have a project in xilinx and i want to make a GUI for it, in this case we will input data from gui which ofcourse in C# and xilinx will execute this input data….. kindly tell me that how can i do this, my email address is salmanahmad112@gmail.com , i will be very great ful

  11. rdengineer says:

    I’m usually skeptical on new technologies. In any given day I will work in several different languages, on different platforms. I have used VHDL, and LabVIEW FPGA to create large fpga applications.  I use C#, LabVIEW, C and VHDL regularly.

    I don’t believe this example at all, or at least I don’t believe that this example is doing what this article claims.

    There are a couple good reasons why I say this.

    1.) Compiler optimization shouldn’t allow any math at all for this circuit. Since all variables are known at the start of the program the compiler would do all math before the compiler is finished. In other words during the pre-processing of this program the compiler would already have recognized that n=5 and fac=1 at the start of the program. The compiler would have also seen that there are a finite number of iterations in the loop. This would allow the compiler to just create a constant for the output. So in the first pass of the compiler the code for FactorialCircuit() would have been translated to simply to

    Fac = 5

    Kiwi.pause()

    Fac = 20;

    Kiwi.pause()

    Fac = 60

    Kiwi.pause()

    Fac = 120

    Kiwi.pause()

    Counsole.WriteLine(“Factorial is 120”)

    Kiwi.pause()

    If C# compiler doesn’t do this, I know for sure that Verilog does this.

    The only reason that it would keep fac at all would be because the compiler would somehow know that fac is an output, and will remain until the next clock. I’m guess that’s what kiwi is doing. Yet somehow the modelsim output shows zero for the first iteration. I wouldn’t have been to surprise if it was a 1, but I don’t understand where the zero came from.

    2.) The Modelsim picture that you show has a 0.1ns period clock. That would place the clock frequency at 10Ghz.  That is really fast.  Why is the modelsim test bench running it at this rate? There is absolutely no chance that this code would synthesize at that rate.  Also, where is the modelsim testbench?  I see comments in the code talking about a testbench. Does kiwi create a vhdl testbench and then you use a tcl script to compile the testbench for the simulation (this is similar to how LabVIEW generates the VHDL testbench).  

    3.) I see no configuration for clock domains. This implies that even though the program is written in C# there is still much work to be done in the ISE Verilog project.

    4.) I do like the floor planning.

  12. Semyon says:

    Hello.

    Is this project still alive? Is it possible to get binaries or sources for research?

    Thanks.