LCD 16x2 (I2C) with FPGA (Altera Cyclone II)
You'd implement a block for the low-level parts of the I2C protocol, and a block that schedules the data transfers, and then evolve from there.
I2C has a gated clock and a bidirectional data pin, these are your first steps on the low level block, and both are great learning experiences as well:
The clock isn't very fast, so you can in theory generate the clock as a normal signal by dividing a faster clock, but that is messy to get right since you also need to drive the data line synchronously to that.
So step 1 is to generate an I2C clock with a PLL, you can find the PLL interface in the IP Catalog.
Check that the clock works, then build a gated clock output.
This is typically done by instantiating a DDR output driver (also in the IP Catalog) that outputs the gate signal while the clock is high, and 0 while the clock is low.
The third thing you want (also from the IP Catalog) is a bidirectional IO driver for the data line.
Then, implement a state machine that performs a single transfer over the I2C bus using these primitives, ideally some hardcoded command that is immediately visible on the LCD, and then extend from there.
Connecting that to the rest of the design will later require either a rework of clocking the I2C part of the design to use a faster clock and pulses from a divisor that advance the I2C state machine, or a clock domain crossing mechanism, that will be another great learning opportunity. :)