设计要求:
1.多人参赛,每人都有一个按钮,主持人有一个按钮。每名参赛选手有一个发光二极管。
2.率先抢到的选手对应的二极管发光,有人抢答后,其他人抢答无效。
3.当有人抢答后,蜂鸣器响2秒,同时数码管倒计时10秒(0-9-8....0),结束后蜂鸣器响2秒,标志一轮抢答结束。
4.一轮抢答结束后,主持人可以按下按钮进行重置,从而开始下一轮抢答。
模块划分:
1.抢答模块
2.计时模块
3.蜂鸣模块
4.数码管控制模块
5.分频模块
抢答模块
使用D触发器来实现抢答信号输入以及锁定功能。
PRN | CLRN | CLK | D | Q* |
---|---|---|---|---|
0 | 1 | X | X | 1 |
1 | 0 | X | X | 0 |
0 | 0 | X | X | 禁止 |
1 | 1 | ↑ | 1 | 1 |
1 | 1 | ↑ | 0 | 0 |
可以看到,我们只需要让PRN端恒接高电平,通过控制CLRN端即可控制抢答器抢答和切换,至于锁定只需要让时钟信号端接收不到上升沿即可。
仿真一下试试
可以看到,仿真结果确实挺不错的!
计时模块
在接收到高电平时,输出两秒的高电平,间隔十秒后再次输出两秒的高电平用来驱动蜂鸣器模块。
process(clk)
begin
if rising_edge(clk) then
input_reg <= input_signal;
case state is
when IDLE =>
output_signal <= '0';
if (input_signal = '1' and input_reg = '0') then
state <= FIRST_HIGH;
counter <= 0;
end if;
when FIRST_HIGH =>
output_signal <= '1';
if counter = 1 then
state <= WAT;
counter <= 0;
else
counter <= counter + 1;
end if;
when WAT =>
output_signal <= '0';
if counter = 9 then
state <= SECOND_HIGH;
counter <= 0;
else
counter <= counter + 1;
end if;
when SECOND_HIGH =>
output_signal <= '1';
if counter = 1 then
state <= IDLE;
counter <= 0;
else
counter <= counter + 1;
end if;
end case;
end if;
end process;
定义四种状态,初始态IDLE,FIRST_HIGH输出两秒高电平,WAT,等待10秒,SECOND_HIGH再次输出两秒高电平。
数码管控制模块
process (clk)
begin
if rising_edge(clk) then
if (input = '1' and input_last = '0') then
countdown <= 9;
trigger <= '1';
elsif trigger = '1' then
if countdown > 0 then
countdown <= countdown - 1;
else
trigger <= '0';
end if;
end if;
input_last <= input;
end if;
end process;
在输入信号的上升沿(input 从 '0' 变为 '1')时,重置倒计时值为9,并设置 trigger 信号为 '1'。如果 trigger 信号为 '1',且倒计时值大于0,则倒计时值减1;如果倒计时值为0,则将 trigger 信号重置为 '0'。最后更新 input_last 信号,用于检测下一个时钟周期的输入信号变化。
蜂鸣器模块
接上1000Hz的时钟信号即可。非常简单。
总图
按需分配管脚即可。
总结
非常简单的一篇小博客,如果有帮助的话希望能点上一个小小的赞,非常感谢!