Build A PSP LCD Interface

Program Files (ISE 11.1):

The Simple RGB Project:

The Pyro Logo Project:

The Software
The code for this tutorial is not too complex, especially if you are familiar with any of the previous FPGA & VGA tutorials I wrote: Creating VGA With VHDL or Advanced VGA On A UP2. The code used is actually copied from those projects. The main change is the clock rate and the number of pixels the screen can display.

The Clock Rate
The PSP LCD requires a clock input of 7.83 to 9.26 MHz, with ideal clock being 50% duty cycle at 9 MHz. The clock speed of the FPGA used in this tutorial is 100 MHz, so the easiest way to get that near 9 MHz is by using a 'clock divider'. We use some VHDL signals/variables to increment every 100 MHz and output its own, slower clock signal, to the PSP Display.

~~~ Clock Divider Code Begin ~~~
IF(clk_count = 5) THEN
	clk_out_9mhz <= '0';
end if;
IF(clk_count = 11) THEN
	clk_out_9mhz <= '1';
	clk_count := 0;
end if;

--Clock Counter Increment
clk_count:= 1 + clk_count;

--Vga Timing Logic Start:
IF(clk_count = 1)THEN
~~~ Clock Divider Code Begin ~~~

The code shown above shows you how counting 11 clock ticks can get us to 100/11 => 9.09 MHz. The duty cycle is 45:55 which is right at the border of the min and max values seen in the theory section. An alternative would be to count 12 clock cycles and use 6 clock ticks for logic 1 and 6 for logic 0. The output clock frequency would then be 100/12 => 8.3 MHz with a 50:50 duty cycle for each clock pulse.

Updating The Pixel Limits
The second thing we need to do to the VHDL code from the previous Creating VGA With VGA project is input our new pixel range. For this PSP LCD, as we saw in the theory section, there are 525 clock ticks per horizontal line (480 visible pixels) and 286 horizontal lines (272 visible lines) per screen refresh. So we will need to update these numbers along with some others in order to follow the theory of the timing diagram shown previously.

~~~VGA VHDL Changes In Bold~~~
          --Reset Horizontal Counter
IF (h_cnt = 525) THEN
          h_cnt <= "0000000000";
          h_cnt <= h_cnt + 1;
          --Generate Horizontal Sync
IF (h_cnt <= 523) AND (h_cnt >= 482) THEN
          h_sync <= '0';
          h_sync <= '1';

--Vertical Sync And Reset Vertical Counter
IF (v_cnt >= 285) AND (h_cnt >= 499) THEN
          v_cnt <= "0000000000";
ELSIF (h_cnt = 499) THEN
          v_cnt <= v_cnt + 1;
--Generate Vertical Sync
IF (v_cnt <= 283) AND (v_cnt >= 274) THEN
          v_sync <= '0';
          v_sync <= '1';
--Generate Horizontal Data
IF (h_cnt <= 479) THEN
          horizontal_en <= '1';
          column <= h_cnt;
          pixel_column <= (h_cnt-20);
          horizontal_en <= '0';
--Generate Vertical Data
IF (v_cnt <= 271) THEN
          vertical_en <= '1';
          row <= v_cnt;
          pixel_row <= (v_cnt+20);
          vertical_en <= '0';
~~~End Code~~~

User Constraints File (Assigning Pins)
The .UCF file allows us to do many things with a Xilinx FPGA, however in this case we're concerned with assigning VHDL module inputs and outputs to actual pins on the FPGA, specifically the pins the ribbon cable is connected to. A quick look at the datasheet for the specific FPGA board I'm using tells me the names of all the pins connected to the I/O port. Here's a look at the UCF file with pins and signals connected:

~~~UCF File For PSP LCD FPGA~~~
NET "clk" LOC = B15;
NET "led_1" LOC = D13;
NET "led_2" LOC = D12;
NET "blue[0]" LOC = AD22;
NET "blue[1]" LOC = AC22;
NET "blue[2]" LOC = AD21;
NET "blue[3]" LOC = AC21;
NET "blue[4]" LOC = AC20;
NET "blue[5]" LOC = AD19;
NET "green[0]" LOC = AA24;
NET "green[1]" LOC = Y23;
NET "green[2]" LOC = AA23;
NET "green[3]" LOC = AC24;
NET "green[4]" LOC = AB23;
NET "green[5]" LOC = AD23;
NET "red[0]" LOC = V20;
NET "red[1]" LOC = W21;
NET "red[2]" LOC = V22;
NET "red[3]" LOC = W24;
NET "red[4]" LOC = Y24;
NET "red[5]" LOC = W23;
NET "clk_out_9mhz" LOC = Y21;
NET "hsync" LOC = AC18;
NET "vsync" LOC = AC19;
~~~End Code~~~

The LEDs are just debug leds to make sure everything is working. They blink after the FPGA code is downloaded. With the code all written and compiled, download the .bit file to the FPGA and see the results!