上一篇文章我们使用模块的方式实现了计数器,但是我们看到在计数器前的零全部显示,这在我们的日常生活中是不太符合逻辑的,因为我们通常没有这些0。本次实验我们将这些0不显示。
首先,我们来思考,消除这些0我们需要在显示模块中设置一个标志位,如果标志位为1,那么我们就显示0,如果标志位为0,那么我们不显示即可。关于标志位的判断,按照我们的常识,当这一位是0时,如果该位之前的位不全部为0,那么我们需要显示该0,这一位之前全部都是0,那么我们不显示该0。如果该位不为0,正常显示即可。按照上述逻辑,我们做出以下修改。
1.将显示模块num_show增加一个输入zero_en 参数,在0显示是检测该标志位是否为1,判断是否显示。
2.将计数模块num_cnt增加一个输入参数zero_en1,一个输出参数zero_en2。zero_en1用来连接高位输出的zero_en2,同时将本模块的zero_en2,连接至和本模块连接的num_show模块的zero_en参数。在num_cnt模块中判断如何本模块的数据不是0,那么输出标志位zero_en2=1,如果当前位是0,检测上一位传入的标志位zero_en1是否为1,如果是1 ,那么zero_en2=1,否则zero_en2=0。即可。
计数器模块num_cn的代码如下
/*
Author:Alawyssun
Time:2020/03/25
实现功能:完成一个计数器模块
计数器输入: 1 进位脉冲
2 时钟信号和复位信号
计数器输出:1 当前计数值
2 当前是否有进位信号
*/
module num_cnt(
input rst,//复位信号
input clk,//时钟信号
input en,//使能信号 每使能一次计数加一
input zero_en1,
output reg zero_en2,
output reg pulse,//输出进位信号 传给下一个计数器
output reg[3:0] data//当前保存的数据
);
always@(posedge clk)
begin
if(data!=0)
begin
zero_en2<=1;
end
else
begin
if(zero_en1!=0)
begin
zero_en2<=1;
end
else
begin
zero_en2<=0;
end
end
end
always@(posedge clk)
begin
if(rst==0)//按下复位键
begin
data<=4'd0;//计数器和输出全为0
pulse<=1'd0;
end
if(en)//如果有进位输入
begin
if(data==4'd9)//如果此时计数值已经达到9,那么将进位标志位设置为1 同时数据清零
begin
pulse<=1'b1;
data<=4'd0;
end
else //如果计数值不是9 那么计数值自己加一 同时进位标志位为0
begin
pulse<=1'b0;
data<=data+4'd1;
end
end
else
begin
pulse<=1'b0;
end
end
endmodule
显示模块的代码如下
/*
Author:Alawyssun
Time:2020/03/25
实现功能:输入一个数字转换成对应的数码管编码
输入:data 输入的参数
输出:seg_data输出对应的数码管的编码
*/
module num_show(
input[3:0]data,
input zero_en,
output reg[7:0]seg_data
);
/*
4'ha:seg_data <= 8'b1000_1000;
4'hb:seg_data <= 8'b1000_0011;
4'hc:seg_data <= 8'b1100_0110;
4'hd:seg_data <= 8'b1010_0001;
4'he:seg_data <= 8'b1000_0110;
4'hf:seg_data <= 8'b1000_1110;
*/
always@(*)
begin
case(data)
4'd0:
if(zero_en)
begin
seg_data <= 8'b1100_0000;
end
else
begin
seg_data <= 8'b1111_1111;
end
4'd1:seg_data <= 8'b1111_1001;
4'd2:seg_data <= 8'b1010_0100;
4'd3:seg_data <= 8'b1011_0000;
4'd4:seg_data <= 8'b1001_1001;
4'd5:seg_data <= 8'b1001_0010;
4'd6:seg_data <= 8'b1000_0010;
4'd7:seg_data <= 8'b1111_1000;
4'd8:seg_data <= 8'b1000_0000;
4'd9:seg_data <= 8'b1001_0000;
default:seg_data <= 8'b1111_1111;
endcase
end
endmodule
扫描模块的代码如下
/*
Author:Alawyssun
Time:2020/03/25
程序功能:实现数码管的扫描显示
输入:六个数码管的输出编码数据
输出:扫描之后的数码管段选和片选信号
*/
module num_scan(
input clk,
input rst,
input[7:0] seg_data_scan_0,
input[7:0] seg_data_scan_1,
input[7:0] seg_data_scan_2,
input[7:0] seg_data_scan_3,
input[7:0] seg_data_scan_4,
input[7:0] seg_data_scan_5,
output reg[7:0] seg_data_scan,
output reg[5:0] seg_sel
);
parameter SCAN_FREQ = 200; //扫描的频率
parameter CLK_FREQ = 50000000; //时钟频率
parameter SCAN_COUNT = CLK_FREQ /(SCAN_FREQ*7) - 1;//扫描一次 需要时钟计数的个数
reg[31:0]time_cnt2;//时间计数器2 用作刷新数码管的时钟
reg[7:0] wei_cnt_clk;//判断输出哪一个数码管
//数码管刷新时间 计数
always@(posedge clk or negedge rst)
begin
if(rst==1'b0)
begin
time_cnt2<=32'd0;
end
else if(time_cnt2==SCAN_COUNT)
begin
time_cnt2<=32'd0;
if(wei_cnt_clk==8'd7)
begin
wei_cnt_clk<=0;
end
else
begin
wei_cnt_clk<=wei_cnt_clk+1;
end
end
else
begin
time_cnt2<=time_cnt2+32'd1;
end
end
//数码管显示
always@(posedge clk or negedge rst)
begin
if(rst == 1'b0)
begin
seg_sel <= 6'b000000;
seg_data_scan <= 8'hff;
end
else
begin
case(wei_cnt_clk)//如果计时为0 刷新第一个数码管
8'd0:
begin
seg_data_scan<=seg_data_scan_0;
seg_sel=6'b01_1111;
end
8'd1:
begin
seg_data_scan<=seg_data_scan_1;
seg_sel=6'b10_1111;
end
8'd2:
begin
seg_data_scan<=seg_data_scan_2;
seg_sel=6'b11_0111;
end
8'd3:
begin
seg_data_scan<=seg_data_scan_3;
seg_sel=6'b11_1011;
end
8'd4:
begin
seg_data_scan<=seg_data_scan_4;
seg_sel=6'b11_1101;
end
8'd5:
begin
seg_sel <= 6'b11_1110;
seg_data_scan <= seg_data_scan_5;
end
8'd6://消影
begin
seg_sel <= 6'b00_0000;
seg_data_scan <= 8'hff;
end
endcase
end
end
endmodule
总体模块的代码如下
/*
Author:Alawyssun
Time:2020/03/25
实现功能:利用模块化的方法,实现六个数码管显示一个数字的功能
该数字在时钟的作用下,按一定的频率自动加一 同时将数字之前的0消去
*/
`timescale 1n/1ps
module seg_test(
input clk,
input rst,
output [5:0] seg_pi,//片选
output [7:0] seg_data//数据位
);
reg[31:0] time_cnt;
reg one_hz;
parameter CLK_FREQ = 50_000_000; //时钟频率
parameter CNT_SECOND = 1; //计数器加一需要的时间 比如1秒 就写10 0.5秒就写5
parameter CNT_NUMBER = CNT_SECOND*CLK_FREQ; //计数器加一需要的时间
always@(posedge clk or negedge rst)
begin
if(rst==1'b0)
begin
time_cnt<=32'd0;
end
else
begin
if(time_cnt==32'd49_999_999)
begin
time_cnt<=32'd0;
one_hz<=1'b1;
end
else
begin
time_cnt<=time_cnt+32'd1;
one_hz<=1'b0;
end
end
end
wire[3:0] count0;
wire t0;
wire[7:0] seg_data_0;
wire zero_my0,zero_my1,zero_my2,zero_my3,zero_my4,zero_my5;
num_cnt num_cnt0_my(
.rst (rst),
.clk (clk),
.en (one_hz),
.zero_en1 (zero_my1),
.zero_en2 (zero_my0),
.pulse (t0),
.data (count0)
);
num_show num_show0_my(
.data (count0),
.zero_en(zero_my0),
.seg_data (seg_data_0)
);
wire[3:0] count1;
wire t1;
wire[7:0] seg_data_1;
num_cnt num_cnt1_my(
.rst (rst),
.clk (clk),
.en (t0),
.zero_en1 (zero_my2),
.zero_en2 (zero_my1),
.pulse (t1),
.data (count1)
);
num_show num_show1_my(
.data (count1),
.zero_en(zero_my1),
.seg_data (seg_data_1)
);
wire[3:0] count2;
wire[7:0] seg_data_2;
wire t2;
num_cnt num_cnt2_my(
.rst (rst),
.clk (clk),
.en (t1),
.zero_en1 (zero_my3),
.zero_en2 (zero_my2),
.pulse (t2),
.data (count2)
);
num_show num_show2_my(
.data (count2),
.zero_en(zero_my2),
.seg_data (seg_data_2)
);
wire[3:0] count3;
wire[7:0] seg_data_3;
wire t3;
num_cnt num_cnt3_my(
.rst (rst),
.clk (clk),
.en (t2),
.zero_en1 (zero_my4),
.zero_en2 (zero_my3),
.pulse (t3),
.data (count3)
);
num_show num_show3_my(
.data (count3),
.zero_en(zero_my3),
.seg_data (seg_data_3)
);
wire[7:0] seg_data_4;
wire[3:0] count4;
wire t4;
num_cnt num_cnt4_my(
.rst (rst),
.clk (clk),
.en (t3),
.zero_en1 (zero_my5),
.zero_en2 (zero_my4),
.pulse (t4),
.data (count4)
);
num_show num_show4_my(
.data (count4),
.zero_en(zero_my4),
.seg_data (seg_data_4)
);
wire[7:0] seg_data_5;
wire[3:0] count5;
wire t5;
num_cnt num_cnt5_my(
.rst (rst),
.clk (clk),
.en (t4),
.zero_en1 (0),
.zero_en2 (zero_my5),
.pulse (t5),
.data (count5)
);
num_show num_show5_my(
.data (count5),
.zero_en(zero_my5),
.seg_data (seg_data_5)
);
num_scan num_scan_my(
.clk (clk),
.rst (rst),
.seg_data_scan_0 (seg_data_0),
.seg_data_scan_1 (seg_data_1),
.seg_data_scan_2 (seg_data_2),
.seg_data_scan_3 (seg_data_3),
.seg_data_scan_4 (seg_data_4),
.seg_data_scan_5 (seg_data_5),
.seg_data_scan (seg_data),
.seg_sel (seg_pi)
);
endmodule
本次实验结果如下,可以看到数字之前的0全部没有显示
本次实验的工程下载地址为: https://download.csdn.net/download/qq_34020487/12270483