Blinking LEDs with a Numato Elbert V2 FPGA

FPGA Development boards usually run on a high frequency oscillator in the tens or hundreds of Megahertz range. One way to toggle an IO line at a slower frequency is to use a counter circuit. I will show you how to write some Verilog code that divides down a high clock frequency to a more human friendly time scale, and blink some LEDs!

We will be using an affordable FPGA Development board called the Numato Elbert V2, which contains a Spartan 3 FPGA with 1584 logic cells. The FPGA is a little on the small side, but the board comes with a nice set of IO accessories for the price.

First, we must consider what clock speed this FPGA is being run at. This board has a 12 MHz clock on it, so each clock cycle has a period of T = 1/f 83.33 ns. We will design a register such that with every clock cycle it’s value is incremented by 1.

If our clock cycle is 83.33 ns, 225 clock cycles will amount to 2.796 s. If we design a register to be 25 bits wide, and it is incremented by 1 each clock cycle, it will overflow (reset) every 2.796 seconds. The bit below the MSB, the 24th bit, will change from o to 1 in 1.398 seconds and from 1 to 0 in 1.398 seconds. We will chose to blink the slowest LED at this frequency by linking the LED state to the state of the 24th bit in the register in our user constraint file.

To blink an LED twice as fast we simply hook up a second LED to bit 23. To blink an LED four times as fast we hook up a third LED to bit 22. We will hook up our 8 LEDs to bits 24-17 of our register, such that each successive LED blinks twice as fast.

Let’s look at the code.

module universalCounter
	#(parameter N = 25)

	// IO declarations
	(
	  input wire clk, reset, inc,
	  output wire [7:0] ledout 
        ); 
        // internal signals 
        reg [N-1:0] r_reg, r_next;

 

Our module is called universalCounter, and has a parameter N=25 which corresponds to the width of our register we will invoke. Our circuit will have 3 input wires: clk which will be routed to the on board 12 MHz clock, reset which will asynchronously reset the counter, and inc which will activate the counter, letting our LEDs blink. Output array q will route our output from the register to our LEDs.

We next declare two reg arrays which will be used in the register and next-state logic blocks.

	// register
	always @(posedge clk, posedge reset)
		 if(reset)
			r_reg <= 0;
		 else 
			r_reg <= r_next; 

 

Our register behavior is invoked in an always block. The if-else statement invokes a priority routing network, where if the reset input gets a positive edge then 0 is routed to r_reg, else r_next, the next state of the register, is routed to r_reg on each positive clock edge. If we think of the register as being composed of D flip flops, every positive edge of the clock cycle will have the next state of the register stored in it, with r_reg being like q and r_next being like d.

	// next state logic 
	always @* 
               if (inc)
                 r_next = r_reg + 1;    // increment
	       else 
		 r_next = r_reg;        // unchanged

 

The next state logic always block invokes a priority routing network where if inc is asserted, then then r_reg + 1 adder circuit is routed to r_next, incrementing the value stored, else r_reg routes to r_next, and the register remains unchanged. This determines what the next state of the register will be at each positive edge of the clock.

	// output logic 
	assign ledout = r_reg[24:17];

endmodule 

 

Lastly bits 24 through 17 are routed to the output q, which will be set to the 8 LEDs in our constraint file.

module uc_test
	(
	   input wire clk, reset, inc,
	   output wire[7:0] LED
	);
	
	universalCounter uc_unit (.clk(clk), .reset(~reset), .inc(~inc), .ledout(LED));
	
endmodule 

 

Finally we have a test module that has our IO variables we will set in the user constraint file. We invoke our universalCounter circuit and route the IO to it. Note that the complement of reset and inc are used, as the pushbuttons on the Elbert board have pullup resistors and are normally asserted.

NET "clk"        LOC = P129  | IOSTANDARD = LVCMOS33 | PERIOD = 12MHz;
	 
NET "reset"      LOC = P80   | PULLUP;
NET "inc"        LOC = P76   | PULLUP;

NET "LED[7]"     LOC = P46;
NET "LED[6]"     LOC = P47;
NET "LED[5]"     LOC = P48;
NET "LED[4]"     LOC = P49;
NET "LED[3]"     LOC = P50;
NET "LED[2]"     LOC = P51;
NET "LED[1]"     LOC = P54;
NET "LED[0]"     LOC = P55;

 

For completeness the user constraint file used for this circuit on the Elbert V2 is listed above, linking the IO variables to the pins on the FPGA.

The blinking LED behavior is shown at the beginning of this post. As you can see, the left most LED is controlled by the state of bit 24 of the register, which has a period we designed to be 2.796 seconds.

Using my oscilloscope to probe the IO line tied to bit 24 shows the designed period.

Probing the IO line tied to bit 23 shows that is has half the previous period, therefor the LED to the right of the first one blinks twice as fast.

 

This continues down to the last LED which is tied to bit 17 of the register and has a period of 2.796 / 27 = 21.8 ms! Bingo!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s