tags:

views:

56

answers:

2

I want to describe an entity that can either function normally or be put in a test mode. The general design I have is a top level entity that wraps the "real" entity and a test entity.

I am trying to figure out the best way to express this in VHDL, but I get the feeling I'm overcomplicating things.

Consider a small top-level entity (realistically, there are many more I/Os):

entity toplevelobject is
    port (
        in1 : inout std_logic;
        in2 : inout std_logic;
        out1 : out std_logic;
        out2 : out std_logic;
        testline : in std_logic;
        testclk : in std_logic;
    );

end toplevelobject;

This is supposed to switch between the real functionality and the test mode depending on the state of "testline" (high means test). Note that the test module actually uses everything but clk as an output, even in_*.

architecture test_passthrough of toplevelobject is
    -- This is the actual module
    component real_module
    port (
        in1 : in std_logic;
        in2 : in std_logic;
        out1 : out std_logic;
        out2 : out std_logic;
        clk : in std_logic;
        -- Note absence of "testline"
    );
    end component;

    -- This is the test module, which will just put the clk
    -- signal out on all pins, or play a tune, or something
    component test_module
    port (
        in1 : out std_logic;
        in2 : out std_logic;
        out1 : out std_logic;
        out2 : out std_logic;
        testclk : in std_logic;
        -- Note absence of "testline"
    );
    end component;

    signal real_in1, real_in2 : std_logic;
    signal real_out1, real_out2 : std_logic;

    signal test_in1, test_in2 : std_logic;
    signal test_out1, test_out2 : std_logic;

begin

    real_0 : real_module port map (
        in1 => real_in1,
        in2 => real_in2,
        out1 => real_out1,
        out2 => real_out2,
        clk => clk,
    );

    test_0 : test_module port map (
        in1 => test_in1,
        in2 => test_in2,
        out1 => test_out1,
        out2 => test_out2,
        testclk => clk,
    );

    -- Ports that are outputs on both don't need
    -- much special attention

    out1 <= real_out1 when testline = '0' else test_out1;
    out2 <= real_out2 when testline = '0' else test_out2;

end test_passthrough;

So I have a few questions:

  • For the inout ports, should I have one big process with a case ... when statement that switches on testline? Or a process for each I/O with an if statement? Theoretically I figure that many smaller processes are executed concurrently instead of sequentially, but will it actually make a difference to simulation or synthesis? For example:

    passthrough_in1 : process(testline, in1, test_in1) is
    begin
        if testline = '0' then
            real_in1 <= in1;
        else
            in1 <= test_in1;
        end if;
    end process passthrough_in1;
    

...vs...

    passthrough_all : process(in1, test_in1, in2, test_in2, testline) is

        case testline is
            when '0' =>
                real_in1 <= in1;
                real_in2 <= in2;
            when '1' =>
                in1 <= test_in1;
                in2 <= test_in2;
        end case;

    end process passthrough_all;
  • Is this a sane approach or is there something simpler?
  • I'm confused about sensitivity — do I need passthrough_in1 (or even passthrough_all to be sensitive to anything other than testline?
  • Do I need the real_in1/test_in1 to select between the two wrapped entities? Or is there another way to say "if testline is high, connect test_module output in_1 to the toplevelobject I/O in_1?
A: 

Maybe I don't fully understand what you're trying to do, but in a typical VHDL testbench:

  • Your "real_module" code is left as it is. No changes are made to it when it is tested.
  • A second module, akin to your "toplevelobject" is made. This is typically called a testbench module.
  • The toplevelobject testbench instantiates real_module.
  • The testbench usually has no inputs, and doesn't really need outputs (depending on the situation and the testing software used).
  • The testbench has sequential logic that drives the inputs of real_module.
  • If you're using testing software such as ModelSim, the inputs and outputs of real_module can be plotted over time to watch the behaviour of real_module as it is driven by your testbench.

What software are you using? I can dig up an old testbench example from a university project a couple of years ago if it would be of any help to you.

Reinderien
I think you misunderstand. I actually want to end up with a physical device which, when in circuit, should enter testing mode when the voltage on the pin for `testline` is logic high, otherwise it performs as normal. I am trying to do this without disturbing the existing VHDL for the real module as much as that's possible.
detly
+1  A: 

If I understand you correctly your testmodule drives the (badly named - I assume in the real code they make more sense :) in1,2 ports?

If so, you need to do something like this:

real_in1 <= in1;
in1 <= test_in1 when testline = '1' else 'Z';

That way in non-test-mode the in1 signal will be driven by a 'Z', so the external proper in1 signal can override it.

You can represent this in various other ways (like the processes that you described), all of which should come out being equal in the simulator. The downside of the "all in one process" option is that you'll need to keep what might end up as an enormous sensitivity list up to date. Doing it one process per signal is just a long winded way of what I did above.

To save some code and copy/paste effort, you could potentially push those two lines of code into an entity of their own and then instance it many times - in that case, I'd put the instance and port map all on one line, but that would offend some coding standards...

This all assumes I've understood the problem correctly!

Martin Thompson
Yes, they make more sense in the real one... but there's about 60 of them :) In this example, though, it's more that they designate "pins that would be inputs if it were just the real module." I had not thought about the 'Z' option... I figured I would need to see how to set the tristate settings for the pins on my particular device, so I should check to see if that will come out the same in synthesis. Oh, and I really like the idea of the separate "switcher" entity... even if it doesn't save code, it *does* mean I can correct any mistakes in just one place.
detly
One problem with the "switcher entity" idea is that some inputs are just single signals and others are vectors. Still, it's better than the verbatim approach.
detly
Make a switcher that accepts an unconstrained std_logic_vector - that will work for all the vectors then. For the single bits: pass them into the vector one (probably with a slv cast I think) - they'll be seen as a slv(0 to 0). You could create a single_bit wrapper to do this for you, depending on where your casting-tolerance lies :)
Martin Thompson