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