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

whiteTigr

Участник
  • Постов

    54
  • Зарегистрирован

  • Посещение

Репутация

0 Обычный

Информация о whiteTigr

  • Звание
    Участник
    Участник
  • День рождения 29.11.1987

Контакты

  • Сайт
    Array
  • ICQ
    Array
  1. Собственно, топик. По всему подфоруму равномерно разбросаны оба применения, и периодически в темах получаются холивары.
  2. Так оно же не синтезирует чтение из файла, а просто дает памяти начальные значения. По смыслу получается примерно тоже самое, что и *.coe подключать.
  3. Найденное в интернете описание на регистр - ИР15 - 4-разрядный универсальный регистр. Что-то язык, на котором Вы привели программу, больше на VHDL похож. if R='0' and C'Event and C='1' and PE1='0' and PE2='0' then Нежелательно смешивать определение фронта тактового сигнала и логические переменные. if c'event and c = '1' then -- или rising_edge(c) if r = '0' and PE1 = '0' and PE2 = '0' then Длинная цепочка "if ... elsif ... elsif" нежелательно. Лучше заменять такие конструкции на case <selector> is when <value> => ...; -- действия при selector = value when <value2> => ...; -- действия при selector = value2 when others => null; -- действия, во всех остальных случаях. end case; "Селектор" можно сформировать в виде S <= PE2 & PE1; Небольшая статья на эту тему - http://www.piv.by/journals/KiT_02_2008.pdf
  4. Вы уже описали всю схему. Осталось только немножко поискать. По сдвиговому регистру, например, первая же ссылка с пачкой реализаций: http://electronix.ru/forum/index.php?showtopic=11996. Применительно к Вашей задаче, должно получится что-то такое: signal D: std_logic_vector(7 downto 0) := "10101100"; ... process(clk) begin if rising_edge(clk) then d(7 downto 0) <= d(6 downto 0) & d(7); end if; end process; Вот здесь я не понял. В моем понимании процент ошибок и будет хранится в сдвиговом регистре. И выдает выход invert. invert <= d(0); q <= d when invert = '0' else not d; Вам осталось только собрать все это вместе. П.С.: Разница между Си и VHDL существенная. Си последовательно исполняет строчку за строчкой, а VHDL работает параллельно. Особенно сильно мозг выворачивается в начале изучения из-за разрыва шаблона. Например, операция обмена двух "переменных" в VHDL будет выглядеть примерно так process(clk) begin if rising_edge(clk) then a <= b; b <= a; end if; end process; Никаких временных переменных. Просто прямой обмен.
  5. 2 варианта: 1) Вы указываете что нужно сделать, и Вам предлагают несколько вариантов реализации. 2) Вы указываете как нужно сделать, и Вам помогают реализовать вашу схему. Что-то такое Вы хотите? Компаратор сравнивает два каких то числа и выдает сигнал на инвертер входного сигнала. q <= d when invert = '0' else not d;
  6. А програмирование на десктопе - это намагничивание дисков в нужных местах :laughing:
  7. Так начало то более-менее стандартное. Диодики, кнопки, счетчик по кнопке (с защитой от дребезга). И дальше уже ближе к решаемой задаче.
  8. Самостоятельно изучать програмирование ПЛИС - сложное занятие. Если же, это делается не самостоятельно, то вопросы не нужно задавать на форуме. Лучше все же будет узнать у преподавателя.
  9. ... architecture Behavioral ... is signal D: std_logic_vector(7 downto 0); signal Q: std_logic_vector(7 downto 0); signal WE: std_logic; -- write enable begin process(clk) begin if rising_edge(clk) then if WE = '1' then Q <= D; end if; end if; end process; end Behavioral; Как он реализуется в схеме? Скоре всего это будут LUT4 (LUT6 в новых ПЛИС). А в VHDL это обычная операция типа: cmpRes <= '1' when D = Q else '0'; или process(clk) begin if rising_edge(clk) then if D = Q then cmpRes <= '1'; else cmpRes <= '0'; end if; end if; end process; Хотя, возможно, я недопонял сути второго вопроса.
  10. Вариант 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): 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;
  11. Вариант номер 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;
  12. Вот так получилось. Теперь можно меня громко обругать за корявость кода. :) П.С.: к сожалению, не помню тега, чтобы блок кода был со скроллером. 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;
  13. Хм, реализовал решение "в лоб", в ISIM работает примерно также, как и ожидалось (83 такта получилось). Сейчас поищу, как быстрее все это считают. :)
  14. Начнемс с начала. Bin2Bcd. :) Попробую сделать его параметризованым с InputWidth (максимум 32 бита) в generic. Считать буду за несколько тактов простым вычитанием (худший случай 1_999_999_999, должно быть ~90 тактов на вычисление).
  15. Может кто-нибудь подкинуть интересных задачек на VHDL для развития мозгов? Возможно, с различными условиями типа "занять не больше ячеек X", "сделать без умножалок", "посчитать не более, чем за X тактов" и т.п. Или просто интересные задачи без каких либо условий. Поиск в гугле практически ничего не дает. Попадаются ссылки на форумы, "задачи" студентов уровня "как сделать c = a + b".
×
×
  • Создать...