|
|
  |
"Схемотехнические трюки для ПЛИСоводов", создание аналога "Алгоритмические трюки для программистов" |
|
|
|
Oct 22 2012, 15:34
|
Частый гость
 
Группа: Свой
Сообщений: 180
Регистрация: 17-02-09
Из: Санкт-Петербург
Пользователь №: 45 001

|
Цитата(ISK @ Oct 2 2012, 13:32)  Была у меня похожая задача, на 100 МГц на циклоне 3 схема работала. ISK, не могли бы подробнее рассказать что к чему? Уже несколько часов потратил, никак не разберусь - толи устал, толи способностей не хватает( Переменной point_cnt вы что задаёте? Также меня интересует начальное состояние cmp_res... В зависимости от него в строке cmp_res_reg(15) независимо от add_sub_res будет либо X"8000" , либо X"FFFF"... Ничего не понимаю, объясните пожалуйста подробнее.
|
|
|
|
|
Oct 23 2012, 12:50
|
Частый гость
 
Группа: Свой
Сообщений: 180
Регистрация: 17-02-09
Из: Санкт-Петербург
Пользователь №: 45 001

|
Вобщем, с кодом ISKа разобраться так и не смог, сделал свой вариант. Если входной массив разбить по 4 слова, и использовать не сравнение значений, а разность(т.е. логику ускоренного переноса), то получается довольно неплохо. CODE library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL;
library UNISIM; use UNISIM.VComponents.all;
entity Sort_Four is generic( wigth : natural := 16); Port ( clk : in std_logic; in_word : in std_logic_vector((4*wigth - 1) downto 0); ---- out_index : out std_logic_vector(1 downto 0); out_data : out std_logic_vector((wigth - 1) downto 0)); end Sort_Four;
architecture Behavioral of Sort_Four is
----------------------------------------------------------- ----------------------------------------------------------- attribute syn_hier : string; attribute syn_hier of Behavioral : architecture is "hard";
attribute syn_keep : boolean; ----------------------------------------------------------- ----------------------------------------------------------- type word_type is array (0 to 3) of std_logic_vector((wigth - 1) downto 0); signal word, word_1d : word_type;
signal sub_0f : std_logic_vector(1 downto 0); signal word_mux_st, word_mux_ml : std_logic_vector((wigth - 1) downto 0); signal sub_1f : std_logic; signal sub_general : std_logic_vector(2 downto 0);
-- signal data_1d, data : std_logic_vector((order - 1) downto 0);
----------------------------------------------------------- -----------------------------------------------------------
begin
----------------------------------------------------------- ----------------------------------------------------------- process (clk) begin if (clk = '1' and clk'event) then for i in 0 to 3 loop word_1d(i) <= in_word(((i + 1)*wigth - 1) downto i*wigth); word(i) <= word_1d(i); end loop; end if; end process;
----------------------------------------------------------- ----------------------------------------------------------- process (word) variable sub_w32_temp, sub_w10_temp : std_logic_vector((wigth - 1) downto 0); begin sub_w32_temp := (word(3) + (not word(2)) + 1); sub_w10_temp := (word(1) + (not word(0)) + 1); sub_0f <= (sub_w32_temp(wigth - 1)&sub_w10_temp(wigth - 1)); end process;
word_mux_st <= word(3) when sub_0f(1) = '1' else word(2); word_mux_ml <= (not word(1)) when sub_0f(0) = '1' else (not word(0));
----------------------------------------------------------- ----------------------------------------------------------- process (word_mux_st, word_mux_ml) variable word_mux_temp : std_logic_vector((wigth - 1) downto 0); begin word_mux_temp := (word_mux_st + word_mux_ml + 1); sub_1f <= word_mux_temp(wigth - 1); end process;
----------------------------------------------------------- ----------------------------------------------------------- -- process (clk) -- begin -- if (clk = '1' and clk'event) then -- if sub_1f = '1' then -- if sub_0f(1) = '1' then -- data_1d <= word(3); -- else -- data_1d <= word(2); -- end if; -- else -- if sub_0f(0) = '1' then -- data_1d <= word(1); -- else -- data_1d <= word(0); -- end if; -- end if; -- data <= data_1d; -- end if; -- end process;
-- out_data <= data; ----------------------------------------------------------- ----------------------------------------------------------- sub_general <= (sub_1f&sub_0f); process (sub_general, word) begin case sub_general is when "000" => out_data <= word(0); out_index <= "00"; when "001" => out_data <= word(0); out_index <= "00"; when "010" => out_data <= word(1); out_index <= "01"; when "011" => out_data <= word(1); out_index <= "01"; when "100" => out_data <= word(2); out_index <= "10"; when "101" => out_data <= word(2); out_index <= "10"; when "110" => out_data <= word(3); out_index <= "11"; when "111" => out_data <= word(3); out_index <= "11"; when others => null; end case; end process;
end Behavioral; При входном массиве 16x16 получается 8 слоёв логики(не считая carry-chain), и для V6-1 схема разводится на 185МГц... Жалко только, что мне надо 300 - буду ставить конвеер(
Сообщение отредактировал TRILLER - Oct 23 2012, 12:51
|
|
|
|
|
May 11 2014, 13:53
|
Группа: Новичок
Сообщений: 2
Регистрация: 8-05-14
Пользователь №: 81 615

|
всем привет! учусь на втором курсе.задали сделать семестровую работу по теме: "Моделирование САУ Адаптивного робота:Проектирование в виде системы на кристалле или интегральная схема - на основе метода ПЛИС, используя VHDL..но я не знаю как(VHDL не проходили даже)...помогите пожалуйста!
|
|
|
|
|
May 11 2014, 14:22
|
Гуру
     
Группа: Модераторы
Сообщений: 4 011
Регистрация: 8-09-05
Из: спб
Пользователь №: 8 369

|
Цитата(riza @ May 11 2014, 17:53)  всем привет! учусь на втором курсе.задали сделать семестровую работу по теме: "Моделирование САУ Адаптивного робота:Проектирование в виде системы на кристалле или интегральная схема - на основе метода ПЛИС, используя VHDL..но я не знаю как(VHDL не проходили даже)...помогите пожалуйста! 1. Написать алгоритм работы робота 2. По нему сделать блок-схему алгоритма 3. По ней сделать блок-схему вычислителя. 4. Проверить ее в маткадах-иатлабах 5. Вычислитель реализовать в ПЛИС... Вот собственно и все... Первые 4 пункта можно делать, ничего не зная о ПЛИС... Или мало зная о ПЛИС. Потом задать преподу вопрос: почему заставляют делать то, чему не учили... Мы готовы ответить на конкретный вопрос, но не делать за Вас всю работу. Нам это не интересно, это Ваша проблема, а не наша... Да и тему надо перенести в другой раздел.... Либо для "начинающих", либо "предлагаю работу"....
--------------------
www.iosifk.narod.ru
|
|
|
|
|
May 11 2014, 14:24
|
Группа: Новичок
Сообщений: 2
Регистрация: 8-05-14
Пользователь №: 81 615

|
спасибо большое!
|
|
|
|
|
May 28 2014, 02:31
|
Группа: Новичок
Сообщений: 3
Регистрация: 28-05-14
Пользователь №: 81 794

|
2 вопроса: а) чем содержательно должен отличаться подразумеваемый раздел от 4-ого раздела по ПЛИС "Системы на ПЛИС - System on Programmable Chip" (он открывался для обсуждения корок)? большей мелкозернистостью обсуждаемых модулей? б) по какому принципу будет организовываться структура раздела? надеюсь каталогизация подразумевается?
--------------------
|
|
|
|
|
Aug 3 2015, 12:30
|
Местный
  
Группа: Свой
Сообщений: 388
Регистрация: 27-02-06
Из: Москва
Пользователь №: 14 759

|
может кому будет нужно `timescale 1ns / 1ps // module divider # ( parameter WIDTH_DIVIDENT = 27, parameter WIDTH_DIVIDER = 9 ) ( // global input Clock, // input input DivIn, input [WIDTH_DIVIDENT-1 : 0] Divident, input [WIDTH_DIVIDER-1 : 0] Divider, // output output wire DivOut, output wire [WIDTH_DIVIDENT-1 : 0] Result, output wire [WIDTH_DIVIDER-1 : 0] Fractional, // debug output wire Test );
// wire [0 : 0] Comp [WIDTH_DIVIDENT-1 : 0]; wire [WIDTH_DIVIDER-1 : 0] CarryTemp [WIDTH_DIVIDENT-1 : 0];
// sift registers reg [0 : 0] DivTemp [WIDTH_DIVIDENT-1 : 0]; reg [WIDTH_DIVIDENT-1 : 0] ResultTemp [WIDTH_DIVIDENT-1 : 0]; reg [WIDTH_DIVIDENT+WIDTH_DIVIDER-1 : 0] DividentTemp [WIDTH_DIVIDENT-1 : 0]; reg [WIDTH_DIVIDER-1 : 0] DividerTemp [WIDTH_DIVIDENT-1 : 0]; // first always @(posedge Clock) begin DivTemp[0][0 : 0] = DivIn; ResultTemp[0][WIDTH_DIVIDENT-1 : 0] = (Comp[0]) ? 8'd1 : 8'd0; DividentTemp[0][WIDTH_DIVIDENT+WIDTH_DIVIDER-2 : 0] = {{(WIDTH_DIVIDER-1){1'b0}}, Divident[WIDTH_DIVIDENT-1 : 0]}; DividerTemp[0][WIDTH_DIVIDER-1 : 0] = Divider[WIDTH_DIVIDER-1 : 0]; end //always // next all genvar i; generate for (i=1; i<WIDTH_DIVIDENT; i=i+1) begin: shift always @(posedge Clock) begin DivTemp[i][0 : 0] = DivTemp[i-1][0 : 0]; ResultTemp[i][WIDTH_DIVIDENT-1 : 0] = {(ResultTemp[i-1][WIDTH_DIVIDENT-2 : 0]), ((Comp[i]) ? 1'b1 : 1'b0)}; DividentTemp[i][WIDTH_DIVIDENT+WIDTH_DIVIDER-2 : 0] = {CarryTemp[i-1][WIDTH_DIVIDER-2 : 0], DividentTemp[i-1][WIDTH_DIVIDENT-2 : 0], 1'b0}; DividerTemp[i][WIDTH_DIVIDER-1 : 0] = DividerTemp[i-1][WIDTH_DIVIDER-1 : 0]; end //always end endgenerate
// calculate genvar j; generate for (j=0; j<WIDTH_DIVIDENT; j=j+1) begin: calc assign Comp[j][0 : 0] = (DividentTemp[j][WIDTH_DIVIDENT+WIDTH_DIVIDER-2 :WIDTH_DIVIDENT-1] >= DividerTemp[j][WIDTH_DIVIDER-1 : 0]) ? 1'b1 : 1'b0; assign CarryTemp[j][WIDTH_DIVIDER-1 : 0] = (Comp[j]) ? (DividentTemp[j][WIDTH_DIVIDENT+WIDTH_DIVIDER-2 :WIDTH_DIVIDENT-1] - DividerTemp[j][WIDTH_DIVIDER-1 : 0]) : DividentTemp[j][WIDTH_DIVIDENT+WIDTH_DIVIDER-2 :WIDTH_DIVIDENT-1]; end endgenerate
// fractional reg [WIDTH_DIVIDER-1 : 0] FractionalReg; always @(posedge Clock) FractionalReg[WIDTH_DIVIDER-1 : 0] = CarryTemp[WIDTH_DIVIDENT-1];
// result valid reg DivReg; always @(posedge Clock) DivReg = DivTemp[WIDTH_DIVIDENT-1][0 : 0];
// output assign Result[WIDTH_DIVIDENT-1 : 0] = ResultTemp[WIDTH_DIVIDENT-1]; assign Fractional[WIDTH_DIVIDER-1 : 0] = FractionalReg[WIDTH_DIVIDER-1 : 0]; assign DivOut = DivReg;
// debug assign Test = 1'b0;
endmodule //divider
|
|
|
|
|
Aug 3 2015, 13:10
|
Знающий
   
Группа: Участник
Сообщений: 527
Регистрация: 4-06-14
Из: Санкт-Петербург
Пользователь №: 81 866

|
Цитата может кому будет нужно ... Оформите в виде исходного файла + простенького тб в архиве блоки Код // next all ...
// calculate ... имхо лучше сделать как обычные циклы под always@(posedge Clock) и always@(*) соответственно ну и если вруг не лениво, то небольшую справку по результатам имплементации на любой понравившейся ПЛИС, чтобы человек, если вдруг заинтересуется, имел представление во что это ему может вылиться.
|
|
|
|
|
Aug 3 2015, 13:30
|
Местный
  
Группа: Свой
Сообщений: 388
Регистрация: 27-02-06
Из: Москва
Пользователь №: 14 759

|
вот другая реализация. Это простые делители - первый итерационный, а этот нет
// Fast Array Divider 8 bit to 4 bit module fast_array_divider (a_in, d_in, q_out, r_out);
input [7:0] a_in; input [3:0] d_in; output [7:0] q_out; wire [7:0] q_out; output [3:0] r_out; wire [3:0] r_out;
wire [12:1] a; wire [4:1] d; wire [8:1] q; wire [8:5] r;
wire c_0_3, c_0_2, c_0_1, c_0_0; wire s_0_3, s_0_2, s_0_1, s_0_0; wire q1_inv; restoring_array_divider array_0_0 ( a[2], d[1], c_0_1, q1_inv, c_0_0, s_0_0); restoring_array_divider array_0_1 ( a[3], d[2], c_0_2, q1_inv, c_0_1, s_0_1); restoring_array_divider array_0_2 ( a[4], d[3], c_0_3, q1_inv, c_0_2, s_0_2); restoring_array_divider array_0_3 ( a[5], d[4], 1'b0, q1_inv, c_0_3, s_0_3); assign q[1] = ( a[1] | !c_0_0 ); assign q1_inv=!q[1];
wire c_1_3, c_1_2, c_1_1, c_1_0; wire s_1_3, s_1_2, s_1_1, s_1_0; wire q2_inv; restoring_array_divider array_1_0 ( s_0_1, d[1], c_1_1, q2_inv, c_1_0, s_1_0); restoring_array_divider array_1_1 ( s_0_2, d[2], c_1_2, q2_inv, c_1_1, s_1_1); restoring_array_divider array_1_2 ( s_0_3, d[3], c_1_3, q2_inv, c_1_2, s_1_2); restoring_array_divider array_1_3 ( a[6], d[4], 1'b0, q2_inv, c_1_3, s_1_3); assign q[2] = ( s_0_0 | !c_1_0 ); assign q2_inv=!q[2];
wire c_2_3, c_2_2, c_2_1, c_2_0; wire s_2_3, s_2_2, s_2_1, s_2_0; wire q3_inv; restoring_array_divider array_2_0 ( s_1_1, d[1], c_2_1, q3_inv, c_2_0, s_2_0); restoring_array_divider array_2_1 ( s_1_2, d[2], c_2_2, q3_inv, c_2_1, s_2_1); restoring_array_divider array_2_2 ( s_1_3, d[3], c_2_3, q3_inv, c_2_2, s_2_2); restoring_array_divider array_2_3 ( a[7], d[4], 1'b0, q3_inv, c_2_3, s_2_3); assign q[3] = ( s_1_0 | !c_2_0 ); assign q3_inv=!q[3];
wire c_3_3, c_3_2, c_3_1, c_3_0; wire s_3_3, s_3_2, s_3_1, s_3_0; wire q4_inv; restoring_array_divider array_3_0 ( s_2_1, d[1], c_3_1, q4_inv, c_3_0, s_3_0); restoring_array_divider array_3_1 ( s_2_2, d[2], c_3_2, q4_inv, c_3_1, s_3_1); restoring_array_divider array_3_2 ( s_2_3, d[3], c_3_3, q4_inv, c_3_2, s_3_2); restoring_array_divider array_3_3 ( a[8], d[4], 1'b0, q4_inv, c_3_3, s_3_3); assign q[4] = ( s_2_0 | !c_3_0 ); assign q4_inv=!q[4];
wire c_4_3, c_4_2, c_4_1, c_4_0; wire s_4_3, s_4_2, s_4_1, s_4_0; wire q5_inv; restoring_array_divider array_4_0 ( s_3_1, d[1], c_4_1, q5_inv, c_4_0, s_4_0); restoring_array_divider array_4_1 ( s_3_2, d[2], c_4_2, q5_inv, c_4_1, s_4_1); restoring_array_divider array_4_2 ( s_3_3, d[3], c_4_3, q5_inv, c_4_2, s_4_2); restoring_array_divider array_4_3 ( a[9], d[4], 1'b0, q5_inv, c_4_3, s_4_3); assign q[5] = ( s_3_0 | !c_4_0 ); assign q5_inv=!q[5];
wire c_5_3, c_5_2, c_5_1, c_5_0; wire s_5_3, s_5_2, s_5_1, s_5_0; wire q6_inv; restoring_array_divider array_5_0 ( s_4_1, d[1], c_5_1, q6_inv, c_5_0, s_5_0); restoring_array_divider array_5_1 ( s_4_2, d[2], c_5_2, q6_inv, c_5_1, s_5_1); restoring_array_divider array_5_2 ( s_4_3, d[3], c_5_3, q6_inv, c_5_2, s_5_2); restoring_array_divider array_5_3 ( a[10], d[4], 1'b0, q6_inv, c_5_3, s_5_3); assign q[6] = ( s_4_0 | !c_5_0 ); assign q6_inv=!q[6];
wire c_6_3, c_6_2, c_6_1, c_6_0; wire s_6_3, s_6_2, s_6_1, s_6_0; wire q7_inv; restoring_array_divider array_6_0 ( s_5_1, d[1], c_6_1, q7_inv, c_6_0, s_6_0); restoring_array_divider array_6_1 ( s_5_2, d[2], c_6_2, q7_inv, c_6_1, s_6_1); restoring_array_divider array_6_2 ( s_5_3, d[3], c_6_3, q7_inv, c_6_2, s_6_2); restoring_array_divider array_6_3 ( a[11], d[4], 1'b0, q7_inv, c_6_3, s_6_3); assign q[7] = ( s_5_0 | !c_6_0 ); assign q7_inv=!q[7];
wire c_7_3, c_7_2, c_7_1, c_7_0; wire s_7_3, s_7_2, s_7_1, s_7_0; wire q8_inv; restoring_array_divider array_7_0 ( s_6_1, d[1], c_7_1, q8_inv, c_7_0, s_7_0); restoring_array_divider array_7_1 ( s_6_2, d[2], c_7_2, q8_inv, c_7_1, s_7_1); restoring_array_divider array_7_2 ( s_6_3, d[3], c_7_3, q8_inv, c_7_2, s_7_2); restoring_array_divider array_7_3 ( a[12], d[4], 1'b0, q8_inv, c_7_3, s_7_3); assign q[8] = ( s_6_0 | !c_7_0 ); assign q8_inv=!q[8];
assign r[8:5]={s_7_3, s_7_2, s_7_1, s_7_0};
assign a[12:1]={a_in[0], a_in[1], a_in[2], a_in[3], a_in[4], a_in[5], a_in[6], a_in[7], 4'b0000}; assign d[4:1]={d_in[0], d_in[1], d_in[2], d_in[3]}; assign q_out[7:0]={q[1] ,q[2], q[3], q[4], q[5], q[6], q[7], q[8]}; assign r_out[3:0]={r[5], r[6], r[7], r[8]};
endmodule //fast_array_divider
|
|
|
|
|
Jan 29 2016, 11:13
|

я только учусь...
     
Группа: Модераторы
Сообщений: 3 447
Регистрация: 29-01-07
Из: Украина
Пользователь №: 24 839

|
Решил поделиться алгоритмом: Например, вам надо понять, является ли введенное число степенью двойки или нет. Для этого вы можете просто делить это число на 2, пока не получите двойку на последнем шаге. Этот алгоритм будет работать, он выдаст результат, но на больших числах будет тратить много лишнего времени. А можете написать простое выражение в одну строку: x & (x-1) == 0. Тут используется немного битовой магии, но результат будет тем же, но за гораздо меньшее время.
PS Надеюсь будет кому-то полезным...
--------------------
If it doesn't work in simulation, it won't work on the board.
"Ты живешь в своих поступках, а не в теле. Ты — это твои действия, и нет другого тебя" Антуан де Сент-Экзюпери повесть "Маленький принц"
|
|
|
|
|
Mar 2 2016, 11:47
|
Знающий
   
Группа: Участник
Сообщений: 835
Регистрация: 9-08-08
Из: Санкт-Петербург
Пользователь №: 39 515

|
Цитата(Maverick @ Jan 29 2016, 14:13)  Решил поделиться алгоритмом: Например, вам надо понять, является ли введенное число степенью двойки или нет. Для этого вы можете просто делить это число на 2, пока не получите двойку на последнем шаге. Этот алгоритм будет работать, он выдаст результат, но на больших числах будет тратить много лишнего времени. А можете написать простое выражение в одну строку: x & (x-1) == 0. Тут используется немного битовой магии, но результат будет тем же, но за гораздо меньшее время. Здесь надо не делить на 2, а подсчитать количество единичных битов, и сравнить его с единицей. Поскольку конкретное значение количества единичных битов вычислять не требуется, стандартная архитектура решения этой задачи упрощается. Например, для 15 бит на Ксайлинксах потребуется три пары LUT5 на нижнем слое логики, и один LUT6 на следующем, как раз один слайс. Нижний слой выдаёт по трём группам из пяти бит значения "нет единиц", "одна единица", "больше одной единицы", а верхний LUT6 выносит окончательный вердикт. А через вычитание потребуются 4 слайса только для вычитания и потом ещё 2 на логику.
|
|
|
|
|
  |
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|