本设计目的是在FPGA中设计一个模60计数器,并通过数码管动态显示出来。
一. 整体模块化设计
该工程包含顶层模块counter60以及底层模块accum和Data_show。
accum模块实现分频器以及计数器的功能;Data_show模块实现数据的数码管的动态显示。
整体工程模块图如下:
二.数码管硬件部分电路
通过原理图可知,位选信号由AN0,AN1,AN2,AN3控制,段选信号由CG,CC,CH,CD,CE,CA,CF,CB控制,由此可知为八段数码管。
由下图可知,数码管段选信号以及位选信号皆为低电平有效。
以下为四位位选控制信号和八段段选控制信号对应的FPGA引脚:
实现数码管的动态显示,四位数码管的段选信号同时控制,轮流点亮位选信号。
由于余晖效应,加上人眼的视觉暂留效果,我们看四位数码管时四个数码管是同时亮的。
动态显示的优点是节省IO资源。
三.分析设计代码实现
1.顶层模块counter60
在其中实现对底层模块accum和Data_show的例化。
module counter60(
input wire clk_24m ,
input wire rst_n ,
output wire [7:0] seg ,
output wire [3:0] dig
);
wire [7:0] num;
accum accum_inst
(
.clk_24m (clk_24m ),
.rst_n (rst_n ),
.num (num )
);
Data_show Data_show_inst
(
.clk_24m (clk_24m ),
.rst_n (rst_n ),
.num (num ),
.seg (seg ),
.dig (dig )
);
endmodule
2.底层模块accum,分频器和计数器
分频器产生频率为1HZ的时钟clk1,对计数功能进行描述。
核心部分代码如下:
initial num = 8'b1; //置初值为1,实现1-60的计数
always@( posedge clk_24m or negedge rst_n )
if( rst_n == 1'b0 )
cnt <= 24'd0;
else if( cnt == 25'd12_000_000-1'b1 )
begin
cnt <= 24'd0;
clk1 <= ~clk1;
end
else
begin
cnt <= cnt + 1'b1;
clk1 <= clk1;
end
always@( posedge clk1 or negedge rst_n ) //对计数功能进行描述
if( rst_n == 1'b0 )
num <= 8'd1;
else if( num[3:0] == 4'd9 )
begin
num[3:0] <= 4'd0;
num[7:4] <= num[7:4] + 1'b1;
end
else if( num[7:4] == 4'd6 && num[3:0] == 4'd0 )
begin
num[3:0] <= 4'd1;
num[7:4] <= 4'd0;
end
else
num[3:0] <= num[3:0] + 1'b1;
3.数码管动态显示模块Data_show
为实现数码管的动态显示,通过动态扫描的方法处理数码管的位选信号。
定义信号cnt_w,产生0.01秒的标志信号。通过对其最高位cnt_w[17]的0和1变换实现位选信号dig[1]以及dig[0]的扫描显示,轮流点亮后两位,但由于余辉效应以及人眼的视觉残留,我们看到的是数码管后两位一直保持亮起。
核心代码如下:
reg [17:0] cnt_w ;
reg [3:0] Result ;
parameter CNT_W_MAX = 18'd240_000;
always@(posedge clk_24m or negedge rst_n)
begin
if(rst_n == 1'b0 )
cnt_w <= 18'd0;
else if(cnt_w == CNT_W_MAX)
cnt_w <= 18'd0;
else
cnt_w <= cnt_w + 1;
end
always@(posedge clk_24m or negedge rst_n)
if( rst_n == 1'b0 )
dig <= 4'b1111;
else
begin
case( cnt_w[17] ) //动态扫描数码管后两位 实现动态显示
1'b0:dig <= 4'b1110;
1'b1:dig <= 4'b1101;
endcase
end
always@(posedge clk_24m or negedge rst_n)
begin
if( rst_n == 1'b0 )
Result <= 4'd0;
else
begin
case( cnt_w[17] )
1'b0:Result <= num[3:0];
1'b1:Result <= num[7:4];
endcase
end
end
always@(*)
begin
case ( Result )
4'd0:seg <= 8'hc0;
4'd1:seg <= 8'hf9;
4'd2:seg <= 8'ha4;
4'd3:seg <= 8'hb0;
4'd4:seg <= 8'h99;
4'd5:seg <= 8'h92;
4'd6:seg <= 8'h82;
4'd7:seg <= 8'hf8;
4'd8:seg <= 8'h80;
4'd9:seg <= 8'h90;
default:seg <= 8'hc0;
endcase
end
四.运行结果展示
成功实现1-60的计数功能,计数器模为60。