---
title: Breathing RGB Light
---
# Lab 2 Homework - Breathing RGB Light
###### tags: `FPGA2021`
Group Member:
* E24066226 魏晉成
* E24066470 余采蓴
[TOC]
## Problem 1
### Requirement
Names listed below are according to homework description. As for corresponding names in circuit module and constraint file, they would be mentioned in details under each item.
* SW[1:0]
In decoder module: switch[1:0]
In constraint file: sw[1:0]
This switch is to select which kind of color currently the on-board LEDs should display, colors of corresponding switch states are listed in the table below. Furthermore, on-board `SW0` is connected to sw[0] and `SW1` is connected to sw[1].
| Switch state | LED color | Hex triplet |
| ------------ | ------------------------------------ | ----------- |
| 2'b00 | <font color="#7f1fff">Purple</font> | #7f1fff |
| 2'b01 | <font color="#00ffff">Cyan</font> | #00ffff |
| 2'b10 | <font color="#ffff00">Yellow</font> | #ffff00 |
| 2'b11 | <font color="#ff00ff">Crimson</font> | #ff00ff |
* BTN
In decoder module: reset
In constraint file: rst
This button reset the breathing light output when it is pressed, making the breathing LED (rgb5) start over from minimum illuminance.
* rgb4[2:0]
In decoder module: {Constant_R, Constant_G, Constant_B}
In constraint file: {R_out_4, G_out_4, B_out_4}
This LED would display the color selected by `sw[1:0]` with constant illuminance by technique of PWM.
* rgb5[2:0]
In decoder module: {Breathing_R, Breathing_G, Breathing_B}
In constraint file: {R_out_5, G_out_5, B_out_5}
This LED would display the color selected by `sw[1:0]` with changing illuminance from low to high, then back to low, and so on. Besides technique of PWM, an additional counter to count current illuminance is used.
### Implementation
#### Design philosophy
There are three things needed to take them into consideration in this design, PWM counter, counter to create the effect of breathing, and boundaries that limit the lightness.
1. PWM counter:
It is a simple 8-bit counter to suffice the length of each component in hex triplet. It is also the main counter to control switching of LEDs by a relatively naive way - **check if the value of counter is less than the boundary of that LED. If so, then LED would be turned on, else way, it would be turned off.**
2. Breathing counter:
It is a 19-bit back-and-forth counter that count from 0 to 0x7_ffff and then back to 0 on every time PWM counter counts to 0xff. Thus, with the frequency of FPGA is set to 125MHz by constraint file, $2^{8+19}=134,217,727, \frac{125000000}{134217727}=0.9313...$, the LEDs with breathing features would go from lowest brightness to full brightness and back to lowest brightness with 0.9313 Hz.
3. Boundaries:
There are two kinds of boundaries requiring calculation, first are constant PWM limits, second are dynamic PWM limits controlled by `breathing counter`. To optimize the circuit toward area (or the number of logic cells in fpga), I applied below design. However, the optimization hasn't been confirmed to be effective since I didn't do any experiment to compare area.
First, a naively designed dynamic (breathing) boundary might be designed as 3 registers, count up at positive edge of MSB of breathing counter, and if the counters would be greater than its limit, than count down instead. This would cause two problems, three counters aside from `breathing counter` are needed, and three comparators are required.
Thus, I tried reuse signals of `breathing counter` and shrink the number of comparators from 3 to 1. First, use a two-bit signal to represent `8'h00`, `8'h1f`, `8'h7f` and `8'hff` in the corresponding component in triplet. Second, use the select signal to multiplex `dynamic PWM limit` of corresponding component from `8'h0`, `{4'd0, Breathing_Counter[18:14]`, `{1'd0, Breathing_Counter[18:14], 2'b11}`, `{Breathing_Counter[18:14], 3'b111}`. Therefore, 3 counters and 3 comparators are reduced into 3 sets of 8-bit 4-to-1 mux and one counter. This would be further discussed in below section.
#### Design Block Diagram

As above section has described, first stage of multiplexer would encode switch into brightness. Later, the selection would be done in second-level multiplexers to choose the real PWM limit of each color. Last but not the least, to achieve breathing effect, differt kind of padding for `Breathing Counter` would also be selected by code encoded by the first-level multiplexers. By comparing value of `PWM Counater` and `Breathing Counter`, the breathing effect can be implemented.
#### Block Design on Vivado

## Problem 2
### Requirement
Names listed below are according to homework description. As for corresponding names in circuit module and constraint file, they would be mentioned in details under each item.
* BTN
In decoder module: reset
In constraint file: rst
This button reset the breathing light output when it is pressed, making the breathing LED (rgb4) start over from first color with minimum illuminance.
* rgb4[2:0]
In decoder module: {R_out, G_out, B_out}
In constraint file: {R_out_4, G_out_4, B_out_4}
This LED would contiounously changing its color from one to another when illuminance change one cycle from lowest to highest and back to lowest.
Below is the sequence of colors.
| Sequence | LED color | Hex triplet |
| -------- | ----------------------------------- | ----------- |
| 1 | <font color="red">Red</font> | #ff0000 |
| 2 | <font color="orange">Orange</font> | #ff6100 |
| 3 | <font color="#ffff00">Yellow</font> | #ffff00 |
| 4 | <font color="green">Green</font> | #00ff00 |
| 5 | <font color="blue">Blue</font> | #0000ff |
| 6 | <font color="#7f1fff">Purple</font> | #7f1fff |
### Implementation
#### Design philosophy
There are four things needed to take them into consideration in this design, PWM counter, counter to create the effect of breathing, boundaries that limit the lightness, along with the state machine that keeps current color.
1. PWM counter:
It is a simple 8-bit counter to suffice the length of each component in hex triplet. It is also the main counter to control switching of LEDs by a relatively naive way - **check if the value of counter is less than the boundary of that LED. If so, then LED would be turned on, else way, it would be turned off.**
2. Breathing counter:
It is a 29-bit back-and-forth counter that count from 0 to 0x3fff_ffff and then back to 0 on positive edge of clock. Thus, with the frequency of FPGA is set to 125MHz by constraint file, $2^{30}=1,073,741,824, \frac{125000000}{1073741824}=0.116...$, the LEDs with breathing features would go from lowest brightness to full brightness and back to lowest brightness with 0.116 Hz. Furthermore, **the lightness stage is 128 for every color**, since there is at least one color whose full brightness is 127 because this design can add the minimum step of lightness with 1 in 8-bit width limit.
3. Boundaries:
Dynamic PWM limits controlled by `breathing counter` are quite similar to how I controlled the breathing LED in last problem. With brightness of single LED encoded into 5 codes, representing 0x00, 0x1f, 0x61, 0x7f, 0xff, we can acquire which kind of upper limit for breathing LEDs should be applied. With corresponding code, breathing limits should be `8'h0`, `{3'd0, Breathing_Counter[29:25]}`, `{1'd0, Breathing_Counter[29:23]} - {3'd0, Breathing_Counter[29:25]} + {7'd0, Breathing_Counter[29]}`, `{1'd0, Breathing_Counter[29:23]}`, `Breathing_Counter[29:22]`.
The value `{1'd0, Breathing_Counter[29:23]} - {3'd0, Breathing_Counter[29:25]} + {7'd0, Breathing_Counter[29]}` is not so straightforward, but that's how I deal with the lightness boudary of 0x61.
4. State Machine for Colors:
Last but not the least, to change color, the state machine must be applied in this design. State machine changes its value when the counting down flag of breathing counter is set and breathing counter is 1. That's the timing for new color to show up.
#### Design Block Diagram
Because there are 6 colors (corresponding to 6 states) and 5 encoded brightness, with 8-to-1 mux, the block diagram would be much complex. Thus, the block diagram would not be presented in this problem.
#### Block Design of Vivado
