dpaul
Advanced Member level 5
VHDL error: Cannot determine exact overloaded matching definition for "&"
Hi all,
I am trying to simulate a "True DP Asym RAM Write First". I have adapted the code from UG901 v2017.1, page 141.
I have used use IEEE.NUMERIC_STD.ALL instead of use ieee.std_logic_unsigned.all and use ieee.std_logic_arith.all.
Here is the VHDL code. The commented out parts are the Xilinx code lines.
The error shown:
In my opinion at line 132, addrB and i are both std_logic_vector. Same is for line 137. So why am I seeing this?
Does it have something to do with my change of libraries or am I making some silly mistake somewhere?
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
PortA is my write port and PortB is my read port for initial analysis. The TB should write writes 32 bits data at a time via PortA
PortA size (32 bits) < PortB size (1280 bits).
At portB, I only want to read out the written data 1280 bits at a time.
Hi all,
I am trying to simulate a "True DP Asym RAM Write First". I have adapted the code from UG901 v2017.1, page 141.
I have used use IEEE.NUMERIC_STD.ALL instead of use ieee.std_logic_unsigned.all and use ieee.std_logic_arith.all.
Here is the VHDL code. The commented out parts are the Xilinx code lines.
Code:
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;
-- use ieee.std_logic_unsigned.all;
-- use ieee.std_logic_arith.all;
library unisim;
use unisim.vcomponents.all;
entity asym_ram_tdp is
generic (
WIDTHA : integer := 4;
SIZEA : integer := 1024;
ADDRWIDTHA : integer := 10;
WIDTHB : integer := 16;
SIZEB : integer := 256;
ADDRWIDTHB : integer := 8
);
port (
clkA : in std_logic;
clkB : in std_logic;
enA : in std_logic;
enB : in std_logic;
weA : in std_logic;
weB : in std_logic;
addrA : in std_logic_vector(ADDRWIDTHA-1 downto 0);
addrB : in std_logic_vector(ADDRWIDTHB-1 downto 0);
diA : in std_logic_vector(WIDTHA-1 downto 0);
diB : in std_logic_vector(WIDTHB-1 downto 0);
doA : out std_logic_vector(WIDTHA-1 downto 0);
doB : out std_logic_vector(WIDTHB-1 downto 0)
);
end asym_ram_tdp;
architecture asym_ram_tdp_arc of asym_ram_tdp is
function max(L, R: INTEGER) return INTEGER is
begin
if L > R then
return L;
else
return R;
end if;
end;
function min(L, R: INTEGER) return INTEGER is
begin
if L < R then
return L;
else
return R;
end if;
end;
function log2 (val: INTEGER) return natural is
variable res : natural;
begin
for i in 0 to 31 loop
if (val <= (2**i)) then
res := i;
exit;
end if;
end loop;
return res;
end function Log2;
constant minWIDTH : integer := min(WIDTHA,WIDTHB);
constant maxWIDTH : integer := max(WIDTHA,WIDTHB);
constant maxSIZE : integer := max(SIZEA,SIZEB);
constant RATIO : integer := maxWIDTH / minWIDTH;
-- An asymmetric RAM is modeled in a similar way as a symmetric RAM, with an array of array object.
-- Its aspect ratio corresponds to the port with the lower data width (larger depth).
type ramType is array (0 to maxSIZE-1) of std_logic_vector(minWIDTH-1 downto 0);
signal my_ram : ramType := (others => (others => '0'));
signal readA : std_logic_vector(WIDTHA-1 downto 0):= (others => '0');
signal readB : std_logic_vector(WIDTHB-1 downto 0):= (others => '0');
signal regA : std_logic_vector(WIDTHA-1 downto 0):= (others => '0');
signal regB : std_logic_vector(WIDTHB-1 downto 0):= (others => '0');
begin
process (clkA)
begin
if rising_edge(clkA) then
if enA = '1' then
if weA = '1' then
my_ram(to_integer(unsigned(addrA))) <= diA; --my_ram(conv_integer(addrA)) <= diA;
readA <= diA;
else
readA <= my_ram(to_integer(unsigned(addrA)));
end if;
end if;
regA <= readA;
end if;
end process;
process (clkB)
begin
if rising_edge(clkB) then
for i in 0 to RATIO-1 loop
if enB = '1' then
if weB = '1' then
my_ram( to_integer(unsigned( addrB & std_logic_vector(to_unsigned(i,log2(RATIO))) )) ) <= diB((i+1)*minWIDTH-1 downto i*minWIDTH);
--my_ram( conv_integer( addrB & conv_std_logic_vector(i,log2(RATIO)) ) ) <= diB((i+1)*minWIDTH-1 downto i*minWIDTH);
end if;
-- The read statement below is placed after the write statement on purpose to ensure write-first synchronization
-- through the variable mechanism
readB((i+1)*minWIDTH-1 downto i*minWIDTH) <= my_ram( to_integer(unsigned( addrB & std_logic_vector(to_unsigned(i,log2(RATIO))) )) );
--readB((i+1)*minWIDTH-1 downto i*minWIDTH) <= my_ram( conv_integer( addrB & conv_std_logic_vector(i,log2(RATIO)) ) );
end if;
end loop;
regB <= readB;
end if;
end process;
doA <= regA;
doB <= regB;
end asym_ram_tdp_arc;
The error shown:
Code:
INFO: [VRFC 10-163] Analyzing VHDL file "C:/Work/true_dp_filtersets_ram/true_dp_filtersets_ram.srcs/sources_1/new/asym_ram_tdp.vhd" into library xil_defaultlib
INFO: [VRFC 10-307] analyzing entity asym_ram_tdp
ERROR: [VRFC 10-724] found '2' definitions of operator "&", cannot determine exact overloaded matching definition for "&" [C:/Work/true_dp_filtersets_ram/true_dp_filtersets_ram.srcs/sources_1/new/asym_ram_tdp.vhd:132]
ERROR: [VRFC 10-724] found '2' definitions of operator "&", cannot determine exact overloaded matching definition for "&" [C:/Work/true_dp_filtersets_ram/true_dp_filtersets_ram.srcs/sources_1/new/asym_ram_tdp.vhd:137]
ERROR: [VRFC 10-1504] unit asym_ram_tdp_arc ignored due to previous errors [C:/Work/true_dp_filtersets_ram/true_dp_filtersets_ram.srcs/sources_1/new/asym_ram_tdp.vhd:59]
INFO: [VRFC 10-240] VHDL file C:/Work/true_dp_filtersets_ram/true_dp_filtersets_ram.srcs/sources_1/new/asym_ram_tdp.vhd ignored due to errors
In my opinion at line 132, addrB and i are both std_logic_vector. Same is for line 137. So why am I seeing this?
Does it have something to do with my change of libraries or am I making some silly mistake somewhere?
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
PortA is my write port and PortB is my read port for initial analysis. The TB should write writes 32 bits data at a time via PortA
PortA size (32 bits) < PortB size (1280 bits).
At portB, I only want to read out the written data 1280 bits at a time.
Code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;
library unisim;
use unisim.vcomponents.all;
entity asym_ram_tdp_tb is
-- Port ( );
end asym_ram_tdp_tb;
architecture asym_ram_tdp_tb_arc of asym_ram_tdp_tb is
component asym_ram_tdp is
generic (
WIDTHA : integer := 4;
SIZEA : integer := 1024;
ADDRWIDTHA : integer := 10;
WIDTHB : integer := 16;
SIZEB : integer := 256;
ADDRWIDTHB : integer := 8
);
port (
clkA : in std_logic;
clkB : in std_logic;
enA : in std_logic;
enB : in std_logic;
weA : in std_logic;
weB : in std_logic;
addrA : in std_logic_vector(ADDRWIDTHA-1 downto 0);
addrB : in std_logic_vector(ADDRWIDTHB-1 downto 0);
diA : in std_logic_vector(WIDTHA-1 downto 0);
diB : in std_logic_vector(WIDTHB-1 downto 0);
doA : out std_logic_vector(WIDTHA-1 downto 0);
doB : out std_logic_vector(WIDTHB-1 downto 0)
);
end component;
-- Denfine clocks
constant CLK_111M111_PERIOD : time := 9.000 ns;
constant CLK_100_PERIOD : time := 10.000 ns;
signal clk_111M111 : std_logic := '0';
signal clk_100M : std_logic := '0';
signal write_done : std_logic := '0';
signal write_done_q : std_logic := '0';
-- Port B
constant DATA_WIDTH_B : integer := 1280;
constant SIZE_B : integer := 128;
constant ADDR_WIDTH_B : integer := 7;
signal en_b : std_logic := '0' ;
signal w_en_b : std_logic := '0' ;
signal addr_b : std_logic_vector(ADDR_WIDTH_B-1 downto 0) := (others => '0');
signal d_in_b : std_logic_vector(DATA_WIDTH_B-1 downto 0) := (others => '0');
signal d_out_b : std_logic_vector(DATA_WIDTH_B-1 downto 0) ;
signal addr_b_cnt : integer range 0 to 127 := 0 ;
-- Port A
constant DATA_WIDTH_A : integer := 32 ;
constant SIZE_A : integer := 8192;
constant ADDR_WIDTH_A : integer := 13;
signal en_a : std_logic := '0' ;
signal w_en_a : std_logic := '0' ;
signal addr_a : std_logic_vector(ADDR_WIDTH_A-1 downto 0) := (others => '0');
signal d_in_a : std_logic_vector(DATA_WIDTH_A-1 downto 0) := (others => '0');
signal d_out_a : std_logic_vector(DATA_WIDTH_A-1 downto 0) ;
signal addr_a_cnt : integer range 0 to 8191 := 0 ;
constant FILTER_SET_NUM : integer := DATA_WIDTH_B/DATA_WIDTH_A;
begin
dp_filterset_ram : asym_ram_tdp
generic map(
WIDTHA => DATA_WIDTH_A,
SIZEA => SIZE_A ,
ADDRWIDTHA => ADDR_WIDTH_A,
WIDTHB => DATA_WIDTH_B,
SIZEB => SIZE_B ,
ADDRWIDTHB => ADDR_WIDTH_B
)
port map(
clkA => clk_111M111,
clkB => clk_100M ,
enA => en_a ,
enB => en_b ,
weA => w_en_a ,
weB => w_en_b ,
addrA => addr_a ,
addrB => addr_b ,
diA => d_in_a ,
diB => d_in_b ,
doA => d_out_a ,
doB => d_out_b
);
-- Generate clocks
clk_111M111 <= not(clk_111M111) after CLK_111M111_PERIOD/2;
clk_100M <= not(clk_100M) after CLK_100_PERIOD/2;
------------
-- Write RAM
------------
write_p : process
begin
-- For testing we will fill in 3 filter-sets. So we need 3x20 write cycles.
en_a <= '0';
w_en_a <= '0';
addr_a <= (others => '0');
wait for CLK_111M111_PERIOD*2;
fill_ram_1: for i in 0 to FILTER_SET_NUM-1 loop
en_a <= '1';
w_en_a <= '1';
addr_a <= std_logic_vector(to_unsigned(i, ADDR_WIDTH_A));
d_in_a <= std_logic_vector(to_unsigned(i, DATA_WIDTH_A));
addr_a_cnt <= i;
wait until rising_edge(clk_111M111);
end loop fill_ram_1;
en_a <= '0';
w_en_a <= '0';
addr_a <= (others => '0');
write_done <= '1';
wait for CLK_111M111_PERIOD*1;
write_done <= '0';
fill_ram_2: for i in addr_a_cnt+1 to addr_a_cnt+1+FILTER_SET_NUM loop
en_a <= '1';
w_en_a <= '1';
addr_a <= std_logic_vector(to_unsigned(i, ADDR_WIDTH_A));
d_in_a <= std_logic_vector(to_unsigned(i, DATA_WIDTH_A));
addr_a_cnt <= i;
wait until rising_edge(clk_111M111);
end loop fill_ram_2;
en_a <= '0';
w_en_a <= '0';
addr_a <= (others => '0');
write_done <= '1';
wait for CLK_111M111_PERIOD*1;
write_done <= '0';
fill_ram_3: for i in addr_a_cnt+1 to addr_a_cnt+1+FILTER_SET_NUM loop
en_a <= '1';
w_en_a <= '1';
addr_a <= std_logic_vector(to_unsigned(i, ADDR_WIDTH_A));
d_in_a <= std_logic_vector(to_unsigned(i, DATA_WIDTH_A));
addr_a_cnt <= i;
wait until rising_edge(clk_111M111);
end loop fill_ram_3;
en_a <= '0';
w_en_a <= '0';
addr_a <= (others => '0');
write_done <= '1';
wait for CLK_111M111_PERIOD*1;
write_done <= '0';
fill_ram_4: for i in addr_a_cnt+1 to addr_a_cnt+1+FILTER_SET_NUM loop
en_a <= '1';
w_en_a <= '1';
addr_a <= std_logic_vector(to_unsigned(i, ADDR_WIDTH_A));
d_in_a <= std_logic_vector(to_unsigned(i, DATA_WIDTH_A));
addr_a_cnt <= i;
wait until rising_edge(clk_111M111);
end loop fill_ram_4;
en_a <= '0';
w_en_a <= '0';
addr_a <= (others => '0');
write_done <= '1';
wait for CLK_111M111_PERIOD*1;
write_done <= '0';
wait;
end process write_p;
------------
-- Read RAM
------------
read_p : process
begin
en_b <= '0';
wait for CLK_100_PERIOD*FILTER_SET_NUM;
en_b <= '1';
addr_b <= std_logic_vector(to_unsigned(0, ADDR_WIDTH_B));
wait for CLK_100_PERIOD*1;
en_b <= '0';
wait for CLK_100_PERIOD*FILTER_SET_NUM;
en_b <= '1';
addr_b <= std_logic_vector(to_unsigned(1, ADDR_WIDTH_B));
wait for CLK_100_PERIOD*1;
en_b <= '0';
wait;
end process read_p;
Last edited: