前言
采用七段数码管,如下图,8bits的段选用来控制数字的显示(0~F)
16进制的单个数字和段选的对应关系如下,我们写成verilog模块的形式,方便直接使用。
module to_seg7 (
input [3:0] t,
output [7:0] seg
);
always @(t) begin
case (t)
4'h0 : seg = 8'hfc;
4'h1 : seg = 8'h60;
4'h2 : seg = 8'hda;
4'h3 : seg = 8'hf2;
4'h4 : seg = 8'h66;
4'h5 : seg = 8'hb6;
4'h6 : seg = 8'hbe;
4'h7 : seg = 8'he0;
4'h8 : seg = 8'hfe;
4'h9 : seg = 8'hf6;
4'ha : seg = 8'hee;
4'hb : seg = 8'h3e;
4'hc : seg = 8'h9c;
4'hd : seg = 8'h7a;
4'he : seg = 8'h9e;
4'hf : seg = 8'h8e;
default: seg = 8'h0;
endcase
end
endmodule
多位数码管的显示
这里将一个两位数字(十进制),用两个数码管来显示。
输入的数字是current_time
,输出2bits的an
是位选,控制哪个数码管亮灯,输出8bits的seg
是段选,含义见前言部分。
原理:动态扫描显示,数码管的动态显示是对每个数码管采用分时复用的方式轮流点亮每个数码管,在同一时间只会点亮一个数码管。 分时复用的扫描显示利用了人眼的视觉暂留特性。
**思路:**将输入的两位数字的时间转换成十位和个位,然后通过动态扫描的方式(翻转sel
)轮流显示。
**扩展:**如果要显示4个或者8个数码管,原理相同,将sel
弄成对应的bit位数,然后进行循环计数。
module display(
input clk ,
input rst ,
input [4:0] current_time ,
output reg [1:0] an ,
output reg [7:0] seg
);
wire [3:0] high_data;
wire [3:0] low_data;
wire [7:0] high_time;
wire [7:0] low_time;
reg sel;
assign high_data = current_time / 4'd10;
assign low_data = current_time % 4'd10;
to_seg7 high_to_seg7(high_data, high_time);
to_seg7 low_to_seg7(low_data, low_time);
always @(posedge clk or posedge rst) begin
if (rst) begin
sel <= 0;
end else begin
sel <= ~sel;
end
end
always @(posedge clk or posedge rst) begin
if (rst) begin
an <= 2'b00;
seg <= 8'b0000_0000;
end else begin
if (sel == 1'b0) begin
an <= 2'b01;
seg <= low_time;
end else if (sel == 1'b1) begin
an <= 2'b10;
seg <= high_time;
end else begin
an <= 2'b00;
seg <= 8'b0000_0000;
end
end
end
endmodule