模数通用计数器

use*_*971 4 generics counter vhdl modulo

我需要设计一个带有通用参数的模"n"计数器.我无法修复将保存输出的std_logic_vector的长度.首先,我在数字类型上使用airthmetic运算符时遇到错误.其次,我不允许在向量的范围规范中使用动态表达式.到目前为止,这是我的代码:

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;
Run Code Online (Sandbox Code Playgroud)

Mor*_*mer 6

一些建议:

  • 必须ceil(log2(1.0*n))改为natural(ceil(log2(real(n)))),以解决类型不匹配问题

  • 必须更改count := 0count := (others => '0'),因为无法0直接分配给std_logic_vector.

  • 可以integer range 1 to integer'right改为positive,因为使用 standard包类型清楚地表明了意图

  • 可以将变量声明中的范围更改为data_in'range,因为使用VHDL属性清楚地表明了意图

  • 可以更改if(conv_integer(count)=n-1) thenif (count = n-1) then,因为conv_integer使用时不需要 ieee.std_logic_unsigned.all

  • 可以if(...) then改为if ... then,因为()不是必需的 if因为if是一个声明而不是一个函数

  • 可以clk'event and clk = '1'改为rising_edge(clk),因为使用 std_logic_1164包函数清楚地表明了意图

  • 可以改变else if使用elsif更清晰,更简洁的风格

然后可以将代码更新为:

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;
Run Code Online (Sandbox Code Playgroud)

考虑更改ieee.std_logic_unsignedieee.numeric_std.all,因为ieee.std_logic_unsigned它不是标准包,因此 ieee库中的位置具有误导性.它需要改变内在if:

if to_integer(unsigned(count)) = n-1 then
  count := (others => '0');
else
  count := std_logic_vector(unsigned(count)+1);
end if;
Run Code Online (Sandbox Code Playgroud)