I am trying to create schematics for a NxM -bit parallel block multiplier using generic parameters to define the size of the multiplier, and generate statements to describe the internal structure. I am having some trouble with my sums and carries and I am not able to implement what I want to do in VHDL code.
Here is what I got so far:
1-bit multiplier:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use ieee.numeric_std.all;
use ieee.std_logic_unsigned.all;
entity mult is
port (
a : in std_logic;
b : in std_logic;
Sin : in std_logic; --sum-in
Cin : in std_logic; --carry-in
Sout : out std_logic; --sum-out
Cout : out std_logic --carry-out
);
end mult;
architecture mult of mult is
begin
Sout <= '1' when a = '0' and b = '0' and Sin = '0' and Cin = '1' else
'1' when a = '0' and b = '0' and Sin = '1' and Cin = '0' else
'1' when a = '0' and b = '1' and Sin = '1' and Cin = '0' else
'1' when a = '0' and b = '1' and Sin = '0' and Cin = '1' else
'1' when a = '1' and b = '0' and Sin = '0' and Cin = '1' else
'1' when a = '1' and b = '0' and Sin = '1' and Cin = '0' else
'1' when a = '1' and b = '1' and Sin = '0' and Cin = '0' else
'1' when a = '1' and b = '1' and Sin = '1' and Cin = '1' else
'0';
Cout <= '1' when a = '0' and b = '0' and Sin = '1' and Cin = '1' else
'1' when a = '0' and b = '1' and Sin = '1' and Cin = '1' else
'1' when a = '1' and b = '0' and Sin = '1' and Cin = '1' else
'1' when a = '1' and b = '1' and Sin = '0' and Cin = '1' else
'1' when a = '1' and b = '1' and Sin = '1' and Cin = '0' else
'1' when a = '1' and b = '1' and Sin = '1' and Cin = '1' else
'0';
end mult;
Used it as a component in an NxM multiplier:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use ieee.numeric_std.all;
use ieee.std_logic_unsigned.all;
entity generic_mult is
generic (bits: integer);
port (
a : in std_logic_vector(bits-1 downto 0);
b : in std_logic_vector(bits-1 downto 0);
answer: out std_logic_vector(bits*2-1 downto 0) --sum-out
);
end entity generic_mult;
architecture behavioral of generic_mult is
component mult is
port (
a : in std_logic;
b : in std_logic;
Sin : in std_logic; --sum-in
Cin : in std_logic; --carry-in
Sout : out std_logic; --sum-out
Cout : out std_logic --carry-out
);
end component;
type mem_word is array (0 to bits) of std_logic_vector(bits downto 0);
signal carry_internal : mem_word;
signal sum_internal : mem_word;
begin
this_is_label: for N in 1 to bits generate --Im sorry, my labels are horrible :(
this_is_label3: for M in 0 to bits-1 generate
this_is_label2: mult
port map (
a => a(N-1),
b => b(M),
Cin => carry_internal(M)(N),
Cout => carry_internal(M+1)(N),
Sin => sum_internal(M)(N),
Sout => sum_internal(M+1)(N-1)
);
end generate;
end generate;
labellll: for N in 0 to bits-1 generate
sum_internal(N+1)(N) <= carry_internal(N)(N);
carry_internal(0) <= (others => '0');
sum_internal(0) <= (others => '0');
answer(bits*2-1) <= carry_internal(bits)(bits);
answer(bits downto 0) <= sum_internal(bits);
end generate;
end behavioral;
And a testbench for it:
library IEEE;
use IEEE.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_unsigned.all;
entity NM_mult_tb is
end NM_mult_tb;
architecture behavioral of NM_mult_tb is
component generic_mult
generic (bits: integer := 4);
port (
a : in std_logic_vector(bits-1 downto 0);
b : in std_logic_vector(bits-1 downto 0);
answer: out std_logic_vector(bits*2-1 downto 0) --sum-out
);
end component;
--declaring inputs and initializing them
signal a : std_logic_vector(3 downto 0) :="0101";
signal b : std_logic_vector(3 downto 0) :="1010";
signal Sin: std_logic_vector(3 downto 0) :="0000";
signal Cin: std_logic := '0';
--declaring outputs and initializing them
signal answer : std_logic_vector(7 downto 0); --sum-out
signal correct: std_logic; --carry-out
BEGIN
-- Instantiating the Design Under Test (DUT)
dut: generic_mult
GENERIC MAP (4)
PORT MAP (
a => a,
b => b,
answer => answer
);
-- Stimulus process
correct <= '1' when to_integer(unsigned(a))*to_integer(unsigned(b)) =
to_integer(unsigned(answer)) else '0';
stim_proc: process
begin
wait for 1 ns;
a <= a + 1;
if a = "0" then b <= b + 1; end if;
end process;
END;
When I simulate it I see that there is something wrong with carry-ins and sum-ins and outs and my answer has undefined bits in it:
(I am not allowed to embedded images on this post before I have 10 reputation so here is a link to the image:) https://i.stack.imgur.com/y4ED9.png
If you have read my post this far, thank you very much for your attention. If someone could find the time to help me out with my problem I would be very grateful!
Sincerely,
A confused VHDL beginner
Best Answer
Here's how I would work it. Code first:
mult.vhd
generic_mult.vhd
simulation
The first thing I did was to simplify the
mult
entity. And since it is implemented as a 1-bit multiplier, I changed the signal names.For
generic_mult
, I found it much easier to split yourcarry_internal
andsum_internal
buses to separate in/out buses. It removed a lot of the confusion. From there, it's not too difficult - as I think you'll see from the code.Lastly, I changed your
to
to allow for MxN widths.