понимание двоичного множителя с использованием диаграммы уровня затвора - PullRequest
0 голосов
/ 18 января 2019

У меня проблемы с пониманием следующего кода (bimpy.v), который выполняет операцию 2-разрядного умножения без знака.

Редактировать : Добавлен комментарий от одного из моих друзей: следующая модификация делает то же самое с меньшим количеством логики !!

o_r <= (i_a[0] ? i_b : 2'b0) + ((i_a[1] ? i_b : 2'b0) << 1);

Каковы цели двух сигналов (w_r и c) в bimpy.v?

assign  w_r =  { ((i_a[1])?i_b:{(BW){1'b0}}), 1'b0 }
            ^ { 1'b0, ((i_a[0])?i_b:{(BW){1'b0}}) };

assign  c = { ((i_a[1])?i_b[(BW-2):0]:{(BW-1){1'b0}}) }
        & ((i_a[0])?i_b[(BW-1):1]:{(BW-1){1'b0}});

Код не соответствует 2-битному 2-битному двоичному множителю диаграмма уровня шлюза , пожалуйста, исправьте меня, если ошиблись

2-bit by 2-bit binary multiplier

Я также добавляю рабочий сигнал из bimpy.v для простого множителя без знака 2x2.

bimpy.v waveform

Я также сгенерировал диаграмму представления уровня шлюза для bimpy.v

gate-level representation of bimpy.v

 ////////////////////////////////////////////////////////////////////////////////
//
// Filename:    bimpy
//
// Project: A multiply core generator
//
// Purpose: An unsigned 2-bit multiply based upon the fact that LUT's allow
//      6-bits of input, but a 2x2 bit multiply will never carry more
//  than one bit.  While this multiply is hardware independent, it is
//  really motivated by trying to optimize for a specific piece of
//  hardware (Xilinx-7 series ...) that has 4-input LUT's with carry
//  chains.
//
// Creator: Dan Gisselquist, Ph.D.
//      Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015,2017-2019, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of  the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program.  If not, see <http://www.gnu.org/licenses/> for a
// copy.
//
// License: GPL, v3, as defined and found on www.gnu.org,
//      http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
module  bimpy(i_clk, i_reset, i_ce, i_a, i_b, o_r);
    parameter   BW=2, LUTB=2;
    input               i_clk, i_reset, i_ce;
    input       [(LUTB-1):0]    i_a;
    input       [(BW-1):0]  i_b;
    output  reg [(BW+LUTB-1):0] o_r;

    wire    [(BW+LUTB-2):0] w_r;
    wire    [(BW+LUTB-3):1] c;

    assign  w_r =  { ((i_a[1])?i_b:{(BW){1'b0}}), 1'b0 }
                ^ { 1'b0, ((i_a[0])?i_b:{(BW){1'b0}}) };
    assign  c = { ((i_a[1])?i_b[(BW-2):0]:{(BW-1){1'b0}}) }
            & ((i_a[0])?i_b[(BW-1):1]:{(BW-1){1'b0}});

    initial o_r = 0;
    always @(posedge i_clk)
        if (i_reset)
            o_r <= 0;
        else if (i_ce)
            o_r <= w_r + { c, 2'b0 };

endmodule

1 Ответ

0 голосов
/ 18 января 2019

Примечание по 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)

В конце концов:

  • c = {A1 & 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 (надеюсь!).

...