Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > VHDL > testbench procedure trouble

Reply
Thread Tools

testbench procedure trouble

 
 
Toby
Guest
Posts: n/a
 
      02-11-2005
Hi, I'm kinda new to this whole testbench thing. I have a procedure in
my testbench that looks something like this:

procedure SMP_READ
(
signal A_P_SMP_DATA_READ: out std_logic_vector(7 downto 0);
) is
begin

A_P_SMP_DATA_READ(7) <= A_SMP_DATA7;
A_P_SMP_DATA_READ(6) <= A_SMP_DATA6;
A_P_SMP_DATA_READ(5) <= A_SMP_DATA5;
A_P_SMP_DATA_READ(4) <= A_SMP_DATA4;
A_P_SMP_DATA_READ(3) <= A_SMP_DATA3;
A_P_SMP_DATA_READ(2) <= A_SMP_DATA2;
A_P_SMP_DATA_READ(1) <= A_SMP_DATA1;
A_P_SMP_DATA_READ(0) <= A_SMP_DATA0;

end SMP_READ;

Where A_SMP_DATA7, A_SMP_DATA6......A_SMP_DATA0 are signals assigned
for the entire testbench (between the component declarations and the
procedure declarations) as follows:

signal A_SMP_DATA0 : STD_LOGIC := 'L';
signal A_SMP_DATA1 : STD_LOGIC := 'L';
signal A_SMP_DATA2 : STD_LOGIC := 'L';
signal A_SMP_DATA3 : STD_LOGIC := 'L';
signal A_SMP_DATA4 : STD_LOGIC := 'L';
signal A_SMP_DATA5 : STD_LOGIC := 'L';
signal A_SMP_DATA6 : STD_LOGIC := 'L';
signal A_SMP_DATA7 : STD_LOGIC := 'L';

The problem is, A_P_SMP_DATA_READ(7..0) is not getting the values
assigned to it in the procedure. I can set a breakpoint (Aldec
Active-HDL) near the end of the procedure, and I run the cursor over
the A_P_SMP_DATA_READ(#) and the A_SMP_DATA#, and they just arent
equal. How can that even be? If I say A_P_SMP_DATA_READ(7) <=
A_SMP_DATA7; then shouldn't those two things be equal? Any ideas
would be greatly appreciated.

 
Reply With Quote
 
 
 
 
Mike Treseler
Guest
Posts: n/a
 
      02-11-2005
Toby wrote:
> Hi, I'm kinda new to this whole testbench thing. I have a procedure in

.. . .
> The problem is, A_P_SMP_DATA_READ(7..0) is not getting the values
> assigned to it in the procedure.


consider adding a synchronous wait to your procedure:

procedure tic is
begin
wait until rising_edge(tb_clk_s);
end procedure tic;

procedure SMP_READ is
begin
A_P_SMP_DATA_READ(7) <= A_SMP_DATA7;
A_P_SMP_DATA_READ(6) <= A_SMP_DATA6;
A_P_SMP_DATA_READ(5) <= A_SMP_DATA5;
A_P_SMP_DATA_READ(4) <= A_SMP_DATA4;
A_P_SMP_DATA_READ(3) <= A_SMP_DATA3;
A_P_SMP_DATA_READ(2) <= A_SMP_DATA2;
A_P_SMP_DATA_READ(1) <= A_SMP_DATA1;
A_P_SMP_DATA_READ(0) <= A_SMP_DATA0;
tic; -- wait after assignments to see changes
end SMP_READ;

-- Mike Treseler
 
Reply With Quote
 
 
 
 
Toby
Guest
Posts: n/a
 
      02-11-2005
I tried to add the tic thing, but it didnt seem to help. The procedure
posted earlier was simplified a bit. Here is the complete procedure
(including the tic call):

procedure SMP_READ
-- Timing taken from 'C50 datasheet
(constant A_SPACE: in character;
constant A_P_SMP_ADDR_TEMP: in std_logic_vector(2 downto 0);
signal A_TURBO: in std_logic;
signal A_SMP_RD_L, A_SMP_IS_L, A_SMP_DS_L, A_SMP_PS_L: out std_logic;
signal A_P_SMP_DATA_READ: out std_logic_vector(15 downto 0);
signal A_P_SMP_ADDR: out std_logic_vector(2 downto 0);
signal A_UPCLKOUT: in std_logic
) is
begin
A_P_SMP_ADDR <= A_P_SMP_ADDR_TEMP;
if(A_SPACE = 'I') then
A_SMP_IS_L <= '0';
elsif(A_SPACE = 'D') then
A_SMP_DS_L <= '0';
elsif(A_SPACE = 'P') then
A_SMP_PS_L <= '0';
end if;
-- tsu(AV-RDL)
if(A_TURBO = '0') then --turbo mode
wait for 10 ns;
else --slow mode
wait for 20 ns;
end if;
A_SMP_RD_L <= '0';
-- tw(RDL)
if(A_TURBO = '0') then --turbo mode
wait for 58 ns;
else --slow mode
wait for 88 ns;
end if;
A_P_SMP_DATA_READ(15) <= A_SMP_DATA15;
A_P_SMP_DATA_READ(14) <= A_SMP_DATA14;
A_P_SMP_DATA_READ(13) <= A_SMP_DATA13;
A_P_SMP_DATA_READ(12) <= A_SMP_DATA12;
A_P_SMP_DATA_READ(11) <= A_SMP_DATA11;
A_P_SMP_DATA_READ(10) <= A_SMP_DATA10;
A_P_SMP_DATA_READ(9) <= A_SMP_DATA9;
A_P_SMP_DATA_READ( <= A_SMP_DATA8;
A_P_SMP_DATA_READ(7) <= A_SMP_DATA7;
A_P_SMP_DATA_READ(6) <= A_SMP_DATA6;
A_P_SMP_DATA_READ(5) <= A_SMP_DATA5;
A_P_SMP_DATA_READ(4) <= A_SMP_DATA4;
A_P_SMP_DATA_READ(3) <= A_SMP_DATA3;
A_P_SMP_DATA_READ(2) <= A_SMP_DATA2;
A_P_SMP_DATA_READ(1) <= A_SMP_DATA1;
A_P_SMP_DATA_READ(0) <= A_SMP_DATA0;
--tw(RDL) continued
wait for 1 ns;
A_SMP_RD_L <= 'H';
if(A_SPACE = 'I') then
A_SMP_IS_L <= 'H';
elsif(A_SPACE = 'D') then
A_SMP_DS_L <= 'H';
elsif(A_SPACE = 'P') then
A_SMP_PS_L <= 'H';
end if;
A_P_SMP_ADDR <= "LLL";

tic(A_UPCLKOUT);

end SMP_READ;


As you can see, there are lots of IF and WAIT statements in there too.
I'm wondering if there is some rule or something I have broken about
using WAIT and IF statements? Is that procedure even normal looking,
or is there a better way of doing what I am trying to do? (I am trying
to have a procedure that simulates all the signals and associated
timing from a microprocessor read cycle). Thank you thank you to
anyone who has any suggestions!

 
Reply With Quote
 
Mike Treseler
Guest
Posts: n/a
 
      02-11-2005
Toby wrote:
> I tried to add the tic thing, but it didnt seem to help. The procedure
> posted earlier was simplified a bit. Here is the complete procedure
> (including the tic call):


Yikes. Consider a synchronous testbench
using tic;tic;tic; instead of wait for 30ns;

Do you have a clock and reset process working
out through to the uut in and out signals?
Get this working first.

Do you have some base process wrapped around
the procedure declarations run the show?


-- Mike Treseler

___________________
main : process is
<declarations>
constant reps : natural := 16;
begin -- process main
init;
for i in 1 to reps loop
timed_cycle;
end loop;
for i in 1 to reps loop
handshake_cycle;
end loop;
coda;
end process main;
end architecture sim;
 
Reply With Quote
 
Toby
Guest
Posts: n/a
 
      02-14-2005
Hi Mike,

a synchronous testbench using tic; tic; tic, huh? Holy crap! I never
thought of that! Thank you. I do quite a bit of VHDL, and I
definitely understand the importance of synchronizing stuff, I just
never thought to do it in a testbench. Is there anything wrong with
doing tic = 1ps, and doing for loops like a thousand times? Because I
have some stuff that has to be fractions of a nanosecond, and some
stuff the is tens or hundreds of nanoseconds. And I want everything in
my testbench to use the same tic process, right? Tic should be a
process, not a procedure, right?

I do have a clock and reset working throughout the uut.

I dont understand your last comment about having a process wrapped
around the procedure declarations. A procedure can go in a process? I
didnt know that. You dont mean I need a single process for the whole
testbench, do you? I've got a lot of stuff going on in this testbench,
and a lot of it can happen at the same time (i.e. completely seperate
logic in the uut). So I think I need seperate processes for that.
Well, as you can see, any general type of advice about testbenches
would be very helpful.

Anyway, thank you so much! I will work on using that tic clock.

-Toby

 
Reply With Quote
 
Toby
Guest
Posts: n/a
 
      02-14-2005
Hi Mike,

a synchronous testbench using tic; tic; tic, huh? Holy crap! I never
thought of that! Thank you. I do quite a bit of VHDL, and I
definitely understand the importance of synchronizing stuff, I just
never thought to do it in a testbench. Is there anything wrong with
doing tic = 1ps, and doing for loops like a thousand times? Because I
have some stuff that has to be fractions of a nanosecond, and some
stuff the is tens or hundreds of nanoseconds. And I want everything in
my testbench to use the same tic process, right? Tic should be a
process, not a procedure, right?

I do have a clock and reset working throughout the uut.

I dont understand your last comment about having a process wrapped
around the procedure declarations. A procedure can go in a process? I
didnt know that. You dont mean I need a single process for the whole
testbench, do you? I've got a lot of stuff going on in this testbench,
and a lot of it can happen at the same time (i.e. completely seperate
logic in the uut). So I think I need seperate processes for that.
Well, as you can see, any general type of advice about testbenches
would be very helpful.

Anyway, thank you so much! I will work on using that tic clock.

-Toby

 
Reply With Quote
 
Mike Treseler
Guest
Posts: n/a
 
      02-14-2005
Toby wrote:

> a synchronous testbench using tic; tic; tic, huh? Holy crap! I never
> thought of that! Thank you. I do quite a bit of VHDL, and I
> definitely understand the importance of synchronizing stuff, I just
> never thought to do it in a testbench. Is there anything wrong with
> doing tic = 1ps, and doing for loops like a thousand times? Because I
> have some stuff that has to be fractions of a nanosecond, and some
> stuff the is tens or hundreds of nanoseconds. And I want everything in
> my testbench to use the same tic process, right? Tic should be a
> process, not a procedure, right?


No the other way around.

I use one clock/reset generator process (see tb_clk below)
and one main process. The main process is constructed
out of procedure calls. The lowest level procedure
(i.e. the top declaration) is tic, which waits for
one system clock period. The other procedures
call tic once, at the end, or not at all.
All of the procedure calls, other than tic;
execute in zero simulation time, so no, I don't
need a 1 ps clock period. The clock is strictly
for synchronization of uut stimulus and verification.

> I do have a clock and reset working throughout the uut.


That's a good start.

> I dont understand your last comment about having a process wrapped
> around the procedure declarations. A procedure can go in a process?


The procedure *code* (declaration) for "do_this"
is placed before the BEGIN of the
main process *and* before any other.
procedures that call "do_this"

The procedure *call* "do_this;"
must be placed either in a
process or procedure after the BEGIN.

> I didnt know that. You dont mean I need a single process for the whole
> testbench, do you?


I use at least two, tb_clk and main. In my last posting
I showed the main process calls of a real testbench.
All of the details are in the procedures that I cut out
from the line <declarations>. When I get back from
Utah, I will clean up a full example for the group.

> I've got a lot of stuff going on in this testbench,
> and a lot of it can happen at the same time (i.e. completely seperate
> logic in the uut). So I think I need seperate processes for that.


Yes sometimes you do.

> Anyway, thank you so much! I will work on using that tic clock.


You are welcome. Good luck

-- Mike Treseler


--____________________________________________
tb_clk : process is
constant clk_cy : time := 10 ns;
constant rst_time : time := 100 ns;
begin
clk_s <= '0';
if now < rst_time then
rst_s <= '1'; -- rst once with clk running

else
rst_s <= '0'; -- then low forever
end if;
wait for clk_cy/2; -- clk rising
clk_s <= '1';
wait for clk_cy/2; -- clk falling
if done_s then
wait; -- Stop clock
end if;
end process tb_clk;
-------------------------------------------------------------------------------
 
Reply With Quote
 
Paul Uiterlinden
Guest
Posts: n/a
 
      02-15-2005
Mike Treseler wrote:
>
> --____________________________________________
> tb_clk : process is
> constant clk_cy : time := 10 ns;
> constant rst_time : time := 100 ns;
> begin
> clk_s <= '0';
> if now < rst_time then
> rst_s <= '1'; -- rst once with clk running
> else
> rst_s <= '0'; -- then low forever
> end if;
> wait for clk_cy/2; -- clk rising
> clk_s <= '1';
> wait for clk_cy/2; -- clk falling
> if done_s then
> wait; -- Stop clock
> end if;
> end process tb_clk;
> -------------------------------------------------------------------------------


I would not combine the generation of the clock and reset:

CONSTANT clk_cy : delay_length := 10 ns;
CONSTANT rst_time : rst_time := 10*clk_cy;

SIGNAL clk_s : std_ulogic := '0';
SIGNAL rst_s : std_ulogic;
SIGNAL done_s : boolean;

clk_gen: clk_s <= '0' WHEN done_s ELSE NOT clk_s AFTER clk_cy/2;
rst_gen: rst_s <= '1', '0' AFTER rst_time;

Nice and short, just two lines. No needless evaluation of "now <
rst_time". Surely it would make not much of a difference in simulation
time, but I find my version better readable. Of course, this is a
personal thing.

The initial value of clk_s really is needed, or otherwise the clock
always would be 'X'. Also note that by chosing '0' as initial value (in
contrast to '1'), rst_s changes value at the falling edge of the clock
(as in your example).

Paul.
 
Reply With Quote
 
Toby
Guest
Posts: n/a
 
      02-15-2005
Can somebody either post, or tell me EXACTLY where to find a nice, BIG,
COMPLETE, good, testbench example with all this stuff you guys are
talking about? Several examples would be even better, but all this
stuff you guys are showing me is just pieces, and I'm having a little
trouble seeing the overall picture of a good testbench design. Thanks!

-Toby

 
Reply With Quote
 
Mike Treseler
Guest
Posts: n/a
 
      02-15-2005
Toby wrote:
> Can somebody either post, or tell me EXACTLY where to find a nice, BIG,
> COMPLETE, good, testbench example with all this stuff you guys are
> talking about? Several examples would be even better, but all this
> stuff you guys are showing me is just pieces, and I'm having a little
> trouble seeing the overall picture of a good testbench design. Thanks!


My comments are incomplete, but here you go:

http://home.comcast.net/~mike_treseler/

-- Mike Treseler
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
procedure as argument in procedure AlexWare VHDL 2 10-23-2009 09:14 AM
Are there any Modelsim hooks to allow testbench code to figure out procedure call stack? Andrew FPGA VHDL 7 11-01-2008 07:26 PM
'Procedure or function <stored procedure name> has too many arguments specified',,,ARGH! Mike P ASP .Net 0 06-19-2006 01:19 PM
testbench procedure trouble Toby VHDL 0 02-11-2005 04:09 PM
How to drive record fields from procedure AND testbench? Joe Vanderwall VHDL 11 05-09-2004 07:40 PM



Advertisments