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