SOURCES
Xilinx — www.xilinx.com
XC3S50A; XC3S700A; ISE WebPACK;
Spartan-3A Starter Kit; Platform Cable USB
Saelig — www.saelig.com
CleverScope
module slide_to_led(
input sw0_in,
input sw1_in,
input sw2_in,
input sw3_in,
output led0_out,
output led1_out,
output led2_out,
output led3_out
);
reg led0;
reg led1;
reg led2;
reg led3;
assign led0_out = led0;
assign led1_out = led1;
assign led2_out = led2;
assign led3_out = led3;
always @(sw0_in,sw1_in,sw2_in,sw3_in)
begin
if(sw0_in)
led0 = 1;
else
led0 = 0;
if(sw1_in)
led1 = 1;
else
led1 = 0;
if(sw2_in)
led2 = 1;
else
led2 = 0;
if(sw3_in)
led3 = 1;
else
ed3 = 0;
end
endmodule
Note that I removed all of the explicit data type definitions. Doing that allows all of our port arguments (inputs
and outputs) to default to wire. We have already proven that
we can’t directly drive a Verilog wire with code alone. So,
we have to add something to our Verilog code to drive the
ledx_out wires. That “something” is a quartet of Verilog
registers: led0, led1, led2, and led3. To have the newly added
Verilog regs drive the Verilog LED output wires, we assign
each of the ledx registers to its logically associated ledx_out
wire. The rest of the if/else Verilog code remains the same,
sorta. Note that now we must write to our newly added
ledx registers as our ledx_out entries are now Verilog wires.
FPGAs are natural born counters. Now that we have a
grasp on FPGA I/O operations, let’s build on our Verilog
knowledge and code up an eight-bit counter that reveals
itself via the LEDs.
84 August 2008
BLINKING THE LIGHTS WITH VERILOG
The Spartan-3A starter kit is equipped with an
on-board 50 MHz oscillator. There’s no way we humans
can see a 50 MHz scan rate in the LED bank. So, we must
divide the incoming 50 MHz clock to produce a scan rate
that we can see in the LED bank. To keep things simple,
we’ll craft our clock divider to run on powers of 2.
Let’s shoot for a scan rate of around 10 Hz. That
means that we must divide our 50 MHz clock by
5,000,000. The divisor value in hexadecimal is 0x4C4B40.
The idea is to key our clock divider on an overflow of the
most significant bit. We can’t do that accurately with
0x4C4B40. So, let’s use 0x3FFFFF as our clock divisor.
We’ll count from 0 to 0x3FFFFF and reset our divisor
when it rolls over to 0x400000. Let’s do the math to see
what scan rate that will give us:
Scan rate = 50,000,000 Hz / 0x3FFFFF
( 4,194,303 decimal) = 11. 92 Hz
To double-check our scan rate math, let’s compute
the period of 11. 92 Hz and take a snapshot of the scan
rate with a CleverScope:
Period of 11. 92 Hz = 1 / 11. 92 = 0.084 seconds or 84 ms
Screenshot 1 confirms our scan rate. Here’s the Verilog
code that produced the waveform you see in Screenshot 1:
module led_cntr_code(
input clk,
output reg [7:0] led_out
);
reg [22:0] clk_divider;
always @(posedge clk)
begin
clk_divider <= clk_divider + 1;
if(clk_divider[22])
begin
clk_divider[22] <= 0;
led_out <= led_out + 1;
end
end
endmodule
There’s some new stuff in the LED counter code.
However, I don’t think you’ll have any problems figuring out
what our Verilog code is doing. Our 50 MHz clock is fed into
the FPGA via the clk input, which is assigned to an FPGA clock
input pin (E12). The LED output is defined as an eight-bit
(bits 7 through 0) register with each of its led_out LEDs
tied to an FPGA output pin as specified in Schematic 1. Our
23-bit clock divider register collects the 50 MHz ticks and
is reset every time the most significant bit (bit 23) is equal to 1.
At every clock divider reset, the led_out register is incremented and the LEDs reflect the value of the led_out register.
Note that our “always” sensitivity list is focused on the
rising edge of every clock cycle of the incoming 50 MHz
clock. Thus, this always loop’s contents are executed on