我有以下代码,这是我的数字时钟的一部分:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_unsigned.all;
-- Seconds counter
entity SecCounter is
port(
s_enable: in std_logic;
s_load: in std_logic; -- When high, sets this counter to the value in the data inputs
s_clk: in std_logic; -- Clock
s_input: in std_logic_vector(5 downto 0); -- Data inputs
s_output: out std_logic_vector(5 downto 0); --Outputs
s_wrap: out std_logic
);
end SecCounter;
architecture imp of SecCounter is
-- Intermediate signal to mainpulate the seconds as integer
signal sec: integer range 0 to 60 := 22;
begin
s_output <= std_logic_vector(to_unsigned(sec,6)); -- Assign the input to the binary value of sec
process(s_clk, s_load, s_enable) -- If clk, enable, or load is changed
begin
s_wrap <= '0'; -- Clear the wrap
if (s_enable = '0' and s_load = '1') then -- Set the clock
sec <= to_integer(unsigned(s_input));
elsif (s_enable = '1' and rising_edge(s_clk)) then -- Increment the counter
sec <= sec + 1;
end if;
if sec = 60 then -- Restart counter and toggle the next counter
sec <= 0;
s_wrap <= '1';
end if;
end process;
end imp;
s_wrap充当下一个计数器的启用。我想要做的是,如果这个计数器等于60,我想为一个时钟边沿启用下一个计数器。我试图通过将s_wrap设置为true然后在下一个时钟边缘设置为false来执行此操作;但是,它没有改变。有没有办法让is_wrap无国籍?如果没有,我该如何解决这个问题?
答案 0 :(得分:2)
您要将值分配给rising_edge(clk)子句之外的sec。如果s_enable = 0且s_load = 0,则不会将任何内容分配给sec。这些事实中的任何一个都使得sec成为异步信号。如果你修复了这两个问题,那么所描述的问题就会消失。
Oli Charlesworth对于检查59而不是60来说有一个很好的观点。然后你不必人为地将你不存在的60包括在你的范围内。将sec初始化为一个值没有意义。您应该在reset子句中初始化它。
由于您正在异步读取s_enable,s_load和s_input,因此可能还有其他问题。这通常仅针对复位信号进行。
答案 1 :(得分:1)
[免责声明:我对VHDL不太满意,所以我无法就语法提出建议。]
我认为您希望在s_wrap
达到 59 而非 60 时断言sec
。这样,在下一个时钟边沿,分钟计数器将看到s_wrap = 1
并递增,同时此计数器输出再次变为0。
我想你想要这样的东西:
process(s_clk, s_load, s_enable) -- If clk, enable, or load is changed
begin
if (s_enable = '0' and s_load = '1') then -- Set the clock
sec <= to_integer(unsigned(s_input));
elsif (s_wrap = '1') then -- Wrap
sec <= 0;
elsif (s_enable = '1' and rising_edge(s_clk)) then -- Increment the counter
sec <= sec + 1;
end if;
end process;
s_wrap <= '1' when sec = 59 else '0';
答案 2 :(得分:0)
我会做的是将sec声明为流程中的变量,因为变量会立即更新:
process(s_clk, s_load, s_enable)
variable v_sec : integer range 0 to 60;
begin
if reset = '1' then
v_sec := 0;
s_sec <= (others => '0');
s_wrap <= '0';
elsif rising_edge(s_clk) then
s_output <= std_logic_vector(to_unsigned(v_sec,6));
if s_enable = '1' then
v_sec := v_sec +1;
if v_sec = 60 then
v_sec:= 0;
s_wrap <= '1';
else
s_wrap <= '0';
end if;
else
s_wrap <= '0';
end if;
end if;
如果你在modelsim中模拟这个,那么sec将会变为0,1,2,.... 58,59,0,1,2,并且s_wrap将等于1每次秒等于0,除了第一次,当复位条件将其设置为0时。