Digital Adventures

Notes on programmable logic, tabletop games & other stuff

Blinkenlights

| Comments

Enough fluff, it’s time for some original content. In this first project, Blinkenlights, we’ll be making a simple Verilog program that blinks the lights on the microboard. While this isn’t the most exciting project in the world, it will serve as a good introduction to using the Xilinx ISE Project Navigator.

This guide (and all guides henceforth) assume that you have some knowledge of Verilog, or at the very least, an understanding of how hardware description languages differ from your favorite procedural language. I also assume that you have some sort of FPGA development board (ideally the S6 Microboard, but any Xilinx device should do) and have installed ISE WebPACK suite version 13 or 14, as well as the requisite drivers for your development board.

Project Setup

Launch Project Navigator. For me it’s nice and hidden in the start menu; Xilinx Design Tools - ISE Design Suite 14.1 - ISE Design Tools - 32-bit Project Navigator. Start a new project. Give it the name “blinkenlights” and set the location to some path that doesn’t contain spaces. The next step has numerous important project settings, so if you’re using a S6 Microboard, you should follow along carefully. The development board is None, Family “Spartan6”, Device “XC6SLX9”, Package “CSG324”, Speed “-3”, and the preferred language is, of course, Verilog.

Once that is done, right click in the hierarchy pane and select New Source (alternatively Project - New Source from the top menu). The source type is Verilog Module and name it “blink.v”. You can skip the next screen, “Define Module”, which is just a dialog for generating module inputs and outputs. To be honest, I don’t know why this exists; it does nothing useful in my opinion.

Let’s Write Some Verilog

Erase everything in blink.v that was automatically generated by the new source wizard and then paste in the following snippet:

blink.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
module blink(
  input clk,
  input rst,
  output [1:0] leds
  );
  
  reg [23:0] counter;
      
  assign leds = counter[23:22];
      
  always @(posedge clk, posedge rst) begin
    if(rst)
       counter <= 0;
    else
       counter <= counter + 1;
    end
endmodule

This simple program implements a 24-bit counter with asynchronous reset. The LED state is determined by the two most significant bits of the counter.

Next, right click on the blink.v file in the project hierarchy and add a new source. This source is an Implementation Constraints File, and it should be named “blink.ucf”. If you’re not using the S6 Microboard, this file won’t work for you. Instead, consult the master UCF or documentation for the board you’re using and update the pin locations accordingly.

blink.ucf
1
2
3
4
5
NET "clk" LOC = C10;
NET "leds[0]" LOC = P4;
NET "leds[1]" LOC = L6;
NET "rst" LOC = V4;
NET "rst" PULLDOWN;

I’ll be going into more detail about implementation constraint files in a later post, but suffice it to say that this file maps inputs and outputs of our top level module (blink) to to pins on the FPGA.

Coffee Break

That’s right, it’s synthesis time. With “blink (blink.v)”, our top module, selected in the project hierarchy, a number of possible actions should show up in the design pane below the hierarchy pane. Right click on “Generate Programming File” and select Run. This will automatically perform all the prerequisite actions (Synthesize and Implement Design) before generating the programming file. While this is running, connect the development board to your PC (if you’re using a microboard, this is the USB-A connector, not the USB-micro one). There might be a warning about “Result of 25-bit expression is truncated to fit in 24-bit target.” Feel free to ignore it; XST simply picked up that we’ll eventually have an overflow with our counter, which is expected.

Programming time

Double click on “Generate Target PROM/ACE File” and say OK to the dialog. Once you have connected your development board, double click on “Boundary Scan” in the top left pane. Next, hit ctrl+I, or right click the large white region and select “Initialize Chain”. Say No to the dialog asking about SPI/BPI Flash and click OK in the next dialog. At this point there should be an icon of a Xilinx chip in the large window. Right click on the chip, select “Assign New Configuration File”, and find the file “blink.bit” in the folder that this project lives in (I have no idea why iMPACT doesn’t automatically navigate to this folder when launched from Project Navigator; it works just fine when it is launched from PlanAhead). Say No to the next dialog about SPI/BPI Flash. Right click on the chip once more and select Program.

Now look at your board. Now back at me. Are your LEDs flashing? They should be. You did it! (Well, we did it together, but if you want to phone your parents with wonderful news about how you’re a natural when it comes to programmable logic, I’ll pretend I had nothing to do with your accomplishment.)

Wrap-Up

FPGA devices have volatile memory. What this means is that when you unplug your board from USB and plug it back in later, this blinking light program won’t be on there any more. You’ll need to reprogram the device with iMPACT. How do you make programs last, you ask? I’ll cover this more in detail at a later date, but to make a long story short, most development boards include nonvolatile flash or EEPROM memory that stores the configuration file for the FPGA. This storage element is what iMPACT was asking about in the two dialogs that we said no to. Why not make make this demo project permanent, you ask? It’s because writing the program to nonvolatile storage is painfully slow, often more than 10 minutes.

Next time

Buttons! And possibly switches!

Comments