VHDL control signal from different processes

I have a little problem with the following VHDL code:

process (zbroji) begin if rising_edge(zbroji) then oduzima <= '0'; ucitanPrvi <= '1'; broj1 <= ulaz_broj; end if; end process; process (oduzmi) begin if rising_edge(oduzmi) then oduzima <= '1'; ucitanPrvi <= '1'; broj1 <= ulaz_broj; end if; end process; 

The problem is that the ucitanPrvi signal always has the value X. If I do not try to set its value in two processes, then I have no problems ... Therefore, I know that I do not have to control one signal from several processes, but I don’t know how to write it differently ... Does anyone have an idea how I can solve this problem?

Thanks!

EDIT: Thanks to all the guys for the answers :) Now I understand why I can't control one signal from several processes (at least the way I wanted it to work).

+7
source share
5 answers

If you want to synthesize your design for a real FPGA or ASIC, you will have to think about VHDL in terms of real equipment (wires, flip flops, gates, etc.). In addition, if you want to detect a real rising edge in hardware, you will need a system clock that controls the flip flop. Given the original code sample, it doesn't seem like zbroji or oduzmi are a system clock, but just std_logic signals. I wrote this sample code, assuming the basic functionality from your example, I hope you can take my code and comments and do what you need.

 library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity example is port (Reset : in std_logic; SysClk : in std_logic; zbroji : in std_logic; oduzmi : in std_logic; ulaz_broj : in std_logic; oduzima : out std_logic; ucitanPrvi : out std_logic; broj1 : out std_logic ); end example; architecture Behavioral of example is -- Delayed version of input signals (1 clock cycle delay) signal zbroji_d : std_logic; signal oduzmi_d : std_logic; signal zbrojiRE : std_logic; signal oduzmiRE : std_logic; begin -- Generate 1 clock cycle delayed version of -- signals we want to detect the rising edge -- Assumes active high reset -- Note: You should only use the rising_edge macro -- on an actual global or regional clock signal. FPGA and -- ASICs place timing constraints on defined clock signals -- that make it possible to use rising_edge, otherwise, we have -- to generate our own rising edge signals by comparing delayed -- versions of a signal with the current signal. -- Also, with any respectable synthesizer / simulator using -- rising_edge is almos exactly the same as (clk'event and clk='1') -- except rising_edge only returns a '1' when the clock makes a -- valid '0' to '1' transition. (see link below) EdgeDetectProc : process (Reset, SysClk) begin if Reset = '1' then zbroji_d <= '0'; oduzmi_d <= '0'; elsif rising_edge(SysClk) then zbroji_d <= zbroji; oduzmi_d <= oduzmi; end if; end process EdgeDetectProc; -- Assert risinge edge signals for one clock cycle zbrojiRE <= '1' when zbroji = '1' and zbroji_d = '0' else '0'; oduzmiRE <= '1' when oduzmi = '1' and oduzmi_d = '0' else '0'; -- Assumes that you want a single cycle pulse on ucitanPrvi on the -- rising edege of zbroji or oduzmi; ucitanPrvi <= zbrojiRE or oduzmiRE; -- Based on your example, I can't tell what you want to do with the -- broj1 signal, but this logic will drive broj1 with ulaz_broj on -- either the zbroji or oduzmi rising edge, otherwise '0'. broj1 <= ulaz_broj when zbrojiRE = '1' else ulaz_broj when oduzmiRE = '1' else '0'; -- Finally, it looks like you want to clear oduzima on the rising -- edge of zbroji and assert oduzima on the rising edge of -- oduzmi LatchProc : process (Reset, SysClk) begin if Reset = '1' then oduzima <= '0'; elsif rising_edge(SysClk) then if zbrojiRE = '1' then oduzima <= '0'; elsif oduzmiRE = '1' then oduzima <= '1'; end if; end if; end process LatchProc; end Behavioral; 

The previous code assumes that you have a system clock. In a simulator such as ModelSim (a free publication for students), you can generate a clock frequency of 100 MHz with a non-synthesized testbench code like this ...

 ClockProc : process begin SysClk <= '0'; wait for 5 ns; SysClk <= '1'; wait for 5 ns; end process ClockProc; 

In a real FPGA / ASIC implementation, you probably want to use an external oscillator that you run in your microchip, bring the signal to DCM (Digital Clock Manager), which outputs a very clean clock signal to all your VHDL logic, so you might have a design with an error.

And finally, here is a great explanation of the differences between rising_edge and (clk'event and clk = '1')

http://vhdlguru.blogspot.com/2010/04/difference-between-risingedgeclk-and.html

Hope this helps.

+5
source

If you control the std_logic signal from more than one process (and remember that continuous assignment outside the process also creates an implied process!), Then all but one of them must drive Z into the signal. In a first approximation, the resolution function (which determines the final value) should produce X if this does not happen.

I'm not sure how best to change your code - you need to decide when some process should not control the signal and force it to press Z at that moment.


A full definition of how multiple drivers are allowed is defined in the ieee.std_logic_1164 package and covers all features such as 1 and L driving, etc. IEEE cheats on copyrights, m is not going to publish even an excerpt here, but you can find it in the source libraries of your simulator.

+3
source

Driving signals from several processes is a bad idea if you really don't know what you are doing. You can rewrite this code in one process as follows.

 process (zbroji, oduzmi) begin if rising_edge(zbroji) then oduzima <= '0'; ucitanPrvi <= '1'; broj1 <= ulaz_broj; end if; if rising_edge(oduzmi) then oduzima <= '1'; ucitanPrvi <= '1'; broj1 <= ulaz_broj; end if; end process; 

Please note that if you do this and you get a rising edge on both zbroji and oduzmi , then oduzima will get a value of 1 , as this is the last in the process. Before you tried to set it to 0 and 1 at the same time. This will simulate before X and probably will not be synthesized. If he synthesized, you would connect the power and combine in a CMOS design.


An alternative method is for each process to control its own version of the signal, and then enable them externally with any function you like (or another process). In this case, I used or :

 process (zbroji) begin if rising_edge(zbroji) then ucitanPrvi_1 <= '1'; end if; end process; process (oduzmi) begin if rising_edge(oduzmi) then ucitanPrvi_2 <= '1'; end if; end process; ucitanPrvi <= ucitanPrvi_1 or ucitanPrvi_2; 
+2
source

If zbroji and oduzmi are not separate hours, this is my recommended implementation

This registers zbroji and oduzmi and checks if the value in the register is the opposite of the original signal. This should only happen when zbroji / oduzmi goes from 0 to 1, and the register has not yet updated the signal change.

 process (clk) begin if rising_edge(clk) then if zbroji = '1' and zbroji_old = '0' then oduzima <= '0'; ucitanPrvi <= '1'; broj1 <= ulaz_broj; elif oduzmi = '1' and oduzmi_old = '0' then oduzima <= '1'; ucitanPrvi <= '1'; broj1 <= ulaz_broj; end if; zbroji_old <= zbroji; oduzmi_old <= oduzmi; end if; end process; 

It also appears that ucitanPrvi and broj1 are always the same. Either the signals are useless, it was a typo, or you create "updated" pulses, in which case you need approval

  ucitanPrvi <= '0' broj1 <= (others=>'0') -- assumed reset? 

after the if (rising_edge (clk) statement

+1
source

When you change the same signal value from several processes, the simulator will create several signal drivers for it. Exit from them will essentially be unauthorized. Think of it as a combination of several gates, what do you expect?

To overcome this, you need to implement a resolution function that outputs a signal.

http://www.csee.umbc.edu/portal/help/VHDL/misc.html#resf

If you have any doubts, let me know.

0
source

All Articles