名称:基于FPGA的拔河游戏的电路设计VHDL代码Quartus 实验箱
软件:Quartus
语言:VHDL
代码功能:
1.任务及要求
设计一个能进行拔河游戏的电路。
电路使用7个发光二极管,开机后只有中间一个发亮,此即拔河的中心点。游戏双方各持一个按钮,迅速地、不断地按动,产生脉冲,谁按得快,亮点就向谁的方向移动,每按一次,亮点移动一次。亮点移到任一方终端二极管时,这一方就获胜,此时双方按钮均无作用,输出保持,只有复位后才使亮点恢复到中心。用数码管显示获胜者的盘数。
2、设计提示
按钮信号即输入的脉冲信号,每按一次按钮都应能进行有效的计数。用可逆计数器的加、减计数输入端分别接受两路脉冲信号,可逆计数器原始输出状态为0000,经译码器输出,使中间一只二极管发亮。当计数器进行加法计数时,亮点向右移;进行减法计数时,亮点向左移。由一个控制电路指示谁胜谁负,当亮点移到任一方终端时,由控制电路产生一个信号,使计数器停止计数。将双方终端二极管“点亮”信号分别接两个计数器的“使能”端,当一方取胜时,相应的计数器进行一次计数,这样得到双方取胜次数的显示。设置一个“复位”按钮,使亮点回到中心,取胜计数器也要设置一个“复位”按钮,使之能清零。
本代码已在实验箱验证,实验箱如下,其他开发板可以修改管脚适配:
1. 工程文件
2. 程序文件
3. 程序编译
4. RTL图
状态图
5. 管脚分配
6. 仿真图
拔河控制仿真
部分代码展示:
LIBRARY ieee; USE ieee.std_logic_1164.all; USE ieee.std_logic_unsigned.all; --控制模块 ENTITY bahe_ctrl IS PORT ( clk : IN STD_LOGIC;--标准时钟 reset_n : IN STD_LOGIC;--复位信号,低有效 reset_cnt : IN STD_LOGIC;--计数复位信号,低有效 shift1 : IN STD_LOGIC;--选手1 shift2 : IN STD_LOGIC;--选手2 led : OUT STD_LOGIC_VECTOR(6 DOWNTO 0);--7个led win1_times :OUT STD_LOGIC_VECTOR(15 DOWNTO 0);--1号获胜次数 win2_times :OUT STD_LOGIC_VECTOR(15 DOWNTO 0)--2号获胜次数 ); END bahe_ctrl; ARCHITECTURE behave OF bahe_ctrl IS TYPE State_type IS (s_idle, s_start, s_left_shift, s_right_shift, s_win_1, s_win_2); -- 定义状态 SIGNAL state : State_Type; -- 创建信号 SIGNAL game_led : STD_LOGIC_VECTOR(6 DOWNTO 0) := "0001000"; SIGNAL win1_num : STD_LOGIC_VECTOR(15 DOWNTO 0) := "0000000000000000"; SIGNAL win2_num : STD_LOGIC_VECTOR(15 DOWNTO 0) := "0000000000000000"; BEGIN PROCESS (clk) BEGIN IF (clk'EVENT AND clk = '1') THEN IF ((NOT(reset_n)) = '1') THEN state <= s_idle; ELSE CASE state IS WHEN s_idle =>--复位状态 state <= s_start; WHEN s_start =>--游戏中 IF (game_led = "1000000") THEN state <= s_win_1;--1号赢 ELSIF (game_led = "0000001") THEN state <= s_win_2;--2号赢 ELSIF (shift1 = '1') THEN state <= s_left_shift;--led左移 ELSIF (shift2 = '1') THEN state <= s_right_shift;--led右移 ELSE state <= s_start; END IF; WHEN s_left_shift =>--led左移 state <= s_start; WHEN s_right_shift =>--led右移 state <= s_start; WHEN s_win_1 => state <= s_win_1;--1号赢 WHEN s_win_2 => state <= s_win_2;--2号赢 WHEN OTHERS => END CASE; END IF; END IF; END PROCESS; PROCESS (clk) BEGIN IF (clk'EVENT AND clk = '1') THEN IF ((NOT(reset_n)) = '1') THEN--复位 game_led <= "0001000"; ELSIF (state = s_left_shift) THEN game_led <= (game_led(5 DOWNTO 0) & '0');--led左移 ELSIF (state = s_right_shift) THEN game_led <= ('0' & game_led(6 DOWNTO 1));--led右移 END IF; END IF; END PROCESS; PROCESS (clk) BEGIN IF (clk'EVENT AND clk = '1') THEN IF ((NOT(reset_cnt)) = '1') THEN--复位 win1_num <= "0000000000000000"; ELSIF (state = s_start and game_led = "1000000") THEN----1号赢 win1_num <=win1_num+ "0000000000000001";--加1 ELSE win1_num <=win1_num; END IF; END IF; END PROCESS; PROCESS (clk) BEGIN IF (clk'EVENT AND clk = '1') THEN IF ((NOT(reset_cnt)) = '1') THEN--复位 win2_num <= "0000000000000000"; ELSIF (state = s_start and game_led = "0000001") THEN----2号赢 win2_num <=win2_num+ "0000000000000001";--加1 ELSE win2_num <=win2_num; END IF; END IF; END PROCESS; --输出 win1_times<=win1_num; win2_times<=win2_num; led <= game_led; END behave;
源代码
扫描文章末尾的公众号二维码