Search code examples
vhdl

VHDL: Combining multiplication and slicing into one line


I have a hardware accelerated function that requires two instances of fixed point multiplication. My current solution (example below) requires two clock cycles per multiplication; one step of multiplication, followed by a second step where that value is sliced back to the original input word size. I would like this to take as few cycles as necessary for latency.

Here is my current solution:

signal a        : std_logic_vector(7 downto 0);
signal b        : std_logic_vector(7 downto 0);
signal y        : std_logic_vector(7 downto 0);
signal product  : std_logic_vector(15 downto 0);
    
MULTIPLY_PROCESS : process(clk) 
    begin
        if(rising_edge(clk)) then
            product <= std_logic_vector(unsigned(a) * unsigned(b));
            y <= product(11 downto 4);      --takes one additional clock cycle
        end if;                             --for y to appear
end process;

It makes sense to me that this could be shrunk down to one clock cycle, as normal unsigned multiplication does this automatically by throwing out the top end of the oversized vector.

example:

signal a    : std_logic_vector(7 downto 0);
signal b    : std_logic_vector(7 downto 0);
signal y    : std_logic_vector(7 downto 0);

MULTIPLY_PROCESS : process(clk)
    begin
        if(rising_edge(clk)) then
            y <= std_logic_vector(unsigned(a) * unsigned(b)); --truncates automatically
        end if;
end process;

This is code I thought would work, but throws a compiler error:

y <= std_logic_vector(unsigned(x) * unsigned(a))(11 downto 4)

Error: Prefix of slice name cannot be type conversion (STD_LOGIC_VECTOR) expression.

Is there some way to fixed-point multiply and truncate in a single line/step/clock cycle?


Solution

  • Credit to user1155120. Calling the multiplication through a function and then slicing the function before conversion does the trick.

    y <= std_logic_vector("*"(unsigned(x), unsigned(a))(11 downto 4));