I am looking for some alternatives/suggestions on how to use
always@(posedge clk) or always@(negedge clk) anyplace in a design -
for example in a dual-port memory design.
The main problem is that one can't just add a "if(posedge clk)"
anyplace inside an always@() block of Verilog code - it has to be -
for example - within an always@(posedge clk) statement itself.
As a result, I need some sort of alternative for picking out the edges
of the clock in a memory design. Does anyone have some suggestions on
how to go about doing this? Here is what I am currently doing - but
this doesn't work since it just lengthens the edge of the clock rather
then finding the EDGE of the clock as a posedge or negedge statment
would do.
1.)
always @ (port_a_read_clock)
begin
last_port_a_read_clock = ~port_a_read_clock;
end
always @ (port_b_read_clock)
begin
last_port_b_read_clock = ~port_b_read_clock;
end
2.) Here is my main always block...
always @ (port_a_write_enable or port_b_write_enable or
port_a_data_in or port_b_data_in or
port_a_address or port_b_address or
port_a_byte_ena_mask or port_b_byte_ena_mask or
port_b_read_enable or
port_a_read_clock or port_b_read_clock or
last_port_a_read_clock or last_port_b_read_clock
)
begin
// DETECT POSITIVE EDGE
if(port_a_read_clock & ~last_port_a_read_clock)
// READ SOME DATA
// DETECT NEGATIVE EDGE
if(~port_a_read_clock & last_port_a_read_clock)
// WRITE SOME DATA
/*
// Ideally I would like to do the following but I can't...
if (port_a_write_enable)
if(negedge port_a_read_clock)
mem[port_a_address*port_a_data_width + i] = port_a_data_in[i];
*/
end
The only problem with the above is that it detects the concept of
transition of the clock and this will last until the next transition
rather then detecting ONLY the edge like a posedge or negedge
statement would.
Does anyone have any suggestions on how to go about detecting the edge
of the clock anyplace in a Verilog design - meaning outside of
always@()?
Any ideas on this??? Help...! :o)
Take care,
>Asher<
PS: Please e-mail any suggestions to ASH...@ASHERM.COM in addition to
any postings - since I often cannot see all the postings on
comp.lang.verilog.
Thanks! :o)
In article <3e30b793.02011...@posting.google.com>, Asher C.
Martin <ash...@asherm.com> writes
>I am looking for some alternatives/suggestions on how to use
>always@(posedge clk) or always@(negedge clk) anyplace in a design -
>for example in a dual-port memory design.
If you really mean "in a DESIGN", i.e. something you intend to
synthesise, then the answer is No: stick with the always @()
style approved by synthesis tools. And don't try to detect
signal transitions anywhere else in the process.
>The main problem is that one can't just add a "if(posedge clk)"
>anyplace inside an always@() block of Verilog code - it has to be -
>for example - within an always@(posedge clk) statement itself.
Wrong! You can say @(posedge clk) anywhere you like within any
block of procedural code, for simulation.
Because synthesis coding styles are so restricted, a lot of people
are not aware of the syntactic significance of @() and other Verilog
timing controls. The deal is:
1) Any procedural statement whatsoever can be prefixed with a
timing control. The resulting statement, **with no intervening
semicolon** :
timing_control statement;
has the status of just one single procedural statement - so it
doesn't need to be wrapped in begin...end.
2) A timing control can be any one of:
@(event_specification)
#delay
wait (condition) [VHDLers NOTE: this is LEVEL sensitive!]
and an event_specification can be any one of:
wire_or_reg [waits for any transition]
named_event [waits for named_event to be fired]
pos/negedge wire_or_reg [waits for specified edge]
You can string a load of event_specifications together with "or"
(comma is permissible in Verilog-2001). The parentheses are
not required if the event_specification is just one signal or
event name.
3) Any group of procedural statements wrapped in begin...end or
fork...join counts as one procedural statement, and therefore
can be prefixed with a timing control.
4) Procedural control structures such as while, forever, if
all control precisely one procedural statement.
5) always and initial are module-level structures that contain
exactly one procedural statement.
So your traditional "always @(edge) begin....end" is NOT a magic
spell "always@(edge)" followed by a begin...end block; it's an
"always" containing a single procedural statement that happens to
be a begin...end prefixed with an @(edge) timing control.
To synthesise your dual port RAM, instantiate it.
To simulate your dual port RAM, go ahead and write a model that
has @() controls anywhere you like in it.
--
Jonathan Bromley
DOULOS Ltd.
Church Hatch, 22 Market Place, Ringwood, Hampshire BH24 1AW, United Kingdom
Tel: +44 1425 471223 Email: jonathan...@doulos.com
Fax: +44 1425 471573 Web: http://www.doulos.com
**********************************
** Developing design know-how **
**********************************
This e-mail and any attachments are confidential and Doulos Ltd. reserves
all rights of privilege in respect thereof. It is intended for the use of
the addressee only. If you are not the intended recipient please delete it
from your system, any use, disclosure, or copying of this document is
unauthorised. The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
There is no way to "query" whether there was an edge on a clock after
it has happened. All you can do is ask to be triggered when it happens.
Your problem is that you are going about this in the wrong way.
You are trying to treat the device as one monolithic process that is
triggered by different inputs and then does different things depending
on what triggered it. That isn't what you have. What you have is
multiple independent processes (i.e. pieces of logic), each of which is
triggered by something different and does something different.
For example, you are trying to do something like this invalid code:
always @(posedge clka or posedge clkb)
begin
if (posedge clka)
do_thing_a;
if (posedge clkb)
do_thing_b;
end
The correct way to do this is:
always @(posedge clka)
do_thing_a;
always @(posedge clkb)
do_thing_b;
With a dual-port RAM, you don't have one set of read/write logic that
is triggered by both ports and does the right thing depending on which
one triggered it. You have two mostly independent sets of read/write
logic, each of which is triggered only by its own port inputs.
Hi Steven,
Thanks for your comments... and I agree with what you are saying.
However, the problem is that what I am trying to do is a little more
complicated then a conventional RAM - I need to create a ram that is
re-configurable.
Basically, what this means is that it has to be able to do two
different things depending on the mode.
So for example, you can write from port a and read from port b in
something called dual port mode. But then in true dual port mode it
can also read and write from port a and at the same time it can also
read and writing from port b as well. So there is some port cross
over (or whatever you want to call it) that requires both ports to be
in the same always block.
So it's not really a matter of splitting it up into two different
always blocks as you suggested-that is the way I would prefer if I had
the chose but as you know in HDL one of the basic laws is that each
always block can only write to one output. Meaning you can't have two
different always blocks writing to the same port as I need to so they
have to be in the same always block.
Anyway, thanks for your thought provoking comments. What I am mainly
looking for is some control logic that will basically read the clock
last after a sequence of crazy events... something like a wait until
posedge of clock statement would be perfect.
Any idea about that? Thanks again for your suggestions...
Take care,
>Asher<