Есть ли лучший способ использования цикла for?

#vhdl #fpga

#vhdl #fpga

Вопрос:

Я пишу код для (128 бит) степени (4 бита) и делителя, чтобы найти остаток (128 бит) степени (4 бита) и переменную (4 бита). Я использовал повторяющееся сложение, чтобы найти первую операцию, и повторяющееся вычитание, чтобы найти остаток. Я использовал цикл for для того же. верхняя граница цикла for действительно высока для (128 бит) мощности (4 бита), и моделирование выдает ошибку. Моделирование внезапно останавливается, сообщая, что процесс завершен. И обнаружена неустранимая ошибка в модуле питания (Xilinx 12.1 в Windows xp). Эта ошибка появляется в xilinx 14.7 в Windows 10:

ОШИБКА: переносимость: 3 — У этого приложения Xilinx закончилась память или возник конфликт памяти. Текущее использование памяти составляет 3085052 КБ. Вы можете попробовать увеличить физическую или виртуальную память вашей системы. Если вы используете систему Win32, вы можете увеличить объем памяти вашего приложения с 2 ГБ до 3 ГБ, используя переключатель / 3G в вашем файле boot.ini. Для получения дополнительной информации об этом, пожалуйста, обратитесь к записи ответа Xilinx # 14932. Для получения технической поддержки по этому вопросу, пожалуйста, посетите http://www.xilinx.com/support .

Симулятор завершился неожиданным образом. Пожалуйста, просмотрите журнал ISim (isim.log) для получения подробной информации. Есть ли какой-либо эффективный способ избежать этой проблемы? пожалуйста, помогите. Чтобы найти мощность:

 entity power is
    Port ( mes : in  STD_LOGIC_VECTOR (207 downto 0);
           d : in  STD_LOGIC_VECTOR (11 downto 0);
           outt : out  STD_LOGIC_VECTOR (2007 downto 0);
           clk : in  STD_LOGIC);
end power;

architecture Behavioral of power is
signal mes1:unsigned (207 downto 0);
signal d1:unsigned (11 downto 0);
signal mes3:unsigned (2007 downto 0);
begin
process(clk)
begin
if(clk'event and clk='1') then
mes1<=unsigned(mes);
d1<=unsigned(d);
end if;
end process;

process(clk,mes1)
variable varr:unsigned (2007 downto 0);
variable cnt,cnt1: unsigned (207 downto 0);
variable mes2: unsigned (2007 downto 0);
begin

cnt:=x"0000000000000000000000000000000000000000000000000001";
mes2:=x"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
mes2(207 downto 0):=mes1;
if(clk'event and clk='1') then
for i in 0 to 90 loop
     if(cnt<d1) then
      varr:=x"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
      cnt1:=x"0000000000000000000000000000000000000000000000000001";
           for j in 0 to 150000 loop
               if (cnt1<=mes1) then
                    varr:=varr mes2;
                      cnt1:=cnt1 1;
                end if;
            end loop;
              mes2:=varr;
              cnt:=cnt 1;
      end if;
end loop;
mes3<=mes2;
end if;
end process;


process(clk)
begin
if(clk'event and clk='1') then
outt<=std_logic_vector(mes3);
end if;
end process;


end Behavioral;
  

Чтобы найти остаток:

 entity div22 is
    Port ( a : in  STD_LOGIC_VECTOR (2007 downto 0);
           b : in  STD_LOGIC_VECTOR (7 downto 0);
           remi : out  STD_LOGIC_VECTOR (2007 downto 0);
           clk : in  STD_LOGIC);
end div22;

architecture Behavioral of div22 is

signal q:unsigned (11 downto 0);
signal a1,r:unsigned (2007 downto 0);
signal b1:unsigned (7 downto 0);
--signal i:STD_LOGIC_VECTOR (3 downto 0);
begin

process(clk)
begin
if(clk'event and clk='1') then
a1<=unsigned(a);
b1<=unsigned(b);
end if;
end process;

process(clk,a1,b1)
variable remo1,remo2: unsigned(2007 downto 0);
begin
remo1:=a1;
if RISING_EDGE(clk) then
for i in 0 to 150000 loop
      remo2:=remo1;

     if(remo2>=b1) then
      remo1:=remo2-b1; 

      end if;
end loop;
r<=remo1;
end if;
end process;
process(clk,r)
begin
if RISING_EDGE(clk) then
remi<= std_logic_vector(r);
end if;
end process;

end Behavioral;
  

Чтобы найти напоминание, верхняя граница для цикла for действительно высока. Есть ли какой-либо эффективный способ решить эту проблему? Пожалуйста, помогите.

Комментарии:

1. Какую ошибку он выдает? Какую проблему вы пытаетесь решить? Вы обнаружите, что ваш вопрос закрыт, если вы не будете более конкретны.

2. @EML Ошибка не указана. Он просто говорит о какой-то фатальной ошибке при включении, когда я увеличиваю верхнюю границу цикла

3. Вероятно, вы используете массивные массивы. Вы пробовали использовать 64-битную систему с большим объемом оперативной памяти? Кроме того, этот код не будет синтезироваться. Ограничение цикла итерации для синтеза обычно равно 10000, и даже тогда использование ресурсов для этого кода, вероятно, будет больше, чем у любой fpga, плюс максимальная тактовая частота будет очень низкой. Я рекомендую спроектировать схему на бумаге перед написанием кода. Перевод c в vhdl для синтеза всегда будет давать плохие результаты.

4. Я думаю, что нам, опытным разработчикам HDL, интересно, что вы пытаетесь сделать. Почему вы используете HDL для написания кода, который никогда не поместится в FPGA или даже ASIC. Это заставляет меня думать, что у вас проблема с X-Y. Итак, в чем проблема / алгоритм, который вы пытаетесь решить. Потому что я подозреваю, что это не то решение, которое вы ищете.

5. Хорошо, теперь мы к чему-то пришли. Ваш вопрос относится к категории «Как мне реализовать X». К сожалению, в этом случае нет быстрого и простого ответа . По сути, вам нужно полностью переписать код, разделив его на этапы, которые решаются в последовательных циклах, балансируя параллельные и последовательные операции, которые оптимально используют доступную тактовую частоту. Потребовалось бы много месяцев обучения, чтобы научить вас писать эффективный HDL для этого. Я предлагаю начать просмотр кода HDL на www, который выполняет аналогичные алгоритмы.

Ответ №1:

Лучший способ в вашем контексте — не использовать циклы.

Как правило, для достижения наилучшей производительности и приемлемого размера области реализации вам следует использовать реализацию состояния (fsm). Вы должны балансировать между частотой (критическим путем) и количеством циклов, необходимых для завершения работы. Это моя базовая реализация (в Verilog) операции «Остаток от общего деления — остаток» из моей магистерской диссертации. В моем случае проблема в том, что сумматор был слишком большим. Итак, в моей окончательной версии добавление реализации происходит параллельно — я использовал несколько меньших сумматоров, чтобы получить лучшую частоту. Этот код является частью реализации RSA моей магистерской диссертации.

 module div(a,n,clk,reset,R, ready); // a,b,n mniejszy rozmiar
// a mod n = R
parameter size=1024; // data length

parameter
  A0 = 2'b00, // Reset.
  A1 = 2'b01, // Find  _n > _R.  
  A2 = 2'b10, // Calc.
  A3 = 2'b11; // Ready - calc done.

input [size-1:0] a,n;

input clk,reset;
output ready;
output [size-1:0] R;

reg signed [size:0] _R;
reg [size:0] _n;
reg [size-1:0] tmp_r;
reg ready; // operation is done.
reg [11:0]i;

(*safe_implementation = "yes"*)// directive for XST
(* signal_encoding = "user" *) // directive for XST

(* fsm_encoding = "user" *)    // directive for XST
reg [1:0] cs;

initial
  begin
     _R = 0;
     _n = 0;
     i = 0;
     ready = 0;
      tmp_r = 0;
      cs = A0;
  end



always @(posedge clk)
  begin
    if (reset)
       begin
          _R = a;
          _n = n;
          i = 0;
          tmp_r= a;
          ready = 0;
          cs = A0;
        end
     else
    begin
       case(cs)
          A0:
            begin
               cs = A1; 
             end
          A1:
            begin
            _n = _n << 1;
               i = i   1;
               if ( _n > _R )
                 begin
                    _n = _n >> 1;
                _R = _R - _n;                 
                    cs = A2;
                  end
               else
                 begin
                    cs = A1;
                  end
             end
          A2:
            begin
               if (i==0)
                  begin
                    cs = A3;
                  end
                else
                  begin
                    _n = _n >> 1;
                  if (_R[size]==1'b0)
                    begin
                       tmp_r = _R;  // Save last positiv number. 
                        _R = _R - _n;
                     end
                  else
                    begin
                       _R = _R   _n;
                     end
                  i = i -1;
                  cs = A2;
               end    
             end
          A3:
            begin
               ready = 1'b1;
               cs = A3;
             end
          default:;  
        endcase
    end
  end

assign R=tmp_r;  
endmodule
  

div fsm

В моей магистерской диссертации вы можете найти больше приемов для повышения производительности и оптимизации области, применимых к вашему контексту (проблема в том, что он на польском языке):
https://www.researchgate.net/publication/332752272_Realizacja_wybranych_algorytmow_kryptograficznych_w_strukturach_FPGA_Smolinski_Lukasz

Извините за мой английский.