FPGA数字秒表设计

发布于 2021-11-30  1,645 次阅读


内容纲要

↓本次设计的仿真源文件见下方↓

题目:用VHDL写一个数字秒表
要求:数码管显示最大为999.9,之后归零重新计数
分析:题目要求能显示十分秒,所以十分秒位应该是每100ms(产生10Hz的时钟信号)加一,然后十分秒位满10往前进一位,依次类推,SO应该有如下结构

20211130193819.png

因此本题最重要的几个点就是:由输入时钟产生10Hz的时钟信号,数码管能够正确显示数据,并能正常进位计数

1.首先分频器部分,假如我们用的是100Hz的时钟,要产生10Hz的频率信号,只能进行10分频,然后通过分频后的时钟信号对十分秒位进行计数进位操作,相应的分频器代码如下:

--第一种写法
if clk'event and clk='1' then
    if ctr_10 < 9 then 
        ctr_10 <= ctr_10+1;
    else
        ctr_10<=0;
    end if;
    if ctr_10 < 5 then
    clk_div10 <= '0';
    else 
    clk_div10 <= '1';
end if;
--第二种写法
signal x:std_logic;--定义信号
if clk'event and clk='1' then
    if ctr_10 < 10 then
        ctr_10:=ctr_10+1;
    else
        ctr_10:=0;
        x <= not x;
    end if;
    clk_div10 <= x;
end if;

2.其次判断计数器的进位操作,相应代码如下:

process(RST,clk_div10) --计数器进程(100ms+1)
                begin
                    if RST='0' then
                        counter_sec <= x"0000";
                    elsif clk_div10'EVENT AND clk_div10='1' then
                        if START='1' then
                            if counter_sec(3 downto 0) < x"9" then --判断十分秒进位
                                counter_sec(3 downto 0) <= counter_sec(3 downto 0)+'1';
                            else
                                counter_sec(3 downto 0)<=x"0";
                                if counter_sec(7 downto 4) < x"9" then--判断秒进位
                                    counter_sec(7 downto 4) <= counter_sec(7 downto 4)+'1';
                                else 
                                    counter_sec(7 downto 4) <= x"0";
                                    if counter_sec(11 downto 8) < x"9" then--判断十秒进位
                                        counter_sec(11 downto 8) <= counter_sec(11 downto 8)+'1';
                                    else
                                        counter_sec(11 downto 8) <= x"0";
                                        if counter_sec(15 downto 12) < x"9" then--判断百秒位
                                            counter_sec(15 downto 12) <= counter_sec(15 downto 12)+'1';
                                        else
                                            counter_sec(15 downto 12) <= x"0";
                                        end if;
                                    end if;
                                end if;
                            end if;
                        end if;
                    end if;
            end process;

3.数码管显示模块

20211130195832.png

由于七段数码管公共端连接到GND(共阴极型), 当数码管的中的那一个段被输入高电平, 则相应的这一段被点亮。 反之则不亮。 四位一体的七段数码管在单个静态数码管的基础上加入了用于选择哪一位数码管的位选信号端口。 八个数码管的a、 b、 c、 d、 e、 f、 g、 h、 dp都连在了一起, 8个数码管分别由各自的位选信号来控制, 被选通的数码管显示数据, 其余关闭

20211130200120.png

数码管模块采用的是38译码器,好处是可以减少IO口的占用,只需要用三个输入就可以控制八个输出,我们利用这个来进行数码管的位选操作,位选就是选择第几位数码管,而段选就是控制一个数码管上的灯条的亮灭

根据题目要求第三个数码管要一直显示小数点,所以要把第三位数码管的dp位(最高位)置1,其余数码管的dp位置0,这样就实现了只让第三个数码管小数点点亮,数码管模块部分代码如下:

--shumaguan.vhd

library ieee;
use ieee.std_logic_1164.all;

entity shumaguan is
    port(
        RST,CLK :in std_logic;
        DIN     :in std_logic_vector(15 downto 0);
        BIT_4   :buffer std_logic_vector(2 downto 0);
        SEG_8   :out std_logic_vector(7 downto 0)
        );
end entity;

architecture rtl of shumaguan is
    type Disp_State is(S_DIG4,S_DIG3,S_DIG2,S_DIG1);--定义显示状态机类型,有S4,S3,S2,S1四个状态
    signal currect_state,next_state: Disp_State;--定义当前状态和下个状态信号
    signal num:std_logic_vector(3 downto 0);

begin
switch_p:process(RST,currect_state)--切换段
            begin
                if RST='0' then
                    next_state<=S_DIG4;
                else
                    case currect_state is
                        when S_DIG4=>next_state<=S_DIG3;
                        when S_DIG3=>next_state<=S_DIG2;
                        when S_DIG2=>next_state<=S_DIG1;
                        when S_DIG1=>next_state<=S_DIG4;
                        when others=>next_state<=S_DIG4;
                    end case;
                end if;
        end process;

lock_p:process(RST,CLK)--锁存段,将下个状态锁存到当前状态的信号
            begin
                if RST='0' then 
                    currect_state<=S_DIG4;
                elsif CLK'EVENT AND CLK='1' then 
                    currect_state<=next_state;
                end if;
        end process;

handle_p:process(RST,CLK)
        begin
            if RST='0' then
                BIT_4<="000";
                num <="0000";
            elsif CLK'EVENT AND CLK='1' then
                case currect_state is
                    when S_DIG4=>
                        BIT_4 <= "000";
                        num  <= DIN(15 downto 12);
                    when S_DIG3=>
                        BIT_4 <= "001";
                        num  <= DIN(11 downto 8);
                    when S_DIG2=>
                        BIT_4 <= "010";
                        num  <= DIN(7 downto 4);
                    when S_DIG1=>
                        BIT_4 <= "011";
                        num  <= DIN(3 downto 0);
                    when others =>
                        BIT_4 <= "000";
                        num  <= "0000";
                end case;
            end if;
        end process;

decode_p:process(num,BIT_4)--译码进程:共阴数码管
            begin
                if BIT_4 = "010" then
                case num is
                    when X"0" => SEG_8 <= X"BF";--10111111
                    when X"1" => SEG_8 <= X"86";--10000110
                    when X"2" => SEG_8 <= X"DB";--11011011
                    when X"3" => SEG_8 <= X"CF";--11001111
                    when X"4" => SEG_8 <= X"E6";--11100110
                    when X"5" => SEG_8 <= X"ED";--11101101
                    when X"6" => SEG_8 <= X"FD";--11111101
                    when X"7" => SEG_8 <= X"87";--10000111
                    when X"8" => SEG_8 <= X"FF";--11111111
                    when X"9" => SEG_8 <= X"EF";--11101111
                    when others=>SEG_8 <= X"BF";
                end case;

                else
                case num is
                    when X"0" => SEG_8 <= X"3F";
                    when X"1" => SEG_8 <= X"06";
                    when X"2" => SEG_8 <= X"5B";
                    when X"3" => SEG_8 <= X"4F";
                    when X"4" => SEG_8 <= X"66";
                    when X"5" => SEG_8 <= X"6D";
                    when X"6" => SEG_8 <= X"7D";
                    when X"7" => SEG_8 <= X"07";
                    when X"8" => SEG_8 <= X"7F";
                    when X"9" => SEG_8 <= X"6F";
                    when others=>SEG_8 <= X"3F";
                end case;
                end if;
        end process;
end architecture;

同理,课程设计当中用到数码管的地方也进行类似操作,比如打地鼠游戏中显示STAR-,只需要把每一个数码管点亮的灯条变动,然后加到case判断中去就好啦
真的已经傻瓜式教学了,再不会找个班上吧 bili_smilies

总结:多动手,多动脑,少白嫖,你不会一直白嫖,实践>理论
end...

相关文件下载地址
©下载资源版权归作者所有;本站所有资源均来源于网络,仅供学习使用,请支持正版!
  • alipay_img
  • wechat_img
届ける言葉を今は育ててる
最后更新于 2022-12-13