• Re: Disabled generate gives compile error in Modelsim

    From KJ@21:1/5 to Stef on Sun Dec 11 14:10:56 2022
    On Friday, December 9, 2022 at 6:20:14 AM UTC-5, Stef wrote:
    <snip>
    If I declare 'sigio' as 'inout', as below and as I got the model, then when I simulate it, the signals in the simulation remain 'U'. So somehow the 'gentest' model drives the 'sigio' signal although the generic 'this_is_a_simulation' has been set to
    true.

    When you declared sigio as inout, you're saying that there will be a driver for this signal. But in your testbench you've connected sigio to the signal clk, and you have a process that drives clk. Regardless of how if this_is_a_simulation is set there
    will be problems.
    * if this_is_a_simulation = true then sigio will get set to '1'. But since clk is also driving the signal to either a '0' or '1', half the time the two drivers will be in conflict. When clk happens to be set to '1' is the only time that you will get a '
    1'. The other half of the time you'll have a '1' and a '0' being driven...resulting in unknown
    * if this_is_a_simulation = false then the gentest entity will say that there is a driver for 'sigio', but since the architecture doesn't actually drive the signal, sigio will be unknown and will always override the '0' and '1' that clk is being set to.
    The result of that condition is an unknown, all of the time.

    You could work around the problem for "if this_is_a_simulation = false" by changing the entity to give a default of 'Z' like this: "sigio : inout std_logic := 'Z'; -- Original line". Now sigio will have a driver of 'Z' at t=0 and 'clk' will always be
    able to override the 'Z' with a '0' or '1'.

    I then just comment out the 'rtlblk' generate, the model simulates as expected.

    Not sure what you mean with "as expected". This design is fatally flawed by having two drivers both trying to drive the same signal at the same time. I have no idea what you're trying to do inside gentest with sigio in the first place. Either sigio
    should be of type 'in' and the "sigio <= 1'" statement should be removed OR if it really is meant to be of type 'inout', then you should only be driving sigio when nothing on the outside (i.e. the testbench signal clk) is actively driving it to '0' or '1'
    . During that time clk should be driven to 'Z' in the testbench. I have no idea how you expect gentest to know this based on the posted code. Generally, when there are multiple potential drivers of a signal, there is also another signal that tells
    both sides who has control. Check how something like an 74xx244 IC works. There is an OE input signal that tells the IC when it should actively drive the signal low or high and when it should tri-state the outputs.

    Kevin Jennings

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stef@21:1/5 to All on Mon Dec 12 10:26:41 2022
    On 2022-12-11 KJ wrote in comp.lang.vhdl:
    On Friday, December 9, 2022 at 6:20:14 AM UTC-5, Stef wrote:
    <snip>
    If I declare 'sigio' as 'inout', as below and as I got the model, then when I simulate it, the signals in the simulation remain 'U'. So somehow the 'gentest' model drives the 'sigio' signal although the generic 'this_is_a_simulation' has been set to
    true.

    When you declared sigio as inout, you're saying that there will be a driver for this signal. But in your testbench you've connected sigio to the signal clk, and you have a process that drives clk. Regardless of how if this_is_a_simulation is set
    there will be problems.

    Okay, just the fact that the signal is declared as inout is a problem
    already.

    * if this_is_a_simulation = true then sigio will get set to '1'. But since clk is also driving the signal to either a '0' or '1', half the time the two drivers will be in conflict. When clk happens to be set to '1' is the only time that you will get
    a '1'. The other half of the time you'll have a '1' and a '0' being driven...resulting in unknown
    * if this_is_a_simulation = false then the gentest entity will say that there is a driver for 'sigio', but since the architecture doesn't actually drive the signal, sigio will be unknown and will always override the '0' and '1' that clk is being set to.
    The result of that condition is an unknown, all of the time.

    You could work around the problem for "if this_is_a_simulation = false" by changing the entity to give a default of 'Z' like this: "sigio : inout std_logic := 'Z'; -- Original line". Now sigio will have a driver of 'Z' at t=0 and 'clk' will always be
    able to override the 'Z' with a '0' or '1'.


    In the examples I tried to reduce the problem down to a small model and
    I may have simpified it too much. In the "if this_is_a_simulation =
    false" situation, the sigio in gentest.vhd is connected to the clock
    pin of an instantiated PLL block and according to the code I inherited,
    this pin is an inout signal (you would expect an in, but it is inout).

    I then just comment out the 'rtlblk' generate, the model simulates as expected.

    Not sure what you mean with "as expected". This design is fatally flawed by having two drivers both trying to drive the same signal at the same time. I have no idea what you're trying to do inside gentest with sigio in the first place. Either sigio
    should be of type 'in' and the "sigio <= 1'" statement should be removed OR if it really is meant to be of type 'inout', then you should only be driving sigio when nothing on the outside (i.e. the testbench signal clk) is actively driving it to '0' or '1'
    . During that time clk should be driven to 'Z' in the testbench. I have no idea how you expect gentest to know this based on the posted code. Generally, when there are multiple potential drivers of a signal, there is also another signal that tells
    both sides who has control. Check how something like an 74xx244 IC works. There is an OE input signal that tells the IC when it should actively drive the signal low or high and when it should tri-state the outputs.


    What I "expect" is that I can simulate the
    model (this_is_a_simulation = true) with the testbench
    driving the clk signal. And that by setting this_is_a_simulation
    to false, I can generate the logic for the real FPGA, where clk is
    connected to an IO pin and must for some reason be inout.

    I now solve this by commenting in/out a block of code. This works, but
    is error prone. Luckily forgetting to uncomment the PLL block is easily
    spotted as it results in a fast run with an empty FPGA as a result. ;-)

    As I said before, I got this code with this construct and could not get
    is to work and I do not know if it ever worked.

    I expected the problem to be in the "if condition generate" part of the
    code. But of I understand you correctly, the problem already is in
    declaring the signal as inout.

    But what should a compiler do with a conditional generate block that is
    off? Should it be completely ignored or should it still be tested for
    validity?

    Say we have an entity with this port:

    port( signal_in : in std_logic );

    And then somewhere in the architecture we have this:

    testblock : if false generate
    signal_in <= '1';
    end generate;

    Should the compiler ignore driving a input signal or should it give an
    error although testblock is "off"?


    --
    Stef

    Walk softly and carry a BFG-9000.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From KJ@21:1/5 to Stef on Tue Dec 13 17:33:28 2022
    On Monday, December 12, 2022 at 4:26:46 AM UTC-5, Stef wrote:
    On 2022-12-11 KJ wrote in comp.lang.vhdl:
    On Friday, December 9, 2022 at 6:20:14 AM UTC-5, Stef wrote:

    In the examples I tried to reduce the problem down to a small model and
    I may have simpified it too much. In the "if this_is_a_simulation =
    false" situation, the sigio in gentest.vhd is connected to the clock
    pin of an instantiated PLL block and according to the code I inherited,
    this pin is an inout signal (you would expect an in, but it is inout).

    This doesn't make any sense. Is gentest connected to an input or an output of the PLL block? Whichever it is, gentest should be the opposite. This is pretty basic, you connect inputs to outputs and vice versa. You don't connect outputs together, you
    don't connect inputs. Pretty simple.

    Not sure what you mean with "as expected". This design is fatally flawed by having two drivers both trying to drive the same signal at the same time. I have no idea what you're trying to do inside gentest with sigio in the first place. Either sigio
    should be of type 'in' and the "sigio <= 1'" statement should be removed OR if it really is meant to be of type 'inout', then you should only be driving sigio when nothing on the outside (i.e. the testbench signal clk) is actively driving it to '0' or '1'
    . During that time clk should be driven to 'Z' in the testbench. I have no idea how you expect gentest to know this based on the posted code. Generally, when there are multiple potential drivers of a signal, there is also another signal that tells both
    sides who has control. Check how something like an 74xx244 IC works. There is an OE input signal that tells the IC when it should actively drive the signal low or high and when it should tri-state the outputs.

    What I "expect" is that I can simulate the
    model (this_is_a_simulation = true) with the testbench
    driving the clk signal. And that by setting this_is_a_simulation
    to false, I can generate the logic for the real FPGA, where clk is
    connected to an IO pin and must for some reason be inout.


    This doesn't make much sense either. You shouldn't be changing logic to do simulation. The whole point of simulation is to have a model of the real system. If you are making logic changes "for simulation", you are most likely making a mistake that you
    will then have to figure out.

    I now solve this by commenting in/out a block of code. This works, but
    is error prone. Luckily forgetting to uncomment the PLL block is easily spotted as it results in a fast run with an empty FPGA as a result. ;-)


    Error prone is a polite way to put it. Of no value at all would be another.

    As I said before, I got this code with this construct and could not get
    is to work and I do not know if it ever worked.


    That's why you run the simulator...to find out what's wrong. But you don't start by connecting outputs together.

    I expected the problem to be in the "if condition generate" part of the code. But of I understand you correctly, the problem already is in
    declaring the signal as inout.


    The problem is that you are thinking that a real design would connect two outputs together. It has nothing to do with VHDL at all.

    But what should a compiler do with a conditional generate block that is
    off? Should it be completely ignored or should it still be tested for validity?


    The compiler already did the right thing.

    Say we have an entity with this port:

    port( signal_in : in std_logic );

    And then somewhere in the architecture we have this:

    testblock : if false generate
    signal_in <= '1';
    end generate;

    Should the compiler ignore driving a input signal or should it give an
    error although testblock is "off"?


    As long as the syntax is correct (and your signal assignment to signal_in is), there is no error for the compiler to report. What error do you think should be reported? The compiler does not report on design errors such as connecting two outputs
    together as you did. Instead it shows you the results of that design error which is that the resulting output is undefined.

    If you want the compiler itself to help you out some more, change all your usages of 'std_logic' to 'std_ulogic' in gentest as well as the testbench. Then the compilation will fail because signals of type 'std_ulogic' can have only one driver. You won'
    t even be able to start the simulation until you fix the error. Use of std_ulogic rather than std_logic finds the design errors that you are creating right at compile time and gives you all the information about where the problem is located in the code.
    Using std_logic only in situations where their truly can be multiple drivers such as some shared bus like the data bus between a processor and memory. In all other cases, use std_ulogic. FPGAs do not support multiple driver designs for any internal
    signal.

    Kevin Jennings

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stef@21:1/5 to All on Wed Dec 14 13:08:31 2022
    On 2022-12-14 KJ wrote in comp.lang.vhdl:
    On Monday, December 12, 2022 at 4:26:46 AM UTC-5, Stef wrote:
    On 2022-12-11 KJ wrote in comp.lang.vhdl:
    On Friday, December 9, 2022 at 6:20:14 AM UTC-5, Stef wrote:

    In the examples I tried to reduce the problem down to a small model and
    I may have simpified it too much. In the "if this_is_a_simulation =
    false" situation, the sigio in gentest.vhd is connected to the clock
    pin of an instantiated PLL block and according to the code I inherited,
    this pin is an inout signal (you would expect an in, but it is inout).

    This doesn't make any sense. Is gentest connected to an input or an output of the PLL block? Whichever it is, gentest should be the opposite. This is pretty basic, you connect inputs to outputs and vice versa. You don't connect outputs together,
    you don't connect inputs. Pretty simple.


    In the design I inherited the PLL pin is a package pin and declared as
    inout. Why this was done, I do not know. So two inouts are connected
    together. And yes, I am aware that you don't connect outputs or inputs
    together (I am and electronics engineer). I will see if it can be changed
    to an input to get rid of this problem.

    Not sure what you mean with "as expected". This design is fatally flawed by having two drivers both trying to drive the same signal at the same time. I have no idea what you're trying to do inside gentest with sigio in the first place. Either sigio
    should be of type 'in' and the "sigio <= 1'" statement should be removed OR if it really is meant to be of type 'inout', then you should only be driving sigio when nothing on the outside (i.e. the testbench signal clk) is actively driving it to '0' or '1'
    . During that time clk should be driven to 'Z' in the testbench. I have no idea how you expect gentest to know this based on the posted code. Generally, when there are multiple potential drivers of a signal, there is also another signal that tells both
    sides who has control. Check how something like an 74xx244 IC works. There is an OE input signal that tells the IC when it should actively drive the signal low or high and when it should tri-state the outputs.

    What I "expect" is that I can simulate the
    model (this_is_a_simulation = true) with the testbench
    driving the clk signal. And that by setting this_is_a_simulation
    to false, I can generate the logic for the real FPGA, where clk is
    connected to an IO pin and must for some reason be inout.


    This doesn't make much sense either. You shouldn't be changing logic to do simulation. The whole point of simulation is to have a model of the real system. If you are making logic changes "for simulation", you are most likely making a mistake that
    you will then have to figure out.


    Aparently the PLL could not be simulated, so the clock came directly
    from the test bench. So some switch between testbench and pll clock must
    be made between simulation and hardware generation. Probably not the
    best solution, as you say. But this is how I got it. And I try to
    understand why they did this before changing everything.

    I now solve this by commenting in/out a block of code. This works, but
    is error prone. Luckily forgetting to uncomment the PLL block is easily
    spotted as it results in a fast run with an empty FPGA as a result. ;-)


    Error prone is a polite way to put it. Of no value at all would be another.

    I would not say that, only the clock source is changed from PLL'ed input
    to direct input (at the intended PLL frequency).

    As I said before, I got this code with this construct and could not get
    is to work and I do not know if it ever worked.


    That's why you run the simulator...to find out what's wrong. But you don't start by connecting outputs together.

    I expected the problem to be in the "if condition generate" part of the
    code. But of I understand you correctly, the problem already is in
    declaring the signal as inout.


    The problem is that you are thinking that a real design would connect two outputs together. It has nothing to do with VHDL at all.

    No I do not think that, what makes you believe I do?

    But what should a compiler do with a conditional generate block that is
    off? Should it be completely ignored or should it still be tested for
    validity?


    The compiler already did the right thing.

    Say we have an entity with this port:

    port( signal_in : in std_logic );

    And then somewhere in the architecture we have this:

    testblock : if false generate
    signal_in <= '1';
    end generate;

    Should the compiler ignore driving a input signal or should it give an
    error although testblock is "off"?


    As long as the syntax is correct (and your signal assignment to signal_in is), there is no error for the compiler to report. What error do you think should be reported? The compiler does not report on design errors such as connecting two outputs
    together as you did. Instead it shows you the results of that design error which is that the resulting output is undefined.


    The syntax in itself is correct, but assigning a value to an input is
    not. So I would not expect an error on that code, as do you, I read in
    the above. However when I compile this in Modelsim:

    rtlblk : if this_is_a_simulation = false generate
    sigio <= '1';
    sigout <= '1';
    end generate;

    With this_is_a_simulation set to true and sigio declared as in, I get
    the following error

    -- Compiling architecture behav of gentest
    ** Error: ../gentest.vhd(19): Cannot drive signal 'sigio' of mode IN.

    This is not what I expect, why is the assignment not ignored?

    This is the core of my original question. What is the expected behaviour
    when such generate blocks are disabled and contain incorrect code?

    If you want the compiler itself to help you out some more, change all your usages of 'std_logic' to 'std_ulogic' in gentest as well as the testbench. Then the compilation will fail because signals of type 'std_ulogic' can have only one driver. You
    won't even be able to start the simulation until you fix the error. Use of std_ulogic rather than std_logic finds the design errors that you are creating right at compile time and gives you all the information about where the problem is located in the
    code. Using std_logic only in situations where their truly can be multiple drivers such as some shared bus like the data bus between a processor and memory. In all other cases, use std_ulogic. FPGAs do not support multiple driver designs for any
    internal signal.

    No, FPGAa don't have internal tri-state signals. Changing to std_ulogic
    sounds like a good idea. Is this what you normally use for internal logic?

    --
    Stef

    Two wrongs are only the beginning.
    -- Kohn

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From KJ@21:1/5 to Stef on Sat Dec 17 11:34:07 2022
    On Wednesday, December 14, 2022 at 7:08:35 AM UTC-5, Stef wrote:
    On 2022-12-14 KJ wrote in comp.lang.vhdl:
    On Monday, December 12, 2022 at 4:26:46 AM UTC-5, Stef wrote:
    On 2022-12-11 KJ wrote in comp.lang.vhdl:
    On Friday, December 9, 2022 at 6:20:14 AM UTC-5, Stef wrote:


    This doesn't make any sense. Is gentest connected to an input or an output of the PLL block? Whichever it is, gentest should be the opposite. This is pretty basic, you connect inputs to outputs and vice versa. You don't connect outputs together, you
    don't connect inputs. Pretty simple.

    In the design I inherited the PLL pin is a package pin and declared as inout. Why this was done, I do not know. So two inouts are connected together. And yes, I am aware that you don't connect outputs or inputs together (I am and electronics engineer). I will see if it can be changed
    to an input to get rid of this problem.

    The place to look is in the documentation for the PLL, not in the VHDL code. If the PLL documentation says that there are times when the pin is driven externally and other times that it is producing an output then it should be described in VHDL as an
    inout. I doubt that to actually be the case based on what you've described so far. However, if it is truly a bi-directional signal, then that same PLL documentation will also describe the conditions under which the PLL uses the pin as an input and the
    times it is an output. VHDL is a description of hardware, it is not the place one should go to as the definition of how the signal works.

    If the documentation says the pin is an output, then it is. If the VHDL says it is an inout, the VHDL is not correctly describing the PLL which means the VHDL is wrong and should be corrected.

    Aparently the PLL could not be simulated, so the clock came directly
    from the test bench. So some switch between testbench and pll clock must
    be made between simulation and hardware generation. Probably not the
    best solution, as you say. But this is how I got it. And I try to
    understand why they did this before changing everything.

    Not wanting to make changes before understanding is a good approach. But now I think we're finally getting to the nuts and bolts of the problem you're actually looking at which is that there is no simulation model for the PLL, correct? What you should
    then be doing is creating an if/generate around the PLL itself, not in some separate entity which is how it appears that you are currently doing it.

    So in the FPGA design there is someplace where you are instantiating a component that is the PLL. All FPGA PLLs will have an input clock and produce output clocks and will have multiple parameters to configure it. The instantiation then will look
    something like this...

    MyPll : ThePll(InputClock, OutputClock, ...);

    So, if you really don't have a simulation model for the PLL you would modify this single instantiation to be the following. Note that what is being switched between based on this_is_a_simulation will be in the same entity/architecture. What you
    originally posted had the process that generated the clock in one entity (the testbench). You don't really show where the instantiation of the PLL is located, but I'm assuming it is in gentest which I'm guessing is the FPGA design. Regardless though,
    this is how you structure things in the VHDL code that are to be 'switched' out based on some simulation parameter. The thing that is receiving the PLL's OutputClock signal is not modified at all. In particular, there is no need to add code to drive
    some sigio signal under some conditions.

    Also note that for the simulation part, I've simply copied the code you posted from the testbench just renaming the 'clk' signal to be the same name as the clock signal output from the PLL. PLLs also tend to have an output that says when the PLL has
    locked on to the input and the output clock is now valid. If you're using such a signal (or other PLL output signals), you would connect them to the PLL component in the rtlblk for the MyPll but then also generate logic in the simblk to create that
    output. Maybe it's something like "locked <= '0', '1' after 1 us;"

    simblk : if this_is_a_simulation = true generate
    process
    begin
    OutputClock <= '0';
    wait for 10ns;
    OutputClock <= '1';
    wait for 10ns;
    end process;
    -- Add code for any other PLL outputs that you're using here

    Having said all that, you might want to double check your FPGA tools. Typically there is a simulation model of the PLL. In that case you wouldn't make any changes to the source code of the FPGA design as described above. Instead all you need to do is
    add the simulation model VHDL file to the simulation project. That would be the best approach since it gets you the correct simulation model as opposed to something that is cobbled together. Which software are you using to build the FPGA design? I
    know Altera (now Intel) does create PLL simulation models. Haven't used any others in quite a while.


    The problem is that you are thinking that a real design would connect two outputs together. It has nothing to do with VHDL at all.

    No I do not think that, what makes you believe I do?

    Because you added code in gentest to explicitly drive a signal that is already being driven by the testbench.

    The syntax in itself is correct, but assigning a value to an input is
    not. So I would not expect an error on that code, as do you, I read in
    the above. However when I compile this in Modelsim:
    rtlblk : if this_is_a_simulation = false generate
    sigio <= '1';
    sigout <= '1';
    end generate;
    With this_is_a_simulation set to true and sigio declared as in, I get
    the following error

    -- Compiling architecture behav of gentest
    ** Error: ../gentest.vhd(19): Cannot drive signal 'sigio' of mode IN.

    This is not what I expect, why is the assignment not ignored?

    Because a VHDL generate statement is not like a C pre-processor where it ignores entire blocks of code. For example, in C you can have the following which will compile just fine and not produce any problems

    #if false
    alkljdfljk
    #endif

    The equivalent in VHDL would be
    MyGenerate : if false
    alkljdfljk
    end generate

    VHDL will flag 'alkljdfljk' as an error because it analyzes all of the code, even if the conditions imply that the code will never be used. In your case, the error was that you tried to assign a value to an input.

    You may choose to see this as "Why the heck are you complaining about code that will not be used?" or choose to see it as making sure that all of the code, whether it will be used or not, is valid code. In this case, it may be trivial, but consider if
    you had several if/generate statements controlled by various parameters. Would you really want to have to compile all of the possible parameter settings in order to know that every possible combination of parameters compiles correctly? What VHDL is
    doing is validating that every possible if/generate will in fact compile correctly with a single compile.

    This is the core of my original question. What is the expected behaviour when such generate blocks are disabled and contain incorrect code?

    I think I've answered the question here. Hopefully that is the case. If not, chime back in.

    If you want the compiler itself to help you out some more, change all your usages of 'std_logic' to 'std_ulogic' in gentest as well as the testbench. Then the compilation will fail because signals of type 'std_ulogic' can have only one driver. You
    won't even be able to start the simulation until you fix the error. Use of std_ulogic rather than std_logic finds the design errors that you are creating right at compile time and gives you all the information about where the problem is located in the
    code. Using std_logic only in situations where their truly can be multiple drivers such as some shared bus like the data bus between a processor and memory. In all other cases, use std_ulogic. FPGAs do not support multiple driver designs for any internal
    signal.
    No, FPGAa don't have internal tri-state signals. Changing to std_ulogic sounds like a good idea. Is this what you normally use for internal logic?

    Yes, I use std_ulogic for all signals, testbench and design, that have a single driver in 'real life'. Bi-directional interfaces, such as that to an external memory, are the only std_logic signals.

    Kevin Jennings

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stef@21:1/5 to All on Tue Dec 20 10:37:55 2022
    On 2022-12-17 KJ wrote in comp.lang.vhdl:
    On Wednesday, December 14, 2022 at 7:08:35 AM UTC-5, Stef wrote:
    On 2022-12-14 KJ wrote in comp.lang.vhdl:
    On Monday, December 12, 2022 at 4:26:46 AM UTC-5, Stef wrote:
    On 2022-12-11 KJ wrote in comp.lang.vhdl:
    On Friday, December 9, 2022 at 6:20:14 AM UTC-5, Stef wrote:


    This doesn't make any sense. Is gentest connected to an input or an output of the PLL block? Whichever it is, gentest should be the opposite. This is pretty basic, you connect inputs to outputs and vice versa. You don't connect outputs together, you
    don't connect inputs. Pretty simple.

    In the design I inherited the PLL pin is a package pin and declared as
    inout. Why this was done, I do not know. So two inouts are connected
    together. And yes, I am aware that you don't connect outputs or inputs
    together (I am and electronics engineer). I will see if it can be changed
    to an input to get rid of this problem.

    The place to look is in the documentation for the PLL, not in the VHDL code. If the PLL documentation says that there are times when the pin is driven externally and other times that it is producing an output then it should be described in VHDL as an
    inout. I doubt that to actually be the case based on what you've described so far. However, if it is truly a bi-directional signal, then that same PLL documentation will also describe the conditions under which the PLL uses the pin as an input and the
    times it is an output. VHDL is a description of hardware, it is not the place one should go to as the definition of how the signal works.

    If the documentation says the pin is an output, then it is. If the VHDL says it is an inout, the VHDL is not correctly describing the PLL which means the VHDL is wrong and should be corrected.

    That was my initial thought as well, but the documentation is not very
    clear on this subject:
    PACKAGEPIN: PLL REFERENCE CLOCK pin that serves as the input to the
    SB_PLL40_PAD primitive.

    "serves as an input" is not saying explicitely that it is an 'in'. Could
    be.

    The part is a Lattice iCE40 and the pll entity is created by the PLL configurator in the iCEcube2 tool. If I re-do the configuration, I get
    the exact same PLL entity, with the 'inout' PACKAGEPIN as input clock to
    the PLL.


    Aparently the PLL could not be simulated, so the clock came directly
    from the test bench. So some switch between testbench and pll clock must
    be made between simulation and hardware generation. Probably not the
    best solution, as you say. But this is how I got it. And I try to
    understand why they did this before changing everything.

    Not wanting to make changes before understanding is a good approach. But now I think we're finally getting to the nuts and bolts of the problem you're actually looking at which is that there is no simulation model for the PLL, correct? What you
    should then be doing is creating an if/generate around the PLL itself, not in some separate entity which is how it appears that you are currently doing it.


    I have not searched for a simulation model. I was first trying to get
    the package I got to work, and that does not include the PLL model.

    The iCEcube2 tool creates a wrapper entity for the PLL and this wrapper
    entity was instantiated in the top level. The if/generate was indeed in
    the top level, acting on the wrapper, not on the PLL itself.

    So in the FPGA design there is someplace where you are instantiating a component that is the PLL. All FPGA PLLs will have an input clock and produce output clocks and will have multiple parameters to configure it. The instantiation then will look
    something like this...

    MyPll : ThePll(InputClock, OutputClock, ...);

    So, if you really don't have a simulation model for the PLL you would modify this single instantiation to be the following. Note that what is being switched between based on this_is_a_simulation will be in the same entity/architecture. What you
    originally posted had the process that generated the clock in one entity (the testbench). You don't really show where the instantiation of the PLL is located, but I'm assuming it is in gentest which I'm guessing is the FPGA design. Regardless though,
    this is how you structure things in the VHDL code that are to be 'switched' out based on some simulation parameter. The thing that is receiving the PLL's OutputClock signal is not modified at all. In particular, there is no need to add code to drive
    some sigio signal under some conditions.


    Yes, the simulated clock is generated in the testbench and connected to
    the input that in real life is the input for the PLL input clock.

    in gentest, the PLL is in 'rtlblk' with its output connected to sigout.
    In simulation the external clock is assigned directly to sigout in
    'simblk'.


    Also note that for the simulation part, I've simply copied the code you posted from the testbench just renaming the 'clk' signal to be the same name as the clock signal output from the PLL. PLLs also tend to have an output that says when the PLL has
    locked on to the input and the output clock is now valid. If you're using such a signal (or other PLL output signals), you would connect them to the PLL component in the rtlblk for the MyPll but then also generate logic in the simblk to create that
    output. Maybe it's something like "locked <= '0', '1' after 1 us;"

    simblk : if this_is_a_simulation = true generate
    process
    begin
    OutputClock <= '0';
    wait for 10ns;
    OutputClock <= '1';
    wait for 10ns;
    end process;
    -- Add code for any other PLL outputs that you're using here

    Having said all that, you might want to double check your FPGA tools. Typically there is a simulation model of the PLL. In that case you wouldn't make any changes to the source code of the FPGA design as described above. Instead all you need to do
    is add the simulation model VHDL file to the simulation project. That would be the best approach since it gets you the correct simulation model as opposed to something that is cobbled together. Which software are you using to build the FPGA design? I
    know Altera (now Intel) does create PLL simulation models. Haven't used any others in quite a while.


    It is lattice iCEcube2. I will look into this when I need to make more extensive modifications to the device.


    The problem is that you are thinking that a real design would connect two outputs together. It has nothing to do with VHDL at all.

    No I do not think that, what makes you believe I do?

    Because you added code in gentest to explicitly drive a signal that is already being driven by the testbench.

    Ok, this is where the problem starts. I was expecting the 'rtlblk' to be ignored in simulation, so there would still be a single driver.

    The syntax in itself is correct, but assigning a value to an input is
    not. So I would not expect an error on that code, as do you, I read in
    the above. However when I compile this in Modelsim:
    rtlblk : if this_is_a_simulation = false generate
    sigio <= '1';
    sigout <= '1';
    end generate;
    With this_is_a_simulation set to true and sigio declared as in, I get
    the following error

    -- Compiling architecture behav of gentest
    ** Error: ../gentest.vhd(19): Cannot drive signal 'sigio' of mode IN.

    This is not what I expect, why is the assignment not ignored?

    Because a VHDL generate statement is not like a C pre-processor where it ignores entire blocks of code. For example, in C you can have the following which will compile just fine and not produce any problems

    #if false
    alkljdfljk
    #endif

    As I program more C than VHDL, this was indeed what I was expecting.

    The equivalent in VHDL would be
    MyGenerate : if false
    alkljdfljk
    end generate

    VHDL will flag 'alkljdfljk' as an error because it analyzes all of the code, even if the conditions imply that the code will never be used. In your case, the error was that you tried to assign a value to an input.


    In your previous answer you said, that the compiler checks validity of
    the unused code anyway, but only for correct syntax.
    So an error for "alkljdfljk", but not for "sigio <= '1';", contrary to
    what I observed in Modelsim. This what confused me and that is why I
    posted the exact error description.

    You may choose to see this as "Why the heck are you complaining about code that will not be used?" or choose to see it as making sure that all of the code, whether it will be used or not, is valid code. In this case, it may be trivial, but consider if
    you had several if/generate statements controlled by various parameters. Would you really want to have to compile all of the possible parameter settings in order to know that every possible combination of parameters compiles correctly? What VHDL is
    doing is validating that every possible if/generate will in fact compile correctly with a single compile.


    Okay, I think we are on the same page now. VHDL checks all code as if it
    where used, even when not used.

    This is the core of my original question. What is the expected behaviour
    when such generate blocks are disabled and contain incorrect code?

    I think I've answered the question here. Hopefully that is the case. If not, chime back in.


    Yes, this is answered now. And I now believe the original construct
    probably never worked in the state I got it in. :-(

    If you want the compiler itself to help you out some more, change all your usages of 'std_logic' to 'std_ulogic' in gentest as well as the testbench. Then the compilation will fail because signals of type 'std_ulogic' can have only one driver. You
    won't even be able to start the simulation until you fix the error. Use of std_ulogic rather than std_logic finds the design errors that you are creating right at compile time and gives you all the information about where the problem is located in the
    code. Using std_logic only in situations where their truly can be multiple drivers such as some shared bus like the data bus between a processor and memory. In all other cases, use std_ulogic. FPGAs do not support multiple driver designs for any internal
    signal.
    No, FPGAa don't have internal tri-state signals. Changing to std_ulogic
    sounds like a good idea. Is this what you normally use for internal logic? >>
    Yes, I use std_ulogic for all signals, testbench and design, that have a single driver in 'real life'. Bi-directional interfaces, such as that to an external memory, are the only std_logic signals.

    Kevin Jennings


    --
    Stef

    What's the matter with the world? Why, there ain't but one thing wrong
    with every one of us -- and that's "selfishness."
    -- The Best of Will Rogers

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)