Boobrilla 0 28 сентября, 2017 Опубликовано 28 сентября, 2017 (изменено) · Жалоба Привет всем. Просто доделал, решил поделиться) Может молодым спецам пригодится) Кордик для вычисления синуса 100KHz c четвертью в 250 тактов. (если какие нибудь замечания будут, или советы по оптимизации, был бы рад) 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; 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; 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; 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; 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; Ну и результат Изменено 28 сентября, 2017 пользователем Boobrilla Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 28 сентября, 2017 Опубликовано 28 сентября, 2017 (изменено) · Жалоба А вот у Вас в модуле 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; Изменено 28 сентября, 2017 пользователем Flip-fl0p Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Boobrilla 0 28 сентября, 2017 Опубликовано 28 сентября, 2017 · Жалоба По портам не заметил) Но, видимо, ISE позволяет) (оба in). По поводу подхода "в лоб" - я слишком еще не опытен. Лучше сделать так, как точно будет работать) Ну а если нужно будет изменить длину задержки, то просто добавлять/удалять кол-во переменных действий) В моем случае задержка была 190 ns = 19 по 10 ns. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 28 сентября, 2017 Опубликовано 28 сентября, 2017 · Жалоба По портам не заметил) Но, видимо, ISE позволяет) (оба in). По поводу подхода "в лоб" - я слишком еще не опытен. Лучше сделать так, как точно будет работать) Ну а если нужно будет изменить длину задержки, то просто добавлять/удалять кол-во переменных действий) В моем случае задержка была 190 ns = 19 по 10 ns. А если задержка 1000 ns ? Тогда 100 по 10 ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Boobrilla 0 28 сентября, 2017 Опубликовано 28 сентября, 2017 (изменено) · Жалоба Ну выходит что так) Но я бы просто тогда наверно вермя такта менял, если бы этого позволяло задание Изменено 28 сентября, 2017 пользователем Boobrilla Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Maverick_ 15 28 сентября, 2017 Опубликовано 28 сентября, 2017 · Жалоба Ну выходит что так) Но я бы просто тогда наверно вермя такта менял, если бы этого позволяло задание где тестбенч для симуляции? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Boobrilla 0 2 октября, 2017 Опубликовано 2 октября, 2017 · Жалоба где тестбенч для симуляции? Тестбенч не кидал, ибо он стандартно "пустой", ничего не добавлял. Кроме наверное ресета = 1 . 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; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Bad0512 2 3 октября, 2017 Опубликовано 3 октября, 2017 · Жалоба Ну и результат Какой SFDR у вас в итоге получился? Сколько ресурсов при этом было сожрано? По сравнению с классической DDS (четверть периода в RAM block плюс логика управления) какие преимущества у вашего решения? Ну и более глобальный вопрос ( на вырост ) : с какой целью все эти усилия по изобретению очередного велосипеда? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Amurak 0 3 октября, 2017 Опубликовано 3 октября, 2017 · Жалоба Ну и более глобальный вопрос ( на вырост ) : с какой целью все эти усилия по изобретению очередного велосипеда? Сейчас отобьете у человека желание заниматься проектированием ПЛИС. :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 3 октября, 2017 Опубликовано 3 октября, 2017 · Жалоба Сейчас отобьете у человека желание заниматься проектированием ПЛИС. :) То что человек выложил готовый модуль - это хорошо, честь ему и хвала за старание и плюсик в карму. То что модуль задокументирован чуть больше чем никак - это плохо. Ибо отсутствие какой-либо документации кода (хотя бы комментариев) сводит на нет всю пользу модуля. Проще с нуля написать, чем разобраться в этом коде. Тем более, по моему скромному мнению, многие куски кода написаны уж больно "некрасиво". Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться