artyombn 0 20 мая, 2017 Опубликовано 20 мая, 2017 · Жалоба День добрый, уважаемые форумчане. Я новенький в VHDL, и первое задание мое было это восьмиразрядный тактовый умножитель . Причем не банальным способом где a*b, а иным. Немного поискав информации в интернете я нашел способ, получил умножитель в виде счетчика с регистром сдвига. В общем вот код. library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_unsigned.all; entity test is port( clk, r: in std_logic; a : in std_logic_vector(7 downto 0); b : in std_logic_vector(7 downto 0); p : out std_logic_vector(15 downto 0) ); end test; --}} End of automatically maintained section architecture test of test is begin process(clk,r,a,b) variable pv,bp: std_logic_vector(15 downto 0); begin pv:= "0000000000000000"; bp:= "00000000" & b; if r='1' then pv:="0000000000000000"; p<=pv; else if clk'event and clk = '1' then for i in 0 to 7 loop if a(i) = '1' then pv:= pv+bp; p<=pv; end if; bp:= bp(14 downto 0) & '0'; end loop; end if; end if; end process; end test; а вот результат моделирования. Как видите все работает. Но возникает вопрос. Почему он выдает результат сразу за 1 такт, а не за 8 тактов как должно быть? ведь каждое начало цикла должно входить в 1 такт. а тут сразу весь цикл в такт входит. Но мне нужен тактовый умножитель, чтобы за каждый такт он делал сложение pv с bp и последующим сдвигом влево. Подскажите как сделать так чтобы результат умножения был за 8 тактов а не за 1. Если есть возможность, желательно подскажите на примере, так как я начинающий в этом деле на словах могу не понять. Спасибо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Maverick_ 15 20 мая, 2017 Опубликовано 20 мая, 2017 · Жалоба День добрый, уважаемые форумчане. Спасибо. еще это можете посмотреть + иное описание (при реализации в "лоб" просидает тактовая частота (получается не высокой), т.е. как i_ma* i_mb) library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity mult_pipe is port ( i_clk : in std_logic; i_rstb : in std_logic; i_ma : in std_logic_vector(34 downto 0); i_mb : in std_logic_vector(34 downto 0); o_m : out std_logic_vector(69 downto 0)); end mult_pipe; architecture rtl of mult_pipe is -- A[34:17] x 2^17 +A[16:0]) x (B[34:17] x 2^17 +B[16:0]) = -- A[34:17] x B[34:17] x2^34 +(A[34:17] x B[16:0] + A[16:0] x B[34:17] )x2^17 + A[16:0] x B[16:0] type p_operand_hi is array(0 to 3) of signed(17 downto 0); type p_operand_lo is array(0 to 3) of signed(16 downto 0); signal p_ma_hi : p_operand_hi; signal p_ma_lo : p_operand_lo; signal p_mb_hi : p_operand_hi; signal p_mb_lo : p_operand_lo; signal r_p1 : signed(35 downto 0); -- 18x18 => 36 bit (34 + 2 sgn bit) signal r_p2 : signed(35 downto 0); -- 18x18 => 36 bit (35 + 1 sgn bit) signal r_p3 : signed(35 downto 0); -- 18x18 => 36 bit (35 + 1 sgn bit) signal r_p4 : signed(35 downto 0); -- 18x18 => 36 bit signal r_m1 : signed(35 downto 0); -- 18x18 => 36 bit (34 + 2 sgn bit) signal r_m2 : signed(35 downto 0); -- 18x18 => 36 bit (35 + 1 sgn bit) signal r_m3 : signed(35 downto 0); -- 18x18 => 36 bit (35 + 1 sgn bit) signal r_m4 : signed(35 downto 0); -- 18x18 => 36 bit signal p_m1 : p_operand_lo; -- delay compensation signal p_m3 : signed(16 downto 0); -- delay compensation begin o_m(69 downto 34) <= std_logic_vector(r_m4(35 downto 0)); o_m(33 downto 17) <= std_logic_vector(p_m3); o_m(16 downto 0) <= std_logic_vector(p_m1(2)); p_mult : process(i_clk,i_rstb) begin if(i_rstb='0') then p_ma_hi <= (others=>(others=>'0')); p_ma_lo <= (others=>(others=>'0')); p_mb_hi <= (others=>(others=>'0')); p_mb_lo <= (others=>(others=>'0')); p_m1 <= (others=>(others=>'0')); p_m3 <= (others=>'0'); r_m1 <= (others=>'0'); r_m2 <= (others=>'0'); r_m3 <= (others=>'0'); r_m4 <= (others=>'0'); p_m1 <= (others=>(others=>'0')); p_m3 <= (others=>'0'); elsif(rising_edge(i_clk)) then p_ma_hi <= signed(i_ma(34 downto 17))&p_ma_hi(0 to p_ma_hi'length-2); p_ma_lo <= signed(i_ma(16 downto 0))&p_ma_lo(0 to p_ma_lo'length-2); p_mb_hi <= signed(i_mb(34 downto 17))&p_mb_hi(0 to p_mb_hi'length-2); p_mb_lo <= signed(i_mb(16 downto 0))&p_mb_lo(0 to p_mb_lo'length-2); p_m1 <= r_m1(16 downto 0)&p_m1(0 to p_m1'length-2); p_m3 <= r_m3(16 downto 0); r_p1 <= signed('0'&p_ma_lo(0)) * signed('0'&p_mb_lo(0)); r_p2 <= signed('0'&p_ma_lo(1)) * p_mb_hi(1); r_p3 <= p_ma_hi(2) * signed('0'&p_mb_lo(2)); r_p4 <= p_ma_hi(3) * p_mb_hi(3); r_m1 <= r_p1; r_m2 <= r_p2 + r_m1(34 downto 17); r_m3 <= r_p3 + r_m2; r_m4 <= r_p4 + r_m3(35 downto 17); end if; end process p_mult; end rtl; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
artyombn 0 20 мая, 2017 Опубликовано 20 мая, 2017 (изменено) · Жалоба если смотреть на код, то тут просто в лоб a*b ) чего мне не нужно. подскажите, если вы знаете, как сделать так, чтобы мой умножитель делал каждое действие сложения по такту. наверное нужен особенный клок? вот я этого понять не могу. если просто тупо убрать цикл и попробовать прописать все условия if a(0)='1' ..... if a(1)='1'.... все равно он мне все делает за 1 такт. я не знаю как сделать чтобы каждое действие (pv+ bp и сдвиг bp влево) делалось за 1 такт. Изменено 20 мая, 2017 пользователем artyombn Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dr.Alex 0 21 мая, 2017 Опубликовано 21 мая, 2017 · Жалоба подскажите, если вы знаете, как сделать так Студентов, которым готовый код нужен, тут не очень любят, а если хотите разобраться, то другое дело. loop надо убрать. Вместо этого инкрементируйте i (1 раз за такт clk, есесно :-) и в зависимости от его значения что-то делайте. И советую избавиться от переменных (используйте только сигналы), а то соседство блокирующих и неблокирующих назначений это для начинающего верный путь запутаться и ничего не понять. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
artyombn 0 21 мая, 2017 Опубликовано 21 мая, 2017 · Жалоба loop надо убрать. Вместо этого инкрементируйте i (1 раз за такт clk, есесно :-) и в зависимости от его значения что-то делайте. И советую избавиться от переменных (используйте только сигналы), а то соседство блокирующих и неблокирующих назначений это для начинающего верный путь запутаться и ничего не понять. loop убрал. инкрементирую i 1 раз за такт. возникает ряд вопросов. почему bp прыгает, сначала как полагается, оно равно 11, затем по единице clk становится 22 (тут произошел сдвиг влево), а затем по спаду оно становится равно опять 11. почему? оно ведь перезаписалось, и до следующего такта не должна меняться. из-за этого оно всегда будет меняться с 11 до 22. почему это условие if a(i) = '1' then pv<= pv+bp; end if; работает как цикл в одном такте импульса? я не понимаю почему такое банальное описание приводит к таким результатам. где я ошибаюсь? вот код с моделированием. library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_unsigned.all; use IEEE.NUMERIC_STD.all; entity test is port( clk, r: in std_logic; a : in std_logic_vector(7 downto 0); b : in std_logic_vector(7 downto 0); p : out std_logic_vector(15 downto 0) ); end test; --}} End of automatically maintained section architecture test of test is signal pv: std_logic_vector(15 downto 0):=(others => '0'); signal bp: std_logic_vector(15 downto 0); signal i : integer range 0 to 8; begin process(clk) begin bp<= "00000000" & b; if r='1' then pv<="0000000000000000"; p<=pv; i <= 0; else if (clk'event and clk = '1' and not(i=8)) then if a(i) = '1' then pv<= pv+bp; end if; bp<=bp(14 downto 0) & '0'; i<=i+1; p<=pv; end if; end if; end process; end test; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dr.Alex 0 21 мая, 2017 Опубликовано 21 мая, 2017 · Жалоба а затем по спаду оно становится равно опять 11. почему? Это происходит из-за верхней строчки bp<= "00000000" & b; У неё нет никаких условий, поэтому она срабатывает при любом изменении clk. Её нужно убрать, а как производить первоначальную загрузку bp — подумайте. Может быть стоит проверять условие i = 0 и тогда что-то делать? and not(i=8) тоже нужно убрать, так не пишут. почему это условие работает как цикл в одном такте импульса? я не понимаю почему такое банальное описание приводит к таким результатам. Не понял вопроса. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
artyombn 0 21 мая, 2017 Опубликовано 21 мая, 2017 (изменено) · Жалоба Это происходит из-за верхней строчки bp<= "00000000" & b; У неё нет никаких условий, поэтому она срабатывает при любом изменении clk. Её нужно убрать, а как производить первоначальную загрузку bp — подумайте. Может быть стоит проверять условие i = 0 и тогда что-то делать? and not(i=8) тоже нужно убрать, так не пишут. таким способом записать bp не получается: signal bp: std_logic_vector(15 downto 0):="00000000" & b; поэтому создал переменную load и сделал условие. if load = '1' then bp<= "00000000" & b; i<=0; end if; теперь возникают 2 вопроса. как избавиться от проскока значений bp=22 и i=1, которые срабатывают в условии при clk=1? и почему срабатывает условие if a(i)='1' , при i=1 (где a(1)=0) . т.е. мы наблюдаем что при i=1 pv=bp, хотя при i=1 по коду это условие не должно выполняться и просто должен произойти сдвиг bp. хотя я нашел выход) просто прописал условие в нужном месте begin if r='1' then pv<="0000000000000000"; p<=pv; i <= 0; else if load = '1' then bp<= "00000000" & b; i<=0; else if (clk'event and clk = '1' and not(i=8)) then if a(i) = '1' then pv<= pv+bp; end if; bp<=bp(14 downto 0) & '0'; i<=i+1; p<=pv; end if; end if; end if; почему нельзя писать not(i=8) при разводке в леонардо это скажется? и как остановить расчет иначе когда i достигнет 8? Изменено 21 мая, 2017 пользователем artyombn Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dr.Alex 0 21 мая, 2017 Опубликовано 21 мая, 2017 · Жалоба signal bp: std_logic_vector(15 downto 0):="00000000" & b; Так и не нужно. поэтому создал переменную load и сделал условие. А вот это уже правильно. Поскоку устройство не может принимать данные в каждом такте, то в перспективе оно должно сигнализировать наружу о своей готовности, готовности результата, а "наружа" должна сигнализировать загрузку новых данных (ваш load). теперь возникают 2 вопроса. Как сказал Мюллер, вы уже на полпути в успеху :-)))) А я ухожу, вернусь поздно вечером. почему нельзя писать not(i=8) при разводке в леонардо это скажется? и как остановить расчет иначе когда i достигнет 8? Ну не делают так. Когда расчёт закончен, нужно сигнализировать наружу о готовности результата и ждать следующего load. А пытаться остановить клок и ничё не делать нельзя. Ну и вообще, до хорошего стиля программирования мы ещё не дошли. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
artyombn 0 21 мая, 2017 Опубликовано 21 мая, 2017 (изменено) · Жалоба избавился от not(i=8) if load = '1' then bp<= "00000000" & b; else if (clk'event and clk = '1') then if a(i) = '1' then pv<= pv+bp; end if; bp<=bp(14 downto 0) & '0'; i<=i+1; if i<=8 then p<=pv; end if; end if; но я не знаю как остановить дальнейшее увеличение i. и ещё такой вопрос. если у нас load не доходит до фронта первого такта, то задержка выхода p составляет 1 такт. если load доходит или лежит в области первого такта, то задержка на выходе p составляет 2 такта. есть ли возможность избавиться от задержки? Изменено 21 мая, 2017 пользователем artyombn Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dr.Alex 0 21 мая, 2017 Опубликовано 21 мая, 2017 · Жалоба но я не знаю как остановить дальнейшее увеличение i. Да просто поставить условие. Если меньше чего-то, тогда инкрементируем. и ещё такой вопрос. если у нас load не доходит до фронта первого такта Как не доходит? Тогда данные не загрузятся (если только случайно). Он должен стоять одновременно с данными. есть ли возможность избавиться от задержки? p<=pv нужно вообще вынести из процесса, один такт уйдёт. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
artyombn 0 21 мая, 2017 Опубликовано 21 мая, 2017 (изменено) · Жалоба Да просто поставить условие. Если меньше чего-то, тогда инкрементируем. да, что-то сглупил в этом моменте. Как не доходит? Тогда данные не загрузятся (если только случайно). Он должен стоять одновременно с данными. вот результат если load не будет доходить до clk а вот результат если будет разницу не вижу. вижу задержку по такту. с одной стороны хорошо когда i на первом клоке равно 0, но тогда результат будет даже не за 9 тактов, а за 10. что ещё хуже. а нужно результат вообще за 8 тактов. p<=pv нужно вообще вынести из процесса, один такт уйдёт. вынес из процесса. он мне показывает неопределенное состояние. скорее всего потому что pv каждый раз меняет свое значение, а я прошу вывести общую p<=pv. поэтому он и не понимает какую нужно вывести. получается просто вынести pv из процесса не получится Изменено 21 мая, 2017 пользователем artyombn Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dr.Alex 0 21 мая, 2017 Опубликовано 21 мая, 2017 · Жалоба Проглядел немного что вы там понаписали.... Нельзя так писать, у вас лоад асинхронный получился. Шаблон такой: process begin wait until clk'event and clk = '1'; if load = '1' then что-то else if i < 8 then if i = 0 then что-то end if; что-то ещё else что-то end if; end if; end process; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
artyombn 0 21 мая, 2017 Опубликовано 21 мая, 2017 (изменено) · Жалоба if i = 0 then что-то end if; что-то ещё else что-то ; я не понял зачем тут if i=0 ? т.е. мне каждое изменение i описывать? к примеру как я понял: if i<8 then if i<=0 then if a(i) = '1' then pv<= pv+bp; end if; bp<=bp(14 downto 0) & '0'; i<=i+1; else if i<=1 then if a(i) = '1' then pv<= pv+bp; end if; bp<=bp(14 downto 0) & '0'; i<=i+1; end if; end if; end if; end if; и ещё VHDL ругается на "wait until clk'event and clk = '1';" , с непонятной для меня ошибкой: "# Error: COMP96_0242: testt.vhd : (50, 1): Wait statement in process with explicit sensitivity list is not allowed." Изменено 21 мая, 2017 пользователем artyombn Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dr.Alex 0 21 мая, 2017 Опубликовано 21 мая, 2017 · Жалоба я не понял зачем тут if i=0 ? т.е. мне каждое изменение i описывать? Каждое не нужно, а 0 может быть и нужно. "# Error: COMP96_0242: testt.vhd : (50, 1): Wait statement in process with explicit sensitivity list is not allowed." Ну так уберите сенситивити лист, я же ясно написал process begin. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
artyombn 0 21 мая, 2017 Опубликовано 21 мая, 2017 · Жалоба вот переписанный код library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_unsigned.all; use IEEE.NUMERIC_STD.all; entity test is port( clk, r: in std_logic; a : in std_logic_vector(7 downto 0); b : in std_logic_vector(7 downto 0); p : out std_logic_vector(15 downto 0); load: in std_logic ); end test; --}} End of automatically maintained section architecture test of test is signal pv: std_logic_vector(15 downto 0):=(others => '0'); signal bp: std_logic_vector(15 downto 0); signal i : integer range 0 to 8; begin process begin wait until clk'event and clk = '1'; if load = '1' then bp<= "00000000" & b; i <= 0; else if i<8 then if i<=0 then if a(i) = '1' then pv<= pv+bp; end if; bp<=bp(14 downto 0) & '0'; i<=i+1; else if a(i) = '1' then pv<= pv+bp; end if; bp<=bp(14 downto 0) & '0'; i<=i+1; end if; end if; p<=pv; end if; end process; end test; вот моделирование изначально он не может понять что такое bp пока не стартанет клок. задать заранее bp мы не можем, ибо без клока ничего вообще происходить не будет. именно поэтому раньше клок у меня шел после лоад, но тогда, как вы сказали, лоад будет действительно ассинхронный. и почему pv в первый такт не стал равен bp? вроде как это условие выполняется if i<8 then if i<=0 then if a(i) = '1' then pv<= pv+bp; end if; и должно попасть в первый такт и почему pv в первый такт не стал равен bp? вроде как это условие выполняется if i<8 then if i<=0 then if a(i) = '1' then pv<= pv+bp; end if; и должно попасть в первый такт хотя оно попадает, но во второй такт.. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться