2
\$\begingroup\$

I am trying to connect a microcontroller(cortex m3) and a fpga(actel a3p060). I am able to read/write successfully with 16 bit databus. My modules in vhdl is structured as follows:

  1. Top module(interface with controller)
  2. sub module where I am having a frequency divider.

The idea is to generate different frequencies fed by the controller to the fpga. In the main module, I'm passing a signal called as the Load_Divider which will be checked in the frequency divider module as follows:

process(Load_Division)
if(Load_Division='1')
   Data_Buffer<=DataBus;
   Load_Divider <='0';
end if;
end process;

if(Counter = X"0000") then
   Counter <= Data_Buffer; //reloading counter

And in the main module :

case Address is
   "00100"=>Load_Divider <='1'; // generating load signal when proper address is found

But what happens is my Load_Divider is not going '0' when driven from the sub module.

Is it not possible to drive a signal from two modules?

\$\endgroup\$
  • 3
    \$\begingroup\$ No, you can't drive the same signal from different modules (or even processes) because you can't specify what driver has priority in case of a collision. Either do it in the same process or use different signals and add logic for them to generate the signal in question, with whatever priority makes sense. BTW, your sensitivity list is incomplete. \$\endgroup\$ – apalopohapa Jan 24 '13 at 8:50
2
\$\begingroup\$

It is possible to drive a signal from two modules.

However, it is not straightforward; the two modules have to cooperate - if one drives '1' and the other '0' at the same time, you have created a short circuit across the power supply, and you can potentially damage the device. In simulation, thankfully, the results are less dramatic!

Two ways to do so; and the reason not to use either of them inside an FPGA.

The first way is the traditional "wired AND" where there is a weak '1' permanently connected to the signal. Traditionally this was a resistor connected to +5V; in VHDL you might say Load_Divider <='H'; in the toplevel design. H and L are weak versions of '1' and '0'.

Now every driver can either pull it low, or turn off

if condition then 
   Load_Divider <='0';
else
   Load_Divider <='Z';
end if;

('Z' means the high-Z or high impedance state, i.e. turn off the driver).

If ALL the modules drive Z, the output is 'H' (equal to '1').

The second way is called a tri-state bus. Here either module may drive 0, 1 or Z onto the bus. However, you the designer MUST make sure that when one module is driving '0' or '1', ALL the other modules are driving 'Z', to prevent the short circuit and damage mentioned above. That requires the cooperation of all the modules in some way:

if my_turn then 
   Load_Divider <= my_signal;   -- 0 or 1
else
   Load_Divider <='Z';
end if;

Either of these techniques are valid ways to communicate between separate FPGAs and other chips (memories, CPUs) on your board. But inside an FPGA there are no tri-state signals (only on its I/O pins) so if you use either technique above, the synthesis tools translate it into an equivalent signal without the tri-states.

For example the first technique (wired-AND) might translate to

Load_Divider_1 <= '0';   -- module 1
Load_Divider_2 <= '1';   -- module 2
Load_Divider <= Load_Divider_1 and Load_Divider_2;

where you can see that each signal has only one driver. So why not write that in the first place?

\$\endgroup\$
  • \$\begingroup\$ Two points: 1) no synthesis tool will allow routing a short-circuit internally in the FPGA - there is no user mistake that can lead to this. 2) There are hardly any synthesis tools supporting driving 'H' on internal logic. (Such a thing can be simulated though.) \$\endgroup\$ – Carl Aug 5 '14 at 21:23
  • \$\begingroup\$ Both valid points. The short circuit problem can realistically only occur between FPGAs. Whether it causes actual harm depends on the I/O block details, but it is certainly not recommended! Re:'H' on internal logic : I recently found Synplicity silently creating incorrect logic for such a case (not in one of my cores!) \$\endgroup\$ – Brian Drummond Aug 6 '14 at 8:30
  • \$\begingroup\$ Yes, with any connection outside the FPGA, short-circuit is possible to achieve of course (but in this case it was clear that Load_Divider was internal to the FPGA). Interesting about the H. I've tried with internal tri-states with XST before, letting XST replace it with logic. But it as well created incorrect logic in that case. \$\endgroup\$ – Carl Aug 6 '14 at 12:37
1
\$\begingroup\$

When I need to do this I have each module drive its own separate signal, then do whatever I want in the toplevel module.

Something like

signal sig_a, sig_b, sig_final: std_logic;

foo_a: entity foo PORT MAP (
    clk => clk,
    rst => reset,
    out => out_a
    );

foo_b: entity foo PORT MAP (
    clk => clk,
    rst => reset,
    out => out_b
    );

-- for active-high, use or:
sig_final <= sig_a or sig_b;

-- for active-low, use and;
sig_final <= sig_a and sig_b;

-- if you have to override bad entity logic:
sig_final <= sig_a or sig_b when reset = '0' else '0';

-- if you have something really complex and that has to be registered:
determine_sig: process(clk, reset)
begin
    if reset = '1' then
        sig_final <= '0';
    else if rising_edge(clk) then
        -- do something wild and wooly based on sig_a, sig_b, state variables, phase of the moon, etc.
    end if;
end process;

signals are cheap and allow you to be explicit with your code. There is almost never any need to muck about with strong and weak drivers, and NEVER use the high-impedance state ('Z') for internal signals.

\$\endgroup\$
1
\$\begingroup\$

You can have multiple drivers of a signal. However, you must provide a resolution function for the signal that determines what the output is if more than one source drives the same signal at the same time.

You would typically define a resolution function in a package and then include the package in both modules. The most commonly cited example is that of std_logic in the std_logic_1164 package which can be seen here. That example is probably a little more complex than you need. A simpler example would be a wired AND:

package my_package is
    function wired_and (input : std_logic_vector) return std_logic;
end my_package;

package body my_package is
    function wired_and (input : std_logic_vector) return std_logic is
        --setting this to '1' ensures that even if there is only one
        --driver, the AND will output the correct value
        variable output : std_logic := '1';

    begin
        --AND each input driver with all of the others
        for i in input'range loop
            output := output and input(i);
        end loop;

        return output;
    end wired_and;
end my_package;

The function takes in an array, the std_logic_vector called input, that contains all of the multiple drivers. And it outputs a single bit, the std_logic called output.

Instead of using this to assign your signal a value:

Load_Divider <= '0';

You would use this:

Load_Divider <= wired_and('0');

Though that can get somewhat annoying and can be error prone. It is generally easier to declare a subtype that automatically uses the resolution function like this:

subtype my_type is wired_and std_logic;

And declare your signal like so:

signal Load_Divider : my_type;

That way, whenever there are multiple drivers of that signal (even if there are more than two in the example above), the resolution function will automatically be called and the appropriate value output.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.