📄 wb_rtc.v
字号:
//////////////////////////////////////////////////////////////////////
//// ////
//// 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 + -