【国产FPGA高云GW1N-4系列开发板测评】——6、数码管显示时钟(时、分、秒)
[复制链接]
本帖最后由 gs001588 于 2021-12-25 22:47 编辑
【国产FPGA高云GW1N-4系列开发板测评】——6、数码管显示时钟(时、分、秒)
从开发板原理图可看出,4位7段数码管为共阳极类型。位选信号LED_DIS_SEL为低电平‘0’时,驱动三极管导通,数码管供电;数码管段码由低电平驱动,为低电平的段被点亮。
原理图中对应FPGA管脚分配如下图所示
在用户手册中也有管脚分配相关信息。
用LED数码管数据生成器生成0到9的共阳显示码。
实现代码如下:
- --*******************************************************************************
- --*-------------------------- 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: IN STD_LOGIC; --50MHz系统时钟
-
- -------------------------------------------------------------------------------
- --系统全局复位 RESET
- -------------------------------------------------------------------------------
- NRESET: IN STD_LOGIC;
-
- -------------------------------------------------------------------------------
- --SEGx4
- -------------------------------------------------------------------------------
- DIS: OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
- SEL: OUT STD_LOGIC_VECTOR(4 DOWNTO 1);
-
- -------------------------------------------------------------------------------
- --SWx4
- -------------------------------------------------------------------------------
- SW: IN STD_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 <= 0;
- ELSIF (RISING_EDGE(CLK_50M)) THEN
- IF (COUNTER < 50000000-1) THEN
- COUNTER <= COUNTER + 1;
- ELSE
- COUNTER <= 0;
- END IF;
- END IF;
- END PROCESS;
-
- PROCESS(NRESET,CLK_50M)
- BEGIN
- IF (NRESET = '0') THEN
- COUNTER1 <= 0;
- ELSIF (RISING_EDGE(CLK_50M)) THEN
- IF (COUNTER1 < 62500-1) THEN
- COUNTER1 <= COUNTER1 + 1;
- ELSE
- COUNTER1 <= 0;
- END IF;
- END IF;
- END PROCESS;
-
- PROCESS(NRESET,CLK_50M)
- BEGIN
- IF (NRESET = '0') THEN
- SCAN_CLK <= '0';
- ELSIF (RISING_EDGE(CLK_50M)) THEN
- IF (COUNTER1 = 62500-1) THEN
- SCAN_CLK <= NOT SCAN_CLK;
- END IF;
- END IF;
- END PROCESS;
-
- PROCESS(NRESET,SCAN_CLK)
- BEGIN
- IF (NRESET = '0') THEN
- CNT <= 1;
- ELSIF (RISING_EDGE(SCAN_CLK)) THEN
- IF (CNT = 4) THEN
- CNT <= 1;
- ELSE
- CNT <= CNT + 1;
- END IF;
- END IF;
- END PROCESS;
-
- SEL_Reg <= (1=>'0',others=>'1') WHEN CNT = 1 ELSE
- (2=>'0',others=>'1') WHEN CNT = 2 ELSE
- (3=>'0',others=>'1') WHEN CNT = 3 ELSE
- (4=>'0',others=>'1') WHEN CNT = 4 ELSE
- (others=>'1');
-
- SEL <= SEL_Reg;
-
- DIS <= DIS_Reg(CNT);
- DIS_Reg(4) <= SMG(MIN / 10) WHEN SW(1)='0' ELSE
- BLANK WHEN SW(1)='1' AND (HR/10)=0 ELSE
- SMG(HR / 10);
- DIS_Reg(3) <= (NOT TICK_CLK) & SMG(MIN REM 10)(6 downto 0) WHEN SW(1)='0' ELSE
- '0' & SMG(HR REM 10)(6 downto 0);
- DIS_Reg(2) <= SMG(SEC / 10) WHEN SW(1)='0' ELSE
- SMG(MIN / 10);
- DIS_Reg(1) <= SMG(SEC REM 10) WHEN SW(1)='0' ELSE
- SMG(MIN REM 10);
-
- PROCESS(NRESET,CLK_50M)
- BEGIN
- IF (NRESET = '0') THEN
- TICK_CLK <= '0';
- ELSIF (RISING_EDGE(CLK_50M)) THEN
- IF (COUNTER = 25000000-1) OR (COUNTER = 50000000-1)THEN
- TICK_CLK <= NOT TICK_CLK;
- END IF;
- END IF;
- END PROCESS;
-
- PROCESS(NRESET,TICK_CLK)
- BEGIN
- IF (NRESET = '0') THEN
- HR <= 23;
- MIN <= 59;
- SEC <= 00;
- ELSIF (RISING_EDGE(TICK_CLK)) THEN
- IF (SEC = 59) THEN
- SEC <= 0;
- IF (MIN = 59) THEN
- MIN <= 0;
- IF (HR = 23) THEN
- HR <= 0;
- ELSE
- HR <= HR + 1;
- END IF;
- ELSE
- MIN <= MIN + 1;
- END IF;
- ELSE
- SEC <= SEC + 1;
- END IF;
- END IF;
- END PROCESS;
-
- END MY_CODE;
-
VHDL比Verilog用起来稍麻烦一些,VHDL比较严谨,数据类型不同会报错,需要转换后才可赋值;语法要求也比较严格。
10到13行为公共库声明,没有库简单的代码编译都做不到。15到41行实体定义,定义输入输出接口。
45到76行,定义变量和常量,在使用前必须定义,定义必须在整个代码实现BEGIN(80行)之前。
82到93行,分频产生1Hz节拍时钟;
95到106行,分频产生800Hz数码管扫描基准时钟。50,000,000 / 62,500 = 800;
108到117,800Hz翻转时钟,实际对应数码管扫描时钟400Hz。
119到130行,数码管扫描计数器,1到4循环;
132到138行,CNT从1到4循环,分别对应数码管位1到4。
通过一位拨码开关SW(1)来选择功能。当SW(1)为'0'时,功能为4位数据码显示分、秒,并伴随有“点段”闪烁;当当SW(1)为'1'时,功能为显示时、分,点段常亮,当时位小于10时,只显示一位,大于等于10时显示2位。SEL的位选、DIS的显示段值正好都与CNT相关,每个位显示寄存器DIS_REG()实时赋值,DIS_Reg(CNT)查表显示。
151到160行,产生1Hz节后时钟。
162到185行,产生24小时时钟的时、分、秒,方法也比较简单易懂。在秒时钟的节拍下秒、分都是59进位,时为23归零。
时间初值设置为23点59分00秒,是为了区分从23点跳到0点后,只显示一位小时。
视频上传不成功。
视频截取了gif图片,显示比较快,实际为秒闪。拨码开关打到下方时,显示分、秒,分个位的点闪烁;拨到上方时,显示时、分,时的个位点常亮。
|