Перейти к содержанию
    

Задачи на ПЛИС

Может кто-нибудь подкинуть интересных задачек на VHDL для развития мозгов?

Возможно, с различными условиями типа "занять не больше ячеек X", "сделать без умножалок", "посчитать не более, чем за X тактов" и т.п. Или просто интересные задачи без каких либо условий.

 

Поиск в гугле практически ничего не дает. Попадаются ссылки на форумы, "задачи" студентов уровня "как сделать c = a + b".

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Может кто-нибудь подкинуть интересных задачек на VHDL для развития мозгов?

по форуму куча подобного с примерами раскидана, bin2bcd, count_ones, divider, FWPT FIFO, ff_ram_buffer и т.д. и т.п. %)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

по форуму куча подобного с примерами раскидана, bin2bcd, count_ones, divider, FWPT FIFO, ff_ram_buffer и т.д. и т.п. %)

 

Начнемс с начала. Bin2Bcd. :)

Попробую сделать его параметризованым с InputWidth (максимум 32 бита) в generic. Считать буду за несколько тактов простым вычитанием (худший случай 1_999_999_999, должно быть ~90 тактов на вычисление).

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Считать буду за несколько тактов простым вычитанием (худший случай 1_999_999_999, должно быть ~90 тактов на вычисление).

в соседних темах делают намного быстрее ;)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

в соседних темах делают намного быстрее ;)

 

Хм, реализовал решение "в лоб", в ISIM работает примерно также, как и ожидалось (83 такта получилось). Сейчас поищу, как быстрее все это считают. :)

Изменено пользователем whiteTigr

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Хм, реализовал решение "в лоб", в ISIM работает примерно также, как и ожилась (83 такта получилось). Сейчас поищу, как быстрее все это считают. :)

а поделиться ;)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

а поделиться ;)

 

Вот так получилось. Теперь можно меня громко обругать за корявость кода. :)

П.С.: к сожалению, не помню тега, чтобы блок кода был со скроллером.

 

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.Math_real.ALL;

entity bin2bcd is
Generic(
  InputWidth: integer := 8;	  
  OutputWidth: integer := 12
);
Port ( clk : in  STD_LOGIC;
	   d : in  STD_LOGIC_VECTOR (InputWidth-1 downto 0);
	   q : out  STD_LOGIC_VECTOR (OutputWidth-1 downto 0);
	   nd: out std_logic);
end bin2bcd;

architecture Behavioral of bin2bcd is

constant NumberOfDigits: integer := integer(Ceil(Log10(real(2**InputWidth))));
constant NeededOutputWidth: integer := NumberOfDigits * 4;

type TCmpTable is array(0 to 8) of std_logic_vector(31 downto 0);
constant CmpTable: TCmpTable := 
 (x"0000_000A", x"0000_0064", x"0000_03E8", 
  x"0000_2710", x"0001_86A0", x"000F_4240",
  x"0098_9680", x"05F5_E100", x"3B9A_CA00");

type TAddTable is array(0 to 8) of std_logic_vector(39 downto 0);
constant AddTable: TAddTable := 
 (x"00_0000_0006", x"00_0000_009C", x"00_0000_0C18", 
  x"00_0000_D8F0", x"00_000E_7960", x"00_00F0_BDC0",
  x"00_0F67_6980", x"00_FA0A_1F00", x"0F_C465_3600");  

signal dBuf: std_logic_vector(InputWidth-1 downto 0);
signal qBuf: std_logic_vector(NeededOutputWidth-1 downto 0);
signal CurDigit: integer range 0 to 8;
signal CmpValue: std_logic_vector(InputWidth-1 downto 0);
signal AddValue: std_logic_vector(NeededOutputWidth-1 downto 0);

signal State: integer range 0 to 2 := 0;

begin

--не знаю как преобразовать Integer в строку, чтобы вывести предупредение
--PROCESS BEGIN
--ASSERT (OutputWidth = NeededOutputWidth);-- REPORT "Needed OutputWidth = " & string(NeededOutputWidth) SEVERITY WARNING;
--END PROCESS;

process(clk)
begin
 if rising_edge(clk) then
CmpValue <= CmpTable(CurDigit)(InputWidth-1 downto 0);
AddValue <= AddTable(CurDigit)(NeededOutputWidth-1 downto 0);
 end if;
end process;

process(clk)
begin
 if rising_edge(clk) then		
case State is
  when 0 =>
	q <= qBuf(OutputWidth-1 downto 0);	  
	qBuf <= conv_std_logic_vector(0, NeededOutputWidth - InputWidth) & d;
	dBuf <= d;
	nd <= '1';
	CurDigit <= NumberOfDigits - 2;
	State <= 1;
  when 1 =>
	nd <= '0';
	-- такт на чтение данных из памяти
	State <= 2;
  when 2 =>		
	if dBuf >= CmpValue then
	  dBuf <= dBuf - CmpValue;
	  qBuf <= qBuf + AddValue;
	elsif CurDigit = 0 then		  
	  State <= 0;
	else
	  CurDigit <= CurDigit - 1;
	  State <= 1;
	end if;	  
  when others => State <= 0;
end case;
 end if;
end process;

end Behavioral;

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вариант номер 2.

За основу взята pdf'ка http://people.ee.duke.edu/~dwyer/courses/e...D_Converter.pdf

Это уже больше похоже на нормальное преобразование.

Худших случаев нет, преобразование длится (InputWidth*2 + 1) тактов.

Теперь модуль дополнительно ждет изменения сигнала на входе, перед началом преобразования.

Завтра проверю занимаемые ресурсы в этих двух вариантах, сейчас уже точно не помню сколько получалось в первом, вроде бы примерно столько же.

Возможно на форуме уже что-то подобное было, но свою главную задачу я выполнил - не умер от скуки. :)

 

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.Math_real.ALL;

entity bin2bcd_ver2 is
   Generic(
     InputWidth: integer := 32;      
     OutputWidth: integer := 40
   );
   Port ( clk : in  STD_LOGIC;
          d : in  STD_LOGIC_VECTOR (InputWidth-1 downto 0);
          q : out  STD_LOGIC_VECTOR (OutputWidth-1 downto 0);
          nd : out  STD_LOGIC);
end bin2bcd_ver2;

architecture Behavioral of bin2bcd_ver2 is

constant NumberOfDigits: integer := integer(Ceil(real(InputWidth) * 3.012));
constant NeededOutputWidth: integer := NumberOfDigits * 4;

signal LastD: std_logic_vector(InputWidth-1 downto 0);
signal dBuf: std_logic_vector(InputWidth-1 downto 0);
signal qBuf: std_logic_vector(NeededOutputWidth-1 downto 0);

type TState is (Buffering, Shifting, Correcting);
signal State, LastState: TState;
signal ShiftCounter: integer range 0 to InputWidth;

begin

process(clk)
begin
 if rising_edge(clk) then
   case State is
     when Buffering =>                
       dBuf <= d;
       qBuf <= (others => '0');                    
       ShiftCounter <= InputWidth;      
       LastD <= d;
       if LastD /= d then
         State <= Shifting;          
       end if;
     when Shifting =>              
       qBuf(NeededOutputWidth-1 downto 1) <= qBuf(NeededOutputWidth-2 downto 0);
       qBuf(0) <= dBuf(InputWidth-1);
       dBuf(InputWidth-1 downto 1) <= dBuf(InputWidth-2 downto 0);          
       dBuf(0) <= '0';
       ShiftCounter <= ShiftCounter - 1;                  
       State <= Correcting;        
     when Correcting =>      
       if ShiftCounter > 0 then
         State <= Shifting;        
         for i in 0 to NumberOfDigits-1 loop                      
           if qBuf((i * 4) + 3 downto i * 4) > x"4" then
             qBuf((i * 4) + 3 downto i * 4) <= qBuf((i * 4) + 3 downto i * 4) + x"3";
           end if;
         end loop;       
       else      
         State <= Buffering;
       end if;  
     when others => State <= Buffering;
   end case;

   LastState <= State;
   if (LastState /= Buffering) and (State = Buffering) then
     q <= qBuf(OutputWidth-1 downto 0);
     nd <= '1';      
   else
     nd <= '0';
   end if;
 end if;
end process;

end Behavioral;

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вариант 2.1.

Совмещены состояния Shifting и Correcting, теперь преобразование длится в 2 раза меньше времени "InputWidth + 1" такт (по результатам синтеза на Spartan3S400 выдает максимальную частоту 130Мгц).

Добавлена таблица Correct, вместо условия "if (a > 4) then a += 3;", это немного уменьшило занимаемые ресурсы.

Исправлена досадная опечатка в вычислении NumberOfDigits.

Границы применимости:

  • минимальное число десятичных разрядов = 2 (InputWidth >= 7).
  • максимальное, должно быть, не ограничено. Тестировал на 64 бита входного сигнала и 80 бит выходного.

Занимаемые ресурсы (InputWidth = 32, OutputWidth = 40):

ad0b1494.png

 

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.Math_real.ALL;

entity bin2bcd_ver2 is
   Generic(
     InputWidth: integer := 32;      
     OutputWidth: integer := 40
   );
   Port ( clk : in  STD_LOGIC;
          d : in  STD_LOGIC_VECTOR (InputWidth-1 downto 0);
          q : out  STD_LOGIC_VECTOR (OutputWidth-1 downto 0);
          nd : out  STD_LOGIC);
end bin2bcd_ver2;

architecture Behavioral of bin2bcd_ver2 is

constant NumberOfDigits: integer := integer(Ceil(real(InputWidth) * 0.30103));
constant NeededOutputWidth: integer := NumberOfDigits * 4;

type TCorrectTable is array(0 to 15) of std_logic_vector(3 downto 0);
signal Correct: TCorrectTable :=
 (x"0", x"1", x"2", x"3",
  x"4", x"8", x"9", x"A",
  x"B", x"C", x"F", x"F",
  x"F", x"F", x"F", x"F"
 );

signal LastD: std_logic_vector(InputWidth-1 downto 0);
signal dBuf: std_logic_vector(InputWidth-1 downto 0);
signal qBuf: std_logic_vector(NeededOutputWidth-1 downto 0);

type TState is (Buffering, Shifting);
signal State, LastState: TState;
signal ShiftCounter: integer range 0 to InputWidth-1;

begin

process(clk)
begin
 if rising_edge(clk) then
   case State is
     when Buffering =>                
       dBuf <= d;
       qBuf <= (others => '0');                    
       ShiftCounter <= InputWidth-1;
       LastD <= d;
       if LastD /= d then
         State <= Shifting;          
       end if;
     when Shifting =>
       for i in 1 to NumberOfDigits-1 loop
         if ShiftCounter > 0 then
           qBuf((i * 4) + 3 downto i * 4) <= Correct(conv_integer(qBuf((i * 4) + 2 downto i * 4 - 1)));
         else
           qBuf((i * 4) + 3 downto i * 4) <= qBuf((i * 4) + 2 downto i * 4 - 1);
         end if;
       end loop;
       if ShiftCounter > 0 then
         qBuf(3 downto 0) <= Correct(conv_integer(qBuf(2 downto 0) & dBuf(InputWidth-1)));
       else
         qBuf(3 downto 0) <= qBuf(2 downto 0) & dBuf(InputWidth-1);
       end if;
       dBuf(InputWidth-1 downto 1) <= dBuf(InputWidth-2 downto 0);          
       dBuf(0) <= '0';
       if ShiftCounter > 0 then
         ShiftCounter <= ShiftCounter - 1;
       else
         State <= Buffering;
       end if;              
     when others => State <= Buffering;
   end case;

   LastState <= State;
   if (LastState /= Buffering) and (State = Buffering) then
     q <= qBuf(OutputWidth-1 downto 0);
     nd <= '1';      
   else
     nd <= '0';
   end if;
 end if;
end process;

end Behavioral;

Изменено пользователем whiteTigr

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...