gs001588 发表于 2021-12-25 22:40

【国产FPGA高云GW1N-4系列开发板测评】——6、数码管显示时钟(时、分、秒)

本帖最后由 gs001588 于 2021-12-25 22:47 编辑

<p><span style="font-size:16px;"><span style="font-family:宋体;">&nbsp; &nbsp;【国产FPGA高云GW1N-4系列开发板测评】&mdash;&mdash;6、数码管显示时钟(时、分、秒)</span></span></p>

<p>&nbsp;</p>

<p><span style="font-size:16px;"><span style="font-family:宋体;">&nbsp; &nbsp;从开发板原理图可看出,4位7段数码管为共阳极类型。位选信号LED_DIS_SEL为低电平&lsquo;0&rsquo;时,驱动三极管导通,数码管供电;数码管段码由低电平驱动,为低电平的段被点亮。</span></span></p>

<p><span style="font-size:16px;"><span style="font-family:宋体;"></span></span></p>

<p>&nbsp;</p>

<p><span style="font-size:16px;"><span style="font-family:宋体;">&nbsp; &nbsp;原理图中对应FPGA管脚分配如下图所示</span></span></p>

<p><span style="font-size:16px;"><span style="font-family:宋体;"></span></span></p>

<p>&nbsp;</p>

<p><span style="font-size:16px;"><span style="font-family:宋体;">&nbsp; &nbsp;在用户手册中也有管脚分配相关信息。</span></span></p>

<p><span style="font-size:16px;"><span style="font-family:宋体;"></span></span></p>

<p>&nbsp;</p>

<p><span style="font-size:16px;"><span style="font-family:宋体;">&nbsp; &nbsp;用LED数码管数据生成器生成0到9的共阳显示码。</span></span></p>

<p><span style="font-size:16px;"><span style="font-family:宋体;"></span></span></p>

<p>&nbsp;</p>

<p><span style="font-size:16px;"><span style="font-family:宋体;">&nbsp; &nbsp;实现代码如下:</span></span></p>

<pre>
<code>--*******************************************************************************
--*-------------------------- file ---------------                                    
--* name:segx4.vhd       
--* ver : A
--* date:2021-12-9
--*------------------------------------------------
--*******************************************************************************

---------- LIB----------------------------------------------------------------
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;

----------ENTITY -------------------------------------------------------------
ENTITY segx4 IS
PORT (                                                                                                        
-------------------------------------------------------------------------------
--系统全局时钟 CLK
-------------------------------------------------------------------------------         
    CLK_50M:    INSTD_LOGIC;        --50MHz系统时钟
                     
-------------------------------------------------------------------------------
--系统全局复位 RESET
-------------------------------------------------------------------------------
    NRESET:   INSTD_LOGIC;                               

-------------------------------------------------------------------------------
--SEGx4
-------------------------------------------------------------------------------
    DIS:      OUTSTD_LOGIC_VECTOR(7 DOWNTO 0);
    SEL:      OUTSTD_LOGIC_VECTOR(4 DOWNTO 1);

-------------------------------------------------------------------------------
--SWx4
-------------------------------------------------------------------------------
    SW:         INSTD_LOGIC_VECTOR(4 DOWNTO 1)
-------------------------------------------------------------------------------

);
END segx4;

-----------ARCHITECTURE-------------------------------------------------------

ARCHITECTURE MY_CODE OF segx4 IS
       
-----------------------------------------------------------------------
    SIGNAL       COUNTER:       integer range 0 to 50000000;
    SIGNAL       LED_Reg:       STD_LOGIC_VECTOR(3 downto 0);

    SIGNAL       COUNTER1:      integer range 0 to 62500;
    SIGNAL       CNT:         integer range 0 to 8;
    SIGNAL   SCAN_CLK:       STD_LOGIC;
    TYPE DIS_Reg_Index IS ARRAY(1 to 4) OF STD_LOGIC_VECTOR(7 downto 0);
    SIGNAL   DIS_Reg:   DIS_Reg_Index;
    SIGNAL       SEL_Reg:       STD_LOGIC_VECTOR(4 downto 1);

-----------------------------------------------------------------------
    TYPE SMG_INDEX IS ARRAY(0 to 9) OF STD_LOGIC_VECTOR(7 downto 0);
    CONSTANT SMG:       SMG_INDEX := (X"C0",-- 0
                                        X"F9",-- 1
                                        X"A4",-- 2
                                        X"B0",-- 3
                                        X"99",-- 4
                                        X"92",-- 5
                                        X"82",-- 6
                                        X"F8",-- 7
                                        X"80",-- 8
                                        X"90"   -- 9
                                     );
    CONSTANT BLANK:   STD_LOGIC_VECTOR(7 DOWNTO 0):=X"FF";

    SIGNAL   TICK_CLK:   STD_LOGIC;
    SIGNAL   HR:      integer range 0 to 23;
    SIGNAL   MIN:       integer range 0 to 59;
    SIGNAL   SEC:       integer range 0 to 59;   
--**********************************************************************************
--*****   
--**********************************************************************************
BEGIN

PROCESS(NRESET,CLK_50M)
BEGIN
        IF (NRESET = '0') THEN
      COUNTER &lt;= 0;
        ELSIF (RISING_EDGE(CLK_50M)) THEN
      IF (COUNTER &lt; 50000000-1) THEN
            COUNTER &lt;= COUNTER + 1;
      ELSE
            COUNTER &lt;= 0;
      END IF;
        END IF;               
END PROCESS;

PROCESS(NRESET,CLK_50M)
BEGIN
        IF (NRESET = '0') THEN
      COUNTER1 &lt;= 0;
        ELSIF (RISING_EDGE(CLK_50M)) THEN
      IF (COUNTER1 &lt; 62500-1) THEN
            COUNTER1 &lt;= COUNTER1 + 1;
      ELSE
            COUNTER1 &lt;= 0;
      END IF;
        END IF;               
END PROCESS;

PROCESS(NRESET,CLK_50M)
BEGIN
        IF (NRESET = '0') THEN
      SCAN_CLK &lt;= '0';
        ELSIF (RISING_EDGE(CLK_50M)) THEN
      IF (COUNTER1 = 62500-1) THEN
            SCAN_CLK &lt;= NOT SCAN_CLK;
      END IF;
        END IF;
END PROCESS;

PROCESS(NRESET,SCAN_CLK)
BEGIN
        IF (NRESET = '0') THEN
      CNT &lt;= 1;
        ELSIF (RISING_EDGE(SCAN_CLK)) THEN
      IF (CNT = 4) THEN
            CNT &lt;= 1;
      ELSE
            CNT &lt;= CNT + 1;
      END IF;
        END IF;               
END PROCESS;

    SEL_Reg &lt;=(1=&gt;'0',others=&gt;'1') WHEN CNT = 1 ELSE
                (2=&gt;'0',others=&gt;'1') WHEN CNT = 2 ELSE
                (3=&gt;'0',others=&gt;'1') WHEN CNT = 3 ELSE
                (4=&gt;'0',others=&gt;'1') WHEN CNT = 4 ELSE
                (others=&gt;'1');

    SEL &lt;= SEL_Reg;

    DIS         &lt;=DIS_Reg(CNT);
    DIS_Reg(4)&lt;=SMG(MIN / 10)   WHEN SW(1)='0' ELSE
                  BLANK         WHEN SW(1)='1' AND (HR/10)=0 ELSE
                  SMG(HR / 10);
    DIS_Reg(3)&lt;=(NOT TICK_CLK) &amp; SMG(MIN REM 10)(6 downto 0) WHEN SW(1)='0'ELSE
                  '0' &amp; SMG(HR REM 10)(6 downto 0);
    DIS_Reg(2)&lt;=SMG(SEC / 10)   WHEN SW(1)='0'ELSE
                  SMG(MIN / 10);
    DIS_Reg(1)&lt;=SMG(SEC REM 10) WHEN SW(1)='0'ELSE
                  SMG(MIN REM 10);

PROCESS(NRESET,CLK_50M)
BEGIN
        IF (NRESET = '0') THEN
      TICK_CLK &lt;= '0';
        ELSIF (RISING_EDGE(CLK_50M)) THEN
      IF (COUNTER = 25000000-1) OR (COUNTER = 50000000-1)THEN
            TICK_CLK &lt;= NOT TICK_CLK;
      END IF;
        END IF;               
END PROCESS;

PROCESS(NRESET,TICK_CLK)
BEGIN
        IF (NRESET = '0') THEN
      HR&lt;= 23;
      MIN &lt;= 59;
      SEC &lt;= 00;
        ELSIF (RISING_EDGE(TICK_CLK)) THEN
      IF (SEC = 59) THEN
            SEC &lt;= 0;
            IF (MIN = 59) THEN
                MIN &lt;= 0;
                IF (HR = 23) THEN
                  HR &lt;= 0;
                ELSE
                  HR &lt;= HR + 1;
                END IF;
            ELSE
                MIN &lt;= MIN + 1;
            END IF;
      ELSE
            SEC &lt;= SEC + 1;
      END IF;
        END IF;       
END PROCESS;

END MY_CODE;
</code></pre>

<p><span style="font-size:16px;"><span style="font-family:宋体;">&nbsp; &nbsp;</span></span></p>

<p><span style="font-size:16px;"><span style="font-family:宋体;">&nbsp; &nbsp;VHDL比Verilog用起来稍麻烦一些,VHDL比较严谨,数据类型不同会报错,需要转换后才可赋值;语法要求也比较严格。</span></span></p>

<p><span style="font-size:16px;"><span style="font-family:宋体;">&nbsp; &nbsp;10到13行为公共库声明,没有库简单的代码编译都做不到。15到41行实体定义,定义输入输出接口。</span></span></p>

<p><span style="font-size:16px;"><span style="font-family:宋体;"></span></span></p>

<p>&nbsp;</p>

<p><span style="font-size:16px;"><span style="font-family:宋体;">&nbsp; &nbsp;45到76行,定义变量和常量,在使用前必须定义,定义必须在整个代码实现BEGIN(80行)之前。</span></span></p>

<p><span style="font-size:16px;"><span style="font-family:宋体;"></span></span></p>

<p>&nbsp;</p>

<p><span style="font-size:16px;"><span style="font-family:宋体;">&nbsp; &nbsp;82到93行,分频产生1Hz节拍时钟;</span></span></p>

<p><span style="font-size:16px;"><span style="font-family:宋体;">&nbsp; &nbsp;95到106行,分频产生800Hz数码管扫描基准时钟。50,000,000 / 62,500 = 800;</span></span></p>

<p><span style="font-size:16px;"><span style="font-family:宋体;">&nbsp; &nbsp;108到117,800Hz翻转时钟,实际对应数码管扫描时钟400Hz。</span></span></p>

<p><span style="font-size:16px;"><span style="font-family:宋体;"></span></span></p>

<p>&nbsp;</p>

<p><span style="font-size:16px;"><span style="font-family:宋体;">&nbsp; &nbsp;119到130行,数码管扫描计数器,1到4循环;</span></span></p>

<p><span style="font-size:16px;"><span style="font-family:宋体;">&nbsp; &nbsp;132到138行,CNT从1到4循环,分别对应数码管位1到4。</span></span></p>

<p><span style="font-size:16px;"><span style="font-family:宋体;"></span></span></p>

<p>&nbsp;</p>

<p><span style="font-size:16px;"><span style="font-family:宋体;">&nbsp; &nbsp;通过一位拨码开关SW(1)来选择功能。当SW(1)为&#39;0&#39;时,功能为4位数据码显示分、秒,并伴随有&ldquo;点段&rdquo;闪烁;当当SW(1)为&#39;1&#39;时,功能为显示时、分,点段常亮,当时位小于10时,只显示一位,大于等于10时显示2位。SEL的位选、DIS的显示段值正好都与CNT相关,每个位显示寄存器DIS_REG()实时赋值,DIS_Reg(CNT)查表显示。</span></span></p>

<p><span style="font-size:16px;"><span style="font-family:宋体;"></span></span></p>

<p>&nbsp;</p>

<p><span style="font-size:16px;"><span style="font-family:宋体;">&nbsp; &nbsp;151到160行,产生1Hz节后时钟。</span></span></p>

<p><span style="font-size:16px;"><span style="font-family:宋体;">&nbsp; &nbsp;162到185行,产生24小时时钟的时、分、秒,方法也比较简单易懂。在秒时钟的节拍下秒、分都是59进位,时为23归零。</span></span></p>

<p><font face="宋体"><span style="font-size:16px">&nbsp; &nbsp;时间初值设置为23点59分00秒,是为了区分从23点跳到0点后,只显示一位小时。</span></font></p>

<p><span style="font-size:16px;"><span style="font-family:宋体;"></span></span></p>

<p>&nbsp;</p>

<p><span style="font-size:16px;"><span style="font-family:宋体;">&nbsp; &nbsp;视频上传不成功。</span></span></p>

<p><font face="宋体"><span style="font-size: 16px;">&nbsp; &nbsp;视频截取了gif图片,显示比较快,实际为秒闪。拨码开关打到下方时,显示分、秒,分个位的点闪烁;拨到上方时,显示时、分,时的个位点常亮。</span></font></p>

<p></p>

<p>&nbsp;</p>

gs001588 发表于 2021-12-25 23:14

<p>工程文件:</p>

<p></p>

怀揣少年梦 发表于 2021-12-26 17:20

gs001588 发表于 2021-12-25 23:14
工程文件:

<p>大佬使用VHDL,厉害</p>

gs001588 发表于 2021-12-26 17:37

怀揣少年梦 发表于 2021-12-26 17:20
大佬使用VHDL,厉害

<p>不厉害,一般般,用VHDL只是个人习惯问题。Verilog可以加头文件,可以&#39;define,这点比VHDL人性化。有时也混用,模块化设计,不同语言写的模块可以相互调用。</p>

<p>语言只是个工具,FPGA的硬件思维是灵魂。</p>

怀揣少年梦 发表于 2021-12-26 22:20

gs001588 发表于 2021-12-26 17:37
不厉害,一般般,用VHDL只是个人习惯问题。Verilog可以加头文件,可以&#39;define,这点比VHDL人性化。有 ...

<p>我是刚入门的小白,就觉得Verilog,简单,好上手,懂C语言的,简直是无门槛入门。VHDL,做复杂系统稳定。</p>
页: [1]
查看完整版本: 【国产FPGA高云GW1N-4系列开发板测评】——6、数码管显示时钟(时、分、秒)