
This CORDIC (Coordinate Rotation DIgital Computer) core is a hardware-efficient iterative algorithm used to calculate trigonometric functions—specifically Sine and Cosine—using only shifts and additions. It operates in rotation mode to rotate a vector by a specific input angle.
| Signal | Direction | Width | Description |
|---|---|---|---|
clk |
Input | 1 | System clock. |
rst_n |
Input | 1 | Active-low asynchronous reset. |
start |
Input | 1 | Pulse high to initiate a new calculation. |
angle_in |
Input | 16 | Target angle in radians (Q2.13 format). |
cos_out |
Output | 16 | Calculated Cosine value (Q2.13). |
sin_out |
Output | 16 | Calculated Sine value (Q2.13). |
done |
Output | 1 | Pulses high for one cycle when output is valid. |
The CORDIC algorithm natively converges for angles between $-\pi/2$ and $+\pi/2$. This core includes a pre-processing step:
flip register tracks this change to invert the final results, extending the range to the full $[-\pi, \pi]$ circle.16'sd4974 ($0.60725 \times 2^{13}$). This compensates for the inherent CORDIC gain $A_n \approx 1.6467$ that occurs during rotation.For each iteration ($i = 0$ to $13$), the core performs the following transformation:
$x_{i+1} = x_i - \sigma_i \cdot y_i \cdot 2^{-i}$ $y_{i+1} = y_i + \sigma_i \cdot x_i \cdot 2^{-i}$ $z_{i+1} = z_i - \sigma_i \cdot \arctan(2^{-i})$
Where $\sigma_i = 1$ if $z_i \geq 0$, and $-1$ otherwise.
start signal.start, angle_in is loaded into $z$, $x$ is set to the $1/A_n$ constant, and $y$ is cleared.>>>), no actual multipliers are used in the hardware fabric.busy flag drops, done pulses high, and the result is latched into sin_out and cos_out.The controller module acts as the top-level interface for the CORDIC system. It is responsible for deserializing 4-bit input data into a full 16-bit angle, triggering the calculation, and multiplexing the final result based on the user's selection (Sine or Cosine).
| Signal | Direction | Width | Description |
|---|---|---|---|
clk |
Input | 1 | System clock. |
rst_n |
Input | 1 | Active-low asynchronous reset. |
rx_data |
Input | 4 | Input nibble (4-bits) containing a portion of the angle. |
valid |
Input | 1 | Logic high when rx_data is ready to be sampled. |
sin_cos |
Input | 1 | Mode selection: 0 for Sine, 1 for Cosine. |
byte_select |
Input | 2 | Index of the nibble being sent (00 to 11). |
result |
Output | 16 | The final calculated 16-bit value (Q2.13). |
| Signal | Direction | Width | Description |
|---|---|---|---|
cordic_start |
Output | 1 | Pulse sent to the CORDIC core to begin calculation. |
angle |
Output | 16 | The full 16-bit angle assembled from nibbles. |
sin_out |
Input | 16 | Sine result from the CORDIC core. |
cos_out |
Input | 16 | Cosine result from the CORDIC core. |
cordic_done |
Input | 1 | Completion signal from the CORDIC core. |
The controller utilizes a 7-state FSM to manage data flow:
valid signal. Captures the sin_cos mode.rx_data into angle[3:0].rx_data into angle[7:4].rx_data into angle[11:8].rx_data into angle[15:12].cordic_start for one clock cycle.cordic_done. Once complete, it latches either sin_out or cos_out to the result bus and returns to IDLE.valid pulses. The user must provide the corresponding byte_select (0, 1, 2, then 3) to fill the 16-bit angle register.START state to kick off the CORDIC core logic.disp_select register remembers if the user wanted Sine or Cosine. When the CORDIC core finishes, this bit determines which internal bus is routed to the external result output.always @(posedge clk) block.valid signal and the correct byte_select before transitioning between receiving states, ensuring data integrity during the assembly of the 16-bit angle.45'deg, then in rad=45*pi/180. Then convert this rad value to fixed point by doing angle_fixed_point_val=angle_rad x (2^13) as 16 bit form. If it's a negative angle, take the 2s complement form.(ui_in[5,4]) to 00 and put the lower 4 bits of the converted angle value in ui_in[3:0]. Then set valid signal ui_in[7] to 1.uio_out and uo_out. Note that it will produce output in fixed-point representation. So you need to divide it by 2^13 to get the original sin/cos value. You can select sine/cosine output by setting sin_cos pin ui_in[6](=0 to get sine output and 1 to get cosine output)No external hardwares are required.
| # | Input | Output | Bidirectional |
|---|---|---|---|
| 0 | angle[0] | y[0] | y[8] |
| 1 | angle[1] | y[1] | y[9] |
| 2 | angle[2] | y[2] | y[10] |
| 3 | angle[3] | y[3] | y[11] |
| 4 | byte_select[0] | y[4] | y[12] |
| 5 | byte_select[1] | y[5] | y[13] |
| 6 | sin_cos | y[6] | y[14] |
| 7 | valid | y[7] | y[15] |