( ESNUG 498 Item 5 ) -------------------------------------------- [02/07/12]

Subject: How to accurately model an asynchronous SRAM in standard Verilog?

> 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 70 nsec 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 70 nsec 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 70 nsec access timeout) as an event.


From: Dave Colson  <dscolson=user domain=rcn not calm>

Try putting the ADDR in your sensitivity list.

    - Dave Colson
      Kollmorgen                                 Radford, VA

         ----    ----    ----    ----    ----    ----   ----

From: Dave Rich <dave_rich=user domain=mentor not calm>

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 70 nsec to flow to the LHS.

    - Dave Rich
      Mentor Graphics Corp.                      Fremont, CA

         ----    ----    ----    ----    ----    ----   ----

From: David Rogoff <david.rogoff=user domain=qlogic not calm>

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 Rogoff
      Qlogic Corp.                               Orange County, CA

         ----    ----    ----    ----    ----    ----   ----

>> The continuous assignment is sensitive to all changes on the RHS of
>> the '=', and take 70 nsec 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. ...


From: Stephen Williams <steve=user domain=icarus not calm>

Um, there is some abuse of terminology here...  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 70 nsec 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.

    - Steve Williams
      Icarus Verilog                             Berkeley, CA

         ----    ----    ----    ----    ----    ----   ----

From: Gabor Szakacs <gabor=user domain=alacron not calm>

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 Xilinx ISIM and it did what I expected.  YMMV...

    - Gabor Szakacs
      Alacron, Inc.                              Nashua, NH
Join    Index    Next->Item






   
 Sign up for the DeepChip newsletter.
Email
 Read what EDA tool users really think.


Feedback About Wiretaps ESNUGs SIGN UP! Downloads Trip Reports Advertise

"Relax. This is a discussion. Anything said here is just one engineer's opinion. Email in your dissenting letter and it'll be published, too."
This Web Site Is Modified Every 2-3 Days
Copyright 1991-2024 John Cooley.  All Rights Reserved.
| Contact John Cooley | Webmaster | Legal | Feedback Form |

   !!!     "It's not a BUG,
  /o o\  /  it's a FEATURE!"
 (  >  )
  \ - / 
  _] [_     (jcooley 1991)