Monthly Archive for September, 2010

Seven Segment LED Control FPGA Module

I was bored last night, so I decided to write up a small module for my Nexys2 that would allow me to easily control the 4-digit 7-segment LED display on the board. Quite simply, this module allows you to enter a single 16-bit number and the corresponding hex value will be written out on the display. You can also set any number of the four decimal points. There is another input mode as well: if you want to update just a single digit of of the array, you can give that a new value without disturbing the others. Here’s the obligatory photo:

You can download the VHDL module here. I’ve also written a small testing environment that takes the output of some UART like Digilent’s RS232 module and uses two bytes of data to set the corresponding numbers on the display.

The module is really simple to use. First, you may need to set the CLKDIVAMT value inside the module depending on your oscillator (I used a 50MHz oscillator); the internal clock divider simply just sets the refresh rate of the display (since we update one digit at a time, we must update them fast enough so that the user doesn’t see any flickering).

Next, when you instantiate the component, you’ll need to feed in your clock, a reset signal (I haven’t tested this, but it should set the numbers all to 0), and specify the output anodes and cathodes of the LEDs on your board (for a seven segment LED, I wired ctout(7) to the decimal point value). Next, you need to take care of inputting the data.

The easiest way to input data is to set useseg to ‘0’ and then feed in a 16-bit number into val and set wen (write enable) to ‘1’. This will push in new data for the display to show.

To enter decimal points, set or clear the corresponding values in dp and then use the wendp enable mask to perform an action. For example if you set dp <= "1101" and wendp <= "1110", the module will turn the decimal points on for the two most significant digits and turn the decimal point off for the third most significant digit, but it won't change the least significant because wendp(0) is 0. Finally, there is one other way to control the digits, using the seg{3,2,1,0} signals. With this mode, you can update a single segment without affecting the others. To do this, set useseg <= '1', seg{3,2,1,0} to whatever 4 bit values you'd like (again, you don't have to set all of them), and set wenseg to the mask of values that you want to change (it works like wendp -- if you set wenseg <= "1001", the most significant digit and least significant digit will be updated).

Nexys2 Board Testing

After ordering my Digilent Nexys2 eval board with a 500K-gate Xilinx Spartan-3E and a variety of I/O devices, I never got around to testing it (other than to use the factory-programmed image on the PROM). I brought it to my dorm when I moved back in a few days ago and have had some free time to play around with it.

This is just a very simple example. The board takes two bytes of input and then acts on the data. The first byte says which LEDs to modify (e.g. 11100000 would modify LEDs 0, 1, and 2). The second tells which value to set them all, as a number from 0 to 255. The data is then read into a controller that stores the new value and specifies the brightness of the LED via a PWM block.

Once I got that up and running, I just wrote a few macros that would allow me to set the LEDs. The “chase” macro simply sets an LED and then diminishes the ones behind it. The “grad” macro simply makes a gradient. Currently, I’m implementing Xilinx’s FFT core so that I can take the FFT of some serial data and control the LEDs as necessary.

My implementation can be found here (just create a new project, load this design in, with serpwm.vhd as the top level, and specify the pins: TXD, RXD, LEDS, and clk).