P
Paul Urbanus
Guest
In the following forum thread, member Alex reports some odd behavior
when using ISIM to simulate some code that is part of an FPGA emulation
of an arcade game.
http://forum.gadgetfactory.net/index.php?/topic/1544-isim-is-driving-me-crazy/#entry10072
Since the code is likely a literal translation of the arcade game
schematic, some bits from a 5-bit slv counter are used as the async
reset and clock in a process. Don't be distracted by this
non-synchronous design practice, as this isn't the issue.
The issue is that the rising_edge() function wasn't working correctly.
After some investigation and simulation, a determination has been made
that in ISIM the 'last_value attribute isn't being properly evaluated
*inside* the function when the argument to rising_edge() is a bit from a
standard_logic_vector???
If the counter bit, counter(1), that is used as the clock is assigned to
the std_logic signal, counter_1, then the 'last_value attribute is
evaluated properly in the rising_edge() function call.
To test this a 2nd process is created using the counter_1 signal as the
clock. The rising_edge function source is copied from the Xilinx library
and modified to report the status of the incoming signal.
Here is the test bench which illustrates the problem.
********** BEGIN CODE ***********
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity test_tb is
end test_tb;
architecture behavior of test_tb is
function rising_edge (signal s : std_ulogic) return boolean is
begin
report "s'event=" & boolean'image(s'event) & " s=" &
std_ulogic'image(s) & " s'last_value=" & std_ulogic'image(s'last_value);
return (s'event and (to_x01(s) = '1') and
(to_x01(s'last_value) = '0'));
end;
signal output : std_logic := '0';
signal counter : std_logic_vector(4 downto 0) := (others => '0');
constant period : time := 20 ns;
signal counter_1 : std_logic;
signal output_1 : std_logic;
begin
process
variable counter_i : std_logic_vector(4 downto 0) := (others => '0');
begin
wait for period;
counter <= counter+1;
end process;
process(counter(1), counter(4))
begin
report "counter(1)'event=" & boolean'image(counter(1)'event) & "
counter(1)=" & std_ulogic'image(counter(1)) & " counter(1)'last_value="
& std_ulogic'image(counter(1)'last_value);
if (counter(4) = '0') then
output <= '0';
elsif rising_edge(counter(1)) then
output <= (not counter(3)) and counter(2);
end if;
end process;
counter_1 <= counter(1);
process(counter_1, counter(4))
begin
report "counter_1'event=" & boolean'image(counter_1'event) & "
counter_1=" & std_ulogic'image(counter_1) & " counter_1'last_value=" &
std_ulogic'image(counter_1'last_value);
if (counter(4) = '0') then
output_1 <= '0';
elsif rising_edge(counter_1) then
output_1 <= (not counter(3)) and counter(2);
end if;
end process;
end;
********** END CODE ***********
Here are the reports from the ISIM log for the beginning of the time
period when counter(4) is '1' and the async reset in the process is not
asserted. As you can see, the 'last_value attribute value is incorrect
for all rising_edge(counter(1)) calls but correct for
rising_edge(counter_1).
The code runs correctly in ModelSim 10.1, producing identical results
for both function calls.
********** BEGIN ISIM LOG ***********
at 320 ns(1): Note: counter(1)'event=true counter(1)='0'
counter(1)'last_value='1' (/test_tb/).
at 320 ns(1): Note: s'event=true s='0' s'last_value='0' (/test_tb/).
at 320 ns(1): Note: counter_1'event=false counter_1='1'
counter_1'last_value='0' (/test_tb/).
at 320 ns(1): Note: s'event=false s='1' s'last_value='0' (/test_tb/).
at 320 ns(2): Note: counter_1'event=true counter_1='0'
counter_1'last_value='1' (/test_tb/).
at 320 ns(2): Note: s'event=true s='0' s'last_value='1' (/test_tb/).
at 360 ns(1): Note: counter(1)'event=true counter(1)='1'
counter(1)'last_value='0' (/test_tb/).
at 360 ns(1): Note: s'event=true s='1' s'last_value='1' (/test_tb/).
at 360 ns(2): Note: counter_1'event=true counter_1='1'
counter_1'last_value='0' (/test_tb/).
at 360 ns(2): Note: s'event=true s='1' s'last_value='0' (/test_tb/).
at 400 ns(1): Note: counter(1)'event=true counter(1)='0'
counter(1)'last_value='1' (/test_tb/).
at 400 ns(1): Note: s'event=true s='0' s'last_value='1' (/test_tb/).
at 400 ns(2): Note: counter_1'event=true counter_1='0'
counter_1'last_value='1' (/test_tb/).
at 400 ns(2): Note: s'event=true s='0' s'last_value='1' (/test_tb/).
********** END ISIM LOG ***********
Any ideas? Is this a legitimate bug or a hole in my understanding of
VHDL and simulation in general?
Urbite
when using ISIM to simulate some code that is part of an FPGA emulation
of an arcade game.
http://forum.gadgetfactory.net/index.php?/topic/1544-isim-is-driving-me-crazy/#entry10072
Since the code is likely a literal translation of the arcade game
schematic, some bits from a 5-bit slv counter are used as the async
reset and clock in a process. Don't be distracted by this
non-synchronous design practice, as this isn't the issue.
The issue is that the rising_edge() function wasn't working correctly.
After some investigation and simulation, a determination has been made
that in ISIM the 'last_value attribute isn't being properly evaluated
*inside* the function when the argument to rising_edge() is a bit from a
standard_logic_vector???
If the counter bit, counter(1), that is used as the clock is assigned to
the std_logic signal, counter_1, then the 'last_value attribute is
evaluated properly in the rising_edge() function call.
To test this a 2nd process is created using the counter_1 signal as the
clock. The rising_edge function source is copied from the Xilinx library
and modified to report the status of the incoming signal.
Here is the test bench which illustrates the problem.
********** BEGIN CODE ***********
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity test_tb is
end test_tb;
architecture behavior of test_tb is
function rising_edge (signal s : std_ulogic) return boolean is
begin
report "s'event=" & boolean'image(s'event) & " s=" &
std_ulogic'image(s) & " s'last_value=" & std_ulogic'image(s'last_value);
return (s'event and (to_x01(s) = '1') and
(to_x01(s'last_value) = '0'));
end;
signal output : std_logic := '0';
signal counter : std_logic_vector(4 downto 0) := (others => '0');
constant period : time := 20 ns;
signal counter_1 : std_logic;
signal output_1 : std_logic;
begin
process
variable counter_i : std_logic_vector(4 downto 0) := (others => '0');
begin
wait for period;
counter <= counter+1;
end process;
process(counter(1), counter(4))
begin
report "counter(1)'event=" & boolean'image(counter(1)'event) & "
counter(1)=" & std_ulogic'image(counter(1)) & " counter(1)'last_value="
& std_ulogic'image(counter(1)'last_value);
if (counter(4) = '0') then
output <= '0';
elsif rising_edge(counter(1)) then
output <= (not counter(3)) and counter(2);
end if;
end process;
counter_1 <= counter(1);
process(counter_1, counter(4))
begin
report "counter_1'event=" & boolean'image(counter_1'event) & "
counter_1=" & std_ulogic'image(counter_1) & " counter_1'last_value=" &
std_ulogic'image(counter_1'last_value);
if (counter(4) = '0') then
output_1 <= '0';
elsif rising_edge(counter_1) then
output_1 <= (not counter(3)) and counter(2);
end if;
end process;
end;
********** END CODE ***********
Here are the reports from the ISIM log for the beginning of the time
period when counter(4) is '1' and the async reset in the process is not
asserted. As you can see, the 'last_value attribute value is incorrect
for all rising_edge(counter(1)) calls but correct for
rising_edge(counter_1).
The code runs correctly in ModelSim 10.1, producing identical results
for both function calls.
********** BEGIN ISIM LOG ***********
at 320 ns(1): Note: counter(1)'event=true counter(1)='0'
counter(1)'last_value='1' (/test_tb/).
at 320 ns(1): Note: s'event=true s='0' s'last_value='0' (/test_tb/).
at 320 ns(1): Note: counter_1'event=false counter_1='1'
counter_1'last_value='0' (/test_tb/).
at 320 ns(1): Note: s'event=false s='1' s'last_value='0' (/test_tb/).
at 320 ns(2): Note: counter_1'event=true counter_1='0'
counter_1'last_value='1' (/test_tb/).
at 320 ns(2): Note: s'event=true s='0' s'last_value='1' (/test_tb/).
at 360 ns(1): Note: counter(1)'event=true counter(1)='1'
counter(1)'last_value='0' (/test_tb/).
at 360 ns(1): Note: s'event=true s='1' s'last_value='1' (/test_tb/).
at 360 ns(2): Note: counter_1'event=true counter_1='1'
counter_1'last_value='0' (/test_tb/).
at 360 ns(2): Note: s'event=true s='1' s'last_value='0' (/test_tb/).
at 400 ns(1): Note: counter(1)'event=true counter(1)='0'
counter(1)'last_value='1' (/test_tb/).
at 400 ns(1): Note: s'event=true s='0' s'last_value='1' (/test_tb/).
at 400 ns(2): Note: counter_1'event=true counter_1='0'
counter_1'last_value='1' (/test_tb/).
at 400 ns(2): Note: s'event=true s='0' s'last_value='1' (/test_tb/).
********** END ISIM LOG ***********
Any ideas? Is this a legitimate bug or a hole in my understanding of
VHDL and simulation in general?
Urbite