EmbDev.net

Forum: FPGA, VHDL & Verilog 4 bit up down counter with a programmable modulo value


von Ahmed A. (Company: none) (amd1416)


Rate this post
useful
not useful
I am designing an up down counter that has a modulo value that can be 
programmed so that value is the highest it can reach to count up to or 
down from. I want it so that only if I reset the code the modulo value 
is loaded. So if I change it and don't reset the old modulo value will 
remain. Also with my counter code I want to implement a clock divider 
that I have been given and need to use.

Here are my codes:

This is the code of the counter with the clock divider as a component 
within it:
1
library IEEE; 
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.STD_LOGIC_ARITH.ALL;
4
use IEEE.STD_LOGIC_UNSIGNED.ALL;
5
6
entity counter4bit_modproc is
7
   GENERIC(LIMIT : integer := 2);
8
   port( 
9
        mod_value:        in  std_logic_vector(3 downto 0);
10
        clock:            in  std_logic;
11
        enable_count:     in  std_logic;
12
        reset:            in  std_logic;
13
        direction:        in  std_logic;
14
        output_counter:   out std_logic_vector(3 downto 0) );
15
 end counter4bit_modproc;
16
17
 architecture behavioral of counter4bit_modproc is
18
   component Clock_Divider is
19
      generic ( LIMIT : integer := 2 );
20
      port (
21
            Clock   : in std_logic;
22
            Reset   : in std_logic;
23
            Clk_Div : out std_logic);
24
   end component;
25
  
26
   signal dig: std_logic_vector(3 downto 0);
27
  signal clk: std_LOGIC;
28
   begin
29
  
30
   clkdiv: Clock_Divider generic map (LIMIT => 50000000)
31
                 port map ( 
32
                                   clock   => Clock, 
33
                                   Reset   => Reset, 
34
                                   clk_Div => clk);
35
      
36
   process(clk, Reset)
37
      begin
38
         if Reset='1' then
39
            dig <= "0000";
40
         elsif ( rising_edge(clk)) then
41
            if (enable_count = '1') then  
42
               if (direction = '0') then  
43
                  if (dig <= mod_value) then
44
                      dig <= "0000";
45
                      --dig <= (others =>'0');
46
               else
47
                      dig <= dig + 1;
48
                  end if;
49
               elsif (dig = "0000") then
50
                      dig <= mod_value;
51
               else
52
                      dig <= dig - 1;
53
               end if; 
54
           end if;
55
        end if;
56
   end process;
57
      output_counter <= dig;
58
 end behavioral;

here is the code for the clock divider:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.STD_LOGIC_UNSIGNED.ALL;
4
5
entity Clock_Divider is
6
  GENERIC(LIMIT : integer := 2); 
7
  PORT (
8
      Clock    : IN  STD_LOGIC;
9
      Reset    : IN  STD_LOGIC;
10
      Clk_Div : OUT  STD_LOGIC
11
      );
12
end Clock_Divider;
13
14
architecture Behavioral of Clock_Divider is
15
signal cnt : STD_LOGIC_VECTOR(31 downto 0);
16
begin
17
18
PC: process (Clock, Reset)            
19
   begin
20
    if rising_edge(Clock) then
21
      if Reset = '1' then
22
        cnt <= (others => '0');
23
        Clk_Div <= '0';
24
      elsif cnt = LIMIT-1 then
25
        cnt <= (others => '0');
26
        Clk_Div <= '1';
27
      else
28
        cnt <= cnt+1;
29
        Clk_Div <= '0';
30
      end if;
31
    end if;
32
   end process;
33
   
34
end Behavioral;

: Edited by Moderator
von Lothar M. (Company: Titel) (lkmiller) (Moderator)


Rate this post
useful
not useful
Ahmed A. wrote:
> use IEEE.STD_LOGIC_ARITH.ALL;
> use IEEE.STD_LOGIC_UNSIGNED.ALL;
Don't use those old obsolete Synopsys libs (although they are in all the 
school books). Use the numeric_std instead...

> Here are my codes:
Whats the problem with it? What do you expect? And what does happen 
instead? Do you have a test bench for simulation?

> PC: process (Clock, Reset)
In this totally synchronous process only clock is needed in the 
sensitivity list.

> architecture Behavioral of Clock_Divider is
This ist not the way a clock is generated inside an FPGA! If you MUST 
generate a slower/different clock then use a clock manager. The rest is 
done by clock-enables.

To keep things short: a beginners design has only 1 clock active on the 
same edge all over the design.

> I want it so that only if I reset the code the modulo value is loaded.
Then you must implement a local register set for storing the mod value. 
Just as a hint:
1
library IEEE; 
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.STD_LOGIC_ARITH.ALL;
4
use IEEE.STD_LOGIC_UNSIGNED.ALL;
5
6
entity counter4bit_modproc is
7
   GENERIC(LIMIT : integer := 2);
8
   port( 
9
        mod_value:        in  std_logic_vector(3 downto 0);
10
        clock:            in  std_logic;
11
        enable_count:     in  std_logic;
12
        reset:            in  std_logic;
13
        direction:        in  std_logic;
14
        output_counter:   out std_logic_vector(3 downto 0) );
15
 end counter4bit_modproc;
16
17
 architecture behavioral of counter4bit_modproc is
18
   component Clock_Divider is
19
      generic ( LIMIT : integer := 2 );
20
      port (
21
            Clock   : in std_logic;
22
            Reset   : in std_logic;
23
            Clk_Div : out std_logic);
24
   end component;
25
  
26
   signal dig: std_logic_vector(3 downto 0);
27
   signal mv:  std_logic_vector(3 downto 0);   -- store the mod_value
28
   signal clk: std_LOGIC;
29
   begin
30
  
31
   clkdiv: Clock_Divider generic map (LIMIT => 50000000)
32
                 port map ( 
33
                                   clock   => Clock, 
34
                                   Reset   => Reset, 
35
                                   clk_Div => clk);
36
    
37
   process(clk, Reset)
38
      begin
39
         if Reset='1' then
40
            dig <= "0000";
41
            mv  <= mod_value;    -- quick'n DIRTY! never do this in real life!
42
         elsif ( rising_edge(clk)) then
43
            if (enable_count = '1') then  
44
               if (direction = '0') then  
45
                  if (dig <= mv) then
46
                      dig <= "0000";
47
                      --dig <= (others =>'0');
48
               else
49
                      dig <= dig + 1;
50
                  end if;
51
               elsif (dig = "0000") then
52
                      dig <= mv;
53
               else
54
                      dig <= dig - 1;
55
               end if; 
56
           end if;
57
        end if;
58
   end process;
59
      output_counter <= dig;
60
 end behavioral;
But there are 2 things:
1. don't use a reset and specially a async reset for latching values
2. you MUST sync in the reset signal to the FPGA system clock
The worst thing that can happen is a totally async reset. This will 
geive you a design that may occasionally start in an undefined manner 
with strange behaviour...
Best for an beginner is to use NO RESET at all.

: Edited by Moderator
von Ahmed A. (Company: none) (amd1416)


Rate this post
useful
not useful
Thank you for getting back to me.

I want this to count up or down depending on the direction to a 
specified value set by the modulo. Also, the clock that is driving the 
system should be the output from the clock divider.

The way you have done the modulo value would that change and update the 
code only when it is rest?

I need a reset in the code.

von Klaus (Guest)


Rate this post
useful
not useful
It would have been "nice" if you posed a question. You only described 
what you want to do.

However, the code you have shown, wouldn't do what you described - so 
you may have intended to ask, either how, or why i does not what you 
want.


Its valuable to exercise some analysis of the problem, beforehand.

If the design takes the mod_value input to compare it with the current 
counter value, which impact has it, if it is changed? Clearly, that this 
new value will be used at the next clock. Nothing in the design enforces 
the compare value to be dependent on reset as you described it. 
Therefore it will not depend on it. Easy!

So how to enforce the compare value to be constant? It shall only change 
on reset? As well, easy! Use a register to store that compare value from 
mod_value input and use that register contents as compare value.

von Ahmed A. (Company: none) (amd1416)


Rate this post
useful
not useful
Ok thanks for that and how would I make a register as a process to go 
along with the counter?

von Klaus (Guest)


Rate this post
useful
not useful
Nothing as easy :-)

Just add a signal like "dig" to your counter4bit_modproc which holds the 
modulo-value (say you name it "current_modulo_value"). "dig" and that 
additional "signal" are to be seen as registers; one counts one does not 
count but stores the modulo value.

Change the process so, that

1. current_modulo_value will store the input mod_value in when reset = 
1. You could add that at the point of the text where you set dig to 
zero.

2. current_modulo_value will be used for comparison instead of the input 
mod_value.

von Lothar M. (Company: Titel) (lkmiller) (Moderator)


Rate this post
useful
not useful
Ahmed A. wrote:
> how would I make a register as a process
Its simple: invoke a clock. Then you'll get a register.
1
library IEEE; 
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.STD_LOGIC_ARITH.ALL;
4
use IEEE.STD_LOGIC_UNSIGNED.ALL;
5
6
entity counter4bit_modproc is
7
   GENERIC(LIMIT : integer := 2);
8
   port( 
9
        mod_value:        in  std_logic_vector(3 downto 0);
10
        clock:            in  std_logic;
11
        enable_count:     in  std_logic;
12
        reset:            in  std_logic;
13
        direction:        in  std_logic;
14
        output_counter:   out std_logic_vector(3 downto 0) );
15
 end counter4bit_modproc;
16
17
 architecture behavioral of counter4bit_modproc is
18
   component Clock_Divider is
19
      generic ( LIMIT : integer := 2 );
20
      port (
21
            Clock   : in std_logic;
22
            Reset   : in std_logic;
23
            Clk_Div : out std_logic);
24
   end component;
25
  
26
   signal dig: std_logic_vector(3 downto 0);
27
   signal mv:  std_logic_vector(3 downto 0);   -- store the mod_value
28
   signal clk: std_LOGIC;
29
   begin
30
  
31
   clkdiv: Clock_Divider generic map (LIMIT => 50000000)
32
                 port map (        clock   => Clock, 
33
                                   Reset   => Reset, 
34
                                   clk_Div => clk);
35
36
   process(clk)
37
      if ( rising_edge(clk)) then
38
         if Reset='1' then
39
            mv  <= mod_value;    -- this will get you a set of registers
40
         end if;
41
      end if;
42
   end process
43
    
44
   process(clk)
45
     begin
46
       if ( rising_edge(clk)) then
47
         if Reset='1' then    -- use a sync reset and keep in mind to sync the reset to the clk!!!
48
            dig <= "0000";
49
         else
50
            if (enable_count = '1') then  
51
               if (direction = '0') then  
52
                  if (dig <= mv) then
53
                      dig <= "0000";
54
                      --dig <= (others =>'0');
55
                  else
56
                      dig <= dig + 1;
57
                  end if;
58
               elsif (dig = "0000") then
59
                      dig <= mv;
60
               else
61
                      dig <= dig - 1;
62
               end if; 
63
            end if;
64
         end if;
65
     end if;
66
   end process;
67
      output_counter <= dig;
68
 end behavioral;
BTW: have a look at the RTL schematics to see whether the synthesizer 
understands your description of what you want him do do...

von Ahmed A. (Company: none) (amd1416)


Rate this post
useful
not useful
thank you so now I have a register so that if the mod value is changed 
and it is reset that mod value would go to the main counter code as the 
maximum value.

Also the clock that is driving the counter is the clk coming out of the 
clock divider?

and now it counts up and down and loops around when the mod value is 
reached?
is that right?

von Lothar M. (Company: Titel) (lkmiller) (Moderator)


Rate this post
useful
not useful
Ahmed A. wrote:
> a register so that if the mod value is changed and it is reset
> that mod value would go to the main counter code as the maximum value.
Thats the idea, yes.

> it counts up and down and loops around when the mod value is reached?
I assume there are some problems in your part of the code. One is this 
here:
1
                  if (dig <= mv) then
2
                      dig <= "0000";
3
                  else
4
                      dig <= dig + 1;
5
                  end if;
This compare seems to be the wrong direction: will dig here ever be 
able to become anything other than 0000?
So, as already said: run the design on a (behavioral) test bench to 
check that out.

> Also the clock that is driving the counter is the clk coming out of the
> clock divider?
As already said: that is bad design practice. It should not be done this 
way in real life FPGA.

: Edited by Moderator
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.