From: hughes@swine.cs.uiuc.edu (Eric Hughes)
Subject: Re: Avoiding inertial delay in delay lines
Organization: University of Illinois, Dept. of Comp. Sci., Urbana, IL
Date: Thu, 12 Nov 1992 14:26:15 GMT

smb@afterlife.ncsc.mil (Steve M. Burinsky) writes:

>I need to simulate delay lines in order to model a bus interface.  The
>solution seems obvious --  use a net delay.  However, the signal I need
>to delay has pulse widths (w) which are shorter than the delay time (d);
>that is w < d.  The problem is that inertial delay causes the short pulse
>to disappear within the delay.

>So, how should this be implemented?  I have two options, neither of which
>I like:
>1.  Implement the delay line as a string of (for example) 10 buffers, each
>with 10% of the total required delay.  This has drawbacks, as it requires
>that the user know the number of internal sub-delay units in order to
>guarantee acurate delay generation.  Also, (given that 10 buffers are used)
>10w > d is required.
>2.  Implement a PLI routine which calls (for example) tf_strdelputp, which
>allows me to specify transport (versus inertial) delay.

>Is there anyway I can choose transport delay using a standard language
>construct?  Is there another (easy, portable, general) way of implementing
>delay lines I'm missing?

>Thanks,
>Steve Burinsky
>smb@afterlife.ncsc.mil

>-- 

>Steve M. Burinsky
>smb@afterlife.ncsc.mil

I bumped into this problem a long time ago.  I found that the most flexible
way to solve the problem was to write a module for the delay line.  The model
is truly event-driven, which keeps it from slowing down the simulation too
much.  I've included it below.

Good luck,  Eric Hughes
451 Loomis Lab   1110 W. Green St.   Urbana, IL  61801  USA
hughes@cs.uiuc.edu

------------------------------------------------
module trans_delay(In, Out);

parameter qlen = 60;               /* number of transitions to be queued */
parameter delay_time = 960;        /* delay time of pipe */

input   In;                        /* input signal */
output  Out;                       /* output signal */
reg     Out;

reg     [32:1] times [1:qlen];     /* queue of transition times */
reg     [1:qlen] values;           /* queue of transition values */
integer read_addr;                 /* addresses to read */
integer write_addr;                /*  and write */
reg     q_full;                    /* remember if queue is full */
reg     q_empty;                   /* remember if queue is empty */

initial begin
    read_addr = 1;
    write_addr = 1;
    q_full = 0;
    q_empty = 1;
    @(negedge q_empty);
    while (1) begin                /* drive the output */
        #(times[read_addr] - $stime);
        Out = values[read_addr];
        q_full = 0;
        read_addr = read_addr % qlen + 1;
        if (read_addr == write_addr) begin
            q_empty = 1;           /* queue is empty */
            @(negedge q_empty);    /* wait for insertion */
        end /* if */
    end /* while */
end /* initial */

always @(In) begin
    if(q_full) $display("Transport queue is full -- make it bigger");
    else begin
        times[write_addr] = $stime + delay_time;
        values[write_addr] = In;
        write_addr = write_addr % qlen + 1;
        if (read_addr == write_addr) q_full = 1;
        q_empty = 0;
    end /* else */
end /* always */

endmodule

Xref: sparky comp.lang.verilog:421 comp.lang.vhdl:530 comp.parallel:2517