masics 0 18 августа, 2015 Опубликовано 18 августа, 2015 · Жалоба Есть код: module tb; logic one_bit; logic [3:0] select; logic [15:0] mask; assign mask = (~one_bit) << select; initial begin one_bit = 1'b0; select = 3; #1; $display("mask = %x", mask); end endmodule На выходе я получаю: mask = fff8 А ожидал: mask = 0008 Как исправить знаю (даже несколькими способами), но не понимаю почему оно не работает в таком виде. Не подскажете? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Александр77 1 19 августа, 2015 Опубликовано 19 августа, 2015 · Жалоба Насколько понимаю, Вы сперва инвертируете one_bit (результат FFFF), а затем сдвигаете на 3 разряда (итог fff8). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
masics 0 19 августа, 2015 Опубликовано 19 августа, 2015 · Жалоба Я ожидал, что инверсия одного бита будет один бит. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Sobol' 0 19 августа, 2015 Опубликовано 19 августа, 2015 · Жалоба Используйте "!" вместо "~" Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
masics 0 19 августа, 2015 Опубликовано 19 августа, 2015 · Жалоба Используйте "!" вместо "~" Это одно из решений. Но не всегда работает. Например, если one_bit будет 2 или больше бит. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Shivers 0 19 августа, 2015 Опубликовано 19 августа, 2015 · Жалоба Просто, надо всегда указывать разрядности у шин. mask[15:0] = {15'h0,~one_bit} << select; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
embddr 0 19 августа, 2015 Опубликовано 19 августа, 2015 · Жалоба Действительно странно. Это как-то связано с неявным приведением типов, потому что если сделать wire inv_one_bit = ~one_bit; assign mask = inv_one_bit << select; то работает как задумывалось. Однако, в стандарте я ничего не нашел на этот счет. Может плохо искал, потому что все симуляторы показывают одинаковый результат. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
masics 0 19 августа, 2015 Опубликовано 19 августа, 2015 · Жалоба Можно и так: assign mask = 1'(~one_bit) << select; Но хотелось бы узнать настоящую причину. Я не зря скобки ставил - думал что сначала выполнится инверсия, а уж потом будет приведение типа. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
embddr 0 19 августа, 2015 Опубликовано 19 августа, 2015 · Жалоба думал что сначала выполнится инверсия, а уж потом будет приведение типа. Похоже, что сначала все переменные приводятся к типу результата, а потом производятся вычисления. Надо стандарт еще раз почитать, наверняка там есть информация про это. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AndrewS6 0 19 августа, 2015 Опубликовано 19 августа, 2015 · Жалоба Похоже, что сначала все переменные приводятся к типу результата, а потом производятся вычисления. Надо стандарт еще раз почитать, наверняка там есть информация про это. SystemVerilog IEEE1800-2012 Глава 11.6 Expression bit lengths Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
masics 0 19 августа, 2015 Опубликовано 19 августа, 2015 · Жалоба Я не думаю что это то место. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
FatRobot 0 19 августа, 2015 Опубликовано 19 августа, 2015 · Жалоба классная головоломка, ага. Общая идея такая: вы подключаете шину меньшего размера к шине большего размера. Какое значение примут оставшиеся не подключенными проводники? Ответ: любое, какое вы можете нафантазировать. В данном случае это значение msb шины меньшего размера из-за промежуточного преобразования в int. Можно заглянуть в стандарт и, наверное, найти место, где про это рассказано, но гораздо быстрее для получения результата описать конструкцию прямолинейным и очевидным способом. Держать все эти особенности стандарта в голове вместе со ссылками на разделы стандарта - это слишком хлопотно. практический вывод из всего этого только один: не стоит экономить на нажатиях клавиш. Вы сэкономили 10 лишних символов в исходнике, но зато написали не меньше 100 символов сюда, чтобы разобраться, почему не работает. Такая вот простая бухгалтерия. Я не думаю что это то место. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 19 августа, 2015 Опубликовано 19 августа, 2015 · Жалоба на самом деле если написать так $unsigned( ((~one_bit) << select) ) старшими будут нолики, а если так $signed( ((~one_bit) << select) ) старшими будут в зависимости от старшего в ((~one_bit) << select), почему по умолчанию преобразование signed непонятно... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
serjj1333 0 19 августа, 2015 Опубликовано 19 августа, 2015 (изменено) · Жалоба почему по умолчанию преобразование signed непонятно... signed тут не причём. Подозреваю, что в случае $unsigned( ((~one_bit) << select) ) сначала выполняется то что в скобках с приведением типов после уже для расширенного числа (операция <<), а, если $unsigned опустить, то сначала произойдёт приведение типов, а именно расширение разрядности one_bit до разрядности результата, операция ~ при этом даст 1 во всех добавленных битах, простая логическая операция без привязки к signed/unsigned представлению. Вот и знаменитое автоматическое согласование разрядностей верилога :rolleyes: Изменено 19 августа, 2015 пользователем serjj Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
embddr 0 19 августа, 2015 Опубликовано 19 августа, 2015 (изменено) · Жалоба SystemVerilog IEEE1800-2012 Глава 11.6 Expression bit lengths Не, там написано, что результат операции "~" имеет длину аргумента. По идее, сначала дожно вычисляться (~one_bit) с длиной результата 1 бит, а потом расширение до 16 бит. Но в нашем случае почему-то сначала расширяется one_bit до 16 бит, а потом происходит инверсия. Кстати, можно и без сдвига. Если оставить одну инверсию, получится 0xfff. Изменено 19 августа, 2015 пользователем embddr Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться