FPGA-使用RTC时钟芯片进行时钟读取(数码管显示)

简介: FPGA-使用RTC时钟芯片进行时钟读取(数码管显示)

做时钟显示如果用单片机做,会产生很大的累积误差,本程序采用时钟芯片PCF8563

一:芯片主要电气特性:

1)大工作电压范围:1.0~5.5V

2)400KHz 的 I2C 总线接口(VDD=1.8~5.5V 时)。

时钟频率最大400KH

3)i2C 总线从地址:读,0A3H;写,0A2H .

二:管脚

image.png

top.v:


moduletop(ext_clk_25m,ext_rst_n,dtube_cs_n,dtube_data,rtc_iic_sck,rtc_iic_sda    );
inputext_clk_25m;
inputext_rst_n;
output [3:0] dtube_cs_n;
output [6:0] dtube_data;
outputrtc_iic_sck;
inoutrtc_iic_sda;
wire [7:0]rtc_secd,rtc_mini,rtc_hour;
wireiicrd_req;
wireiicwr_req;
wire [7:0] iic_addr;
wire [7:0] iic_rddb;
wire [7:0] iic_wrdb;
wireiic_ack;
rtc_controlleruut_rtc(
    .clk(ext_clk_25m),
    .rst_n(ext_rst_n),
    .iicwr_req(iicwr_req),
    .iicrd_req(iicrd_req),
    .iic_addr(iic_addr),
    .iic_wrdb(iic_wrdb),
    .iic_rddb(iic_rddb),
    .iic_ack(iic_ack),
    .rtc_hour(rtc_hour),
    .rtc_mini(rtc_mini),
    .rtc_secd(rtc_secd)
    );
iic_controlleruut_iic(
    .clk(ext_clk_25m),
    .rst_n(ext_rst_n),
    .iicwr_req(iicwr_req),
    .iicrd_req(iicrd_req),
    .iic_addr(iic_addr),
    .iic_wrdb(iic_wrdb),
    .iic_rddb(iic_rddb),
    .iic_ack(iic_ack),
    .scl(rtc_iic_sck),
    .sda(rtc_iic_sda)
    );
seg_4uut_seg(
    .clk(ext_clk_25m),
    .rst_n(ext_rst_n),
    .dis_data({rtc_mini,rtc_secd}),
    .dtube_cs_n(dtube_cs_n),
    .dtube_data(dtube_data)
        );
endmodule

iic.v:


`timescale1ns/1psmoduleiic_controller(clk,rst_n,iicwr_req,iicrd_req,iic_addr,iic_wrdb,iic_rddb,iic_ack,scl,sda    );
inputclk;              //时钟信号inputrst_n;            //复位信号inputiicwr_req;        //写请求信号inputiicrd_req;        //读请求信号input [7:0]iic_addr;    //读入地址寄存器input [7:0]iic_wrdb;    //写入数据寄存器outputreg[7:0]iic_rddb;//读入数据寄存器outputiic_ack;         //读写应答信号outputregscl;         //配置时钟信号inoutsda;              //配置数据信号parameterI2C_ILDE=4'D0,  //起始状态    I2C_START=4'D1,  //起始信号    //写信号I2C_WR_IDADDR=4'D2,  //(写指令)    I2C_WR_ACK1=4'D3,  //应答信号    I2C_WR_REGADDR=4'D4,  //驱动写地址  I2C_WR_ACK2=4'D5,  //应答信号    I2C_WR_DATA=4'D6,  //写数据      I2C_WR_ACK3=4'D7,  //应答信号    //读信号I2C_RS_START=4'D8,  //复位起始信号I2C_RD_IDADDR=4'D9,  //(读信号)    I2C_RD_ACK=4'D10, //应答信号    I2C_RD_DATA=4'D11, //读数据I2C_RD_NPACK=4'D12, //应答信号I2C_STOP=4'D13; //停止传输信号parameterDEVICE_WRADD=8'HA2,  //写地址DEVICE_RDADD=8'HA3;  //读地址parameterI2C_FREQ=250,     //时钟频率SEND_BIT=8;       //发送数据位数//-------------------------------------------------reg [7:0]cnt;//scl计数寄存器reg [2:0]byte_cnt;//数据位寄存器reg [3:0]state_c,state_n;//状态寄存器regsdar;         //sda输出寄存器regsdalink;      //sda方向控制器0-input1-outputassignscl_hs=(cnt==1'b0+1'b1);
assignscl_hc=(cnt==(I2C_FREQ>>2));
assignscl_ls=(cnt==(I2C_FREQ>>1));
assignscl_lc=(cnt==(I2C_FREQ>>2)*3);
//iic时钟信号产生逻辑always@(posedgeclkornegedgerst_n)beginif(rst_n==1'b0)begincnt<=1'b0;endelseif(cnt==I2C_FREQ-1'b1)begincnt<=1'b0;endelsebegincnt<=cnt+1'b1;endendalways@(posedgeclkornegedgerst_n)beginif(rst_n==1'b0)beginscl<=1'b0;endelseif(cnt>=1'b0 &&cnt <= (I2C_FREQ>>1)-1'b1)beginscl<=1'b1;endelsebeginscl<=1'b0;endend//iic状态机控制信号always@(posedgeclkornegedgerst_n)beginif(rst_n==1'b0)beginstate_c<=I2C_ILDE;
endelsebeginstate_c<=state_n;
endendalways@(*)begincase(state_c)
I2C_ILDE:
if((iicwr_req==1'b1||iicrd_req==1'b1)&&scl_hs==1'b1)beginstate_n<=I2C_START;
endelsebeginstate_n<=I2C_ILDE;
endI2C_START:
if(scl_ls==1'b1)beginstate_n<=I2C_WR_IDADDR;
endelsebeginstate_n<=I2C_START;
endI2C_WR_IDADDR:
if(scl_lc==1'b1&&byte_cnt==3'd0)beginstate_n<=I2C_WR_ACK1;
endelsebeginstate_n<=I2C_WR_IDADDR;
endI2C_WR_ACK1:
if(scl_ls==1'b1&&byte_cnt==SEND_BIT-1'b1)beginstate_n<=I2C_WR_REGADDR;
endelsebeginstate_n<=I2C_WR_ACK1;
endI2C_WR_REGADDR:
if(scl_lc==1'b1&&byte_cnt==3'd0)beginstate_n<=I2C_WR_ACK2;
endelsebeginstate_n<=I2C_WR_REGADDR;
endI2C_WR_ACK2:
if(scl_ls==1'b1&&(byte_cnt==SEND_BIT-1'b1)&&iicwr_req)beginstate_n<=I2C_WR_DATA;
endelseif(scl_ls==1'b1&&(byte_cnt==SEND_BIT-1'b1)&&iicrd_req)beginstate_n<=I2C_RS_START;
endelsebeginstate_n<=I2C_WR_ACK2;
endI2C_WR_DATA:
if(scl_lc==1'b1&&(byte_cnt==3'd0))beginstate_n<=I2C_WR_ACK3;
endelsebeginstate_n<=I2C_WR_DATA;
endI2C_WR_ACK3:
if(scl_ls==1'b1&&byte_cnt==SEND_BIT-1'b1)beginstate_n<=I2C_STOP;
endelsebeginstate_n<=I2C_WR_ACK3;
endI2C_RS_START:
if(scl_ls==1'b1)beginstate_n<=I2C_RD_IDADDR;
endelsebeginstate_n<=I2C_RS_START;
endI2C_RD_IDADDR:
if(scl_lc==1'b1&&byte_cnt==3'd0)beginstate_n<=I2C_RD_ACK;
endelsebeginstate_n<=I2C_RD_IDADDR;
endI2C_RD_ACK:
if(scl_ls==1'b1&&(byte_cnt==SEND_BIT-1'b1))beginstate_n<=I2C_RD_DATA;
endelsebeginstate_n<=I2C_RD_ACK;
endI2C_RD_DATA:
if(scl_ls==1'b1&&byte_cnt==SEND_BIT-1'b1)beginstate_n<=I2C_RD_NPACK;
endelsebeginstate_n<=I2C_RD_DATA;
endI2C_RD_NPACK:
if(scl_ls==1'b1&&SEND_BIT-2'd2)beginstate_n<=I2C_STOP;
endelsebeginstate_n<=I2C_RD_NPACK;
endI2C_STOP:
if(scl_ls==1'b1)beginstate_n<=I2C_ILDE;
endelsebeginstate_n<=I2C_STOP;
enddefault:state_n<=I2C_ILDE;
endcaseend//数据位寄存器控制always@(posedgeclkornegedgerst_n)beginif(rst_n==1'b0)beginbyte_cnt<=3'd0;endelsebegincase(state_c)
I2C_ILDE:
byte_cnt<=SEND_BIT-1'b1;I2C_WR_IDADDR,I2C_WR_REGADDR,I2C_WR_DATA,
I2C_RD_IDADDR,I2C_RD_DATA:
if(scl_hs==1'b1)beginbyte_cnt<=byte_cnt-1'b1;endI2C_WR_ACK1,I2C_WR_ACK2,I2C_WR_ACK3:
if(scl_lc==1'b1)beginbyte_cnt<=SEND_BIT-1'b1;endI2C_RD_ACK:
if(scl_ls==1'b1)beginbyte_cnt<=SEND_BIT-1'b1;endI2C_RD_NPACK:
if(scl_lc==1'b1)beginbyte_cnt<=byte_cnt-1'b1;enddefault: ;
endcaseendend//数据输入输出控制always@(posedgeclkornegedgerst_n)beginif(rst_n==1'b0)beginsdar<=1'b1;sdalink<=1'b1;iic_rddb<=8'd0;endelsebegincase(state_c)
I2C_ILDE:
beginsdar<=1'b1;sdalink<=1'b1;endI2C_START:
beginif(scl_hc==1'b1)beginsdar<=1'b0;endendI2C_WR_IDADDR:
beginif(scl_lc==1'b1)beginsdar<=DEVICE_WRADD[byte_cnt];
endendI2C_WR_ACK1:
beginif(scl_lc==1'b1)beginsdar<=1'b1;sdalink<=1'b0;endendI2C_WR_REGADDR:
beginif(scl_lc==1'b1)beginsdar<=iic_addr[byte_cnt];
sdalink<=1'b1;endendI2C_WR_ACK2:
beginif(scl_lc==1'b1)beginsdar<=1'b1;sdalink<=1'b0;endendI2C_WR_DATA:
beginif(scl_lc==1'b1)beginsdar<=iic_wrdb[byte_cnt];
sdalink<=1'b1;endendI2C_WR_ACK3:
beginif(scl_lc==1'b1)beginsdar<=1'b1;sdalink<=1'b0;endendI2C_RS_START:
beginif(scl_hc==1'b1)beginsdar<=1'b0;endelseif(scl_lc==1'b1)beginsdar<=1'b1;sdalink<=1'b1;endendI2C_RD_IDADDR:
beginif(scl_lc==1'b1)beginsdar<=DEVICE_RDADD[byte_cnt];
endendI2C_RD_ACK: 
beginif(scl_lc==1'b1&&byte_cnt==SEND_BIT-1'b1)beginsdalink<=1'b0;endendI2C_RD_DATA:   
beginif(scl_hc==1'b1)beginiic_rddb[byte_cnt+1'b1]<=sda;sdar<=1'b1;endendI2C_RD_NPACK:  
beginif(scl_lc==1'b1)beginsdalink<=1'b1;sdar<=1'b0;endendI2C_STOP:  
beginif(scl_lc==1'b1)beginsdalink<=1'b1;sdar<=1'b0;endelseif(scl_hc==1'b1)beginsdar<=1'b1;endenddefault: ;
endcaseendendassignsda=sdalink?sdar:1'bz;assigniic_ack=(state_n==I2C_STOP)&&scl_hs==1'b1;endmodule

rtc_controller.v:


`timescale1ns/1psmodulertc_controller(clk,rst_n,iicwr_req,iicrd_req,iic_addr,iic_wrdb,iic_rddb,iic_ack,rtc_hour,rtc_mini,rtc_secd    );
inputclk;
inputrst_n;
outputregiicrd_req;
outputregiicwr_req;
outputreg[7:0]iic_addr;
outputreg[7:0]iic_wrdb;
input [7:0] iic_rddb;
inputiic_ack;
outputreg[7:0]rtc_hour;
outputreg[7:0]rtc_mini;
outputreg[7:0]rtc_secd;
//--------------------------------------------parameterRTC_IDLE=4'D0,RTC_RD_SECD=4'D1,RTC_WAIT1=4'D2,RTC_RD_MINI=4'D3,RTC_WAIT2=4'D4,RTC_RD_HOUR=4'D5;//--------------------------------------------reg [17:0]cnt;
reg [3:0] state_c,state_n;
//10ms定时器always@(posedgeclkornegedgerst_n)beginif(rst_n==1'b0)begincnt<=1'b0;endelseif(cnt<18'd249_999)begincnt<=cnt+1'b1;endelsebegincnt<=1'b0;endendwiretimer1_10ms=(cnt==18'd49_999);wiretimer2_10ms=(cnt==18'd149_999);wiretimer3_10ms=(cnt==18'd249_999);//状态控制always@(posedgeclkornegedgerst_n)beginif(rst_n==1'b0)beginstate_c<=RTC_IDLE;
endelsebeginstate_c<=state_n;
endendalways@(*)begincase(state_c)
RTC_IDLE:
beginif(timer1_10ms==1'b1)beginstate_n<=RTC_RD_SECD;
endelsebeginstate_n<=RTC_IDLE;
endendRTC_RD_SECD:
beginif(iic_ack==1'b1)beginstate_n<=RTC_WAIT1;
endelsebeginstate_n<=RTC_RD_SECD;
endendRTC_WAIT1:  
beginif(timer2_10ms==1'b1)beginstate_n<=RTC_RD_MINI;
endelsebeginstate_n<=RTC_WAIT1;
endendRTC_RD_MINI:
beginif(iic_ack==1'b1)beginstate_n<=RTC_WAIT2;
endelsebeginstate_n<=RTC_RD_MINI;
endendRTC_WAIT2:  
beginif(timer3_10ms==1'b1)beginstate_n<=RTC_RD_HOUR;
endelsebeginstate_n<=RTC_WAIT2;
endendRTC_RD_HOUR:
beginif(iic_ack==1'b1)beginstate_n<=RTC_IDLE;
endelsebeginstate_n<=RTC_RD_HOUR;
endenddefault:state_n<=RTC_IDLE;
endcaseendalways@(posedgeclkornegedgerst_n)beginif(rst_n==1'b0)beginiicwr_req<=1'b0;iicrd_req<=1'b0;iic_addr<=1'b0;iic_wrdb<=1'b0;endelsebegincase(state_c)
RTC_RD_SECD:
beginiicwr_req<=1'b0;iicrd_req<=1'b1;iic_addr<=8'd2;iic_wrdb<=1'b0;endRTC_RD_MINI:
beginiicwr_req<=1'b0;iicrd_req<=1'b1;iic_addr<=8'd3;iic_wrdb<=1'b0;endRTC_RD_HOUR:
beginiicwr_req<=1'b0;iicrd_req<=1'b1;iic_addr<=8'd4;iic_wrdb<=1'b0;enddefault:
beginiicwr_req<=1'b0;iicrd_req<=1'b0;iic_addr<=1'b0;iic_wrdb<=1'b0;endendcaseendendalways@(posedgeclkornegedgerst_n)beginif(rst_n==1'b0)beginrtc_hour<=1'b0;rtc_mini<=1'b0;rtc_secd<=1'b0;endelsebegincase(state_c)
RTC_RD_SECD:
beginif(iic_ack==1'b1)beginrtc_secd<={1'b0,iic_rddb[6:0]};endelsebeginrtc_secd<=rtc_secd;
endendRTC_RD_MINI:
beginif(iic_ack==1'b1)beginrtc_mini<={1'b0,iic_rddb[6:0]};endelsebeginrtc_mini<=rtc_mini;
endendRTC_RD_HOUR:
beginif(iic_ack==1'b1)beginrtc_hour<={1'b0,iic_rddb[6:0]};endelsebeginrtc_hour<=rtc_hour;
endendendcaseendendendmodule

seg_4.v:


`timescale1ns/1psmoduleseg_4(clk,rst_n,dis_data,dtube_cs_n,dtube_data        );
inputclk;      //时钟信号25MHzinputrst_n;            //复位信号ainput [15:0] dis_data;//outputreg[3:0] dtube_cs_n; //段选数据位outputreg[6:0] dtube_data;//位选数据位reg [3:0]TimeH;         //两位输入高位  [0]
reg [3:0]TimeL;         //两位输入低位  [1]
reg [3:0]TimeH1;        //两位输入高位  [2]
reg [3:0]TimeL1;        //两位输入低位  [3]   
reg [3:0] display_num;  //当前显示数据reg [16:0] div_cnt; //延时计数器计数位always@(posedgeclkornegedgerst_n)beginif(rst_n==1'b0)beginTimeH<=1'b0;    TimeL<=1'b0;    TimeH1<=1'b0;TimeL1<=1'b0;endelsebeginTimeH<=dis_data[7:4];      
TimeL<=dis_data[3:0];aTimeH1<=dis_data[15:12];
TimeL1<=dis_data[11:8];
endendinitialdiv_cnt=0;//赋初值为0//延时计数器模块always@ (posedgeclkornegedgerst_n)
beginif(!rst_n) 
div_cnt<=8'd0;elseif(div_cnt==17'd80000)div_cnt<=8'd0;        elsediv_cnt<=div_cnt+1'b1;end//显示当前的数据模块always@(posedgeclkornegedgerst_n)
beginif(!rst_n) 
display_num<=4'h0;elseif(div_cnt<17'd20000)display_num<=TimeL;
elseif((div_cnt>17'd20000)&(div_cnt <17'd40000))
display_num<=TimeH;
elseif((div_cnt>17'd40000)&(div_cnt < 17'd60000))
display_num<=TimeL1;
elsedisplay_num<=TimeH1;
end//段选数据译码模块(共阴数码管)
always@(*)
beginif(!rst_n) 
dtube_data<=8'h00;elsebegincase(display_num) 
4'h0: dtube_data <= 8'h3f;
4'h1: dtube_data <= 8'h06;
4'h2: dtube_data <= 8'h5b;
4'h3: dtube_data <= 8'h4f;
4'h4: dtube_data <= 8'h66;
4'h5: dtube_data <= 8'h6d;
4'h6: dtube_data <= 8'h7d;
4'h7: dtube_data <= 8'h07;
4'h8: dtube_data <= 8'h7f;
4'h9: dtube_data <= 8'h6f;
default:dtube_data<=8'h00;endcaseendend//位选选译模块always@(posedgeclkornegedgerst_n)  
beginif(!rst_n) 
dtube_cs_n<=4'b1111;elseif(div_cnt<=17'd20000)dtube_cs_n<=4'b1110;elseif((div_cnt>17'd20000)&(div_cnt <=17'd40000))
dtube_cs_n<=4'b1101;elseif((div_cnt>17'd40000)&(div_cnt <=17'd60000))
dtube_cs_n<=4'b1011;elsedtube_cs_n<=4'b0111;endendmodule
目录
相关文章
|
7月前
|
芯片 异构计算
【FPGA】高云FPGA之数字钟实验->HC595驱动数码管(一)
【FPGA】高云FPGA之数字钟实验->HC595驱动数码管
221 2
|
7月前
|
芯片 异构计算
【FPGA】高云FPGA之数字钟实验->HC595驱动数码管(三)
【FPGA】高云FPGA之数字钟实验->HC595驱动数码管
174 4
|
5月前
|
异构计算
FPGA入门(6):数码管静态/动态显示(二)
FPGA入门(6):数码管静态/动态显示(二)
71 10
|
5月前
|
异构计算
FPGA入门(6):数码管静态/动态显示(一)
FPGA入门(6):数码管静态/动态显示
56 0
|
7月前
|
存储 芯片 异构计算
【FPGA】高云FPGA之数字钟实验->HC595驱动数码管(二)
【FPGA】高云FPGA之数字钟实验->HC595驱动数码管
186 4
|
7月前
|
缓存 监控 异构计算
|
机器学习/深度学习 调度 芯片
快速入门数字芯片设计,UCSD ECE111(九)FPGA vs ASIC(一)
快速入门数字芯片设计,UCSD ECE111(九)FPGA vs ASIC
114 0
|
7月前
|
存储 芯片 异构计算
【FPGA原型验证】FPGA 技术:芯片和工具-当今的 FPGA 器件技术_fpga原型版本
【FPGA原型验证】FPGA 技术:芯片和工具-当今的 FPGA 器件技术_fpga原型版本
196 0
|
存储 前端开发 芯片
快速入门数字芯片设计,UCSD ECE111(九)FPGA vs ASIC(三)
快速入门数字芯片设计,UCSD ECE111(九)FPGA vs ASIC(三)
124 0
|
芯片 C++ 异构计算
快速入门数字芯片设计,UCSD ECE111(九)FPGA vs ASIC(二)
快速入门数字芯片设计,UCSD ECE111(九)FPGA vs ASIC(二)
88 0

热门文章

最新文章