1

I am trying to implement a recoding logic for a 32 bit multiplier in VHDL. Besides, the input bit vector (x_in) to be recoded, it has one extra input "one". The intent is when "one" is '1' the output should be x_in else if "one" is '0', it should be twice x_in. And if "neg" is high then the output has to be inverted. Here is my VHDL code:

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use IEEE.std_logic_arith.all;

package sum_vector_pkg is
    type partial_sum_array is array (0 to 15) of std_logic_vector(32 downto 0);
end package;

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use IEEE.std_logic_arith.all;
use work.sum_vector_pkg.all;
use work.test.all;

entity multipleGenerator is 
    generic(
           constant WIDTH : integer := 32
    );
    port(
        x_in      : in std_logic_vector(WIDTH - 1 downto 0);
        one       : in std_logic_vector(WIDTH/2 - 1 downto 0);
        multiple  : out partial_sum_array
    );
end entity multipleGenerator;

architecture logic of multipleGenerator is
    signal sum  : std_logic_vector(WIDTH downto 0);

begin
    gen : for i in 0 to WIDTH/2 - 1 generate
        process (one,sum,x_in) is begin
            case one(i) is
                when '0' => sum <= x_in & '0'; -- twice x_in
                when '1' => sum <= '0' & x_in; -- same as x_in
                when others => sum <= x"00000000" &'0';
            end case;
            multiple(i) <= sum;
            report "The sum is " & toString(sum) & " one(i) is " & toString(one(i)) & " x_in is " & toString(x_in);
        end process;
    end generate;
end architecture logic;

I am running it with the following testbench:

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
use work.sum_vector_pkg.all;

entity tb_multipleGenerator is

end entity tb_multipleGenerator;

architecture logic of tb_multipleGenerator is

    component multipleGenerator
        generic(
           constant WIDTH : integer := 32
        );
        port(
            x_in      : in std_logic_vector(31 downto 0);
            one       : in std_logic_vector(15 downto 0);
            multiple  : out partial_sum_array
        );
    end component;

    signal x_tb        : std_logic_vector(31 downto 0);
    signal one_tb      : std_logic_vector(15 downto 0);
    signal multiple_tb : partial_sum_array;

begin
    process begin
        x_tb <= x"00000000";
        one_tb <= x"0000";
        wait for 200 ns;
        x_tb <= x"00001111";
        one_tb <= x"0011";
        wait;
    end process;

    u_mult: multipleGenerator
        generic map (
           WIDTH => 32
        )
        port map (
            x_in     => x_tb,   
            one      => one_tb,
            multiple => multiple_tb
        );
end architecture logic;

To check the output I am using the following package:

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use IEEE.std_logic_arith.all;

package test is
    function toString(v : std_logic_vector) return string;
    function toString(b : std_logic) return string;
end package;

package body test is 
    function toString(b : std_logic) return string is
        variable str : string(1 to 3);
        begin
            str := std_logic'image(b);
            return "" & str(2);
    end toString;

    function toString(v : std_logic_vector) return string is
        variable str    : string(1 to 1);
        variable strOut : string(1 to v'length);
        begin
            for i in 1 to v'length  loop
                str := toString(v(i-1));
                strOut(v'length - i + 1) := str(1);
            end loop;
            return strOut;
    end toString;
end test;

When I run the above code I get 'X' in the output. Here is the sample output:

    Time: 200 ns  Iteration: 2  Region: /tb_multiplegenerator/u_mult/gen(12)
# ** Note: The sum is 0000000000000000000XX00XX00XX00XX one(i) is 0 x_in is 00000000000000000001000100010001
#    Time: 200 ns  Iteration: 2  Region: /tb_multiplegenerator/u_mult/gen(13)
# ** Note: The sum is 0000000000000000000XX00XX00XX00XX one(i) is 0 x_in is 00000000000000000001000100010001
#    Time: 200 ns  Iteration: 2  Region: /tb_multiplegenerator/u_mult/gen(14)
# ** Note: The sum is 0000000000000000000XX00XX00XX00XX one(i) is 0 x_in is 00000000000000000001000100010001
#    Time: 200 ns  Iteration: 2  Region: /tb_multiplegenerator/u_mult/gen(15)

Could someone please explain why this code is not working?

sarthak
  • 774
  • 1
  • 11
  • 27
  • How about a [Minimal, Complete and Verifiable example](https://stackoverflow.com/help/mcve)? You could have dummied package mlite_pack with function bv_negate and provided a testbench. At the minimum supply a clear value for one and neg at the time of failure and shown how those report statements are generated. Your problem can't be replicated with what you have supplied. –  Jun 15 '17 at 22:29
  • @user1155120 I have updated the question and provided the testbench as well, please take a look, it should be replicable now. – sarthak Jun 15 '17 at 22:53
  • 1
    Where is the "The sum is ..." output generated in your code? – mkrieger1 Jun 15 '17 at 22:55
  • I have a separate package for it which I have not included to make the question readable. But the output should be evident from the waveforms. But I can add if you need it. – sarthak Jun 15 '17 at 22:57
  • If I understand correctly, it should be generated somewhere in the `gen : for i in 0 to WIDTH/2 - 1 generate` loop, but there is nothing there. – mkrieger1 Jun 15 '17 at 23:01
  • Inside the generate block I have a process and in the last line of process, I have the following line: `report "The sum is " & toString(sum) & " one(i) is " & toString(one(i)) & " x_in is " & toString(x_in);` toString is a function defined in a separate package which converts the sum signal to string for printing. – sarthak Jun 15 '17 at 23:03
  • In your testbench you set `x_tb <= x"00000000"` or `x_tb <= x"00001111"`. But the output says `x_in is 10001000100010000000000000000000`. Something is not right here as well. – mkrieger1 Jun 15 '17 at 23:16
  • I suggest you check whether your `toString` function is correct. – mkrieger1 Jun 15 '17 at 23:16
  • I have added the code and I am also seeing the 'X' in the waveforms in questasim so should be correct. – sarthak Jun 15 '17 at 23:17
  • 2
    Try removing `std_logic_arith` and `std_logic_unsigned`, maybe they interfere with the normal `std_logic_vector` in unexpected ways. [You shouldn't be using them anyway](http://insights.sigasi.com/tech/deprecated-ieee-libraries.html). – mkrieger1 Jun 15 '17 at 23:28
  • Didn't work either. – sarthak Jun 15 '17 at 23:33

1 Answers1

1

The problem is already in your multipleGenerator entity. You define the signal sum, which you keep reusing in your generate statement. However, these assignments happen in parallel in VHDL. So in effect, you are assigning sum with 16 drivers!

But you don't need sum actually.

Cleaning up your code (and making it vhdl 2008)

std_logic_vector_vector_pkg.vhd:

library ieee;
use ieee.std_logic_1164.all;

package std_logic_vector_vector_pkg is
    type std_logic_vector_vector is array (natural range <>) of std_logic_vector;
end package;

converter_pkg.vhd

library ieee;
use ieee.std_logic_1164.all;

package converter_pkg is
    function to_string(slv : std_logic_vector) return string;
end package;

package body converter_pkg is
    function to_string(slv : std_logic_vector) return string is
        variable output : string(1 to slv'length) := (others => 'X');
        variable i_o : positive := 1;
    begin
        for i_s in slv'high downto slv'low loop
            output(i_o) := std_logic'image(slv(i_s))(2);
            i_o := i_o + 1;
        end loop;
        return output;
    end function;
end package body;

multipleGenerator.vhd

library ieee;
use ieee.std_logic_1164.all;
use work.std_logic_vector_vector_pkg.all;
use work.converter_pkg.all;

entity multipleGenerator is 
    generic(
        WIDTH : integer := 32
    );
    port(
        x_in      : in std_logic_vector(WIDTH - 1 downto 0);
        one       : in std_logic_vector(WIDTH/2 - 1 downto 0);
        multiple  : out std_logic_vector_vector(0 to WIDTH/2 - 1)(WIDTH downto 0)
    );
end entity;

architecture rtl of multipleGenerator is
begin
    gen : for i in 0 to WIDTH/2 - 1 generate
        multiple(i) <= '0' & x_in when one(i)='1' else x_in & '0';
    end generate;

    process(one)
    begin
        for i in 0 to WIDTH/2 - 1 loop 
            report "The sum is " & to_string(multiple(i)) &
                " one(" & integer'image(i) & ") is " & std_logic'image(one(i)) &
                " x_in is " & to_string(x_in);
        end loop;
    end process;
end architecture;

multipleGenerator_tb.vhd

library ieee;
use ieee.std_logic_1164.all;
use work.std_logic_vector_vector_pkg.all;

entity multipleGenerator_tb is end entity;

architecture behavioral of multipleGenerator_tb is
    signal b        : std_logic_vector(31 downto 0);
    signal one      : std_logic_vector(15 downto 0);
    signal multiple : std_logic_vector_vector(0 to one'length-1)(x'length downto 0);
begin
    process
    begin
        x <= (others => '0');
        one <= (others => '0');
        wait for 200 ns;
        x <= x"00001111";
        one <= x"0011";
        wait;
    end process;

    u_mult: entity work.multipleGenerator
        generic map (
            WIDTH => x'length
        )
        port map (
            x_in     => x,   
            one      => one,
            multiple => multiple
        );
end architecture;
JHBonarius
  • 10,824
  • 3
  • 22
  • 41