写在前面
本人也是初学者,刚开始学FPGA开发半个月左右,代码和设计有诸多不好的地方,各位大神口下留情。
分享给初学者,希望能一起进步。
项目简介
基于Xilinx7系FPGA,使用Verilog语言设计一个电子表,并使用8段数码管显示,要求时间为24h格式。
设计思路
首先,分析电子表的显示要素有哪些,我们也不是做多高大上的一个东西,就是一个基础的能计时24h的电子表,我们需要显示的内容主要就是时、分、秒。
具体怎么在8段数码管进行显示,可以参考下图(略丑)

这里的数码管一共有8个,我这里选择用sel[7:6]显示小时(H),sel[5]和sel[2]显示途中符号(没有冒号将就用了),sel[4:3]显示分钟(min),sel[1:0]显示秒(s)。
至于数码管的显示原理我就不讲了,网上一大堆都是的,我这里的数码管采用的是共阳极的连接方式。
另外需要说明的是,因为我买的是现成的开发板,所以个模块的集成度比较高,这里的数码管显示用到了74HC595芯片,其工作原理可以参考这篇文章。
链接: link.
该芯片的作用就是移位寄存器,通过移位的方式,节省FPGA的管脚。
接下来就直接上程序了。采用模块化设计。这里用到了三个模块,分别是数码管显示模块,74HC595驱动模块,时间(时分秒)生成模块。
程序设计
时钟生成模块
这里需要注意的一个地方,通常我们见到的时间都是十进制的,但是我们用计数器计数之后输出的数据通常为16进制数。
十进制数显示的范围为0~9;
十六进制数显示的范围为0~f;我们需要的数只有0到9,所以当数超过9时对于我们的电子表来说是多余的。因此我们需要对十六进制数进行转换,让输出的数(也就是数码管上显示的数)为十进制。
其转换原理为:
对应十进制数大于9时,进行加6操作;
对应十进制数大于19时,进行加12操作;
对应十进制数大约29时,进行加18操作;
以此类推···
其转换的核心思想是将二进制数转化为BCD码,我这里以图片说明。

可以看到,转换后的BCD码输出就跟我们需要的十进制输出一致。至于这里为什么要转换为BCD码,就是为了方便在数码管上显示时间对应的十进制输出。具体请看联调代码。
// 时钟生成模块
// An highlighted block
`timescale 1ns / 1ps
//////////////////////////////////////////////
//code by 清月
//time:2021.09.14
// 时钟信息的产生,时,分,秒
//////////////////////////////////////////////
module dzb_cnt(
clk,
ret,
h_out,
m_out,
s_out
);
input clk;
input ret;
output reg[7:0]h_out;//小时输出
output reg[7:0]m_out;//分钟输出
output reg[7:0]s_out;//秒输出
parameter MCNT = 50000000;
//基本时间单位计数(单位S)
reg [31:0]div_cnt;
always@(posedge clk or negedge ret)
if(!ret)
div_cnt<= 0;
else if(div_cnt>=MCNT-1)
div_cnt<= 0;
else
div_cnt<= div_cnt+1'd1;
// 时间单位计数,1min = 60s
reg [7:0]s_cnt;
reg [7:0]r_s_out;//寄存s
always@(posedge clk or negedge ret)
if(!ret)begin
s_cnt <= 0;
r_s_out <= 0;
end
else if(s_cnt > 8'd59)
s_cnt <= 0;
else if(div_cnt == MCNT-1)begin
s_cnt <= s_cnt +1'd1;
r_s_out <= s_cnt+1'd1;
end else
r_s_out <= r_s_out;
always@(posedge clk)
if(r_s_out > 8'd09 && r_s_out<8'd20)begin
s_out <= r_s_out + 8'd6;end
else if(r_s_out>8'd19 && r_s_out<8'd30)begin
s_out <= r_s_out + 8'd12;end
else if(r_s_out>8'd29 && r_s_out<8'd40)begin
s_out <= r_s_out + 8'd18;end
else if(r_s_out>8'd39 &&r_s_out<8'd50)begin
s_out <= r_s_out + 8'd24;end
else if(r_s_out>8'd49 && r_s_out<8'd60)begin
s_out <= r_s_out + 8'd30;end
else
s_out <= r_s_out;
//时间单位计数,1h = 60min
reg [7:0]m_cnt;
reg [7:0]r_m_out;
always@(posedge clk or negedge ret)
if(!ret)begin
m_cnt <= 0;
r_m_out <= 0;
end
else if(m_cnt > 8'd59)
m_cnt <= 0;
else if(s_cnt > 8'd59)begin
m_cnt <= m_cnt +1'd1;
r_m_out <= m_cnt+1'd1;
end else
r_m_out <= r_m_out;
always@(posedge clk)
if(r_m_out > 8'h09 && r_m_out<8'd20)begin
m_out <= r_m_out + 8'd6;end
else if(r_m_out>8'h13 && r_m_out<8'd30) begin

这篇博客介绍了作者作为初学者如何基于Xilinx7系列FPGA,使用Verilog语言设计一个24小时格式的电子表。设计包括时钟生成、数码管显示和74HC595驱动模块。通过74HC595移位寄存器节省FPGA资源,数码管采用共阳极连接方式,时钟生成模块中涉及了十六进制到十进制的转换,确保数码管正确显示时间。
最低0.47元/天 解锁文章
1157

被折叠的 条评论
为什么被折叠?



