Verilog меняет размер правой части
У меня есть базовый модуль, чтобы кое-что продемонстрировать.
module tb();
reg [2:0] U;
reg [2:0] T;
reg [2:0] C;
reg E;
initial begin
U = 5;
T = 3;
{E, C} = U + ~T + 1'b1;
#1000;
end
endmodule
Я ожидаю, что E будет 1, потому что;
U
является 101
T
является 011
и U + ~T + 001
есть,
101
100
001
+______
= 1010
Итак, C получает часть 010, а E получает 1. Это ожидаемое поведение, однако я получаю C то же самое, но E как 0. Я думаю, verilog увеличивает размеры переменных RHS до 4 бит, потому что левая часть составляет 4 бита ( 1 + 3). Однако для T он добавляет начальный 0 перед дополнением T, поэтому T становится 0011, а его дополнение оказывается равным 1100 вместо 0100, 4-битная версия дополнения T.
И это приводит к
0101
1100
0001
+______
= 10010
Это приводит к тому, что E равняется 0, как видно.
Я не понимаю, почему это так, и не мог найти способ сделать дополнение до добавления ведущего нуля.
Если вместо этого я сделаю следующее, все будет нормально, и E получит 1:
U = 5;
T = 3;
T = ~T;
{E, C} = U + T + 1'b1;
Это подтверждает, что мои подозрения верны. Итак, у меня есть такое решение, да. Однако я не очень доволен этим, я думаю, что должен быть способ предотвратить такое поведение.
Любая помощь будет оценена по достоинству.
Ответы
Когда у вас есть операнды, состоящие из смеси разной ширины, Verilog имеет правила для определения размера каждого операнда по ширине самого большого операнда на основе контекста выражения. Вы правильно заметили, что LHS - это 4 бита, операнды на RHS расширяются до 4 бит. Это происходит перед применением операции.
Вы можете исправить это, воспользовавшись тем фактом, что операнды конкатенации являются самоопределяемыми контекстами:
{E, C} = U + {~T} + 1'b1;
Теперь ширина ~T
определяется исключительно шириной T
.