else
read:
step1: place address request (also enable read pin)
step2. place valid address
step3: if ack is generated and data placed in next clock then read
now i have excluded other control signals like busy, request pending,
parity, etc.,
my question is what is best(optimized) coding practice to design in
this system verilog?
thanks,
sundar
The level that you are describing is what I call the RTL level or
signal level. For this coding you might as well right it the same way
you would in Verilog.
The biggest RTL difference is that you might use interfaces to contain
all the signals in the bus interface and pass them to the modules.
That way you have a single file that describes all the signal on the
bus, etc.
At a higher level SystemVerilog makes it easy to create a transaction
level model of your design. So you could write behavioral models of
all your blocks and pass transactions between them. In this case you
would write a design unit called a "driver" to convert the transaction
to the signals you describe.
Ray
--
Author of Leading After a Layoff : http://tinyurl.com/ycv2xa
First of all welcome to world of SystemVerilog.
The point you are talking about is some bus protocol.
when we talk about bus protocols there is hardly any
difference the way you capture the protocol.
so as Ray pointed out doesn't matter whether you code in verilog or
systemVerilog(these are going to be simple tasks).
but of course when we talk about SV its at higher abstraction then
verilog. for you testbench you can use it,make use
of SV interface and other constructs which are very powerful.
well my point here was very general but if you have specific query
feel free to post it.
Regards
Manmohan
On Sep 10, 5:51 pm, "Ray Salemi" <rdsal...@gmail.com> wrote:
> Hi Sundar,
>
> The level that you are describing is what I call the RTL level or
> signal level. For this coding you might as well right it the same way
> you would in Verilog.
>
> The biggest RTL difference is that you might use interfaces to contain
> all the signals in the bus interface and pass them to the modules.
> That way you have a single file that describes all the signal on the
> bus, etc.
>
> At a higher level SystemVerilog makes it easy to create a transaction
> level model of your design. So you could write behavioral models of
> all your blocks and pass transactions between them. In this case you
> would write a design unit called a "driver" to convert the transaction
> to the signals you describe.
>
> Ray
>
Let me more specific now,
I thot of exploring FIFO and I saw various design options in SV like
using queue.
But I wanted to explore a protocol , with a small example of so called
"driver" as mentioned by Ray.
Now how best can we design the same using AVM package in SV?
We need a design(driver), a test bench which has a
transactor,initiator and responder modules.
any thoughts or even same code snippets are welcome.
thanks again for all your responses
Sundar
I believe the AVM area as several examples.
In SV, we tend to use a queue to implement a fifo code interface. In
other words, the implementation is a queue, but the order that "put()"
and "get()" provide is FIFO. I hope my feeble explanation makes sense.
One of the major differences between SV and Verilog is an ability to
separate the interface from the implementation. For example, in your
driver, the class interface might look like this (not compiled code,
just typing here):
typedef bit[31:0] uint32;
interface driver_wires(
out uint32 address, out uint32 data, out read, out read
);
end nterface;
class driver;
extern function new (virtual driver_wires w);
extern task do_write (uint32 address, uint32 data);
extern task do_read (uint32 address, out uint32 data);
endclass
That's pretty much straight coding. Now to add a transaction based
system on top,define a transaction and a class to have a transaction
interface.
class transaction;
endclass;
I have implemented (not in AVM, but similar) a verification framework
that has three examples, progressing from small to medium sized. Feel
free to download then and see if they help.
Take Care,
Mike
Sorry about the premature post. Let's pick up with transactions...
That's pretty much straight coding. Now to add a transaction based
system on top,define a transaction and a class to have a transaction
interface.
class transaction;
uint32 address;
uint32 data;
bit read;
bit write;
endclass;
class driver_transaction extends driver;
task send (transaction t);
endclass
(Note that I will ignore the issue of determining where/how to store
the read result).
The reason I code a base class (driver) with out transactions is that
it is maximally reusable. It makes no assumptions on how/whether you
use a transaction, or how you choose to call the driver's methods.
Now for one last level of complication, the queue or fifo. This is
where we really get into religion ;-)
To minimize the connection between the driver and the generator, and
to decouple the timing between the two, we use a queue. This queue,
which we tend to call a channel, has a form similar to:
class transaction_channel;
task put (transaction t);
task get (out transaction t);
endclass
Now there are loads of design decisions around this interface (what is
copied when, is the depth limited, do we use templating, etc), but the
general idea is that the driver and generator "talk" to a channel, not
directly to each other.
class driver_transactor extends driver //the decision to extend or
"own" is not clear
extern function new (string name, virtual driver_wires w,
transaction_channel channel);
task start ();
forever () begin
transaction tx;
channel_.get (tx);
send (tx);
end
endtask
endclass
There are literally hundreds of design decisions I stepped through
and around, but the general idea is there.
I hope this helps.
Take care,
mike