When you just can't get any better  
 
    Home

VHDL Code

Code for the Xilinx Spartan-3 board (more specifically, the Xilinx FPGA on that board) was written in VHDL inside the Xilinx Integrated Software Environment (ISE). I used ISE9.2i, but I understand there's a new version avaliable. It's called the ISE Foundation on their website and you can find it HERE. It's a pretty steep learning curve, but very worthwhile and very cool. Among other things, in this environment you edit files, compile VHDL code, and generate the .bit file necessary to program the FPGA. Also, you'll need a way to get the .bit file from your PC to the board. I used the Adept Suite V1.10.0 from the Digilent website, which you can find HERE.

I'm planning to post the source code HERE.

 

Software Overview

A counter called line_cnt gets incremented each BURST and reset each VSYNC. This way there's a counter that runs from 0 to 262 that can be used thoughout the program to signify the line we're looking at. I've found that line 175 works well. A similar counter that increments at CLOCK RATE (50Mhz) and resets at burst called samp_cnt generates a number between 0 and 3054 signifying a specific location on the line. Although this counter isn't locked to the video signal, the clock is so fast in comparison to the signal, there's very little jitter.

By using line_cnt, samp_cnt, ODD/EVEN and the SLICE output of the comparator, we can tell if a specific spot on the screen is LIGHT OR DARK. On the Wii Guitar Hero there are frets that are broken in 5 places. By looking at the video signal at these breaks we can tell if there's a puck passing that spot on the screen or not.

Since we're looking at line 175 and the button press can't happen until the puck reaches approximately line 212, we store the presence of the puck in a shift register clocked by VSYNC and use a tap about 6 frames later to actually press the note button.

To generate the Strum signal, we "OR" the five Note Buttons together, stretch the output, and send it to the Strum Button output.

The output from the Digital Processing Board is a signal for each Note Button (5), one for the Strum Button(1), and a HIGHLIGHT signal. The Highlight signal goes back to the Analog Processing Board and is used to visually locate a spot on the screen or present indicators on the bottom of the screen to show what the program is doing. The fret and strum signals go to the Guitar interface board to buffer these signals for their trip down the RS-232 cable.

We added a male RS-232 connector to the Wii Guitar. It's not an RS-232 signal, but a convienent way to get up to 9 signals from the interface board (only 6 used) to the Wii Guitar. Inside the guitar we've added a board that holds 6 opto-isolators, each wired across one of the switches of interest. Read more about the Modification to the Wii Guitar HERE.

 

VHDL Code for Horizontal Samples

------------------------------------------------------
This routine counts from 0 to some max number to signify a position on a single line. It counts at 50Mhz (the clock rate of the Spartan-3 board. I've found that it's maximum count is 3054. It's used throughout the program to locate a specific spot on a line of video.


process(clk, samp_cnt, burst)
begin
if clk'event and clk = '1' then
if burst = '0' then
samp_cnt <= "0000000000000";
else
samp_cnt <= samp_cnt + 1;
end if;
--find the maximum sample count (3054 counts)
if samp_cnt > max_samp_cnt then
max_samp_cnt <= samp_cnt;
end if;
end if;
end process;

 

VHDL Code for Vert Samples

------------------------------------------------------
This routine counts from 0 to 262 signifying the line count. This routine runs every frame (v_sync). This line_cnt register is used throughout the program to locate a specific line. Coupled with ODD/EVEN, and samp_cnt above, you can locate a specific spot on the screen.


process(v_sync, burst, line_cnt)
begin
if burst'event and burst = '0'then
if v_sync = '0' then
line_cnt <= "000000000";
else
line_cnt <= line_cnt + 1;
end if;
--find the maximum line count (262 lines)
if line_cnt > max_line_cnt then
max_line_cnt <= line_cnt;
end if;
end if;
end process;

 

VHDL Code for finding a puck

------------------------------------------------------
This routine checks to see if line_cnt = the correct sense line, samp_cnt = the correct position on the line, and the slicer sees 'white'. If so, it sets the bit 'color-center' for later processing. This routine runs every 20nS (clock rate)

process(clk)
begin
if clk'event and clk = '1' then
if odd_even = '0'
and line_cnt = sense_line
and window_in = '1'
and samp_cnt >= puck_center_r
and samp_cnt <= puck_center_r + 2 then
red_center <= '1';
else
red_center <= '0';
end if;
end if;
end process;

 

VHDL Code for stretching the pulse

------------------------------------------------------
This routine runs every 20nS (clk rate). It stretches the pulse from red_center (above) to a pulse that ends at the end of a line.

process(clk, v_sync, red_center)
begin
if clk'event and clk = '1' then
if v_sync = '0' then
red_frame_latched <= '0';
else
if red_center = '1' then
red_frame_latched <= '1';
end if;
end if;
end if;
end process;