Top level description
Here is shown the top-level implementation, written in VHDL and synthesized using free licence tools from Lattice, which are the Diamond LSE for the sysnthesys, Diamond Programmer Tool for flashing the configuration memory, ICE Cube for the P&R and the integration of the LSE tool, Aldec Active HDL for the simulation.
In the top level, you can spot the SPI slave, which sends data to the Deserializer, where on its turn splits the data in paraller and synchronous way to the Color Generator. This module will implement the intensity management, the white saturation, the color and the mode. The mode simply instruct the Color Generator to excludes all the white, intensity and color management and follow the SPI data. Otherwise, will ignore the RGBW data from the SPI and generates it according to an index, generated in the Atmega.
The original idea was to send back the data to the MCU, but then I realized that I have not enough pins, so in the FPGA it is also implemented a 4 channel PWM module.
Nice similarities in Atmega products
It is nice to see that my PWM have the same bug as the Atmega: it cannot swing from 0 to 100%, but it will have a glitch. So the minimum is 1/255 if not inverted or the maximum can be 254/255 if inverted. I simply inverted internally the control circuitry, so that I have a PWM that swing from 0/255 up to 254/255, but it is a not inverted type. In this way, this glitch cannot be seen. This glitch is totally normal in a raw implementation, and can be easily masked. I wonder why it isn't in Atmegas. What a lazy one the designer.
Below a simulation snapshot showing the glitch on D3 signal:
Overall FPGA utilization
The FPGA itself is almost full, especially when optimizing for speed. This project gives to me some feedback on how really problematic could be an HDL design when you have few resources. For example, I have initially implemented a division, a combinatorial default one: 50% of the FPGA was filled with this logic, while the other 50% shall be filled with 80% of resources. My iCE40 does not have the 130% of space.
So the division for implmenting the dimming was made by issuing a dynamic shift in the Color Generator, reducing the dimming steps for the user. In the Atmega, a division was performed very well. But the previous code was fine tuned, smooth and big 8kB more.