My First FPGA Project — Larson Scanner
- June 15th, 2011
- Write comment
I’ve decided to take a little break from MSP430 and learn something new. FPGA’s have always intrigued me, so I picked up a Nexys 2 from Digilent and started reading a book called FPGA Prototyping by Verilog Examples by Pong P. Chu. (That reminds me, I still need to finish Pong for the MSP430.)
I read several chapters to familiarize myself with the hardware and language, but nothing beats learning by doing. My summer construction job was rained out today, so I decided to grab a Rockstar energy drink and write my first Verilog project. I figured a Kitt light/Larson Scanner/Cylon eye would be something I could figure out in a few hours. I’m not too sure how “correct” my code is, so I’d love to hear some suggestions.
module main
(
input wire clk,
output wire [2:0] position,
output wire direction,
output wire [7:0] Led
);
// symbolic state declaration
localparam rising = 1'b1,
falling = 1'b0;
reg [24:0] position_state_count, brightness_state_count;
reg dir_state_reg, dir_state_next;
reg [2:0] position_state_reg, position_state_next;
reg [3:0] brightnesses [7:0];
// reg [2:0] brightnesses_next [7:0];
// state register
always @(posedge clk)
begin
dir_state_reg <= dir_state_next;
position_state_reg <= position_state_next;
end
// next position state logic
always @(posedge clk)
if(position_state_count == 7500000)
begin
position_state_count = 0;
if(dir_state_reg)
position_state_next = position_state_reg + 1;
else
position_state_next = position_state_reg - 1;
end
else
position_state_count = position_state_count + 1;
// next direction state logic
always @(posedge clk)
if(position_state_reg == 7)
dir_state_next = falling;
else if(position_state_reg == 0)
dir_state_next = rising;
// assign position = position_state_reg;
// assign direction = dir_state_reg;
// brightness state logic
always @(posedge clk)
begin
if(brightness_state_count == 1500000)
begin
brightness_state_count = 0;
if(brightnesses[0] > 0)
brightnesses[0] = brightnesses[0] - 1;
if(brightnesses[1] > 0)
brightnesses[1] = brightnesses[1] - 1;
if(brightnesses[2] > 0)
brightnesses[2] = brightnesses[2] - 1;
if(brightnesses[3] > 0)
brightnesses[3] = brightnesses[3] - 1;
if(brightnesses[4] > 0)
brightnesses[4] = brightnesses[4] - 1;
if(brightnesses[5] > 0)
brightnesses[5] = brightnesses[5] - 1;
if(brightnesses[6] > 0)
brightnesses[6] = brightnesses[6] - 1;
if(brightnesses[7] > 0)
brightnesses[7] = brightnesses[7] - 1;
end
else
brightness_state_count = brightness_state_count + 1;
brightnesses[position_state_reg] = 15;
end
// instantiate led pwm logic
pwm led_ctl0 (.brightness(brightnesses[0]), .out(Led[0]), .clk(clk));
pwm led_ctl1 (.brightness(brightnesses[1]), .out(Led[1]), .clk(clk));
pwm led_ctl2 (.brightness(brightnesses[2]), .out(Led[2]), .clk(clk));
pwm led_ctl3 (.brightness(brightnesses[3]), .out(Led[3]), .clk(clk));
pwm led_ctl4 (.brightness(brightnesses[4]), .out(Led[4]), .clk(clk));
pwm led_ctl5 (.brightness(brightnesses[5]), .out(Led[5]), .clk(clk));
pwm led_ctl6 (.brightness(brightnesses[6]), .out(Led[6]), .clk(clk));
pwm led_ctl7 (.brightness(brightnesses[7]), .out(Led[7]), .clk(clk));
endmodule
module pwm
(
input wire clk,
// 16 levels of brightness
input wire [3:0] brightness,
output wire out
);
reg [2:0] counter_reg;
wire [2:0] counter_next;
always @(posedge clk)
counter_reg <= counter_next;
assign counter_next = counter_reg + 1;
assign out = (brightness == 4'b1111) ? 1'b1 :
(brightness > counter_reg) ? 1'b1 : 1'b0;
endmodule
Constraints for Nexys 2:
# clock pin for Nexys 2 Board
NET "clk" LOC = "B8"; # Bank = 0, Pin name = IP_L13P_0/GCLK8, Type = GCLK, Sch name = GCLK0
# Leds
NET "Led<0>" LOC = "J14"; # Bank = 1, Pin name = IO_L14N_1/A3/RHCLK7, Type = RHCLK/DUAL, Sch name = JD10/LD0
NET "Led<1>" LOC = "J15"; # Bank = 1, Pin name = IO_L14P_1/A4/RHCLK6, Type = RHCLK/DUAL, Sch name = JD9/LD1
NET "Led<2>" LOC = "K15"; # Bank = 1, Pin name = IO_L12P_1/A8/RHCLK2, Type = RHCLK/DUAL, Sch name = JD8/LD2
NET "Led<3>" LOC = "K14"; # Bank = 1, Pin name = IO_L12N_1/A7/RHCLK3/TRDY1, Type = RHCLK/DUAL, Sch name = JD7/LD3
NET "Led<4>" LOC = "E17"; # Bank = 1, Pin name = IO, Type = I/O, Sch name = LD4? s3e500 only
NET "Led<5>" LOC = "P15"; # Bank = 1, Pin name = IO, Type = I/O, Sch name = LD5? s3e500 only
NET "Led<6>" LOC = "F4"; # Bank = 3, Pin name = IO, Type = I/O, Sch name = LD6? s3e500 only
NET "Led<7>" LOC = "R4"; # Bank = 3, Pin name = IO/VREF_3, Type = VREF, Sch name = LD7? s3e500 only
