EmbDev.net

Forum: FPGA, VHDL & Verilog Binary counter


von daniel (Guest)


Attached files:

Rate this post
useful
not useful
Hello I would love your help
I designed a simple binary counter,
though if I do not put the single Q in the sensitivity list. The counter 
updates falling_edge Why is that?

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.all;
use IEEE.STD_LOGIC_UNSIGNED.all;

entity Binary_Counter is
--generic( n :   positive:=24);
    Port (
           Clk : in STD_LOGIC;
           -- the LTF(n) signal

           Up_Down : in STD_LOGIC;
           -- Up_Down ='1'  the counter counts up
           -- Up_Down ='0'  the counter counts down

           T_Gate : in STD_LOGIC;
           -- Enable count

           O : in integer range 0 to 10:=2;
           -- The number of times the counter works

           ResetS : in STD_LOGIC;
           -- Asynchronously reset

           Pe : in STD_LOGIC;
           -- Asynchronously loads data on the Preset Inputs.

           Pi : in STD_LOGIC_VECTOR(23 downto 0);
           --Data on these inputs is loaded into the counter when PE is 
taken high.

           Q_Out : out STD_LOGIC_VECTOR(23 downto 0);
           -- Binary data is present outputs

           Carry_Out : out STD_LOGIC);
           --used to indicate terminal count.

end Binary_Counter;

architecture Behavioral of Binary_Counter is
signal Q : STD_LOGIC_VECTOR(23 downto 0):=(others=>'0');
begin

process(Clk,ResetS,Pe,T_Gate,Up_Down)
variable CountQ : integer range 0 to 10:=O;
begin

if( ResetS = '1') then Q<=(others=>'0');

            elsif(CountQ /=0 and T_Gate='1') then

             if(rising_edge(clk)) then

                if( pe='1' ) then Q<= pi;

                        elsif(Up_Down='1') then
                                if(Q=x"111111") then
                                    Carry_Out<='1';
                                    Q<=x"000000";
                                else
                                    Q<=Q+1;
                                end if;
                         else
                            if(Q=x"000000") then
                                Carry_Out<='1';
                                Q<=x"111111";
                            else
                                Q<=Q-1;
                            end if;

                 end if;

             end if;
end if;
Q_Out<=Q;
end process;
end Behavioral;

von Tim (Guest)


Rate this post
useful
not useful
At first some basics hints:

IEEE.STD_LOGIC_ARITH.all
thats outdated and should never be used.

Next, write a clean clocked process. Only reset should be outside of 
rising_edge.

von FPGA NOTFALLSEELSORGE (Guest)


Rate this post
useful
not useful
Oh well ... where to start?

--- 1. ---

use IEEE.STD_LOGIC_ARITH.all;
use IEEE.STD_LOGIC_UNSIGNED.all;

Do not use those! But use instead

use ieee.numeric_std.all;

--- 2. ---

O : in integer range 0 to 10:=2;

Try to use only std_logic and std_logic_vectors for ports.

--- 3. ---

Try to avoid variables if you do not know how they work.
And the code suggests you do not know that.

--- 4. ---

CountQ is only assigned at the start of the process but never changed. 
So there is no need to use it at all.

--- 5. ---

process(Clk,ResetS,Pe,T_Gate,Up_Down)

You can write it that way, but you only need the asynchronous signals + 
clock. So O, T_Gate, ResetS and Clk would be sufficient.

--- 6. ---

I do not understand the function of O.

--- 7. ---

Try to use "speaking Names"
Pe, Pi say nothing to me, you could name them
Preset_load and Preset_value or the like.

--- 8. ---

A very simmilar question (same counter) was asked in the german section 
of the forum. Look here:
Beitrag "VHDL Anfänger braucht Unterstützung (keine Lösung)"

von FPGA NOTFALLSEELSORGE (Guest)


Rate this post
useful
not useful
--- 9. ---

Carry_Out is undefinded till it is set to '1'. This is an error!

--- 10. ---

Try to format your code for easy reding + understanding.

--- 11. ---

To your initial question:

daniel wrote:
> The counter updates falling_edge Why is that?

This is because you have written (shorted):
1
process (Clk,ResetS,Pe,T_Gate,Up_Down)
2
begin
3
  if rising_edge(clk) then
4
5
    if Up_Down='1' then
6
      if Q = x"111111" then
7
        Carry_Out <= '1';
8
        Q <= x"000000";
9
      else
10
        Q <= Q + 1;
11
      end if;
12
    else
13
      if Q = x"000000" then
14
        Carry_Out <= '1';
15
        Q <= x"111111";
16
      else
17
        Q <= Q - 1;
18
      end if;
19
    end if;
20
  end if;
21
  
22
  Q_Out <= Q;
23
24
end process;

So Q updates with every rising_edge of the clock. But the process itself 
is restarted with every action on all of these signals 
(Clk,ResetS,Pe,T_Gate,Up_Down), so it is restarted on the falling_edge 
of the clock, too. And because Q was updated on the rising_edge, with 
Q_Out gets the new value with the next process run which is with the 
next falling_edge.

To avoid this you should write
Q_Out <= Q;
outside the process or write it inside the
if rising_edge(clk) then

end if;
part. But: If you write it in the if rising_edge(clk) then ... part, you 
get 1 clock cycle latency. So you may want to write it outside the 
process.

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.