Search code examples
vhdlquartus

Why Quartus II recognizes my variable as a signal?


I'm new to VHDL programming, and this is my first project - to build a binary counter with capability for both regular/reverse counting order. My plan is simple:

  1. Write a frequency divider process to fetch desired clock frequency and output this new clock as a bit signal flag.
  2. Put "flag" to the sensitivity list of another process, count it according to the regular/reverse state - stored as curr_s in my code.
  3. The third process receives input ctl signal as a sensitive, then switch curr_s and reset the value of count - which is set to store the counts of my last process.

Now the thing is, however, that Quartus II returns me the error message:

Error (10028): Can't resolve multiple constant drivers for net "count[31]" at bi_counter.vhd(35)

Error (10029): Constant driver at bi_counter.vhd(46)

Error (10028): Can't resolve multiple constant drivers for net "count[30]" at bi_counter.vhd(35)

...

Error (10028): Can't resolve multiple constant drivers for net "count[14]" at bi_counter.vhd(35)

I googled a little bit and there are rules like it's not allowed to change the value of a signal in multiple processes, but the problem is I declare my count as a shared variable instead of signal - which should not encounter such error. And I intended to do this because I want to use count as a variable to exchange information among processes - does this make sense and if not, is there any workaround?

Here is my code:

--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.numeric_std.all;
--
entity bi_counter is
    port(
        master_clk, ctl, rst: in std_logic;
                           q: out std_logic_vector(7 downto 0)
        );
end bi_counter;
--
architecture behv of bi_counter is
    shared variable curr_s: std_logic := '0'; -- 0 for incremental, 1 for reverse counting
    shared variable count: integer := -1;
    shared variable master_count: natural := 0;
    signal flag: std_logic;
begin
    p_freq_div: process(master_clk, rst)
    begin
        if rst = '0' then
            master_count := 0;
        elsif master_clk'event and master_clk='1' then
            master_count := master_count + 1;
            if master_count = 24000000 then
                flag <= not flag;
                master_count := 0;
            end if;
        end if;
    end process p_freq_div;
    
    p_count: process(flag)
    begin
        if curr_s = '1' then
            count := count + 1;
            q <= conv_std_logic_vector(count, 8);
        else
            count := count - 1;
            q <= conv_std_logic_vector(count, 8);
        end if;
    end process p_count;
    
    p_switch: process(ctl)
    begin
        if ctl'event and ctl='1' then
            curr_s := not curr_s;
            if curr_s = '0' then
                count := 0;
            else
                count := 1000;
            end if;
        end if;
    end process p_switch;
end behv;

Solution

  • You wrote:

    I googled a little bit and there are rules like it's not allowed to change the value of a signal in multiple processes, but the problem is I declare my count as a shared variable instead of signal - which should not encounter such error.

    This "rule" isn't just there to make your life more difficult.

    Think about what you're trying to do. You're trying to synthesize something to put on your device that will hold a value, which you are trying to assign from two independent processes (even though they may be related and you know how they're supposed to work, they're still independent). No matter what linguistic element you use - signal, variable, whatever - it becomes irrelevant once you get to the device, which only has physical circuits. That is to say, you may not be violating any language rules, but you are violating a physical rule.

    Your output can be stated in the following form: if some condition, then output something, else if some other condition, output something else, etc. And that can be put into a single process, which is what I suggest you do.

    Also, as Russell suggested, you probably shouldn't use shared variables, especially to get around a language rule like you did.