1.试验任务
- 完成6位数码管以动态方式从0开始计数,没100ms计数值增加1,当计数值从0增加到999999后重新从0开始计数。
2.硬件原理图
3.程序框图
- 程序设计思想:
FPGA顶层(top_seg_led)例化了以下两个模块:计数模块(count)以及数码管动态显示模块(seg_led)。实现各模块之间数据的交互。计数模块将计数值通过data端口传递给数码管动态显示模块, 使能信号en使能数码管显示数据, 小数点显示信号point控制小数点的显示,符号信号sign可以让数码管显示负号。
计数模块(count):显示的数字每100ms加“1”。
数码管动态显示模块 (seg_led) : 数码管动态显示模块在数码管上以动态方式显示数值。
module top_seg_led(
input sys_clk,
input sys_rst_n,
output [5:0] seg_wei,
output [7:0] seg_duan
);
wire [19:0] seg_num;
time_count u_time_count(
.sys_clk (sys_clk),
.sys_rst_n (sys_rst_n),
.seg_num (seg_num)
);
seg_led u_seg_led(
.sys_clk (sys_clk),
.sys_rst_n (sys_rst_n),
.seg_num (seg_num),
.seg_wei (seg_wei),
.seg_duan (seg_duan)
);
endmodule
module time_count(
input sys_clk,
input sys_rst_n,
output reg [19:0] seg_num
);
reg [22:0] time_num;
reg time_flag;
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)begin
time_num<=23'd0;
time_flag<=1'b0;
end
else begin
if(time_num<23'd5_000_000)begin
time_num<=time_num+1'b1;
time_flag<=1'b0;
end
else begin
time_num <=23'd1;
time_flag<=1'b1;
end
end
end
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)begin
seg_num<=20'd0;
end
else begin
if(time_flag&&seg_num<20'd1_000_000)
seg_num<=seg_num+1'b1;
else if(seg_num==20'd1_000_000)
seg_num<=20'd0;
else
seg_num<=seg_num;
end
end
endmodule
module seg_led(
input sys_clk,
input sys_rst_n,
input [19:0] seg_num,
output reg [5:0] seg_wei,
output reg [7:0] seg_duan
);
wire [23:0] data_num; //每位数码管需要显示的数
assign data_num[3:0] =seg_num%10;
assign data_num[7:4] =seg_num/4'd10%10;
assign data_num[11:8] =seg_num/7'd100%10;
assign data_num[15:12]=seg_num/10'd1000%10;
assign data_num[19:16]=seg_num/14'd10000%10;
assign data_num[23:20]=seg_num/17'd100000;
/
reg [22:0] time_num;
reg time_flag;
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)begin
time_num<=23'd0;
time_flag<=1'b0;
end
else
begin
if(time_num<23'd100_000)begin
time_num<=time_num+1'b1;
time_flag<=1'b0;
end
else begin
time_num <=23'd1;
time_flag<=1'b1;
end
end
end
/
reg [3:0] seg_static;
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)
seg_static<=4'd0;
else begin
if(seg_static<4'd6&&time_flag)
seg_static<=seg_static+1'b1;
else if(seg_static==4'd6)
seg_static<=4'd0;
else
seg_static<=seg_static;
end
end
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)begin
seg_wei <=6'b000000;
seg_duan<=8'b1111111;
end
else begin
case(seg_static)
4'd0: begin
seg_wei <=6'b111110;
case (data_num[3:0])
4'd0 : seg_duan <= 8'b1100_0000; //显示数字 0
4'd1 : seg_duan <= 8'b1111_1001; //显示数字 1
4'd2 : seg_duan <= 8'b1010_0100; //显示数字 2
4'd3 : seg_duan <= 8'b1011_0000; //显示数字 3
4'd4 : seg_duan <= 8'b1001_1001; //显示数字 4
4'd5 : seg_duan <= 8'b1001_0010; //显示数字 5
4'd6 : seg_duan <= 8'b1000_0010; //显示数字 6
4'd7 : seg_duan <= 8'b1111_1000; //显示数字 7
4'd8 : seg_duan <= 8'b1000_0000; //显示数字 8
4'd9 : seg_duan <= 8'b1001_0000;
endcase
end
4'd1:begin
seg_wei <=6'b111101;
case (data_num[7:4])
4'd0 : seg_duan <= 8'b1100_0000; //显示数字 0
4'd1 : seg_duan <= 8'b1111_1001; //显示数字 1
4'd2 : seg_duan <= 8'b1010_0100; //显示数字 2
4'd3 : seg_duan <= 8'b1011_0000; //显示数字 3
4'd4 : seg_duan <= 8'b1001_1001; //显示数字 4
4'd5 : seg_duan <= 8'b1001_0010; //显示数字 5
4'd6 : seg_duan <= 8'b1000_0010; //显示数字 6
4'd7 : seg_duan <= 8'b1111_1000; //显示数字 7
4'd8 : seg_duan <= 8'b1000_0000; //显示数字 8
4'd9 : seg_duan <= 8'b1001_0000;
endcase
end
4'd2:begin
seg_wei <=6'b111011;
case (data_num[11:8])
4'd0 : seg_duan <= 8'b1100_0000; //显示数字 0
4'd1 : seg_duan <= 8'b1111_1001; //显示数字 1
4'd2 : seg_duan <= 8'b1010_0100; //显示数字 2
4'd3 : seg_duan <= 8'b1011_0000; //显示数字 3
4'd4 : seg_duan <= 8'b1001_1001; //显示数字 4
4'd5 : seg_duan <= 8'b1001_0010; //显示数字 5
4'd6 : seg_duan <= 8'b1000_0010; //显示数字 6
4'd7 : seg_duan <= 8'b1111_1000; //显示数字 7
4'd8 : seg_duan <= 8'b1000_0000; //显示数字 8
4'd9 : seg_duan <= 8'b1001_0000;
endcase
end
4'd3:begin
seg_wei <=6'b110111;
case (data_num[15:12])
4'd0 : seg_duan <= 8'b1100_0000; //显示数字 0
4'd1 : seg_duan <= 8'b1111_1001; //显示数字 1
4'd2 : seg_duan <= 8'b1010_0100; //显示数字 2
4'd3 : seg_duan <= 8'b1011_0000; //显示数字 3
4'd4 : seg_duan <= 8'b1001_1001; //显示数字 4
4'd5 : seg_duan <= 8'b1001_0010; //显示数字 5
4'd6 : seg_duan <= 8'b1000_0010; //显示数字 6
4'd7 : seg_duan <= 8'b1111_1000; //显示数字 7
4'd8 : seg_duan <= 8'b1000_0000; //显示数字 8
4'd9 : seg_duan <= 8'b1001_0000;
endcase
end
4'd4:begin
seg_wei <=6'b101111;
case (data_num[19:16])
4'd0 : seg_duan <= 8'b1100_0000; //显示数字 0
4'd1 : seg_duan <= 8'b1111_1001; //显示数字 1
4'd2 : seg_duan <= 8'b1010_0100; //显示数字 2
4'd3 : seg_duan <= 8'b1011_0000; //显示数字 3
4'd4 : seg_duan <= 8'b1001_1001; //显示数字 4
4'd5 : seg_duan <= 8'b1001_0010; //显示数字 5
4'd6 : seg_duan <= 8'b1000_0010; //显示数字 6
4'd7 : seg_duan <= 8'b1111_1000; //显示数字 7
4'd8 : seg_duan <= 8'b1000_0000; //显示数字 8
4'd9 : seg_duan <= 8'b1001_0000;
endcase
end
4'd5:begin
seg_wei <=6'b011111;
case (data_num[23:20])
4'd0 : seg_duan <= 8'b1100_0000; //显示数字 0
4'd1 : seg_duan <= 8'b1111_1001; //显示数字 1
4'd2 : seg_duan <= 8'b1010_0100; //显示数字 2
4'd3 : seg_duan <= 8'b1011_0000; //显示数字 3
4'd4 : seg_duan <= 8'b1001_1001; //显示数字 4
4'd5 : seg_duan <= 8'b1001_0010; //显示数字 5
4'd6 : seg_duan <= 8'b1000_0010; //显示数字 6
4'd7 : seg_duan <= 8'b1111_1000; //显示数字 7
4'd8 : seg_duan <= 8'b1000_0000; //显示数字 8
4'd9 : seg_duan <= 8'b1001_0000;
endcase
end
endcase
end
end
endmodule
仿真 结果如下:
起初调试的时候只有最低为显示自加1,原因为led_static的 计数写的后问题 ,后进行改进
PS:补一下上周的实验仿真调试