문제

I'm designing a 1 bit ALU and using a structural approach. For some reason I keep getting a type mismatch error even though I'm only using std_logic_vectors for everything. I don't see what could be wrong?

Here's the code: 1 bit ALU:

LIBRARY ieee; 
USE ieee.std_logic_1164.ALL; 
USE ieee.std_logic_arith.ALL; 
USE ieee.std_logic_unsigned.ALL;
USE ieee.numeric_std.all;

ENTITY alu1 is

PORT(
    a        : IN STD_LOGIC_VECTOR; 
    b        : IN STD_LOGIC_VECTOR; 
    op       : IN STD_LOGIC_VECTOR(2 DOWNTO 0); 
    result   : OUT STD_LOGIC_VECTOR; 
    cout     : OUT STD_LOGIC; 
    zero     : OUT STD_LOGIC); 
END alu1;

ARCHITECTURE structure OF alu1 IS 

    COMPONENT FourToOneMux 
    PORT(
        andIn   : IN STD_LOGIC_VECTOR;
        orIn    : IN STD_LOGIC_VECTOR;
        addIn   : IN STD_LOGIC_VECTOR;
        bMuxIn  : IN STD_LOGIC_VECTOR;
        sel     : IN STD_LOGIC_VECTOR;
        muxOut  : OUT STD_LOGIC_VECTOR);
    END COMPONENT;

    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;

    COMPONENT FullAdder
    PORT(
        a       :IN STD_LOGIC_VECTOR;
        b       :IN STD_LOGIC_VECTOR;
        cin     :IN STD_LOGIC_VECTOR;
        cout    :OUT STD_LOGIC_VECTOR;
        output  :OUT STD_LOGIC_VECTOR);
    END COMPONENT;

    signal muxOneOut, muxTwoOut, andOut, orOut, addOut, FMuxOut, carryOut : STD_LOGIC_VECTOR := (others => '0');

BEGIN

    M1: TwoToOneMux port map(b, NOT b, op(0), muxOneOut);
    M2: TwoToOneMux port map(a, b, op(0), muxTwoOut);
    andOut <= a AND muxOneOut;
    orOut <= a OR muxOneOut;
    A1: FullAdder port map(a, muxOneOut, cout, carryOut, addOut);
    F1: FourToOneMux port map(andOut, orOut, addOut, muxTwoOut, op(1) & op(2), result); 

END structure;

And the TwoToOneMux code:

LIBRARY ieee; 
USE ieee.std_logic_1164.ALL; 
USE ieee.std_logic_arith.ALL; 
USE ieee.std_logic_unsigned.ALL;
USE ieee.numeric_std.all;

ENTITY TwoToOneMux is

PORT(
    in1     : IN STD_LOGIC_VECTOR;
    in2     : IN STD_LOGIC_VECTOR;
    sel     : IN STD_LOGIC_VECTOR;
    output  : OUT STD_LOGIC_VECTOR);
END TwoToOneMux;

ARCHITECTURE behavioral OF TwoToOneMux IS BEGIN

    WITH sel select
        output <= in1 when "0",
                  in2 when "1",
                  null when others;

END behavioral;

I'm a newcomer to VHDL and I'm feeling way over my head so any help is appreciated.

도움이 되었습니까?

해결책

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.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top