❀工信工实验参考——《VHDL实验2——数码管及分频器》

一般来说,我贴上来的代码都是能直接跑的,如果不行可以邮箱交流1902946954@qq.com

仅供参考,微机的老师讲的很好,所以请还是要先自己完成咯。
免责声明,本人菜只因一只,内容仅供参考,错了不负责哈

该实验和报告部分参考了ZhouzhouFighting的报告(链接华南理工大学VHDL实验数码管与分频器_vhdl数码管扫描频率-讲义代码类资源-CSDN下载),但是因为我们EDA实验室换成了正点原子新起点V2开发板,因此在数码管输出和前面的输入等部分做了一定的修改与调整。 

实验二  数据管及分频器

地          点:

      31    楼

   312房;

实验台号:

实验日期与时间:

评    分:

预习检查纪录:

批改教师:

报告内容:

一,实验要求:

(1)利用硬件描述语言设计分频器模块和七段显示码模块;

(2)学习数码管驱动芯片74HC595的时序,请同学根据时序写出VHDL代码;

(3)设计数据产生模块,每秒输出数字加1;

  1. 设计顶层文件,驱动数码管模块,使(3)产生数据显示在数码管上。

二、实验内容:

预期顶层逻辑图

 

(因为更换了开发板,因此最后输出应该改为输出seg_duan 和seg_wei)

三、实验设计原理

本次实验一共分为三个模块,分别为divider,data_gen, seg。Divider负责把开版本的时钟频率变为我们计时需要用的1HZ频率;data_gen负责计数;seg负责与数码管显示连接的接口,输出位码与段码。

接下来一一分析实现的逻辑与代码:

  1. Divider模块
Library IEEE;
Use IEEE.std_logic_1164.ALL;
ENTITY class2_driver IS
PORT(clk,rst:IN std_logic;
     q:OUT std_logic);
END ENTITY;
ARCHITECTURE behav of class2_driver IS
SIGNAL time:integer :=1;
BEGIN
PROCESS(clk,rst)
BEGIN
IF rst='0' THEN time<=1;
ELSIF rising_edge(clk) THEN
     time<=time+1;
IF time=50000000 THEN
q<='1';
time<=1;
ELSE q<='0';
END IF;
END IF;
END PROCESS;
END behav;

开发板的时钟频率为50MHZ,查阅文献可知,人眼能够分辨的最高频率为24HZ。开发板的时钟频率远远超出人眼分辨范围,因此需要对时钟信号进行分频处理,以便后续计时模块产生的输出到数码管上可被人眼分辨。题目要求分频器模块时钟周期为1HZ,在代码实体中设置一个范围为1-50M的信号count,当count≥25M时分频器输出为‘1’,反之输出为’0’,当count=50M时,count=1。以此编程得到的输出时钟信号频率为1HZ,每1s产生一个上升沿。

        2.data_gen模块

Library IEEE;
Use IEEE.std_logic_1164.ALL;
use ieee.std_logic_signed.all;
ENTITY class2_counter IS
PORT(rst,en,clk,clk_1HZ: IN std_logic;
     data:OUT std_logic_vector(15 DOWNTO 0)
);
END entity;
ARCHITECTURE behav of class2_counter IS
SIGNAL temp:std_logic_vector(15 DOWNTO 0):=(others=>'0');
SIGNAL TEST:std_logic:='0';
BEGIN
PROCESS(clk,rst)
BEGIN
IF en='0' THEN TEST<='1';END IF;
IF TEST='0' THEN temp<=(others=>'0');
elsif rst='0' THEN  TEST<='0';temp<=(others=>'0');
ELSIF rising_edge(clk) THEN
IF clk_1HZ='1' THEN temp<=(temp+1);
END IF;
END IF;
data<=temp;
END PROCESS;
END behav;

题目要求数据产生模块,每秒输出数字加1,且数码管可显示16进制数,故data-gen模块的输出为一个16位二进制信号。该模块以divider模块输出的1HZ信号为时钟,模块内部有一信号q,当时钟上升沿到来时q=q+1。当q为’FFFF’时,q复位。最后将q值赋给data_gen模块的输出data。

3.seg模块(这是老师提供的verilog写的,我改的VHDL找不到了,凑合凑合吧能用)

module Verilog1(
			clk,rst_n,
			idis_data,
			seg_duan,seg_wei
		);

input clk;	
input rst_n;
input [15:0] idis_data ;

output     reg[7:0] seg_duan;
output 	reg[5:0] seg_wei;

parameter 	SEG_NUM0 	= 8'hc0,
			SEG_NUM1 	= 8'hf9,
			SEG_NUM2 	= 8'ha4,
			SEG_NUM3 	= 8'hb0,
			SEG_NUM4 	= 8'h99,
			SEG_NUM5 	= 8'h92,
			SEG_NUM6 	= 8'h82,
			SEG_NUM7 	= 8'hF8,
			SEG_NUM8 	= 8'h80,
			SEG_NUM9 	= 8'h90,
			SEG_NUMA 	= 8'h88,
			SEG_NUMB 	= 8'h83,
			SEG_NUMC 	= 8'hc6,
			SEG_NUMD 	= 8'ha1,
			SEG_NUME 	= 8'h86,
			SEG_NUMF 	= 8'h8e;

parameter	SEG_WE0		= 6'b11_1110,
			SEG_WE1		= 6'b11_1101,
			SEG_WE2		= 6'b11_1011,
			SEG_WE3		= 6'b11_0111,
SEG_WE4		= 6'b10_1111,
	SEG_WE5		= 6'b01_1111;

reg[3:0] seg_num;
reg[7:0] cnt_4;	
always @(posedge clk or negedge rst_n)
	if(!rst_n) cnt_4 <= 8'd0;
	else cnt_4 <= cnt_4+1'b1;
always @(posedge clk or negedge rst_n)
	if(!rst_n) seg_num <= 8'h00;
	else 
		case(cnt_4[7:6])
				2'b00: seg_num <= idis_data[3:0];
				2'b01: seg_num <= idis_data[7:4];
				2'b10: seg_num <= idis_data[11:8];
				2'b11: seg_num <= idis_data[15:12];
			default:  ;
			endcase

always @(posedge clk or negedge rst_n)
	if(!rst_n)seg_duan <= 8'hff;

	else
		case(seg_num) 
			4'h0: seg_duan <= SEG_NUM0;
			4'h1: seg_duan <= SEG_NUM1;
			4'h2: seg_duan <= SEG_NUM2;
			4'h3: seg_duan <= SEG_NUM3;
			4'h4: seg_duan <= SEG_NUM4;
			4'h5: seg_duan <= SEG_NUM5;
			4'h6: seg_duan <= SEG_NUM6;
			4'h7: seg_duan <= SEG_NUM7;
			4'h8: seg_duan <= SEG_NUM8;
			4'h9: seg_duan <= SEG_NUM9;
			4'ha: seg_duan <= SEG_NUMA;
			4'hb: seg_duan <= SEG_NUMB;
			4'hc: seg_duan <= SEG_NUMC;
			4'hd: seg_duan <= SEG_NUMD;
			4'he: seg_duan <= SEG_NUME;
			4'hf: seg_duan <= SEG_NUMF;
		default:	 ;
		endcase
		
always @(cnt_4[7:6])
	case(cnt_4[7:6])
			2'b00: seg_wei <= SEG_WE0;
			2'b01: seg_wei <= SEG_WE1;
			2'b10: seg_wei <= SEG_WE2;
			2'b11: seg_wei <= SEG_WE3;
		default:  seg_wei <= 6'b0000_00;
		endcase
endmodule

首先对于数码管显示,由于人的视觉暂留现象及发光二极管的余辉效应,尽管实际上各位数码管并非同时点亮,但只要扫描的速度足够快,给人的印象就是一组稳定的显示数据,不会有闪烁感,动态显示的效果和静态显示是一样的。

因此我们应该用不断扫描的方法来点亮数码管。

输出的段码和位码分别控制数码管在第几位显示和显示什么数字。在每次时钟上升沿时会重新读入扫描来重新显示。具体实现方法为:

Data_gen会将数字的二进制传入seg,seg会将其按每四位拆分开,将最低4位的位码设为0,即在最低位的数码管显示,具体显示的数字遍历七段码列表匹配后,按七段码输出段码。其他位以此类推。

此外,设置复位信号rst_n。当复位信号为低电平时,设计的模块中的输出和计时信号全部复位。设置复位信号是为了异步复位,达到重新计数的目的。

  1. 实例化

将上述代码设为顶层实体,并且create symbol files for current file来创立元件,在新建的bpf文件中可直接使用。下图为三个实例化元件:

图1 分频器

图2 计数器data_gen

图3 seg数码管接口模块

并且最后按照对应线路将其连接完整,如图4所示:

图4 完整接线图

  1. 烧录至开发板

我们将bpf文件设为顶层文件并且编译,编译成功后,按照图5分配引脚后再次编译,并将文件烧录至正点原子新起点V2开发板。

图5 实验2 引脚分配图(这个老师会给的)

四、实验结果和分析

图6 计数初始化

图7 计数实物图

由图6我们可以看到按下reset键数码管开始从0计时,由图7可以看到数码管能够正常计数,残留未能完全消影但是不影响使用。

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
社会演员多的头像社会演员多普通用户
上一篇 2023年12月7日
下一篇 2023年12月7日

相关推荐