How to simulate a RAM's access time.

P

Paul Marciano

Guest
Hello. I'm a bit of a beginner at Verilog, so please be gentle.

I'm trying to build a model for an asynchronous SRAM, and I'm stuck on
how to model the data_out whilst its invalid. Specifically, the
datasheet says the data is valid 70ns after ~nCS & nWE, or any change
in ADDR.

My first try was:

always @(negedge nCS)
if (nWE) begin
data_out = 16'hxxxx;
data_out = #70 ram[ADDR];
end
end

But this has many problems. It only reacts to the edge of CS, so
multiple transactions with CS held low don't work and it doesn't
restart the 70ns access timer if any parameters change.

What I think I need is an FSM, but without a clock I don't know how to
model time (i.e the 70ns access timeout) as an event.

This is purely a learning exercise. I hope someone can clue me in.

Thanks,
Paul.
 
On Nov 21, 3:25 pm, Paul Marciano <pm...@yahoo.com> wrote:
Hello.  I'm a bit of a beginner at Verilog, so please be gentle.

I'm trying to build a model for an asynchronous SRAM, and I'm stuck on
how to model the data_out whilst its invalid.  Specifically, the
datasheet says the data is valid 70ns after ~nCS & nWE, or any change
in ADDR.

My first try was:

always @(negedge nCS)
  if (nWE) begin
    data_out = 16'hxxxx;
    data_out = #70 ram[ADDR];
  end
end

But this has many problems.  It only reacts to the edge of CS, so
multiple transactions with CS held low don't work and it doesn't
restart the 70ns access timer if any parameters change.

What I think I need is an FSM, but without a clock I don't know how to
model time (i.e the 70ns access timeout) as an event.

This is purely a learning exercise.  I hope someone can clue me in.

Thanks,
Paul.
try putting the ADDR in your sensitivity list
 
On Nov 21, 1:13 pm, "dscol...@rcn.com" <dscol...@rcn.com> wrote:
On Nov 21, 3:25 pm, Paul Marciano <pm...@yahoo.com> wrote:









Hello.  I'm a bit of a beginner at Verilog, so please be gentle.

I'm trying to build a model for an asynchronous SRAM, and I'm stuck on
how to model the data_out whilst its invalid.  Specifically, the
datasheet says the data is valid 70ns after ~nCS & nWE, or any change
in ADDR.

My first try was:

always @(negedge nCS)
  if (nWE) begin
    data_out = 16'hxxxx;
    data_out = #70 ram[ADDR];
  end
end

But this has many problems.  It only reacts to the edge of CS, so
multiple transactions with CS held low don't work and it doesn't
restart the 70ns access timer if any parameters change.

What I think I need is an FSM, but without a clock I don't know how to
model time (i.e the 70ns access timeout) as an event.

This is purely a learning exercise.  I hope someone can clue me in.

Thanks,
Paul.

try putting the ADDR in your sensitivity list
What you need is a continuous assignment and the conditional operator

assign #70ns data_out = (!nCS && !nWE) ? ram[ADDR] : 16'hz;

The continuous assignment is sensitive to all changes on the RHS of
the '=', and take 70ns to flow to the LHS.
 
On Monday, November 28, 2011 3:42:23 PM UTC-8, Dave Rich wrote:
On Nov 21, 1:13 pm, "dsco...@rcn.com" <dsco...@rcn.com> wrote:
On Nov 21, 3:25 pm, Paul Marciano
wrote:
What you need is a continuous assignment and the conditional operator

assign #70ns data_out = (!nCS && !nWE) ? ram[ADDR] : 16'hz;

The continuous assignment is sensitive to all changes on the RHS of
the '=', and take 70ns to flow to the LHS.
The danger with this is that it's a blocking assignment, so if any of the RHS signal change in less than #70 (whatever that means based on timescale), they won't propagate. This might be the correct modeling - or it might not. Using always @* (Verilog 2001 - hopefully works on all simulators today) or always_comb (System Verilog) with blocking ( <= ) assignments will propagate all input changes.

Welcome to some of the confusing parts of Verilog! Search for "transport delay vs inertial delay" for more explanation.

David
 
Um, there is some abuse of terminology here...

On 11/28/2011 10:20 PM, unfrostedpoptart wrote:
On Monday, November 28, 2011 3:42:23 PM UTC-8, Dave Rich wrote:
On Nov 21, 1:13 pm, "dsco...@rcn.com" <dsco...@rcn.com> wrote:
On Nov 21, 3:25 pm, Paul Marciano
wrote:
What you need is a continuous assignment and the conditional operator

assign #70ns data_out = (!nCS && !nWE) ? ram[ADDR] : 16'hz;

The continuous assignment is sensitive to all changes on the RHS of
the '=', and take 70ns to flow to the LHS.

The danger with this is that it's a blocking assignment, so if any of the RHS signal change in less than #70 (whatever that means based on timescale), they won't propagate. This might be the correct modeling - or it might not. Using always @* (Verilog 2001 - hopefully works on all simulators today) or always_comb (System Verilog) with blocking ( <= ) assignments will propagate all input changes.
A continuous assignment is a continuous assignment. A "blocking
assignment" is something specific and only happens in behavioral
code.

However you are correct that continuous assignments implement
inertial delays. However, that is probably what you want in
this case anyhow. (If your memory has 70ns access times, then
changing your inputs faster then that would be bad.)

If you do go with "always @*..." then you will get transport
delays. Note that the "<=" assignment is called *NON*-blocking
assignment, and is probably not what you want if you are modeling
combinational logic in an always statement.

Welcome to some of the confusing parts of Verilog! Search for "transport delay vs inertial delay" for more explanation.
Indeed.


--
Steve Williams "The woods are lovely, dark and deep.
steve at icarus.com But I have promises to keep,
http://www.icarus.com and lines to code before I sleep,
http://www.picturel.com And lines to code before I sleep."
 
Stephen Williams wrote:
Um, there is some abuse of terminology here...

On 11/28/2011 10:20 PM, unfrostedpoptart wrote:
On Monday, November 28, 2011 3:42:23 PM UTC-8, Dave Rich wrote:
On Nov 21, 1:13 pm, "dsco...@rcn.com" <dsco...@rcn.com> wrote:
On Nov 21, 3:25 pm, Paul Marciano
wrote:
What you need is a continuous assignment and the conditional operator

assign #70ns data_out = (!nCS && !nWE) ? ram[ADDR] : 16'hz;

The continuous assignment is sensitive to all changes on the RHS of
the '=', and take 70ns to flow to the LHS.
The danger with this is that it's a blocking assignment, so if any of the RHS signal change in less than #70 (whatever that means based on timescale), they won't propagate. This might be the correct modeling - or it might not. Using always @* (Verilog 2001 - hopefully works on all simulators today) or always_comb (System Verilog) with blocking ( <= ) assignments will propagate all input changes.

A continuous assignment is a continuous assignment. A "blocking
assignment" is something specific and only happens in behavioral
code.

However you are correct that continuous assignments implement
inertial delays. However, that is probably what you want in
this case anyhow. (If your memory has 70ns access times, then
changing your inputs faster then that would be bad.)

If you do go with "always @*..." then you will get transport
delays. Note that the "<=" assignment is called *NON*-blocking
assignment, and is probably not what you want if you are modeling
combinational logic in an always statement.

Welcome to some of the confusing parts of Verilog! Search for "transport delay vs inertial delay" for more explanation.

Indeed.
You can schedule multiple transport delayed events for a single input
change. For example if you want to drive your data to 'X' between the
minimum and maximum delay times you can do something like this:

`timescale 1ns / 1ps

module address_delay_tb;

reg [7:0] ADDR = 8'h55;
reg nCS = 1'b1;
reg nWE = 1'b1;

initial begin
#20 nCS = 1'b0;
#40 ADDR = 8'h44;
#40 nCS = 1'b1;
end

parameter T_min = 5,
T_max = 20,
T_zmin = 4,
T_zmax = 16;


reg [7:0] DATA = 8'bZ;
reg driving = 1'b0;

// always @* includes "driving" - we don't want that!
always @(ADDR or nCS or nWE) begin
if (nCS | !nWE) begin
if (driving) begin
DATA <= #T_zmin 8'bX;
DATA <= #T_zmax 8'bZ;
end
else DATA <= #T_zmin 8'bZ;
driving <= #T_zmax 1'b0;
end
else begin
if (driving) begin
DATA <= #T_min 8'bX;
DATA <= #T_max ADDR;
end
else begin
DATA <= #T_zmin 8'bX;
DATA <= #T_max ADDR;
end
driving <= #T_zmax 1'b1;
end
end

endmodule

I ran this in ISIM and it did what I expected. YMMV...

-- Gabor
 
Thanks for the ideas. The desire was for the output to go to 'x'
whenever any of the inputs change; only finally going valid if the
inputs have been held for as long as the required access time of the
RAM.

Special thanks for Gabor for pointing out that a sensitivity list
doesn't _have_ to include every signal. I has gotten into the habit
of using @* without thinking (that's a problem right there).

Paul.
 

Welcome to EDABoard.com

Sponsor

Back
Top