Как Verilog ведет себя с отрицательными числами?
например, скажем, у меня есть reg [7:0] myReg
Я присваиваю ему значение -8'D69
Я знаю, что Verilog хранит его как дополнение 2, поэтому он должен храниться как
10111011
вопрос, который у меня сейчас есть, если бы я должен был выполнить операцию на нем, скажем myReg / 2
будет ли он оценивать до -34? Или он возьмет 10111011 и превратит его в 187, а затем выполнит деление, вернув 93?
3 ответов
вы должны помнить, что -8d69
просто немного шаблон. reg-это тип, который содержит битовые шаблоны. Это тип переменной, которая указывает /
выполнить signed или unsigned арифметика.
если это для синтеза голого в виду, что вы хотите попытаться избежать разделителей, вы действительно хотите попытаться избежать подписанных разделителей. Скорее всего, синтез будет меньше с >>> 1
reg [7:0] a;
reg signed [7:0] b;
reg [7:0] c;
reg signed [7:0] d;
initial begin
a = -8'd69 ;
b = -8'd69 ;
c = -8'd69 ;
d = -8'd69 ;
#10ns;
a = a/2 ;
b = b/2 ;
#10ns;
$display("a : %8b, %d", a, a);
$display("b : %8b, %d", b, b);
$display("c >>>1 : %8b, %d", c>>>1, c>>>1);
$display("d >>>1 : %8b, %d", d>>>1, d>>>1);
end
выдает:
a : 01011101, 93
b : 11011110, -34
c >>>1 : 01011101, 93
d >>>1 : 11011101, -35
>> x
сдвиги вправо на x мест, >>> x
сдвигает вправо X мест, но знак распространяется на подписанные типы.
NB:/2
также округляется в моих примерах,>>>
округлит/усечет.
например, скажем, у меня есть reg [7: 0] myReg я назначаю ему значение -8'D69
на самом деле это не знаковое число, а выражение, состоящее из унарного отрицания, применяемого к положительной константе. Если выражение -8'd130
результат будет переполнен. Подписанные константы объявляются как 8'sd69
или просто 69
.
вопрос, который у меня сейчас есть, если бы я должен был выполнить операцию на нем, сказать myReg/2
myReg
не имеет знака, поэтому результат выражения также будет без знака*. Если вам нужно, чтобы результат был подписан, чем все операнды должны быть подписаны. Есть несколько способов добиться этого:
//Declare the reg as signed and divide by a signed value
reg signed [7:0] myReg;
assign result = myReg/2;
//Use system functions
assign result = $signed(myReg)/2;
*полные правила относительно оценки выражений намного сложнее, но в основном результат любого выражения без знака, если все операнды не подписаны.
reg signed [7:0] a;
reg [7:0] b;
initial
begin
result = a; //Signed
result = a * a; //Signed
result = a * 10; //Signed
result = $unsigned(a); //Unsigned
result = a[0]; //Unsigned
result = a[7:0]; //Unsigned
result = {a,a}; //Unsigned
result = 10{a}; //Unsigned
result = a + b; //Unsigned
result = a * b; //Unsigned
end
Я добавлю, что 1. По умолчанию типы данных bit и reg не имеют знака. 2. По умолчанию подписываются типы данных int, integer, longint, shortint и byte. 3. Все эти типы данных могут принимать подписанный или неподписанный квалификатор для изменения значения по умолчанию.
таким образом, присвоение -8'd69 myReg делает неявное преобразование в 187. Затем myReg / 2 = 187/2 = 93, без знака. Важно понимать, когда и как SystemVerilog выполняет неявные преобразования типов в выражениях и назначениях.