使用按钮具有不同速度的 VHDL 时钟发生器
VHDL clock generator with different speeds using button
我是 VHDL 新手,目前正在研究可生成两种不同时钟速度的时钟发生器。
一切正常,除了慢速和快速之间的切换 speed_status。
"speed button" 似乎有问题,因为有时我必须多次按下它才能更改当前的设定速度。 "reset button" 始终按预期工作。我的 VHDL 代码有问题还是我需要添加某种软件去抖?如果是这样,为什么重置按钮有效?
你能给我一些建议,我可以改进我的时钟发生器的哪些部分吗 (code/logic)?
entity clk_gen is
Port ( clk_in : in STD_LOGIC;
clk_btn_in : in STD_LOGIC_VECTOR (3 DOWNTO 0);
clk_out : out STD_LOGIC);
end clk_gen;
architecture Behavioral of clk_gen is
signal temp : STD_LOGIC := '0';
begin
clock: process(clk_in,clk_btn_in)
variable counter : integer range 0 to 49999999 := 0;
constant freq_cnt_slow : integer := 49999999;
constant freq_cnt_fast : integer := 4999999;
type speed is (slow, fast);
variable speed_status : speed := slow;
begin
if rising_edge(clk_in) then
-- RESET BUTTON PRESSED
if (clk_btn_in = "1000") then
temp <= '0';
counter := 0;
speed_status := slow;
-- SPEED BUTTON
elsif (clk_btn_in = "0100") then
if (speed_status = fast) then
speed_status:= slow;
elsif (speed_status = slow) then
speed_status := fast;
end if;
end if;
if ((counter = freq_cnt_fast) and (speed_status = fast)) then
temp <= NOT(temp);
counter := 0;
elsif ((counter = freq_cnt_slow) and (speed_status = slow)) then
temp <= NOT(temp);
counter := 0;
else
counter := counter + 1;
end if;
end if;
end process clock;
clk_out <= temp;
end Behavioral;
我使用 Xilinx ISE 13.4 和基于 Xilinx Virtex 5 的 XC5VLX110T。
您的速度模式似乎会在按钮处于 'pressed' 状态时随时切换。除非你能保证你的按钮只有 'pressed' 一个时钟周期,否则状态很可能会切换多次,从而使你按下按钮后的状态基本上是随机的(取决于按下按钮的确切时间)。
首先,您需要在按钮上安装去抖动电路。这可以在外部实现,也可以在 FPGA 内实现。我不会在这里详细介绍开关去抖动,但您可以在其他地方轻松找到这方面的信息。其次,您需要将按钮转换为同步信号,即与您的时钟具有固定关系的信号。您的示例的示例同步器是:
signal button_reg1 : std_logic_vector(3 downto 0) := (others => '0');
signal button_reg2 : std_logic_vector(3 downto 0) := (others => '0');
...
process (clk_in)
begin
if (rising_edge(clk_in)) then
button_reg2 <= button_reg1;
button_reg1 <= clk_btn_in;
end if;
end process;
button_reg2
将与时钟建立固定关系。
否则,您可能会违反 speed_status
寄存器的 setup/hold 约束。最后,您需要将按钮的按下转换为长度为一个时钟周期的脉冲。示例:
signal speed_button_reg : std_logic := '0';
signal speed_button_pressed : std_logic := '0';
...
process (clk_in)
begin
if (rising_edge(clk_in)) then
speed_button_reg <= button_reg2(2);
if (speed_button_reg = '0' and button_reg2(2) = '1') then
-- The button has just been pressed (gone from low to high)
-- Do things here, or set another signal e.g.
speed_button_pressed <= '1';
else
speed_button_pressed <= '0';
end if;
end if;
end process;
我是 VHDL 新手,目前正在研究可生成两种不同时钟速度的时钟发生器。 一切正常,除了慢速和快速之间的切换 speed_status。 "speed button" 似乎有问题,因为有时我必须多次按下它才能更改当前的设定速度。 "reset button" 始终按预期工作。我的 VHDL 代码有问题还是我需要添加某种软件去抖?如果是这样,为什么重置按钮有效? 你能给我一些建议,我可以改进我的时钟发生器的哪些部分吗 (code/logic)?
entity clk_gen is
Port ( clk_in : in STD_LOGIC;
clk_btn_in : in STD_LOGIC_VECTOR (3 DOWNTO 0);
clk_out : out STD_LOGIC);
end clk_gen;
architecture Behavioral of clk_gen is
signal temp : STD_LOGIC := '0';
begin
clock: process(clk_in,clk_btn_in)
variable counter : integer range 0 to 49999999 := 0;
constant freq_cnt_slow : integer := 49999999;
constant freq_cnt_fast : integer := 4999999;
type speed is (slow, fast);
variable speed_status : speed := slow;
begin
if rising_edge(clk_in) then
-- RESET BUTTON PRESSED
if (clk_btn_in = "1000") then
temp <= '0';
counter := 0;
speed_status := slow;
-- SPEED BUTTON
elsif (clk_btn_in = "0100") then
if (speed_status = fast) then
speed_status:= slow;
elsif (speed_status = slow) then
speed_status := fast;
end if;
end if;
if ((counter = freq_cnt_fast) and (speed_status = fast)) then
temp <= NOT(temp);
counter := 0;
elsif ((counter = freq_cnt_slow) and (speed_status = slow)) then
temp <= NOT(temp);
counter := 0;
else
counter := counter + 1;
end if;
end if;
end process clock;
clk_out <= temp;
end Behavioral;
我使用 Xilinx ISE 13.4 和基于 Xilinx Virtex 5 的 XC5VLX110T。
您的速度模式似乎会在按钮处于 'pressed' 状态时随时切换。除非你能保证你的按钮只有 'pressed' 一个时钟周期,否则状态很可能会切换多次,从而使你按下按钮后的状态基本上是随机的(取决于按下按钮的确切时间)。
首先,您需要在按钮上安装去抖动电路。这可以在外部实现,也可以在 FPGA 内实现。我不会在这里详细介绍开关去抖动,但您可以在其他地方轻松找到这方面的信息。其次,您需要将按钮转换为同步信号,即与您的时钟具有固定关系的信号。您的示例的示例同步器是:
signal button_reg1 : std_logic_vector(3 downto 0) := (others => '0');
signal button_reg2 : std_logic_vector(3 downto 0) := (others => '0');
...
process (clk_in)
begin
if (rising_edge(clk_in)) then
button_reg2 <= button_reg1;
button_reg1 <= clk_btn_in;
end if;
end process;
button_reg2
将与时钟建立固定关系。
否则,您可能会违反 speed_status
寄存器的 setup/hold 约束。最后,您需要将按钮的按下转换为长度为一个时钟周期的脉冲。示例:
signal speed_button_reg : std_logic := '0';
signal speed_button_pressed : std_logic := '0';
...
process (clk_in)
begin
if (rising_edge(clk_in)) then
speed_button_reg <= button_reg2(2);
if (speed_button_reg = '0' and button_reg2(2) = '1') then
-- The button has just been pressed (gone from low to high)
-- Do things here, or set another signal e.g.
speed_button_pressed <= '1';
else
speed_button_pressed <= '0';
end if;
end if;
end process;