Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

4 bit up down counter with programmable modulo value

Status
Not open for further replies.

amd1416

Newbie level 5
Newbie level 5
Joined
Mar 9, 2016
Messages
10
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
118
Hi everyone,

I am designing a 4 bit up and down counter that when counting up has a programmable modulo value.

Here is my code for the whole counter with modulo but I keep getting errors that I don't know how to solve.

Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
library IEEE; 
 use IEEE.STD_LOGIC_1164.ALL;
 use IEEE.STD_LOGIC_ARITH.ALL;
 use IEEE.STD_LOGIC_UNSIGNED.ALL;
 
 entity counter4bit is
 port( 
        mod_value:          in  std_logic_vector(0 to 3);
        clock:              in  std_logic;
        enable_count:       in  std_logic;
        reset:              in  std_logic;
        direction:          in  std_logic;
        output_counter: out std_logic_vector(0 to 3) );
 end counter4bit;
 
 architecture structural of counter4bit is
 component register4bit is
 port(
        Din      : in  std_logic_vector(3 downto 0);
        en       : in  std_logic;
        clock    : in  std_logic;
        reset    : in  std_logic;
        Dout     : out std_logic_vector(3 downto 0));
 end component;
 
    
 signal dig, tmp: std_logic_vector(3 downto 0); 
 begin
    mod1: register4bit port map (tmp(0) <= Dout(0), tmp(1) <= Dout(1),tmp(2) <= Dout(2),tmp(3) <= Dout(3), Din(0) <= mod_value(0), Din(1) <= mod_value(1), Din(2) <= mod_value(2), Din(3) <= mod_value(3), reset <= reset, clock <= clock, en < reset);
    
 process(Clock,Reset)
     begin
         if Reset='1' then
             dig <= "0000";
         elsif ( rising_edge(clock)) then
             if (enable_count<='1' and direction<='0') then
             if dig <= "tmp(3)tmp(2)tmp(1)tmp(0)" then 
                 dig <= "0000";
             else dig <= dig + 1;
             if (enable_count<='1' and direction<='1') then
                 dig <= dig - 1;
             end if;
             end if;
             end if;
         end if;
 end process;
     output_counter <= dig;
 end structural;



Here is the code for the 4 bit register used to control the modulo value:

Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
use IEEE.numeric_std.all;
 
-- TOP VHDL design which implements a 8-bit Universal Shift Register
entity register4bit is
  port (
    Din      : in  std_logic_vector(3 downto 0);
     EN       : in  std_logic;
     Clock    : in std_logic;
     Reset    : in std_logic;
     Dout     : out std_logic_vector(3 downto 0));
end entity register4bit;
--// End of entity
 
--// This is an architecture of 4-bits universal shift register 
architecture structural of register4bit is
component D_flip_flop is
port (
 
     D        : in std_logic;
     EN       : in std_logic;
     Clock    : in std_logic;
     Reset    : in std_logic;
     Q        : out std_logic);
 
end component;
     
 begin
 
 U1: D_flip_flop port map(D => Din(0), EN => EN, Clock => Clock, Reset => Reset, Q=> Dout(0));
 U2: D_flip_flop port map(D => Din(1), EN => EN, Clock => Clock, Reset => Reset, Q=> Dout(1) );
 U3: D_flip_flop port map(D => Din(2), EN => EN, Clock => Clock, Reset => Reset, Q=> Dout(2) );
 U4: D_flip_flop port map(D => Din(3), EN => EN, Clock => Clock, Reset => Reset, Q=> Dout(3) );
 
end structural;
 
Here is the code for the d-type flip flop used to do the register:
 
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
use IEEE.numeric_std.all;
 
-- TOP VHDL design which implements a 8-bit Universal Shift Register
entity D_flip_flop is
  port (
    D        : in  std_logic;
     EN       : in  std_logic;
     Clock    : in std_logic;
     Reset    : in std_logic;
     Q        : out std_logic);
end entity D_flip_flop;
--// End of entity
 
--// This is an architecture of 4-bits universal shift register 
architecture RTL of D_flip_flop is
begin
PROCESS ( Clock, Reset ) 
BEGIN
    IF Reset = '1' THEN
        Q <= '0';
    ELSIF rising_edge(Clock) THEN
        Q <= D;
    END IF;
END PROCESS;
end RTL;
-- End of architectural block



here are the errors I get for the main code:

Error (10482): VHDL error at counter4bit.vhd(29): object "Dout" is used but not declared
Error (10482): VHDL error at counter4bit.vhd(29): object "Din" is used but not declared
Error (10558): VHDL error at counter4bit.vhd(29): cannot associate formal port "Dout" of mode "out" with an expression
Error (10589): VHDL Port Map Aspect error at counter4bit.vhd(29): too many actuals for block "register4bit" with only 5 formals
Error (10784): HDL error at counter4bit.vhd(17): see declaration for object "register4bit"
Error: Quartus II 32-bit Analysis & Synthesis was unsuccessful. 5 errors, 1 warning
Error: Peak virtual memory: 361 megabytes
Error: Processing ended: Wed Mar 09 14:41:42 2016
Error: Elapsed time: 00:00:01
Error: Total CPU time (on all processors): 00:00:01
Error (293001): Quartus II Full Compilation was unsuccessful. 7 errors, 1 warning
 

Your instantiation is wrong.

You have <= which is backwards for an instatiation. It should be =>. Using large run on named associations is really bad. It makes the code unreadable in my opinion.
Code:
mod1: register4bit port map (tmp(0) <= Dout(0), tmp(1) <= Dout(1),tmp(2) <= Dout(2),tmp(3) <= Dout(3), Din(0) <= mod_value(0), Din(1) <= mod_value(1), Din(2) <= mod_value(2), Din(3) <= mod_value(3), reset <= reset, clock <= clock, en < reset);
You can't call out each individual bit of the bus in an instantiation you connect the entire bus with one named association. This is why the tools complain about too many actuals.

It should have connections defined as follows:
Code:
port map (
  Dout => tmp,
  Din => mod_value,
  etc
Keeping each port association on a separate line will make your code much more readable.

i.e.:
Code:
port amp (entity_port_name => top_level_signal_connection, ....

I'm assuming someone else wrote the register4bit code as that code has the correct instantiations

Besides that you probably shouldn't be using std_logic_unsigned it's not an IEEE package it's a deprecated Synopsys package.
 
Hi ads-ee,

thanks for the reply I have made the correct adjustments and my code is this now


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
library IEEE; 
 use IEEE.STD_LOGIC_1164.ALL;
 use IEEE.STD_LOGIC_ARITH.ALL;
 use IEEE.STD_LOGIC_UNSIGNED.ALL;
 
 entity counter4bit is
 port( 
        mod_value:          in  std_logic_vector(0 to 3);
        clock:              in  std_logic;
        enable_count:       in  std_logic;
        reset:              in  std_logic;
        direction:          in  std_logic;
        output_counter: out std_logic_vector(0 to 3) );
 end counter4bit;
 
 architecture structural of counter4bit is
 component register4bit is
 port(
        Din      : in  std_logic_vector(3 downto 0);
        en       : in  std_logic;
        clock    : in  std_logic;
        reset    : in  std_logic;
        Dout     : out std_logic_vector(3 downto 0));
 end component;
 
    
 signal dig, tmp: std_logic_vector(3 downto 0); 
 begin
    mod1: register4bit port map ( Dout => tmp,
                                            Din => mod_value,
                                            reset <= reset,
                                            clock <= clock, 
                                            en <= reset);
    
 process(Clock,Reset)
     begin
         if Reset='1' then
             dig <= "0000";
         elsif ( rising_edge(clock)) then
             if (enable_count<='1' and direction<='0') then
             if dig <= "tmp(3)tmp(2)tmp(1)tmp(0)" then 
                 dig <= "0000";
             else dig <= dig + 1;
             if (enable_count<='1' and direction<='1') then
                 dig <= dig - 1;
             end if;
             end if;
             end if;
         end if;
 end process;
     output_counter <= dig;
 end structural;

but it still came up with these errors:

Error (10437): VHDL Association List error at counter4bit.vhd(31): positional associations must be listed before named associations
Error: Quartus II 64-Bit Analysis & Synthesis was unsuccessful. 1 error, 0 warnings
Error: Peak virtual memory: 511 megabytes
Error: Processing ended: Wed Mar 09 17:51:56 2016
Error: Elapsed time: 00:00:01
Error: Total CPU time (on all processors): 00:00:01
Error (293001): Quartus II Full Compilation was unsuccessful. 3 errors, 0 warnings
 
Last edited by a moderator:

You are still using <= in the port map. Use => for all signals (reset, clock, en)
 
thanks for the reply i have fixed the code now and here it is.


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
library IEEE; 
 use IEEE.STD_LOGIC_1164.ALL;
 use IEEE.STD_LOGIC_ARITH.ALL;
 use IEEE.STD_LOGIC_UNSIGNED.ALL;
 
 entity counter4bit is
 port( 
        mod_value:          in  std_logic_vector(0 to 3);
        clock:              in  std_logic;
        enable_count:       in  std_logic;
        reset:              in  std_logic;
        direction:          in  std_logic;
        output_counter: out std_logic_vector(0 to 3) );
 end counter4bit;
 
 architecture structural of counter4bit is
 component register4bit is
 port(
        Din      : in  std_logic_vector(3 downto 0);
        en       : in  std_logic;
        clock    : in  std_logic;
        reset    : in  std_logic;
        Dout     : out std_logic_vector(3 downto 0));
 end component;
 
    
 signal dig, tmp: std_logic_vector(3 downto 0); 
 begin
    mod1: register4bit port map ( Dout => tmp,
                                            Din => mod_value,
                                            reset => reset,
                                            clock => clock, 
                                            en => reset);
    
 process(Clock,Reset)
     begin
         if Reset='1' then
             dig <= "0000";
         elsif ( rising_edge(clock)) then
             if (enable_count<='1' and direction<='0') then
             if dig <= "tmp(3)tmp(2)tmp(1)tmp(0)" then 
                 dig <= "0000";
             else dig <= dig + 1;
             if (enable_count<='1' and direction<='1') then
                 dig <= dig - 1;
             end if;
             end if;
             end if;
         end if;
 end process;
     output_counter <= dig;
 end structural;



here are the errors from it:
Error (10327): VHDL error at counter4bit.vhd(41): can't determine definition of operator ""<="" -- found 0 possible definitions
Error: Quartus II 64-Bit Analysis & Synthesis was unsuccessful. 1 error, 0 warnings
Error: Peak virtual memory: 511 megabytes
Error: Processing ended: Wed Mar 09 19:33:46 2016
Error: Elapsed time: 00:00:08
Error: Total CPU time (on all processors): 00:00:02
Error (293001): Quartus II Full Compilation was unsuccessful. 3 errors, 0 warnings
 
Last edited by a moderator:

What is this supposed to be?
Code:
if dig <= "tmp(3)tmp(2)tmp(1)tmp(0)" then

if you are trying to check if dig is less than or equal to tmp then you check them directly with each other not try and assemble the tmp BUS with each bit by the code above.

You are comparing dig to a string "tmp(3)tmp(2)tmp(1)tmp(0)" a string of 24 characters.

Use
Code:
if dig <= tmp then

You need to read a VHDL book before trying to code. All of your mistakes are very rudimentary VHDL syntax problems, which you would learn by reading a VHDL book.

- - - Updated - - -

edit..

I'm pretty sure there is something wrong with the logic in your process:

Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
process(Clock,Reset)
    begin
    if Reset='1' then
        dig <= "0000";
    elsif ( rising_edge(clock)) then
        if (enable_count<='1' and direction<='0') then
            if dig <= "tmp(3)tmp(2)tmp(1)tmp(0)" then 
                dig <= "0000";
            else
                dig <= dig + 1;  -- add 1 to dig
                if (enable_count<='1' and direction<='1') then  -- but if this is met then subtract 1 from dig (this means you did nothing)
                    dig <= dig - 1;  -- dig +1 -1?
                end if;
            end if;
        end if;
    end if;
end process;


Logically this code makes no sense. I suspect your poor code formatting was then main contribution to creating faulty logic.

- - - Updated - - -

This line also makes no sense.
Code:
if (enable_count<='1' and direction<='0') then
As enable_count and direction are single bits they shouldn't be compared with less than or equal (<=). So what are your trying to do here? Do you think you can do an assignment in an if statement or something equally illegal? If you are trying to check if enable_count is 1 and direction is 0 then you do this instead.

Code:
if (enable_count = '1' and direction = '0') then

In fact the way your coding your up down counter is hard to "see" at a glance. It's IMO a convoluted way to code something. I also think the comparison to tmp is wrong...so I've changed it below into a terminal count value.

Code an up/down counter like this so it's easy to see what it does.

Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
if (count_enable = '1') then  -- counter is enabled
    if (direction = '0') then  -- counting up
        if (dig = tmp) then
            dig <= (others =>'0');
        else
            dig <= dig + 1;
        end if;
    else -- count down direction is '1'
        dig <= dig - 1;
    end if;
end if;

though I do wonder if your down counting should roll over to tmp when it reaches "0000" (which I didn't implement).
 
Yeah it does roll over when it reaches "0000" so how do we add that in?
 


Code VHDL - [expand]
1
2
3
4
5
if (dig = "0000") then
    dig <= tmp;
else
    dig <= dig - 1;
end if;

 
ok thank you I have made the modifications to the code and now it looks like this:

Code:
library IEEE; 
 use IEEE.STD_LOGIC_1164.ALL;
 use IEEE.STD_LOGIC_ARITH.ALL;
 use IEEE.STD_LOGIC_UNSIGNED.ALL;

 entity counter4bit is
 port( 
		mod_value: 			in  std_logic_vector(0 to 3);
		clock: 				in  std_logic;
		enable_count: 		in  std_logic;
		reset: 				in  std_logic;
		direction: 			in  std_logic;
		output_counter:	out std_logic_vector(0 to 3) );
 end counter4bit;

 architecture structural of counter4bit is
 component register4bit is
 port(
		Din      : in  std_logic_vector(3 downto 0);
		en       : in  std_logic;
		clock    : in  std_logic;
		reset    : in  std_logic;
		Dout     : out std_logic_vector(3 downto 0));
 end component;
 
	
 signal dig, tmp: std_logic_vector(3 downto 0); 
 begin
	mod1: register4bit port map ( Dout => tmp,
											Din => mod_value,
											reset => reset,
											clock => clock, 
											en => reset);
	
 process(Clock,Reset)
 	 begin
	  	 if Reset='1' then
			 dig <= "0000";
		 elsif ( rising_edge(clock)) then
			 if (enable_count = '1') then  
				if (direction = '0') then  
					if (dig = tmp) then
						dig <= (others =>'0');
				else
						dig <= dig + 1;
					end if;
				elsif (dig = "0000") then
					 dig <= tmp;
				else
					 dig <= dig - 1;
            end if; 
			end if;
		 end if;
 end process;
  	 output_counter <= dig;
	 
 end structural;

It compiles I just need to test it. Thank you very much.
 

You can't call out each individual bit of the bus in an instantiation you connect the entire bus with one named association. This is why the tools complain about too many actuals.

Yes you can - as long as you connect every bit of the bus, you can slice it however you want:

Code:
my_inst : entity work.Register4Bit
port map (
dout(0) <= tmp(1),
dout(2 downto 1) <= tmp(0)  & tmp(2),
dout(3) <= tmp(3) --must be connected or you get an error
);
 
  • Like
Reactions: ads-ee

    ads-ee

    Points: 2
    Helpful Answer Positive Rating
@TrickyDicky/@ads_ee
IIRC, some tools also require the bits be assigned in contiguous lines. I recall having an issue with:
Code:
port map (
  -- interface 0
  Din(0) => Ain,
  Vin(0) => v(0),
  -- interface 1
  Din(1) => Bin,
  Vin(1) => v(1),
  -- pretend there is more here
  -- ...
  )

with at least one tool. Not sure if that is actually a LRM issue. It was a use case that is now solved by VHDL2008.
 

hi guys, I have done it but now I need to implement this clock divider in the divider code

I have made a new file where I am using both the counter and the clock divider as components to do the task together, here are my codes:

code for original clock divider that I have been
Code:
-------------------------------------------------------------------------------------------
--    Project  : Programmable Up/Down Counter Design 
--    File     : Clock_Divider.vhd
--    Authors  : Alistair A. McEwan and Irfan Mir
--    Company  : University of Leicester
--    Date     : 10 March 2013
-------------------------------------------------------------------------------------------
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;

here is the code for the counter now:

Code:
library IEEE; 
 use IEEE.STD_LOGIC_1164.ALL;
 use IEEE.STD_LOGIC_ARITH.ALL;
 use IEEE.STD_LOGIC_UNSIGNED.ALL;

 entity counter4bit_half is
 port( 
		mod_value: 			in  std_logic_vector(0 to 3);
		clk_div: 			in  std_logic;
		enable_count: 		in  std_logic;
		reset: 				in  std_logic;
		direction: 			in  std_logic;
		output_counter:	out std_logic_vector(0 to 3) );
 end counter4bit_half;

 architecture behavioral of counter4bit_half is 
	component register4bit is
	
		port(
			  Din      : in  std_logic_vector(3 downto 0);
			  en       : in  std_logic;
			  clock    : in  std_logic;
			  reset    : in  std_logic;
			  Dout     : out std_logic_vector(3 downto 0));
	
	end component;
 
 signal dig, tmp: std_logic_vector(3 downto 0); 
 begin
	mod1: register4bit port map ( Dout => tmp,
											Din => mod_value,
											reset => reset,
											clock => clk_div, 
											en => reset);
	
	process(clk_div, Reset)
		begin
			if Reset='1' then
				dig <= "0000";
			elsif ( rising_edge(clk_div)) then
				if (enable_count = '1') then  
					if (direction = '0') then  
						if (dig = tmp) then
							dig <= (others =>'0');
					else
							dig <= dig + 1;
						end if;
					elsif (dig = "0000") then
							dig <= tmp;
					else
							dig <= dig - 1;
					end if; 
				end if;
			end if;
	end process;
		output_counter <= dig;
 end behavioral;

here is the code with both codes are used as component:

Code:
library IEEE; 
 use IEEE.STD_LOGIC_1164.ALL;
 use IEEE.STD_LOGIC_ARITH.ALL;
 use IEEE.STD_LOGIC_UNSIGNED.ALL;
 
 entity counter4bit is
 port( 
		mod_value: 			in  std_logic_vector(0 to 3);
		clock:    			in  std_logic;
		enable_count: 		in  std_logic;
		reset: 				in  std_logic;
		direction: 			in  std_logic;
		output_counter:	out std_logic_vector(0 to 3) );
 end counter4bit;
 
 architecture structural of counter4bit 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 clk : STD_LOGIC;
 
 Begin
	clkdiv: Clock_Divider GENERIC MAP (LIMIT => 50000000)
								 PORT MAP ( 
								          Clock   => Clock, 
											 Reset   => Reset, 
											 Clk_Div => clk);
	component counter4bit_half is
	
		port(
			  mod_value: 			in  std_logic_vector(0 to 3);				
			  clk_div: 			   in  std_logic;
			  enable_count: 		in  std_logic;
			  reset: 				in  std_logic;
			  direction: 			in  std_logic;
			  output_counter:		out std_logic_vector(0 to 3));
	
	end component;
 
 signal clk: std_logic; 
 begin
	cntr: counter4bit_half port map ( 
	                                mod_value 	  => mod_value,
											  direction 	  => direction,
											  enable_count   => enable_count,
											  clock          => clk, 
											  reset          => reset
											  output_counter => output_counter);
											  
end structural;

here are the errors I got for the code when I put them both together:
Error (10500): VHDL syntax error at counter4bit.vhd(32) near text "component"; expecting "end", or "(", or an identifier ("component" is a reserved keyword), or a concurrent statement
Error (10500): VHDL syntax error at counter4bit.vhd(37) near text "in"; expecting "(", or an identifier ("in" is a reserved keyword), or a sequential statement
Error (10500): VHDL syntax error at counter4bit.vhd(38) near text "in"; expecting "(", or an identifier ("in" is a reserved keyword), or a sequential statement
Error (10500): VHDL syntax error at counter4bit.vhd(39) near text "in"; expecting "(", or an identifier ("in" is a reserved keyword), or a sequential statement
Error (10500): VHDL syntax error at counter4bit.vhd(40) near text "out"; expecting "(", or an identifier ("out" is a reserved keyword), or a sequential statement
Error (10500): VHDL syntax error at counter4bit.vhd(40) near text ")"; expecting "(", or "'", or "."
Error (10500): VHDL syntax error at counter4bit.vhd(45) near text "begin"; expecting "end", or "(", or an identifier ("begin" is a reserved keyword), or a concurrent statement
Error (10500): VHDL syntax error at counter4bit.vhd(52) near text "output_counter"; expecting ")", or ","
Error: Quartus II 32-bit Analysis & Synthesis was unsuccessful. 8 errors, 1 warning
Error: Peak virtual memory: 361 megabytes
Error: Processing ended: Thu Mar 10 12:22:06 2016
Error: Elapsed time: 00:00:01
Error: Total CPU time (on all processors): 00:00:01
Error (293001): Quartus II Full Compilation was unsuccessful. 10 errors, 1 warning
 
Last edited by a moderator:

First of all, dividing a clock like this is very bad practice, as it will be prone to all sorts of timing issues. You are much better off generating a clock enable that effectively divides your clock by only enabling the register 1 in every N clocks of the main system clock.

As to your errors : signals and components need to be declared before the BEGIN of the architecture, instatiations are done after (please see a VHDL textbook or tutorial)
 
hi guys that idea to doing the counter was bad and I overcomplicated thinks.

Now I have written a new code and I would like you to check if now I am applying the clock divider correctly and if my mod value here can be controlled:

here is the code:

Code:
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(0 to 3);
		clock:				in std_logic;
		enable_count: 		in  std_logic;
		reset: 				in  std_logic;
		direction: 			in  std_logic;
		output_counter:	out std_logic_vector(0 to 3) );
 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);
	begin
		process(clock, Reset)
		begin
			if Reset='1' then
				dig <= "0000";
			elsif ( rising_edge(clock)) then
				if (enable_count = '1') then  
					if (direction = '0') then  
						if (dig = mod_value) then
							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 clock divider code:

Code:
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;
 

Your counter4bit_modproc doesn't use the Clock_Divider component, even though it's declared. Did you forget to instantiate it and make it the driver of the enable_count signal?

I don't recall if defining a bus using (0 to 3) will work with another bus defined as (3 downto 0). Most engineers will write VHDL with buses defined as MSB downto LSB, writing it the opposite way is atypical and I would switch to match the coding standards of the majority of the world.

On another note, don't use TABs in your code, take a look at the way it's formatted and you'll notice the if-elsif-else-end if statements sometimes line up and sometimes don't line up properly, in fact a lot of lines have vertical alignment problems. The way to not have this issue is set your text editor to use SPACES in place of TABs. If your text editor doesn't allow this...find a new text editor that is used by programmers.

- - - Updated - - -

edit...

Also I hope you are aware that your mod_value should always be set to 1 less than the actual modulo value you want to cycle on.
e.g. for a module 4 count you would want to set mod_value equal to 3.... 0,1,2,3 (cycles with 4 values)

I only mention that because so many people show up here and think they are counting correctly with clock dividers that actually count the wrong number by 1 extra and are actually off frequency.
 
What about this code now?

[incorrect version removed by moderator, for better readability]

- - - Updated - - -

I made a mistake in the previous code I posted and here is the correct one:

Code:
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;

Also I don't quite get the mod_value needing to be 1 less than the modulo value

also now if I change the modulo value and reset it will the modulo value be updated to the new one?
 
Last edited by a moderator:

If you want modulo 4 it means you want the count to cycle over 4 values. Therefore...

0 - 1st count value
1 - 2nd count value
2 - 3rd count value
3 - 4th count value

If you use 4 directly you will count like so...

0 - 1st count value
1 - 2nd count value
2 - 3rd count value
3 - 4th count value
4 - 5th count value

which is modulo 5 not modulo 4.

This code is logically wrong
Code:
if (dig <= mod_value) then  -- dig less than or equal to mod_value, i.e. 0 <= 4? YES!
    dig <= "0000";  -- Make dig 0 again
else
    dig <= dig + 1;
end if;
This is because you perform the following compare dig <= mod_value (which is the wrong comparison btw as it will force dig to 0 forever as dig will always be less than mod_value). Do you know there is a difference between assignment <= and less than or equal to <=? You should be using = in this case to check for the terminal value of 3 (assuming mod_value is set to 3 for a modulo 4 count).


Get a book or read a tutorial site on the syntax and structure of VHDL code. You really need to do this, instead of wasting time coding-posting-coding-posting-coding-posting-coding-posting.

Here is VHDL tutorial site and here are a bunch of VHDL examples.

- - - Updated - - -

Tricky already told you this is a BAD PRACTICE.


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
clkdiv: Clock_Divider generic map (LIMIT => 50000000)
                                 port map ( 
                                   clock   => Clock, 
                                   Reset   => Reset, 
                                   clk_Div => clk); -- generated clock from a flip-flop, NO, very bad practice!
      
   process(clk, Reset)
      begin
         if Reset='1' then
            dig <= "0000";
         elsif ( rising_edge(clk)) then -- NO don't use the SIGNAL from a flip-flop as a clock.



Use a synchronous clock enable instead.

BTW you're generated divided clock has a junk duty cycle that varies depending on the divide LIMIT value. It generates a single Clock period pulse over the entire LIMIT Clock cycles. Given the way it's generated it makes more sense that it's used as a clock enable instead.
 

I know he said that I need to use a clock enable. But I need to use this clock division file in my design so how would I implement this file in my counter's code
 

Assuming NEW_CLK_PERIOD value is for the new generated clock's period in Clock cycles.


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
process (Reset, Clock)
begin
    if (Reset = '1') then
        div_cnt <= 0;
        div_clk <= 0;
    elsif (rising_edge(Clock)) then
        if (div_cnt < NEW_CLK_PERIOD/2-1) then
            div_cnt <= div_cnt + 1;
        else  -- toggle the div_clk at half of the LIMIT count value
            div_cnt <= 0;
            div_clk <= not div_clk;  -- 50% duty cycle generated clock instead of a single pulse
        end if;
    end if;
end process;

 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top