|
помогите разобраться с кодом |
|
|
|
Sep 5 2015, 16:27
|
Участник

Группа: Участник
Сообщений: 46
Регистрация: 9-10-12
Пользователь №: 73 873

|
Всем доброго времени суток! Среди поисков алгоритмов dds нашел вот такой код. Из этого кода все, что я понял, так это то, что 40 рязрядный сумматор разбит на десять 4-х разрядных сумматоров. Не могли бы Вы описать более подробную картину, что здесь происходит?) CODE 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 CODE 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 CODE 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;
Здесь, в таких тонкостях, еще хуже. … не понятно, как это функционирует все вместе… Подскажите, поделитесь своими мыслями!) Хочу разобраться для начала с этим, поскольку дальше еще используется перекодировка с таблицей синусов. Заранее большое спасибо всем откликнувшимся!)
|
|
|
|
|
Sep 8 2015, 06:07
|
Участник

Группа: Участник
Сообщений: 32
Регистрация: 1-04-15
Из: Тверь
Пользователь №: 86 019

|
Сумматор разбит на 10 маленьких для организации конвеера, чтобы повысить скорость работы. К алгоритму это все отношения не имеет. Поначалу можно заменить простым аккумулятором, а если не будет хватать скорости, уже думать об оптимизации.
А если надо разобраться именно с этим кодом, лучше его просимулировать.
|
|
|
|
|
Sep 21 2015, 10:34
|
Участник

Группа: Участник
Сообщений: 46
Регистрация: 9-10-12
Пользователь №: 73 873

|
В продолжении обсуждения вопроса про dds. С выхода накопительного сумматора берем 10 старших разрядов и с помощью таблицы синусов вычисляем значения амплитуды. Есть вот такой код: CODE
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))); Подскажите, пожалуйста, поделитесь мыслями. Заранее большое спасибо!!
|
|
|
|
|
Sep 21 2015, 11:54
|
Участник

Группа: Участник
Сообщений: 46
Регистрация: 9-10-12
Пользователь №: 73 873

|
Цитата(Krys @ Sep 21 2015, 15:00)  Вобщем, здесь тоже разбито на 2 стадии. Вся таблица содержит 1024 ячейки, она логически разбита на 32 подтаблицы по 32 ячейки. Значение из подтаблицы выбирается на первом такте. А сама подтаблица выбирается на 2м такте. Разбивка на 5 битов адресации очень удобна: дело в том, что в Xilinx LUTы могут иметь 2 выхода и 5 входов, если входы одинаковые (что и есть в нашем случае). Таким образом хорошо экономятся ресурсы. Ну вкратце так. Если что неясно описал - спрашивайте, какое конкретно место непонятно в объяснениях. Да))) теперь стало понятно! Большое спасибо!! Но есть еще вопрос.. А если нужно взять не 10, а 12 старших разрядов, то тогда у нас уже будет 4096 ячеек во всей таблице и 64 подтаблицы с 64 ячейками, так?) Но тут скорее всего не хватит ресурсов под такую таблицу( задумался над укорачиванием таблицы. Сделал расчет для четверти периода. Тогда получится 16 подтаблиц с 64 ячейками. Так?) получается во всей таблице записано 1024 значения, от нуля до макс. Но как сделать так, чтобы и на оставшиеся 3/4 периода была адресация и высчитывались значения, и чтобы в итоге получился целый синус? Большое спасибо!)
|
|
|
|
|
Sep 21 2015, 13:16
|
Участник

Группа: Участник
Сообщений: 32
Регистрация: 1-04-15
Из: Тверь
Пользователь №: 86 019

|
Самый старший (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))); Надеюсь, нигде не ошибся.
Сообщение отредактировал Artemius_tv - Sep 21 2015, 13:23
|
|
|
|
|
Sep 21 2015, 21:37
|
Участник

Группа: Участник
Сообщений: 46
Регистрация: 9-10-12
Пользователь №: 73 873

|
Цитата(Artemius_tv @ Sep 21 2015, 17:16)  Самый старший (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. Как такие числа воспримет цап? Подскажите, запутался совсем...
Сообщение отредактировал mcaffee - Sep 21 2015, 22:17
|
|
|
|
|
Sep 22 2015, 05:06
|

Гуру
     
Группа: Свой
Сообщений: 2 002
Регистрация: 17-01-06
Из: Томск, Россия
Пользователь №: 13 271

|
А какой ЦАП? Надо на него доку читануть, из неё станет понятно. Цитата(mcaffee @ Sep 21 2015, 18:54)  А если нужно взять не 10, а 12 старших разрядов, то тогда у нас уже будет 4096 ячеек во всей таблице и 64 подтаблицы с 64 ячейками, так?) Чото теперь уже я не понял: у Вас весь синус 12 битов аргумент имеет? Тогда таблица на 10 битов аргумента так и остаётся. Это четверть периода. А старшие 2 бита, как написали, указывают, как эту четверть развернуть, чтобы получить результат в нужном квадранте.
--------------------
Зная себе цену, нужно ещё и пользоваться спросом...
|
|
|
|
|
Sep 22 2015, 05:38
|
Участник

Группа: Участник
Сообщений: 46
Регистрация: 9-10-12
Пользователь №: 73 873

|
Цитата(Krys @ Sep 22 2015, 09:06)  А какой ЦАП? Надо на него доку читануть, из неё станет понятно.
Чото теперь уже я не понял: у Вас весь синус 12 битов аргумент имеет? Тогда таблица на 10 битов аргумента так и остаётся. Это четверть периода. А старшие 2 бита, как написали, указывают, как эту четверть развернуть, чтобы получить результат в нужном квадранте. ЦАП планируется применять вот такой: 1273 па4т ( он вообще 14 разрядный) Да, согласен, в таблице у аргумента будет 10 разрядов и амплитуда там принимает значения от 0 до 1023. Всего 1024 значения и 32 на 32. Но вот как правильно описать как эти четверти развернуть, чтобы все правильно получилось?)
|
|
|
|
|
Sep 22 2015, 06:58
|
Участник

Группа: Участник
Сообщений: 32
Регистрация: 1-04-15
Из: Тверь
Пользователь №: 86 019

|
Цитата(mcaffee @ Sep 22 2015, 00:37)  Подскажите, а вот тут все правильно? Нет, конечно же я наошибался. Надо Код 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 бит фазы это мало.
Сообщение отредактировал Artemius_tv - Sep 22 2015, 07:18
|
|
|
|
|
Sep 22 2015, 11:11
|

Гуру
     
Группа: Свой
Сообщений: 2 002
Регистрация: 17-01-06
Из: Томск, Россия
Пользователь №: 13 271

|
Цитата(mcaffee @ Sep 22 2015, 04:37)  А если будет так, что в этой записи 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. Как такие числа воспримет цап? Подскажите, запутался совсем... Цитата(mcaffee @ Sep 22 2015, 12:38)  ЦАП планируется применять вот такой: 1273 па4т ( он вообще 14 разрядный) Доку то на цап читали? Там поди есть ответы ))) Цитата(mcaffee @ Sep 22 2015, 12:38)  Но вот как правильно описать как эти четверти развернуть, чтобы все правильно получилось?) Вы нарисуйте период синуса на бумажке. Увидите там 4 повторяющиеся части ))) Но правильнее увидеть сначала 2 крупные повторяющиеся части (полупериоды), а в каждой из частей ещё 2 мелкие повторяющиеся части (четверти). Закономерности: 1. Полупериоды просто имеют противоположный знак. За полупериоды отвечает старший бит аргумента (поскольку это самые крупные повторяющиеся части). 2. Четвертинки имеют обратную зависимость от аргумента: т.е. если аргумент таблицы в первой четвертинке меняется от 0 до 1023, то во второй четвертинке он должен меняться от 1023 до 0. За четвертинки отвечает следующий от старшего бит аргумента.
--------------------
Зная себе цену, нужно ещё и пользоваться спросом...
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|