123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152 |
- module sysclock (
- input rst_n,
- input sys_clk,
- input rtc_clk,
- output rtc_clk_s,
- input valid,
- input addr,
- output reg [31:0] rdata,
- input [31:0] wdata,
- input [3:0] wstrb,
- output periodic,
- output [15:0] rtc_ctr
- );
- parameter PERIODIC_HZ_LG2 = 5;
- synchronizer synchro (
- .rst_n ( 1'b1 ),
- .clk ( sys_clk ),
- .d ( rtc_clk ),
- .q ( rtc_clk_s )
- );
- reg rtc_clk_q;
- reg rtc_clk_stb;
- always @(posedge sys_clk)
- begin
- rtc_clk_q <= rtc_clk_s;
- rtc_clk_stb <= rtc_clk_s & ~rtc_clk_q;
- end
- function logic [4:0] maxday(input [3:0] mon,
- input [6:0] year);
- case (mon)
- 4'd4,
- 4'd6,
- 4'd9,
- 4'd11: begin
- maxday = 5'd30;
- end
- 4'd2: begin
- if ((|year[1:0]) | (year == (2100 - 1980)))
- maxday = 5'd28;
- else
- maxday = 5'd29;
- end
- default: begin
- maxday = 5'd31;
- end
- endcase
- endfunction
- function logic [7:0] tick(input [7:0] me,
- input [7:0] start,
- input wrap_pre,
- input wrap_me);
- tick = wrap_me ? start : me + wrap_pre;
- endfunction
-
- reg [15:0] tm_hold;
- reg [ 1:0] tm_whold;
- reg [15:0] tm_tick;
- reg [31:0] tm_dt;
- wire [4:0] tm_2sec = tm_dt[4:0];
- wire [5:0] tm_min = tm_dt[10:5];
- wire [4:0] tm_hour = tm_dt[15:11];
- wire [4:0] tm_mday = tm_dt[20:16];
- wire [3:0] tm_mon = tm_dt[24:21];
- wire [6:0] tm_year = tm_dt[31:25];
- wire wrap_tick = rtc_clk_stb & &tm_tick;
- wire wrap_sec = wrap_tick & (tm_2sec >= 5'd29);
- wire wrap_min = wrap_sec & (tm_min >= 6'd59);
- wire wrap_hour = wrap_min & (tm_hour >= 5'd23);
- wire wrap_mday = wrap_hour & (tm_mday >= maxday(tm_mon, tm_year));
- wire wrap_mon = wrap_mday & (tm_mon >= 4'd12);
-
- assign periodic = tm_tick[14 - PERIODIC_HZ_LG2];
- assign rtc_ctr = tm_tick;
- always @(posedge sys_clk)
- begin
- tm_tick <= tm_tick + rtc_clk_stb;
- tm_dt[4:0] <= tick(tm_2sec, 5'd0, wrap_tick, wrap_sec);
- tm_dt[10:5] <= tick(tm_min, 6'd0, wrap_sec, wrap_min);
- tm_dt[15:11] <= tick(tm_hour, 4'd0, wrap_min, wrap_hour);
- tm_dt[20:16] <= tick(tm_mday, 5'd1, wrap_hour, wrap_mday);
- tm_dt[24:21] <= tick(tm_mon, 4'd1, wrap_mday, wrap_mon);
- tm_dt[31:25] <= tick(tm_year, 7'hxx, wrap_mon, 1'b0);
- if (~rst_n)
- begin
- tm_hold <= tm_tick;
- tm_whold <= 2'b00;
- end
- else if (valid)
- case (addr)
- 1'b0: begin
-
- if (wstrb[0]) tm_dt[7:0] <= wdata[7:0];
- if (wstrb[1]) tm_dt[15:8] <= wdata[15:8];
- if (wstrb[2]) tm_dt[23:16] <= wdata[23:16];
- if (wstrb[3]) tm_dt[31:24] <= wdata[31:24];
- if (tm_whold[0]) tm_tick[7:0] <= tm_hold[7:0];
- if (tm_whold[1]) tm_tick[15:8] <= tm_hold[15:8];
- tm_hold <= tm_tick;
- tm_whold <= 2'b00;
- end
- 1'b1: begin
-
- if (wstrb[0]) tm_hold[7:0] <= wdata[7:0];
- if (wstrb[1]) tm_hold[15:8] <= wdata[15:8];
- if (wstrb[2]) tm_tick[7:0] <= wdata[23:16];
- if (wstrb[3]) tm_tick[15:8] <= wdata[31:24];
- tm_whold <= tm_whold | wstrb[1:0];
- end
- endcase
- end
-
- always @(*)
- case (addr)
- 1'b0: rdata = tm_dt;
- 1'b1: rdata = { tm_tick, tm_hold };
- endcase
- endmodule
|