Clock Edge notation

Jonathan Bromley wrote:
Note, however, that each concurrent assignment introduces a
delta-cycle delay (roughly the same as the delay between executing a
nonblocking assignment in Verilog and its signal being updated). By
contrast, the Verilog continuous assignment effectively uses blocking
assignment and introduces no delay whatsoever (unless you specify
one, of course). This is VERY important if you try to create gated
clocks.
Someone creating gated clocks (hopefully) knows that care is needed or
their synthesis results won't work. The real "gotcha"s, IMHO, happen
when you run a clock through a "wire" for some reason.

I've never been 100% clear on just when delta delays get introduced, so
someone please tell me I get something wrong in what follows.

Connections made during instantiation via a port map do not introduce a
delta delay but connections inside an architecture, even a "wire" like
"a<=b" do. A result of this is that you have to be careful about some
kinds of structures that may make sense from a structured
programming/code re-use viewpoint.

In particular, be careful of using generics and generates to choose
which input is used as a clock. e.g.:

if generic_use_clock_a generate
module_clock <= input_clock_a;
end generate;
if generic_use_clock_b generate
module_clock <= input_clock_b;
end generate;

This kind of thing adds a delta delay to your module's clock. The
consequence of this is your clocked processes may now be scheduled at
the same time as inputs that are clocked outputs of other modules. This
results in a race condition with indeterminate results since the order
of execution of events with identical deltas is left up to the
simulator. I've seen cases with multiple inputs from another module
where some inputs will be treated as "arriving" at a process before the
clock, and others after. Even more interesting is that this before/after
order may change following a recompile. The consequence is a debugging
nightmare.
--
Tim Hubberstey, P.Eng. . . . . . Hardware/Software Consulting Engineer
Marmot Engineering . . . . . . . VHDL, ASICs, FPGAs, embedded systems
Vancouver, BC, Canada . . . . . . . . . . . http://www.marmot-eng.com
 
On Fri, 01 Apr 2005 19:01:57 GMT, Tim Hubberstey <bogus@bogusname.com>
wrote:

Jonathan Bromley wrote:
Note, however, that each concurrent assignment introduces a
delta-cycle delay (roughly the same as the delay between executing a
nonblocking assignment in Verilog and its signal being updated). By
contrast, the Verilog continuous assignment effectively uses blocking
assignment and introduces no delay whatsoever (unless you specify
one, of course). This is VERY important if you try to create gated
clocks.

Someone creating gated clocks (hopefully) knows that care is needed or
their synthesis results won't work. The real "gotcha"s, IMHO, happen
when you run a clock through a "wire" for some reason.

I've never been 100% clear on just when delta delays get introduced, so
someone please tell me I get something wrong in what follows.
Just about everything you say agrees with my understanding, except...

This kind of thing
[ internal_clock <= source_clock; ]
adds a delta delay to your module's clock.
Yes.

consequence of this is your clocked processes may now be scheduled at
the same time as inputs that are clocked outputs of other modules.
I'm not quite sure what you mean here - perhaps I can rephrase it:
"your clocked processes are now scheduled to run in a delta cycle
when clocked outputs of other modules have already been updated".
A VHDL delta cycle proceeds in two completely separate phases
that absolutely do NOT overlap: updating of signals (which may in
turn cause sensitive processes to bee scheduled for execution in
this or future deltas), and execution of processes (which, of
course, may schedule new signal updates in future deltas).

This
results in a race condition with indeterminate results since the order
of execution of events with identical deltas is left up to the
simulator.
I simply don't understand this. I absolutely agree that the
scenario you describe will give results that are different from
what you wanted, and indeed that it can give rise to a synthesis/
simulation mismatch. But I cannot see how it is indeterminate.
The two-phase delta cycle essentially forbids that.

You are right that "order of execution of events with identical
deltas" (i.e. processes ready for execution in the same delta
cycle) is indeterminate. But regardless of their order of
execution, all those processes will see the values of signals
exactly as they were at the end of the current delta's
signal-update phase. No updating of signals takes place
during the process-execution phase, so there can be no
indeterminacy - unlike Verilog, in which blocking assignment
can update "signals" during the execution of a single process.

I've seen cases with multiple inputs from another module
where some inputs will be treated as "arriving" at a process before the
clock, and others after.
Sure; it depends how many signal assignments those signals have
been through on the way. In VHDL it's very common to have an
internal signal in a module that is finally assigned to an
output of the module using continuous assignment (because it's
impossible to read "out" ports). Such a signal will arrive
at its "process(clock)" destination TWO deltas after the
clock edge that updated it. So a one-delta delay in the second
block's clock will not hurt for that signal, but would give bad
behaviour for a signal that was directly assigned on the
original clock edge.

Even more interesting is that this before/after
order may change following a recompile.
In Verilog yes; in VHDL, no way. Find me an example and I'll
eat humble pie, but I reckon I'm on safe ground unless EITHER
(a) you're comparing a gate-level sim with an RTL sim, OR
(b) you used shared variables or files in a dodgy way.

Cheers

--
Jonathan Bromley
 
"genlock" <genlocks@gmail.com> wrote in message
news:1112393343.667330.208180@l41g2000cwc.googlegroups.com...

Does anybody have any idea about dithering?
I have a few. What do you want to do.
If you're worried about dropping bits.
you can add the dropped bits in on the
next sample. That is simple and works well for
video, and probably many other signals.

Ulichney goes into dithering in some detail.

http://www.amazon.com/exec/obidos/tg/detail/-/0262210096/qid=1112397759/sr=8-1/ref=pd_csp_1/103-8033715-0505409?v=glance&s=books&n=507846
 
genlock wrote:
Yes I am actually truncating a 48 bit value to 24 bits and hence am
losing the last 24 bits information of audio.....
24 bits is already 144 dB !
Are you sure you lose a lot of useful information ?
 
fpgawizz wrote:
I am using the following code to write some contents to an external memory.
a data_ready signal is sent to my mem controller to do the write.the
problem i have here is that i want my data to go into addr 0 through
5..instead i find its there in address 1 through 6..i am not sure where i
am introducing this offset..i do have a counter that counts up to each mem
location..
i am pasting my code here..am i doing the counting the wrong way? thanks
("N" is my address counter)
I already suggested that you should check the design intention
when you test a signal right after having assigned it in a process.
The code, for a VHDL beginner, is misleading since the actual
change only occurs later...
RE your immediate concern, if the data consumer reacts synchronously,
there is a chance he will catch the incremented address since the address
(N) does change in the next clock cycle after Write enable is set.
Maybe you storage part is assuming the address remains stable after the
wr=1 cycle ?

If you simulate your design, you should be able to see and understand
what happens.

Bert
 
In message <1112400734.606976.260850@o13g2000cwo.googlegroups.com>
"genlock" <genlocks@gmail.com> wrote:

Yes I am actually truncating a 48 bit value to 24 bits and hence am
losing the last 24 bits information of audio.....

So I would like to do dithering
Whatever ADC you use, or whatever analogue electronics you have in front
of the ADC, does all the dithering you will ever need.

Dave
 
Taras_96 wrote:

[many excellent questions omitted]

Finally, is there a use of variables in synthesisable VHDL at RTL?
Yes.
Process variables allow me to describe
a complex logic operation sequentially.
This type of description is easy for me
to write now and to understand later.

Suppose I want to describe a complex logic
operation, let's say shift left,
followed by a mask inversion,
then add 42 -- all in one clock tick.
With variables (or blocking assignments)
I can just say exactly that in three statements and
synthesis will work out the details very efficiently.
While I could work out the details myself
at the signal, gates and flops level, the
resulting description would likely a require
a simulation run to understand.

Signal assignments (or non-blocking assignments)
handle the job of transferring the needed results to
the entity port or architecture signal.

See
http://www.designabstraction.co.uk/Articles/Advanced%20Synthesis%20Techniques.htm
for a good explanation by Ian Lang of variable/blocking assignments
for synthesis with VHDL and verilog examples.

See
http://home.comcast.net/~mike_treseler/uart.vhd
for my take on one of Ian's VHDL examples.


-- Mike Treseler
 
On 2 Apr 2005 18:17:17 -0800, "Taras_96" <tagas96@hotmail.com> wrote:

Hi everyone

Thanks for your replies. Jonathan, what I meant by saying "concurrent
is a bad description" was that concurrent was a bad word to use to
describe the mechanims of the assignment (not that its not useful:)) -
concurrent means to me that it happens at the same time,
Curious. I (and, I think, most people) think of "concurrent" to
mean "at the same time as other things". Your interpretation
would be better phrased as "immediate" or "instantaneous", no?
VHDL concurrent signal assignments are concurrent with all
such other concurrent assignments, and all other processes.

"the Verilog continuous assignment effectively uses
blocking assignment and introduces no delay whatsoever (unless you
specify one, of course). "

In programming verilog, I viewed continuous assignments as assignments
that were 'always true'
Fair enough, but of course in simulation that effect is achieved
by evaluating the continuous assignment only whenever its
contributing inputs change.

at all points of the simulation cycle.
what do you mean by this? It makes no sense to me. If I write
(in Verilog)

assign a = b;

then there is a point in the simulation cycle when 'b' has
changed, but 'a' has not yet changed. It doesn't matter; you
can't make any effective use of it; but it happens.

Perhaps you mean the Verilog blocking assignment?
No. I'm prone to typographical errors like everyone else,
but this time I said exactly what I meant.

Also, as I understand it the issue with clock gating is that it often
involves signal assignment between clocks:

clock_a<=clock_b

This introduces a delta delay between clock_a and clock_b

Could someone provide an example of this happening?
process (clock_a) begin
if rising_edge(clock_a) then
FF1 <= d; -- FF1 is delta-delayed relative to clock_a
end if;
end process;

clock_b <= clock_a; -- clock_b is delta-delayed

process (clock_b) begin
if rising_edge(clock_b) then
FF2 <= FF1; -- OOPS: here we read the UPDATED value of FF1
end if;
end process;


I agree with Jonathan about the race conditions not being possible
because of the non-overlapping signal assignment & event processing
stages (not because VHDL is my area of expertise :) its intuitive to me
I suppose)
Hmmm. How "intuitive" do you find Verilog's simulation model? ;-)
--
Jonathan Bromley
 
dwerdna wrote:

Not having thought it was necessary to use a dual port ram until now I
was after a bit of advice.. I'm getting a few warnings on ModelSim,
and though I dont think I'm doing anything critically wrong I would
like to know if it can be improved.
Dual port RAM is not really a VHDL - for beginners topic.
Consider trying a design using registers first.

Im targetting a Spartan 2E, and instantiating ramb4_s8_s8
I have a sampler which updates a RAM addr every second. My RAM is 64
addresses deep, therefore storing the previous minutes results which
the CPU can retrieve and graph at its leisure.
Sounds you could get by with
one read port and one write port.
This can be inferred from a vhdl template,
and requires no arbitration.
http://groups-beta.google.com/groups?q=vhdl+mem_type+dual+port

-- Mike Treseler
 
On 4 Apr 2005 00:14:45 -0700, "Neo" <zingafriend@yahoo.com> wrote:

verilog is widely prevalent in asic design world and is the language of
choice. But in FPGA design community both are widely used.
It isn't that simple; there are many serious commercial ASIC/custom
outfits that use VHDL.

Sadly, though, it is true that VHDL simply doesn't seem to have the
momentum that Verilog has. I know that Jim Lewis and all the
great people involved in VHDL-200x are working hard to rectify
that, but in the last analysis the only sensible approach for
an individual engineer is: become bilingual in VHDL and Verilog.
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL, Verilog, SystemC, Perl, Tcl/Tk, Verification, Project Services

Doulos Ltd. Church Hatch, 22 Market Place, Ringwood, BH24 1AW, UK
Tel: +44 (0)1425 471223 mail:jonathan.bromley@doulos.com
Fax: +44 (0)1425 471573 Web: http://www.doulos.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 
Did you try:
either:

component CLKDLL
generic (CLKDV_DIVIDE : real);
port (
CLKIN, CLKFB, RST : in STD_LOGIC;
CLK0, LOCKED : out std_logic
);
end component;


or:

clkdll_1 : CLKDLL
generic map (CLKDV_DIVIDE => 2.5) -- for simulation and PAR
port map (CLKIN => CLKIN, CLKFB => CLK, RST => gnd,
CLK0 => CLK0,
CLK90 => open,
CLK180 => open,
CLK270 => open,
CLK2X => open,
CLKDV => CLKDV, LOCKED => LOCKED);


Herb T wrote:
VHDL arch, clkdll_divide doesn't use all the ports of the CLKDLL
component. For instance, component CLKDLL ports CLK90, CLK180, CLK270,
and CLK2X are not mapped. The XST synthesizer complains about these
being unconnected. Is there some way I can assign these ports (to dead
logic or otherwise) in order to resolve the XST warning messages?
Thanks,
-HT

library ieee;
use ieee.std_logic_1164.all;

entity clkdll_divide is
port (
clk_in : in std_logic;
clk_out : out std_logic
);
end clkdll_divide;


architecture Behavioral of clkdll_divide is

component CLKDLL
generic (CLKDV_DIVIDE : real);
port (
CLKIN, CLKFB, RST : in STD_LOGIC;
CLK0, CLK90, CLK180, CLK270, CLK2X, CLKDV, LOCKED : out std_logic
);
end component;

component IBUFG
port (
I : in std_logic;
O : out std_logic
);
end component;

component BUFG
port (
I : in std_logic;
O : out std_logic
);
end component;


signal CLKIN, CLK : std_logic;
signal CLK0, CLKDV : std_logic;
signal gnd, LOCKED : std_logic := '0';


begin

ibufg_1 : IBUFG port map (I => clk_in, O => CLKIN);

clkdll_1 : CLKDLL
generic map (CLKDV_DIVIDE => 2.5) -- for simulation and PAR
port map (CLKIN => CLKIN, CLKFB => CLK, RST => gnd,
CLK0 => CLK0, CLKDV => CLKDV, LOCKED =
LOCKED);

clk0_bufg_1 : BUFG port map (I => CLK0, O => CLK);
clkdv_bufg_1 : BUFG port map (I => CLKDV, O => clk_out);


end Behavioral;

Analyzing Entity <clkdll_divide> (Architecture <behavioral>).
WARNING:Xst:766 - D:/design/ISE/Tutorial/clkdll_divide.vhd line 49:
Generating a Black Box for component <IBUFG>.
WARNING:Xst:753 - D:/design/ISE/Tutorial/clkdll_divide.vhd line 51:
Unconnected output port 'CLK90' of component 'CLKDLL'.
WARNING:Xst:753 - D:/design/ISE/Tutorial/clkdll_divide.vhd line 51:
Unconnected output port 'CLK180' of component 'CLKDLL'.
WARNING:Xst:753 - D:/design/ISE/Tutorial/clkdll_divide.vhd line 51:
Unconnected output port 'CLK270' of component 'CLKDLL'.
WARNING:Xst:753 - D:/design/ISE/Tutorial/clkdll_divide.vhd line 51:
Unconnected output port 'CLK2X' of component 'CLKDLL'.
WARNING:Xst:766 - D:/design/ISE/Tutorial/clkdll_divide.vhd line 51:
Generating a Black Box for component <CLKDLL>.
WARNING:Xst:766 - D:/design/ISE/Tutorial/clkdll_divide.vhd line 56:
Generating a Black Box for component <BUFG>.
WARNING:Xst:766 - D:/design/ISE/Tutorial/clkdll_divide.vhd line 57:
Generating a Black Box for component <BUFG>.
Entity <clkdll_divide> analyzed. Unit <clkdll_divide> generated.
 
Herb T wrote:
Folks,
I was talking to some electronics buffs on a chat channel, and they
were telling me that only Universities and DOD uses VHDL. I thought it
was hogwash, but wanted to find out if many commercial companies are
using the language earnestly. The resident HDL expert was saying
verilog is the language of choice these days. Is that true? I
personally prefer VHDL because the I already have too many reference
materials on how to use it.
I was somewhat surprised when I received Xilinx EDK, and all the cores
included with it (numbering 50-75 I would say) were written in VHDL. I
was even more surprised when I discovered that all the bit vectors were
written as std_logic_vector(0 to n) (instead of downto)!
 
It's just an example. It can be further optimized.
It's a parallel full speed solution...

-- Divide a 24 bits unsigned by 1.122
-- Author : Bert Cuzeau
-- not overly optimzed (under 200 LCs)

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;

-- ---------------------------------------
Entity DIVBYR is -- Divide a 24 bits by 1.122
-- ---------------------------------------
Port ( Clk : In std_logic; -- Main System Clock
Rst : In std_logic; -- Asynchronous reset, active high
D : in unsigned (23 downto 0); -- use std_logic_vector !
Q : out unsigned (23 downto 0) -- use std_logic_vector !
); --
end;

-- ---------------------------------------
Architecture RTL of DIVBYR is
-- ---------------------------------------
begin

process (Rst,Clk)
begin
if Rst='1' then
Q <= (others=>'0');
elsif rising_edge (Clk) then
Q <= to_unsigned( (to_integer(D) * 7301 / 8192 ),24);
end if;
end process;

end RTL;


genlock wrote:

Bert,
Thankyou very much for this technique.

I want the synthesizer to work and it is working when using the '/'
operator with powers of 2.

What library do I need to add in order to use the function: to_integer?
I need to convert the resultant integer back to a bit vector.

I am using the functions conv_integer and conv_std_logic_vector. I have
added the library
ieee.std_logic_signed.vhd for these functions.

Can you explain where I would need an accumulator and shift register...
I am using Xilinx ISE and coding in VHDL....I dont understnad the RTL
part you are talking about...

I am going to try this solution and see how it works....

Thankyou
 
Herb T wrote:


I was talking to some electronics buffs on a chat channel, and they
were telling me that only Universities and DOD uses VHDL. I thought it
was hogwash, but wanted to find out if many commercial companies are
using the language earnestly. The resident HDL expert was saying
verilog is the language of choice these days. Is that true? I
personally prefer VHDL because the I already have too many reference
materials on how to use it.
Most of the american companies use Verilog while in Europe VHDL is common.

I prefer VHDL, too, because
* it is strongly typed and typing errors, that did not lead to syntax
errors are detected more often
* it avoids all these ugly cases mentioned in "verilog coding styles,
that kill" (Clifford Cummings
http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA.pdf )
* it protects better from writing to one signal from different processes
* signed / unsigned arithmetics are defined more preceisely (with the
disadvantage of having all these type conversions)
* handling of multi-dimensional vectors is possible and handling of
two-dimensional vectors is much easier
* generic parameters and generate statements are easier to use than
Verilog parameters and defines
* finally: VHDL code it better human-readable - IMHO ;-)

Ralf
 
dwerdna wrote:

Since I very well could still be in the beginners group, could you
explain what the templates are all about please?? I had already looked
over the posts which come up under your suggested search string,
previous to my original question, and most of those posts are talking
about instantiating primitives, which is what I am doing..
And others show template inference.
Synthesis manuals also show RAM templates.

Is there any particular issue with having the same clock - with no
phase difference - going into both ports of the RAM??
No. Make sure it is on a global net.

What is the worst thing that will happen if I am referencing the same
address, but ONLY writing to one address at that time?? From the
Xilinx info I would suggest that I will just get an unknown value on my
read port..
I don't know. Consider arbitration.


-- Mike Treseler
 
dwerdna wrote:
What is the worst thing that will happen if I am referencing the same
address, but ONLY writing to one address at that time?? From the
Xilinx info I would suggest that I will just get an unknown value on my
read port..
The error message generated when this happens in VHDL simulation says
(for example):

# ** Warning: Memory Collision Error on RAMB16_S4_S4: at simulation
time 92425 ns.
# A read was performed on address fff (hex) of port B while a write was
requested to the same address on Port A The write will be successful
however the read value is unknown until the next CLKB cycle
# Time: 92425 ns Iteration: 2 Instance:
/bd_top/uut/data_buf_e/ram2_e/art_ram_g__7/art_ram_e

So there you go. One of the most detailed warning messages I have ever
seen ;)
 
Taras_96 wrote:

I was hoping someone could tell me if the following analysis was
correct, as I'm a bit rusty?
Consider getting a simulator so that
you can work through your own examples.
A simulator is faster and more
accurate than a newsgroup.

I think what Mike is suggesting is that, using his example:
No. I'm afraid you missed the point.

The example was meant to be a small
part of the "update_process_regs" portion
of a synchronous process structured like:

clockedLogic : process (clock, reset) is
if reset = '1' then
init_all_regs_and_ports;
elsif rising_edge(clock) then
init_fast_regs; -- init dynamic registers every clk
update_process_regs;
update_output_ports;
end if;
end process clockedLogic;

the code fragment might look like

reg_v := in_port; -- get a byte
reg_v := shift_left(reg_v, 1 ); -- shift left
reg_v := reg_v xor mask_c; -- mask inversion
reg_v := reg_v + 42; -- add 42

My point was that variable (blocking) assignments
can make code that is very easy to understand compared
to an equivalent schematic or netlist of gates and flops.

3) If you wish to model synchronous logic, use an always@(posedge
clock) block with non-blocking assignments.
This is the conventional wisdom.
I disagree. I prefer to use signal (non-blocking)
assignments _only_ for the purpose of transferring
a variable (register) value to a port or to
another process.

-- Mike Treseler
 
"hongyan" <hy34@njit.edu> wrote in message
news:1112658006.455779.39610@f14g2000cwb.googlegroups.com...
The following is my source code;
-----------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;

entity EGC is
generic(M : natural := 4);
Port ( input1 : in std_logic_vector(15 downto 0);
output1 : out std_logic_vector(15 downto 0));

end EGC;

architecture Behavioral of EGC is
subtype vector16 is std_logic_vector(15 downto 0);
type vector_M_16_Out is array(0 to M) of vector16;
signal out1: vector_M_16_Out;


begin

out1(0) <= input1;

proc0 : process(out1, input1)
begin
--out1(0) <= input1;
for i in 1 to M loop
out1(i) <= 2+out1(i-1);
end loop;
end process proc0;

output1 <= out1(M);
end Behavioral;
-----------------------------------------------

It is very strange that it doesn't work this way. All the signals
out1(0-4) are xxxx. But if I put "out1(0) <= input1;" into the
process, it works fine.
I can't understand this because the for loop in the process won't
modify the out1(0). Did I miss somthing? Any suggestions will be
appreciate.

snip

I don't think Out1 should be in your process sensitivity list.
Everytime input1 changes proc0 is run, and at the same time Out0 is
undefined as although the inputs have been set, the outputs haven't been
assigned yet. Thus all the additions in the process are undefined, and will
generate Xs.

With the statement inside the process, Out1(0) is defined at the end of the
first iteration, and since you have Out1 in your process sensitivity list
the process will repeat until the additions have propagated to Out1(M) and
Out1 no longer changes.

Instead try:

out1(0) <= input1;

gen0:
for i in 1 to M generate
out1(i) <= 2+out1(i-1);
end generate;

output1 <= out1(M);

which to me seems more elegant.

Someone correct me if I'm wrong - I've only started coding vhdl (since uni)
last week. :)

Ross
 
"genlock" <genlocks@gmail.com> wrote in message
news:1112400734.606976.260850@o13g2000cwo.googlegroups.com...
Yes I am actually truncating a 48 bit value to 24 bits and hence am
losing the last 24 bits information of audio.....

So I would like to do dithering
I'm not an audio guy, but I would have thought
that 24 bits would have been fine.
Can you hear anything more?

Last time I was working on audio was 1976,
and 14 bits was the best we could do.

If you have a dedicated adder at the output
(say 48 bits but that's adding overkill to
overkill) and take the most significant 24 bits out
to go to your dac, you need to take the dropped
(least significant) 24 bits, delay them in a register,
and feed the output of the register, appropriately
sign extended, back to the input of the adder,
where it is summed with the full 48 bits of the
next sample. It will spectrally shape your noise
so it is less objectionable to those with super-human
hearing.
 
On 5 Apr 2005 08:09:28 -0700, "Salman"
<salmanisheikh@gmail.com> wrote:

How do I compactly replace the group of statements like this all over
the place in a large testbench and a similar one for a regrd? Do I use
a function or procedure? I thought both of those could not have wait
statements in them?

regwr <= '1';
wait for 75 ns;
regwr <= '0';
wait for 75 ns;
Use a procedure.

Procedures can have wait statements; functions cannot.

If the procedure is declared locally within the process that
uses it, you can write from it to signals that do not appear
in its parameter list. This is often convenient for simple
jobs. For example, your code could be a simple parameterless
procedure...

TestGenerator: process

procedure PulseRegWr is
begin
regwr <= '1';
wait for 75 ns;
regwr <= '0';
wait for 75 ns;
end;

begin
...
PulseRegWr;
...
end process;

However, if you choose to put the procedure into
a package or into the architecture, then any signals it
drives should be passed to it as parameters of "signal"
class. For example, your procedure could be coded thus:

procedure PulseStrobe(signal WrStb: out std_logic) is
begin
WrStb <= '1';
wait for 75 ns;
WrStb <= '0';
wait for 75 ns;
end;

and you might call it thus:

...
PulseStrobe(regwr);
...

The advantage of this is that you may be able to use the same
procedure to do more than one thing, by getting it to work
on different signals. The downside is that it is of course
more verbose to call the procedure, because you must pass it
all the signals it will manipulate.

Consider designing your procedures at a somewhat higher level
of abstraction than merely twiddling a signal. For example,
you could create a "write a register" procedure with two
parameters - one to specify which register is to be written,
and the second to specify the data value it should write.

Consider also adding parameters to configure the time
delays that the procedure body will use. You can pass
parameters of type "time" to a procedure, and you can use
named association of procedure parameters. When you carry
this idea to its conclusion, you can end up with a
"transaction level" view of your testbench in which your
main stimulus generator code does stuff like...

Stimulus: process
constant ControlRegAdrs: std_logic_vector := X"3FE8";
...
procedure WriteToRegister (...) is ...;
begin
...
WriteToRegister (
address => ControlRegAdrs,
data => X"AA",
setupTime => 10 ns,
strobeTime => 20 ns,
holdTime => 5 ns
);
...

This is much nicer because concerns are separated well: the
WriteToRegister procedure fusses with all the irritating detail
about which signal to wiggle at what time, and the main process
simply calls it with the appropriate set of values and expects
to have the job done.

HTH
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL, Verilog, SystemC, Perl, Tcl/Tk, Verification, Project Services

Doulos Ltd. Church Hatch, 22 Market Place, Ringwood, BH24 1AW, UK
Tel: +44 (0)1425 471223 mail:jonathan.bromley@doulos.com
Fax: +44 (0)1425 471573 Web: http://www.doulos.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 

Welcome to EDABoard.com

Sponsor

Back
Top