级联计数器的十进制数字增量太晚
Decade Digit of Cascading Counter increments too late
我正在尝试设计一个两位数计数器,以循环方式向上和向下计数 00 和 99 之间的计数。我大部分时间都在使用它,但是,无论我尝试什么,我都无法让十进制数字与第一位数字保持同步。我现在的结果是这样的:
08 -> 09 -> 00 -> 11 ... 18 -> 19 -> 10 -> 21
和
21 -> 20 -> 29 -> 18 ... 11 -> 10 -> 19 -> 08
由此看来,从第一位溢出到十进制位似乎有所延迟。我已经尝试了几件事来尝试解决这个问题。提供任何有益结果的唯一方法是添加一个额外的 if 语句,提前发送溢出状态,但这只是表面修复。如果我在第一个数字为 8 或 0 时停止计数器,然后再次启动它,我会回到与以前相同的问题。
我也尝试制作一个额外的 'synchronizer' 模块,想也许我可以设置它,所以即使它们不同步,它们也会像同步一样显示,但它没有任何改变。
两周多来我一直在努力解决这个问题,但我已经束手无策了。
这是我的计数器代码,如果有人想检查同步器,我们将不胜感激。
**我正在使用 VHDL,使用 Vivado 2015.2 对 Zybo Digilent 开发板进行编程
个位数计数器模块,溢出成为十进制位使能。
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;
您导致同步问题的明显基本问题是您的 'overflow' 信号已注册,它是在 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;
请注意,我还将启用与溢出信号进行了 AND 运算,因此它可以用作下一阶段的启用:
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;
这给出了:
(可点击)
虽然这里只是简单的表示个位翻滚,但是在测试台下的向下计数和翻滚是可以扩展的
我正在尝试设计一个两位数计数器,以循环方式向上和向下计数 00 和 99 之间的计数。我大部分时间都在使用它,但是,无论我尝试什么,我都无法让十进制数字与第一位数字保持同步。我现在的结果是这样的:
08 -> 09 -> 00 -> 11 ... 18 -> 19 -> 10 -> 21
和
21 -> 20 -> 29 -> 18 ... 11 -> 10 -> 19 -> 08
由此看来,从第一位溢出到十进制位似乎有所延迟。我已经尝试了几件事来尝试解决这个问题。提供任何有益结果的唯一方法是添加一个额外的 if 语句,提前发送溢出状态,但这只是表面修复。如果我在第一个数字为 8 或 0 时停止计数器,然后再次启动它,我会回到与以前相同的问题。
我也尝试制作一个额外的 'synchronizer' 模块,想也许我可以设置它,所以即使它们不同步,它们也会像同步一样显示,但它没有任何改变。
两周多来我一直在努力解决这个问题,但我已经束手无策了。
这是我的计数器代码,如果有人想检查同步器,我们将不胜感激。
**我正在使用 VHDL,使用 Vivado 2015.2 对 Zybo Digilent 开发板进行编程
个位数计数器模块,溢出成为十进制位使能。
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;
您导致同步问题的明显基本问题是您的 'overflow' 信号已注册,它是在 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;
请注意,我还将启用与溢出信号进行了 AND 运算,因此它可以用作下一阶段的启用:
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;
这给出了:
虽然这里只是简单的表示个位翻滚,但是在测试台下的向下计数和翻滚是可以扩展的