求助APB接口和RTC仿真(程序模块已有,需要编写测试模块用ModelSim仿真)

该博客主要讨论如何为已经存在的mGPIO_RTC_Timer模块编写测试模块,用于在ModelSim环境中进行仿真。内容包括APB接口、RTC时钟模块、日期和定时器的相关输入输出信号描述,以及中断控制和时间更新的逻辑。通过这个测试模块,可以验证模块在不同条件下的行为和正确性。
摘要由CSDN通过智能技术生成

一   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;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值