Примечание по MUX
Напомним, что ?
описывает мультиплексор (MUX), поэтому утверждение:
out = sel ? x : y
эквивалентен в реализации уровня шлюза:
out = (sel & x) | (~sel & y)
(когда sel=1
, out <= x
, когда sel=0
, out <= y
)
Если y=0
, то MUX понижается до AND между x
и sel
: out = (sel & x) | (~sel & 0) = sel & x
Получение w_r
Предполагается, что BW=2
и LUTB=2
w_r
являются 4-битным сигналом. Давайте разберемся с этим:
w_r = w_rL ^ x_rR
w_rL = { ((i_a[1])?i_b:{(BW){1'b0}}), 1'b0 }
w_rR = { 1'b0, ((i_a[0])?i_b:{(BW){1'b0}}) }
Обратите внимание, что оба значения "else" MUX обнуляются, поэтому MUX упрощаются до AND, как в примечании выше:
w_rL = { BW{i_a[1]} & i_b, 1'b0 } = { A1 & B1, A1 & B0, 0 }
w_rR = { 1'b0, BW{i_a[0]} & i_b } = { 0, A0 & B1, A0 & B0}
Я заменил i_a = {A1, A0}
и i_b = {B1, B0}
, чтобы упростить представление. В конце концов, XORing их поразрядно:
w_r[0] = 0 ^ (A0 & B0) = A0 & B0
w_r[1] = (A1 & B0) ^ (A0 & B1)
w_r[2] = (A1 & B1) ^ 0 = A1 & B1
w_r[3] = 0
(устанавливается неявно)
Получение c
Аналогично, для 1-битного c
сигнала:
c = cL & cR
cL = i_a[1] ? i_b[(BW-2):0]:{(BW-1){1'b0}} = {A1 & B0}
cR = i_a[0] ? i_b[(BW-1):1]:{(BW-1){1'b0}} = {A0 & B1)
В конце концов:
Получение o_r
Если мы сломаем o_r
бит:
o_r[0] = 0 + w_r[0] = A0 & B0
o_r[1] = 0 + w_r[1] = (A1 & B0) ^ (A0 & B1)
o_r[2] = c + w_r[2] = (A1 & B0 & A0 & B1) + (A1 & B1)
- если мы добавим их, то сумма будет их XOR, а перенос будет их И, т.е.: o_r[2] = (A1 & B0 & A0 & B1) ^ (A1 & B1)
o_r[3] = <carry from o_r[2] addition> = A1 & B0 & A0 & B1 & A1 & B1 = A1 & B0 & A0 & B1
(помните, ANDing with the себе равняется самому себе, т.е. x & x = x
)
Выходы схемы уровня затвора
Ваша диаграмма уровня ворот изображает следующие уравнения:
C0 = A0 & B0
(=o_r[0]
)
C1 = (A0 & B1) ^ (A1 & B0)
(=o_r[1]
)
C2 = (A0 & B1 & A1 & B0) ^ (A1 & B1)
(=o_r[2]
сумма)
C3 = (A0 & B1 & A1 & B0) & (A1 & B1) = A0 & B1 & A1 & B0
(=o_r[3]
нести)
Почему реализация такая странная?!
Комментарии к коду указывают, что ячейка умножителя построена для конкретной архитектуры FPGA, и похоже, что первоначальный кодер намеревался разместить каждую ячейку умножителя в одной LUT для этой архитектуры. Поэтому я держу пари, что оригинальный кодер пытался «направить» старый, тупой инструмент на построение множителя эффективным с точки зрения ПЛИС способом, который обычно не эффективен на уровне затвора. Я думаю, что такие «ручные» оптимизации уровня RTL бесполезны с современными инструментами EDA (надеюсь!).