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?
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;