I am required to design a modulo "n" counter with generic parameters. I am having trouble fixing the length of the std_logic_vector which will hold the output. Firstly, I get errors regarding the use of airthmetic operators on numeric types. And secondly, I am not allowed to use a dynamic expression in the range specification of the vector. Here is my code so far:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
use IEEE.math_real.all;
entity counter_mod is
generic(n: integer range 1 to integer'right);
port(clk,reset,load:in std_logic;
data_in:in std_logic_vector(ceil(log2(1.0*n))-1 downto 0);
q:out std_logic_vector(ceil(log2(1.0*n))-1 downto 0));
end counter_mod;
architecture behavioral of counter_mod is
begin
process(clk,reset,load)
variable count:std_logic_vector(ceil(log2(1.0*n))-1 downto 0):=(others=>'0');
begin
if(reset='1') then
count:=(others=>'0');
else if(load='1') then
count:=data_in;
else if(clk'event and clk='1') then
if(conv_integer(count)=n-1) then
count:=0;
else
count:=count+1;
end if;
end if;
end if;
end if;
q<=count;
end process;
end architecture;
Some suggestions:
Must change ceil(log2(1.0*n))
to natural(ceil(log2(real(n))))
, to address
the type mismatches
Must change count := 0
to count := (others => '0')
, since it is not
possible to assign 0
directly to std_logic_vector
.
May change integer range 1 to integer'right
to positive
, since use of the
standard
package type states the intention clearly
May change range in variable declaration to data_in'range
, since use of the
VHDL attribute states the intention clearly
May change if(conv_integer(count)=n-1) then
to if (count = n-1) then
,
since the conv_integer
is not required when using
ieee.std_logic_unsigned.all
May change if(...) then
to if ... then
, since ()
are not required in
if
because if
is a statement and not a function
May change clk'event and clk = '1'
to rising_edge(clk)
, since use of the
std_logic_1164
package function states the intention clearly
May change the else if
to use of elsif
for a clearer and less verbose
style
The code can then be updated to:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
use IEEE.math_real.all;
entity counter_mod is
generic(n : positive);
port(clk, reset, load : in std_logic;
data_in : in std_logic_vector(natural(ceil(log2(real(n))))-1 downto 0);
q : out std_logic_vector(natural(ceil(log2(real(n))))-1 downto 0));
end counter_mod;
architecture behavioral of counter_mod is
begin
process(clk, reset, load)
variable count : std_logic_vector(data_in'range) := (others => '0');
begin
if reset = '1' then
count := (others => '0');
elsif load = '1' then
count := data_in;
elsif rising_edge(clk) then
if count = n-1 then
count := (others => '0');
else
count := count+1;
end if;
end if;
q <= count;
end process;
end architecture;
Consider changing ieee.std_logic_unsigned
to ieee.numeric_std.all
, since
the ieee.std_logic_unsigned
is not a standard package, so the place in the
ieee
library is misleading. It requires change in inner if
to:
if to_integer(unsigned(count)) = n-1 then
count := (others => '0');
else
count := std_logic_vector(unsigned(count)+1);
end if;