有没有更好的方法在VHDL代码中用较少的“if-statement”重写BCD计数器?

时间:2012-03-27 03:32:49

标签: counter vhdl modelsim

我刚开始在modelsim中学习VHDL,所以如果我正在做的事情看起来真的很棒,我会事先道歉。

基本上我想要创建的是一个可合成的VHDL代码,用于一位数的上/下BCD计数器。当“启用”为“1”时,计数器将计数,否则它将保持不变。当输入“Init”初始化时,计数器设置为0或9,具体取决于“Direction”输入的值。 (当“Direction”为“1”时,它是一个向上计数器。)

我只是想知道是否有更好的工具可用于此工作,而不是连续使用100 if和else。

这是我的代码,我正在为它编写一个测试平台,所以我还不确定这是否会起作用。因此,如果您碰巧也发现了一些错误,请指出我。

提前多多感谢,这是我的代码

entity BCD_counter is
  port(clk, direction, init, enable: in bit;
    q_out: out integer);
end entity BCD_counter;

architecture behaviour of BCD_counter is
  signal q: integer;
begin
  process(clk)
  begin
    if(Clk'event and Clk = '1') then
      if(direction = '1') then -- counting up
        if(init = '1')then --initialize
          q<=0; -- reset to 0
        else
         if(enable = '1')then -- counting          
            if (q<9) then
              q<=q+1;
            else
              q<=0;
            end if;          
         else
          q<=q;
          end if;
        end if;
      elsif(direction = '0') then --counting down
        if(init = '1') then --initialize
          q<=9; --reset to 9
        else
          if(enable = '1') then --counting        
            if (q>0) then
              q<=q-1;
            else
              q<=9;
            end if;       
          else
            q<=q;
          end if;
        end if;
      end if;
    end if;

  end process;  
      q_out <= q;  
end architecture behaviour;

3 个答案:

答案 0 :(得分:2)

风格略有不同,但这就是我写它的方式

architecture behaviour of BCD_counter is
  signal next_q : integer;
  signal q      : integer;
begin

  pReg : process
  begin  -- process pReg
    wait until clk'event and clk = '1';
    if init = '1' then
      q <= 0;
    else
      q <= next_q;
    end if;
  end process pReg;

  pCount : process (direction, enable, q)
  begin  -- process pCount
    next_q <= q;

    if enable = '1' then
      if direction = '1' then
        next_q <= q + 1;

        if q = 9 then
          next_q <= 0;
        end if;

      else
        next_q <= q - 1;

        if q = 0 then
          next_q <= 9;
        end if;

      end if;
    end if;
  end process pCount;

  q_out <= q;
end architecture behaviour;

注意事项:

  • 寄存器行为与逻辑分开。我发现这种风格很干净。其他人有不同的意见,通常归结为不喜欢next_blah信号。
  • init是你的复位信号,因此它会覆盖其他所有信号,并将复位信号放入寄存器进程中。
  • 计数器进程的第一行是我想要默认发生的事情。在这种情况下,它表示q的下一个状态是当前状态。
  • 我将外if作为enable的核对。如果我们没有启用,我们什么都不做,那么为什么要先检查direction
  • 在方向条件的每一半内部,代码结构是相同的。设置我想要的正常情况,然后检查规则的例外情况。例如:如果我们上升,我将下一个状态设置为q + 1,但如果q为9,则用q&lt; = 0覆盖它。
  • 我没有在任何比较中使用><。这些费用比=贵,=就好了。

或者,您可以将启用带入注册过程。它略短,可能更清晰。这也很明显,您希望使用寄存器的使能引脚来实现此功能。

  pReg : process
  begin  -- process pReg
    wait until clk'event and clk = '1';
    if init = '1' then
      q <= 0;
    else
      if enable = '1' then
        q <= next_q;
      end if;
    end if;
  end process pReg;

  pCount : process (direction, q)
  begin  -- process pCount
    if direction = '1' then
      next_q <= q + 1;

      if q = 9 then
        next_q <= 0;
      end if;
    else
      next_q <= q - 1;

      if q = 0 then
        next_q <= 9;
      end if;
    end if;
  end process pCount;

答案 1 :(得分:1)

我唯一想到的是你可以省略两个

else
   q<=q;

语句,因为如果没有其他条件检出,则隐式完成。

答案 2 :(得分:0)

我做了很多这个 - 我创建了一个名为modulo_increment的函数,它接受一个输入整数和“模数”整数,并返回包裹的值。

所以你可以这样做

q <= modulo_increment(q, 10);