⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wb_rtc.v

📁 // -*- Mode: Verilog -*- // Filename : wb_master.v // Description : Wishbone Master Behavorial //
💻 V
📖 第 1 页 / 共 2 页
字号:
//////////////////////////////////////////////////////////////////////
////                                                              ////
////  WISHBONE Real Time Clock Module                             ////
////                                                              ////
////                                                              ////
////                                                              ////
////  Author(s):                                                  ////
////      - Jianmin Zhang                                         ////
////                                                              ////
//////////////////////////////////////////////////////////////////////

// synopsys translate_off
`include "timescale.v"
// synopsys translate_on


module	rtc_top(
		// WISHBONE Interface
		wb_clk_i,
		wb_rst_i,
		wb_cyc_i,
		wb_adr_i,
		wb_dat_i,
		wb_sel_i,
		wb_we_i,
		wb_stb_i,
		wb_dat_o,
		wb_ack_o,
		wb_err_o,
		
		// Internal Interface
		rtc_int_o,
		
		// External XTAL Inout
		XTAL,
		EXTAL
		);
		
		
// Wishbone Interface
input		wb_clk_i;	// Clock
input		wb_rst_i;	// Reset
input		wb_cyc_i;	// cycle valid input
input 	[4:0]	wb_adr_i;	// address bus inputs
input	[31:0]	wb_dat_i;	// input data bus
input	[3:0]	wb_sel_i;	// byte select inputs
input		wb_we_i;	// indicates write transfer
input		wb_stb_i;	// strobe input
output	[31:0]	wb_dat_o;	// output data bus
output		wb_ack_o;	// normal termination
output		wb_err_o;	// termination error

// Internal Interface
output		rtc_int_o;
		
// External XTAL Inout
input		XTAL;		// XTAL input
output		EXTAL;		// XTAL output


// Local Wires and Registers
reg	[6:0]	rtc_inte;	// Interrupt Enable Register
reg	[6:0]	int_mask;	// Interrupt Mask Register
reg	[31:0]	fred_cnt;	// Frequency Division counter
reg	[31:0]	inicount;	// Initial counter value register
reg	[6:0]	rtc_con;	// RTC contrl register
reg	[15:0]	bcdyear;	// The BCD data of year
reg	[4:0]	bcdmon;		// The BCD data of month
reg	[5:0]	bcddate;	// The BCD data of date
reg	[3:0]	bcdday;		// The BCD data of day
reg	[5:0]	bcdhour;	// The BCD data of hour
reg	[6:0]	bcdmin;		// The BCD data of minute
reg	[6:0]	bcdsec;		// The BCD data of second

reg	[15:0]	preyear;	// The predetermining data of year
reg	[4:0]	premon;		// The predetermining data of month
reg	[5:0]	predate;	// The predetermining data of date
reg	[3:0]	preday;		// The predetermining data of day
reg	[5:0]	prehour;	// The predetermining data of hour
reg	[6:0]	premin;		// The predetermining data of minute
reg	[6:0]	presec;		// The predetermining data of second

wire		preyear_sel;
wire		premon_sel;
wire		predate_sel;
wire		preday_sel;
wire		prehour_sel;
wire		premin_sel;
wire		presec_sel;
wire		mask_sel;
wire		inte_sel;
wire		fredcnt_sel;
wire		count_sel;
wire		con_sel;
wire		year_sel;
wire		mon_sel;
wire		date_sel;
wire		day_sel;
wire		hour_sel;
wire		min_sel;
wire		sec_sel;
	
reg		wb_ack_o;
wire		wb_ack;
wire		wb_err;
reg		wb_err_o;
reg	[31:0]	wb_data;
reg	[31:0]	wb_dat_o;
wire		dig_clk;
wire		clk_rtc;
wire		fred_full;
reg		leapyear;
reg		sec_int;
reg		min_int;
reg		hour_int;
reg		date_int;
reg		week_int;
reg		mon_int;
wire		equ_int;
reg		equsec;
reg		equmin;
reg		equhour;
reg		equday;
reg		equdate;
reg		equmon;
reg		equyear;
reg		rtc_int;
reg		rtc_int_r;



///////////////////////////////////////////////////////////////
//
// WISHBONE Interface Logic
//

//
// Wishbone Acknowledge
//

assign	wb_ack = wb_cyc_i && wb_stb_i && !wb_err_o;

always	@(posedge wb_clk_i or posedge wb_rst_i)
  begin
	if (wb_rst_i)
	  begin
		wb_ack_o <= 1'b0;
	  end
	else
	  begin		
		wb_ack_o <= wb_ack && !wb_ack_o;	
	  end
  end


// 
// Wishbone Error
//

assign	wb_err = wb_cyc_i && wb_stb_i && ((wb_adr_i[4:0] == 5'h19) & (wb_sel_i != 4'b0011) |
					  (wb_adr_i[4:0] == 5'h18) & (wb_sel_i != 4'b0001) |
					  (wb_adr_i[4:0] == 5'h17) & (wb_sel_i != 4'b0001) |
					  (wb_adr_i[4:0] == 5'h16) & (wb_sel_i != 4'b0001) |
					  (wb_adr_i[4:0] == 5'h15) & (wb_sel_i != 4'b0001) |
					  (wb_adr_i[4:0] == 5'h14) & (wb_sel_i != 4'b0001) |
					  (wb_adr_i[4:0] == 5'h13) & (wb_sel_i != 4'b0001) |
					  (wb_adr_i[4:0] == 5'h12) & (wb_sel_i != 4'b0001) |
					  (wb_adr_i[4:0] == 5'h11) & (wb_sel_i != 4'b0001) |
					  (wb_adr_i[4:0] == 5'h0d) & (wb_sel_i != 4'b1111) |
					  (wb_adr_i[4:0] == 5'h09) & (wb_sel_i != 4'b1111) |
					  (wb_adr_i[4:0] == 5'h08) & (wb_sel_i != 4'b0001) |
					  (wb_adr_i[4:0] == 5'h06) & (wb_sel_i != 4'b0011) |
					  (wb_adr_i[4:0] == 5'h05) & (wb_sel_i != 4'b0001) |
					  (wb_adr_i[4:0] == 5'h04) & (wb_sel_i != 4'b0001) |
					  (wb_adr_i[4:0] == 5'h03) & (wb_sel_i != 4'b0001) |
					  (wb_adr_i[4:0] == 5'h02) & (wb_sel_i != 4'b0001) |
					  (wb_adr_i[4:0] == 5'h01) & (wb_sel_i != 4'b0001) |
					  (wb_adr_i[4:0] == 5'h00) & (wb_sel_i != 4'b0001));

always	@(posedge wb_clk_i or posedge wb_rst_i)
  begin
	if (wb_rst_i)
	  begin
	  	wb_err_o <= 1'b0;
	  end
	else
	  begin
	  	wb_err_o <= wb_err && !wb_err_o;
	  end
  end


// 
// Write select logic
//
assign	preyear_sel = wb_cyc_i && wb_stb_i && (wb_adr_i[4:0] == 5'h19) && (wb_sel_i == 4'b0011) && rtc_con[5];
assign	premon_sel  = wb_cyc_i && wb_stb_i && (wb_adr_i[4:0] == 5'h18) && (wb_sel_i == 4'b0001) && rtc_con[5];
assign	predate_sel = wb_cyc_i && wb_stb_i && (wb_adr_i[4:0] == 5'h17) && (wb_sel_i == 4'b0001) && rtc_con[5];
assign	preday_sel  = wb_cyc_i && wb_stb_i && (wb_adr_i[4:0] == 5'h16) && (wb_sel_i == 4'b0001) && rtc_con[5];
assign	prehour_sel = wb_cyc_i && wb_stb_i && (wb_adr_i[4:0] == 5'h15) && (wb_sel_i == 4'b0001) && rtc_con[5];
assign	premin_sel  = wb_cyc_i && wb_stb_i && (wb_adr_i[4:0] == 5'h14) && (wb_sel_i == 4'b0001) && rtc_con[5];
assign	presec_sel  = wb_cyc_i && wb_stb_i && (wb_adr_i[4:0] == 5'h13) && (wb_sel_i == 4'b0001) && rtc_con[5];
assign	mask_sel    = wb_cyc_i && wb_stb_i && (wb_adr_i[4:0] == 5'h12) && (wb_sel_i == 4'b0001);
assign	inte_sel    = wb_cyc_i && wb_stb_i && (wb_adr_i[4:0] == 5'h11) && (wb_sel_i == 4'b0001);
assign	fredcnt_sel = wb_cyc_i && wb_stb_i && (wb_adr_i[4:0] == 5'h0d) && (wb_sel_i == 4'b1111);
assign	count_sel   = wb_cyc_i && wb_stb_i && (wb_adr_i[4:0] == 5'h09) && (wb_sel_i == 4'b1111);
assign	con_sel	    = wb_cyc_i && wb_stb_i && (wb_adr_i[4:0] == 5'h08) && (wb_sel_i == 4'b0001);
assign	year_sel    = wb_cyc_i && wb_stb_i && (wb_adr_i[4:0] == 5'h06) && (wb_sel_i == 4'b0011) && rtc_con[0];
assign	mon_sel	    = wb_cyc_i && wb_stb_i && (wb_adr_i[4:0] == 5'h05) && (wb_sel_i == 4'b0001) && rtc_con[0];
assign	date_sel    = wb_cyc_i && wb_stb_i && (wb_adr_i[4:0] == 5'h04) && (wb_sel_i == 4'b0001) && rtc_con[0];
assign	day_sel     = wb_cyc_i && wb_stb_i && (wb_adr_i[4:0] == 5'h03) && (wb_sel_i == 4'b0001) && rtc_con[0];
assign	hour_sel    = wb_cyc_i && wb_stb_i && (wb_adr_i[4:0] == 5'h02) && (wb_sel_i == 4'b0001) && rtc_con[0];
assign	min_sel	    = wb_cyc_i && wb_stb_i && (wb_adr_i[4:0] == 5'h01) && (wb_sel_i == 4'b0001) && rtc_con[0];
assign	sec_sel	    = wb_cyc_i && wb_stb_i && (wb_adr_i[4:0] == 5'h00) && (wb_sel_i == 4'b0001) && rtc_con[0];


//
// Write to predetermining Second Register
//

always	@(posedge wb_clk_i)
  begin
	if (presec_sel && wb_we_i)
	  begin
	  	presec <= wb_dat_i[6:0];
	  end
  end


//
// Write to predetermining Minute Register
//
	
always	@(posedge wb_clk_i)
  begin
	if (premin_sel && wb_we_i)
	  begin
	  	premin <= wb_dat_i[6:0];
	  end
  end


//
// Write to predetermining Hour Register
//

always	@(posedge wb_clk_i)
  begin
	if (prehour_sel && wb_we_i)
	  begin
	  	prehour <= wb_dat_i[5:0];
	  end
  end


//
// Write to predetermining Day Register
//

always	@(posedge wb_clk_i)
  begin
	if (preday_sel && wb_we_i)
	  begin
	  	preday <= wb_dat_i[3:0];
	  end
  end


//
// Write to predetermining Date Register
//

always	@(posedge wb_clk_i)
  begin
	if (predate_sel && wb_we_i)
	  begin
	  	predate <= wb_dat_i[5:0];
	  end
  end


//
// Write to predetermining Month Register
//

always	@(posedge wb_clk_i)
  begin
	if (premon_sel && wb_we_i)
	  begin
	  	premon <= wb_dat_i[4:0];
	  end
  end


//
// Write to predetermining Year Register
//
  
always	@(posedge wb_clk_i)
  begin
	if (preyear_sel && wb_we_i)
	  begin
	  	preyear <= wb_dat_i[15:0];
	  end
  end


//
// Write to INT MASK Register
//

always	@(posedge wb_clk_i)
  begin
	if (mask_sel && wb_we_i)
	  begin
		int_mask <= wb_dat_i[6:0];
	  end
  end
  

//
// Write to INT ENABLE Register
//

always	@(posedge wb_clk_i)
  begin
	if (inte_sel && wb_we_i)
	  begin
		rtc_inte <= wb_dat_i[6:0];
	  end
  end


//
// Write to INICOUNT Register
//

always	@(posedge wb_clk_i)
  begin
	if (count_sel && wb_we_i)
	  begin
		inicount <= wb_dat_i;
	  end
  end


//
// Write to CONTROL Register
//

always	@(posedge wb_clk_i)
  begin
	if (con_sel && wb_we_i)
	  begin
		rtc_con <= wb_dat_i[6:0];
	  end
  end


//
// Mux of Reading Registers
//

always	@(wb_adr_i or bcdsec or bcdmin or bcdhour or bcdday or bcddate or
	  bcdmon or bcdyear or rtc_con or inicount or fred_cnt or rtc_inte or
	  int_mask or presec or premin or prehour or preday or predate or
	  premon or preyear)
  begin
	case (wb_adr_i[4:0])
		5'h00:
		  begin
		  	wb_data[6:0] = bcdsec;
		  	wb_data[31:7] = 25'b0;
		  end
		5'h01:
		  begin
		  	wb_data[6:0] = bcdmin;
		  	wb_data[31:7] = 25'b0;
		  end
		5'h02:
		  begin
		  	wb_data[5:0] = bcdhour;
		  	wb_data[31:6] = 26'b0;
		  end
		5'h03:
		  begin
		  	wb_data[3:0] = bcdday;
		  	wb_data[31:4] = 28'b0;
		  end
		5'h04:
		  begin
		  	wb_data[5:0] = bcddate;
		  	wb_data[31:6] = 26'b0;
		  end
		5'h05:
		  begin
		  	wb_data[4:0] = bcdmon;
		  	wb_data[31:5] = 27'b0;
		  end
		5'h06:
		  begin
		  	wb_data[15:0] = bcdyear;
		  	wb_data[31:16] = 16'b0;
		  end
		5'h08:
		  begin
		  	wb_data[6:0] = rtc_con;
		  	wb_data[31:7] = 25'b0;
		  end
		5'h09:
		  begin
		  	wb_data = inicount;
		  end
		5'h0d:
		  begin
		  	wb_data = fred_cnt;		  	
		  end
		5'h11:
		  begin
		  	wb_data[6:0] = rtc_inte;
		  	wb_data[31:7] = 25'b0;
		  end
		5'h12:
		  begin
		  	wb_data[6:0] = int_mask;
		  	wb_data[31:7] = 25'b0;
		  end
		5'h13:
		  begin
		  	wb_data[6:0] = presec;
		  	wb_data[31:7] = 25'b0;
		  end
		5'h14:
		  begin
		  	wb_data[6:0] = premin;
		  	wb_data[31:7] = 25'b0;
		  end
		5'h15:
		  begin
		  	wb_data[5:0] = prehour;
		  	wb_data[31:6] = 26'b0;
		  end
		5'h16:
		  begin
		  	wb_data[3:0] = preday;
		  	wb_data[31:4] = 28'b0;
		  end
		5'h17:
		  begin
		  	wb_data[5:0] = predate;
		  	wb_data[31:6] = 26'b0;
		  end
		5'h18:
		  begin
		  	wb_data[4:0] = premon;
		  	wb_data[31:5] = 27'b0;
		  end
		5'h19:
		  begin
		  	wb_data[15:0] = preyear;
		  	wb_data[31:16] = 16'b0;
		  end
		default:
		  begin
		  	wb_data = 32'b0;
		  end
	endcase
  end


//
// Wishbone data output
//

always	@(posedge wb_clk_i or posedge wb_rst_i)
  begin
	if (wb_rst_i)
	  begin
		wb_dat_o <= 32'b0;
	  end
	else
	  begin
		wb_dat_o <= wb_data;
	  end
  end



////////////////////////////////////////////////////////
//
// Convert Analog clk to Digital clk
// and Frequency Division
//

assign	dig_clk = ~XTAL;
assign	clk_rtc = ~dig_clk;
assign	EXTAL	= clk_rtc;



///////////////////////////////////////////////////////////////////////
//
// Frequency Division and Calendar Generate Logic
// The frequency division factor is inicount,
// Calendar includes year, month, date, hour, minute, second
//

always	@(posedge clk_rtc)
  begin
	if (sec_sel && wb_we_i)
	  begin
	  	bcdsec <= wb_dat_i[6:0];
	  end
	
	if (min_sel && wb_we_i)
	  begin
	  	bcdmin <= wb_dat_i[6:0];
	  end
	
	if (hour_sel && wb_we_i)
	  begin
	  	bcdhour <= wb_dat_i[5:0];
	  end
	
	if (day_sel && wb_we_i)
	  begin
	  	bcdday <= wb_dat_i[3:0];
	  end
	
	if (date_sel && wb_we_i)
	  begin
	  	bcddate <= wb_dat_i[5:0];
	  end

	if (mon_sel && wb_we_i)
	  begin
	  	bcdmon <= wb_dat_i[4:0];
	  end

	if (year_sel && wb_we_i)
	  begin
	  	bcdyear <= wb_dat_i[15:0];
	  end
		 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -