Style Request for Testbench with Bus Interfaces

Discussion in 'VHDL' started by M. Norton, Mar 29, 2011.

  1. M. Norton

    M. Norton Guest

    Hello folks,

    I'm posting this in hopes that folks have some suggestions on how to
    handle this in a clean way. I find myself (not surprisingly) writing
    testbenches for a lot of very similar bus interfaces. At the simplest
    I've got an address signal, data out, data in, and a write enable
    signal. On a more complex one I might have the full backend interface
    to the Actel PCI core or the Altera Avalon interface.

    Regardless, I would really like to be able to write my basic
    interaction procedures once and just use them after that. However I'm
    running into some difficulty with the language and scoping rules. So
    for talking purposes, here's a little skeleton

    use work.generic_bus_if_pkg.all; -- <procedure declaration area C :
    preferred>

    entity just_a_testbench is
    end entity just_a_testbench;

    architecture behavioral of just_a_testbench is
    <procedure declaration area B>
    signal be_addr : unsigned(15 downto 0);
    signal be_rddata : std_logic_vector(31 downto 0);
    signal be_wrdata : std_logic_vector(31 downto 0);
    signal be_wren : std_logic;
    begin
    DUT : entity work.foo
    port map (
    ....
    be_addr => be_addr,
    be_rddata => be_rddata,
    be_wrdata => be_wrdata,
    be_wren => be_wren,
    ....
    );

    BUS_CONTROL : process is
    <procedure declaration region A>
    begin
    .....
    be_read32();
    be_write32();
    .....
    end process BUS_CONTROL;

    end architecture behavioral;

    Alright, I think that's enough to give an idea. So I'd really like my
    procedure calls to be something I can abstract preferably into a
    package. Also I'd really like to keep the parameter list as minimal
    as possible. However I run into scope issues with signals. So if I
    use region A for declaring my read/write procedures, I can directly
    access all the signals running into the DUT. I don't have to pass
    them in. I can simply have an address and data parameters. However
    this means every testbench has to declare everything right there in
    the process and that's ugly to me.

    Now if I use B or C, then I no longer have scope on the signals. If I
    want to use a procedure for reading and writing, I've got to pass them
    into the procedure. With the example described, it's not really too
    big a deal, but consider a PCI interface with all its myriad signals
    or another example various PCI core backend interfaces with start,
    stop, rdcyc, wrcyc, and various other signals for backpressure. It
    seems to me that the parameter list could get unwieldy very quickly.
    So I can put the procedures here, but that violates my desire to have
    manageable calls.

    So, I'm hoping there's some sort of clever way of passing a bus in and
    out of procedure declarations to keep code readable and maintainable.
    The only way I've thought that might work is to declare a record that
    comprises the entire bus interface. Then I could pass in a single
    token that represents the entire bus. I haven't really worked out how
    that might work with different naming conventions (I'm usually pretty
    consistent with signal names, but sometimes there are variations.)
    There are very likely other ways to do it, but I haven't had a lot of
    exposure to folks who do large scale testbenches and have already
    worked out these tricks.

    So, in summary does anyone have any technique or best practice for how
    to organize bus interfaces for passing in and out of procedure calls?

    Thanks for any ideas. I appreciate it.

    Best regards,
    Mark Norton
     
    M. Norton, Mar 29, 2011
    #1
    1. Advertising

  2. On 3/29/2011 9:42 AM, M. Norton wrote:

    > So, I'm hoping there's some sort of clever way of passing a bus in and
    > out of procedure declarations to keep code readable and maintainable.


    I haven't seen it, if we include the "readable" part.
    I like to use variables and procedures and minimize processes.
    Something like:
    ....
    constant reps : natural := 8;
    begin -- process main: Top level loop invokes top procedures.
    init;
    for i in 1 to reps loop
    timed_cycle;
    end loop;
    for i in 1 to reps loop
    handshake_cycle;
    end loop;
    coda;
    end process main;

    for details, see the testbench here:
    http://mysite.ncnetwork.net/reszotzl/

    -- Mike Treseler
     
    Mike Treseler, Mar 29, 2011
    #2
    1. Advertising

  3. M. Norton

    Andy Guest

    On Mar 29, 11:42 am, "M. Norton" <> wrote:
    > Hello folks,
    >
    > I'm posting this in hopes that folks have some suggestions on how to
    > handle this in a clean way.  I find myself (not surprisingly) writing
    > testbenches for a lot of very similar bus interfaces.  At the simplest
    > I've got an address signal, data out, data in, and a write enable
    > signal.  On a more complex one I might have the full backend interface
    > to the Actel PCI core or the Altera Avalon interface.
    >
    > Regardless, I would really like to be able to write my basic
    > interaction procedures once and just use them after that.  However I'm
    > running into some difficulty with the language and scoping rules.  So
    > for talking purposes, here's a little skeleton
    >
    > use work.generic_bus_if_pkg.all; -- <procedure declaration area C :
    > preferred>
    >
    > entity just_a_testbench is
    > end entity just_a_testbench;
    >
    > architecture behavioral of just_a_testbench is
    >      <procedure declaration area B>
    >      signal be_addr : unsigned(15 downto 0);
    >      signal be_rddata : std_logic_vector(31 downto 0);
    >      signal be_wrdata : std_logic_vector(31 downto 0);
    >      signal be_wren : std_logic;
    > begin
    >     DUT : entity work.foo
    >          port map (
    >               ....
    >               be_addr => be_addr,
    >               be_rddata => be_rddata,
    >               be_wrdata => be_wrdata,
    >               be_wren => be_wren,
    >               ....
    >          );
    >
    >      BUS_CONTROL : process is
    >           <procedure declaration region A>
    >      begin
    >            .....
    >            be_read32();
    >            be_write32();
    >            .....
    >      end process BUS_CONTROL;
    >
    > end architecture behavioral;
    >
    > Alright, I think that's enough to give an idea.  So I'd really like my
    > procedure calls to be something I can abstract preferably into a
    > package.  Also I'd really like to keep the parameter list as minimal
    > as possible.  However I run into scope issues with signals.  So if I
    > use region A for declaring my read/write procedures, I can directly
    > access all the signals running into the DUT.  I don't have to pass
    > them in.  I can simply have an address and data parameters.  However
    > this means every testbench has to declare everything right there in
    > the process and that's ugly to me.
    >
    > Now if I use B or C, then I no longer have scope on the signals.  If I
    > want to use a procedure for reading and writing, I've got to pass them
    > into the procedure.  With the example described, it's not really too
    > big a deal, but consider a PCI interface with all its myriad signals
    > or another example various PCI core backend interfaces with start,
    > stop, rdcyc, wrcyc, and various other signals for backpressure.  It
    > seems to me that the parameter list could get unwieldy very quickly.
    > So I can put the procedures here, but that violates my desire to have
    > manageable calls.
    >
    > So, I'm hoping there's some sort of clever way of passing a bus in and
    > out of procedure declarations to keep code readable and maintainable.
    > The only way I've thought that might work is to declare a record that
    > comprises the entire bus interface.  Then I could pass in a single
    > token that represents the entire bus.  I haven't really worked out how
    > that might work with different naming conventions (I'm usually pretty
    > consistent with signal names, but sometimes there are variations.)
    > There are very likely other ways to do it, but I haven't had a lot of
    > exposure to folks who do large scale testbenches and have already
    > worked out these tricks.
    >
    > So, in summary does anyone have any technique or best practice for how
    > to organize bus interfaces for passing in and out of procedure calls?
    >
    > Thanks for any ideas.  I appreciate it.
    >
    > Best regards,
    > Mark Norton


    I've used a single record with an inout port on the procedure(s). All
    of the elements of the record must be resolved types. I declare an
    "undriven" constant of that record such that the elements that are
    never used as outputs by each process are harmlessly driven to 'Z'.

    Andy
     
    Andy, Mar 29, 2011
    #3
  4. M. Norton

    M. Norton Guest

    On Mar 29, 2:24 pm, Mike Treseler <> wrote:
    > I haven't seen it, if we include the "readable" part.
    > I like to use variables and procedures and minimize processes.
    > Something like:

    ....
    > for details, see the testbench here:http://mysite.ncnetwork.net/reszotzl/


    Yeah, this is essentially what I'm doing right now, one process
    describing test over time (with loops and whatnot as need requires)
    and then a lot of local procedures to handle the transactions. The
    only trouble I've got is that I end up repeating myself quite a lot
    over a number of testbenches that use identical or more-likely near-
    identical protocols. All it takes is a few names changed and my cut
    and paste of previously written transaction procedures gets smoked.

    I suppose I'm glad to know I'm not too far off in what I've come up
    with but it'd be nice to find something that's more reusable. Thanks
    for the information!

    Mark
     
    M. Norton, Mar 29, 2011
    #4
  5. M. Norton

    M. Norton Guest

    On Mar 29, 2:51 pm, Andy <> wrote:
    > I've used a single record with an inout port on the procedure(s). All
    > of the elements of the record must be resolved types. I declare an
    > "undriven" constant of that record such that the elements that are
    > never used as outputs by each process are harmlessly driven to 'Z'.


    I've read and reread this a bit and while I get the theory of what
    you're doing with the constant, I'm not sure how it's being applied.
    So if we've got a package with a record containing the signal elements
    of a bus, including control lines, that would allow harnessing up a
    generic procedure to a testbench component. However when do you apply
    the constant that's got things set to high impedance? Does that
    happen inside the procedure at the beginning of the procedure and then
    subsequent assignments override it?

    So, possibly something like this?

    procedure my_generic_write( ... ; signal my_bus :
    T_BUS_RECORD; ... ) is
    begin
    my_bus <= C_HARMLESSLY_DRIVEN_TO_Z;
    wait until rising_edge(some_clk);
    my_bus.address <= some_address;
    my_bus.wr_cyc <= '1';
    wait until rising_edge(some_clk);
    my_bus.data <= some_data;
    my_bus.wren <= '1';
    wait until rising_edge(some_clk);
    my_bus_wren <= '0';
    wait until rising_edge(some_clk);
    my_bus.wr_cyc <= '0';
    wait until rising_edge(some_clk);
    my_bus <= C_HARMLESSLY_DRIVEN_TO_Z;
    end procedure my_generic_write;

    Then during that procedure call, all the my_bus.rd_cyc, my_bus.rd_stb,
    etc would remain Z. I will have to try that out and see how it goes.
    Seems like it might do what I want (assuming I have your intent
    divined correctly).

    Thanks for the information!
    Mark
     
    M. Norton, Mar 29, 2011
    #5
  6. On Tue, 29 Mar 2011 09:42:05 -0700 (PDT), "M. Norton" wrote:

    >I'm posting this in hopes that folks have some suggestions on how to
    >handle this in a clean way. I find myself (not surprisingly) writing
    >testbenches for a lot of very similar bus interfaces.[...]
    >I would really like to be able to write my basic
    >interaction procedures once and just use them after that. However I'm
    >running into some difficulty with the language and scoping rules.


    Yup.

    >Alright, I think that's enough to give an idea. So I'd really like my
    >procedure calls to be something I can abstract preferably into a
    >package. Also I'd really like to keep the parameter list as minimal
    >as possible.


    But, as you've found, a procedure in a package can
    only hit signals through its arguments (parameters).
    Which may be numerous, for any reasonably complex
    model.

    There are other issues too. Your bus model probably
    needs to keep track of some persistent state, which
    you can't comfortably do with a package either.

    So, here's what I would regard as the preferred
    way to start. Others will doubtless have different
    opinions, of course.

    First off, consider encapsulating your bus model
    not as a package but as an entity. That way it
    can have persistent PER-INSTANCE state, i.e.
    you can use the same model for numerous different
    buses in the same testbench with no difficulty.
    And you can provide ports on the entity that
    will connect to the physical pins of your
    interface. As a super-simple example we can
    model an asynchronous serial data (UART)
    protocol where the DUT is a receiver, and
    your testbench is the transmitter. So the
    physical interface is just two wires: TxD
    from TB to DUT, and CTS (Clear to Send) from
    DUT to TB. Something like this (yes I know it's
    no use like this: bear with me as I build up
    the example.) Lots of details and declarations
    missing, but I'm sure you can fill it all in
    yourself.

    entity UART_TX_incomplete is
    port (
    TXD: out std_logic; -- to DUT
    CTS: in std_logic ); -- from DUT
    end;
    architecture incomplete of UART_TX_incomplete is
    begin
    Transmitter: process
    procedure Tx(bit_to_send: std_logic);
    begin
    TXD <= bit_to_send;
    wait for BIT_TIME;
    end;
    procedure Tx(byte_to_send: unsigned(7 downto 0));
    begin
    wait until CTS = '1'; -- handshake
    Tx('0'); -- start bit
    for i in byte_to_send'reverse_range loop
    Tx(byte_to_send(i)); -- LSB first
    end loop;
    Tx('1'); -- stop bit
    end;
    begin
    end process; -- eh??? nothing in this process!!!
    end;

    OK, this is cool; we just create an instance of this
    thing, hook its ports to our DUT interface, and, errm,
    call the procedure... oh dear, we can't because the
    procedure is hidden away inside a process, inside
    the instance. So, how do we call that procedure
    from OUTSIDE the UART_TX entity? Answer: provide
    a port on said entity that allows your testbench
    to command it to do things. This port won't connect
    to DUT wires; it will be hooked to a very abstract
    signal in the TB, conveying commands. So we can
    usefully create a record type that represents a
    command. In our case that's kinda simple (just
    a byte) but you get the idea. While we're writing
    a package that defines this record, we can also
    write a procedure to encapsulate the whole business
    of getting the UART_TX to do something for us.

    package UART_TB_CONTROL_pkg is
    type UART_TB_CONTROL_RECORD is record
    info: unsigned(7 downto 0);
    end record;
    procedure send_message(
    data_to_send: unsigned(7 downto 0);
    signal request: out UART_TB_CONTROL_RECORD;
    signal response: in boolean );
    begin
    -- issue command to UART_TX
    request.info <= data_to_send;
    -- wait for response signal to toggle
    wait on response;
    end
    endpackage

    Now, of course, we must modify our UART_TX so that
    it can cope with this request/response protocol.
    That costs a couple more ports, but thanks to the
    record type, there will ONLY be two such ports
    no matter how complex the protocol.

    entity UART_TX is
    port (
    TXD: out std_logic; -- signals to DUT
    CTS: in std_logic; -- signals from DUT
    REQ: in UART_TB_CONTROL_RECORD;
    RSP: out boolean);
    end;
    architecture OK of UART_TX is
    signal response_toggle: boolean;
    begin
    Transmitter: process
    procedure Tx(bit_to_send: std_logic);
    begin
    TXD <= bit_to_send;
    wait for BIT_TIME;
    end;
    procedure Tx(byte_to_send: unsigned(7 downto 0));
    begin
    wait until CTS = '1'; -- handshake
    Tx('0'); -- start bit
    for i in byte_to_send'reverse_range loop
    Tx(byte_to_send(i)); -- LSB first
    end loop;
    Tx('1'); -- stop bit
    end;
    begin -- here's the management process
    -- Wait for the TB to request a new action
    wait on REQ'transaction;
    -- Implement the requested action
    Tx(REQ.info);
    -- Indicate completion
    response_toggle <= not response_toggle;
    -- then loop back to wait for next command
    end process;
    -- Echo out the response indication
    RSP <= response_toggle;
    end;

    Now we're really ready to go. In your TB, create an
    instance of UART_TX with its TXD and CTS signals
    connected up to the DUT in the obvious way. Of course,
    in your real world there will be many more signals than
    two - but the same principles apply. Then, in the TB,
    provide signals for the REQ and RSP ports of your UART_TX
    instance. And then a process in the TB can generate
    stimulus like this:

    send_many_characters: process
    variable L: line; -- to get stimulus data from a file?
    variable Ch: character;
    variable V: unsigned(7 downto 0);
    begin
    -- Read L from a file using usual textio stuff.
    -- Or anything else to get some interesting data.
    -- Then, send the characters stored in L to the UART:
    for i in L'range loop
    Ch := L(i);
    V := to_unsigned(character'pos(Ch), V'length);
    send_message(V, REQ_signal, RSP_signal);
    end loop;
    end process;

    Now the send_message procedure (defined in the package)
    has only a small number of arguments, regardless of the
    complexity of your physical interface - the complexity
    is abstracted-away in the transaction record type.

    If you find yourself calling the procedure send_message()
    many times in the same process, with the same signal
    arguments every time, you can tidy that up too:

    process
    ....
    -- Simplified local version of the package procedure
    procedure send_message(V: unsigned(7 downto 0);
    begin
    -- Call the package procedure, with appropriate
    -- signals provided as arguments. These signals
    -- must be declared in the architecture, of course.
    send_message(V, REQ_signal, RSP_signal);
    end;
    begin -- main body of process
    -- calls the local procedure, which fills in the signals
    send_message("00001111"); -- it's that simple
    send_message("10101010");
    ...

    I'm aware that this example has been quite sketchy,
    and uses some "advanced" (whatever that means)
    tricks like 'transaction, but I hope at least
    it points you in some interesting directions.
    Many details yet to fill in - initialization,
    declarations, you name it. Over to you.

    You can make this work the other way, too, for
    models that monitor (rather than drive) a DUT
    interface. Same idea applies: convert the messy
    signal-wiggles into a transaction record, and work
    with that in the TB. Capture the signal-to-record
    converter block as an entity, instantiate it with
    ports connected to DUT signals and just a couple
    of ports to expose the collected transaction
    record. Hook up those latter ports to TB-only
    signals so that the rest of the TB can see them.

    There are several interesting variants on this
    theme: for example, the blocks can be coded as
    procedures and "instanced" as concurrent
    procedure calls. That's convenient, but it
    causes some trouble with the 'transaction
    trickery, so personally I prefer to use entities.

    Enjoy, and thanks for asking all the right questions.
    --
    Jonathan Bromley
     
    Jonathan Bromley, Mar 29, 2011
    #6
  7. M. Norton

    M. Norton Guest

    On Mar 29, 4:08 pm, Jonathan Bromley <>
    wrote:
    > There are other issues too.  Your bus model probably
    > needs to keep track of some persistent state, which
    > you can't comfortably do with a package either.


    Glad you mentioned this. I hadn't even gotten to the point where I
    was concerned about persistent state. My initial examples were pretty
    straightforward and simple, but I do have in mind trying to create a
    PCI bus model to try to test this core we seem to be using and reusing
    and that absolutely would be a far more complex driver and would
    require persistent state for some transactions.

    > I'm aware that this example has been quite sketchy,
    > and uses some "advanced" (whatever that means)
    > tricks like 'transaction, but I hope at least
    > it points you in some interesting directions.
    > Many details yet to fill in - initialization,
    > declarations, you name it.  Over to you.


    Absolutely, sketchy is fine. I'm looking for theory mainly and this
    has given me a lot to chew on. In the past I have used entities as
    DUT drivers, usually for complex packet data, but I hadn't really
    thought of abstracting it a level further and giving myself command
    hooks into it. This also neatly dodges the issue of clocks. I was
    thinking about that when I wrote the little snippet asking about what
    Andy suggested, and was realizing I would need to pass in the clock as
    well as everything else, which seems a little on the messy side.
    Ideally the procedure call would be transaction and message related
    information only.

    And having a variety of tools in the toolbox is never a bad thing.
    Seems to me there's times when Mike's strategy is simplest, and then
    Andy's and then this feels like the sledgehammer.

    > Enjoy, and thanks for asking all the right questions.


    I appreciate it.

    Best regards,
    Mark
     
    M. Norton, Mar 29, 2011
    #7
  8. On 3/29/2011 1:26 PM, M. Norton wrote:

    > Yeah, this is essentially what I'm doing right now, one process
    > describing test over time (with loops and whatnot as need requires)
    > and then a lot of local procedures to handle the transactions. The
    > only trouble I've got is that I end up repeating myself quite a lot
    > over a number of testbenches that use identical or more-likely near-
    > identical protocols. All it takes is a few names changed and my cut
    > and paste of previously written transaction procedures gets smoked.


    I try to do the heavy lifting in functions, which are easily packaged
    with required and default parameters.
    I use simple procedures with no parameters when possible for readable
    code.

    > I suppose I'm glad to know I'm not too far off in what I've come up
    > with but it'd be nice to find something that's more reusable. Thanks
    > for the information!


    Functions are easily packaged and reused.
    Procedures can at least eliminate the local
    cut and paste.

    -- Mike Treseler
     
    Mike Treseler, Mar 30, 2011
    #8
  9. M. Norton

    KJ Guest

    On Mar 29, 12:42 pm, "M. Norton" <> wrote:

    >
    > So, in summary does anyone have any technique or best practice for how
    > to organize bus interfaces for passing in and out of procedure calls?
    >


    1. Similar to what Jonathon suggested, but a bit easier (I think) to
    draw good boundary lines for the testing entity is to model real
    parts. FPGAs in real applications do not exist untethered to the rest
    of the world, they are connected to real parts on a circuit board so
    your 'FPGA testbench' could (I think 'should') be a model of that PCBA
    (and surrounding systems)...which means that if you model the parts
    that go on that PCBA and connect them per the netlist then you're
    modelling your real system. In your case, you had mentioned in later
    posts about modelling a PCI bus. I'm guessing that there is a
    processor on the board, so model that processor and you'll have your
    PCI bus. Maybe for starters, the PCI bus is about all that you will
    model, the rest can come later when needed. In any case, by doing
    this, you'll be refining your cheezy processor model over time and
    making it closer to the real thing which will make that model better
    and better over time.

    What I've also found is that as I model more of the real system, there
    comes less of a need for that 'magic communications interface' between
    two parts that Jonathon mentioned in his post. If needed, I simply
    put that interface into a 'magic comms' package which is project
    specific (but can be named the same for each project). For the most
    part, simulations become watching the system perform whatever it is
    that you set it up to do without too much 'magic' communications
    between components.

    2. Standardize on a comm interface. For the most part, interfaces
    simply need to read and write. Use Avalon as a guide, at the low
    level you can write once and use over and over that handshake for any
    interface. Then the task becomes to create an 'Avalon to PCI' widget
    (as an example). If that same type of PCI interface is needed in a
    different application that is a totally different processor, then
    guess what? You can use that Avalon to PCI widget that you created in
    your new processor. Both processors could use the same Avalon
    protocol on the one side with PCI on the other.

    3. As has been pointed out and you've discovered, removing the
    signals from procedures means putting them into a process which can be
    a pain. However, if you implement #2, then this becomes a
    straightforward wrapper to portion of your your part model from #1.
    That description is likely unique to that model so you wouldn't really
    have a need to 'reuse it' somewhere else other than to plop down your
    part model from #1. However, there can still be cutting and pasting
    within that part model. Consider a processor model where you
    implement the equivalent of several 'threads' that wake up and run at
    appropriate times. Each thread would be a process, therefore each
    'thread' would have to have the shorthand procedures cut and pasted.
    A pain, but again those procedures are only of use to that part model
    so you're likely editing a single file.

    Kevin Jennings
     
    KJ, Mar 30, 2011
    #9
  10. M. Norton

    Andy Guest

    On Mar 29, 3:36 pm, "M. Norton" <> wrote:
    > On Mar 29, 2:51 pm, Andy <> wrote:
    >
    > > I've used a single record with an inout port on the procedure(s). All
    > > of the elements of the record must be resolved types. I declare an
    > > "undriven" constant of that record such that the elements that are
    > > never used as outputs by each process are harmlessly driven to 'Z'.

    >
    > I've read and reread this a bit and while I get the theory of what
    > you're doing with the constant, I'm not sure how it's being applied.
    > So if we've got a package with a record containing the signal elements
    > of a bus, including control lines, that would allow harnessing up a
    > generic procedure to a testbench component.  However when do you apply
    > the constant that's got things set to high impedance?  Does that
    > happen inside the procedure at the beginning of the procedure and then
    > subsequent assignments override it?
    >
    > So, possibly something like this?
    >
    >    procedure my_generic_write( ... ; signal my_bus :
    > T_BUS_RECORD; ... ) is
    >    begin
    >         my_bus <= C_HARMLESSLY_DRIVEN_TO_Z;
    >         wait until rising_edge(some_clk);
    >         my_bus.address <= some_address;
    >         my_bus.wr_cyc <= '1';
    >         wait until rising_edge(some_clk);
    >         my_bus.data <= some_data;
    >         my_bus.wren <= '1';
    >         wait until rising_edge(some_clk);
    >         my_bus_wren <= '0';
    >         wait until rising_edge(some_clk);
    >         my_bus.wr_cyc <= '0';
    >         wait until rising_edge(some_clk);
    >         my_bus <= C_HARMLESSLY_DRIVEN_TO_Z;
    >    end procedure my_generic_write;
    >
    > Then during that procedure call, all the my_bus.rd_cyc, my_bus.rd_stb,
    > etc would remain Z.  I will have to try that out and see how it goes.
    > Seems like it might do what I want (assuming I have your intent
    > divined correctly).
    >
    > Thanks for the information!
    > Mark


    Yes, you'd use it like that in the procedure(s), but you also need to
    make sure that processes in the DUT that interact with the record also
    drive the constant onto the signal, so that the DUT does not end up
    driving 'U' on input elements of the record.

    Andy
     
    Andy, Mar 30, 2011
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Doug Miller
    Replies:
    4
    Views:
    686
    Jonathan Bromley
    Jan 30, 2004
  2. Mike Treseler
    Replies:
    1
    Views:
    687
    Jim Lewis
    Jan 29, 2004
  3. M. Norton
    Replies:
    1
    Views:
    762
  4. Ken Varn
    Replies:
    0
    Views:
    479
    Ken Varn
    Apr 26, 2004
  5. Replies:
    0
    Views:
    98
Loading...

Share This Page