抢答器设计

设计一个四组人参加的竞赛抢答器系统,要求如下:

  1. 当某组参赛者首先在规定时间内(5s)按下抢答开关时,相应显示灯亮,此时抢答系统不再接收其他输入信号

  2. 回答问题有时间显示,30秒

  3. 当主持人下达命令前,若有参赛者按下抢答开关,视为犯规

程序如下:(注,六个数码管从左到右依次显示的是时间<两位>,抢答有效选手号<一位>,违规选手号<一位>)

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
package packagexp is
    function transform(a : std_logic_vector)
        return std_logic_vector;
end;
package body packagexp is
    function transform(a : std_logic_vector)
       return std_logic_vector is
       
       variable temp : std_logic_vector(3 downto 0);
      begin
          case a is
                      when "0001" => temp :="0001" ;  --1
     when "0010" => temp :="0010" ;  --2
     when "0100" => temp :="0011" ;  --3
     when "1000" => temp :="0100" ;  --4
     when others => null;
          end case;
          return temp;
    end function transform;
end;


library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use work.packagexp.all;


entity myanswer is 
port( a,b,c,d,rst,op,clk,clk1:in std_logic;         --a,b,c,d代表选手,一个时钟用来计时,一个时钟用来刷新数码管
 scan:out std_logic_vector(5 downto 0);        --数码管动态扫描
 dout:out std_logic_vector( 7 downto 0)        --数码管段码
 );
end myanswer;


architecture behv of myanswer is


    signal temp : std_logic_vector(2 downto 0);
signal time1: std_logic_vector(3 downto 0);     --十位秒数计时
signal time2: std_logic_vector(3 downto 0);     --个位秒数计时
signal right: std_logic_vector(3 downto 0);     --正确选手号码寄存器
signal wrong: std_logic_vector(3 downto 0);     --错误选手号码寄存器
signal din  : std_logic_vector(3 downto 0);
signal dataout:std_logic_vector(3 downto 0);



signal answerflag : std_logic;                  --进入30秒回答问题计时标志
signal errorflag  : std_logic;                  --违规标志
signal timeoutflag: std_logic;                  --抢答超时信号标志
signal firstflag  : std_logic;                  --刚刚抢答成功标志
signal long       : std_logic;

  begin
    din <= a&b&c&d;
process(clk1)
   begin
   if clk1'event and clk1 = '1' then
   if temp = "101" then
   temp <= "000";
else
   temp <= temp + 1;
end if;
end if;
end process;

process(temp)     --动态扫描
  begin
       case temp is
      when "000" => dataout <= wrong; scan <= "000001";
  when "001" => dataout <= "0000"; scan <= "000010";
  when "010" => dataout <= right; scan <= "000100";
  when "011" => dataout <= "0000"; scan <= "001000";
  when "100" => dataout <= time2; scan <= "010000";
  when "101" => dataout <= time1; scan <= "100000";
  when others => null;
  end case;
end process;

process(rst,op,din)       --抢答逻辑判断
   begin
     if rst = '1' then           --初始化时
         errorflag <= '0';
         answerflag<= '0';
         firstflag <= '0';
         right <= "0000"; wrong <= "0000";
     elsif op = '0' then        --违规抢答
         if din /= "0000" and wrong = "0000" then
             errorflag <= '1';
             wrong <= transform(din);
         end if;
     elsif timeoutflag = '0' and right = "0000" then    --还未超时且无人抢答(可以抢答)
         if din /= "0000" then  --有人抢答
             answerflag <= '1';
             firstflag <= '1';
             right <= transform(din);
         end if;
     else
         null;
     end if;
end process;

process(op,clk,rst,firstflag) --计时逻辑
   begin            
   if rst = '0' then         
       if op = '1' then                      --下了抢答命令
         if clk'event and clk = '1' and errorflag = '0' then    --没有人违规的情况下继续倒计时
             if answerflag = '0' then      --五秒倒计时阶段
                 if time2 > "0000" then
                     time2 <= time2 - 1;
                 else
                    timeoutflag <= '1';
                 end if;
             elsif firstflag = '1' and time1 = "0000" and long = '1'  then       --三十秒倒计时阶段,如果刚进入         
                 time1 <= "0011"; time2 <= "0000";
             else                                                --正常30秒计时阶段
                 if time2 = "0000" then
                     if time1 > "0000" then
                         time1 <= time1 - 1; time2 <= "1001";
                     else
                         null;
                     end if;
                 else
                     time2 <= time2 - 1;
                 end if;
             end if;
             if time1 /= "0000" then             --改变long标志位
                 long <= '0';
             end if;
         end if;
     end if;
 else
   time1 <= "0000"; time2 <= "0101";  
   timeoutflag<= '0';  
   long <= '1';
 end if;
end process;
   
process(dataout)
      begin
      case dataout is 
when "0000" => dout <="00111111" ;  --0
when "0001" => dout <="00000110" ;  --1
when "0010" => dout <="01011011" ;  --2
when "0011" => dout <="01001111" ;  --3
   when "0100" => dout <="01100110" ;  --4
when "0101" => dout <="01101101" ;  --5
when "0110" => dout <="01111101" ;  --6
when "0111" => dout <="00000111" ;  --7
when "1000" => dout <="01111111" ;  --8
when "1001" => dout <="01101111" ;  --9
when "1010" => dout <="01110111" ;  --a
when "1011" => dout <="01111100" ;  --b
when "1100" => dout <="00111001" ;  --c
when "1101" => dout <="01011110" ;  --d
when "1110" => dout <="01111001" ;  --e
when "1111" => dout <="01110001" ;  --f
when others => dout<="00000000";
 end case;
    end process;


end behv;

你可能感兴趣的:(VHDL)