一 mGPIO_RTC_Timer.v
module mGPIO_RTC_Timer(
iCLK, //clock from osci
iYearMonDateWeek, //year, month, date, week
iHourMinSecMsec, //hour, minute, second, million second(used for alarm)
iPre_YearMonDateWeek, //preset year, month, date, week
iPre_HourMinSecMsec, //preset hour, minute, second, million second(used for alarm)
iMsecInitCnt, //initial data for million second generate counter
iRTCFredCnt, //frequency divide counter
iRTCIntCtrl, //interrupt control signals
iRTCRegCtrl, //read or write control signals from mGPIO_RTC_interface
oYearMonDateWeek, //year, month, date, week
oHourMinSecMsec, //hour, minute, second, million second(used for alarm)
oPre_YearMonDateWeek, //preset year, month, date, week
oPre_HourMinSecMsec, //preset hour, minute, second, million second(used for alarm)
oMsecInitCnt, //initial data for million second generate counter
oRTCFreDivCnt, //frequency divide counter
oRTCIntCtrl, //interrupt control signals
oTickInt, //interrupt generate when date/hour/min/second changes
oAlarmInt, //interrupt genetate when reach the set time
oTimerWrEnClear //indicate the time has been updated by user, and used to clear the write enable signal
);
///
// I/O ports declaration //
///
input iCLK;
input [31:0] iYearMonDateWeek;
input [31:0] iHourMinSecMsec;
input [31:0] iPre_YearMonDateWeek;
input [31:0] iPre_HourMinSecMsec;
input [31:0] iMsecInitCnt;
input [31:0] iRTCFredCnt;
input [31:0] iRTCIntCtrl;
input [31:0] iRTCRegCtrl;
output [31:0] oYearMonDateWeek;
output [31:0] oHourMinSecMsec;
output [31:0] oPre_YearMonDateWeek;
output [31:0] oPre_HourMinSecMsec;
output [31:0] oMsecInitCnt;
output [31:0] oRTCFreDivCnt;
output [31:0] oRTCIntCtrl;
output oTickInt;
output oAlarmInt;
output oTimerWrEnClear;
///
// parameter declaration //
///
///
// wire & reg declaration //
///
//synchronized signals
wire [31:0] wYYMMDDWW_Sync; //year, month, date, week
wire [31:0] wHHMMSSMs_Sync; //hour, minute, second, million second(used for alarm)
wire [31:0] wPreYYMMDDWW_Sync; //preset year, month, date, week
wire [31:0] wPreHHMMSSMs_Sync; //preset hour, minute, second, million second(used for alarm)
wire [31:0] wMsecInitCnt_Sync; //initial data for million second generate counter
wire [31:0] wRTCFredCnt_Sync; //nfrequency divide counter
wire [31:0] wRTCIntCtrl_Sync; //interrupt control signals
wire [31:0] wRTCRegCtrl_Sync; //read or write control signals
//Time relative registers
reg [9:0] rMillionSec; //0--->999
reg [5:0] rSecond; //0--->59
reg [5:0] rMinute; //0--->59
reg [4:0] rHour; //0--->23
reg [2:0] rWeek; //0--->6
reg [4:0] rDate; //1--->31
reg [3:0] rMonth; //1--->12
reg [11:0] rYear; //0---> ...
reg [9:0] rPreMillionSec; //0--->999
reg [5:0] rPreSecond; //0--->59
reg [5:0] rPreMinute; //0--->59
reg [4:0] rPreHour; //0--->23
reg [2:0] rPreWeek; //0--->6
reg [4:0] rPreDate; //1--->31
reg [3:0] rPreMonth; //1--->12
reg [11:0] rPreYear; //0---> ...
reg [31:0] rMsecInitCnt; //used to set the frequency divide number
reg [31:0] rRTCFreDivCnt; //frequency divide counter
reg [31:0] rIntCtrl; //interrupt control register
//signals in rIntCtrl
wire wTickEn; //tick interrupt enable
wire wAlarmEn; //alarm interrupt enable
wire [1:0] wTickSel; //select the interval between 2 tick interrupt
wire [7:0] wCompMask; //mask some of the registers when compare with the alarm time
//signals in iRTCRegCtrl
wire [18:0] wWrMask; //mask some of the regissters when write the new time by user
wire wIsWrite; //write enable
wire wMatch; //rRTCFreDivCnt == rMsecInitCnt
wire wMillionSec999; //rMillionSec = 999
wire wSecond59; //rSecond = 59
wire wMinute59; //rMinute = 59
wire wHour23; //rHour = 23
wire wWeek6; //rWeek = 6
wire wMonthEnd; //the last date in a month
wire wMonth12; //rMonth = 12
reg rLeapYear; //indicate a leap year
//tick interrupts
reg rTickInt_Second;
reg rTickInt_Min;
reg rTickInt_Hour;
reg rTickInt_Date;
reg rTickInt;
//tick final tick interrupt
reg rAlarmInt;
//signals used to generate alarm interrupt
reg rMillionSec_Equ;
reg rSecond_Equ;
reg rMinute_Equ;
reg rHour_Equ;
reg rWeek_Equ;
reg rDate_Equ;
reg rMonth_Equ;
reg rYear_Equ;
reg [31:0] rRTCFreDivCnt_Next;
reg [9:0] rMillionSec_Next;
reg [5:0] rSecond_Next;
reg [5:0] rMinute_Next;
reg [4:0] rHour_Next;
reg [2:0] rWeek_Next;
reg [4:0] rDate_Next;
reg [3:0] rMonth_Next;
reg [11:0] rYear_Next;
reg rTickInt_Next;
reg rAlarmInt_Next;
//add 2005.01.26
///
// behavior description //
///
//synchronize the input data from PCLK region
mGPIO_RTC_Timer_Sync #(32) aYYMMDDWW_Sync(
.iCLK(iCLK),
.iData(iYearMonDateWeek),
.oData(wYYMMDDWW_Sync)
);
mGPIO_RTC_Timer_Sync #(32) aHHMMSSMs_Sync(
.iCLK(iCLK),
.iData(iHourMinSecMsec),
.oData(wHHMMSSMs_Sync)
);
mGPIO_RTC_Timer_Sync #(32) aPreYYMMDDWW_Sync(
.iCLK(iCLK),
.iData(iPre_YearMonDateWeek),
.oData(wPreYYMMDDWW_Sync)
);
mGPIO_RTC_Timer_Sync #(32) aPreHHMMSSMs_Sync(
.iCLK(iCLK),
.iData(iPre_HourMinSecMsec),
.oData(wPreHHMMSSMs_Sync)
);
mGPIO_RTC_Timer_Sync #(32) aMsecInitCnt_Sync(
.iCLK(iCLK),
.iData(iMsecInitCnt),
.oData(wMsecInitCnt_Sync)
);
mGPIO_RTC_Timer_Sync #(32) aRTCIntCtrl_Sync(
.iCLK(iCLK),
.iData(iRTCIntCtrl),
.oData(wRTCIntCtrl_Sync)
);
mGPIO_RTC_Timer_Sync #(32) aRTCRegCtrl_Sync(
.iCLK(iCLK),
.iData(iRTCRegCtrl),
.oData(wRTCRegCtrl_Sync)
);
mGPIO_RTC_Timer_Sync #(32) aRTCFredCnt_Sync(
.iCLK(iCLK),
.iData(iRTCFredCnt),
.oData(wRTCFredCnt_Sync)
);
//assignment of the control signals
//interrupt control signals
assign wTickEn = rIntCtrl[0];
assign wAlarmEn = rIntCtrl[1];
assign wTickSel = rIntCtrl[3:2];
assign wCompMask = rIntCtrl[31:24];
//signals used to write in the new time
assign wWrMask = wRTCRegCtrl_Sync[31:13];
assign wIsWrite = wRTCRegCtrl_Sync[1];
//signals used to update the time
assign wMatch = (rRTCFreDivCnt == rMsecInitCnt);
assign wMillionSec999 = (rMillionSec == 10'd999);
assign wSecond59 = (rSecond == 6'd59);
assign wMinute59 = (rMinute == 6'd59);
assign wHour23 = (rHour == 5'd23);
assign wWeek6 = (rWeek == 3'd6);
assign wMonthEnd = (((rDate == 5'd28) && (rMonth == 4'd2) && (~rLeapYear)) ||
((rDate == 5'd29) && (rMonth == 4'd2) && (rLeapYear)) ||
((rDate == 5'd30) && ((rMonth == 4'd4) || (rMonth == 4'd6) || (rMonth == 4'd9) || (rMonth == 4'd11))) ||
((rDate == 5'd31) && ((rMonth == 4'd1) || (rMonth == 4'd3) || (rMonth == 4'd5) || (rMonth == 4'd7) || (rMonth == 4'd8) || (rMonth == 4'd10) || (rMonth == 4'd12))));
assign wMonth12 = (rMonth == 4'd12);
//write control
// 1. write by input data
// 2. write each million second
always @ (wIsWrite or wWrMask or wRTCFredCnt_Sync or wMatch or rRTCFreDivCnt)
begin
if(wIsWrite & wWrMask[18])
rRTCFreDivCnt_Next = wRTCFredCnt_Sync;
else if(wMatch == 1'b1)
rRTCFreDivCnt_Next = 32'b0;
else
rRTCFreDivCnt_Next = rRTCFreDivCnt + 1;
end
always @ (posedge iCLK)
begin
rRTCFreDivCnt <= rRTCFreDivCnt_Next;
end
//always @ (posedge iCLK)
// begin
// if(wIsWrite & wWrMask[18])
// rRTCFreDivCnt <= wRTCFredCnt_Sync;
// else if(wMatch)
// rRTCFreDivCnt <= 32'b0;
// else
// rRTCFreDivCnt <= rRTCFreDivCnt + 1;
// end
always @ (wIsWrite or wWrMask or wHHMMSSMs_Sync or wMatch or wMillionSec999 or rMillionSec)
begin
if(wIsWrite & wWrMask[0])
rMillionSec_Next = wHHMMSSMs_Sync[9:0];
else if(wMatch & wMillionSec999)
rMillionSec_Next = 10'b0;
else if(wMatch & (~wMillionSec999))
rMillionSec_Next = rMillionSec + 1;
else
rMillionSec_Next = rMillionSec;
end
always @ (posedge iCLK)
begin
rMillionSec <= rMillionSec_Next;
end
always @ (wIsWrite or wWrMask or wHHMMSSMs_Sync or wMatch or wMillionSec999 or wSecond59 or rSecond)
begin
if(wIsWrite & wWrMask[1])
rSecond_Next = wHHMMSSMs_Sync[15:10];
else if(wMatch & wMillionSec999 & wSecond59)
rSecond_Next = 6'b0;
else if(wMatch & wMillionSec999 & (~wSecond59))
rSecond_Next = rSecond + 1;
else
rSecond_Next = rSecond;