【问题标题】:Decade Digit of Cascading Counter increments too late级联计数器的十位数字增量太晚
【发布时间】:2015-09-26 21:51:58
【问题描述】:

我正在尝试设计一个两位数计数器,以上下循环方式计数 00 到 99 之间的计数。我大部分时间都在工作,但是,无论我尝试什么,我都无法让十进制数字与第一个数字保持同步。我现在的结果给了我这样的东西:

08 -> 09 -> 00 -> 11 ... 18 -> 19 -> 10 -> 21

21 -> 20 -> 29 -> 18 ... 11 -> 10 -> 19 -> 08

由此看来,第一个数字的溢出在达到十位数字时会延迟。我已经尝试了几件事来尝试解决这个问题。提供任何有益结果的唯一方法是添加一个额外的 if 语句,该语句会提前发送溢出状态,但这只是表面上的修复。如果我在第一个数字是 8 或 0 时停止计数器,然后重新启动它,我会回到和以前一样的问题。

我还尝试制作一个额外的“同步器”模块,想也许我可以设置它,所以即使它们不同步,它们也会显示为好像它们是同步的,但它没有改变任何东西。

两周多来,我一直在努力解决这个问题,但我束手无策。

这是我的计数器代码和同步器,如果有人想检查的话,我们将不胜感激。

**我正在使用 VHDL,使用 Vivado 2015.2 对 Zybo Digilent Board 进行编程

一位数的计数器模块,溢出成为十进制数的使能。

library IEEE;
use IEEE.STD_LOGIC_1164.all;
use ieee.numeric_std.all;

entity counter is
    generic(N      : positive := 4);
    port(
        AR       : in  STD_LOGIC;
        clk      : in  STD_LOGIC;
        ld       : in  STD_LOGIC;
        en       : in  STD_LOGIC;
        up_dn    : in  STD_LOGIC;
        D        : in  STD_LOGIC_VECTOR(N - 1 downto 0);
        overflow : out STD_LOGIC;
        Q        : out STD_LOGIC_VECTOR(N - 1 downto 0);
        sync_in  : in STD_LOGIC;
        sync_out : out STD_LOGIC
    );
end counter;

architecture counter of counter is
    signal Qt : std_logic_vector(N - 1 downto 0);
    signal OvrFlw : std_logic;
    signal sync : std_logic;

begin
    process(clk, AR)
    begin
        if (AR = '1') then
            Qt       <= (others => '0');
            OvrFlw <= '0';
            sync <= sync_in;
        elsif (clk = '1' and clk'event) then
            if ld = '1' then
                Qt <= D;
                sync <= sync_in;
            elsif en = '1' then
                if up_dn = '0' then     -- if counting down
                    if (unsigned(Qt) = 0) then
                        Qt       <= "1001";--(others => '1');
                        OvrFlw <= '1';
                        sync <= sync_in and en;
                    --elsif (unsigned(Qt) = 1) then
                    --    Qt       <= std_logic_vector(unsigned(Qt) - 1);
                    --    OvrFlw <= '1';
                    else
                        Qt       <= std_logic_vector(unsigned(Qt) - 1);
                        OvrFlw <= '0';
                        sync <= sync_in and en;
                    end if;
                else                    -- if counting up
                    if (unsigned(Qt) = 2**N-7) then
                        Qt       <= (others => '0');
                        OvrFlw <= '1';
                        sync <= sync_in and en;
                    --elsif (unsigned(Qt) = 2**N-8) then
                    --    Qt       <= std_logic_vector(unsigned(Qt) + 1);
                    --    OvrFlw <= '1';
                    else
                        Qt       <= std_logic_vector(unsigned(Qt) + 1);
                        OvrFlw <= '0';
                        sync <= sync_in and en;
                    end if;
                end if;
            end if;
        end if;
    end process;

    sync_out <= sync;
    Q <= Qt;
    overflow <= OvrFlw;
end counter;

这是我尝试整理的同步器的代码。不知道它是否真的相关,但我想我会把它放上来以防万一。

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity Synchronizer is
    generic(N      : positive := 4);
    Port (  
          MSB_Sync : in  STD_LOGIC;
          LSB_Sync : in  STD_LOGIC;
          MSB_Q    : in  STD_LOGIC_VECTOR(N-1 downto 0);
          LSB_Q    : in  STD_LOGIC_VECTOR(N-1 downto 0);
          MSB_Out  : out STD_LOGIC_VECTOR(N-1 downto 0);
          LSB_Out  : out STD_LOGIC_VECTOR(N-1 downto 0));
end Synchronizer;

architecture Behavioral of Synchronizer is

begin
process (MSB_Sync, LSB_Sync)
    begin
    if ((MSB_Sync and LSB_Sync) = '1') then
        MSB_Out <= MSB_Q;
        LSB_Out <= LSB_Q;
    end if;
end process;

end Behavioral;

【问题讨论】:

  • 当 N 设置为 4 以外的值时,if (unsigned(Qt) = 2**N-7) then 应该做什么?

标签: synchronization vhdl counter


【解决方案1】:

导致同步问题的明显基本问题是您的“溢出”信号已注册,它是在 if 语句中以时钟上升沿为条件的分配。

我在以下示例中转储了同步内容并删除了溢出寄存器:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity bcd_ud_ctr is
    port (
        AR:         in  std_logic;
        clk:        in  std_logic;
        ld:         in  std_logic;
        en:         in  std_logic;
        up_dn:      in  std_logic;
        D:          in  std_logic_vector (3 downto 0);
        overflow:   out std_logic;
        Q:          out std_logic_vector (3 downto 0)
    );
end entity;

architecture off of bcd_ud_ctr is
    signal Qt:      unsigned (3 downto 0);
    signal nine:    std_logic;
    signal zero:    std_logic;

begin
    -- Count recognizers
    nine <= '1' when Qt = "1001" else
            '0';
    zero <= '1' when Qt = "0000" else
            '0';
COUNT:
    process (clk, AR)
    begin
        if AR = '1' then
            Qt <= (others => '0');
        elsif rising_edge(clk) then
            if ld = '1' then
                Qt <= unsigned(D);
            elsif en = '1' then
                if up_dn = '0' then  -- up
                    if nine = '1' then
                        Qt <= (others => '0');
                    else
                        Qt <= Qt + 1;
                    end if;
                else                  -- down
                    if zero = '1' then 
                        Qt <= "1001"; 
                    else 
                        Qt <= Qt - 1;
                    end if;
                end if;
            end if;
        end if;
    end process;

BUFFERED_OUT:    
    Q <= std_logic_vector(Qt);

CARRY_BORROW:
    overflow <= (en and     up_dn and zero) or
                (en and not up_dn and nine);
end architecture;

请注意,我还将启用与溢出信号相结合,以便它可以用作下一阶段的启用:

library ieee;
use ieee.std_logic_1164.all;

entity bcd_2digit_tb is
end entity;

architecture foo of bcd_2digit_tb is
    signal AR:          std_logic;
    signal clk:         std_logic := '0';
    signal ld:          std_logic := '0'; 
    signal en:          std_logic := '0';
    signal up_dn:       std_logic := '1';
    signal rollover:    std_logic;
    signal Q:           std_logic_vector (7 downto 0);

    constant DIG_PAR:   std_logic_vector(3 downto 0) := "0010"; -- 2
    constant TEN_PAR:   std_logic_vector(3 downto 0) := "0100"; -- 4 (42)
begin

CLOCK:
    process
    begin
        wait for 10 ns;
        clk <= not clk;
        if Now > 500 ns then
            wait;
        end if;
    end process;

DIGITS:
    entity work.bcd_ud_ctr
        port map (
            AR => AR,
            clk => clk,
            ld => ld,
            en => en,
            up_Dn => up_dn,
            D => DIG_PAR,
            overflow => rollover,
            Q => Q(3 downto 0)
        );
TENS:
    entity work.bcd_ud_ctr
        port map (
            AR => AR,
            clk => clk,
            ld => ld,
            en => rollover, 
            up_Dn => up_dn,
            D => TEN_PAR,
            overflow => open,
            Q => Q(7 downto 4)
        );
STIMULUS:
    process
    begin
        wait for 10 ns;
        AR <= '1';
        wait for 10 ns;
        AR <= '0';
        up_dn <= '0'; -- up
        en <= '1';
        wait for 260 ns;
        up_dn <= '1';
        wait;
    end process;
end architecture;

这给出了:

(可点击)

虽然这只是显示一个数字的滚动,但可以扩展测试台下的向下计数和滚动。

【讨论】:

  • 谢谢!它完全按预期工作!我知道问题与时钟敲击时发生的变化有关,但我不知道该怎么做才能解决它。非常感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-06
  • 2016-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多