目录
一、数码管工作原理
二、Verilog模块设计
1、原理
(1)动态扫描的优点:
(2)动态扫描原理简介:
2、Verilog模块的设计
(1)分频器:
2、译码器模块:
3、动态扫描模块:
4、顶层模块:
三、写在最后:
在大二下学期学习《Verilog与FPGA实现》的时候鲲鲲给我们布置了课程实验,有许多实验需要用到数码管作为输出。本文旨在用模块化的思想向大家介绍笔者的通用的数码管显示模块。
一、数码管工作原理
数码管事常见的显示装置,通常由7段或8段LED组成,根据公共端连接方式分为:共阳极数码管、共阴极数码管。
顾名思义,共阴极数码管的所有LED的阴极是接在一块的,当通入高电平数码管才点亮;共阳极数码管的所有LED是阳极接在一起,输入低电平点亮,段选码如下图所示
我们用的Basys2的数码管为共阳极数码管,因此本次设计采用共阳极段码表。
二、Verilog模块设计
1、原理
为了节省管脚,Basys2开发板采用的是动态扫描的方式来进行数码管显示,具体如下:
(1)动态扫描的优点:
管脚对芯片来说是非常宝贵的资源,对于我们的板子来说,用到了4个8段数码管,如果用管脚直接控制LED的亮灭的话,总共需要用到4*(8+2)=40个管脚(8是abcdefg段选,2是两个共阳极),一共用到32个管脚作为控制端;而用动态扫描的方式来进行显示的话需要4个位选(选择四个数码管中的哪一个)和8个段选(abcdefg中的哪一段,当然还有两个共阳极),一共用到12个管脚作为控制端,高下立判。
(2)动态扫描原理简介:
要实现动态扫描,最常用的是数据锁存器和移位寄存器,在某一时刻输入位选选中要显示的数码管,同时送上相应的段选码,下一时刻选中下一个数码管同时送上对应的段选码,只要扫描的频率足够快,人眼就会因为视觉暂留效应而看到的4个数码管显示不同的数字。常用的刷新频率在1KHz到60Hz,太快就会亮度不够,太慢就会闪烁。
2、Verilog模块的设计
设计的模块会将输入的4个二进制码显示在4个位的数码管上,因而需要模块:分频器(将板子50MHz时钟分频为1KHz时钟)、译码模块(二进制码转为共阳极数码管段选码)、动态扫描模块(在特定时刻选中位并送上对应的段选码)、top(顶层封装),具体代码如下:
(1)分频器:
计数分频,通过计算,输入的50MHz时钟分频为1KHz时钟,需要计数50000次,为了节省资源,计数器位宽为16位刚好满足2^16<50000<2^17。
module clk_div(
input clk,
output reg clk_div
);
//输入板子50MHz时钟,输出1KHz时钟
//计数分频:50000次
reg [15:0]cnt = 16'd0;
always@(posedge clk)
begin
if(cnt == 16'd50000)
begin
cnt <= 16'd0;
end
else
begin
cnt <= cnt + 16'd1;
end
end
//输出时钟控制
always@(posedge clk)
begin
if(cnt <= 16'd24999)
begin
clk_div <= 1'b1;
end
else
begin
clk_div <= 1'b0;
end
end
endmodule
2、译码器模块:
一个很简单的case分支实现译码,输入4位二进制编码,输出对应的8位段选码。
module wei_encoder(
input [3:0]hex_number,
output reg [7:0]display_code
);
//将输入的十六进制代码转换为共阳极数码管段选编码并输出
always@(*)
begin
case(hex_number)
4'b0000:display_code = 8'hc0;//0
4'b0001:display_code = 8'hf9;//1
4'b0010:display_code = 8'ha4;//2
4'b0011:display_code = 8'hb0;//3
4'b0100:display_code = 8'h99;//4
4'b0101:display_code = 8'h92;//5
4'b0110:display_code = 8'h82;//6
4'b0111:display_code = 8'hf8;//7
4'b1000:display_code = 8'h80;//8
4'b1001:display_code = 8'h90;//9
4'b1010:display_code = 8'h88;//A
4'b1011:display_code = 8'h83;//B
4'b1100:display_code = 8'hc6;//C
4'b1101:display_code = 8'ha1;//D
4'b1110:display_code = 8'h86;//E
4'b1111:display_code = 8'h8e;//F
default:display_code = 8'hff;//无
endcase
end
endmodule
3、动态扫描模块:
输入分频后的1KHz时钟作为位选信号的扫描频率,通过计数器的数值case输出位选和相应的段选信号。
module Display(
input clk_div,
input [7:0]Out_number_1,//第一位数字对应的段选码
input [7:0]Out_number_2,//第二位数字对应的段选码
input [7:0]Out_number_3,//第三位数字对应的段选码
input [7:0]Out_number_4,//第四位数字对应的段选码
output reg [7:0]duan_code,
output reg [3:0]wei_code
);
//将输入的十六进制代码转换为共阳极数码管段选码动态扫描输出
reg [2:0]sel_cnt;//扫描计数器
//动态扫描
always@(posedge clk_div)
begin
if(sel_cnt == 3'd4)
begin
sel_cnt <= 3'd0;
end
else
begin
sel_cnt <= sel_cnt + 3'd1;
end
end
always@(posedge clk_div)
begin
case(sel_cnt)
3'd0:
begin
wei_code <= 4'b0001;
duan_code <= Out_number_1;
end
3'd1:
begin
wei_code <= 4'b0010;
duan_code <= Out_number_2;
end
3'd2:
begin
wei_code <= 4'b0100;
duan_code <= Out_number_3;
end
3'd3:
begin
wei_code <= 4'b1000;
duan_code <= Out_number_4;
end
default:
begin
wei_code <= 4'b0000;
duan_code <= 8'hff;
end
endcase
end
endmodule
4、顶层模块:
在顶层中例化上述三个模块,封装为一个模块,方便实例化调用,具体流程:分频器将输入的clk(50MHz)分频为clk_div(1KHz),送往Display用于扫描计数器的动态扫描,wei_encoder将输入的二进制数转化为共阳极数码管对应的段选码,送往Display模块扫描输出。文章来源:https://www.toymoban.com/news/detail-484144.html
module SEG_display(
input clk,
input [7:0]number1,
input [7:0]number2,
output [3:0]wei_code,
output [7:0]duan_code
);
//声明内部信号线
wire [7:0]Out_number_1;//将要输出的段选码
wire [7:0]Out_number_2;
wire [7:0]Out_number_3;
wire [7:0]Out_number_4;
wire clk_div;//分频后的时钟
//模块实例化
//时钟分频,用于数码管计数扫描
clk_div div(
.clk(clk),
.clk_div(clk_div)
);
//将将要输出的数转化为段选码
wei_encoder encoder1(
.hex_number(number1[3:0]),
.display_code(Out_number_1)
);
wei_encoder encoder2(
.hex_number(number1[7:4]),
.display_code(Out_number_2)
);
wei_encoder encoder3(
.hex_number(number2[3:0]),
.display_code(Out_number_3)
);
wei_encoder encoder4(
.hex_number(number2[7:4]),
.display_code(Out_number_4)
);
//数码管动态扫描显示
Display display(
.clk_div(clk_div),
.Out_number_1(Out_number_1),
.Out_number_2(Out_number_2),
.Out_number_3(Out_number_3),
.Out_number_4(Out_number_4),
.duan_code(duan_code),
.wei_code(wei_code)
);
endmodule
三、写在最后:
这个Verilog数码管动态扫描模块可以适用于Basys2几乎所有的项目,今后我将陆续更新鲲鲲的《Verilog与FPGA实现》 给我们布置的八个实验,一方面巩固自己的知识,另一方面有助于学弟学妹们学习。笔者不才,如有疏漏,欢迎各位网友批评指正。文章来源地址https://www.toymoban.com/news/detail-484144.html
到了这里,关于基于Basys2的数码管动态扫描module(verilog)的模块化设计的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!