1.IDE:Quartus II
2.设备:Cyclone II EP2C8Q208C8N
3.实验:之前做的数码管实验一直有问题,今天解决了。
(1)模块要足够细化,不要写得臃肿 !!!!!!!!!!
(2)注意每次扫描前需要将所有数码管先关闭,因为我们的数码管会在上一次使用时打开某一位。
4.时序图:
5.步骤:
6.代码:
smg.v
module smg
#( parameter show_number = 14'd9999 )
(
input wire clk,
input wire rst_n,
output reg qw, //用于共阳极数码管控制数码管的开关(千位)
output reg bw, //用于共阳极数码管控制数码管的开关(百位)
output reg sw, //用于共阳极数码管控制数码管的开关(十位)
output reg gw, //用于共阳极数码管控制数码管的开关(个位)
output reg [7:0] smg //映射到真实引脚中
);
parameter show_zero = 8'b11000000;
parameter show_one = 8'b11111001;
parameter show_two = 8'b10100100;
parameter show_three = 8'b10110000;
parameter show_four = 8'b10011001;
parameter show_five = 8'b10010010;
parameter show_six = 8'b10000010;
parameter show_seven = 8'b11111000;
parameter show_eight = 8'b10000000;
parameter show_nine = 8'b10010000;
reg [25:0] cnt;
reg [13:0] counter; //数码管计数值
reg [3:0] qw_value; //数码管千位的值
reg [3:0] bw_value; //数码管百位的值
reg [3:0] sw_value; //数码管十位的值
reg [3:0] gw_value; //数码管个位的值
reg [1:0] scan_ws; //数码管扫描位数序列号(0 个位 1 百位 2 十位 3 千位)
reg [3:0] scan_value; //单个位扫描值
/*
*计数器(时基20ns 50MHz)
*/
always @ (posedge clk or negedge rst_n) begin
if(!rst_n)
cnt <= 26'd0;
else begin
if(cnt < 26'd50000000)
cnt <= cnt + 1'b1;
else
cnt <= 26'd0;
end
end
/*
*定时器(1s),用于数码管显示
*/
always @ (posedge clk or negedge rst_n) begin
if(!rst_n)
counter <= 14'd0;
else if(cnt == 26'd50000000) begin
if(counter < 14'd9999)
counter <= counter +1'b1;
else
counter <= 14'd0;
end
end
/*
*选择打开的数码管
*/
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
qw <= 1'b1;
bw <= 1'b1;
sw <= 1'b1;
gw <= 1'b1;
scan_value <= 4'd0;
end
else if(!(cnt % 26'd200000)) begin //4ms
bw <= 1'b1; //全关(因为程序执行中会打开部分数码管,每次单位数码管扫描前先关闭所有数码管)
sw <= 1'b1;
gw <= 1'b1;
qw <= 1'b1;
case(scan_ws) //决定打开哪个数码管
2'b00 : begin
scan_value <= gw_value;
gw <= 1'b0;
end
2'b01 : begin
scan_value <= sw_value;
sw <= 1'b0;
end
2'b10 : begin
scan_value <= bw_value;
bw <= 1'b0;
end
2'b11 : begin
scan_value <= qw_value;
qw <= 1'b0;
end
default : ;
endcase
end
end
/*
*向数码管写入数据
*/
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
smg <= show_zero;
end
else begin
case(scan_value)
4'd0 : smg <= show_zero;
4'd1 : smg <= show_one;
4'd2 : smg <= show_two;
4'd3 : smg <= show_three;
4'd4 : smg <= show_four;
4'd5 : smg <= show_five;
4'd6 : smg <= show_six;
4'd7 : smg <= show_seven;
4'd8 : smg <= show_eight;
4'd9 : smg <= show_nine;
default : ;
endcase
end
end
/*
*扫描位号赋值
*/
always @ (posedge clk or negedge rst_n) begin
if(!rst_n)
scan_ws <= 2'b00;
else if(!(cnt % 26'd200000)) begin //到达刷新时间
if(scan_ws == 2'b11)
scan_ws <= 2'b00;
else
scan_ws <= 2'b01 + scan_ws;
end
else
scan_ws <= scan_ws ;
end
/*
*向扫描值千百十个位赋值
*/
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
qw_value <= 4'd0;
bw_value <= 4'd0;
sw_value <= 4'd0;
gw_value <= 4'd0;
end
else begin
qw_value <= show_number/10'd1000;
bw_value <= show_number/7'd100%4'd10;
sw_value <= show_number/4'd10%4'd10;
gw_value <= show_number%4'd10;
end
end
endmodule
top_smg.v
/*
*顶层模块
*/
module top_smg
(
input wire clk,
input wire rst_n,
output wire qw,
output wire bw,
output wire sw,
output wire gw,
output wire [7:0] smg
);
/*
*实例化
*/
smg
#(.show_number (14'd1234) )
smg_inst
(
.clk (clk ) ,
.rst_n (rst_n) ,
.qw (qw ) ,
.bw (bw ) ,
.sw (sw ) ,
.gw (gw ) ,
.smg (smg )
);
endmodule