Jump to content
    

Реализация простой операции (Verilog)

К вечеру башка совсем не работает, как проще реализовать следующую вещь (Verilog):

 

reg [7:0] A, B, C, D;

 

d = (A - 4*B + 4*C - D) / 8 ("/" - dicivion by trancation toward zero)

d1 = |d|

 

Все то что на ум приходит необходимо отслеживать на переполнение, а это слишком большим получается.

Забыл сказать, исходные числа только положительны

Share this post


Link to post
Share on other sites

К вечеру башка совсем не работает, как проще реализовать следующую вещь (Verilog):

 

reg [7:0] A, B, C, D;

 

d = (A - 4*B + 4*C - D) / 8 ("/" - dicivion by trancation toward zero)

d1 = |d|

 

Все то что на ум приходит необходимо отслеживать на переполнение, а это слишком большим получается.

Забыл сказать, исходные числа только положительны

 

Заменить умножение и деление чисел, кратных 2, сдвигом влево-вправо на соответствующее число разрядов и все дела.

ну а абс значение определяется по старшему разряду. Если это отрицательное число, то делается преобразование. Эта операция зависит от формы представления числа...

Share this post


Link to post
Share on other sites

Сдвиги это понятно (можно б было об этом и не упоминать)

 

wire [10:0] A_addC, B_addD;

wire [11:0] sum;

wire [8:0] sum_dev;

wire [7:0] abs_sum_dev;

 

assign A_sumC = A + (C << 2'b10);

assign B_sumD = (B << 2'b10 + D);

assign sum = {1'b0, A_sumC} - {1'b0, B_sumD};

assign sum_dev = sum >> 2'b11;

 

assign abs_sum_dev = sum_dev[8] ? (!sum_dev + 1'b1) : sum_dev;

 

Вроде все так, или нет так или еще проще есть вариант?

Остается вопрос почему на работе до этого не доходишь, элементарно же ведь

Share this post


Link to post
Share on other sites

Сдвиги это понятно (можно б было об этом и не упоминать)

 

Отнюдь

 

(

input [7:0] a, b, c, d,

output [8:0] abs_sum_dev

);

 

wire [8:0] A_add_D;

wire [10:0] B_add_C;

wire [11:0] sum;

wire [8:0] sum_dev;

 

 

assign A_add_D = a - d;

assign B_add_C = {c, 2'b00} - {b, 2'b00};

assign sum = {2'b00, A_add_D} + B_add_C;

assign sum_dev = sum[11:3];

assign abs_sum_dev = sum_dev[8] ? -sum_dev : sum_dev;

Share this post


Link to post
Share on other sites

Еще вопросик:

a = (2*(p5 - p8) - 5*(p6 - p7) + 4) >>3

 

Сейчас это выглядит следующим образом (входы строго положительны):

input [7:0] P5, P6, P7, P8;

 

wire [8:0] P5Sub8, P6Sub7;

wire [10:0] A2Temp1;

wire [11:0] A2Temp2, A2Temp;

wire [8:0] A2Combo;

 

assing P5Sub8 = {1'b0, P5} - {1'b0, P8};

assing P6Sub7 = {1'b0, P6} - {1'b0, P7};

 

assign A2Temp1 = {P5Sub8[8], P5Sub8, 1'b0} + 11'd4;

assign A2Temp2 = {P6Sub7[8], P6Sub7, 2'b00} + {P6Sub7[8], P6Sub7[8], P6Sub7[8], P6Sub7};

 

assign A2Temp = {A2Temp1[10], A2Temp1} - A2Temp2;

assign A2Combo = A2Temp[11:3];

 

Но немного не хватает по performance, есть идеи?

Share this post


Link to post
Share on other sites

Но немного не хватает по performance, есть идеи?

 

какие идеи. непонятки одни. С представлением чисел. Или пользуйтесь ключевыми словами

signed? unsigned. Или вручную. Но не смешивайте понятия.

 

module sum_signed_unsigned

(

input add,

input [3:0] a, b, // unsigned

input [3:0] aa, bb, // signed

output [4:0] s, // unsigned

output [4:0] ss // signed

);

 

assign s = add ? {1'b0, a} + {1'b0, b} : {1'b0, a} - {1'b0, b};

assign ss = add ? {aa[3], aa} + {bb[3], bb} : {aa[3], aa} - {bb[3], bb};

 

endmodule

Share this post


Link to post
Share on other sites

Еще вопросик:

a = (2*(p5 - p8) - 5*(p6 - p7) + 4) >>3

ребят, а зачем вам вообще заморочки с ручным упрощением? нормальный синтезёр по-моему разложит это по оптимальной схеме автоматически (?)

Share this post


Link to post
Share on other sites

ребят, а зачем вам вообще заморочки с ручным упрощением? нормальный синтезёр по-моему разложит это по оптимальной схеме автоматически (?)

 

а что значит нормальный синтезатор. Разложит без расширения разрядной сетки. А кому это надо.

Share this post


Link to post
Share on other sites

а что значит нормальный синтезатор. Разложит без расширения разрядной сетки. А кому это надо.

а отдать эту заботу на попечение встроенных типов int или unsigned int? при синтезе лишние биты будут сокращены (?)

Share this post


Link to post
Share on other sites

а отдать эту заботу на попечение встроенных типов int или unsigned int? при синтезе лишние биты будут сокращены (?)

Я ведь из народа вышел. Приведите выше описанное с int. Буду благодарен.

Share this post


Link to post
Share on other sites

ребят, а зачем вам вообще заморочки с ручным упрощением? нормальный синтезёр по-моему разложит это по оптимальной схеме автоматически (?)

 

Не хватет синтезатора, либо ломать то что уже сделано (увеличивать число клоков на расчет, и следовательно падает performance), либо переписывать логику на более простую.

Share this post


Link to post
Share on other sites

Возвращаясь к начальному, посколько тогда это было не использовано, но теперь понадобилось.

 

d = (A - 4*B + 4*C - D) / 8 ("/" - dicivion by trancation toward zero)

 

собака порылась в последнем, как поделить с насыщеним к нулю, если цифра отрицательна?

 

5 - 0101

(-5) - 1011

5/2 = 2 - 010

(-5/2) = -2 - 110

Но если просто сдвинуть на 1 бит (-5), то будет 101, т.е. неверно. Можно конечно выйти в положительную плоскость, но это приведет к двойному суммированию (туда и обратно).

 

Есть вариант: + x[3] (старший бит сдвигаемого числа) и только потом сдвигать, но всегда ли он верен?

Share this post


Link to post
Share on other sites

d = (A - 4*B + 4*C - D) / 8 ("/" - dicivion by trancation toward zero)

 

вообще то классика жанра, во всех книгах по быстрой арифметике есть. если число отрицательное и отбрасываемый остаток != 0 то + 1.

 

вот для деления на 4

 

always_comb begin
  if (dat2scale[$high(dat2scale)] & dat2scale[1:0] != 0)
    dat4scale = dat2scale[$high(dat2scale):2] + 1'b1;
  else
    dat4scale = dat2scale[$high(dat2scale):2];
end

 

Удачи

Share this post


Link to post
Share on other sites

вообще то классика жанра, во всех книгах по быстрой арифметике есть. если число отрицательное и отбрасываемый остаток != 0 то + 1.

 

вот для деления на 4

 

always_comb begin
  if (dat2scale[$high(dat2scale)] & dat2scale[1:0] != 0)
    dat4scale = dat2scale[$high(dat2scale):2] + 1'b1;
  else
    dat4scale = dat2scale[$high(dat2scale):2];
end

 

Удачи

 

Спасибо, в принципе то что я написал выше совпадает с вашим, можно просто сложить со старшим битом числа в количестве равном сдвигу. Получается, что если остаток ненулевой, то +1, либо +3, либо +7, что немного меньше, поскольку нет сравнения. :beer:

 

А книжки нет под руками, :wassat:

 

Спасибо, в принципе то что я написал выше совпадает с вашим, можно просто сложить со старшим битом числа в количестве равном сдвигу. Получается, что если остаток ненулевой, то +1, либо +3, либо +7, что немного меньше, поскольку нет сравнения. :beer:

 

Обшибся, у вас сумматор на пару бит меньше получается, ваш проще.

 

А книжки нет под руками, :wassat:

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...