Getting "test2.vhd(43): VHDL Compiler exiting" error with if-statement on commented out lines but not with the "sum2" lines - vhdl

As the title says, I'm getting a compiler exiting error with the if-statement when I use the lines commented out with the "sum" value but not with the "sum" 2 value and I'm not sure why.
Code:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use IEEE.std_logic_unsigned.all;
entity test2 is port
(
a, b : IN unsigned( 3 DOWNTO 0 );
cin : IN unsigned;
sum : OUT unsigned( 4 DOWNTO 0 )
);
end test2;
architecture behavioral of test2 is
signal a_5, b_5, cin_5, sum2 : unsigned(4 downto 0) := (others => '0');
signal x, y : unsigned(4 downto 0) := (others => '0');
signal z : std_logic;
begin
a_5 <= ('0' & a);
b_5 <= ('0' & b);
cin_5 <= ('0' & '0' & '0' & '0' & cin);
sum <= a_5 + b_5 + cin_5;
sum2 <= a_5 + b_5 + cin_5;
process (sum2, b_5)
--process (sum, b_5)
begin
if (sum2 > b_5) then
--if (sum > b_5) then
z <= '1';
else
z <= '0';
end if;
end process;
end behavioral;
For some context:
I'm working on an adder that adds two 4bit numbers and eventually displays the decimal value on a 7seg display.
I want to take the "sum" value and check if it is greater than decimal value 9 and if so then it sets a flag to always have the 7seg display for the 10s value display a 1. (I only need to count up to decimal value 19). I can probably do this another method but I started doing it this way and got stuck here and I think this is something fundamental I am just not understanding.

sum is a port, which has the type "out". Ports out type "out" can't be read. If you want to read an output port, you must use the type "buffer". sum2 instead is a signal, which can always be read
(By the way you should only use numeric_std and not std_logic_unsigned, which is an old solution and not preferred anymore).

Related

VHDL Counter ones errors

I already done the code, and it can work, However, when I try to write the test bench, I got some troubles on that. The input x sets up as 8 bits, and x: IN BIT_VECTOR (N -1 DOWNTO 0).
When I write the test bench I connot enter the bits number.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
USE ieee.std_logic_unsigned.all;
ENTITY Count_ones IS
GENERIC (N: INTEGER := 8); -- number of bits
PORT ( x: IN BIT_VECTOR (N -1 DOWNTO 0); y: OUT NATURAL RANGE 0 TO N);
END ENTITY ;
architecture Behavioral of Count_ones is
TYPE count is Array (N DOWNTO 1) OF Natural;
signal a : count;
begin
a(0) <= 1 when (x(0) = '1')
else
0;
gen: FOR i IN N-1 DOWNTO 0
GENERATE
a(i+1) <= (a(i)+1) when (x(i)='0')
else
a(i);
END GENERATE;
y <= a(N-1);
end Behavioral;
The Test Bench:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_unsigned.all;
ENTITY Count_ones_TB IS
END Count_ones_TB;
ARCHITECTURE behavior OF Count_ones_TB IS
COMPONENT Count_ones
PORT(
x : IN std_logic_vector(7 downto 0);
y : OUT std_logic_vector(0 to 3)
);
END COMPONENT;
--Inputs
signal x : std_logic_vector(7 downto 0) := (others => '0');
--Outputs
signal y : std_logic_vector(0 to 3);
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: Count_ones PORT MAP (
x => x,
y => y
);
stim_proc: process
begin
x <= "00010101";
wait for 100 ns;
x <= "00001001";
wait for 100 ns;
x <= "11111111101"
wait for 100ns;
-- insert stimulus here
wait;
end process;
END;
The error is
Entity port x does not match with type std_logic_vector of component port
Entity port y does not match with type std_logic_vector of component port
Please help me, I real cannot figure out the way to solve that.
The answer to your specific question is that the types of the ports in the entity, the ports in the component and the types of the signals must match. Here is a link to your code with those errors and many more corrected.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
USE ieee.std_logic_unsigned.all;
ENTITY Count_ones IS
GENERIC (N: INTEGER := 8); -- number of bits
PORT ( x: IN BIT_VECTOR (N -1 DOWNTO 0); y: OUT NATURAL RANGE 0 TO N);
END ENTITY ;
architecture Behavioral of Count_ones is
TYPE count is Array (N DOWNTO 0) OF Natural;
signal a : count;
begin
a(0) <= 1 when (x(0) = '1')
else
0;
gen: FOR i IN N-1 DOWNTO 0
GENERATE
a(i+1) <= (a(i)+1) when (x(i)='0')
else
a(i);
END GENERATE;
y <= a(N-1);
end Behavioral;
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_unsigned.all;
ENTITY Count_ones_TB IS
END Count_ones_TB;
ARCHITECTURE behavior OF Count_ones_TB IS
COMPONENT Count_ones
GENERIC (N: INTEGER := 8); -- number of bits
PORT ( x: IN BIT_VECTOR (N -1 DOWNTO 0);
y: OUT NATURAL RANGE 0 TO N);
END COMPONENT;
--Inputs
signal x : BIT_VECTOR(7 downto 0) := (others => '0');
--Outputs
signal y : natural;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: Count_ones PORT MAP (
x => x,
y => y
);
stim_proc: process
begin
x <= "00010101";
wait for 100 ns;
x <= "00001001";
wait for 100 ns;
x <= "11111101";
wait for 100ns;
-- insert stimulus here
wait;
end process;
END;
However I must point out that you are a long way from achieving your goal of trying to count the number of ones.
Because of that:
My corrections to your code are not the only correct answer. In
fact, my corrections are not even a good answer. I have simply made
the minimum corrections to make your code compile and run. You need
to think very carefully what type all the ports and signals in your
design should be.
My corrections will not make your code work, i.e. count the number of
ones.

Error for if statement condition in adder/subtractor

I am new to the VHDL language, so please bear with me and please help me out.
I have written code for a addition/subtraction unit which will operate on signed integer but at the "if else" part in the last, the compiler is giving an error.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity adder is
port(A,B : in std_logic_vector(3 downto 0);
SUM : out std_logic_vector(3 downto 0);
mode: in std_logic_vector(0 downto 0));
end adder;
architecture behave of adder is
component xorgate is
port( p,q: in std_logic_vector(3 downto 0);
r: out std_logic_vector(3 downto 0));
end component;
signal a1,b1,sum1,output1,mode1:integer;
signal tmp: std_logic_vector(3 downto 0);
variable output: std_logic_vector(3 downto 0);
begin
u1: xorgate port map (B, mode, output);
output1 <= to_integer(signed (output));
a1 <= to_integer(signed(A));
b1 <= to_integer(signed(B));
mode1 <= to_integer(signed(mode));
process(a1,output1,b1,tmp,mode1)
begin
if ( mode1 <= '1') then
sum1 <= a1 + output1 ;
else
sum1 <= a1 + b1;
end if;
tmp <= std_logic_vector(to_signed(sum1,4));
SUM <= tmp( 3 downto 0);
end process;
end behave;
XST Error Message:
ERROR: HDLCompiler:1731 - "E:\XILINX PROGRAM\FULLADD\FULLADD.vhd" Line 31: found '0' definitions of operator "<=", cannot determine exact overloaded matching definition for "<="
ERROR: HDLCompiler:854 - "E:\XILINX PROGRAM\FULLADD\FULLADD.vhd" Line 11: Unit ignored due to previous errors.
Line 31: if ( mode1 <= '1') then
you meant: if ( mode1 = 1) then
Line 11: This just means that because of the previous error, the compiler 'gave up'.
The <= operator in mode1 <= '1' is less-than-or-equal compare of integer with '1', which have no definition, thus the found '0' definitions of operator "<=". Change '1' to simply the integer literal1`.
Other issues with the code are listed below.
The ´variable output: ...´ must be signal output: when output is used as actual for in port map for xorgate. In typical design you don't have variables in the declaration section, between begin and end, of an architecture.
Length of mode is only 1 std_logic (bit), but actual for mode in xorgate port map, which is q in xorgate, is 4 bits. You probably meant to make mode as 3 downto 0 in the port declaration of adder, since compare like mode1 <= 1 will be trivial true if mode is 1 bit.
The intermediate integer signals named *1 and other signal are actually not required if the process uses signed additions from numeric_std package like:
process(A, B, mode, output) is
begin
if signed(mode) <= 1 then
SUM <= std_logic_vector(signed(A) + signed(output));
else
SUM <= std_logic_vector(signed(A) + signed(B));
end if;
end process;
And this can even be reduced to the below, with only output as intermediate signal:
SUM <= std_logic_vector(signed(A) + signed(output)) when (signed(mode) <= 1)
else std_logic_vector(signed(A) + signed(B));
Finally, if mode is to be treaded like unsigned, then replace with unsigned(mode), since unsigned is also defined in the numeric_std package.
The puzzle is probably why the error message is about failure to find an overloaded operator
'1' has at least two definitions, first as a character literal, then as a bit literal. Neither of these have a <= operator comparing them with type Integer, and that's why the compiler gave up.
If you had used an integer literal 1 instead, the compiler could have found a <= operator easily... so if mode1 <= '1' then would work.
Alternatively, you could write your own <= operator accepting inputs of these two types and returning a boolean :
function "<=" (a : Integer; b : Bit) return Boolean is ...
While it would work, it would also deserve a slap on the wrist!

Booth Multiplication Algorithm

I'm new to VHDL and am trying to code up Booth's Multiplication Algorithm. I'm using XILINX and when I synthesize my code, I end up with a lot of warnings:
Upper is assigned but never used,
Product is used but never assigned,
LowerPrevLSB is assigned but never used,
Lower is assigned but never used,
A_2sComp is assigned but never used,
Z has a constant value of 0,
Product has a constant value of 0.
I thought I assigned and wrote the code correctly, but evidently I am not. Any advice and help would be appreciated.
library IEEE;
use IEEE.NUMERIC_STD.ALL;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_arith.ALL;
use IEEE.STD_LOGIC_unsigned.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
-- X * Y = Z
entity BoothMultiplier is
generic
(
numBits_X : integer := 8;
numBits_Y : integer := 8
);
port
(
CLK : in std_logic;
X : in std_logic_vector((numBits_X - 1) downto 0);
Y : in std_logic_vector((numBits_Y - 1) downto 0);
Z : out std_logic_vector((numBits_X + numBits_Y - 1) downto 0)
);
end BoothMultiplier;
architecture Behavioral of BoothMultiplier is
-- Two's Complement Function
function TwosComplement(inputNum : std_logic_vector) return std_logic_vector;
function TwosComplement(inputNum : std_logic_vector) return std_logic_vector is
variable temp : std_logic_vector(inputNum'range);
begin
temp := (not inputNum) + 1;
return temp;
end TwosComplement;
-- End Two's Complement Function
-- MIN Function
function MIN(Left, Right : integer) return integer;
function MIN(Left, Right : integer) return integer is
begin
if Left < Right then return Left;
else return Right;
end if;
end Min;
-- End MIN Function
-- MAX Function
function MAX(Left, Right : integer) return integer;
function MAX(Left, Right : integer) return integer is
begin
if Left > Right then return Left;
else return Right;
end if;
end MAX;
-- End MAX Function
-- Signals
signal Upper : std_logic_vector(MAX(numBits_X, numBits_Y) - 1 downto 0)
:= (others => '0');
signal Lower : std_logic_vector(MIN(numBits_X, numBits_Y) - 1 downto 0)
:= (others => '0');
signal LowerPrevLSB : std_logic := '0';
signal Product : std_logic_vector(numBits_X + numBits_Y - 1 downto 0)
:= (others => '0');
signal A, A_2sComp : std_logic_vector(MAX(numBits_X, numBits_y) - 1 downto 0)
:= (others => '0');
signal counter : integer := 0;
-- End Signals
begin
assert Z'length = (X'length + Y'length) report "Bad Product Length" severity failure;
Lower <= X when (numBits_X <= numBits_Y) else Y;
A <= X when (numBits_X > numBits_Y) else Y;
A_2sComp <= TwosComplement(A);
process(CLK)
begin
if rising_edge(CLK) then
if (Lower(0) = '0' and LowerPrevLSB = '1') then
Upper <= Upper + A;
elsif (Lower(0) = '1' and LowerPrevLSB = '0') then
Upper <= Upper + A_2sComp;
end if;
LowerPrevLSB <= Lower(0);
Product <= Upper & Lower;
for i in 0 to Product'length - 2 loop
Product(i) <= Product(i+1);
end loop;
Product(Product'length-1) <= Product(Product'length-1);
Upper <= Product(Product'length - 1 downto MIN(numBits_X, numBits_Y));
Lower <= Product(MIN(numBits_X, numBits_Y) - 1 downto 0);
counter <= counter + 1;
if (counter = MIN(numBits_X, numBits_Y)) then
Z <= Product;
end if;
end if;
end process;
end Behavioral;
In VHDL, successive assignments to the same signal in a process overrides previous assignments, thus:
if (Lower(0) = '0' and LowerPrevLSB = '1') then
Upper <= Upper + A;
elsif (Lower(0) = '1' and LowerPrevLSB = '0') then
Upper <= Upper + A_2sComp;
end if;
...
Upper <= Product(Product'length - 1 downto MIN(numBits_X, numBits_Y));
The first assignments, in the if block, is completely ignored. If you look at your code, assignments to Product, Upper and Lower are overridden.
I suggest you simulate your design before synthesizing your design with Xilinx. It will be much easier to test and debug. For instance, your counter signal is never reset, and will count up to 2^31-1, then wrap to -2^31. What will happen to your design in those cases? Simulation would point out these error easily, leave synthesis for later!

Subtractor Module VHDL generating wrong values

I have a code as such below that is designed to do subtraction and addition. Basically, when Binv is set, it should subtract, and Binv is 0, it should add. Unfortunately, it seems to be adding when Binv is set sometimes, and subtracting when it isn't set sometimes. Here is a snapshot of the simulation:
entity ADD_SUB is
Port ( A : in STD_LOGIC_VECTOR (31 downto 0);
B : in STD_LOGIC_VECTOR (31 downto 0);
Binv : in STD_LOGIC;
C_in: in STD_LOGIC;
S : out STD_LOGIC_VECTOR (31 downto 0);
TEST : out STD_LOGIC_VECTOR (31 downto 0);
C_out : out STD_LOGIC
);
end ADD_SUB;
architecture ADD_SUB_ARCH of ADD_SUB is
signal S_wider : std_logic_vector(32 downto 0);
begin
process (A,B,C_in,Binv)
begin
if Binv = '0' then
S_wider <= ( A(31) & A) + ( B(31) & B) + C_in;
elsif Binv = '1' then
S_wider <= (A(31)& A) + ('1'& not B) + '1';
else
S_wider <= std_logic_vector(to_signed(0,32));
end if;
S <= S_wider(31 downto 0);
C_out <= S_wider(32);
end process;
I am getting nonsensical results which make no sense. In the first case, you can see that I tried to do (50 - 30) (Binv is 1). I get 80 which is wrong. You can see however that it works on (30 - 50) where I get -20. Second problem is where I try to do (30 + (-50)), however it shows up as 20.
The results are completely off and I can't see where I am going wrong
Jim is absolutely correct.
There are a couple of points that may be worth making.
First, the + C_in or + not C_in implies two 32 bit adds, one of which gets optimized away during synthesis leaving just the carry in to the remaining add.
Second, you are really only manipulating B and C_in using Binv. Subtraction is the equivalent of adding the two's complement, for B the one's complement + X"00000001. Note that Jim inverts C_in with Binv which allows C_in to be used for daisy chain operations (e.g. a 64 bit add or subtract with a 32 bit ALU).
Both points are illustrated with the following code, which also only uses numeric_std.unsigned and and only needs the unsigned numeric_std."+":
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity add_sub is
port (
a: in std_logic_vector (31 downto 0);
b: in std_logic_vector (31 downto 0);
binv: in std_logic;
c_in: in std_logic;
s: out std_logic_vector (31 downto 0);
test: out std_logic_vector (31 downto 0);
c_out: out std_logic
);
end entity;
architecture foo of add_sub is
begin
UNLABELLED:
process (a,b,c_in,binv)
variable x,y,z: std_logic_vector (33 downto 0);
begin
x := a(31) & a & '1'; -- this '1' generates a true carry in to z(1)
-- z(0) is optimized away as unused it's carry
-- retained as carry in to the next MS bit.
if binv = '0' then
y := b(31) & b & c_in;
elsif binv = '1' then
y := not b(31) & not b & not c_in;
else
y := (others => 'X'); -- 'X' on binv is propagated from b onto y
end if;
z := std_logic_vector( unsigned(x) + unsigned(y)); -- only one add
c_out <= z(33);
s <= z(32 downto 1);
end process;
end architecture;
This above example connects C_in a bit more directly to the adder stage with the LS bits of A and B and gives:
(The image is can be clicked to open)
(Synthesis software is generally smart enough to do all this with using Jim's form modified to either add or subtract based on Binv and A and B extended to 33 bits without any direct bit or bitfield manipulation, our synthesis tools have had more than 25 years to get it right.)
The waveform was produced with the following test bench:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity tb_add_sub is
end entity;
architecture foo of tb_add_sub is
signal a: std_logic_vector (31 downto 0) := (others =>'0');
signal b: std_logic_vector (31 downto 0) := (others =>'0');
signal binv: std_logic := '0';
signal c_in: std_logic := '0';
signal s: std_logic_vector (31 downto 0);
signal test: std_logic_vector (31 downto 0);
signal c_out: std_logic;
begin
DUT:
entity work.add_sub
port map (
a => a,
b => b,
binv => binv,
c_in => c_in,
s => s,
test => test,
c_out => c_out
);
STIMULUS:
process
begin
wait for 100 ns;
a <= std_logic_vector(to_signed(50,a'length));
b <= std_logic_vector(to_signed(30,b'length));
wait for 100 ns;
binv <= '1';
wait for 100 ns;
binv <= '0';
a <= std_logic_vector(to_signed(30,a'length));
b <= std_logic_vector(to_signed(-50,b'length));
wait for 100 ns;
binv <= '1';
b <= std_logic_vector(to_signed(50,b'length));
wait for 600 ns;
wait;
end process;
end architecture;
enter code hereYour equation for subtraction is not correct. Like #neodelphi suggested, it should be:
A - B = A + (not B) + 1
However, this does not account for carry in and what to do with it. If I remember right, the borrow is subtracted:
A - B - C_in = A + (not B) + 1 - C_in = A + (not B) + (1 - C_in)
Now note that:
(1 - C_in) = not C_in
Now, to convert it to VHDL. If I overlook the fact that you are doing signed math with the package, std_logic_unsigned (Ahem), you could write (similar to #neodelphi):
S_wider <= (A(31)& A) + (not B(31) & not B) + not C_in ;
Note in the package std_logic_unsigned as well as numeric_std with VHDL-2008, there are no issues with adding with a std_ulogic.
My suggestion about types and packages is very simple. If you are doing math, use a math type like, signed (matching your math here) or unsigned (for other cases). I consider these part of the documentation.
Furthermore, using the appropriate type is important as the math packages allow you to add two array values that are different sizes. If you use the appropriate type, they do the appropriate extension replicate sign bit for signed or '0' fill for unsigned.
Hence, had you used type signed, then you could have used the first argument (A) to size the result and been lazy about B and written:
S_wider <= (A(31)& A) + not B + not C_in ;
BTW, testing for both '0' and '1' does not help the hardware in any way. My recommendation is to either be lazy (and safe) and write:
if Binv = '0' then
S_wider <= ( A(31) & A) + ( B(31) & B) + C_in;
else
S_wider <= (A(31)& A) + (not B(31) & not B) + not C_in;
end if;
Alternately be paranoid and vigilant and make the output is 'X' when the control input is an 'X'. However be sure to double check your "elsif" expression - get this wrong when it is more complex and it may be challenging to find the bug (meaning you better have test cases that cover all possible input values of the controls):
if Binv = '0' then
S_wider <= ( A(31) & A) + ( B(31) & B) + C_in;
elsif Binv = '1' then
S_wider <= (A(31)& A) + (not B(31) & not B) + not C_in;
else
S_wider <= (others => 'X') ; -- X in propagates as X out can help debug
end if;
An AddSub module has only one control input lets call it \bar{add}/sub. This means, if add_sub is zero perform an add operation, if its one perform a subtraction.
There is a solid relation between C_in and Binv. If you want to add Binv and C_in are zero, if you want to subtract both are one.
The equation for an adder is simply S := A + B + 0 for a subtracter it can be retrieved by some transformations:
S := A - B -- transform into an add operation
S := A + (- B) -- transform negative number using 2's complement
S := A + ( 2's complement of B) -- transform 2's complement into 1's complement
S := A + ((1's complement of B) + 1) -- transform 1's complement into bit wise not operation
S := A + ((bit wise not of B) + 1)
If you combine both equations you will get:
S := A + (B xor vector(add_sub)) + add_sub
So in VHDL this would be:
S_wider <= unsigned('0' & A) + unsigned('0' & (B xor (B'range => add_sub))) + unsigned((B'range => '0') & add_sub);
S <= S_wider(S'range);
C_out <= S_wider(S_width'high);
Synthesis is smart enough to find a 3:1 adder with a switchable constant input 3 to be an addsub-macro block. If you want to perform signed add/sub then exchange the conversion functions and sign-extension accordingly.

"This port will be preserved and left unconnected if it belongs to a top-level block...." in VHDL

I am getting the following warning in Xilinx when I synthesize my code of a 4-bit multiplier:
"This port will be preserved and left unconnected if it belongs to a top-level block or it belongs to a sub-block and the hierarchy of this sub-block is preserved." I dont see any problem in my code that can cause this warning.
The code is as follows:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_bit.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity mult4X4 is
Port ( Clk : in bit;
St : in bit;
Mplier : in unsigned (3 downto 0);
Mcand : in unsigned (3 downto 0);
Result : out unsigned (7 downto 0);
Done : out bit);
end mult4X4;
architecture behave1 of mult4X4 is
signal State : integer range 0 to 9;
signal ACC : unsigned (8 downto 0);
alias M : bit is ACC(0);
begin
process(Clk)
begin
if Clk'event and Clk = '1' then
case State is
when 0 =>
if St = '1' then
ACC(8 downto 4) <= "00000";
ACC(3 downto 0) <= Mplier;
State <= 1;
end if;
when 1 | 3 | 5 | 7 =>
if M = '1' then
ACC(7 downto 4) <= ACC(7 downto 4) + Mcand;
ACC(8 downto 0) <= '0' & ACC(8 downto 1);
State <= State + 1;
else
ACC <= '0' & ACC(8 downto 1);
State <= State + 2;
end if;
when 2 | 4 | 6 | 8 =>
ACC <= '0' & ACC(8 downto 1);
State <= State + 1;
when 9 =>
Done <= '1';
State <= 0;
Result <= ACC(7 downto 0);
end case;
end if;
end process;
--Done <= '1' when State = 9 else '0';
--Result <= ACC(7 downto 0);
end behave1;
Notice that the warning is speaking of a port. I expect the line just above would tell you precisely which port, but it's easy enough to derive.
The port will be left unconnected. That means it must have no effect. The easiest way to have no effect is to be unused. All of the ports are accounted for in the process, so we look for other ways they aren't meaningful. Done looks like a prime candidate; it is set to 1 when the state machine finishes, but there's no reset; this means it goes from undefined to high, and stays. The optimizer could replace that with just a high output. A reasonable place to reset it would be at the start condition.
In general the code has no reset, which may be fine if the state machine can recover from any state, but won't simulate properly. Don't be sure it will reset just because of the range of the State signal; having ten values, it would require 4 bits to store causing 6 invisible states with undefined behaviour; or it could well be encoded to one hot, which if not reset could cause multiple states to appear simultaneously.
Try simulating it.
Without simulating it myself I'd guess you're getting all '0's on Result.
These:
ACC(7 downto 4) <= ACC(7 downto 4) + Mcand;
ACC(8 downto 0) <= '0' & ACC(8 downto 1);
Will result in the Multiplicand's influence being eradicated. There is no time between assignments to ACC. See IEEE Std 1076-1993 8.4.1 Updating a projected output waveform (-2008 10.5.2.2 Executing a simple assignment statement), the paragraph starting "The sequence of transactions is ..." and the following narrative. The first assignment's scheduled transaction for the affected bits of ACC (7 downto 4) are deleted as old transactions. For composite types (and ACC is) it happens on an element by element basis.
And it looks like it will get all '0's because of the second assignment statement.
Also from simply reading your state machine the second of those two ACC assignments should simply be deleted in States 1 | 3 | 5 | 7?
Addendum
After Yann Verneir pointed out another error with Done never being assigned '0' I figured I'd demonstrate the effects of the two assignment statements to ACC in States 1 | 3 | 5 | 7.
A simple testbench:
library ieee;
use ieee.numeric_bit.all;
entity mult4x4_tb is
end entity;
architecture foo of mult4x4_tb is
signal clk: bit;
signal start: bit;
signal multiplier: unsigned (3 downto 0) := X"2";
signal multiplicand: unsigned (3 downto 0) := X"4";
signal result: unsigned (7 downto 0);
signal done: bit;
begin
DUT:
entity work. mult4x4
port map (
Clk => clk,
St => start,
Mplier => multiplier,
Mcand => multiplicand,
Result => result,
Done => done
);
CLOCK:
process
begin
wait for 10 ns;
clk <= not clk;
if Now > 300 ns then
wait;
end if;
end process;
STIM:
process
begin
wait for 29 ns;
start <= '1';
wait for 20 ns;
start <= '0';
wait;
end process;
end architecture;
gives:
You can see that when using package numeric_bit instead of packages std_logic_1164 and numeric_std we never see anything but all '0's on Result.
Yann's assignment to '1' only on Done can be cured by:
case State is
when 0 =>
if St = '1' then
ACC(8 downto 4) <= "00000";
ACC(3 downto 0) <= Mplier;
State <= 1;
Done <= '0';
end if;
Removing the second signal assignment to ACC in the sequential statements for cases 1 | 3 | 5 | 7 gives an answer that look's right for 2 x 4:

Resources