题目描述
在板子上的七段数码管上的八个数字分别显示:计时器(两位)、按照拨码开关的输入(两位)、班级(两位)、学号(两位)
其中计时器为2HZ的,从10到到0,当倒计时为0时,从10重新开始计数;当按下开关s0,立即变化为10并重新计数。
拨码开关共有八个,分为两组,前四个控制第一个显示,后四个控制第二个的显示,从0到F都有。
班级学号为常数,但是班级和学号的第二位要显示小数点。
分析 数码管的显示
数码管的显示部分应该是整体的最难环节了,首先我们先介绍一下一个数码管的显示原理。数码管之所以是七段数码管,是因为在构成中分为八个显示部分,(为什么叫七段,可能是显示数字只需要七个,最后一个小数点被忽略了)
我们只需要在对应的8位信号分别对应给出高低信号,就能控制数码管的显示了。
需要注意一下,我们在实验过程中采用的数码管是共阴极,也就是将阴极连接在一起,有的数码管是共阳极,也就是对应低电平有效,那么我们就需要将输入翻转。
0~F的显示方式:
对应的二进制和十六进制:
A B C D E F G DP(点)
0 8’b1111_1100;fc
1 8’b0110_0000;60
2 8’b1101_1010;da
3 8’b1111_0010;f2
4 8’b0110_0110;66
5 8’b1011_0110;b6
6 8’b1011_1110;be
7 8’b1110_0000;e0
8 8’b1111_1110;fe
9 8’b1111_0110;f6
A 8’b1110_1110;ee
B 8’b0011_1110;3e
C 8’b0001_1010;1a
D 8’b0111_1010;7a
E 8’b1001_1110;9e
F 8’b1000_1110;8e
那么多个数码管呢
虽然我们知道了单个的数码管控制方式,但是如何控制多个数码管呢?
每一个都给一个八位的使能信号?
好主意,但是太浪费了,所以人们有更好的方法。
因为是数码管显示,是需要人眼来观察的,我们都知道人眼有视觉暂留特性,因此思路就是将数码管分为两组,一组四个用一个四位使能端控制,那么一边只需要一个八位信号了。只要使能端交替的够快,就相当于每一个数码管都在显示。 人眼的分辨约在25HZ,为了保证功能的实现以及能耗的问题,我们选择1khz交替。
显示模块:
输入为8个八位二进制数(其实4位也可以,只需要在内部进行翻译),时钟信号,输出位左右端的数据和使能信号。
因为是1HZ,我们还是需要一个分频,分频在之前的博客有讲解,这里只贴出代码:
(10-8和10-3差了105,所以我们数到99999)
`timescale 1ns / 1psmodule all_divider( input clk_i, output reg clk_o ); reg [16:0] cnt=0; always@(posedge clk_i) begin if(cnt == 99999) cnt <= ‘b000; else cnt <= cnt + 1’b1; if(cnt <= 49999) clk_o <= 1’b1; else clk_o <= 1’b0; endendmodule
显示模块主部分:
`timescale 1ns / 1psmodule all_counter( input [7:0]out0, input [7:0]out1, input [7:0]out2, input [7:0]out3, input [7:0]out4, input [7:0]out5, input [7:0]out6, input [7:0]out7, input clk_i, output reg [7:0]left, output reg [7:0]right, output reg [3:0]dn0, output reg [3:0]dn1 ); wire clk_o;//分频后的时钟信号 reg [1:0]count=2’b00; //计数器,控制使能端(相当于一个24译码器) //分频模块的调用 all_divider div(clk_i,clk_o); always @(posedge clk_o) begin if(count == 3)//到3记得将计数器清零即可 begin count = 2’b00; left <= out3; right<= out7; dn0<=4’b0001; dn1<=4’b0001; end else begin case(count)//case语句正常判断使能端的内容 2’b00: begin left<=out0; right<=out4; dn0<=4’b1000; dn1<=4’b1000; end 2’b01: begin left<=out1; right<=out5; dn0<=4’b0100; dn1<=4’b0100; end 2’b10: begin left<=out2; right<=out6; dn0<=4’b0010; dn1<=4’b0010; end endcase count = count + 1’b1; end end endmodule
接下来就是每一个八位数的内容了,后两个只需要在顶层模进行常量赋值即可。
计时器
还是需要进行分频,并且我们需要有复位端。
输入:时钟信号和复位使能端
输出:两个八位二进制数(控制前两个的)
`timescale 1ns / 1psmodule counter( input clk_i, input s, output reg [7:0]out0, output reg [7:0]out1); wire clk; reg [3:0]middle=4’b1010;//计数器,从10开始 divider div(clk_i,clk); always @(posedge s or posedge clk) begin if(s)//复位使能端有效 begin middle = 10; out0 = 8’b0110_0000;//1 out1 = 8’b1111_1100;//0 end else if(middle==0)//到0了,重新开始计数 begin middle = 10; out0 = 8’b0110_0000; out1 = 8’b1111_1100; end else begin middle = middle – 1’b1; out0 = 8’b1111_1100;//高位为0 case(middle) 4’b0000:out1 = 8’b1111_1100;//按照计数器内容控制 4’b0001:out1 = 8’b0110_0000; 4’b0010:out1 = 8’b1101_1010; 4’b0011:out1 = 8’b1111_0010; 4’b0100:out1 = 8’b0110_0110; 4’b0101:out1 = 8’b1011_0110; 4’b0110:out1 = 8’b1011_1110; 4’b0111:out1 = 8’b1110_0000; 4’b1000:out1 = 8’b1111_1110; 4’b1001:out1 = 8’b1111_0110; 美国高防vps 4’b1010:out1 = 8’b1111_1100; endcase end end endmodule
(这里的代码有一点不怎么规范,应该都采用非阻塞赋值的,但是因为使能端需要立即改变,而如果是非阻塞则需要等到下一个always块,会相对慢一个周期)
控制四位拨码开关
这个比较简答,就是一个4-16译码器,直接上代码:
`timescale 1ns / 1psmodule four( input [3:0] in, output reg [7:0] out ); always@(*) begin case(in) 4’b0000:out=8’b1111_1100; 4’b0001:out=8’b0110_0000; 4’b0010:out=8’b1101_1010; 4’b0011:out=8’b1111_0010; 4’b0100:out=8’b0110_0110; 4’b0101:out=8’b1011_0110; 4’b0110:out=8’b1011_1110; 4’b0111:out=8’b1110_0000; 4’b1000:out=8’b1111_1110; 4’b1001:out=8’b1111_0110; 4’b1010:out=8’b1110_1110; 4’b1011:out=8’b0011_1110; 4’b1100:out=8’b0001_1010; 4’b1101:out=8’b0111_1010; 4’b1110:out=8’b1001_1110; 4’b1111:out=8’b1000_1110; endcase endendmodule
然后使用一个顶层模块串起来就行了:
`timescale 1ns / 1psmodule hexseg8( input s, input [3:0]sw1, input [3:0]sw2, input clk_i, output wire [7:0]left, output wire [7:0]right, output wire [3:0]dn0, output wire [3:0]dn1 ); wire [7:0]out0; wire [7:0]out1; wire [7:0]out2; wire [7:0]out3; wire [7:0]out4=8’b;//班级 wire [7:0]out5=8’b;//班级(记得加小数点 wire [7:0]out6=8’b;//学号 wire [7:0]out7=8’b; wire [15:0]temp=0; //四位拨码开关 four four1(sw1,out3); four four2(sw2,out2); //计数器 counter counter1(clk_i,s,out0,out1);//数码管显示分频模块 all_counter counter2(out0,out1,out2,out3,out4,out5,out6,out7,clk_i,left,right,dn0,dn1);endmodule 61545448