When I was a kid, I loved watching Knight Rider. Once I picked up FPGA design, I wanted to know how to make LED’s move and dim … just like KITT’s lights did.

If you are a beginner FPGA designer, this makes the perfect beginners project.

Walking through the LEDs

The first step requires simply walking through the LEDs. This is a very important step, as it demonstrates that all of your LEDs are properly set up, properly connected, and that they will turn on when requested.

In our case, we’ll do this two different ways. First, we’ll step the LED’s once each second. This way, there can be no question that the LED comes on at the proper time. Once that works, we can speed the process up, and make a cool LED demo.

To step through the LED’s one at a time, you can use the following code:

`default_nettype none
`define	FASTWALKER
//
module	ledwalker(i_clk, o_led);
	input	wire		i_clk;
	output	reg	[7:0]	o_led;

	// Remember the clock testing code?  This is very similar, only it
	// creates a PPS signal once per second--every time the counter rolls
	// over.  You could create this signal ever half second, or every
	// quarter second, by just dropping the number of bits in the counter.
	reg	pps;
	reg	[31:0]	time_counter;
	always @(posedge i_clk)
		{ pps, time_counter } <= time_counter + 32'd43;

	//
	// We then want to keep track of our state: which LED will be on
	//
	reg	[2:0]	led_posn;
	always @(posedge i_clk)
		if (pps)
			led_posn <= led_posn + 1'b1;

	//
	// Now, we turn on the one LED on corresponding to the state we have
	// chosen.
	//
	always @(posedge i_clk)
	begin
		o_led[0] <= (led_posn == 3'h0);
		o_led[1] <= (led_posn == 3'h1);
		o_led[2] <= (led_posn == 3'h2);
		o_led[3] <= (led_posn == 3'h3);
		o_led[4] <= (led_posn == 3'h4);
		o_led[5] <= (led_posn == 3'h5);
		o_led[6] <= (led_posn == 3'h6);
		o_led[7] <= (led_posn == 3'h7);
	end

endmodule

If you don’t want to type this in, you can find my version of this example here. You’ll need an ICO board and a PMod LED8 from Digilent to run it, although it’s almost generic enough to run on any FPGA board. If you don’t have that many LED’s? Either don’t turn them all on, or adjust led_posn to only cycle through the LED’s that you do have.

With a little work, I’m sure you could modify this example, so that the LED that was ON walked from left to right, and then back from right to left.

Dimming the LED

The next thing you need to know, once you can turn each LED on individually, is that you can “dim” an LED by turning it on and off faster than an eye can see. As you transition the LED from being more often on to more often off, the LED will appear to dim. As an example, try the following:

//
`default_nettype none
//
module dimmer(i_clk, o_led);
  input  wire i_clk;
  output wire o_led;

reg [26:0] counter;
always @(posedge i_clk)
  counter <= counter + 1'b1;

always @(posedge i_clk)
  o_led <= (counter[3:0] < counter[26:23]);

endmodule

If you don’t want to type this in, you can find my version of this here, written for the ICO Board.

The final design

You really don’t want me to give you the answer, now, do you? Without giving you a chance to do it yourself? Try doing it yourself first. Then, if you get stuck or once you’ve achieved your goal, feel free to look at my solution here. It’s a little more advanced than the ones above, in that it uses generic’s and for loops within Verilog, but the concept remains the same.

One problem I had using the “High-brightness” LED’s on the PMod LED8, was that it’s hard to see them actually “dim”. As a result, the Knight Rider effect is more substantial on another board, such as the Nexys Video or the Basys-3 from Digilent, since these use red LED’s that aren’t nearly as bright.