-- File: SineComputer.vhd
-- Generated by MyHDL 0.7dev
-- Date: Mon Oct  4 16:01:02 2010



package pck_SineComputer is

    type t_enum_t_State_1 is (
    WAITING,
    CALCULATING
);

end package pck_SineComputer;

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use std.textio.all;

use work.pck_myhdl_07dev.all;

use work.pck_SineComputer.all;

entity SineComputer is
    port (
        cos_z0: out signed (19 downto 0);
        sin_z0: out signed (19 downto 0);
        done: out std_logic;
        z0: in signed (19 downto 0);
        start: in std_logic;
        clock: in std_logic;
        reset: in std_logic
    );
end entity SineComputer;
-- Sine and cosine computer.
-- 
-- This module computes the sine and cosine of an input angle. The
-- floating point numbers are represented as integers by scaling them
-- up with a factor corresponding to the number of bits after the point.
-- 
-- Ports:
-- -----
-- cos_z0: cosine of the input angle
-- sin_z0: sine of the input angle
-- done: output flag indicating completion of the computation
-- z0: input angle; -pi/2 <= z0 <= pi/2
-- start: input that starts the computation on a posedge
-- clock: clock input
-- reset: reset input

architecture MyHDL of SineComputer is


begin




SINECOMPUTER_PROCESSOR: process (clock, reset) is
    variable i: unsigned(4 downto 0);
    variable state: t_enum_t_State_1;
    variable dz: signed(19 downto 0);
    variable dx: signed(19 downto 0);
    variable dy: signed(19 downto 0);
    variable y: signed(19 downto 0);
    variable x: signed(19 downto 0);
    variable z: signed(19 downto 0);
begin
    if to_boolean(reset) then
        state := WAITING;
        cos_z0 <= "00000000000000000001";
        sin_z0 <= "00000000000000000000";
        done <= '0';
        x := "00000000000000000000";
        y := "00000000000000000000";
        z := "00000000000000000000";
        i := "00000";
    elsif rising_edge(clock) then
        case state is
            when WAITING =>
                if to_boolean(start) then
                    x := "00100110110111010100";
                    y := "00000000000000000000";
                    z := z0;
                    i := "00000";
                    done <= '0';
                    state := CALCULATING;
                end if;
            when CALCULATING =>
                dx := shift_right(y, to_integer(i));
                dy := shift_right(x, to_integer(i));
                case to_integer(i) is
                    when 0 => dz := "00110010010000111111";
                    when 1 => dz := "00011101101011000110";
                    when 2 => dz := "00001111101011011100";
                    when 3 => dz := "00000111111101010111";
                    when 4 => dz := "00000011111111101011";
                    when 5 => dz := "00000001111111111101";
                    when 6 => dz := "00000001000000000000";
                    when 7 => dz := "00000000100000000000";
                    when 8 => dz := "00000000010000000000";
                    when 9 => dz := "00000000001000000000";
                    when 10 => dz := "00000000000100000000";
                    when 11 => dz := "00000000000010000000";
                    when 12 => dz := "00000000000001000000";
                    when 13 => dz := "00000000000000100000";
                    when 14 => dz := "00000000000000010000";
                    when 15 => dz := "00000000000000001000";
                    when 16 => dz := "00000000000000000100";
                    when 17 => dz := "00000000000000000010";
                    when others => dz := "00000000000000000001";
                end case;
                if (z >= 0) then
                    x := (x - dx);
                    y := (y + dy);
                    z := (z - dz);
                else
                    x := (x + dx);
                    y := (y - dy);
                    z := (z + dz);
                end if;
                if (signed(resize(i, 6)) = (19 - 1)) then
                    cos_z0 <= x;
                    sin_z0 <= y;
                    state := WAITING;
                    done <= '1';
                else
                    i := (i + 1);
                end if;
        end case;
    end if;
end process SINECOMPUTER_PROCESSOR;

end architecture MyHDL;
