一般来说,我贴上来的代码都是能直接跑的,如果不行可以邮箱交流[email protected]
仅供参考,微机的老师讲的很好,所以请还是要先自己完成咯。
免责声明,本人菜只因一只,内容仅供参考,错了不负责哈
该实验和报告部分参考了ZhouzhouFighting的报告(链接华南理工大学VHDL实验数码管与分频器_vhdl数码管扫描频率-讲义代码类资源-CSDN下载),但是因为我们EDA实验室换成了正点原子新起点V2开发板,因此在数码管输出和前面的输入等部分做了一定的修改与调整。
地 点: |
31 楼 |
312房; |
实验台号: |
|
实验日期与时间: |
评 分: |
|||
预习检查纪录: |
批改教师: |
报告内容:
一,实验要求:
(1)利用硬件描述语言设计分频器模块和七段显示码模块;
(2)学习数码管驱动芯片74HC595的时序,请同学根据时序写出VHDL代码;
(3)设计数据产生模块,每秒输出数字加1;
二、实验内容:
预期顶层逻辑图
(因为更换了开发板,因此最后输出应该改为输出seg_duan 和seg_wei)
三、实验设计原理
本次实验一共分为三个模块,分别为divider,data_gen, seg。Divider负责把开版本的时钟频率变为我们计时需要用的1HZ频率;data_gen负责计数;seg负责与数码管显示连接的接口,输出位码与段码。
接下来一一分析实现的逻辑与代码:
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。当复位信号为低电平时,设计的模块中的输出和计时信号全部复位。设置复位信号是为了异步复位,达到重新计数的目的。
将上述代码设为顶层实体,并且create symbol files for current file来创立元件,在新建的bpf文件中可直接使用。下图为三个实例化元件:
图1 分频器
图2 计数器data_gen
图3 seg数码管接口模块
并且最后按照对应线路将其连接完整,如图4所示:
图4 完整接线图
我们将bpf文件设为顶层文件并且编译,编译成功后,按照图5分配引脚后再次编译,并将文件烧录至正点原子新起点V2开发板。
图5 实验2 引脚分配图(这个老师会给的)
四、实验结果和分析
图6 计数初始化
图7 计数实物图
由图6我们可以看到按下reset键数码管开始从0计时,由图7可以看到数码管能够正常计数,残留未能完全消影但是不影响使用。