动态显示驱动模块


- point:输入小数点信号,高电平有效,这里我们假设要让第二个数码管显示小数点,其余数码管不显示小数点,那么此时 point 的输入的值就应该是 6’b000010。
- seg_en:数码管使能信号,这里一直让其拉高即可。
- data:输入的十进制数据,假设这里我们输入的十进制数为 9876。
- sign:符号位控制信号,高电平有效。假设我们需要显示的是负数,那么这里就让符号位控制信号为高即可。
- unit、ten、hun、tho、t_tho、h_hun:这六个信号就是我们例化的 bcd_8421 模块转化的的 8421BCD 码,也就是说这六个 BCD 码就是输入十进制数 9876 各个位的 BCD 码。所以这里个位(unit)是 6,十位(ten)是 7,百位(hun)是 8,千位(tho)是 9,万位和十万位都为 0。
- data_reg:数码管待显示内容寄存器,因为这里我们假设输入要显示的十进制数为9876,并且显示负号,所以前五个数码管就会显示-9876 的数值,此时最高位数码管什么都不显示,我们用 X 表示,所以这里六个数码管显示的内容就是:X-9876。
- cnt_1ms:前面讲到要让显示的数码管不会有闪烁感,我们需要使用 1ms 的扫描时间去扫描各个数码管。所以这里我们需要一个 1ms 的计数器对 1ms 进行循环计数。
- flag_1ms:1ms 计数标志信号,当 1ms 计数器计到 1ms 时拉高该标志信号,我们使用该标志信号去控制位选数码管计数器的计数。
- cnt_sel:位选数码管计数器。我们理论学习已经学习到动态扫描方式是用 1ms 的刷新时间让六个数码管轮流显示:第 1ms 点亮第一个数码管,第 2ms 点亮第二个数码管,以此类推依次点亮六个数码管,6ms 一个轮回,也就是说每个数码管每 6ms 点亮一次。那问题是我们怎么去选中这个要显示的数码管并且给其要显示的值呢?这个时候我们就引入了一 cnt_sel 信号,让其从 0~5 循环计数,1 个数代表一个数码管,可以看做是给数码管编号。这样的话我们只要选择计数器的值就相当于选中了其中对应的数码管。特别要说明的是我们的 cnt_sel 计数器必须与数码管的刷新状态一致,也就是 1ms 计 1 个数。
- sel_reg:数码管位选信号寄存器,为了让数码管位选信号和段选信号同步,这里我们先将位选信号进行寄存。刷新到哪个数码管将 sel 中对应位(6 个位宽,每一位表示一个数码管)给高点亮即可。选中点亮的数码管后我们需要给其要显示的值,所以我们引入一个新的信号。
- data_disp:当前点亮数码管显示的值。若我们此时点亮的是第一个数码管,那么我们就需要给第一个数码管显示的值 6,若刷新到第二个数码管就让该信号的值为 7 让第二个数码管显示,以此类推;当刷新到第五个数码管时,此时显示的是负号,那么我们该如何表示呢?这里我们让该信号的值为 10 来表示,也就是说当 data_disp 的值为 10 时就让数码管显示负号,同理这里我们定义 data_disp 的值为 11 时让数码管什么也不显示,即不点亮数码管。
- dot_disp:当前数码管显示的小数点,我们输入的 point 信号是点亮第二个数码管的小数点,而我们的数码管是低电平点亮,所以这里当扫描到第二个数码管时让 dot_disp 信号为低即可。
- seg:数码管段选信号,我们根据数码管编码译码表当扫描到哪个数码管显示需要显示的值时,我们将对于的段点亮即可。
- sel:数码管位选信号。将数码管位选信号寄存器打一拍即可,这样就能实现数码管段选信号和位选信号的同步。
```verilog
module seg_dynamic
(
input wire sys_clk ,
input wire sys_rst_n ,
input wire [19:0] data ,
input wire [5:0] point ,
input wire seg_en ,
input wire sign ,
output reg [5:0] sel ,
output reg [7:0] seg
);
parameter CNT_MAX = 16'd49_999;
wire [3:0] unit ;
wire [3:0] ten ;
wire [3:0] hun ;
wire [3:0] tho ;
wire [3:0] t_tho ;
wire [3:0] h_hun ;
reg [23:0] data_reg ;
reg [15:0] cnt_1ms ;
reg flag_1ms ;
reg [2:0] cnt_sel ;
reg [5:0] sel_reg ;
reg [3:0] data_disp ;
reg dot_disp ;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
data_reg <= 24'b0;
else if((h_hun) || (point[5]))
data_reg <= {h_hun,t_tho,tho,hun,ten,unit};
else if(((t_tho) || (point[4])) && (sign == 1'b1))
data_reg <= {4'd10,t_tho,tho,hun,ten,unit};
else if(((t_tho) || (point[4])) && (sign == 1'b0))
data_reg <= {4'd11,t_tho,tho,hun,ten,unit};
else if(((tho) || (point[3])) && (sign == 1'b1))
data_reg <= {4'd11,4'd10,tho,hun,ten,unit};
else if(((tho) || (point[3])) && (sign == 1'b0))
data_reg <= {4'd11,4'd11,tho,hun,ten,unit};
else if(((hun) || (point[2])) && (sign == 1'b1))
data_reg <= {4'd11,4'd11,4'd10,hun,ten,unit};
else if(((hun) || (point[2])) && (sign == 1'b0))
data_reg <= {4'd11,4'd11,4'd11,hun,ten,unit};
else if(((ten) || (point[1])) && (sign == 1'b1))
data_reg <= {4'd11,4'd11,4'd11,4'd10,ten,unit};
else if(((ten) || (point[1])) && (sign == 1'b0))
data_reg <= {4'd11,4'd11,4'd11,4'd11,ten,unit};
else if(((unit) || (point[0])) && (sign == 1'b1))
data_reg <= {4'd11,4'd11,4'd11,4'd11,4'd10,unit};
else
data_reg <= {4'd11,4'd11,4'd11,4'd11,4'd11,unit};
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_1ms <= 16'd0;
else if(cnt_1ms == CNT_MAX)
cnt_1ms <= 16'd0;
else
cnt_1ms <= cnt_1ms + 1'b1;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
flag_1ms <= 1'b0;
else if(cnt_1ms == CNT_MAX - 1'b1)
flag_1ms <= 1'b1;
else
flag_1ms <= 1'b0;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_sel <= 3'd0;
else if((cnt_sel == 3'd5) && (flag_1ms == 1'b1))
cnt_sel <= 3'd0;
else if(flag_1ms == 1'b1)
cnt_sel <= cnt_sel + 1'b1;
else
cnt_sel <= cnt_sel;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
sel_reg <= 6'b000_000;
else if((cnt_sel == 3'd0) && (flag_1ms == 1'b1))
sel_reg <= 6'b000_001;
else if(flag_1ms == 1'b1)
sel_reg <= sel_reg << 1;
else
sel_reg <= sel_reg;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
data_disp <= 4'b0;
else if((seg_en == 1'b1) && (flag_1ms == 1'b1))
case(cnt_sel)
3'd0: data_disp <= data_reg[3:0] ;
3'd1: data_disp <= data_reg[7:4] ;
3'd2: data_disp <= data_reg[11:8] ;
3'd3: data_disp <= data_reg[15:12];
3'd4: data_disp <= data_reg[19:16];
3'd5: data_disp <= data_reg[23:20];
default:data_disp <= 4'b0 ;
endcase
else
data_disp <= data_disp;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
dot_disp <= 1'b1;
else if(flag_1ms == 1'b1)
dot_disp <= ~point[cnt_sel];
else
dot_disp <= dot_disp;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
seg <= 8'b1111_1111;
else
case(data_disp)
4'd0 : seg <= {dot_disp,7'b100_0000};
4'd1 : seg <= {dot_disp,7'b111_1001};
4'd2 : seg <= {dot_disp,7'b010_0100};
4'd3 : seg <= {dot_disp,7'b011_0000};
4'd4 : seg <= {dot_disp,7'b001_1001};
4'd5 : seg <= {dot_disp,7'b001_0010};
4'd6 : seg <= {dot_disp,7'b000_0010};
4'd7 : seg <= {dot_disp,7'b111_1000};
4'd8 : seg <= {dot_disp,7'b000_0000};
4'd9 : seg <= {dot_disp,7'b001_0000};
4'd10 : seg <= 8'b1011_1111 ;
4'd11 : seg <= 8'b1111_1111 ;
default:seg <= 8'b1100_0000;
endcase
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
sel <= 6'b000_000;
else
sel <= sel_reg;
bcd_8421 bcd_8421_inst
(
.sys_clk (sys_clk ),
.sys_rst_n (sys_rst_n),
.data (data ),
.unit (unit ),
.ten (ten ),
.hun (hun ),
.tho (tho ),
.t_tho (t_tho ),
.h_hun (h_hun )
);
endmodule
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET10 - 预览版1新功能体验(一)