|
|
  |
sine with cordic vhdl, Может кому понадобится |
|
|
|
Sep 28 2017, 08:55
|
Группа: Участник
Сообщений: 11
Регистрация: 14-08-17
Пользователь №: 98 790

|
Цитата(Boobrilla @ Sep 28 2017, 08:48)  Привет всем. Просто доделал, решил поделиться) Может молодым спецам пригодится) Кордик для вычисления синуса 100KHz c четвертью в 250 тактов. (если какие нибудь замечания будут, или советы по оптимизации, был бы рад) CODE library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; use IEEE.STD_LOGIC_SIGNED.ALL;
-- Uncomment the following library declaration if using -- arithmetic functions with Signed or Unsigned values --use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating -- any Xilinx primitives in this code. --library UNISIM; --use UNISIM.VComponents.all;
entity Toplvl is
port ( clk : std_logic; reset : std_logic; sinus1 : out std_logic_vector(16 downto 0)); end Toplvl;
architecture Behavioral of Toplvl is
signal quarter_1 : std_logic_vector (1 downto 0); signal t : std_logic_vector (16 downto 0); signal e : std_logic_vector (16 downto 0); component math port ( clk : in std_logic; reset : in std_logic; qu : out std_logic_vector (1 downto 0); cosin : out std_logic_vector (16 downto 0); sinus : out std_logic_vector (16 downto 0)); end component; component right port ( clk : in std_logic; reset : in std_logic; x : in std_logic_vector(16 downto 0); y : in std_logic_vector(16 downto 0); quarter : in std_logic_vector (1 downto 0); xo : out std_logic_vector(16 downto 0); yo : out std_logic_vector(16 downto 0)); end component; begin
--sinus1 <= yx;
math_end : math port map ( clk => clk, reset => reset, qu => quarter_1, cosin => t, sinus => e);
right_end : right port map ( clk => clk, reset => reset, x => t, y => e, quarter => quarter_1, yo => sinus1); end Behavioral; CODE entity math is port ( clk : in std_logic; reset : in std_logic; qu : out std_logic_vector (1 downto 0); sinus : out std_logic_vector (16 downto 0); cosin : out std_logic_vector (16 downto 0)); end math;
architecture Behavioral of math is
type my_type is array (0 to 16) of signed (16 downto 0); signal x : my_type; signal y : my_type; signal z : my_type; signal j : my_type :=("00111110011110010", "00100100111011010", "00010011011111111", "00001001111011110", "00000100111101111", "00000010011111000", "00000001001111011", "00000000100111110", "00000000010011011", "00000000001010000", "00000000000101000", "00000000000010100", "00000000000001010", "00000000000000101", "00000000000000011", "00000000000000010", "00000000000000001"); signal l : std_logic_vector(16 downto 0); signal f : std_logic_vector(16 downto 0); component delay port ( clk : in std_logic; reset : in std_logic; quarter_do : out std_logic_vector(1 downto 0)); end component;
component rotation generic ( first : integer := 0; second : integer := 1; third : integer := 2; fourth : integer := 3); Port ( clk : in std_logic; reset : in std_logic; Angle : out std_logic_vector (12 downto 0); quarter_in : out std_logic_vector (1 downto 0)); end component;
signal xangle : std_logic_vector(12 downto 0); signal xxangle : signed(16 downto 0); begin
rotation_XYN : rotation port map ( clk => clk, Angle => xangle, reset => reset );
delay_XYN : delay port map ( clk => clk, reset => reset, quarter_do => qu );
xxangle(16) <= '0'; xxangle(15 downto 4) <= signed(xangle(11 downto 0)); xxangle(3 downto 0) <= (others => '0');
process(clk) begin if rising_edge(clk) then if reset <= '1' then x(0) <= "00000100110110110"; y(0) <= "00000000000000000"; z(0) <= signed(xxangle); For n in 0 to 15 loop if (z(n) < 0) then x(n+1) <= x(n) + (y(n)/2**n); y(n+1) <= y(n) - (x(n)/2**n); z(n+1) <= z(n) + j(n); else x(n+1) <= x(n) -(y(n)/2**n); y(n+1) <= y(n) +(x(n)/2**n); z(n+1) <= z(n) - j(n); end if; f <= std_logic_vector(x(16)); l <= std_logic_vector(y(16)); cosin <= f; sinus <= l; end loop; end if; end if; end process;
end Behavioral; CODE entity rotation is generic ( first : integer := 0; second : integer := 1; third : integer := 2; fourth : integer := 3); Port ( clk : in std_logic; reset : in std_logic; Angle : out std_logic_vector (12 downto 0); quarter_in : out std_logic_vector (1 downto 0)); end rotation;
architecture Behavioral of rotation is signal Ang : std_logic_vector (12 downto 0) := (others => '0'); signal state : unsigned (1 downto 0) := to_unsigned(first,2); signal count_ang : std_logic_vector (11 downto 0) := (others => '0');
begin
process (clk)
begin
if (rising_edge(clk)) then if (reset = '1') then case(state) is when to_unsigned(first,2) => if (count_ang >= 3999) then --00 state <= to_unsigned(second,2); count_ang <= "000000010000"; quarter_in <= "01"; Ang <= Ang - 16; else state <= to_unsigned(first,2); quarter_in <= "00"; Ang <= Ang + 16; count_ang <= count_ang + 16; end if; when to_unsigned(second,2) => if (count_ang >= 3999) then --01 state <= to_unsigned(third,2); count_ang <= "000000010000"; quarter_in <= "10"; Ang <= Ang + 16; else state <= to_unsigned(second,2); quarter_in <= "01"; Ang <= Ang - 16; count_ang <= count_ang + 16; end if; when to_unsigned(third,2) => if (count_ang >= 3999) then state <= to_unsigned(fourth,2); count_ang <= "000000010000"; quarter_in <= "11"; Ang <= Ang - 16; else state <= to_unsigned(third,2); quarter_in <= "10"; Ang <= Ang + 16; count_ang <= count_ang + 16; end if; when to_unsigned(fourth,2) => if (count_ang >= 3999) then state <= to_unsigned(first,2); count_ang <= "000000010000"; quarter_in <= "00"; Ang <= Ang + 16; else state <= to_unsigned(fourth,2); quarter_in <= "11"; Ang <= Ang - 16; count_ang <= count_ang + 16; end if; when others => count_ang <= (others => '0'); end case; end if; end if; end process; Angle <= Ang; end Behavioral; CODE entity delay is port ( clk : in std_logic; reset : in std_logic; quarter_do : out std_logic_vector(1 downto 0)); end delay;
architecture Behavioral of delay is signal delay_1 : std_logic_vector(1 downto 0); signal delay_2 : std_logic_vector(1 downto 0); signal delay_3 : std_logic_vector(1 downto 0); signal delay_4 : std_logic_vector(1 downto 0); signal delay_5 : std_logic_vector(1 downto 0); signal delay_6 : std_logic_vector(1 downto 0); signal delay_7 : std_logic_vector(1 downto 0); signal delay_8 : std_logic_vector(1 downto 0); signal delay_9 : std_logic_vector(1 downto 0); signal delay_10 : std_logic_vector(1 downto 0); signal delay_11 : std_logic_vector(1 downto 0); signal delay_12 : std_logic_vector(1 downto 0); signal delay_13 : std_logic_vector(1 downto 0); signal delay_14 : std_logic_vector(1 downto 0); signal delay_15 : std_logic_vector(1 downto 0); signal delay_16 : std_logic_vector(1 downto 0); signal delay_17 : std_logic_vector(1 downto 0); signal delay_18 : std_logic_vector(1 downto 0); signal delay_19 : std_logic_vector(1 downto 0);
component rotation generic ( first : integer := 0; second : integer := 1; third : integer := 2; fourth : integer := 3); Port ( clk : in std_logic; reset : in std_logic; Angle : out std_logic_vector (12 downto 0); quarter_in : out std_logic_vector (1 downto 0)); end component;
begin
rotation_XYN : rotation port map ( clk => clk, reset => reset, quarter_in => delay_1 );
process(clk) begin if rising_edge(clk) then delay_2 <= delay_1; delay_3 <= delay_2; delay_4 <= delay_3; delay_5 <= delay_4; delay_6 <= delay_5; delay_7 <= delay_6; delay_8 <= delay_7; delay_9 <= delay_8; delay_10 <= delay_9; delay_11 <= delay_10; delay_12 <= delay_11; delay_13 <= delay_12; delay_14 <= delay_13; delay_15 <= delay_14; delay_16 <= delay_15; delay_17 <= delay_16; delay_18 <= delay_17; delay_19 <= delay_18; quarter_do <= delay_19; end if; end process;
end Behavioral; CODE entity right is port ( clk : in std_logic; reset : in std_logic; x : in std_logic_vector(16 downto 0); y : in std_logic_vector(16 downto 0); quarter : in std_logic_vector (1 downto 0); xo : out std_logic_vector(16 downto 0); yo : out std_logic_vector(16 downto 0)); end right;
architecture Behavioral of right is signal xq1 : std_logic_vector(16 downto 0); signal xq2 : std_logic_vector(16 downto 0); signal yq1 : std_logic_vector(16 downto 0); signal yq2 : std_logic_vector(16 downto 0); signal xr : std_logic_vector(16 downto 0); signal yr : std_logic_vector(16 downto 0); begin
xq1 <= x + 0; yq1 <= y + 0; xq2 <= 0 - x; yq2 <= 0 - y;
process(clk)
begin if (rising_edge(clk)) then if (reset = '1') then case (quarter) is when "00" => yr <= yq1; xr <= xq1; when "01" => yr <= yq1; xr <= xq2; when "10" => yr <= yq2; xr <= xq2; when "11" => yr <= yq2; xr <= xq1; when others => xr <= (others => '0'); yr <= (others => '0'); end case; else xr <= (others => '0'); yr <= (others => '0'); end if; end if; end process; xo <= xr; yo <= yr; end Behavioral; Ну и результат
Сообщение отредактировал Boobrilla - Sep 28 2017, 09:17
|
|
|
|
|
Sep 28 2017, 10:28
|

В поисках себя...
   
Группа: Свой
Сообщений: 538
Регистрация: 11-06-13
Из: Санкт-Петербург
Пользователь №: 77 140

|
А вот у Вас в модуле Toplvl есть порты, которые объявляются без указания направления. Это так задумано, или ошибка, или ISE позволяет такие вольности с языком ? Код entity Toplvl is
port ( clk : std_logic; reset : std_logic; sinus1 : out std_logic_vector(16 downto 0)); end Toplvl; Из советов по оптимизации я бы модуль delay - описал так(только параметры WIDTH и LENGTH указал): Это по сути многоразрядный сдвиговый регистр. Ваш подход "в лоб" уж больно некрасиво смотрится. А если надо длину задержки поменять ? Код LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL;
ENTITY SHIFT_RAM IS GENERIC ( WIDTH : INTEGER := 24; LENGTH : INTEGER := 6 ); PORT ( CLK : IN STD_LOGIC; DATA_IN : IN STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0); DATA_OUT : OUT STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0) ); END ENTITY;
ARCHITECTURE RTL OF SHIFT_RAM IS TYPE REG_RAM IS ARRAY (LENGTH-1 DOWNTO 0) OF STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0); SIGNAL REG : REG_RAM; ATTRIBUTE RAMSTYLE : STRING; ATTRIBUTE RAMSTYLE OF REG : SIGNAL IS "M9K"; BEGIN SHIFT_REG_PROC : PROCESS ( CLK ) BEGIN IF (RISING_EDGE(CLK)) THEN -- По каждому переднему фронту REG <= REG(LENGTH-2 DOWNTO 0) & DATA_IN; -- Запишем в младший разряд данные со входа и сдвинем их END IF; END PROCESS SHIFT_REG_PROC; DATA_OUT <= REG(LENGTH-1); END ARCHITECTURE;
Сообщение отредактировал Flip-fl0p - Sep 28 2017, 10:30
|
|
|
|
|
Sep 28 2017, 12:35
|
Группа: Участник
Сообщений: 11
Регистрация: 14-08-17
Пользователь №: 98 790

|
По портам не заметил) Но, видимо, ISE позволяет) (оба in). По поводу подхода "в лоб" - я слишком еще не опытен. Лучше сделать так, как точно будет работать) Ну а если нужно будет изменить длину задержки, то просто добавлять/удалять кол-во переменных действий) В моем случае задержка была 190 ns = 19 по 10 ns.
|
|
|
|
|
Sep 28 2017, 12:58
|
Группа: Участник
Сообщений: 11
Регистрация: 14-08-17
Пользователь №: 98 790

|
Ну выходит что так) Но я бы просто тогда наверно вермя такта менял, если бы этого позволяло задание
Сообщение отредактировал Boobrilla - Sep 28 2017, 13:00
|
|
|
|
|
Oct 2 2017, 06:27
|
Группа: Участник
Сообщений: 11
Регистрация: 14-08-17
Пользователь №: 98 790

|
Цитата(Maverick @ Sep 28 2017, 14:58)  где тестбенч для симуляции? Тестбенч не кидал, ибо он стандартно "пустой", ничего не добавлял. Кроме наверное ресета = 1 . CODE ENTITY Final IS END Final; ARCHITECTURE behavior OF Final IS COMPONENT Toplvl PORT( clk : IN std_logic; reset : IN std_logic; sinus1 : OUT std_logic_vector(16 downto 0) ); END COMPONENT;
--Inputs signal clk : std_logic := '0'; signal reset : std_logic := '0';
--Outputs signal sinus1 : std_logic_vector(16 downto 0);
-- Clock period definitions constant clk_period : time := 10 ns; BEGIN -- Instantiate the Unit Under Test (UUT) uut: Toplvl PORT MAP ( clk => clk, reset => reset, sinus1 => sinus1 );
-- Clock process definitions clk_process :process begin clk <= '0'; wait for clk_period/2; clk <= '1'; wait for clk_period/2; end process; -- Stimulus process stim_proc: process begin -- hold reset state for 100 ns. wait for 100 ns;
wait for clk_period*10; reset <= '1'; -- insert stimulus here
wait; end process; END;
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|