Firstly you haven't actually given us a clue what signal or entity the type mismatch applies to, so this will be a scatter-gun answer to problems with your code. But there IS one likely candidate, so bear with me...
For more information, there are a lot of bad sources out there, and some good ones. One of the best is Peter Ashenden's "Designer's Guide to VHDL".
Second, I'm curious where you "got" this USE list: please comment and let me know
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_arith.ALL;
USE ieee.std_logic_unsigned.ALL;
USE ieee.numeric_std.all;
There are a LOT of sources teaching this style or using it in example code, and I'd like to know which sources to steer beginners away from...
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.all;
is all you want or need; the other libraries are non-standard, (forced into VHDL by a large company in their commercial interest, and going against the VHDL philosophy). They introduce multiple definitions of different types with the same names as ieee.numeric_std.signed
and unsigned
which help create confusion.
A quick tutorial in using the numeric_std type system:
- Use std_logic_vector
where the value you are handling is untyped : e.g. a word that could be signed, unsigned, an instruction, a float or whatever else from context
- Use signed
where the value is a signed integer
- Use unsigned
where the value is an usigned integer
Correct choice of declarations will reduce the number of conversions between these types.
Third, ALL your STD_LOGIC_VECTOR
ports and signals are unconstrained. There are places where unconstrained vectors are appropriate, but ... this is broken.
VHDL is strongly typed and does not infer types, but it gives you tools for limited forms of type introspection. Using this is easy and safe (because the compiler catches most errors!) but often considered fairly advanced because it can be frustrating to a beginner.
So
Signal A_BUS : std_logic_vector(31 downto 0);
Signal B_BUS : std_logic_vector(7 downto 0);
declare two different types of signal : both std_logic_vector
but 32 and 8 bits respectively. Now given a component with ports
PORT(
a : IN STD_LOGIC_VECTOR;
b : IN STD_LOGIC_VECTOR );
it can be connected as
PORT MAP(
a => a_bus,
b => b_bus );
... see the problem? a and b are incompatible because they have different lengths. You can maybe get away with this in Python where dynamic typing can try to clean up the mess at runtime or maybe in C where type mismatches silently cause overflows to crash something else much later. But not in VHDL where you're designing hardware, and you actually want it to work.
The simplest (beginner) solution is to explicitly declare all your signal and port lengths
PORT(
a : IN STD_LOGIC_VECTOR(31 downto 0);
b : IN STD_LOGIC_VECTOR(31 downto 0));
and now the compiler will catch the error in the port map.
The downside of this is that it stops you using the same module in a polymorphic manner, e.g. in 8-bit, 16-bit and 32-bit CPUs. Often that doesn't matter, but where it does, more advanced techniques come in...
Look at one of your internal signal declarations :
signal muxOneOut : STD_LOGIC_VECTOR;
Imagine you want muxOneOut
to have the same range as port A... You can do this by declaring:
signal muxOneOut : STD_LOGIC_VECTOR(A'range);
It now adjusts itself to whatever signal is externally connected to port A. If the mux selects ports A or B onto this signal, this works - assuming ports A and B are the same width. So let's check that assumption:
assert A'length = B'length report "Port width mismatch" severity FAILURE;
Now building the design will fail if the external signals are incorrectly sized. And so on...
But we still haven't got to the likely culprit for your type mismatch. And it is this:
COMPONENT TwoToOneMux
PORT(
bIn : IN STD_LOGIC_VECTOR;
bInvertedIn : IN STD_LOGIC_VECTOR;
sel : IN STD_LOGIC_VECTOR;
muxOut : OUT STD_LOGIC_VECTOR);
END COMPONENT;
...
M2: TwoToOneMux port map(a, b, op(0), muxTwoOut);
(ditto M1). And it turns out that you ARE using more than one type : you are using both std_logic_vector
, and std_logic
.
"sel" is clearly a one bit signal, and the clearest way to express it is std_logic
. However a one-bit std_logic_vector
(as you are using here) is perfectly legal, just confusing as hell (though std_logic_vector
makes more sense if you also use the same style for e.g. 4:1 and 8:1 muxes).
All you need to do to extract a 1-bit std_logic_vector
version is to use the correct syntax : op(0 downto 0)
extracts a vector which starts and ends at the same element, instead of op(0)
which extracts a std_logic.