2.数码管篇
2.1 静态数码管显示
1. 实现8个数码管从0-F循环显示
2. 拨码开关控制数码管的显示
利用拨码开关控制8个数码管的显示,拨动SW1,显示1; 关闭SW1,打开SW2,显示2...依此类推,拨动SW8,显示8。
工程下载:seg7_control.zip
代码如下:
module seg7_ctr(
sw ,
seg_cs_n ,
seg_db
);
input [7:0] sw; // 8个拨码开关,控制数码管显示的值
output [7:0] seg_cs_n; // 位选信号,低电平有效
output [7:0] seg_db; // 段选信号
// 定义寄存器
reg [7:0] seg_db;
/******************共阳数码管的编码编码**********************
0 0xc0 1 0xf9 2 0xa4 3 0xb0
4 0x99 5 0x92 6 0x82 7 0xf8
8 0x80 9 0x90 A 0x88 b 0x83
c 0xc6 d 0xa1 E 0x86 F 0x8e
**********************************************************/
always @(sw)
begin
case(sw)
8'b0111_1111: seg_db <= 8'hf9; // 1
8'b1011_1111: seg_db <= 8'ha4; // 2
8'b1101_1111: seg_db <= 8'hb0; // 3
8'b1110_1111: seg_db <= 8'h99; // 4
8'b1111_0111: seg_db <= 8'h92; // 5
8'b1111_1011: seg_db <= 8'h82; // 6
8'b1111_1101: seg_db <= 8'h90; // 7
8'b1111_1110: seg_db <= 8'h80; // 8
default: seg_db <= 8'hc0; //其他情况显示0
endcase
end
assign seg_cs_n = 8'b0000_0000; // 8个数码管均点亮
endmodule
2.2 数码管滚动显示
实现8个数码管的滚动显示,即第1个显示1,时间1s,然后关闭;接着然后第2个显示2,时间1s,关闭...,一直到最后一个显示8,关闭后返回显示第一个数码管。工程下载:seg7_move.zip
代码如下:
module seg7_move(
sys_clk ,
sys_rst_n ,
seg_cs_n ,
seg_db
);
input sys_clk; // 系统时钟,50MHz
input sys_rst_n; // 复位信号,低电平有效
output [7:0] seg_cs_n; // 位选信号,低电平有效
output [7:0] seg_db; // 段选信号
// 定义寄存器
reg [25:0] cnt; // 计数1s
reg [7:0] seg_cs_n; // 位选寄存器
reg [7:0] seg_db; // 段选寄存器
reg [2:0] disp_data; // 计数寄存器,以改变位选信号
/******************共阳数码管的编码编码**********************
0 0xc0 1 0xf9 2 0xa4 3 0xb0
4 0x99 5 0x92 6 0x82 7 0xf8
8 0x80 9 0x90 A 0x88 b 0x83
c 0xc6 d 0xa1 E 0x86 F 0x8e
**********************************************************/
parameter seg0 = 8'hc0,
seg1 = 8'hf9,
seg2 = 8'ha4,
seg3 = 8'hb0,
seg4 = 8'h99,
seg5 = 8'h92,
seg6 = 8'h82,
seg7 = 8'hf8,
seg8 = 8'h80,
seg9 = 8'h90,
sega = 8'h88,
segb = 8'h83,
segc = 8'hc6,
segd = 8'ha1,
sege = 8'h86,
segf = 8'h8e;
//-----------------计数 1 s---------------------------
always @(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
cnt <= 26'd0;
else if(26'd49_999_999 == cnt)
cnt <= 26'd0;
else
cnt <= cnt + 1'b1;
end
//------------------改变寄存器的值-----------------------
always @(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
disp_data <= 3'd0;
else if(26'd49_999_999 == cnt) // 间隔1一次s,改变
disp_data <= disp_data +1'b1;
end
//-----------------改变位选信号-------------------------
always @(disp_data)
begin
case(disp_data)
3'b000: seg_cs_n <= 8'b0111_1111;
3'b001: seg_cs_n <= 8'b1011_1111;
3'b010: seg_cs_n <= 8'b1101_1111;
3'b011: seg_cs_n <= 8'b1110_1111;
3'b100: seg_cs_n <= 8'b1111_0111;
3'b101: seg_cs_n <= 8'b1111_1011;
3'b110: seg_cs_n <= 8'b1111_1101;
3'b111: seg_cs_n <= 8'b1111_1110;
default:seg_cs_n <= 8'b1111_1111;
endcase
end
//----------------改变数码管的显示值---------------------------------
always @(disp_data) // disp_data发生改变,改变显示的值
begin
case(disp_data)
4'h0: seg_db <= seg1;
4'h1: seg_db <= seg2;
4'h2: seg_db <= seg3;
4'h3: seg_db <= seg4;
4'h4: seg_db <= seg5;
4'h5: seg_db <= seg6;
4'h6: seg_db <= seg7;
4'h7: seg_db <= seg8;
default: ;
endcase
end
endmodule
2.3 数码管动态显示
1. 实现数码管动态显示“I LOVE U”。工程下载:seg7_static.zip
代码:
module seg7_static(
sys_clk ,
sys_rst_n ,
seg_cs_n ,
seg_db
);
input sys_clk; // 系统时钟,50MHz
input sys_rst_n; // 复位信号,低电平有效
output [7:0] seg_cs_n; // 位选信号,低电平有效
output [7:0] seg_db; // 段选信号
reg [7:0] seg_cs_n; // 片选寄存器
reg [7:0] seg_db; // 位选寄存器
reg [15:0] cnt; // 计数存储器,计数约1.28 ms
reg [2:0] disp_data; // 计数寄存器,改变位选信号
//-------------------设定扫描频率-------------------------------
always @(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
cnt <= 16'd0;
else
cnt <= cnt + 1'b1;
end
//--------------------改变数码管显示值-----------------------------
always @(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
disp_data <= 3'd0;
else if(16'hffff == cnt)
begin
if(3'd7 == disp_data)
disp_data <= 3'd0;
else
disp_data <= disp_data + 1'b1;
end
end
//--------------------改变位选信号------------------------------
always @(disp_data)
begin
case(disp_data)
3'b000: seg_cs_n <= 8'b0111_1111; //第8个数码管
3'b001: seg_cs_n <= 8'b1011_1111; //第7个数码管
3'b010: seg_cs_n <= 8'b1101_1111;
3'b011: seg_cs_n <= 8'b1110_1111;
3'b100: seg_cs_n <= 8'b1111_0111;
3'b101: seg_cs_n <= 8'b1111_1011;
3'b110: seg_cs_n <= 8'b1111_1101; //第3个数码管
3'b111: seg_cs_n <= 8'b1111_1110; //第2个数码管
default:seg_cs_n <= 8'b1111_1111; //第1个数码管
endcase
end
/******************共阳数码管的编码编码**********************
0 0xc0 1 0xf9 2 0xa4 3 0xb0
4 0x99 5 0x92 6 0x82 7 0xf8
8 0x80 9 0x90 A 0x88 b 0x83
c 0xc6 d 0xa1 E 0x86 F 0x8e
**********************************************************/
always @(disp_data) // 当disp_data发生改变,数码管的值改变
begin
case(disp_data)
4'h0: seg_db <= 8'hf9; // 显示1
4'h1: seg_db <= 8'hff; // 不显示
4'h2: seg_db <= 8'hc7; // 显示L
4'h3: seg_db <= 8'hc0; // 显示0
4'h4: seg_db <= 8'hc1; // 显示U
4'h5: seg_db <= 8'h86; // 显示E
4'h6: seg_db <= 8'hff; // 不显示
4'h7: seg_db <= 8'hc1; // 显示U
default: ;
endcase
end
endmodule
2. 两个数码管显示模为60的加法计数器。计数器从0开始计数,计数到59后清零,重头开始计数。工程下载:seg7_counter.zip
代码如下:
module seg7_counter(
sys_clk ,
sys_rst_n ,
seg_cs_n ,
seg_db
);
input sys_clk; // 系统时钟,50MHz
input sys_rst_n; // 复位信号,低电平有效
output [1:0] seg_cs_n; // 位选信号,低电平有效
output [7:0] seg_db; // 段选信号
reg [7:0] seg_db; // 段选寄存器
reg [15:0] scan_cnt; // 扫描计数器,扫描频率1Khz
reg [25:0] d_cnt; // 计数器,计数1 s
reg [7:0] disp_data; // 寄存器,存储显示的数据
reg disp_sel; // 在2位数码管中选择
reg [3:0] shi; // 计数器十位
reg [3:0] ge; // 计数器个位
/******************共阳数码管的编码编码**********************
0 0xc0 1 0xf9 2 0xa4 3 0xb0
4 0x99 5 0x92 6 0x82 7 0xf8
8 0x80 9 0x90 A 0x88 b 0x83
c 0xc6 d 0xa1 E 0x86 F 0x8e
**********************************************************/
parameter seg0 = 8'hc0,
seg1 = 8'hf9,
seg2 = 8'ha4,
seg3 = 8'hb0,
seg4 = 8'h99,
seg5 = 8'h92,
seg6 = 8'h82,
seg7 = 8'hf8,
seg8 = 8'h80,
seg9 = 8'h90,
sega = 8'h88,
segb = 8'h83,
segc = 8'hc6,
segd = 8'ha1,
sege = 8'h86,
segf = 8'h8e;
//-------------------扫描频率1 Khz------------------------
always @(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
scan_cnt <= 16'd0;
else
begin
if(16'd49_999 == scan_cnt)
scan_cnt <= 16'd0;
else
scan_cnt <= scan_cnt +1'b1;
end
end
//-------------------控制寄存器的计数------------------------
always @(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
disp_sel <= 1'b0;
else
begin
if(16'd49_999 == scan_cnt)
disp_sel <= ~disp_sel;
else
disp_sel <= disp_sel;
end
end
assign seg_cs_n = (disp_sel == 1'b1)?2'b01:2'b10;
//----------------计数 1 s---------------------------
always @(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
d_cnt <= 26'd0;
else
begin
if(26'd49_999_999 == d_cnt)
d_cnt <= 26'd0;
else
d_cnt <= d_cnt + 1'b1;
end
end
//----------------60 S 计数器------------------------------
always @(posedge sys_clk or negedge sys_rst_n)
begin
if(!sys_rst_n)
begin
shi <= 4'd0;
ge <= 4'd0;
end
else
begin
if(26'd49_999_999 == d_cnt )
begin
if(4'd9 == ge)
begin
if(4'd5 == shi)
begin
shi <= 4'd0;
ge <= 4'd0;
end
else
begin
shi <= shi + 4'd1;
ge <= 4'd0;
end
end
else
ge = ge + 4'b1;
end
end
end
//-----------------数码管显示数据的选择--------------------
always @(disp_sel)
begin
case(disp_sel)
1'b0: disp_data <= ge;
1'b1: disp_data <= shi;
default: ;
endcase
end
//-------------------数据译码--------------------------------
always @(disp_data)
begin
case(disp_data)
4'h0: seg_db <= seg0;
4'h1: seg_db <= seg1;
4'h2: seg_db <= seg2;
4'h3: seg_db <= seg3;
4'h4: seg_db <= seg4;
4'h5: seg_db <= seg5;
4'h6: seg_db <= seg6;
4'h7: seg_db <= seg7;
4'h8: seg_db <= seg8;
4'h9: seg_db <= seg9;
default: ;
endcase
end
endmodule