Assume I have this simple core with generics as genertest.vhd
:
--------------------------------------------------------------------------
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 genertest IS
GENERIC(
numbits : natural := 8
);
PORT
(
clk : IN STD_LOGIC;
d_OUT : OUT STD_LOGIC_VECTOR(numbits-1 downto 0);
d_IN : IN STD_LOGIC_VECTOR(numbits-1 downto 0)
);
END genertest;
ARCHITECTURE structure OF genertest IS
BEGIN
main_proc: PROCESS(clk)
BEGIN
IF rising_edge(clk) THEN -- posedge
d_OUT <= not(d_IN);
END IF;
END PROCESS main_proc;
END structure;
... and I want to test it with following test workbench, genertest_twb.vhd
:
----------------------------------------------------------------------------------
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 genertest_twb IS
END genertest_twb;
ARCHITECTURE testbench_arch OF genertest_twb IS
COMPONENT genertest
PORT(
clk : IN STD_LOGIC;
d_OUT : OUT STD_LOGIC_VECTOR(numbits-1 downto 0);
d_IN : IN STD_LOGIC_VECTOR(numbits-1 downto 0)
);
END COMPONENT;
SIGNAL wtCLK : std_logic := '0';
SIGNAL wCntReg : STD_LOGIC_VECTOR(numbits-1 DOWNTO 0) := (others => 'Z');
SIGNAL tmp_cnt : natural := 0 ;
-- clock parameters
constant PERIODN : natural := 20; -- can be real := 20.0;
constant PERIOD : time := PERIODN * 1 ns;
constant DUTY_CYCLE : real := 0.5;
constant OFFSET : time := 100 ns;
BEGIN
UUT : genertest -- VHDL
PORT MAP(
clk => wtCLK,
d_IN => wCntReg,
d_OUT => OPEN
);
-- clock process for generating CLK
-- (here, left as unnamed)
PROCESS
BEGIN
WAIT for OFFSET;
CLOCK_LOOP : LOOP
wtCLK <= '0';
-- tmp_na - natural problems with bit width?
-- wCntReg <= std_logic_vector(to_unsigned(natural'pos(tmp_na), wCntReg'length));
WAIT FOR (PERIOD - (PERIOD * DUTY_CYCLE));
wtCLK <= '1';
WAIT FOR (PERIOD * DUTY_CYCLE);
END LOOP CLOCK_LOOP;
END PROCESS;
count_proc: PROCESS(wtCLK)
BEGIN
IF rising_edge(wtCLK) THEN -- posedge
tmp_cnt <= tmp_cnt + 1;
wCntReg <= std_logic_vector(to_unsigned(natural'pos(tmp_cnt), wCntReg'length));
END IF;
END PROCESS count_proc;
END testbench_arch;
Now, I would assume that by referencing the genertest
component, the workbench would automatically know about the numbits
generic, but unfortunately, that is not the case; behavioral simulation of the above workbench in ISE WebPack fails with:
ERROR:HDLCompiler:69 - "/genertest_tbw.vhd" Line 17: <numbits> is not declared.
ERROR:HDLCompiler:69 - "/genertest_tbw.vhd" Line 18: <numbits> is not declared.
ERROR:HDLCompiler:69 - "/genertest_tbw.vhd" Line 23: <numbits> is not declared.
By adding the generic part in the genertest_tbw.vhd
here:
COMPONENT genertest
GENERIC(
numbits : natural := 8
);
PORT(
...
... will fix generics references local to the component - unfortunately, the reference to the generic in the SIGNAL wCntReg
declaration will still fail.
Finally, adding the generic part in the generte开发者_StackOverflow社区st_tbw.vhd
here:
ENTITY genertest_twb IS
GENERIC(
numbits : natural := 8
);
END genertest_twb;
... makes the generic available to the entire workbench file.
However, that still means I have to manually copy/paste numbits : natural := 8
sentence in the workbench file as well; which means it will figure two places, and I'd have to change both if I want to change the generic value :(
So my question is - is there a way to share / include generics, such that they are written/defined in only one file - and other files can refer to these particular values?
Thanks in advance for any answers,
Cheers!You're missing the point of generics. You don't pass the generic values up through the hierarchy, you pass them down.
Define numbits in your testbench (perhaps as something a bit more meaningful, like RAM_WIDTH), and use it to instantiate genertest with the appropriate number of bits. The default value defined for numbits in your genertest entity is used for code that does not explicitly define the generic value (either for readability, or perhaps to maintain backwards compatibility for a function that used to always take 8 bits, but now is configurable to any width).
So in your testbench, you want something like:
constant RAM_WIDTH : integer := 8;
...
UUT : genertest
GENERIC MAP (
numbits => RAM_WIDTH
);
PORT MAP
(
clk => wtCLK,
...
If you want "shared constants" you need a package
with some constants in it.
Then use those constants to map onto the generics of the items you instantiate.
精彩评论