0

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;
Community
  • 1
  • 1
Sean Chu
  • 43
  • 7
  • 5
    Here's a simple rule for VHDL: Never have two processes modifying the same signal. Figure out another way to do it. Don't use shared variables at all, use signals. – Russell Dec 08 '14 at 18:33
  • @Russell Can u explain why shared variables is not a good option a bit? I mean now I think I know why simultaneous assignment from different processes is prohibited, but why in general the use of shared variables is not recommended at all - then why it exists? Thank you alot! – Sean Chu Dec 10 '14 at 04:43
  • @DavidKoontz Thank u David, I think I get most of what u say. However, as a real newbie to VHDL, I wonder what "not be possible to ever grant exclusive access to the shared variable as outlined in the preceding item b)" means. Why it's exclusive access to shared variable in my code? Thank u – Sean Chu Dec 10 '14 at 04:48
  • NOTE 2 wasn't applicable. Next see [Can't resolve multiple constant drivers for net](http://quartushelp.altera.com/13.1/mergedProjects/msgs/msgs/evrfx_vdb_net_multiple_drivers.htm) and [Constant driver at ](http://quartushelp.altera.com/13.1/mergedProjects/msgs/msgs/evrfx_vdb_net_another_driver.htm). Collectively they're telling you to have only one process write to your shared variables. How does hardware look with two events operating sequential logic (registers, latches,...)? –  Dec 10 '14 at 07:24
  • @SeanChu I've mostly seen shared variables in testbench environments. Even then, you need to be very careful about how you use them because they are subject to race conditions. Others have written extensively about the subject, so search the internet if you're curious. In general though, shared variables are an advanced concept and should be avoided until you have a good handle on the language. – Russell Dec 10 '14 at 13:28
  • @Russell Ok I will look it up. Thank u again for this very important tip. – Sean Chu Dec 11 '14 at 02:39
  • @DavidKoontz David thank u, I think now I understand what is really wrong with my design logics. Have to learn more of this EDA world, I guess :) – Sean Chu Dec 11 '14 at 02:43

1 Answers1

3

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.

fru1tbat
  • 1,605
  • 9
  • 16
  • Thank u for this clear explanation, now I think I know what is really wrong with my thoughts - it's because I kept the concept that "variables" are just something like this term in other programming languages. In VHDL, everything is hardware-based, so I better plan my code from a circuit perspective next time. – Sean Chu Dec 10 '14 at 04:54
  • In VHDL *for synthesis*, yes. If you're working strictly in sim, the "rules" are much more relaxed. – fru1tbat Dec 10 '14 at 11:16
  • so I guess "working strictly in sim" means in cases I only compile my code without synthesizing it into RTL, is it? In fact, I think I'm never informed that what will VHDL source code be complied to be eventually. Say, I know in C, your source will become assembly instructions and finally be some lower-level machine instructions, but what about VHDL? It's said to be a "hardware description language", so maybe RTL is its ultimate form? I know this is beyond my question, but I do appreciate if experienced engineers like u can reveal some underlying mechanisms of this language – Sean Chu Dec 11 '14 at 03:01
  • since my EDA teacher, ummm... Seems he doesn't care about this at all. Again thank u a lot – Sean Chu Dec 11 '14 at 03:03