EmbDev.net

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


Author: Ahmed Alibrahim (Company: none) (amd1416)
Posted on:

Rate this post
0 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:
library IEEE; 
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity counter4bit_modproc is
   GENERIC(LIMIT : integer := 2);
   port( 
        mod_value:        in  std_logic_vector(3 downto 0);
        clock:            in  std_logic;
        enable_count:     in  std_logic;
        reset:            in  std_logic;
        direction:        in  std_logic;
        output_counter:   out std_logic_vector(3 downto 0) );
 end counter4bit_modproc;

 architecture behavioral of counter4bit_modproc is
   component Clock_Divider is
      generic ( LIMIT : integer := 2 );
      port (
            Clock   : in std_logic;
            Reset   : in std_logic;
            Clk_Div : out std_logic);
   end component;
  
   signal dig: std_logic_vector(3 downto 0);
  signal clk: std_LOGIC;
   begin
  
   clkdiv: Clock_Divider generic map (LIMIT => 50000000)
                 port map ( 
                                   clock   => Clock, 
                                   Reset   => Reset, 
                                   clk_Div => clk);
      
   process(clk, Reset)
      begin
         if Reset='1' then
            dig <= "0000";
         elsif ( rising_edge(clk)) then
            if (enable_count = '1') then  
               if (direction = '0') then  
                  if (dig <= mod_value) then
                      dig <= "0000";
                      --dig <= (others =>'0');
               else
                      dig <= dig + 1;
                  end if;
               elsif (dig = "0000") then
                      dig <= mod_value;
               else
                      dig <= dig - 1;
               end if; 
           end if;
        end if;
   end process;
      output_counter <= dig;
 end behavioral;

here is the code for the clock divider:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity Clock_Divider is
  GENERIC(LIMIT : integer := 2); 
  PORT (
      Clock    : IN  STD_LOGIC;
      Reset    : IN  STD_LOGIC;
      Clk_Div : OUT  STD_LOGIC
      );
end Clock_Divider;

architecture Behavioral of Clock_Divider is
signal cnt : STD_LOGIC_VECTOR(31 downto 0);
begin

PC: process (Clock, Reset)            
   begin
    if rising_edge(Clock) then
      if Reset = '1' then
        cnt <= (others => '0');
        Clk_Div <= '0';
      elsif cnt = LIMIT-1 then
        cnt <= (others => '0');
        Clk_Div <= '1';
      else
        cnt <= cnt+1;
        Clk_Div <= '0';
      end if;
    end if;
   end process;
   
end Behavioral;

: Edited by Moderator
Author: Lothar Miller (lkmiller) (Moderator)
Posted on:

Rate this post
1 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:
library IEEE; 
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity counter4bit_modproc is
   GENERIC(LIMIT : integer := 2);
   port( 
        mod_value:        in  std_logic_vector(3 downto 0);
        clock:            in  std_logic;
        enable_count:     in  std_logic;
        reset:            in  std_logic;
        direction:        in  std_logic;
        output_counter:   out std_logic_vector(3 downto 0) );
 end counter4bit_modproc;

 architecture behavioral of counter4bit_modproc is
   component Clock_Divider is
      generic ( LIMIT : integer := 2 );
      port (
            Clock   : in std_logic;
            Reset   : in std_logic;
            Clk_Div : out std_logic);
   end component;
  
   signal dig: std_logic_vector(3 downto 0);
   signal mv:  std_logic_vector(3 downto 0);   -- store the mod_value
   signal clk: std_LOGIC;
   begin
  
   clkdiv: Clock_Divider generic map (LIMIT => 50000000)
                 port map ( 
                                   clock   => Clock, 
                                   Reset   => Reset, 
                                   clk_Div => clk);
    
   process(clk, Reset)
      begin
         if Reset='1' then
            dig <= "0000";
            mv  <= mod_value;    -- quick'n DIRTY! never do this in real life!
         elsif ( rising_edge(clk)) then
            if (enable_count = '1') then  
               if (direction = '0') then  
                  if (dig <= mv) then
                      dig <= "0000";
                      --dig <= (others =>'0');
               else
                      dig <= dig + 1;
                  end if;
               elsif (dig = "0000") then
                      dig <= mv;
               else
                      dig <= dig - 1;
               end if; 
           end if;
        end if;
   end process;
      output_counter <= dig;
 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
Author: Ahmed Alibrahim (Company: none) (amd1416)
Posted on:

Rate this post
0 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.

Author: Klaus (Guest)
Posted on:

Rate this post
0 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.

Author: Ahmed Alibrahim (Company: none) (amd1416)
Posted on:

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

Author: Klaus (Guest)
Posted on:

Rate this post
0 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.

Author: Lothar Miller (lkmiller) (Moderator)
Posted on:

Rate this post
0 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.
library IEEE; 
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity counter4bit_modproc is
   GENERIC(LIMIT : integer := 2);
   port( 
        mod_value:        in  std_logic_vector(3 downto 0);
        clock:            in  std_logic;
        enable_count:     in  std_logic;
        reset:            in  std_logic;
        direction:        in  std_logic;
        output_counter:   out std_logic_vector(3 downto 0) );
 end counter4bit_modproc;

 architecture behavioral of counter4bit_modproc is
   component Clock_Divider is
      generic ( LIMIT : integer := 2 );
      port (
            Clock   : in std_logic;
            Reset   : in std_logic;
            Clk_Div : out std_logic);
   end component;
  
   signal dig: std_logic_vector(3 downto 0);
   signal mv:  std_logic_vector(3 downto 0);   -- store the mod_value
   signal clk: std_LOGIC;
   begin
  
   clkdiv: Clock_Divider generic map (LIMIT => 50000000)
                 port map (        clock   => Clock, 
                                   Reset   => Reset, 
                                   clk_Div => clk);

   process(clk)
      if ( rising_edge(clk)) then
         if Reset='1' then
            mv  <= mod_value;    -- this will get you a set of registers
         end if;
      end if;
   end process
    
   process(clk)
     begin
       if ( rising_edge(clk)) then
         if Reset='1' then    -- use a sync reset and keep in mind to sync the reset to the clk!!!
            dig <= "0000";
         else
            if (enable_count = '1') then  
               if (direction = '0') then  
                  if (dig <= mv) then
                      dig <= "0000";
                      --dig <= (others =>'0');
                  else
                      dig <= dig + 1;
                  end if;
               elsif (dig = "0000") then
                      dig <= mv;
               else
                      dig <= dig - 1;
               end if; 
            end if;
         end if;
     end if;
   end process;
      output_counter <= dig;
 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...

Author: Ahmed Alibrahim (Company: none) (amd1416)
Posted on:

Rate this post
0 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?

Author: Lothar Miller (lkmiller) (Moderator)
Posted on:

Rate this post
0 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:
                  if (dig <= mv) then
                      dig <= "0000";
                  else
                      dig <= dig + 1;
                  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

Reply

Entering an e-mail address is optional. If you want to receive reply notifications by e-mail, please log in.

Rules — please read before posting

  • Post long source code as attachment, not in the text
  • Posting advertisements is forbidden.

Formatting options

  • [c]C code[/c]
  • [avrasm]AVR assembler code[/avrasm]
  • [vhdl]VHDL code[/vhdl]
  • [code]code in other languages, ASCII drawings[/code]
  • [math]formula (LaTeX syntax)[/math]




Bild automatisch verkleinern, falls nötig
Note: the original post is older than 6 months. Please don't ask any new questions in this thread, but start a new one.