Я видел хороший вопрос для VHDL - собери систему, которая получает число и определяет, можно ли его разделить на 5 без остатка. Я пытался решить это с помощью конечного автомата (полагаю, они не хотят, чтобы вы использовали mod или rem ), и хотя у меня был первоначальный успех (числа, такие как 5, 10, 15, и числа, такие как 20, 40, 80, работали ), другие цифры, такие как 130, 75 и так далее, для меня не удалось.
Я бы показал свой конечный автомат, но это полный беспорядок (это не код, это рисунок), и, как я уже сказал, даже не работает.
По сути, я пытался записать двоичные числа, которые делятся на 5, и построить конечный автомат, который будет работать для них.
Я был бы рад, если бы вы могли показать мне, как решить эту проблему и как думать, сталкиваясь с чем-то подобным.
Спасибо!
источник
Ответы:
Выполнение операции остатка в последовательном режиме на самом деле довольно просто. Ключевым предположением является то, что данные поступают в MSB-первых, если они последовательные. Вам нужно только N состояний для вычисления остатка по модулю N. Начните с состояния «0», и если вы окажетесь в состоянии «0» после последнего бита (не имеет значения, сколько там битов), остаток нуль.
смоделировать эту схему - схема, созданная с использованием CircuitLab
Подумайте о том, как бы вы делали длинное деление, если бы единственное, что вам нужно было отслеживать, это остаток:
источник
2n mod 5
, а стрелка 1 указывает на(2n + 1) mod 5
.state
,din
иN
ваш код?Вы также можете создать конечный автомат, если данные поступают в LSB:
Существование такого детерминированного конечного автомата (DFA) напрямую следует из другого ответа , который описывает DFA для MSB-first. Поскольку языки, принятые DFA, являются регулярными, а обычные языки, как известно, закрываются при обращении (например, см. Здесь ), должен существовать DFA, который принимает следующий язык:
.L = { w ∈ { 0 , 1 }*| реверс(ш ) 10 делится на 5 }
строительство
Скопируйте MSFA-первый DFA из ответа Дэйва Твида . Для этого я использовал автомат JFLAP .
Примените алгоритм явного преобразования для аннулирования DFA, например, как описано в CS.SE: Проектирование DFA и его обратное .
Вы можете увидеть (не минимизированный) результат этого шага в старой редакции этого ответа.
Действительно, полученный автомат дает правильные ответы:
источник
Один из способов создания конечного автомата (сначала MSB) заключается в следующем:
Число, полученное до сих пор
N
. Предположим, вы знаете остатокM = N mod 5
.Входит новый бит, и теперь новое значение
N' = N*2 + b
.Новый остаток тогда
M' = (N*2 + b) mod 5 = (M*2 + b) mod 5
.Это достаточно просто для составления таблиц вручную:
Что соответствует конечному автомату в ответе Дэйва Твида.
источник
Можно надеяться, что вопрос интервью касался того, как вы решите проблему, а не входов и выходов VHDL или Verilog. Сведения о языке просты, если у вас есть алгоритм.
источник
В зависимости от того, для чего пишется VHDL, вы можете выбрать подход, который описывает его как прямой, комбинационный расчет. Получение числа может означать, что все число будет в регистре в течение одного такта.
Вы можете, например, записать моду 5 значения, которое представляет каждый из битов, сложить их вместе, а затем повторять процесс, пока у вас не останется что-то меньше 5. Или реализуйте это комбинационно для всех шагов сокращения, или повторно использовать логику для небольшого числа циклов.
Но если вы используете оператор rem VHDL, это может быть правильным ответом. Предполагая, что у компании есть приличные инструменты синтеза, это даст вам довольно эффективную реализацию - возможно, немного больше, чем решения конечных автоматов, но с полной пропускной способностью и, следовательно, вероятно, хорошей энергией на расчет. Это вариант, который будет стоить наименьшего времени для реализации и, следовательно, наименьшее количество денег для работодателя!
Чтобы быть справедливым, это, вероятно, не тот ответ, который они ищут с таким вопросом, но это также возможность показать любой реальный опыт проектирования.
источник
Если число представлено кусками, большими, чем один бит, может быть полезно использовать некоторые параллельные вычисления для вычисления модуля 15 вычетов, при условии, что вычисление может дать 15 точно, если остаток равен нулю. Простой способ вычисления остатка мода-15 состоит в том, чтобы заметить, что для любого значения N> = 1 добавление крайних левых 4N битов к части числа, которая выходит за пределы, приведет к значению, которое совпадает с исходным модом 15. Это позволяет разделить проблему по-разному в зависимости от доступных ресурсов.
Например, если вы начинаете с 32-битного значения, это можно рассматривать как восемь 4-битных значений. Они могут быть сложены попарно для получения четырех 5-битных значений, которые, в свою очередь, могут быть объединены в два 6-битных значения или одно 7-битное значение. Добавление старших трех битов этого 7-битного значения к младшим 4-битам даст 5-битное значение, которое не превышает 21. Таким образом, можно определить, является ли исходное значение кратным 5, наблюдая, является ли окончательное значение один из 0, 5, 10, 15 или 20.
источник
Я не помню свой VHDL, но вот набросок идеи, которая впервые пришла в голову:
Последние цифры (в базе 10) первых степеней двух равны 1, 2, 4, 8, 6, 2, ..., и цикл повторяется. Следовательно, остатки мода 5 степеней двух равны 1, 2, 4, 3, ....
Используя это, мы можем сдвигать биты из LSB и накапливать остатки mod 5, соответствующие позиции, когда
1
бит виден. Сделайте мод накопления 5 тоже, и достаточно проверить, равна ли сумма в конце.источник
Мы можем использовать идею из ответа здесь , что в базе 4 мы можем получить, что число делится на 5, только если сумма чередующихся цифр равна. Поэтому мы
Примерим число 166 = (10) (10) (01) (10): 2,2,1,2
2-2 + 1-2 = -1
который равен <= 3 по абсолютной величине, а не 0, поэтому мы можем сделать вывод только за одну итерацию, что 166 не делится равномерно на 5.
Может быть, небольшая память может быть дешевле / лучше с точки зрения скорости / числа ворот, чем итерация. Конечно, можно заранее рассчитать наихудший (максимально возможный результат с учетом допустимых входных данных) и соответствующим образом спланировать проект.
источник
Подход MSB определенно проще, но мне удалось составить диаграмму состояния LSB без необходимости создания решения MSB ... это заняло у меня пару часов. Оказывается, он эквивалентен показанному @ComFreek, просто аннотирован по-другому.
Мы собираемся отслеживать два номера. Сначала мы собираемся отследить текущую сумму по модулю 5 («СУММА»). Во-вторых, мы отследим значение следующей степени сдвига 2 по модулю 5 («СЛЕДУЮЩАЯ»). Я буду представлять каждое состояние с возможными значениями для «СУММЫ» в верхней части и соответствующими им «СЛЕДУЮЩИМИ» значениями под ними.
Начнем со случая, когда «SUM» по модулю 5 равно 0:
Обратите внимание, что состояние выглядит следующим образом:
3,2,4,1
1,4,3,2
эквивалентно:
1,3,4,2
2,1,3,4
Поскольку оба состояния представляют это:
СУММА = 1 и СЛЕДУЮЩАЯ = 4 ИЛИ
СУММА = 2 и СЛЕДУЮЩАЯ = 3 ИЛИ
СУММА = 3 и СЛЕДУЮЩАЯ = 2 ИЛИ
СУММА = 4 и СЛЕДУЮЩАЯ = 1.
Итак, теперь нам нужно разработать дополнительные состояния, так как большинство интервьюеров не будут впечатлены диаграммой состояний только с одним состоянием. Мы закончили, когда каждое состояние имеет два перехода.
Каждый раз, когда вы переходите в новое состояние, каждое число в «NEXT» удваивается, а затем по модулю 5. Для «SUM» следуйте этим правилам:
Итак, начнем с заполнения переходов, когда входящий бит равен 1.
Хорошо, теперь мы заполняем нули. Добавлено только одно состояние, так что мы продолжим и заполним его переходы.
И вуаля! У нас есть конечный автомат, который сначала принимает LSB, без необходимости генерировать решение MSB.
источник
Все вышеперечисленное кажется таким сложным! Существует простой математический способ определить, делится ли двоичное целое число на пять. Для начала, вы помните, как выполнять «раздачу девяток» в обычной десятичной арифметике? Вычет по модулю 9 десятичного целого числа совпадает с вычетом по модулю 9 суммы его цифр. Это работает, потому что 9 меньше номера базы.
Существует аналогичный процесс, «отбрасывание одиннадцати», когда знаки альтернативных цифр устанавливаются отрицательными. Это работает, потому что одиннадцать больше, чем база чисел.
Так что, если мы хотим «выбросить пятерки», мы можем представить наше целое число в числе четыре. Затем мы начинаем с самой младшей пары цифр в качестве начальной суммы и вычитаем ее из следующей пары цифр, чтобы получить следующую сумму. После прохождения нашего целого числа-кандидата таким образом, окончательная сумма будет равна нулю или делится на 5, если наше исходное целое число делится на 5.
Пример 70: 01 00 01 10 -> 01 00 -1 -> 01 01 -> 00, делится на 5 Пример 49: 11 00 01 -> 11 -1 -> 1 00 -> 1, НЕ делится на 5
Обратите внимание, что вы должны нести дополнительные биты для знака накопленной разности и для случаев, когда есть перенос.
Другой способ - просто добавить шестнадцатеричные цифры, чтобы получить остаток по модулю 15. Конечно, вам нужен последний логический шаг, чтобы определить три приемлемых результата: ноль, пять и десять.
Пример 70: 4 6 -> A, поэтому 70 делится на 5 (но не на 15). Пример 49: 3 1 -> 4, поэтому 70 НЕ делится на 5.
Обратите внимание, что вы можете использовать разные числовые базы для построения множества тестов на делимость, хотя в компьютерной логике те, которые имеют степени 2 +/- 1, проще всего реализовать.
В десятичной арифметике одним из моих любимых является мой тест на остаток от модификации 7. Обратите внимание, что 100 больше, чем кратное 7, на два, поэтому сгруппируйте цифры в пары (работайте в базе чисел 100) и добавьте сотни ДВАЖДЫ из единиц. Здесь мы работаем слева направо ...
Пример: 98 76 -> 2 72 -> 76, поэтому 9876 не делится на 7. Это 6 мод 7. Пример: 03 45 67 -> 51 67 -> 1 69 -> 71, поэтому 1 мод 7.
Конечно, в двоичном коде просто взять сумму восьмеричных цифр (группы из 3 бит).
Извините, я хотел бы быть гуру Verilog, но арифметика - это все, что я могу предложить на этом этапе жизни. Посмотрите «Мертвый расчет» Рона Доерфлера, чтобы увидеть множество подобных трюков.
источник
Вопрос интервью VHDL должен привести к некоторому коду VHDL.
Мне довелось найти бэкэнд-ошибку ghdl llvm с реализацией таблицы перехода состояний Дэйва Твида, где автор ghdl перевел реализацию в функцию до 17 строк:
Соответствующий тестовый пример довольно мал, что упрощает отладку и использует имена состояний, совместимые с VHDL, в перечисляемом типе:
(создано с помощью Dia)
Идея здесь в том, что функция (или даже примерная программа VHDL из 27 строк) достаточно коротка, чтобы написать ответ VHDL во время интервью. Не нужно беспокоиться о том, чтобы испортить вопрос интервью, требующий демонстрации как знаний, так и навыков, и собеседник должен защищать реализацию при допросе.
(Ошибка бэкенда llvm была исправлена в коммите 1f5df6e ранее сегодня.)
Следует отметить, что таблица перехода состояний также сообщает нам, где частным битом будет «1», показанный переходом в состояние с более низким значением остатка (или обоими переходами для r4) при вычитании 5 из дивиденда. Это может быть закодировано в отдельной таблице (или таблице типа записи, которая кажется громоздкой). Мы делаем это исторически в графическом оборудовании, работающем с горизонтальными разрешениями экрана, кратными 5 пикселям.
Это дает нам div / mod5, производящий частное и остаток:
Реализовано здесь с помощью оператора создания, внутреннего оператора создания, производящего частичные биты. Массив remaindr обеспечивает трассировку перехода состояния:
Все без арифметической операции.
Это также возможно реализовать в процедуре без использования всех регистров, использующих параметры с выключенным режимом. Это приблизилось бы к минимальному количеству строк для интервью.
Последовательная реализация с синхронизацией потребует счетчика битов и управления потоком (триггер JK и пара гейтов).
Существует компромисс между временем и сложностью в зависимости от размера дивидендов, который вы, вероятно, также должны будете защищать во время интервью.
источник