You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VHDL编写Simon游戏报错:Case语句需覆盖表达式所有可能值

Simon游戏VHDL代码错误修复与问题排查

问题概述

编写Simon游戏VHDL代码时,第35行的Case display counter is语句持续报错:"Case statement must cover all possible values of expression",同时需排查代码中其他潜在问题。

原始代码

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_ARITH.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity SimonGame is

Port ( clk : in STD_LOGIC;
       rst : in STD_LOGIC;
       btn1, btn2, btn3, btn4 : in STD_LOGIC;
       hex_0, hex_1, hex_2 : out STD_LOGIC_VECTOR(6 downto 0));

end SimonGame;


architecture Behavioral of SimonGame is

signal sequence : STD_LOGIC_VECTOR(2 downto 0);
signal count : INTEGER := 0;
signal display_counter : INTEGER := 0;
signal correct_input : BOOLEAN := TRUE;

type Digit_State is (DISPLAY_SEQUENCE, AWAIT_INPUT);
signal state : Digit_State := DISPLAY_SEQUENCE;

begin
process(clk, rst)
begin
    if rst = '1' then
        sequence <= "001"; -- Initial sequence
        count <= 0;
        display_counter <= 0;
        state <= DISPLAY_SEQUENCE;
    elsif rising_edge(clk) then
        case state is
            when DISPLAY_SEQUENCE =>
                -- Display the sequence on hex_0 and hex_1
                case display_counter is
                    when 0 =>
                        hex_0 <= "0000001";
                        hex_1 <= "0000000";
                    when 1 =>
                        hex_0 <= "0001000";
                        hex_1 <= "0000000";
                    when 2 =>
                        hex_0 <= "0000100";
                        hex_1 <= "0000000";
                    when 3 =>
                        hex_0 <= "0000010";
                        hex_1 <= "0000000";
                    when 4 =>
                        hex_0 <= "0001000";
                        hex_1 <= "0000000";
                    when 5 =>
                        hex_0 <= "0000001";
                        hex_1 <= "0000000";
                        state <= AWAIT_INPUT;
                end case;

                if display_counter < 5 then
                    display_counter <= display_counter + 1;
                else
                    display_counter <= 0;
                    count <= count + 1;
                    sequence <= sequence(0) & sequence(2 downto 1); -- Shift the sequence
                end if;

            when AWAIT_INPUT =>
                -- Check button input against the sequence
                if btn1 = '1' then
                    correct_input <= (sequence = "001");
                elsif btn4 = '1' then
                    correct_input <= (sequence = "010");
                elsif btn3 = '1' then
                    correct_input <= (sequence = "100");
                elsif btn2 = '1' then
                    correct_input <= (sequence = "010");
                else
                    correct_input <= FALSE;
                end if;

                if correct_input then
                    state <= DISPLAY_SEQUENCE;
                end if;
        end case;
    end if;
end process;
end Behavioral;

核心错误修复(Case语句未覆盖所有值)

错误原因

display_counter是INTEGER类型,VHDL中INTEGER默认取值范围极大,而代码中仅处理了0-5的情况,综合器要求必须覆盖所有可能取值。

修复方案

  1. 限定信号取值范围:给display_counter明确指定0-5的范围,缩小综合器的检查范围:
    signal display_counter : INTEGER range 0 to 5 := 0;
    
  2. 添加when others分支:在Case语句末尾补充兜底分支,处理所有未明确列出的情况(即使范围限定后,这也是规范的编码习惯):
    case display_counter is
        when 0 =>
            hex_0 <= "0000001";
            hex_1 <= "0000000";
        when 1 =>
            hex_0 <= "0001000";
            hex_1 <= "0000000";
        when 2 =>
            hex_0 <= "0000100";
            hex_1 <= "0000000";
        when 3 =>
            hex_0 <= "0000010";
            hex_1 <= "0000000";
        when 4 =>
            hex_0 <= "0001000";
            hex_1 <= "0000000";
        when 5 =>
            hex_0 <= "0000001";
            hex_1 <= "0000000";
            state <= AWAIT_INPUT;
        when others => -- 新增兜底分支
            hex_0 <= "1111111"; -- 熄灭数码管
            hex_1 <= "1111111";
    end case;
    

其他代码问题排查与修复

1. 按钮输入逻辑矛盾

  • 原代码中btn4和btn2对应同一段序列"010",逻辑冲突,需修正为各自独立的序列值:
    if btn1 = '1' then
        correct_input <= (sequence = "001");
    elsif btn2 = '1' then
        correct_input <= (sequence = "010");
    elsif btn3 = '1' then
        correct_input <= (sequence = "100");
    elsif btn4 = '1' then
        correct_input <= (sequence = "101"); -- 给btn4分配唯一序列值,可根据需求调整
    else
        correct_input <= correct_input; -- 无输入时保持原有状态,而非直接判定为错误
    end if;
    

2. 序列更新逻辑不符合Simon游戏规则

原代码仅对序列进行移位,而Simon游戏需在正确输入后添加随机新位,可修改为:

-- 替换原移位代码,用计数器生成伪随机位(实际项目可使用专用随机数生成逻辑)
sequence <= sequence(1 downto 0) & std_logic_vector(to_unsigned(count mod 2, 1));

3. 复位时未初始化数码管输出

复位时未设置hex_0、hex_1、hex_2的初始值,可能导致未知状态,需补充:

if rst = '1' then
    sequence <= "001";
    count <= 0;
    display_counter <= 0;
    state <= DISPLAY_SEQUENCE;
    hex_0 <= "1111111"; -- 复位熄灭所有数码管
    hex_1 <= "1111111";
    hex_2 <= "1111111";

4. 未使用hex_2输出

实体定义了hex_2但代码未赋值,可添加回合数显示逻辑(示例):

-- 在DISPLAY_SEQUENCE状态中添加hex_2赋值,显示当前回合数
case count is
    when 0 => hex_2 <= "0000001"; -- 显示0
    when 1 => hex_2 <= "1001111"; -- 显示1
    when 2 => hex_2 <= "0010010"; -- 显示2
    -- 可根据需求扩展更多数值的七段码
    when others => hex_2 <= "1111111";
end case;

5. 缺少按钮消抖逻辑

直接使用按钮原始输入会因机械抖动导致误判,需添加消抖电路(示例):

-- 声明消抖信号
signal btn1_debounce : std_logic_vector(19 downto 0);
signal btn1_stable : std_logic;

-- 消抖进程
process(clk)
begin
    if rising_edge(clk) then
        btn1_debounce <= btn1_debounce(18 downto 0) & btn1;
        if btn1_debounce = X"FFFFF" then
            btn1_stable <= '1';
        elsif btn1_debounce = X"00000" then
            btn1_stable <= '0';
        end if;
    end if;
end process;

-- 后续逻辑使用btn1_stable代替btn1,其余按钮同理

内容的提问来源于stack exchange,提问作者TheYungBuck xX

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 09:40:57