mcaffee 0 5 сентября, 2015 Опубликовано 5 сентября, 2015 · Жалоба Всем доброго времени суток! Среди поисков алгоритмов dds нашел вот такой код. Из этого кода все, что я понял, так это то, что 40 рязрядный сумматор разбит на десять 4-х разрядных сумматоров. Не могли бы Вы описать более подробную картину, что здесь происходит?) long_code_here = library ieee; USE IEEE.std_logic_1164.all; USE IEEE.std_logic_arith.all; entity Accumulator is port ( clk : in std_logic; rst : in std_logic; wr : in std_logic; D : in std_logic_vector (39 downto 0); S : out std_logic_vector (39 downto 0) ); end Accumulator; architecture rtl of Accumulator is component Adder_4bit is port ( clk : in std_logic; rst : in std_logic; A : in std_logic_vector (3 downto 0); B : in std_logic_vector (3 downto 0); cin : in std_logic; S : out std_logic_vector (3 downto 0); cout : out std_logic ); end component; component my_reg is generic ( size : integer range 1 to 255:=1; W : integer range 1 to 32:=4 ); port ( clk : in std_logic; rst : in std_logic; wr : in std_logic; D : in std_logic_vector (W-1 downto 0); Q : out std_logic_vector (W-1 downto 0) ); end component; type result_type is array(9 downto 0) of std_logic_vector(3 downto 0); signal res0, res1, res, input : result_type:=(others=>(others=>'0')); signal carry_chain0, carry_chain1, carry_chain : std_logic_vector (9 downto 0):=(others=>'0'); begin inputs : for i in 1 to 10 generate reg_chain : my_reg generic map (i, 4) port map (clk, rst, D(4*i-1 downto 4*(i-1)), input(i-1)); end generate; first_adder : Adder_4bit port map (clk, rst, input(0), res(0), '0', res(0), carry_chain(0)); adders : for i in 1 to 9 generate carry : Adder_4bit port map (clk, rst, input(i), res(i), '1', res1(i), carry_chain1(i)); no_carry : Adder_4bit port map (clk, rst, input(i), res(i), '0', res0(i), carry_chain0(i)); end generate; sum_mux : for i in 1 to 9 generate res(i)<= res0(i) when carry_chain(i-1)='0' else res1(i); carry_chain(i)<= carry_chain0(i) when carry_chain(i-1)='0' else carry_chain1(i); end generate; output_assign : for i in 1 to 10 generate S(4*i-1 downto 4*(i-1))<=res(i-1); end generate; end rtl; Далее идет описание компонента Adder_4bit long_code_here = library ieee; USE IEEE.std_logic_1164.all; USE IEEE.std_logic_unsigned.all; USE IEEE.std_logic_arith.all; entity Adder_4bit is port ( clk : in std_logic; rst : in std_logic; A : in std_logic_vector (3 downto 0); B : in std_logic_vector (3 downto 0); cin : in std_logic; S : out std_logic_vector (3 downto 0); cout : out std_logic ); end Adder_4bit; architecture rtl of Adder_4bit is signal sum : std_logic_vector (4 downto 0); signal op1, op2 : std_logic_vector (3 downto 0); begin process (rst,clk) begin if (rst='1') then sum<=(others=>'0'); elsif (clk'event and clk='1') then sum <= ('0' & A)+('0' & B )+cin; end if; end process; S <= sum(3 downto 0); cout <= sum(4); end rtl; И компонента my_reg long_code_here = library ieee; USE IEEE.std_logic_1164.all; USE IEEE.std_logic_unsigned.all; entity my_reg is generic ( size : integer range 1 to 255:=1; W : integer range 1 to 32:=4 ); port ( -- Системный интерфейс clk : in std_logic; rst : in std_logic; wr : in std_logic; D : in std_logic_vector (W-1 downto 0); Q : out std_logic_vector (W-1 downto 0) ); end my_reg; architecture rtl of my_reg is type reg_chain_type is array (size-1 downto 0) of std_logic_vector (W-1 downto 0); signal reg_chain : reg_chain_type; signal ena_chain : std_logic_vector (size-1 downto 0); begin process (clk, rst) begin if (rst='1') then ena_chain<=(others=>'0'); elsif (clk'event and clk='1') then ena_chain(0)<='1'; if (size>1) then for i in 1 to size-1 loop ena_chain(i)<=ena_chain(i-1); end loop; end if; end if; end process; process (rst, clk) begin if (rst='1') then reg_chain<=(others=>(others=>'0')); elsif (clk'event and clk='1') then if (ena_chain(0)='1') then reg_chain(0)<=D; end if; if (size>1) then for i in 1 to size-1 loop if (ena_chain(i)='1') then reg_chain(i)<=reg_chain(i-1); end if; end loop; end if; end if; end process; Q<=reg_chain(size-1); end rtl; Здесь, в таких тонкостях, еще хуже. … не понятно, как это функционирует все вместе… Подскажите, поделитесь своими мыслями!) Хочу разобраться для начала с этим, поскольку дальше еще используется перекодировка с таблицей синусов. Заранее большое спасибо всем откликнувшимся!) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Krys 2 8 сентября, 2015 Опубликовано 8 сентября, 2015 · Жалоба Предлагаю для начала ознакомиться с готовыми реализациями: xilinx dds compiler, начиная со стр. 11 там дана теория вопроса. Может, тогда станет понятнее, откуда взялся такой код. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Artemius_tv 0 8 сентября, 2015 Опубликовано 8 сентября, 2015 · Жалоба Сумматор разбит на 10 маленьких для организации конвеера, чтобы повысить скорость работы. К алгоритму это все отношения не имеет. Поначалу можно заменить простым аккумулятором, а если не будет хватать скорости, уже думать об оптимизации. А если надо разобраться именно с этим кодом, лучше его просимулировать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mcaffee 0 21 сентября, 2015 Опубликовано 21 сентября, 2015 · Жалоба В продолжении обсуждения вопроса про dds. С выхода накопительного сумматора берем 10 старших разрядов и с помощью таблицы синусов вычисляем значения амплитуды. Есть вот такой код: library ieee; USE IEEE.std_logic_1164.all; USE IEEE.std_logic_unsigned.all; entity Sin_func is port( clk : in std_logic; rst : in std_logic; Din : in std_logic_vector(9 downto 0); -- входные данные. это 10 страших разрядов с выхода накопительного сумматора. Sout : out std_logic_vector (11 downto 0) -- выходные данные. Значения идут на цап. (амплитуда синуса) ); end Sin_func; architecture rtl of Sin_func is type sin_type is array(31 downto 0) of std_logic_vector(11 downto 0); signal Reg : sin_type; signal In_reg : std_logic_vector (9 downto 0); begin table0: process(clk, rst) begin if (rst='1') then Reg(0) <= (others=>'0'); elsif(clk'event and clk='1') then case Din(4 downto 0) is when "00000" => Reg(0) <= "011111111111"; when "00001" => Reg(0) <= "100000001011"; when "00010" => Reg(0) <= "100000011000"; when "00011" => Reg(0) <= "100000100100"; when "00100" => Reg(0) <= "100000110001"; when "00101" => Reg(0) <= "100000111101"; when "00110" => Reg(0) <= "100001001010"; when "00111" => Reg(0) <= "100001010110"; when "01000" => Reg(0) <= "100001100011"; when "01001" => Reg(0) <= "100001110000"; when "01010" => Reg(0) <= "100001111100"; when "01011" => Reg(0) <= "100010001001"; when "01100" => Reg(0) <= "100010010101"; when "01101" => Reg(0) <= "100010100010"; when "01110" => Reg(0) <= "100010101110"; when "01111" => Reg(0) <= "100010111011"; when "10000" => Reg(0) <= "100011000111"; when "10001" => Reg(0) <= "100011010100"; when "10010" => Reg(0) <= "100011100000"; when "10011" => Reg(0) <= "100011101101"; when "10100" => Reg(0) <= "100011111001"; when "10101" => Reg(0) <= "100100000110"; when "10110" => Reg(0) <= "100100010010"; when "10111" => Reg(0) <= "100100011111"; when "11000" => Reg(0) <= "100100101011"; when "11001" => Reg(0) <= "100100111000"; when "11010" => Reg(0) <= "100101000100"; when "11011" => Reg(0) <= "100101010000"; when "11100" => Reg(0) <= "100101011101"; when "11101" => Reg(0) <= "100101101001"; when "11110" => Reg(0) <= "100101110110"; when "11111" => Reg(0) <= "100110000010"; when others => Reg(0) <= "000000000000"; end case; end if; end process; table1: process(clk, rst) begin if (rst='1') then Reg(1) <= (others=>'0'); elsif(clk'event and clk='1') then case Din(4 downto 0) is when "00000" => Reg(1) <= "100110001110"; when "00001" => Reg(1) <= "100110011011"; when "00010" => Reg(1) <= "100110100111"; и так далее... всего 32 таких таблицы. process(clk, rst) begin if (rst='1') then In_reg <= (others=>'0'); elsif (clk'event and clk='1')then In_reg <= Din; end if; end process; Sout <= Reg (conv_integer(In_reg(9 downto 5))); end architecture rtl; Как видно, здесь значения аргумента принимают значения от 0 до 31. каждому значению фазы ставится в соответствие значение амплитуды синуса. Din это 10 старших разрядов с выхода сумматора. Непонятно почему берется только 5 младших разрядов от Din и им ставится в соответсвие значение амплитуды. и непонятно, что значит предпоследняя строчка, где задействованы 5 старших разрядов от входных данных.. Sout <= Reg (conv_integer(In_reg(9 downto 5))); Подскажите, пожалуйста, поделитесь мыслями. Заранее большое спасибо!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Krys 2 21 сентября, 2015 Опубликовано 21 сентября, 2015 · Жалоба Вобщем, здесь тоже разбито на 2 стадии. Вся таблица содержит 1024 ячейки, она логически разбита на 32 подтаблицы по 32 ячейки. Значение из подтаблицы выбирается на первом такте. А сама подтаблица выбирается на 2м такте. Разбивка на 5 битов адресации очень удобна: дело в том, что в Xilinx LUTы могут иметь 2 выхода и 5 входов, если входы одинаковые (что и есть в нашем случае). Таким образом хорошо экономятся ресурсы. Ну вкратце так. Если что неясно описал - спрашивайте, какое конкретно место непонятно в объяснениях. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mcaffee 0 21 сентября, 2015 Опубликовано 21 сентября, 2015 · Жалоба Вобщем, здесь тоже разбито на 2 стадии. Вся таблица содержит 1024 ячейки, она логически разбита на 32 подтаблицы по 32 ячейки. Значение из подтаблицы выбирается на первом такте. А сама подтаблица выбирается на 2м такте. Разбивка на 5 битов адресации очень удобна: дело в том, что в Xilinx LUTы могут иметь 2 выхода и 5 входов, если входы одинаковые (что и есть в нашем случае). Таким образом хорошо экономятся ресурсы. Ну вкратце так. Если что неясно описал - спрашивайте, какое конкретно место непонятно в объяснениях. Да))) теперь стало понятно! Большое спасибо!! Но есть еще вопрос.. А если нужно взять не 10, а 12 старших разрядов, то тогда у нас уже будет 4096 ячеек во всей таблице и 64 подтаблицы с 64 ячейками, так?) Но тут скорее всего не хватит ресурсов под такую таблицу( задумался над укорачиванием таблицы. Сделал расчет для четверти периода. Тогда получится 16 подтаблиц с 64 ячейками. Так?) получается во всей таблице записано 1024 значения, от нуля до макс. Но как сделать так, чтобы и на оставшиеся 3/4 периода была адресация и высчитывались значения, и чтобы в итоге получился целый синус? Большое спасибо!) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Artemius_tv 0 21 сентября, 2015 Опубликовано 21 сентября, 2015 (изменено) · Жалоба Самый старший (12-й) бит будет отвечать за знак, а 11-й за инвертирование фазы. Получается 11-й бит будет использоваться до регистров Reg, поэтому, наверное, лучше 32 таблицы на 32 значения. Таблицу нужно будет пересчитать (наверное, просто сдвинуть вниз и отбросить старший бит). Будет что-то вроде: ..... signal Din_1 : std_logic_vector (9 downto 0); ..... Din_1 <= Din(9 downto 0) when (Din(10) = '0') else "1111111111" - Din(9 downto 0); table0: process(clk, rst) begin if (rst='1') then Reg(0) <= (others=>'0'); elsif(clk'event and clk='1') then case Din_1(4 downto 0) is when "00000" => Reg(0) <= "000000000000"; when "00001" => Reg(0) <= "000000001010"; ..... process(clk, rst) begin if (rst='1') then In_reg <= (others=>'0'); elsif (clk'event and clk='1')then In_reg(11 downto 10) <= Din; In_reg(9 downto 0) <= Din_1; end if; end process; Sout <= "111111111111" + Reg (conv_integer(In_reg(9 downto 5))) when (In_reg(11) = '0'); else "111111111111" - Reg (conv_integer(In_reg(9 downto 5))); Надеюсь, нигде не ошибся. Изменено 21 сентября, 2015 пользователем Artemius_tv Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mcaffee 0 21 сентября, 2015 Опубликовано 21 сентября, 2015 (изменено) · Жалоба Самый старший (12-й) бит будет отвечать за знак, а 11-й за инвертирование фазы. Получается 11-й бит будет использоваться до регистров Reg, поэтому, наверное, лучше 32 таблицы на 32 значения. Таблицу нужно будет пересчитать (наверное, просто сдвинуть вниз и отбросить старший бит). Будет что-то вроде: ..... signal Din_1 : std_logic_vector (9 downto 0); ..... Din_1 <= Din(9 downto 0) when (Din(10) = '0') else "1111111111" - Din(9 downto 0); table0: process(clk, rst) begin if (rst='1') then Reg(0) <= (others=>'0'); elsif(clk'event and clk='1') then case Din_1(4 downto 0) is when "00000" => Reg(0) <= "000000000000"; when "00001" => Reg(0) <= "000000001010"; ..... process(clk, rst) begin if (rst='1') then In_reg <= (others=>'0'); elsif (clk'event and clk='1')then In_reg(11 downto 10) <= Din; In_reg(9 downto 0) <= Din_1; end if; end process; Sout <= "111111111111" + Reg (conv_integer(In_reg(9 downto 5))) when (In_reg(11) = '0'); else "111111111111" - Reg (conv_integer(In_reg(9 downto 5))); Надеюсь, нигде не ошибся. Большое Вам спасибо!! Подскажите, а вот тут все правильно? In_reg(11 downto 10) <= Din; In_reg(9 downto 0) <= Din_1; Din же (11 downto 0). Наверное и In_reg тоже должен быть (11 downto 0). Или именно 11 downto 10?? И зачем мы в In_reg 2 раза перезаписываем тогда? А если будет так, что в этой записи Sout <= "111111111111" + Reg (conv_integer(In_reg(9 downto 5))), у Reg (conv_integer(In_reg(9 downto 5)) будут одни нули, то тогда на все разряды цапа будут поданы "1". получается, что это -1, но как это воспримет цап? в десятичной системе амплитуда синуса принимает значения от -1 до 511 и дальше вниз до 0, до -511 и снова до 0. Как такие числа воспримет цап? Подскажите, запутался совсем... Изменено 21 сентября, 2015 пользователем mcaffee Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Krys 2 22 сентября, 2015 Опубликовано 22 сентября, 2015 · Жалоба А какой ЦАП? Надо на него доку читануть, из неё станет понятно. А если нужно взять не 10, а 12 старших разрядов, то тогда у нас уже будет 4096 ячеек во всей таблице и 64 подтаблицы с 64 ячейками, так?)Чото теперь уже я не понял: у Вас весь синус 12 битов аргумент имеет? Тогда таблица на 10 битов аргумента так и остаётся. Это четверть периода. А старшие 2 бита, как написали, указывают, как эту четверть развернуть, чтобы получить результат в нужном квадранте. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mcaffee 0 22 сентября, 2015 Опубликовано 22 сентября, 2015 · Жалоба А какой ЦАП? Надо на него доку читануть, из неё станет понятно. Чото теперь уже я не понял: у Вас весь синус 12 битов аргумент имеет? Тогда таблица на 10 битов аргумента так и остаётся. Это четверть периода. А старшие 2 бита, как написали, указывают, как эту четверть развернуть, чтобы получить результат в нужном квадранте. ЦАП планируется применять вот такой: 1273 па4т ( он вообще 14 разрядный) Да, согласен, в таблице у аргумента будет 10 разрядов и амплитуда там принимает значения от 0 до 1023. Всего 1024 значения и 32 на 32. Но вот как правильно описать как эти четверти развернуть, чтобы все правильно получилось?) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Artemius_tv 0 22 сентября, 2015 Опубликовано 22 сентября, 2015 (изменено) · Жалоба Подскажите, а вот тут все правильно? Нет, конечно же я наошибался. Надо In_reg(11 downto 10) <= Din(11 downto 10); In_reg(9 downto 0) <= Din_1; На следующий такт передаем старшие 2 бита в неизменном виде, а младшие 10 бит уже перевернутые или нет в соответствии с Din(10). Хотя Reg(4 downto 0) и Reg(10) все равно не используются. И с Sout <= "111111111111" + Reg (conv_integer(In_reg(9 downto 5))) when (In_reg(11) = '0'); else "111111111111" - Reg (conv_integer(In_reg(9 downto 5))); тоже ошибся, надо "011111111111" или "100000000000" Кстати, насколько я помню, количество используемых разрядов фазы должно быть больше разрядности ЦАП. В AD9834 ЦАП 10-битный и используют 12 бит фазы, AD9854 ЦАП 12-бит и 14 бит фазы. Т.е. для 14-разрядного ЦАП'а 12 бит фазы это мало. Изменено 22 сентября, 2015 пользователем Artemius_tv Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Krys 2 22 сентября, 2015 Опубликовано 22 сентября, 2015 · Жалоба А ПЛИС какая, что ресурсов на таблицу не хватит? Бывает ещё на блочной памяти делают таблицу, а не на LUT. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 22 сентября, 2015 Опубликовано 22 сентября, 2015 · Жалоба Кстати, насколько я помню, количество используемых разрядов фазы должно быть больше разрядности ЦАП. Это для лучшей характеристики по сигнал/шум ДДС, там дополнительные разряды добавляются и четность фазы ломается и другие хитрости делаются, это уже следующий этап для ТС. Это все до таблицы должно быть, битность таблицы должна быть как у ЦАПа со всеми расширениями, потому что иначе это хранение лишней информации. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Krys 2 22 сентября, 2015 Опубликовано 22 сентября, 2015 · Жалоба Тем более, что это всё в теории описано в том документе от Xilinx, ссылку на который я давал в начале Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Krys 2 22 сентября, 2015 Опубликовано 22 сентября, 2015 · Жалоба А если будет так, что в этой записи Sout <= "111111111111" + Reg (conv_integer(In_reg(9 downto 5))), у Reg (conv_integer(In_reg(9 downto 5)) будут одни нули, то тогда на все разряды цапа будут поданы "1". получается, что это -1, но как это воспримет цап? в десятичной системе амплитуда синуса принимает значения от -1 до 511 и дальше вниз до 0, до -511 и снова до 0. Как такие числа воспримет цап? Подскажите, запутался совсем... ЦАП планируется применять вот такой: 1273 па4т ( он вообще 14 разрядный) Доку то на цап читали? Там поди есть ответы ))) Но вот как правильно описать как эти четверти развернуть, чтобы все правильно получилось?)Вы нарисуйте период синуса на бумажке. Увидите там 4 повторяющиеся части ))) Но правильнее увидеть сначала 2 крупные повторяющиеся части (полупериоды), а в каждой из частей ещё 2 мелкие повторяющиеся части (четверти). Закономерности: 1. Полупериоды просто имеют противоположный знак. За полупериоды отвечает старший бит аргумента (поскольку это самые крупные повторяющиеся части). 2. Четвертинки имеют обратную зависимость от аргумента: т.е. если аргумент таблицы в первой четвертинке меняется от 0 до 1023, то во второй четвертинке он должен меняться от 1023 до 0. За четвертинки отвечает следующий от старшего бит аргумента. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться