alperovich 0 21 мая, 2015 Опубликовано 21 мая, 2015 · Жалоба Добрый день. Пытаюсь воспроизвести алгоритм Бута по примеру из Википедии https://ru.wikipedia.org/wiki/%D0%90%D0%BB%....B8.D1.82.D0.BC На листе всё выходит нормально, при написании алгоритма на verilog получается не настолько точно. Вот листинг кода http://pastebin.com/BgSTGGdC Помогите разобраться с ошибкой, пожалуйста. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Maverick_ 15 21 мая, 2015 Опубликовано 21 мая, 2015 · Жалоба Добрый день. Пытаюсь воспроизвести алгоритм Бута по примеру из Википедии https://ru.wikipedia.org/wiki/%D0%90%D0%BB%....B8.D1.82.D0.BC На листе всё выходит нормально, при написании алгоритма на verilog получается не настолько точно. Вот листинг кода http://pastebin.com/BgSTGGdC Помогите разобраться с ошибкой, пожалуйста. зачем? есть встроенные умножители, если нету (в современных плис это редкость), то синтезатор сам синтезирует умножитель ... Вам достаточно написать а = в*с PS думаю Вы плохо "просили" гугл Вам найти пример описания Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alperovich 0 21 мая, 2015 Опубликовано 21 мая, 2015 (изменено) · Жалоба зачем? есть встроенные умножители, если нету (в современных плис это редкость), то синтезатор сам синтезирует умножитель ... Вам достаточно написать а = в*с Пишу диплом на тему "быстрый умножитель". Сравниваю между собой различные алгоритмы. Если говорить про синтезируемый умножитель, то при малых разрядностях он проигрывает как по числу LUT, так и по быстродействию. Я нашел реализации алгоритма Бута на verilog и vhdl, но мне больше интересно, в чем здесь ошибка. Выяснилось, что суммирование и вычитание производятся нужное число раз, но всё равно результат неправильный. Изменено 21 мая, 2015 пользователем Moses Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dworfik 0 8 июня, 2015 Опубликовано 8 июня, 2015 · Жалоба Если вы пишите диплом, то зачем разбираться в том правильный результат или неправильный? B) Помнится сам писал этого Бута, давно это было. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alperovich 0 8 июня, 2015 Опубликовано 8 июня, 2015 · Жалоба Если вы пишите диплом, то зачем разбираться в том правильный результат или неправильный? B) Конечно, вообще никто не будет запускать мой вериложный код, который указан в конце диплома, и можно так всё оставить, но самому интересно, где здесь ошибка. Кстати, если вдруг кому-то нужно, то написал другой алгоритм для разрядностей 4x4, 8x8, 16x16. По некой причине unsigned умножает нормально, signed только в том случае, если A положительное. Поэтому переделал только под умножение беззнаковых чисел. http://pastebin.com/jHsDkRJg Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
serjj1333 0 8 июня, 2015 Опубликовано 8 июня, 2015 · Жалоба Кстати, если вдруг кому-то нужно, то написал другой алгоритм для разрядностей 4x4, 8x8, 16x16. По некой причине unsigned умножает нормально, signed только в том случае, если A положительное. Поэтому переделал только под умножение беззнаковых чисел. 1) этот алгоритм вообще должен работать для знаковых чисел? Если да, то: 2) либо объявите все регистры/порты как знаковые, либо при работе с ними указывайте, что синтезатор должен интерпретировать их как знаковые, используя $signed() 3) у вас в одном месте используется арифметический сдвиг: X <<< 1, а в другом - обычный X << 2, так должно быть? Для беззнаковых это одно и тоже, для знаковых результат будет разным. 4) always@(*) проще, это не VHDL, зачем описывать все входящие переменные так дотошно, хотя в учебных целях может и надо ) 5) используйте регистры, заведите клок и перенесите ваш always @ (A, B) в always@(posedge clock). 6) 3'b000:; 3'b111:; это лучше описать через default. У вас там вообще походу latch нарисовывается. Перепишите через регистры или переделайте блокирующие операции как положено. Поищите примеры реализации подобного кода на верилоге в нете, наверняка их немало, посмотрите как люди делают, может найдёте для себя что нибудь полезное, а вообще нужно книги почитать, что нибудь базовое по rtl design. Но это всё если вы после диплома собираетесь на этом поприще трудиться, если нет, то смело забудьте, что я тут понаписал :rolleyes: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alperovich 0 8 июня, 2015 Опубликовано 8 июня, 2015 · Жалоба 1) этот алгоритм вообще должен работать для знаковых чисел? Если да, то: 2) либо объявите все регистры/порты как знаковые, либо при работе с ними указывайте, что синтезатор должен интерпретировать их как знаковые, используя $signed() 3) у вас в одном месте используется арифметический сдвиг: X <<< 1, а в другом - обычный X << 2, так должно быть? Для беззнаковых это одно и тоже, для знаковых результат будет разным. 4) always@(*) проще, это не VHDL, зачем описывать все входящие переменные так дотошно, хотя в учебных целях может и надо ) 5) используйте регистры, заведите клок и перенесите ваш always @ (A, B) в always@(posedge clock). 6) 3'b000:; 3'b111:; это лучше описать через default. У вас там вообще походу latch нарисовывается. Перепишите через регистры или переделайте блокирующие операции как положено. Поищите примеры реализации подобного кода на верилоге в нете, наверняка их немало, посмотрите как люди делают, может найдёте для себя что нибудь полезное, а вообще нужно книги почитать, что нибудь базовое по rtl design. Но это всё если вы после диплома собираетесь на этом поприще трудиться, если нет, то смело забудьте, что я тут понаписал :rolleyes: Спасибо за совет по поводу signed, действительно в этом дело. По поводу сдвигов - в одном случае происходит умножение на два, в другом просто сдвиг на два бита. Думаю, при умножении имеет смысл сохранять знак. Теперь всё работает правильно :) Что посоветуете почитать по rtl design? За семестр обучения верилога я научился описывать полусумматоры четырьмя способами, собирать из этого полный сумматор, а из полного сумматора - n-битный сумматор, но лишь недавно узнал про assign {carry, summ} = A + B; Вот правильная итоговая версия, если кому-то нужно. http://pastebin.com/Y2fqX3dj Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
serjj1333 0 8 июня, 2015 Опубликовано 8 июня, 2015 (изменено) · Жалоба Я даже не знаю, что посоветовать. Для начала пробегитесь по нету, почитайте туториалы с самыми простейшими конструкциями, попутно реализуя каждую конструкцию в modelsim и смотря на waveview как это работает. После проверки в modelsim обязательно собирайте эту конструкцию в quartus/ise/vivado (что ближе будет, пока вам вендор не важен, quartus имеет самый дружественный интерфейс) и смотрите как ваша схема собирается в rtl viewer. Неплохой сайт например вот. Кое что разбирают на stack exchange ну и вообще гуглите ресурсы по выбранному вами языку. Ну и тут разумеется постоянно обсуждаются всяческие ньюансы, но это все таки форум а не учебник). Кстати в тех же quartus/ise есть темплейты языка на самые базовые конструкции, их тоже все надо бы проиграть. Вот книга, но за неё стоит браться, когда уже немного освоитесь с языком, поможет привести мысли в порядок. Удачи. А, ПС, забыл. Стандарт языка еще конечно. Его читать будет мучительно больно по началу, но это необходимо. Чтобы не получилось, что язык вроде освоили, но полного понимания нет. Надо сразу приучать себя. Сначала будет непонятно, но по мере написания вами самых базовых конструкций, стандарт будет все более и более доступным и необходимым. Изменено 8 июня, 2015 пользователем serjj Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 8 июня, 2015 Опубликовано 8 июня, 2015 · Жалоба А еще описание синтезируемых конструкций под конкретное семейство ПЛИС, поновее возьмите, типа всяких XST User Guide. Там очень дотошно перечислены как в конкретном ПЛИС описывается та или иная конструкция, так что чуть ли не перекрывает стандарт верилога.... Есть такой же обобщенный документ Но я не уверен что надо учить описание элементов и собирать из них схему, я выступаю за поведенческий дизайн, а уже конкретику отдавать синтезатору. Это тратить больше ЛУТов, но зато экономит время. А оно нынче дороже ЛУТов. Все естественно ИМХО... А на алгоритм бута в итоге все забили? или ошибку нашли и поправили? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Maverick_ 15 8 июня, 2015 Опубликовано 8 июня, 2015 · Жалоба Добрый день. Пытаюсь воспроизвести алгоритм Бута по примеру из Википедии https://ru.wikipedia.org/wiki/%D0%90%D0%BB%....B8.D1.82.D0.BC На листе всё выходит нормально, при написании алгоритма на verilog получается не настолько точно. Вот листинг кода http://pastebin.com/BgSTGGdC Помогите разобраться с ошибкой, пожалуйста. посмотрите это Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
serjj1333 0 9 июня, 2015 Опубликовано 9 июня, 2015 (изменено) · Жалоба Вот правильная итоговая версия, если кому-то нужно. http://pastebin.com/Y2fqX3dj 1) Изучите как блокирующие присвоение (=) отличается от неблокирующего (<=) и почему для регистров используется неблокирующее 2) Неправильно в двух или более разных местах присваивать значение одному и тому же регистру; если регистру могут присваиваться разные значения, это должно быть описано в одном always блоке через конструкции if-else if-else или case-endcase. Присвоение в разных местах без условной связи даст вам неопределенный синтез, все равно что написать: Пете 10 лет, а через пол страницы - Пете 13 лет :rolleyes: 3) логика на MULT это какой-то кошмар, его нужно либо переделать, сделав нормальное дерево, либо вынести MULT в блок комбинаторной логики always@(*). Тогда по клоку захватываются входные данные, т.е. ваши M и Х и выходные данные, например MULTREG, а само вычисление будет комбинаторным 4) вообще почитайте что такое циклы for и while в verilog, очень похоже, что вы их тут пытаетесь использовать по аналогии с С 5) вы добавили в case default условие, но что будет по дефолту с MULT? Если case конструкция используется для блокирующего присвоения, вы должны описать все возможные ситуации иначе состояние неопределенности переменной синтезируется как латч, что неправильно. Подозреваю, что это еще одно наследие С Вы рисовали схему вашего устройства умножителя в виде базовых блоков (сумматоры/логика/регистры) например для небольшой разрядности (4/8)? Я бы на вашем месте для начала расписал бы для случая 8, например, без использования for весь алгоритм. И например в двух вариантах - чисто комбинаторном и в виде дерева суммирования с регистрами на каждой стадии. Вам возможно покажется что я тут много всего понаписал, но возможно некоторую пользу вы извлечете и пойдете в верном направлении. Опять повторяюсь, что вам нужно начать прорабатывать базовые и простейшие примеры, а не бросаться сразу на автогенерирующиеся конструкции (которыми и являются циклы) без понимания основ. Изменено 9 июня, 2015 пользователем serjj Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 9 июня, 2015 Опубликовано 9 июня, 2015 · Жалоба Не совсем согласен с 1. Я и для регистров использую блокирующее присвоение. Согласен с тем что надо знать отличие от неблокирующего, но что блокирующее только не для регистров не верно. запись a = a + b; c = a + d; равносильна a <= a + b; c <= a + b + d; это всего лишь удобство записи.... с 2. Тоже не совсем понял. В разных always ISE вообще не даст присваивать одному регистру значения, скажет у регистра много разных источников, но внутри одного не обязательно if-if else - else, верилог дает очень удобную "перегрузку" которая делает запись более читаемой. я всегда конструкции вида always @(posedge clk) begin if(reset) begin .... a <= 0; end else begin a<= ..... end end предпочитаю более читаемую always @(posedge clk) begin a<= ..... if(reset) begin .... a <= 0; end end всегда выполниться последние возможное присвоение... особенно удобно когда есть несколько источников у регистра, которые могут наступить одновременно. Запись регистра по ходу работы, по внешнему интерфейсу, по сигналу ошибки, и сигналу сброса. Так их и описываю друг за другом, в порядка приоритета, сброс в конце, работа в начале, очень удобно и читаемо... Про циклы согласен - все сначала считают что это как в С цикл, в ХДЛ языках это всего лишь сокращение записи не более... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
serjj1333 0 9 июня, 2015 Опубликовано 9 июня, 2015 · Жалоба с 2. Тоже не совсем понял. В разных always ISE вообще не даст присваивать одному регистру значения, скажет у регистра много разных источников, но внутри одного не обязательно if-if else - else, верилог дает очень удобную "перегрузку" которая делает запись более читаемой. Если мы пишем блокирующее присвоение, например в теле функции, то действительно можно спокойно написать a = 'd1; a = a + b; a = a + c; a = a + 1'b1; ... И он будет просто наращивать сумматор, но если речь идёт о неблокирующем присвоение, то тут я за строгость - регистр а существует в одном экземпляре физически, он должен быть определен в одном месте и однозначно без "перегрузок", тогда мы сразу видим при каком сценарие какая логика задаёт его значение. И синтезатор это видит. Не совсем согласен с 1. Я и для регистров использую блокирующее присвоение. Согласен с тем что надо знать отличие от неблокирующего, но что блокирующее только не для регистров не верно. Пока не будет понимания основ про эту "приятную опцию" лучше забыть. ИМХО лучше допускать такое вообще только в функциях. Я тут пару месяцев назад в теме про SV функции потоптался изрядно по граблям с использованием блокирующих присвоений в always_ff блоках, это не то, чему нужно новичка учить, хаос в голове обеспечен :rolleyes: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alperovich 0 9 июня, 2015 Опубликовано 9 июня, 2015 · Жалоба 1) Изучите как блокирующие присвоение (=) отличается от неблокирующего (<=) и почему для регистров используется неблокирующее 2) Неправильно в двух или более разных местах присваивать значение одному и тому же регистру; если регистру могут присваиваться разные значения, это должно быть описано в одном always блоке через конструкции if-else if-else или case-endcase. Присвоение в разных местах без условной связи даст вам неопределенный синтез, все равно что написать: Пете 10 лет, а через пол страницы - Пете 13 лет :rolleyes: 3) логика на MULT это какой-то кошмар, его нужно либо переделать, сделав нормальное дерево, либо вынести MULT в блок комбинаторной логики always@(*). Тогда по клоку захватываются входные данные, т.е. ваши M и Х и выходные данные, например MULTREG, а само вычисление будет комбинаторным 4) вообще почитайте что такое циклы for и while в verilog, очень похоже, что вы их тут пытаетесь использовать по аналогии с С 5) вы добавили в case default условие, но что будет по дефолту с MULT? Если case конструкция используется для блокирующего присвоения, вы должны описать все возможные ситуации иначе состояние неопределенности переменной синтезируется как латч, что неправильно. Подозреваю, что это еще одно наследие С Вы рисовали схему вашего устройства умножителя в виде базовых блоков (сумматоры/логика/регистры) например для небольшой разрядности (4/8)? Я бы на вашем месте для начала расписал бы для случая 8, например, без использования for весь алгоритм. И например в двух вариантах - чисто комбинаторном и в виде дерева суммирования с регистрами на каждой стадии. Вам возможно покажется что я тут много всего понаписал, но возможно некоторую пользу вы извлечете и пойдете в верном направлении. Опять повторяюсь, что вам нужно начать прорабатывать базовые и простейшие примеры, а не бросаться сразу на автогенерирующиеся конструкции (которыми и являются циклы) без понимания основ. 1. Насколько я понимаю, в этом случае после каждой итерации цикла создастся буфер. В таком случае у меня получится конвейерный умножитель, а мне нужен работающий за один такт. 2. Вы про MULT = 33'b0; ? Это тоже из С - обнулять переменные перед использованием. Но ведь, насколько я понимаю, данную запись можно удалить безо всякого опасения. 3. Здесь не совсем понял. Можно поподробнее? 4. Здесь тоже не совсем понял. Можете привести пример правильного использования циклов? 5. По дефолту ничего с ним не будет, останется таким же. Теперь по результатам моделирования: в случае использования неблокирующего присваивания количество LUT увеличивается с 1130 до 1640, умножитель перестаёт правильно работать. Мне кажется, ваши советы, несомненно, хороши, особенно про default и latch, но часть их не совсем применима к этому алгоритму. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
serjj1333 0 9 июня, 2015 Опубликовано 9 июня, 2015 (изменено) · Жалоба 1. Насколько я понимаю, в этом случае после каждой итерации цикла создастся буфер. В таком случае у меня получится конвейерный умножитель, а мне нужен работающий за один такт. Не буфер а регистр. Всё правильно, конвеерное вычисление. Необходимо понимать зачем это применяется. Если вам в данном задание нужно получить минимальную задержку на вычисление, никто не заставляет делать конвеер, но нужно понимать зачем их вообще делают. Забегая вперед, в той книге, которую я выложил несколькими постами выше, в первой главе все это неплохо разжевывается. Это тоже из С - обнулять переменные перед использованием. Верилог не С, здесь вы работаете не с областями памяти, а с физическими ресурсами в виде ЛУТов, регистров и прочего. Когда вы описываете регистр, у вас не может быть двух разных описаний на один и тотже (физически) объект иначе как синтезатор поймет что от него требуется? Т.к. регистры хранят свои значения как память, их можно обнулять, но для этого лучше использовать сигнал сброса (это уже вообще отдельная тема). Если описывается комбинаторная логика, то многократные описания "навешивают" дополнительную логику на вашу схему. Обнуление кстати в случае комбинаторной логики совершенно избыточная операция. 4. Здесь тоже не совсем понял. Можете привести пример правильного использования циклов? пример: logic signed [7:0] q [0:3]; logic signed [6:0] a [0:3]; logic signed [6:0] b [0:3]; always@(*) begin for (int i=0; i<4; i++) begin q[i] = {{(1){a[i][6]}}, a[i]} + {{(1){b[i][6]}}, b[i]}; end end создаст схему из 4-х однотипных умножителей upd.сумматоров. пример: logic [7:0] delayline [0:3]; always@(posedge clock) begin delayline [0] <= idata; for (int i=1; i<4; i++) begin delayline [i] <= delayline [i-1]; end end создаст линию задержки глубиной 4 такта и шириной 8 бит. 5. По дефолту ничего с ним не будет, останется таким же. И будет латч, почитайте в нете про латчи и почему делать их плохо. Не заканчивать case или if-else допускается только для регистров, т.к. если ни одно из условий не выполняеся, регистр просто сохраняет свое значение. 3. Здесь не совсем понял. Можно поподробнее? Этот весь цикл, коль скоро у вас умножитель должен отрабатывать "сразу" нельзя так просто взять и затащить в always@(posedge clock), т.к. это комбинаторная логика, его следует вынести в always@(*). Далее данные по входу и по выходу должны захватываться по входному клоку. В итоге ваша комбинаторная схема будет описывать путь сигналов между входным и выходным регистрами. Этот путь вы сможете проанализировать по времени, сделать оценку на какой максимальной частоте сможет работать ваша схема для выбранного кристалла. Далее сам цикл: каждая "итерация" добавляет новый слой логики, исходными данными для которого служат выходные данные предыдущего слоя. На каждом слое следует полно описывать функцию выхода от входа, т.е. значение выхода для всех возможных вариантов. Если так хотите сделать через цикл, то следует на каждый слой завести свои переменные, т.е что-то вроде: for(...) if (...) state[i]=state[i-1]+...; else if (...) state[i]=state[i-1]-...; else state[i]=state[i-1]; Только учтите, что такое размножение логики удлиняет путь между регистрами входа и выхода, снижая максимальную тактовую частоту, к которой данные могут быть синхронны. Мне кажется, ваши советы, несомненно, хороши, особенно про default и latch, но часть их не совсем применима к этому алгоритму. Вам конечно виднее, ну а я наверное и так много времени на "не совсем применимые советы" потратил наверное разберетесь и так! Изменено 9 июня, 2015 пользователем serjj Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться