I want to multiply a 57-bit integer with an 11-bit integer. The result can be up to 68 bits so I'm planning to split my result into 2 different integers. I cannot use any library and It should be as simple as possible because the code will be translated to VHDL.

There is some way to that online but all of them are not meet my criteria. I want to split the result as an 60-bit lower part and an 8-bit higher part.

C++

int main() {
    unsigned long long int log2 = 0b101100010111001000010111111101111101000111001111011110011;
    unsigned short int absE;
    unsigned in result_M;
    unsigned long long int result_L;

    result_L = absE * log2;
    result_M = 0;
}

VHDL

signal absE : std_logic_vector(10 downto 0);
signal log2 : std_logic_vector(57 downto 0) := "101100010111001000010111111101111101000111001111011110011";
signal result: std_logic_vector(67 downto 0);
result <= absE * log2;

3 Answers

1
chqrlie On Best Solutions

You can split the 57-bit value into smaller chunks to perform the multiplications and recombine into the required parts, for example 8+49 bits:

#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>

int main() {
#define MASK(n)  ((1ULL << (n)) - 1)
    uint64_t log2 = MASK(57);                     // 57 bits
    uint16_t absE = MASK(11);                     // 11 bits
    uint32_t m1 = (log2 >> 49) * absE;            // middle 19 bits at offset 49;
    uint64_t m0 = (log2 & MASK(49)) * absE + ((m1 & MASK(11)) << 49); // low 61 bits
    uint16_t result_H = (uint16_t)(m1 >> 11) + (uint16_t)(m0 >> 60); // final high 8 bits
    uint64_t result_L = m0 & MASK(60);

    printf("%#"PRIx64" * %#"PRIx16" = %#"PRIx16"%012"PRIx64"\n",
           log2, absE, result_H, result_L);
    return 0;
}

Output: 0x1ffffffffffffff * 0x7ff = 0xffdfffffffffff801

You may need more steps if you cannot use the 64-bit multiplication used for the 49-bit by 11-bit step.

0
P__J__ On

VHDL is different than C - here you have the paper how to implement multiplication. Expand it to as many bits as you need:

http://www.eng.auburn.edu/~nelsovp/courses/elec4200/Slides/VHDL%207%20Multiplier%20Example.pdf

0
Cacahuete Frito On

In GCC:

__int128 a;
__int128 b;
__int128 c;
uint64_t c_lo;
uint8_t c_hi;

a = 0x789;
b = 0x123456789ABCDEF;
c = a * b;

c_lo = (uint64_t)c & ((UINT64_C(1) << 60) - 1);
c_hi = (unsigned __int128)c >> 60;

You will need the standard library for this. You will need the header file <stdint.h> (<cstdint> in C++), but that shouldn't be a problem when translating into VHDL.