Sign in

Not a member? | Forgot your Password?

Search blogs

Search tips

Free PDF Downloads

Performance driven FPGA design with an ASIC perspective

FPGAs!? Now What?

Architecture of FPGAs and CPLDs: A Tutorial

FPGA Implementation of Digital Filters

Recent Blogs on FPGARelated

Spline interpolation
posted by Markus Nentwig


[Comments] C HLS Benefits
posted by Christopher Felton


BGA and QFP at Home 1 - A Practical Guide.
posted by Victor Yurkovsky


Introducing the VPCIe framework
posted by Fabien Le Mentec


How FPGAs work, and why you'll buy one
posted by Yossi Kreinin


Learning VHDL - Basics
posted by Enrico Garante


Yet another PWM
posted by Anton Babushkin




Articles by category

See Also

DSPEmbedded Systems

FPGA Blogs > Christopher Felton > MyHDL FPGA Tutorial I (LED Strobe)

Christopher Felton (contact)
Christopher Felton's current favorite projects are implementing DSP digital circuits with MyHDL for FPGAs. More information @ show full bio

Would you like to be notified by email when Christopher Felton publishes a new blog?

  




Pageviews: 9967

MyHDL FPGA Tutorial I (LED Strobe)

Posted by Christopher Felton on Jan 31 2012 under Xilinx | Altera | HDLs | Tips and Tricks | Verification | Basics | Tutorials   

Introduction

Have you seen the latest FPGA offerings from 'X' and 'A'.  These latest devices are huge!  Even the devices that one can get for sub $10 are relatively large.  Because of the size of these FPGAs they are implemented using an HDL.  To manually configure each circuit would be a long and tedious task.  It is not feasible to program an FPGA by manually defining the logic for each LUT and manually connecting the logic blocks.  To implement (configure) an FPGA it is required to use an HDL or other high-level description or tool.  Software will translate the hardware descriptions to the bit configurations required to program the FPGA.

Note:  Yes, it is possible to program an FPGA schematically and build a hierarchy (similar to structural HDL).  This is rarely used, schematic design is used for small "glue" logic or top-level stitching of the blocks together.

As mentioned majority of FPGA designers and FPGA hobbyist will define their FPGA designs with an HDL (hardware description language).  For many people doing an FPGA project, if they have been introduced to an HDL in the past, they will choose Verilog or VHDL as their HDL.  They will select Verilog/VHDL because that is what they were taught.  But doing so they are missing out on another excellent HDL called MyHDLMyHDL is a Python package that allows digital hardware description in Python.

For reasons why you would want to use MyHDL see Why MyHDL.  Also, the MyHDL manual is a good reference.  Jan Decaluwe has done an excellent job creating and maintaining MyHDL.

The following is a tutorial using MyHDL to implement a design and run the FPGA tools generating a bit-stream for a development board.  This tutorial contains project files for the DSPtronics SignaX1 (SX1), Digilent Nexsys2, teraAsic DE2, and USBP boards.  The design of the HDL is board independent, for this design all that is required is a bank of LEDs and a clock.  The only board dependent constraints are the pin mappings and the clock frequency.  The generation of the constraints is handled by the conversion script, creating the FPGA specific constraints and running the tools are handled via Python as well (one-stop language for this tutorial).

FPGA Development Boards

Each of the development boards used in this tutorial have medium sized FPGAs and a bank of LEDs available.  The boards are development boards that I had laying around that made it easy to download the designs once the bit files were created.  As mentioned, for this tutorial everything after the design entry has been automated.  There is one script to create a bit file.  This does require that the FPGA tools be installed and accessible (path to the tools is in your PATH so that the script can access the tools).  Thanks to Guenter Dannoritzer for creating the Python script to run the Xilinx tools.  The script has been modified for this tutorial and the modified script can be found in the repository with the rest of the design files.

Prerequisites

To walk through this tutorial it is presumed that the MyHDL manual has been reviewed and/or one is familiar with digital circuit design, HDL design, and Python and willing to jump in head first!

LED Control

The circuit that will be described here is a simple LED control circuit. The module we want to define will strobe the LEDs on an FPGA development board.  If you are familiar with the 80s pop-icon David Hasselhoff's Pontiac Trans Am (or the recent version of KnightRider) this might look familiar.

http://bit.ly/wCHflu

KnightRider stroby

To implement the design we are going to define the behavior of the circuit in MyHDL.  We want to describe the behavior to strobe the LEDs back and forth at a constant rate.  We will outline the main components that need to be described.

On the development boards we have a clock.  This clock will usually run at some 10s of mega-hertz (MHz).  On the SX1 board the main clock is 48MHz, ufo400 48MHz, the Nexsys2 50MHz, and the DE2 50MHz.  The clock is the only input to our circuit.  Based on this single input we will describe the behavior to create this strobe effect.  The strobe will not operate at the frequency of the clock, the LEDs will shift at some rate much slower than the circuit clock.  One of the components that needs to be described is a clock counter.  A piece of logic that will count clock cycles and generate a pulse -much slower pulse- periodically.  This will indicate when the LEDs should shift.

MyHDL Short Introduction

At this point we will take a slight detour and take a quick look at a MyHDL module.  We will use the shift register as an example.  Describing a shift register in MyHDL is straight-forward.  We need to declare a signal of n bits. And use the shift operator.  The following gives the anatomy of a MyHDL module and implements the shift register logic.

myhdl_module_anatomy

MyHDL code example

The above code snip will simply set the collection of flip-flops to 1 (0001b in the above example) and shift the 1 to the left 1 bit on each clock cycle.

I did not implement a self checking testbench in the above example but I will below for the complete example.

Back to the Design Example

The previous section was a short introduction to MyHDL modules, that is, what is involved to describe a hardware block using MyHDL/Python.  We want to continue on with our basic design example.  We are defining a digital hardware block that will "strobe" a bank of LEDs.  The digital hardware will turn an LED on for a period of time and then move to the next LED.  A strobe is defined as the "ON" LED moving left or right at a defined rate.

stroby.png

Example LED strobe

The above, each line, is a snapshot in time.  The on LED will move one to the left or right.  When the on LED is the most left or right the direction will change.  The dummy LEDs are used so no LEDs are on when the LED goes off the end (the on is a dummy bit).  The number of dummies are the delay that will occur (x2) at each end.  In the above example 4 dummy bits are defined and the LEDs are on for .3 seconds.  The off delay will be 2*4*.3 = 2.4 seconds on each end.

At this point we have enough description of our design to capture important design parameters.

  • Frequency of the input clock
  • The rate the LEDs strobe
  • The number of LEDs in the LED bank (number of LEDs on the hardware development board)
  • The number of dummy bits (delay on the ends)

The above defines the parameters to our module and the following is the module definition using the design parameters.

def m_stroby(
clock, # input : sync clock
reset, # input : sync reset
led, # output : to IO ports, LED drivers
CLK_FREQ = 48e6, # clock frequency
LED_RATE = 333e-3, # strobe rate of 333ms
NUM_DUMB = 4 # the number of dummy bits on each side
):

From the above definition two inputs are defined, clock and reset. Also the LED bit-vector output.  Finally, the parameters for the module.  We have described the functionality, ports, parameters to the design.  Now lets look at testing the design.

Test

One of the big benefits of using Python/MyHDL as the HDL is that all the tools of the Python language are available for verification.  We are going to define a test before we actually code up the design.  The tests are basic, verify that the logic moves the "ON" LED to the right or left.  The test will monitor the LED port and verify that the LED is shifting.  The following code-snip shows the generator function to verify the LED movement and configured delay.

The above will monitor for one of the LEDs to be "ON".  When one of the ends is on it will determine the direction and keep track of the time (ticks) between the current led being on and the next on.

The complete test code-listing is here.   An object is used to wrap the design under test (DUT) and provide some common functions, e.g. clock generation.  The object will take the same parameters as the design (clock frequency, led rate, number of leds, number of blank leds).  The object will have a method that returns the generators needs to run the simulation, this includes the main design generator

The code referenced is the simulation testbench.  This will instantiate the design and verify that the LED is shifting back and forth. The testbench uses a generic template so that it can be used with the py.test unit test framework.  The instantiation of the device under test (DUT) is wrapped in an object so each test can share (not repeat) the instantiation code.  Also the portion of the code that verifies the LED and count is wrapped in a generator, this way different tests (configurations) can utilize the same functionality.  In other words, additional tests can easily be added.

Also, notice in the test_random it includes constraint random testing.  Python is a full-blown modern programming language and, essentially, is unlimited in the tools available for verification.

At this point if we copy the module def to a file called stroby.py (use pass in the body for now) and copy the test functions to test_stropy.py and include the import stroby at the top of test_stropy.py we can run py.test and it should fail.  If the test does not fail we have a problem.  Next we will fill in the logic for the design.

HDL

To describe our functionally we need our storage elements that we will call led_bit_mem.  We also need a counter to divide our FPGA clock down and generate an event to shift.  Basically, we need to describe a counter and a shifter with some states (shift left, shift right, change direction).

Below is the complete code listing for our behavioral model.

 

FPGA Tools

Now we have a couple other tasks to complete before we can download the design to the FPGA development boards.

  1. Convert the design to Verilog/VHDL
  2. Run the FPGA vendor tool chain (synthesis, PaR, bit-stream generation)
  3. Download the design to the FPGA development board

See the tool install page for more information installing the packages and tools.  Each of these steps can be run by the compile_stroby.py script.  This script will convert the design to Verilog or VHDL.  The script will execute the Xilinx synthesis, mapping, place and route, and bit file generation.  This was only tested on a Linux machine with Xilinx ISE 13.x.  The myhdl_tools package is based on Guenter Dannoritzer's original examples.

FPGA Vendor Tool Chain

We are not going to specifically review how to use the vendor FPGA tools in this tutorial.  If you are unfamiliar with the FPGA vendor tools the following links might be useful.

Projects for each of the development boards can be found here.

Download

Downloading the design will depend on the board and software tools used.  The USBP and SX1 have separate software programs to load the bit-files.  The nexsys2 and DE2 can be programmed with the vendor design software.

Video Slow Blinking on UFO400

 

Conclusion

This was an introductory tutorial using MyHDL as the design language for FPGA implementations.  Questions on this tutorial can be submitted in the comments section of this blog post.  As mentioned the full source code can be found in the BitBucket Repository.

If you have any questions or issues feel free to leave a comment in the "comment" section below.

 



Rate this article:
4.5
Rating: 4.5 | Votes: 4
 
   
 
posted by Christopher Felton
Christopher Felton's current favorite projects are implementing DSP digital circuits with MyHDL for FPGAs. More information @ LinkedIn.


Previous post by Christopher Felton: USB-FPGA : Introduction
Next post by Christopher Felton: Grandiose Delusions
all articles by Christopher Felton

Comments / Replies


pascor
Said:
This written description is great, including (and especially) "Why MyHDL", but the Python code is unnecessarily confusing. It needs to be written in the more modern Python style and many very basic comments added. There are cryptic, undocumented and therefore, unintuitive variable names representing... I can't figure them out !. A user of MyHDL needs to be proficient with *both* Python *and* FPGA design. This combination of skills is rare, so this code should be rewritten to a high Python style standard to properly demonstrate this hardware design example.
2 years ago
-1
Reply
Sorry, you need javascript enabled to post any comments.
cfelton
Replied:
@Ray Thanks for the comments. I am not sure what you might be referring to by "more modern Python". I will review the Python PEP8 again and see where I might have strayed. If you have some examples of "more modern Python" code I will gladly review and see if I can improve my Python style, if applicable. You could be correct, too many languages and a lot of time switching between Verilog, VHDL, Python, etc. so coding styles probably cross pollenated. I will heed the advice for future posts and see if I can modify the above. If you could give an example which variable names are the highest offenders that would also be useful. I do "shorten" names, instead of completely writing "memory" I use "mem". Don't know if this causes the confusion. But things like the "term" memory have to be taken in context. This will take some experience with designing FPGAs, e.g. in this case memory doesn't refer to external memory arrays (or internal) but rather a device that retains state (flip-flop / registers). Again, specific examples of confusing variable/signal names would be useful. Variable names and coding style can be a subjective and an art. I doubt I can style the code to meet everyones preferences.
2 years ago
+2
MalikM
Said:
Hi,
Thanks for the tutorial. In lines 29 and 37, how was the size of len determined?
Also, what determines what's an input, output or parameter? non of this is clear to me. Thanks
2 years ago
0
Reply
Sorry, you need javascript enabled to post any comments.
cfelton
Said:
The length of /led/ does not have to be declared in the MyHDL module. Python is a dynamic language. In general, the arguments to the Python function (MyHDL module) can be different types and have different attributes. But the only types that make sense are Signal(intbv), in this case.

We can call (instantiate) the module like this

clk = Signal(False)
rst = Signal(False)
led = Signal(intbv(0)[8:])
led_strobe_i = stroby(clk, rst, led)

Inside the /stroby/ module when /len(led)/ is evaluated it will return 8.

Because Python is dynamic we don't have to declare the "ports" as in, or out. The direction will be determined by the context (how the port is used). Generally, a port will only be used as an /in/ or an /out/ but the dynamics give us the ability to create some very moduler designs.
2 years ago
0
Reply
Sorry, you need javascript enabled to post any comments.
tariq786
Said:
A couple of things need attention

1) The following code-snip in the Test section shows no code snippet
2) In the MyHDL short introduction section, shift_reg function is referred to as generator. What makes this function generator needs to be explained? Is it something inside the body of the function or the decorator that precedes the function?
3) The choice of LED rate of 333ms is not explained?
4) Code organization on bitbucket needs to be explained. I mean isn't it enough to run examples/stroby /myhdl_tut1_ex1.py? If not why not? Why are other files needed like stroby.py and test_stroby.py

Good job though

5) On bitbucket examples/stroby/README.rst is empty
2 months ago
+1
Reply
Sorry, you need javascript enabled to post any comments.
cfelton
Replied:
Tariq,

Thanks for the comments.

1. There seems to be a technical issue, I use the embed feature
that is part of the bitbucket repository. I am not sure why
the code snips are not showing. I have added links to each
section where the code snip should be. Hopefully the embed
function will be resolved soon.

2. The *next* in the example is an attribute of the *Signal*
class. The *Signal* class is not a generator but the
*hdl_shift* function is a generator. The *hdl_shift* is
a generator because the *@always* decorator inserts a
*yeild* - hence making the function a generator.

3. The 333ms is enough delay so the LED is visible, if the
LED is on for too short of a duration the LED will not
be visible.

4. The repository file structure:
* myhdl_tut1_ex1.py, is the first nonsensical shift
example.

* stroby.py, is the LED strobe module

* test_stroby.py, is the testbench

* convert_stroby.py, converts the design to Verilog.

5. Thanks for pointing this out, I will add some text
2 months ago
0
Sorry, you need javascript enabled to post any comments.