VHDL 2008 can't drive a signal with an alias of an external name - vhdl

Please take a look at the following code, specifically the 3 commented lines at the end. I simulated this with Questasim 10.6c:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity alias_extname_driving_signal is
port(
clk : in std_logic
);
end alias_extname_driving_signal;
architecture primary of alias_extname_driving_signal is
signal buried_control_vector16 : std_logic_vector(15 downto 0) := (others => '0');
begin
buried_control_vector16 <= std_logic_vector(unsigned(buried_control_vector16) + 1) when rising_edge(clk);
end architecture primary;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity alias_extname_driving_signal_tb is
end alias_extname_driving_signal_tb;
architecture primary of alias_extname_driving_signal_tb is
signal clk : std_logic := '0';
signal control_vector16 : std_logic_vector(15 downto 0) := (others => '0');
alias control_vector16_alias is control_vector16;
alias buried_control_vector16_alias is << signal .alias_extname_driving_signal_tb.uut.buried_control_vector16 : std_logic_vector(15 downto 0) >>;
signal vector16 : std_logic_vector(15 downto 0);
begin
clk <= not clk after 10 ns;
control_vector16 <= std_logic_vector(unsigned(control_vector16) + 1) when rising_edge(clk);
uut : entity work.alias_extname_driving_signal
port map(
clk => clk
);
-- vector16 <= << signal .alias_extname_driving_signal_tb.uut.buried_control_vector16 : std_logic_vector(15 downto 0) >>; -- this statement works
-- vector16 <= control_vector16_alias; -- this statement works
-- vector16 <= buried_control_vector16_alias; -- vector16 remains perpetually undefined with this statement
end architecture primary;
As you can see, I'm able to drive a signal with an external name, an alias of a local signal, but not an alias of an external name. Is there any way I can use an alias of an external name to drive a signal in vhdl-2008?
Thanks in advance for your help.

External names can only be declared AFTER the object being referenced is elaborated.
VHDL starts elaborating from the testbench. First it elaborates the declaration region. Then it elaborates the code region in order. If it finds a component, it elaborates it and any subcomponents. When it finishes elaborating the component (and any subcomponents) it picks up elaborating int the testbench where it left off.
Hence, you need to move your alias declaration to either a block statement or a process. The code for the block statement is as follows. Note the label with the block statement is required.
architecture primary of alias_extname_driving_signal_tb is
signal clk : std_logic := '0';
signal control_vector16 : std_logic_vector(15 downto 0) := (others => '0');
alias control_vector16_alias is control_vector16;
signal vector16 : std_logic_vector(15 downto 0);
begin
clk <= not clk after 10 ns;
control_vector16 <= std_logic_vector(unsigned(control_vector16) + 1) when rising_edge(clk);
uut : entity work.alias_extname_driving_signal
port map(
clk => clk
);
myblock : block
alias buried_control_vector16_alias is << signal .alias_extname_driving_signal_tb.uut.buried_control_vector16 : std_logic_vector(15 downto 0) >>;
begin
vector16 <= << signal .alias_extname_driving_signal_tb.uut.buried_control_vector16 : std_logic_vector(15 downto 0) >>; -- this statement works
vector16 <= control_vector16_alias; -- this statement works
vector16 <= buried_control_vector16_alias; -- vector16 remains perpetually undefined with this statement
end block myblock ;
end architecture primary;

Related

VHDL - Index out range even If I made concurrent checking using when-else

I'm implementing a register file where I wanna read asynchronously and write on the rising edge.
I made concurrent checks on the addresses and the writing occurs inside a process.
However, it always cause me a fatal error and I don't know why!
Here's my code if anyone could help and tell me how can I read asynchronously and write on rising edge
Thank you!
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity RegFile is
port(
outData1 : out std_logic_vector(15 downto 0);
outData2 : out std_logic_vector(15 downto 0);
inData : in std_logic_vector(15 downto 0);
writeEn : in std_logic;
reg1Sel : in std_logic_vector(2 downto 0);
reg2Sel : in std_logic_vector(2 downto 0);
writeRegSel : in std_logic_vector(2 downto 0);
clk : in std_logic
);
end RegFile;
architecture Register_File of RegFile is
type registerFile is array(0 to 5) of std_logic_vector(15 downto 0);
signal registers : registerFile;
signal reg1Address,reg2Address : integer;
signal reg1FinalAddressing,reg2FinalAddressing : std_logic_vector(2 downto 0);
begin
--Conversion of logic vector to unsigned integer
reg1Address <= to_integer(unsigned(reg1Sel));
reg2Address <= to_integer(unsigned(reg2Sel));
reg1FinalAddressing <= reg1Sel when (reg1Address<6 ) else
(others => '0');
reg2FinalAddressing <= reg2Sel when (reg2Address<6 ) else
(others => '0');
outData1 <= registers(to_integer(unsigned(reg1FinalAddressing)));
outData2 <= registers(to_integer(unsigned(reg2FinalAddressing)));
process (clk) is
begin
-- Reading from Registers 1 and 2
if rising_edge(clk) then
-- Writing to Register file Case Enabled
if writeEn = '1' then
registers(to_integer(unsigned(writeRegSel))) <= inData;
-- Case a value being written to register file, it will be out simultaneously if
-- the register was already selected. (The updated values are being released instantly).
if reg1Sel = writeRegSel then
outData1 <= inData;
end if;
if reg2Sel = writeRegSel then
outData2 <= inData;
end if;
end if;
end if;
end process;
end Register_File;

Realizing Top Level Entity in Testbench using VHDL

I'm a newbie in VHDL and hardware world.
I'm trying to make a Count&Compare example using Top Level Hierarchy and test it with testbench and see the results on ISIM.
Here is my block diagram sketch:
So I end up these 3 vhd source files:
Counter.vhd
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity Count_src is
Port ( CLK : in STD_LOGIC;
Reset : in STD_LOGIC;
S : out STD_LOGIC_VECTOR (3 downto 0));
end Count_src;
architecture Behavioral of Count_src is
signal count : STD_LOGIC_VECTOR (3 downto 0);
begin
process (Reset, CLK)
begin
if Reset = '1' then -- Active high reset
count <= "0000"; -- Clear count to 0
elsif (rising_edge(CLK)) then -- Positive edge
count <= count + "0001"; -- increment count
end if;
end process;
S <= count; -- Export count
end Behavioral;
Compare
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity Compare_src is
Port ( A : in STD_LOGIC_VECTOR (3 downto 0);
B : in STD_LOGIC_VECTOR (3 downto 0);
S : out STD_LOGIC);
end Compare_src;
architecture Behavioral of Compare_src is
begin
S <= '1' when (A = B) else -- Test if A and B are same
'0'; -- Set when S is different
end Behavioral;
CountCompare (Top Level)
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;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity CountCompare_src is
Port ( Clock : in STD_LOGIC;
Reset : in STD_LOGIC;
Value : in STD_LOGIC_VECTOR (3 downto 0);
Flag : out STD_LOGIC);
end CountCompare_src;
architecture Behavioral of CountCompare_src is
-- COMPONENT DECLERATIONS
component counter is
port ( CLK : in std_logic;
Reset : in std_logic;
S : out std_logic_vector(3 downto 0)
);
end component;
component compare is
port (A : in std_logic_vector(3 downto 0);
B : in std_logic_vector(3 downto 0);
S : out std_logic
);
end component;
-- Component Spesification and Binding
for all : counter use entity work.Count_src(behavioral);
for all : compare use entity work.Compare_src(behavioral);
-- Internal Wires
signal count_out : std_logic_vector(3 downto 0);
begin
-- Component instantiation
C1: counter PORT MAP ( Reset => Reset,
CLK => Clock,
S => count_out
);
C2: compare PORT MAP ( A => count_out,
B => Value,
S => Flag
);
end Behavioral;
To test the design I wrote a testbench as follows:
TestBench
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY TopLevelTester_tb IS
END TopLevelTester_tb;
ARCHITECTURE behavior OF TopLevelTester_tb IS
--Input and Output definitions.
signal Clock : std_logic := '0';
signal Reset : std_logic := '0';
signal Value : std_logic_vector(3 downto 0) := "1000";
signal Flag : std_logic;
-- Clock period definitions
constant clk_period : time := 1 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: entity work.CountCompare_src PORT MAP
(
Clock => Clock,
Reset => Reset,
Value => Value
);
proc: process
begin
Clock <= '0';
wait for clk_period/2;
Clock <= '1';
wait for clk_period/2;
end process;
END;
When I simulate behavioral model, the ISIM pops up, but I see no changes on the Compare Flag. Here is the ss of the ISIM:
What am I missing here? Why does'nt the Flag change?
My best regards.
You have two problems, both in your testbench.
The first is that you never reset count in the counter, it will always be 'U's or 'X's (after you increment it).
The second is that the directly entity instantiation in the testbench is missing an association for the formal flag output to the actual flag signal:
begin
uut:
entity work.countcompare_src
port map (
clock => clock,
reset => reset,
value => value,
flag => flag
);
proc:
process
begin
clock <= '0';
wait for clk_period/2;
clock <= '1';
wait for clk_period/2;
if now > 20 ns then
wait;
end if;
end process;
stimulus:
process
begin
wait for 1 ns;
reset <= '1';
wait for 1 ns;
reset <= '0';
wait;
end process;
Fix those two things and you get:

Attribute event requires a static signal prefix in 8 -bit Multiplier in vhdl

I am implementing a multiplier in which i multiply A (8 bits) and B (8 bits), and store result at S. Number of bit required for output S is 16 bits. S have higher part SH and lower part SL.Every time i shift ,add operation is performed
i am getting following errors in my controller part :-
Attribute event requires a static signal prefix
is not declared.
"**" expects 2 arguments
and my code is:-
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity PIPO is
port (reset: in std_logic ;
B:IN STD_LOGIC_VECTOR (7 downto 0 );
LOAD:in std_logic ;
SHIFT:in std_logic ;
ADD:in std_logic ;
Sum:IN STD_LOGIC_VECTOR (7 downto 0 );
C_out:in std_logic ;
CLK:in std_logic ;
result: out STD_LOGIC_VECTOR (15 downto 0) ;
LSB:out std_logic ;
TB:out std_logic_vector (7 downto 0) );
end ;
architecture rtl OF PIPO is
signal temp1 : std_logic_vector(15 downto 0);
----temp2 -add
signal temp2 : std_logic ;
begin
process (CLK, reset)
begin
if reset='0' then
temp1<= (others =>'0');
temp2<= '0';
elsif (CLK'event and CLK='1') then
if LOAD ='1' then
temp1(7 downto 0) <= B;
temp1(15 downto 8) <= (others => '0');
end if ;
if ADD= '1' then
temp2 <='1';
end if;
if SHIFT= '1' then
if ADD= '1' then
------adder result ko add n shift
temp2<= '0';
temp1<=C_out & Sum & temp1( 7 downto 1 );
else
----only shift
temp1<= '0' & temp1( 15 downto 1 );
end if;
end if;
end if;
end process;
LSB <=temp1(0);
result<=temp1( 15 downto 0 );
TB <=temp1(15 downto 8);
end architecture rtl;
-------------------------------------------
-------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity Controller is
Port ( ADD :OUT STD_LOGIC;
SHIFT:OUT STD_LOGIC;
LOAD:OUT STD_LOGIC;
STOP:OUT STD_LOGIC;
STRT:IN STD_LOGIC;
LSB:IN STD_LOGIC;
CLK:IN STD_LOGIC;
reset:IN STD_LOGIC );
end ;
architecture rtl OF Contoller is
---RTL level code is inherently synchronous
signal count : unsigned (2 downto 0);
----differnt states
type state_typ is ( IDLE, INIT, TEST, ADDs, SHIFTs );
signal state : state_typ;
begin
--controller : process (ADD,SHIFT,LOAD,STOP,STRT,LSB,CLK,reset)
process (state)--(CLK, reset,ADD,SHIFT,LOAD,STOP,STRT,LSB)
begin
if reset='0' then
state <= IDLE;
count <= "000";
elsif (CLK'event and CLK='1') then
case state is
when IDLE =>
if STRT = '1' then
--- if STRT = '1' then
state <= INIT;
else
state <= IDLE;
end if;
when INIT =>
state <= TEST;
when TEST =>
if LSB = '0' then
state <= SHIFTs;
else
state <= ADDs;
end if;
when ADDs =>
state <= SHIFTs;
when SHIFTs =>
if count = "111" then
count <= "000";
state <= IDLE;
else
count<= std_logic_vector(unsigned(count) + 1);
state <= TEST;
end if;
end case;
end if;
end process ;
STOP <= '1' when state = IDLE else '0';
ADD <= '1' when state = ADDs else '0';
SHIFT <= '1' when state = SHIFTs else '0';
LOAD <= '1' when state = INIT else '0';
end architecture rtl;
----------------------------------------------
--------------------------------------------
---multiplicand
library ieee;
use ieee.std_logic_1164.all;
entity multiplicand is
port (A : in std_logic(7 downto 0);
reset :in std_logic;
LOAD : in std_logic;
TA : OUT STD_LOGIC(7 downto 0);
CLK : in std_logic );
end entity;
architecture rtl OF multiplicand is
begin
process (CLK, reset)
begin
if reset='0' then
TA <= (others =>'0'); -- initialize
elsif (CLK'event and CLK='1') then
if LOAD_cmd = '1' then
TA(7 downto 0) <= A_in; -- load B_in into register
end if;
end if ;
end process;
end architecture rtl;
------------------------------------------------------
------------------------------------------------------
---Full Adder
library ieee;
use ieee.std_logic_1164.all;
entity Full_Adder is
port (A : in std_logic;
B : in std_logic;
C_in : in std_logic;
Sum : out std_logic ;
C_out : out std_logic);
end;
architecture struc of Full_Adder is
begin
Sum <= A xor B xor C_in;
C_out <= (A and B) or (A and C_in) or (B and C_in);
end struc;
------------------------------------------------------------
-------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity Adder is
Port ( TA : in STD_LOGIC_VECTOR (7 downto 0);
TB : in STD_LOGIC_VECTOR (7 downto 0);
Sum : out STD_LOGIC_VECTOR (7 downto 0);
C_in : in STD_LOGIC;
C_out : out STD_LOGIC);
end Adder;
architecture struc of Adder is
component Full_Adder is
port(A : in std_logic;
B : in std_logic;
C_in : in std_logic;
Sum : out std_logic ;
C_out : out std_logic);
end component;
signal C: std_logic_vector (7 downto 0);
begin
FA0:Full_Adder port map(TA(0), TB(0), C_in, Sum(0), C(0));
FA1: Full_Adder port map(TA(1), TB(1), C(0), Sum(1), C(1));
FA3: Full_Adder port map(TA(2),TB(2), C(1), Sum(2), C(2));
FA4: Full_Adder port map(TA(3), TB(3), C(2), Sum(3), C(3));
FA5: Full_Adder port map(TA(4), TB(4), C(3), Sum(4), C(4));
FA6: Full_Adder port map(TA(5), TB(5), C(4), Sum(5), C(5));
FA7: Full_Adder port map(TA(6), TB(6), C(5), Sum(6), C(6));
FA8: Full_Adder port map(TA(7), TB(7), C(6), Sum(7), C(7));
C_out <= C(7);
end struc;
------------------------------------------------------------
------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity multiplier is
Port ( num1 : in STD_LOGIC_VECTOR (7 downto 0);
num2 : in STD_LOGIC_VECTOR (7 downto 0);
result : out STD_LOGIC_VECTOR (15 downto 0);
CLK:in std_logic ;
reset:IN STD_LOGIC;
STRT:IN STD_LOGIC;
STOP:OUT STD_LOGIC );
end multiplier;
architecture rtl of Multiplier is
signal ADD :STD_LOGIC;
signal SHIFT :STD_LOGIC;
signal LOAD :STD_LOGIC;
signal LSB :STD_LOGIC;
signal A : STD_LOGIC_VECTOR (7 downto 0);
signal B :STD_LOGIC_VECTOR (7 downto 0);
signal Sum:STD_LOGIC_VECTOR (7 downto 0);
signal C_out:STD_LOGIC;
component Controller
port (
ADD :OUT STD_LOGIC;
SHIFT:OUT STD_LOGIC;
LOAD:OUT STD_LOGIC;
STOP:OUT STD_LOGIC;
STRT:IN STD_LOGIC;
LSB:IN STD_LOGIC;
CLK:IN STD_LOGIC;
reset:IN STD_LOGIC );
end component;
component Adder
port (
TA : in STD_LOGIC_VECTOR (7 downto 0);
TB : in STD_LOGIC_VECTOR (7 downto 0);
Sum : out STD_LOGIC_VECTOR (7 downto 0);
C_in : in STD_LOGIC;
C_out : out STD_LOGIC);
end component;
component PIPO
port (reset: in std_logic ;
B:IN STD_LOGIC_VECTOR (7 downto 0 );
LOAD:in std_logic ;
SHIFT:in std_logic ;
ADD:in std_logic ;
Sum:IN STD_LOGIC_VECTOR (7 downto 0 );
C_out:in std_logic ;
CLK:in std_logic ;
result: out STD_LOGIC_VECTOR (15 downto 0) ;
LSB:out std_logic ;
TB:out std_logic );
end component;
component multiplicand
port (A : in std_logic (7 downto 0);
reset :in std_logic;
LOAD : in std_logic;
TA : OUT STD_LOGIC(7 downto 0);
CLK : in std_logic );
end component ;
begin
inst_Controller: Controller
port map (ADD => ADD,
SHIFT =>SHIFT,
LOAD =>LOAD ,
STOP =>STOP,
STRT =>STRT,
LSB =>LSB ,
CLK =>CLK ,
reset =>reset
);
inst_multiplicand :multiplicand
port map (A =>A,
reset=>reset,
LOAD =>LOAD,
TA => TA(7 downto 0),
CLK => CLK
);
inst_PIPO :PIPO
port map ( reset => reset,
B => B ,
LOAD =>LOAD,
SHIFT=>SHIFT,
ADD=>ADD,
Sum=>Sum,
C_out=>C_out,
CLK=>CLK,
result=>result,
LSB=>LSB,
TB=>TB
);
inst_Full_Adder : Full_Adder
port map ( TA => TA,
TB =>TB,
Sum=>Sum ,
C_in=>C_in,
C_out=>C_out
);
end rtl;
Actually the space between CLK and the apostrophe/tick isn't significant
david_koontz#Macbook: token_test
elsif (CLK 'event and CLK ='1') then
KEYWD_ELSIF (151) elsif
DELIM_LEFT_PAREN ( 9) (
IDENTIFIER_TOKEN (128) CLK
DELIM_APOSTROPHE ( 8) '
IDENTIFIER_TOKEN (128) event
KEYWD_AND (134) and
IDENTIFIER_TOKEN (128) CLK
DELIM_EQUAL ( 25) =
CHAR_LIT_TOKEN ( 2) '1'
DELIM_RIGHT_PAREN ( 10) )
KEYWD_THEN (211) then
gives the same answer as:
david_koontz#Macbook: token_test
elsif (CLK'event and CLK ='1') then
KEYWD_ELSIF (151) elsif
DELIM_LEFT_PAREN ( 9) (
IDENTIFIER_TOKEN (128) CLK
DELIM_APOSTROPHE ( 8) '
IDENTIFIER_TOKEN (128) event
KEYWD_AND (134) and
IDENTIFIER_TOKEN (128) CLK
DELIM_EQUAL ( 25) =
CHAR_LIT_TOKEN ( 2) '1'
DELIM_RIGHT_PAREN ( 10) )
KEYWD_THEN (211) then
In vhdl, there is no lexical element parsing requiring a lack of white space. (Sorry Russel).
Correcting the other syntax ambiguities of your code (see below, missing context clause, Controller misspelled in the architecture declaration, count used as both a scalar and array subtype), results in two different VHDL analyzers swallowing the space between CLK and ' just fine.
The problem is in the tool you are using not actually being standard compliant or the code you present as having the problem isn't actually representational of the code generating the error. If a non-compliant tool it's likely a shortcoming you can live with, although there may be more things a bit more irksome.
david_koontz#Macbook: ghdl -a controller.vhdl
david_koontz#Macbook: nvc -a controller.vhdl
david_koontz#Macbook:
(no errors, it also elaborates without a test bench in ghdl, nvc disallows top level ports - which it is permitted to do by the standard)
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity Controller is
Port (
ADD: OUT STD_LOGIC;
SHIFT: OUT STD_LOGIC;
LOAD: OUT STD_LOGIC;
STOP: OUT STD_LOGIC;
STRT: IN STD_LOGIC;
LSB: IN STD_LOGIC;
CLK: IN STD_LOGIC;
reset: IN STD_LOGIC
);
end entity;
architecture rtl OF Controller is
---RTL level code is inherently synchronous
signal count : std_logic_vector (2 downto 0);
----differnt states
type state_typ is ( IDLE, INIT, TEST, ADDs, SHIFTs );
signal state : state_typ;
begin
NOLABEL:
process (CLK, reset)
begin
if reset='0' then
state <= IDLE;
count <= "000";
elsif (CLK 'event and CLK ='1') then
case state is
when IDLE =>
if STRT = '1' then
state <= INIT;
else
state <= IDLE;
end if;
when INIT =>
state <= TEST;
when TEST =>
if LSB = '0' then
state <= SHIFTs;
else
state <= ADDs;
end if;
when ADDs =>
state <= SHIFTs;
when SHIFTs =>
if count = "111" then -- verify if finished
count <= "000"; -- re-initialize counter
state <= IDLE; -- ready for next multiply
else
count <= -- increment counter
std_logic_vector(unsigned(count) + 1);
state <= TEST;
end if;
end case;
end if;
end process;
---end generate; ???
STOP <= '1' when state = IDLE else '0';
ADD <= '1' when state = ADDs else '0';
SHIFT <= '1' when state = SHIFTs else '0';
LOAD <= '1' when state = INIT else '0';
end architecture rtl;
The error message appears to stem from the signal CLK (the prefix for the event attribtute). There is no other use of the event attribute in your code presented with the question. A signal is one of the elements of entity_class that can be decorated with an attribute.
In the VHDL LRM's section on predefined attributes 'EVENT can only decorate a signal, and CLK is a signal (declared in a port). In that section the prefix is required to be denoted by a static signal name.
Is CLK a static signal name? Yes it is. It's a scalar subtype declared in the entity declaration and is locally static (available at analysis time - it's a scalar, a simple name and not involving a generic).
And about now you might get why someone would wonder if the code in the question is representational of the code generating the error or the VHDL tool used is not compliant.
The error message you report is usually associated with trying to use 'EVENT with an indexed signal name, e.g. w(i)'event. (See Signal attributes on a signal vector).
You're going to kick yourself for this one:
elsif (CLK 'event and CLK ='1') then
Should be:
elsif (CLK'event and CLK ='1') then
See the difference?
Even better:
elsif rising_edge(CLK) then
It seems you're missing a clk entry in the process
Change the line reading:
process (state)--(CLK, reset,ADD,SHIFT,LOAD,STOP,STRT,LSB)
to read:
process (clk, reset)

Why Does This VHDL Work in Sumulation and Does not Work on the Virtex 5 Device

I have spent the whole day trying to solve the following problem. I am building a small averaging multichannel oscilloscope and I have the following module for storing the signal:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
use IEEE.numeric_std.all;
entity storage is
port
(
clk_in : in std_logic;
reset : in std_logic;
element_in : in std_logic;
data_in : in std_logic_vector(11 downto 0);
addr : in std_logic_vector(9 downto 0);
add : in std_logic; -- add = '1' means add to RAM
-- add = '0' means write to RAM
dump : in std_logic;
element_out : out std_logic;
data_out : out std_logic_vector(31 downto 0)
);
end storage;
architecture rtl of storage is
component bram is
port
(
clk : in std_logic;
we : in std_logic;
en : in std_logic;
addr : in std_logic_vector(9 downto 0);
di : in std_logic_vector(31 downto 0);
do : out std_logic_vector(31 downto 0)
);
end component bram;
type state is (st_startwait, st_add, st_write);
signal current_state : state := st_startwait;
signal next_state : state := st_startwait;
signal start : std_logic;
signal we : std_logic;
signal en : std_logic;
signal di : std_logic_vector(31 downto 0);
signal do : std_logic_vector(31 downto 0);
signal data : std_logic_vector(11 downto 0);
begin
ram : bram port map
(
clk => clk_in,
we => we,
en => en,
addr => addr,
di => di,
do => do
);
process(clk_in, reset, start)
begin
if rising_edge(clk_in) then
if (reset = '1') then
current_state <= st_startwait;
else
start <= '0';
current_state <= next_state;
if (element_in = '1') then
start <= '1';
end if;
end if;
end if;
end process;
process(current_state, start, dump)
variable acc : std_logic_vector(31 downto 0);
begin
element_out <= '0';
en <= '1';
we <= '0';
case current_state is
when st_startwait =>
if (start = '1') then
acc(11 downto 0) := data_in;
acc(31 downto 12) := (others => '0');
next_state <= st_add;
else
next_state <= st_startwait;
end if;
when st_add =>
if (add = '1') then
acc := acc + do;
end if;
we <= '1';
di <= acc;
next_state <= st_write;
when st_write =>
if (dump = '1') then
data_out <= acc;
element_out <= '1';
end if;
next_state <= st_startwait;
end case;
end process;
end rtl;
Below is the BRAM module as copied from the XST manual. This is a no-change type of BRAM and I believe there is the problem. The symptom is that, while this simulates fine, I read only zeroes from the memory when I use the design on the device.
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
entity bram is
port
(
clk : in std_logic;
we : in std_logic;
en : in std_logic;
addr : in std_logic_vector(9 downto 0);
di : in std_logic_vector(31 downto 0);
do : out std_logic_vector(31 downto 0)
);
end bram;
architecture rtl of bram is
type ram_type is array (0 to 999) of std_logic_vector (31 downto 0);
signal buf : ram_type;
begin
process(clk, en, we)
begin
if rising_edge(clk) then
if en = '1' then
if we = '1' then
buf(conv_integer(addr)) <= di;
else
do <= buf(conv_integer(addr));
end if;
end if;
end if;
end process;
end rtl;
What follows is a description of the chip use and the expected output. "clk_in" is a 50 MHz clock. "element_in" is '1' for 20 ns and '0' for 60 ns. "addr_in" iterates from 0 to 999 and changes every 80 ns. "element_in", "data_in", and "addr" are all aligned and synchronous. Now "add" is '1' for 1000 elements, then both "add" and "dump" are zero for 8000 elements and, finally "dump" is '1' for 1000 elements. Now, if I have a test bench that supplies "data_in" from 0 to 999, I expect data_out to be 0, 10, 20, 30, ..., 9990 when "dump" is '1'. That is according to the simulation. In reality I get 0, 1, 2, 3, ..., 999....
Some initial issues to address are listed below.
The process(current_state, start, dump) in storage entity looks like it is
intended to implement a combinatorial element (gates), but the signal (port)
data_in is not in the sensitivity list.
This is very likely to cause a difference between simulation and synthesis
behavior, since simulation will typically only react to the signals in the
sensitivity list, where synthesis will implement the combinatorial design and
react on all used signals, but may give a warning about incomplete sensitivity
list or inferred latches. If you are using VHDL-2008 then use can use a
sensitivity list of (all) to have the process sensitivity to all used
signals, and otherwise you need to add missing signals manually.
The case current_state is in process(current_state, start, dump) lacks an
when others => ..., so the synthesis tool has probably given you a warning
about inferred latches. This should be fixed by adding the when others =>
with and assign all signals driven by the process to the relevant value.
The use clause lists:
use IEEE.std_logic_unsigned.all;
use IEEE.numeric_std.all;
But both of these should not be used at the same time, since they declare some
of the same identifiers, for example is unsigned declared in both. Since the
RAM uses std_logic_unsigned I suggest that you stick with that only, and
delete use of numeric_std. For new code I would though recommend use of
numeric_std.
Also the process(clk_in, reset, start) in storage entity implements a
sequential element (flip flop) sensitive to only rising edge of clk_in, so
the two last signals in sensitivity list ..., reset, start) are unnecessary,
but does not cause a problem.

ModelSim - Unable To Simulate Button Presses

I want to use four push buttons as inputs and three seven-segment LED displays as outputs. Two push buttons should step up and down through the sixteen RAM locations; the other two should increment and decrement the contents of the currently-displayed memory location. I have the following two entities:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity DE2_TOP is
port (
KEY : in std_logic_vector(3 downto 0); -- Push button
CLOCK_50: in std_logic;
);
end DE2_TOP;
architecture datapath of DE2_TOP is
begin
U1: entity work.lab1 port map (
key => key,
clock => clock_50,
);
end datapath;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity raminfr is -STANDARD RAM INFERENCE
port (
clock: in std_logic;
we : in std_logic;
a : in unsigned(3 downto 0);
di : in unsigned(7 downto 0);
do : out unsigned(7 downto 0)
);
end raminfr;
architecture rtl of raminfr is
type ram_type is array (0 to 15) of unsigned(7 downto 0);
signal RAM : ram_type;
signal read_a : unsigned(3 downto 0);
begin
process (clock)
begin
if rising_edge(clock) then
if we = '1' then
RAM(to_integer(a)) <= di;
end if;
read_a <= a;
end if;
end process;
do <= RAM(to_integer(read_a));
end rtl;
and
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity lab1 is
port(
clock : in std_logic;
key : in std_logic_vector(3 downto 0);
);
end lab1;
architecture up_and_down of lab1 is
signal value_in_ram : unsigned(7 downto 0);
signal we : std_logic;
signal value_counter : unsigned(7 downto 0) ;
signal register_counter : unsigned(3 downto 0);
begin
U1: entity work.raminfr port map (
a => register_counter,
di => value_counter,
do => value_in_ram,
clock => clock,
we => we
);
process(clock)
begin
if rising_edge(clock) then
if (key(3)='0' and key(2)='0' and key(1)='1' and key(0)='0') then
value_counter <= value_counter + "1";
elsif (key(3)='0' and key(2)='0' and key(1)='0' and key(0)='1') then
value_counter <= value_counter - "1";
elsif (key(3)='1' and key(2)='0' and key(1)='0' and key(0)='0') then
register_counter<= register_counter + "1";
value_counter <= value_in_ram;
elsif (key(3)='0' and key(2)='1' and key(1)='0' and key(0)='0') then
register_counter<= register_counter - "1";
value_counter <= value_in_ram;
end if;
end if;
end process;
end architecture up_and_down;
I also have the following test bench, where I try to simulate buttons being pressed via KEY:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity DE2_TOP_TEST is
end;
architecture BENCH of DE2_TOP_TEST is
signal KEY : std_logic_vector(3 downto 0);
signal CLOCK_50 : std_logic := '0';
signal hex4, hex5, hex6 : std_logic_vector(6 downto 0);
begin
clock_50 <= not clock_50 after 50 ns;
process
begin
KEY<="0010";
wait for 1 us;
KEY<="0000";
end process;
uut:work.DE2_TOP port map (
KEY=>key,
CLOCK_50=>clock_50,
hex4=>hex4,
hex5=>hex5,
hex6=>hex6
);
end BENCH;
My test bench set up looks like this:
To simulate, I compile all three of the above files, and then simulate DE2_TOP_TEST, but am met with the result that my "KEY" is still undefined, as below (although CLOCK_50 does get the default value that I set):
Anyone know what's causing this?
(1) You have unconnected ports on the entity you are typing to test. The test results are as expected for those inputs - specifically, clk, being undriven.
(2) Having connected clk, you will need to drive it.
signal clk : std_logic := '0';
and
clk <= not clk after 50 ns;
should give a 10MHz clock, check this in the simulator
(3) Drive "KEY" with a specific sequence of values
subtype keys is std_logic_vector(3 downto 0);
constant count_up : keys := "0001";
constant count_dn : keys := "0010";
constant idle : keys := "0000";
-- etc
process
begin
KEY <= count_up;
wait for 1 us;
KEY <= idle;
wait for ...
-- etc
end process;
(4) Bring the OUTPUTS back out into the testbench so that you can check their values. You need to bring them out as ports in the top level (design) entity anyway, if you are going to connect them to a display!
Then (later, once things have started going to plan) you can test them in the testbench process...
wait for 100 ns;
-- after the last press, we should have "07" on the display
assert digit(1) = "0111111" report "Left digit has wrong value" severity ERROR;
assert digit(0) = "0000111" report "Left digit has wrong value" severity ERROR;
A self-checking testbench like this saves debugging by staring at waveforms. You only need the waveforms when the tests are failing...

Resources