std_logic_vector to integer conversion vhdl - vhdl

I faced with conversion problem/I read a lot of similar topics but my code still not working.Could you pls give me some hints. Quartus give me error:
Error (10476): VHDL error at true_dual_port_ram_single_clock.vhd(44): type of identifier "random_num_i" does not agree with its usage as "std_logic_vector" type
LIBRARY ieee;
USE ieee.std_logic_1164.all;
use IEEE.std_logic_signed.all;
use IEEE.std_logic_unsigned.all;
use IEEE.NUMERIC_STD.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
entity write_ram is
generic(width : integer := 32);
port(clock_i : IN STD_LOGIC;
we_w : IN STD_LOGIC;
wr_addr : IN INTEGER RANGE 0 to 31;
read_add : IN INTEGER RANGE 0 to 31;
q_out : out STD_LOGIC_VECTOR(2 DOWNTO 0)
);
end write_ram;
architecture rtl of write_ram is
--- Component decalarartion
component random is
port(clk : in std_logic;
random_num : out std_logic_vector(width - 1 downto 0) --output vector
);
end component;
component single_clock_ram is
port(clock : IN STD_LOGIC;
data : IN INTEGER RANGE 0 to 31;
write_address : IN INTEGER RANGE 0 to 31;
read_address : IN INTEGER RANGE 0 to 31;
we : IN STD_LOGIC;
q : OUT STD_LOGIC_VECTOR(2 DOWNTO 0)
);
end component;
for all : random use entity work.random(rtl);
for all : single_clock_ram use entity work.single_clock_ram(rtl);
Signal random_num_i : INTEGER RANGE 0 to 31; --interanal signals
begin
-- Component Instantiation
C1 : random Port map(
clk => clock_i,
--random_num <=to_integer(to_signed(random_num_i))
random_num => random_num_i
);
random_num <= to_integer(to_signed(random_num_i)); -- error
C2 : single_clock_ram
Port map(
clock => clock_i,
we => we_w,
read_address => read_add,
write_address => wr_addr,
data => random_num_i,
q => q_out
);
end rtl;

Your question isn't an MCVE with the configuration specifications for random and single_clock_ram present. You didn't supply the entity declarations and architecture bodies (rtl) for them.
With them commented out this analyzes:
library ieee;
use ieee.std_logic_1164.all;
-- use ieee.std_logic_signed.all; -- NOT USED
-- use ieee.std_logic_unsigned.all; -- NOT USED
use ieee.numeric_std.all;
-- use ieee.std_logic_arith.all; -- NOT USED
entity write_ram is
generic (width: integer := 32);
port (clock_i: in std_logic;
we_w: in std_logic;
wr_addr: in integer range 0 to 31;
read_add: in integer range 0 to 31;
q_out: out std_logic_vector(2 downto 0)
);
end entity write_ram;
architecture rtl of write_ram is
--- component declaration
component random is
port (clk: in std_logic;
random_num: out std_logic_vector(width - 1 downto 0) --output vector
);
end component;
component single_clock_ram is
port (clock: in std_logic;
data: in integer range 0 to 31;
write_address: in integer range 0 to 31;
read_address: in integer range 0 to 31;
we: in std_logic;
q: out std_logic_vector(2 downto 0)
);
end component;
-- for all: random use entity work.random(rtl);
-- for all: single_clock_ram use entity work.single_clock_ram(rtl);
signal random_num_i: integer range 0 to 31; -- internal signals
signal random_num: std_logic_vector(width - 1 downto 0); -- added
begin
-- component instantiation
c1: random port map (
clk => clock_i,
-- random_num <=to_integer(to_signed(random_num_i))
-- random_num => random_num_i -- DELETED
random_num => random_num -- ADDED
);
-- random_num <= to_integer(to_signed(random_num_i)); -- error DELETED
random_num_i <= to_integer(signed(random_num)); -- ADDED
c2: single_clock_ram
port map (
clock => clock_i,
we => we_w,
read_address => read_add,
write_address => wr_addr,
data => random_num_i,
q => q_out
);
end architecture rtl;
Note there's been a random_num std_logic_vector declared to hook up to the output of random, which is converted an integer random_num_i used as an input to single_clock_ram data. The output q from the single_clock_ram looks a bit suspicious, should that be an integer or a wider std_logic_vector?

First, delete the non-standard libraries.
use IEEE.std_logic_signed.all;
use IEEE.std_logic_unsigned.all;
use IEEE.STD_LOGIC_ARITH.ALL;
leaving only std_logic_1164 and numeric_std.
The others introduce a bunch of overlapping declarations which make it difficult to determine what is going on - and if there are several declarations for the same operator with the same argument and result types, the compiler makes them all invisible rather than picking an arbitrary one.
Then, decide what you are trying to do. This is currently ambiguous and contradictory.
(1)You have a generic (width : integer :=32); and a port declaration
random_num : out std_logic_vector (width-1 downto 0)
which suggest you are dealing with 32 bit words.
(2) You have a ranged integer : Signal random_num_i: INTEGER RANGE 0 to 31; which (a) should be a ranged NATURAL to make it even clearer that negative values are errors, and (b) suggests you are dealing with 5 bit words.
Which is it? What exactly are you trying to do?
And here, you are apparently trying to connect them together in a port map...
C1: random Port map (
clk => clock_i,
--random_num <=to_integer(to_signed(random_num_i))
random_num =>random_num_i
);
random_num <=to_integer(to_signed(random_num_i)); -- error
There are a number of things wrong here.
1) A simple port mapping like random_num =>random_num_i requires that both sides have the same type. This would work if both sides actually WERE the same type : for example, if you added a signal declaration
random_num_slv : std_logic_vector (width-1 downto 0);
then the port mapping random_num =>random_num_slv would work. Now you can convert to the required type random_num_i in a signal assignment.
random_num_i <= to_integer (unsigned(random_num_slv));
There are still problems with this : a 32-bit output is likely to overflow a 5-bit integer.
While adding an intermediate signal random_num_slv may look inefficient and redundant, it keeps the design clean and simple, which matters when dealing with tools that don't understand type conversions in ports.
Make sure you know how to use intermediate signals even if there's a cleaner approach. It can save you when all else fails.
(2) The commented out port mapping
random_num <=to_integer(to_signed(random_num_i))
would be the way to do it, except for three things ...
(a) <= is a signal assignment, you need => a n association operator
(b) you're converting an integer to an integer, and driving a std_logic_vector with it. That really won't work...
(c) the component port is an OUTPUT so you shouldn't be driving it in the first place.
What you probably meant was
to_integer(unsigned(random_num)) => random_num_i
and this would be the cleanest way to do it if your tools support conversions in port maps properly.
Notes:
again it has the overflow problem, a 32-bit vector won't fit a 5 bit integer.
You can convert from std_logic_vector to either signed or unsigned by casting unsigned rather than a conversion function to_signed as they are closely related types. Integers are not "closely related" to these, so need a conversion function to_integer.
As negative numbers aren't permitted by the declaration of random_num_i, use unsigned rather than signed.
(3) The existing signal assignment
random_num <=to_integer(to_signed(random_num_i)); -- error
again contains several errors. The biggest is that there is no random_num port visible outside the component declaration. Simply delete this line, you need to use one of the port mappings.
Further considerations:
(1) Some type conversions are inevitable. But if you are doing too many, that generally points to a design error, like the use of std_logic_vector everywhere, even for thengs like addresses which are inevitably unsigned integers so either unsigned ornatural would be a better choice. Keep the design as simple and readable as possible. I think your use of integer here is generally good but natural would be better (unless you need negative addresses!)
(2) If you're adding the flexibility of a generic like width, use it correctly and consistently - OR - check it's valid.
Here, as described above, your design ONLY works correctly without surprises IF this entity is instantiated with width => 5.
So, check the value and abort if this precondition is not met.
assert Width = 5 report "Width of " & natural'image(width) & " not supported!"
severity FAILURE;
OR make the design work for all reasonable values of the generic, for example by making other quantities dependent on it in valid ways. For example:
constant DEPTH : natural := 2**WIDTH - 1;
signal random_num_i : natural range 0 to DEPTH;
and so on...

Related

VHDL: big slv array slicing indexed by integer (big mux)

I want to slice a std_logic_vector in VHDL obtaining parts of it of fixed dimensions.
The general problem is:
din N*M bits
dout M bits
sel clog2(N) bits
Expected behaviour in an example (pseudocode): input 16 bit, want to slice it in 4 subvectors of 4bit each.
signal in: std_logic_vector(N*M-1 downto 0);
signal sel: integer;
-- with sel = 0
output <= in(N-1:0);
--with sel = 1 output <= in(2N-1:N)
-- with sel = 2
output <= in(3N-1:2N)
.....
--with sel = M-1
output <= in(M*N-1:(M-1)N)
I know a couples of way to do this, but I don't know which one is the best practice and give the best results in synthesis.
the entity
din: in std_logic_vector(15 downto 0);
dout: out std_logic_vector(3 downto 0);
sel: in std_logic_vecotor(1 downto 0)
CASE STATEMENT
case sel is
when "00" => dout <= din(3:0);
when "01" => dout <= din(7:4);
when "10" => dout <= din(11:8);
when "11" => dout <= din(15:12);
when others => ....`
It clearly implement a mux, but it's not generic at all and If the input gets big it's really hard to write and to codecover.
INTEGER INDEXING
sel_int <= to_integer(unsigned(sel));
dout <= din(4*(sel_int+1) - 1 downto 4*sel_int);
Extremely easy to write and to mantain, BUT it can have problems when the input is not a power of 2. For example, if I want to slice a 24bit vector in chunks of 4, what happen when the integer conversion of sel brings to the index 7?
A STRANGE TRADEOFF
sel_int <= to_integer(unsigned(sel));
for i in 0 to 4 generate
din_slice(i) <= din(4*(i+1)-1 downto 4*i);
end generate dout <= din_slice(sel_int);
I'm searching a solution that is general enough to be used with various input/output relationships and safe enough to be synthesized consistently everytime.
The Case statement is the only one with the Others case (that feels really safe), the other solutions rely on the slv to integer conversion and indexing that feels really comfortable but not so reliable.
Which solution would you use?
practical usecase
I have a 250bit std_logic_vector and I need to select 10 contigous bits inside of it starting from a certain point from 0 to 239. How can I do that in a way that is good for synthesis?
There is another option that is accepted by tools that allow VHDL 2008 (which includes Vivado and Prime Pro). You can use an unconstrained 2d type from a package:
type slv_array_t is array(natural range <>) of std_logic_vector; --vhdl 2008 unconstrained array type
then you can simply select which port you want. And it is as generic as you like.
library ieee;
use ieee.std_logic_1164.all;
use work.my_pkg.all;
entity mux is
generic (
N : natural;
M : natural
);
port (
sel : in natural;
ip : in slv_array_t (N-1 downto 0)(M-1 downto 0);
op : out std_logic_vector (M-1 downto 0);
);
end entity;
architecture rtl of mux is
begin
op <= ip(sel);
end architecture;
First you must extend the incoming data to be sure to have always as much bits as you need for connecting all multiplexer inputs (see the code below, process p_extend).
This will not create any logic at synthesis.
Second you must convert the resulting vector into an array, which you can access later by an index (see the code below, process p_create_array).
Again this will not create any logic at synthesis.
At last you must access this array by the select input signal (see the code below, process p_mux).
library ieee;
use ieee.std_logic_1164.all;
entity mux is
generic (
g_data_width : natural := 250;
g_slice_width : natural := 10;
g_sel_width : natural := 5;
g_start_point : natural := 27
);
port (
d_i : in std_logic_vector(g_data_width-1 downto 0);
sel_i : in std_logic_vector(g_sel_width-1 downto 0);
d_o : out std_logic_vector(g_slice_width-1 downto 0)
);
end entity mux;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
architecture struct of mux is
signal data : std_logic_vector(g_slice_width * 2**g_sel_width-1 downto 0);
type t_std_logic_slice_array is array (natural range <>) of std_logic_vector(g_slice_width-1 downto 0);
signal mux_in : t_std_logic_slice_array (2**g_sel_width-1 downto 0);
begin
p_extend: process(d_i)
begin
for i in 0 to g_slice_width * 2**g_sel_width-1 loop
if i+g_start_point<g_data_width then
data(i) <= d_i(i+g_start_point);
else
data(i) <= '0';
end if;
end loop;
end process;
p_create_array: process (data)
begin
for i in 0 to 2**g_sel_width-1 loop
mux_in(i) <= data((i+1)*g_slice_width-1 downto i*g_slice_width);
end loop;
end process;
p_mux: d_o <= mux_in(to_integer(unsigned(sel_i)));
end architecture;

VHDL - test bench - generics

I've been working on making a decoder that I can use in multiple instances by just changing a generic value for the size of the input/output vector. The decoder will 'sll' a single bit, a number of positions based on the integer conversion of the input. The decoder itself works fine. The problem arrises when I make a test bench and compile. Resulting in:
Error (10482): VHDL error at DECODER.vhd(41): object "n" is used but not declared
I've added the model and test bench below:
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;
ENTITY DECODER IS
--GENERIC (delay : delay_length := 0 ns);
GENERIC (n : POSITIVE := 2);
PORT (a : IN std_logic_vector(n-1 DOWNTO 0);
x : OUT std_logic_vector(2**n-1 DOWNTO 0));
END ENTITY DECODER;
ARCHITECTURE dflow OF DECODER IS
CONSTANT x_out : BIT_VECTOR (2**n-1 DOWNTO 0) :=
( 0 => '1', OTHERS => '0');
BEGIN
x <= to_stdlogicvector(x_out sll to_integer(unsigned(a)));
END ARCHITECTURE dflow;
--test bench----------------------------------------
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;
ENTITY TN2 IS
END ENTITY TN2;
ARCHITECTURE IO_TN2 OF TN2 IS
COMPONENT DECODER IS
--GENERIC (delay : delay_length := 0 ns);
GENERIC (n : POSITIVE := 2);
PORT (a : IN std_logic_vector(n-1 DOWNTO 0);
x : OUT std_logic_vector(2**n-1 DOWNTO 0));
END COMPONENT DECODER;
SIGNAL a : std_logic_vector (n-1 DOWNTO 0); --<-- USED BUT NOT DECLARED
SIGNAL x : std_logic_vector (2**n-1 DOWNTO 0);
BEGIN
G1 : DECODER
GENERIC MAP (n => 2)
PORT MAP (a,x);
a <= "00", "01" AFTER 1 NS, "10" AFTER 2 NS, "11" AFTER 3 NS,
"00" AFTER 4 NS, "0Z" AFTER 5 NS;
END ARCHITECTURE IO_TN2;
CONFIGURATION CFG_DECODER OF TN2 IS
FOR IO_TN2
FOR G1 : DECODER
USE ENTITY work.DECODER(dflow)
GENERIC MAP (n => 2)
PORT MAP (a,x);
END FOR;
END FOR;
END CONFIGURATION CFG_DECODER;
The compiler is telling me that I have not declared n, which I thought I did in the component declaration. Where should I declare it?
A second question is how can I declare multiple generics i.e
1 generic for delay_length
1 generic for n
I tried putting 2 generic statements inside the model entity but the compiler did not think that was the right thing to do.
As always many thanks for the help.
D
Your component declaration is stating that there is a component called decoder, which (along with other properties of this component) has a generic called n, with a default value of 2. At this point in analysis of the file, you have said nothing about the actual value you want to assign to n.
My approach would be to define a constant, prior to declaring the component:
constant DECODER_WIDTH : integer := 2;
You then use this to declare your signal:
SIGNAL a : std_logic_vector (DECODER_WIDTH-1 downto 0);
when you instantiate your decoder, you then also bind the n generic to this constant:
G1 : DECODER
GENERIC MAP (n => DECODER_WIDTH)
PORT MAP (a,x);
If you really need to have the configuration change the value of n, you will have to declare the DECODER_WIDTH constant inside a package, which this file would then use, both before the TN2 entity declaration, and before the configuration statement. If you don't need the configuration to alter the decoder size, then you can just omit the generic map from the configuration statement.
Thanks for the comments I've updated the code below with the amendments you suggested and it works well
--test bench for 2/4 decoder----------------------------------------
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;
ENTITY TN2 IS
END ENTITY TN2;
ARCHITECTURE IO_TN2 OF TN2 IS
COMPONENT DECODER IS
--GENERIC (delay : delay_length := 0 ns);
GENERIC (n : POSITIVE := 2);
PORT (a : IN std_logic_vector(n-1 DOWNTO 0);
x : OUT std_logic_vector(2**n-1 DOWNTO 0));
END COMPONENT DECODER;
CONSTANT DECODER_WIDTH : integer := 2; ---<-- ADDED constant changing this value will alter decoder vector size
SIGNAL a : std_logic_vector (DECODER_WIDTH-1 downto 0); --< changed n to decoder_width
SIGNAL x : std_logic_vector (2**DECODER_WIDTH-1 DOWNTO 0); --< changed n to decoder_width
BEGIN
G1 : DECODER
GENERIC MAP (n => DECODER_WIDTH) --< pass decoder_width to n
PORT MAP (a,x);
a <= "00", "01" AFTER 1 NS, "10" AFTER 2 NS, "11" AFTER 3 NS,
"00" AFTER 4 NS, "0Z" AFTER 5 NS;
END ARCHITECTURE IO_TN2;
CONFIGURATION CFG_DECODER OF TN2 IS
FOR IO_TN2
FOR G1 : DECODER
USE ENTITY work.DECODER(dflow)
GENERIC MAP (n => decoder_width)
PORT MAP (a,x);
END FOR;
END FOR;
END CONFIGURATION CFG_DECODER;

2's compliment input and using vhdl library for signed input

My input data is 2's compliment and I designed the input is signed number and the all of operation is used signed number,the library i used ieee.numeric_std.all, but when i do ‘+’ an error occurred "found '0' definitions of operator "+", cannot determine exact overloaded matching definition for "+"". So I changed another to another library ieee.std_logic_arith.all ans make the add operation as a component, it works.
when i simulate my code by using testbench, error occurred: Entity port xin does not match with type signed of component port.
I think this error is about my library.
can anyone help me ?
new
i do not use adder as a component and the below code works
adder: process(clk)
begin
if (clk'event and clk = '1')then
if enable1='1' then
add1 <= (x0(7)&x0) + (x15(8)&x15);
add2 <= (x1(7)&x1) + (x14(8)&x14);
add3 <= (x2(7)&x2) + (x13(8)&x13);
add4 <= (x3(7)&x3) + (x12(8)&x12);
add5 <= (x4(7)&x4) + (x11(8)&x11);
add6 <= (x5(7)&x5) + (x10(8)&x10);
add7 <= (x6(7)&x6) + (x9(8)&x9);
add8 <= (x7(7)&x7) + (x8(8)&x8);
end if;
end if;
end process adder;
and the library of my testbench use use ieee.numeric_std.all;
USE ieee.std_logic_1164.ALL;
use ieee.numeric_std.all;
use ieee.std_logic_textio.all;
use std.textio.all;
ENTITY tb_signedinput IS
END tb_signedinput;
ARCHITECTURE behavior OF tb_signedinput IS
-- Component Declaration
COMPONENT signedinput is
port( Clk : in std_logic;
reset : in std_logic;
enable1 : in std_logic;
Xin : in signed(7 downto 0);
Yout : out signed(19 downto 0)
);
END COMPONENT;
--Inputs
signal Clk : std_logic := '0';
signal reset : std_logic := '0';
signal Xin : signed(7 downto 0) := (others => '0');
signal enable1 : std_logic := '0';
--Outputs
signal Yout : signed(19 downto 0);
-- Array
constant MEMSIZE: integer :=99;
type testarray is array (MEMSIZE downto 0) of signed(7 DOWNTO 0);
signal testvectors: testarray;
shared variable vectornum,outnum: integer;
-- Clock period definitions
constant Clk_period : time := 10 ns;
BEGIN
-- Component Instantiation
uut: signedinput PORT MAP( Clk => Clk,
reset => reset,
Xin => Xin,
enable1 =>enable1,
Yout => Yout );
the error still occur:
Entity port xin does not match with type std_logic_vector of component port
Entity port yout does not match with type std_logic_vector of component port
therefore, I changed my adder again to
add1 <= resize(x0,9) + x15;
syntax good but same error in testbench..
Is error about my ISE type or library type?
Thank you!
Your addition expression in adder1 is invalid because you're trying to index element "8" when the range of a1 and a2 is 7 downto 0.
Assuming thet you're trying to sign extend it would look something more like this:
q <=(a1(7)&a1 + a2(7)&a2);
The "+" operator has higher precedence than "&" so you are trying to add a1 + a2(7) which is signed + std_logic. This doesn't have an overload defined in numeric_std in addition to being logically wrong.
This works:
q <=(a1(7)&a1) + (a2(7)&a2);
But it isn't the canonical way to implement sign extension when using numeric_std. You only need the left side term to have the same size as q. The signed "+" operator will take care of sign extending its right hand side automatically.
q <= resize(a1, q'length) + a2; -- Sign extend a1 and add
This gives cleaner code that says what it's doing without relying on the non-standard std_logic_arith.
The actual error about the type mismatch on xin isn't apparent from your code. It is possible that you have an older version of signedinput compiled with a different type on its port and haven't updated the library.
Kevin made it look tough, so I figured I'd show something that makes for a good explanation:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity adder1 is
port (
a1: in signed (7 downto 0);
a2: in signed (7 downto 0);
clk: in std_logic;
enable1: in std_logic;
q: out signed (8 downto 0)
);
end entity;
architecture behavioral of adder1 is
begin
UNLABELLED:
process(clk)
begin
if clk'event and clk ='1' then
if enable1 = '1' then
q <= a1(7) & a1 + a2 ;
end if;
end if;
end process;
end architecture;
The assignment to q looks naked so it's worth explaining.
The "+" in numeric_std for signed will sign extend the shorter operand to match the length of the longer operand.
The rest is priority magic.
"+" and "&" are the same priority, which means they're evaluated in left to right textual order, meaning the sign extension with the concatenation operator is performed first (see IEEE Std 1076-2008, 9.2 Operators).
The "+" operator sees the left operand as longer and matches the right operand to it's length, (see package numeric_std "+" for L,R: signed). It does this by using signed RESIZE on both operands after finding the MAX of the length of both, along with converting metavalues to 'X's.
It works if the right operand is longer too:
q <= a1 + (a2(7) & a2) ;
And here we need parentheses to associate the result of the concatenation operator as the right operand of the adding operator, because the two operators are the same priority and would otherwise be encountered in textual order.
There's no reason to call resize yet again, it's only a one bit sign extension by concatenation, based on knowing the sign is embodied in the left hand element (bit) of a two's compliment number.
The term canonical is not found in the VHDL standard.
As far as Xin, I'd agree with Kevin, something likely needs to be reanalyzed so that both references to signed are found in the same package.
Each declaration used in a design is unique. If say the actual in the port map depends on the type signed declaration in package std_logic_arith and the formal were to depend on the declaration of signed in package numeric_std they would be of different types.

Cannot resolve slice name as type std.standard.integer

following code is a simple instruction Memory in Mips CPU
LIBRARY ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
ENTITY instructionMemory IS
generic (delay :time :=10 ns);
PORT( a : INOUT STD_LOGIC_VECTOR ( 31 downto 0);
output: OUT STD_LOGIC_VECTOR( 31 downto 0)
);
END ENTITY;
ARCHITECTURE instructionMemory OF instructionMemory IS
type MemMatrix is array ( 0 to 7 ) of std_logic_vector(31 downto 0); -- instruction from memory
signal Mem:MemMatrix := (x"00000000",x"00000001",x"00000000",x"00000001",x"00000001",x"00000001",x"00000001",x"00000001");
BEGIN
output <= Mem(conv_integer(a(6 downto 2)));
END instructionMemory;
I assume Mem is Memory and initilized it with some value. I wanna read this data and assign it to output.
But it's gives me following error :
no feasible entries for subprogram conv_integer
I change error line to this :
Mem(a(6 downto 2));
But again it gives me another error:
cannot resolve slice name to type std.standard.integer
I have no idea how to solve this, Can any body help me ?
The following analyzes and elaborates:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity instructionmemory is
generic (delay :time :=10 ns);
port( a : inout std_logic_vector ( 31 downto 0);
output: out std_logic_vector( 31 downto 0)
);
end entity;
architecture instructionmemory of instructionmemory is
type memmatrix is array ( 0 to 7 ) of std_logic_vector(31 downto 0); -- instruction from memory
signal mem:memmatrix := (
x"00000000",x"00000001",x"00000000",x"00000001",
x"00000001",x"00000001",x"00000001",x"00000001"
);
begin
output <= mem(conv_integer(a(6 downto 2))); -- closing paren for mem();
end instructionmemory;
What's different about it is the addition of a matching closing paren in the concurrent signal assignment statement targeting output.
ghdl actually pointed to the character location of the problem with a less than helpful message.
instructionMemory.vhdl:20:47: ',' is expected instead of ';'
The assumption being without a closing paren an additional argument is expected. Your error message(s) likely indicates a YACC/Bison based parser without the ability to provide error messages on non-terminals.
Addendum
If you were to note Russell's comment there is an integer range mismatch between the conversion of 6 downto 0 and memmatrix (0 to 7). The conversion has a binary range of 2**5 while mem has a range of 0 to 7. Should a(6 downto 2) every be out of range 0 to 7 a run time error will occur. Use of an integer type would allow to modify or otherwise handle an a field out of range by checking the integer value against the bound of mem.
You could also increase memmatrix size to accomidate the full range of a(6 downto 2).
Your additional question on how to assign a different index to mem for assigning output requires a bit more context. Where do you want want to get the index from?

Type mismatch error in VHDL?

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.

Resources