Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
17247 ディスカッション

up down counter problem

Altera_Forum
名誉コントリビューター II
1,465件の閲覧回数

hi everyone  

i try to make a project to count people entering or going out from a hall  

using VHDL and altera board DE0 

i made two clocks one for counting up (clku) it come from a trigger outside board 

and one for counting down (clkd) also come from a trigger outside board . 

but when doing this Error 10820 appear that says "can't infer register for count because its behavior depends on the edges of multiple distinct clocks" 

 

 

the Full Code is here  

 

 

ENTITY mod_ten_ud ISPORT( 

clku,clkd, enable :IN BIT ; 

q :OUT INTEGER RANGE 0 TO 9);END mod_ten_ud; 

ARCHITECTURE a OF mod_ten_ud 

ISBEGIN 

PROCESS (clku ,clkd)  

VARIABLE count :INTEGER RANGE 0 TO 9; 

BEGIN 

IFenable = '1'  

THEN 

IF( clku = '1' AND clku'EVENT ) 

THEN count := count + 1; 

ELSIF( clkd = '1' AND clkd'EVENT ) 

THEN count := count - 1; 

END IF; 

END IF; 

q <= count; 

END PROCESS;  

END a; 

 

please help me because it is my final study project and thanks a lot
0 件の賞賛
4 返答(返信)
Altera_Forum
名誉コントリビューター II
751件の閲覧回数

First: Please use the CODE-Tags for Code. (obvious, isn't it?) 

 

ENTITY mod_ten_ud ISPORT( clku,clkd, enable :IN BIT ; q :OUT INTEGER RANGE 0 TO 9);END mod_ten_ud; ARCHITECTURE a OF mod_ten_ud ISBEGIN PROCESS (clku ,clkd) VARIABLE count :INTEGER RANGE 0 TO 9; BEGIN IFenable = '1' THEN IF( clku = '1' AND clku'EVENT ) THEN count := count + 1; ELSIF( clkd = '1' AND clkd'EVENT ) THEN count := count - 1; END IF; END IF; q <= count; END PROCESS; END a; 

 

Second: You can't use two clock edges in one process. And it is rather bad style to declare a simple signal as clock and count on the clock edges. 

Better is: 

You create one very fast clock to sample your two input signals. Like this: 

if (rising_edge(fast_clk)) then prev_sig1 <= sig1; prev_sig2 <= sig2; if ((prev_sig1 = '0') and (sig1 = '1')) then {count up} end if; if ((prev_sig2 = '0') and (sig2 = '1')) then {count down} end if; end if;  

This will also give you something like an edge-detect on your signals. But without the meaning that these are clocks.
Altera_Forum
名誉コントリビューター II
751件の閲覧回数

As the signals are asynchronous (external to the board) they need to pass each a double FF synchronizer before entering the edge detection. Otherwise you should expect a certain amount of counting errors (missed or double counted events).

Altera_Forum
名誉コントリビューター II
751件の閲覧回数

yup, debouncing

Altera_Forum
名誉コントリビューター II
751件の閲覧回数

I've had a little play and this is how I would do an up down counter: 

 

library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity people_count is generic ( COUNTER_WIDTH: integer := 8 ); port ( in_clk : in std_logic; in_reset : in std_logic; in_incCount : in std_logic; in_decCount : in std_logic; out_count : out std_logic_vector(COUNTER_WIDTH-1 downto 0) ); end entity people_count; architecture arch_people_count of people_count is signal count: unsigned(COUNTER_WIDTH-1 downto 0); signal count_up: std_logic; signal count_down: std_logic; begin count_up <= '1' when in_incCount ='1' and in_decCount = '0' else '0'; count_down <= '1' when in_incCount ='0' and in_decCount = '1' else '0'; process(in_clk, in_reset) begin if in_reset = '1' then count <= (others => '0'); elsif rising_edge(in_clk) then if (count_up = '1') then count <= count + 1; elsif (count_down = '1') then count <= count - 1; end if; end if; end process; out_count <= std_logic_vector(count); end architecture arch_people_count;  

 

but you would need to synchronize the inputs, debounce the switch and put an edge detector on the input! 

 

have fun :) 

 

geobyjmh 

http://geobyjmhembeddedengineer.blogspot.co.uk/
返信