FPGA VHDL – Using Signal in Different Modules VHDL

fpgavhdl

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?

Best Answer

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?