URL
https://opencores.org/ocsvn/rtc/rtc/trunk
Subversion Repositories rtc
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 10 to Rev 11
- ↔ Reverse comparison
Rev 10 → Rev 11
/trunk/bench/verilog/clkrst.v
0,0 → 1,100
////////////////////////////////////////////////////////////////////// |
//// //// |
//// Clock and Reset Generator //// |
//// //// |
//// This file is part of the RTC project //// |
//// http://www.opencores.org/cores/rtc/ //// |
//// //// |
//// Description //// |
//// Clock and reset generator. //// |
//// //// |
//// To Do: //// |
//// Nothing //// |
//// //// |
//// Author(s): //// |
//// - Damjan Lampret, lampret@opencores.org //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2000 Authors and OPENCORES.ORG //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer. //// |
//// //// |
//// This source file is free software; you can redistribute it //// |
//// and/or modify it under the terms of the GNU Lesser General //// |
//// Public License as published by the Free Software Foundation; //// |
//// either version 2.1 of the License, or (at your option) any //// |
//// later version. //// |
//// //// |
//// This source is distributed in the hope that it will be //// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied //// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// |
//// PURPOSE. See the GNU Lesser General Public License for more //// |
//// details. //// |
//// //// |
//// You should have received a copy of the GNU Lesser General //// |
//// Public License along with this source; if not, download it //// |
//// from http://www.opencores.org/lgpl.shtml //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
// |
// CVS Revision History |
// |
// $Log: not supported by cvs2svn $ |
// Revision 1.1 2001/06/05 07:45:41 lampret |
// Added initial RTL and test benches. There are still some issues with these files. |
// |
// |
|
// synopsys translate_off |
`include "timescale.v" |
// synopsys translate_on |
|
module clkrst(clk_o, rst_o, rtc_clk); |
|
// |
// I/O ports |
// |
output clk_o; // Clock |
output rst_o; // Reset |
output rtc_clk; // (External) RTC clock |
|
// |
// Internal regs |
// |
reg clk_o; // Clock |
reg rst_o; // Reset |
reg rtc_clk; // RTC clock |
|
initial begin |
clk_o = 0; |
rst_o = 1; |
rtc_clk = 0; |
#20; |
rst_o = 0; |
end |
|
// |
// Clock |
// |
always #4 clk_o = ~clk_o; |
|
// |
// RTC clock generator |
// |
task gen_rtc_clk; |
input [31:0] cycles; |
integer i; |
begin |
for (i = 2 * cycles; i; i = i - 1) begin |
#4 rtc_clk = ~rtc_clk; |
if (i % 20000 == 19999) |
$write("."); |
end |
end |
endtask |
|
endmodule |
/trunk/bench/verilog/tb_defines.v
0,0 → 1,67
////////////////////////////////////////////////////////////////////// |
//// //// |
//// RTC Testbench Definitions //// |
//// //// |
//// This file is part of the RTC project //// |
//// http://www.opencores.org/cores/rtc/ //// |
//// //// |
//// Description //// |
//// Testbench definitions that affect how testbench simulation //// |
//// is performed. //// |
//// //// |
//// To Do: //// |
//// Nothing //// |
//// //// |
//// Author(s): //// |
//// - Damjan Lampret, lampret@opencores.org //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2000 Authors and OPENCORES.ORG //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer. //// |
//// //// |
//// This source file is free software; you can redistribute it //// |
//// and/or modify it under the terms of the GNU Lesser General //// |
//// Public License as published by the Free Software Foundation; //// |
//// either version 2.1 of the License, or (at your option) any //// |
//// later version. //// |
//// //// |
//// This source is distributed in the hope that it will be //// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied //// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// |
//// PURPOSE. See the GNU Lesser General Public License for more //// |
//// details. //// |
//// //// |
//// You should have received a copy of the GNU Lesser General //// |
//// Public License along with this source; if not, download it //// |
//// from http://www.opencores.org/lgpl.shtml //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
// |
// CVS Revision History |
// |
// $Log: not supported by cvs2svn $ |
// Revision 1.3 2001/07/16 01:05:01 lampret |
// Fixed some bugs in test bench. Added comments to tb_defines.v |
// |
// Revision 1.2 2001/06/05 08:10:47 lampret |
// Tests dont go through. |
// |
// Revision 1.1 2001/06/05 07:45:41 lampret |
// Added initial RTL and test benches. There are still some issues with these files. |
// |
// |
|
// |
// Define if you want test bench debugging information during simulation |
// |
//`define RTC_DEBUG |
|
// |
// Define if you want VCD dump |
// |
//`define RTC_DUMP_VCD |
/trunk/bench/verilog/wb_master.v
0,0 → 1,308
// synopsys translate_off |
`include "timescale.v" |
// synopsys translate_on |
|
// -*- Mode: Verilog -*- |
// Filename : wb_master.v |
// Description : Wishbone Master Behavorial |
// Author : Winefred Washington |
// Created On : Thu Jan 11 21:18:41 2001 |
// Last Modified By: . |
// Last Modified On: . |
// Update Count : 0 |
// Status : Unknown, Use with caution! |
|
// Description Specification |
// General Description: 8, 16, 32-bit WISHBONE Master |
// Supported cycles: MASTER, READ/WRITE |
// MASTER, BLOCK READ/WRITE |
// MASTER, RMW |
// Data port, size: 8, 16, 32-bit |
// Data port, granularity 8-bit |
// Data port, Max. operand size 32-bit |
// Data transfer ordering: little endian |
// Data transfer sequencing: undefined |
// |
|
module wb_master(CLK_I, RST_I, TAG_I, TAG_O, |
ACK_I, ADR_O, CYC_O, DAT_I, DAT_O, ERR_I, RTY_I, SEL_O, STB_O, WE_O); |
|
input CLK_I; |
input RST_I; |
input [3:0] TAG_I; |
output [3:0] TAG_O; |
input ACK_I; |
output [31:0] ADR_O; |
output CYC_O; |
input [31:0] DAT_I; |
output [31:0] DAT_O; |
input ERR_I; |
input RTY_I; |
output [3:0] SEL_O; |
output STB_O; |
output WE_O; |
|
reg [31:0] ADR_O; |
reg [3:0] SEL_O; |
reg CYC_O; |
reg STB_O; |
reg WE_O; |
reg [31:0] DAT_O; |
|
wire [15:0] mem_sizes; // determines the data width of an address range |
reg [31:0] write_burst_buffer[0:7]; |
reg [31:0] read_burst_buffer[0:7]; |
|
reg GO; |
integer cycle_end; |
integer address; |
integer data; |
integer selects; |
integer write_flag; |
|
// |
// mem_sizes determines the data widths of memory space |
// The memory space is divided into eight regions. Each |
// region is controlled by a two bit field. |
// |
// Bits |
// 00 = 8 bit memory space |
// 01 = 16 bit |
// 10 = 32 bit |
// 11 = 64 bit (not supported in this model |
// |
|
assign mem_sizes = 16'b10_01_10_11_00_01_10_11; |
|
function [1:0] data_width; |
input [31:0] adr; |
begin |
casex (adr[31:29]) |
3'b000: data_width = mem_sizes[15:14]; |
3'b001: data_width = mem_sizes[13:12]; |
3'b010: data_width = mem_sizes[11:10]; |
3'b011: data_width = mem_sizes[9:8]; |
3'b100: data_width = mem_sizes[7:6]; |
3'b101: data_width = mem_sizes[5:4]; |
3'b110: data_width = mem_sizes[3:2]; |
3'b111: data_width = mem_sizes[1:0]; |
3'bxxx: data_width = 2'bxx; |
endcase // casex (adr[31:29]) |
end |
endfunction |
|
always @(posedge CLK_I or posedge RST_I) |
begin |
if (RST_I) |
begin |
GO = 1'b0; |
end |
end |
|
// read single |
task rd; |
input [31:0] adr; |
output [31:0] result; |
|
begin |
cycle_end = 1; |
address = adr; |
selects = 255; |
write_flag = 0; |
|
GO <= 1; |
@(posedge CLK_I); |
// GO <= 0; |
|
// wait for cycle to start |
while (~CYC_O) |
@(posedge CLK_I); |
|
// wait for cycle to end |
while (CYC_O) |
@(posedge CLK_I); |
|
result = data; |
// $display(" Reading %h from address %h", result, address); |
|
end |
endtask // read |
|
task wr; |
input [31:0] adr; |
input [31:0] dat; |
input [3:0] sel; |
begin |
cycle_end = 1; |
address = adr; |
selects = sel; |
write_flag = 1; |
data = dat; |
|
GO <= 1; |
@(posedge CLK_I); |
// GO <= 0; |
|
// wait for cycle to start |
while (~CYC_O) |
@(posedge CLK_I); |
|
// wait for cycle to end |
while (CYC_O) |
@(posedge CLK_I); |
// $display(" Writing %h to address %h", data, address); |
|
end |
endtask // wr |
|
// block read |
task blkrd; |
input [31:0] adr; |
input end_flag; |
output [31:0] result; |
|
begin |
write_flag = 0; |
cycle_end = end_flag; |
address = adr; |
GO <= 1; |
@(posedge CLK_I); |
// GO <= 0; |
|
while (~(ACK_I & STB_O)) |
@(posedge CLK_I); |
|
result = data; |
end |
endtask // blkrd |
|
// block write |
task blkwr; |
input [31:0] adr; |
input [31:0] dat; |
input [3:0] sel; |
input end_flag; |
begin |
write_flag = 1; |
cycle_end = end_flag; |
address = adr; |
data = dat; |
selects = sel; |
GO <= 1; |
@(posedge CLK_I); |
// GO <= 0; |
|
while (~(ACK_I & STB_O)) |
@(posedge CLK_I); |
|
end |
endtask // blkwr |
|
// RMW |
task rmw; |
input [31:0] adr; |
input [31:0] dat; |
input [3:0] sel; |
output [31:0] result; |
|
begin |
// read phase |
write_flag = 0; |
cycle_end = 0; |
address = adr; |
GO <= 1; |
@(posedge CLK_I); |
// GO <= 0; |
|
while (~(ACK_I & STB_O)) |
@(posedge CLK_I); |
|
result = data; |
|
// write phase |
write_flag = 1; |
address = adr; |
selects = sel; |
GO <= 1; |
data <= dat; |
cycle_end <= 1; |
@(posedge CLK_I); |
// GO <= 0; |
|
while (~(ACK_I & STB_O)) |
@(posedge CLK_I); |
|
end |
endtask // rmw |
|
always @(posedge CLK_I) |
begin |
if (RST_I) |
ADR_O <= 32'h0000_0000; |
else |
ADR_O <= address; |
end |
|
always @(posedge CLK_I) |
begin |
if (RST_I | ERR_I | RTY_I) |
CYC_O <= 1'b0; |
else if ((cycle_end == 1) & ACK_I) |
CYC_O <= 1'b0; |
else if (GO | CYC_O) begin |
CYC_O <= 1'b1; |
GO <= 1'b0; |
end |
end |
|
// stb control |
always @(posedge CLK_I) |
begin |
if (RST_I | ERR_I | RTY_I) |
STB_O <= 1'b0; |
else if (STB_O & ACK_I) |
STB_O <= 1'b0; |
else if (GO | STB_O) |
STB_O <= 1'b1; |
end |
|
// selects & data |
always @(posedge CLK_I) |
begin |
if (write_flag == 0) begin |
SEL_O <= 4'b1111; |
if (STB_O & ACK_I) |
data <= DAT_I; |
end |
else begin |
case (data_width(address)) |
2'b00: begin |
SEL_O <= {3'b000, selects[0]}; |
DAT_O <= {data[7:0], data[7:0], data[7:0], data[7:0]}; |
end |
2'b01: begin |
SEL_O <= {2'b00, selects[1:0]}; |
DAT_O <= {data[15:0], data[15:0]}; |
end |
2'b10: begin |
SEL_O <= selects; |
DAT_O <= data; |
end |
endcase |
end |
end |
|
always @(posedge CLK_I) |
begin |
if (RST_I) |
WE_O <= 1'b0; |
else if (GO) |
WE_O <= write_flag; |
end |
|
endmodule |
|
|
|
|
|
/trunk/bench/verilog/timescale.v
0,0 → 1,308
`timescale 1ns/10ps |
/trunk/bench/verilog/tb_top.v
0,0 → 1,131
////////////////////////////////////////////////////////////////////// |
//// //// |
//// RTC Testbench Top //// |
//// //// |
//// This file is part of the RTC project //// |
//// http://www.opencores.org/cores/rtc/ //// |
//// //// |
//// Description //// |
//// Top level of testbench. It instantiates all blocks. //// |
//// //// |
//// To Do: //// |
//// Nothing //// |
//// //// |
//// Author(s): //// |
//// - Damjan Lampret, lampret@opencores.org //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2000 Authors and OPENCORES.ORG //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer. //// |
//// //// |
//// This source file is free software; you can redistribute it //// |
//// and/or modify it under the terms of the GNU Lesser General //// |
//// Public License as published by the Free Software Foundation; //// |
//// either version 2.1 of the License, or (at your option) any //// |
//// later version. //// |
//// //// |
//// This source is distributed in the hope that it will be //// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied //// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// |
//// PURPOSE. See the GNU Lesser General Public License for more //// |
//// details. //// |
//// //// |
//// You should have received a copy of the GNU Lesser General //// |
//// Public License along with this source; if not, download it //// |
//// from http://www.opencores.org/lgpl.shtml //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
// |
// CVS Revision History |
// |
// $Log: not supported by cvs2svn $ |
// Revision 1.1 2001/06/05 07:45:41 lampret |
// Added initial RTL and test benches. There are still some issues with these files. |
// |
// |
|
// synopsys translate_off |
`include "timescale.v" |
// synopsys translate_on |
|
module tb_top; |
|
parameter aw = 16; |
parameter dw = 32; |
|
// |
// Interconnect wires |
// |
wire clk; // Clock |
wire rst; // Reset |
wire cyc; // Cycle valid |
wire [aw-1:0] adr; // Address bus |
wire [dw-1:0] dat_m; // Data bus from RTC to WBM |
wire [3:0] sel; // Data selects |
wire we; // Write enable |
wire stb; // Strobe |
wire [dw-1:0] dat_rtc;// Data bus from WBM to RTC |
wire ack; // Successful cycle termination |
wire err; // Failed cycle termination |
wire rtc_clk;// External RTC clock |
|
// |
// Instantiation of Clock/Reset Generator |
// |
clkrst clkrst( |
// Clock |
.clk_o(clk), |
// Reset |
.rst_o(rst), |
// External clock |
.rtc_clk(rtc_clk) |
); |
|
// |
// Instantiation of Master WISHBONE BFM |
// |
wb_master wb_master( |
// WISHBONE Interface |
.CLK_I(clk), |
.RST_I(rst), |
.CYC_O(cyc), |
.ADR_O(adr), |
.DAT_O(dat_rtc), |
.SEL_O(sel), |
.WE_O(we), |
.STB_O(stb), |
.DAT_I(dat_m), |
.ACK_I(ack), |
.ERR_I(err), |
.RTY_I(0), |
.TAG_I(4'b0) |
); |
|
// |
// Instantiation of RTC core |
// |
rtc rtc( |
// WISHBONE Interface |
.wb_clk_i(clk), |
.wb_rst_i(rst), |
.wb_cyc_i(cyc), |
.wb_adr_i(adr), |
.wb_dat_i(dat_rtc), |
.wb_sel_i(sel), |
.wb_we_i(we), |
.wb_stb_i(stb), |
.wb_dat_o(dat_m), |
.wb_ack_o(ack), |
.wb_err_o(err), |
.wb_inta_o(), |
|
// External RTC Interface |
.clk_rtc_pad_i(rtc_clk) |
); |
|
endmodule |
/trunk/bench/verilog/tb_tasks.v
0,0 → 1,1399
////////////////////////////////////////////////////////////////////// |
//// //// |
//// RTC Testbench Tasks //// |
//// //// |
//// This file is part of the RTC project //// |
//// http://www.opencores.org/cores/rtc/ //// |
//// //// |
//// Description //// |
//// Testbench tasks. //// |
//// //// |
//// To Do: //// |
//// Nothing //// |
//// //// |
//// Author(s): //// |
//// - Damjan Lampret, lampret@opencores.org //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2000 Authors and OPENCORES.ORG //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer. //// |
//// //// |
//// This source file is free software; you can redistribute it //// |
//// and/or modify it under the terms of the GNU Lesser General //// |
//// Public License as published by the Free Software Foundation; //// |
//// either version 2.1 of the License, or (at your option) any //// |
//// later version. //// |
//// //// |
//// This source is distributed in the hope that it will be //// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied //// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// |
//// PURPOSE. See the GNU Lesser General Public License for more //// |
//// details. //// |
//// //// |
//// You should have received a copy of the GNU Lesser General //// |
//// Public License along with this source; if not, download it //// |
//// from http://www.opencores.org/lgpl.shtml //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
// |
// CVS Revision History |
// |
// $Log: not supported by cvs2svn $ |
// Revision 1.2 2001/07/16 01:05:01 lampret |
// Fixed some bugs in test bench. Added comments to tb_defines.v |
// |
// Revision 1.1 2001/06/05 07:45:41 lampret |
// Added initial RTL and test benches. There are still some issues with these files. |
// |
// |
|
// synopsys translate_off |
`include "timescale.v" |
// synopsys translate_on |
|
`include "defines.v" |
`include "tb_defines.v" |
|
module tb_tasks; |
|
integer nr_failed; |
|
// |
// Count/report failed tests |
// |
task failed; |
begin |
$display("FAILED !!!"); |
nr_failed = nr_failed + 1; |
end |
endtask |
|
// |
// Set RTC_RRTC_TIME register |
// |
task settime; |
input [2:0] dow; |
input [5:0] hr; |
input [6:0] min; |
input [6:0] sec; |
input [3:0] tos; |
|
reg [31:0] tmp; |
|
begin |
tmp[`RTC_RRTC_TIME_DOW] = dow[2:0]; |
tmp[`RTC_RRTC_TIME_TH] = hr[5:4]; |
tmp[`RTC_RRTC_TIME_H] = hr[3:0]; |
tmp[`RTC_RRTC_TIME_TM] = min[6:4]; |
tmp[`RTC_RRTC_TIME_M] = min[3:0]; |
tmp[`RTC_RRTC_TIME_TS] = sec[6:4]; |
tmp[`RTC_RRTC_TIME_S] = sec[3:0]; |
tmp[`RTC_RRTC_TIME_TOS] = tos[3:0]; |
tb_top.wb_master.wr(`RTC_RRTC_TIME<<2, tmp, 4'b1111); |
end |
|
endtask |
|
// |
// Set RTC_RRTC_DATE register |
// |
task setdate; |
input [5:0] d; |
input [4:0] m; |
input [15:0] cy; |
|
reg [31:0] tmp; |
|
begin |
tmp[`RTC_RRTC_DATE_TD] = d[5:4]; |
tmp[`RTC_RRTC_DATE_D] = d[3:0]; |
tmp[`RTC_RRTC_DATE_TM] = m[4]; |
tmp[`RTC_RRTC_DATE_M] = m[3:0]; |
tmp[`RTC_RRTC_DATE_TC] = cy[15:12]; |
tmp[`RTC_RRTC_DATE_C] = cy[11:8]; |
tmp[`RTC_RRTC_DATE_TY] = cy[7:4]; |
tmp[`RTC_RRTC_DATE_Y] = cy[3:0]; |
tb_top.wb_master.wr(`RTC_RRTC_DATE<<2, tmp, 4'b1111); |
end |
|
endtask |
|
// |
// Set RTC_RRTC_TALRM register |
// |
task settalrm; |
input [4:0] en; |
input [2:0] dow; |
input [5:0] hr; |
input [6:0] min; |
input [6:0] sec; |
input [3:0] tos; |
|
reg [31:0] tmp; |
|
begin |
tmp[31:27] = en; |
tmp[`RTC_RRTC_TIME_DOW] = dow[2:0]; |
tmp[`RTC_RRTC_TIME_TH] = hr[5:4]; |
tmp[`RTC_RRTC_TIME_H] = hr[3:0]; |
tmp[`RTC_RRTC_TIME_TM] = min[6:4]; |
tmp[`RTC_RRTC_TIME_M] = min[3:0]; |
tmp[`RTC_RRTC_TIME_TS] = sec[6:4]; |
tmp[`RTC_RRTC_TIME_S] = sec[3:0]; |
tmp[`RTC_RRTC_TIME_TOS] = tos[3:0]; |
tb_top.wb_master.wr(`RTC_RRTC_TALRM<<2, tmp, 4'b1111); |
end |
|
endtask |
|
// |
// Set RTC_RRTC_DALRM register |
// |
task setdalrm; |
input [3:0] en; |
input [5:0] d; |
input [4:0] m; |
input [15:0] cy; |
|
reg [31:0] tmp; |
|
begin |
tmp[30:27] = en; |
tmp[`RTC_RRTC_DATE_TD] = d[5:4]; |
tmp[`RTC_RRTC_DATE_D] = d[3:0]; |
tmp[`RTC_RRTC_DATE_TM] = m[4]; |
tmp[`RTC_RRTC_DATE_M] = m[3:0]; |
tmp[`RTC_RRTC_DATE_TC] = cy[15:12]; |
tmp[`RTC_RRTC_DATE_C] = cy[11:8]; |
tmp[`RTC_RRTC_DATE_TY] = cy[7:4]; |
tmp[`RTC_RRTC_DATE_Y] = cy[3:0]; |
tb_top.wb_master.wr(`RTC_RRTC_DALRM<<2, tmp, 4'b1111); |
end |
|
endtask |
|
// |
// Display Day of Week |
// |
task showdow; |
input [2:0] dow; |
|
begin |
case (dow) |
3'd1: $write("Sun"); |
3'd2: $write("Mon"); |
3'd3: $write("Tue"); |
3'd4: $write("Wed"); |
3'd5: $write("Thu"); |
3'd6: $write("Fri"); |
3'd7: $write("Sat"); |
default: $write("XXX"); |
endcase |
end |
|
endtask |
|
// |
// Display RTC_RRTC_TIME register |
// |
task showtime; |
|
reg [31:0] tmp; |
|
begin |
tb_top.wb_master.rd(`RTC_RRTC_TIME<<2, tmp); |
showdow(tmp[`RTC_RRTC_TIME_DOW]); |
$write(" %h%h:", tmp[`RTC_RRTC_TIME_TH], tmp[`RTC_RRTC_TIME_H]); |
$write("%h%h:", tmp[`RTC_RRTC_TIME_TM], tmp[`RTC_RRTC_TIME_M]); |
$write("%h%h:%h ", tmp[`RTC_RRTC_TIME_TS], tmp[`RTC_RRTC_TIME_S], tmp[`RTC_RRTC_TIME_TOS]); |
end |
|
endtask |
|
// |
// Display RTC_RRTC_TALRM register |
// |
task showtalrm; |
|
reg [31:0] tmp; |
|
begin |
tb_top.wb_master.rd(`RTC_RRTC_TALRM<<2, tmp); |
$write("TALRM: %b", tmp[31:27]); |
showdow(tmp[`RTC_RRTC_TIME_DOW]); |
$write(" %h%h:", tmp[`RTC_RRTC_TIME_TH], tmp[`RTC_RRTC_TIME_H]); |
$write("%h%h:", tmp[`RTC_RRTC_TIME_TM], tmp[`RTC_RRTC_TIME_M]); |
$write("%h%h:%h ", tmp[`RTC_RRTC_TIME_TS], tmp[`RTC_RRTC_TIME_S], tmp[`RTC_RRTC_TIME_TOS]); |
end |
|
endtask |
|
// |
// Display RTC_RRTC_DATE register |
// |
task showdate; |
|
reg [31:0] tmp; |
|
begin |
tb_top.wb_master.rd(`RTC_RRTC_DATE<<2, tmp); |
$write("%h%h.", tmp[`RTC_RRTC_DATE_TD], tmp[`RTC_RRTC_DATE_D]); |
$write("%h%h.", tmp[`RTC_RRTC_DATE_TM], tmp[`RTC_RRTC_DATE_M]); |
$write("%h%h", tmp[`RTC_RRTC_DATE_TC], tmp[`RTC_RRTC_DATE_C]); |
$write("%h%h ", tmp[`RTC_RRTC_DATE_TY], tmp[`RTC_RRTC_DATE_Y]); |
end |
|
endtask |
|
// |
// Display RTC_RRTC_DALRM register |
// |
task showdalrm; |
|
reg [31:0] tmp; |
|
begin |
tb_top.wb_master.rd(`RTC_RRTC_DATE<<2, tmp); |
$write("DALRM: %b %h%h.", tmp[30:27], tmp[`RTC_RRTC_DATE_TD], tmp[`RTC_RRTC_DATE_D]); |
$write("%h%h.", tmp[`RTC_RRTC_DATE_TM], tmp[`RTC_RRTC_DATE_M]); |
$write("%h%h", tmp[`RTC_RRTC_DATE_TC], tmp[`RTC_RRTC_DATE_C]); |
$write("%h%h ", tmp[`RTC_RRTC_DATE_TY], tmp[`RTC_RRTC_DATE_Y]); |
end |
|
endtask |
|
// |
// Compare parameters with RTC_RRTC_TIME register |
// |
task comp_time; |
input [2:0] dow; |
input [5:0] hr; |
input [6:0] min; |
input [6:0] sec; |
input [3:0] tos; |
output ret; |
|
reg [31:0] tmp; |
reg ret; |
begin |
tb_top.wb_master.rd(`RTC_RRTC_TIME<<2, tmp); |
|
if (tmp[`RTC_RRTC_TIME_DOW] == dow[2:0] && |
tmp[`RTC_RRTC_TIME_TH] == hr[5:4] && |
tmp[`RTC_RRTC_TIME_H] == hr[3:0] && |
tmp[`RTC_RRTC_TIME_TM] == min[6:4] && |
tmp[`RTC_RRTC_TIME_M] == min[3:0] && |
tmp[`RTC_RRTC_TIME_TS] == sec[6:4] && |
tmp[`RTC_RRTC_TIME_S] == sec[3:0] && |
tmp[`RTC_RRTC_TIME_TOS] == tos[3:0]) |
ret = 1; |
else |
ret = 0; |
end |
|
endtask |
|
// |
// Compare parameters with RTC_RRTC_DATE register |
// |
task comp_date; |
input [5:0] d; |
input [4:0] m; |
input [15:0] cy; |
output ret; |
|
reg [31:0] tmp; |
reg ret; |
begin |
tb_top.wb_master.rd(`RTC_RRTC_DATE<<2, tmp); |
|
if (tmp[`RTC_RRTC_DATE_TD] == d[5:4] && |
tmp[`RTC_RRTC_DATE_D] == d[3:0] && |
tmp[`RTC_RRTC_DATE_TM] == m[4] && |
tmp[`RTC_RRTC_DATE_M] == m[3:0] && |
tmp[`RTC_RRTC_DATE_TC] == cy[15:12] && |
tmp[`RTC_RRTC_DATE_C] == cy[11:8] && |
tmp[`RTC_RRTC_DATE_TY] == cy[7:4] && |
tmp[`RTC_RRTC_DATE_Y] == cy[3:0]) |
ret = 1; |
else |
ret = 0; |
end |
|
endtask |
|
// |
// Display RTC_RRTC_CTRL register |
// |
task showctrl; |
|
reg [31:0] tmp; |
|
begin |
tb_top.wb_master.rd(`RTC_RRTC_CTRL<<2, tmp); |
$write("RTC_RRTC_CTRL: %h", tmp); |
end |
|
endtask |
|
// |
// Get linear value of time in tenths of a second (no date included) |
// |
task getlineartime; |
output [31:0] lin; |
reg [31:0] tmp; |
integer l; |
|
begin |
tb_top.wb_master.rd(`RTC_RRTC_TIME<<2, tmp); |
l = tmp[`RTC_RRTC_TIME_TH] * 360000 + tmp[`RTC_RRTC_TIME_H] * 36000; |
l = l + tmp[`RTC_RRTC_TIME_TM] * 6000 + tmp[`RTC_RRTC_TIME_M] * 600; |
l = l + tmp[`RTC_RRTC_TIME_TS] * 100 + tmp[`RTC_RRTC_TIME_S] * 10 + tmp[`RTC_RRTC_TIME_TOS]; |
lin = l; |
end |
|
endtask |
|
// |
// Get linear value of alarm time in tenths of a second (no date included) |
// |
task getlineartalrm; |
output [31:0] lin; |
reg [31:0] tmp; |
integer l; |
|
begin |
tb_top.wb_master.rd(`RTC_RRTC_TALRM<<2, tmp); |
l = tmp[`RTC_RRTC_TALRM_TH] * 360000 + tmp[`RTC_RRTC_TALRM_H] * 36000; |
l = l + tmp[`RTC_RRTC_TALRM_TM] * 6000 + tmp[`RTC_RRTC_TALRM_M] * 600; |
l = l + tmp[`RTC_RRTC_TALRM_TS] * 100 + tmp[`RTC_RRTC_TALRM_S] * 10 + tmp[`RTC_RRTC_TALRM_TOS]; |
lin = l; |
end |
|
endtask |
|
// |
// Test operation of control bit RTC_RRTC_CTRL[ECLK] |
// |
task test_eclk; |
integer l1; |
integer l2; |
reg [31:0] ctrl; |
begin |
$write(" Testing control bit RTC_RRTC_CTRL[ECLK] ..."); |
|
// |
// Phase 1 |
// |
// RTC uses WISHBONE clock |
// |
|
// Disable RTC |
ctrl = 0; |
#100 tb_top.wb_master.wr(`RTC_RRTC_CTRL<<2, ctrl, 4'hf); |
|
// Set time to zero |
#100 tb_tasks.settime('h0, 'h0, 'h0, 'h0, 'h0); |
|
// Enable RTC, divider 'd16+2 |
ctrl = 1 << `RTC_RRTC_CTRL_EN | 'h10; |
#100 tb_top.wb_master.wr(`RTC_RRTC_CTRL<<2, ctrl, 4'hf); |
`ifdef RTC_DEBUG |
$display; |
#100 showctrl; |
`endif |
|
// Wait for time to advance |
#80000; |
|
// Get linear time |
tb_tasks.getlineartime(l1); |
`ifdef RTC_DEBUG |
$display; |
tb_tasks.showtime; |
$display(" linear: %d ", l1); |
`endif |
|
// |
// Phase 2 |
// |
// Use external RTC clock instead of WISHBONE clock. |
// Generate 2x more clock cycles than in phase 1. |
// |
|
// Disable RTC |
ctrl = 0; |
#100 tb_top.wb_master.wr(`RTC_RRTC_CTRL<<2, ctrl, 4'hf); |
|
// Set time to zero |
#100 tb_tasks.settime('h0, 'h0, 'h0, 'h0, 'h0); |
|
// Enable RTC, enable external clock, divider 'd16+2 |
ctrl = 1 << `RTC_RRTC_CTRL_EN | 1 << `RTC_RRTC_CTRL_ECLK | 'h10; |
#100 tb_top.wb_master.wr(`RTC_RRTC_CTRL<<2, ctrl, 4'hf); |
`ifdef RTC_DEBUG |
$display; |
#100 showctrl; |
`endif |
|
// Wait for time to advance |
// Generate 20000 external clock cycles |
tb_top.clkrst.gen_rtc_clk(20000); |
|
// Get linear time |
tb_tasks.getlineartime(l2); |
`ifdef RTC_DEBUG |
$display; |
tb_tasks.showtime; |
$display(" linear: %d ", l2); |
`endif |
|
// |
// Phase 3 |
// Compare phase 1 and phase 2 |
// Phase 2 should be 2x more than phase 1 |
// |
if (l2 - l1 == l1) |
$display(" OK"); |
else |
failed; |
end |
endtask |
|
// |
// Test operation of control bit RTC_RRTC_CTRL[EN] |
// |
task test_en; |
integer l1; |
integer l2; |
integer l3; |
reg [31:0] ctrl; |
begin |
$write(" Testing control bit RTC_RRTC_CTRL[EN] ..."); |
|
// |
// Phase 1 |
// |
// Run RTC off external clock for 5000 cycles |
// |
|
// Disable RTC |
ctrl = 0; |
#100 tb_top.wb_master.wr(`RTC_RRTC_CTRL<<2, ctrl, 4'hf); |
|
// Set time to zero |
#100 tb_tasks.settime('h0, 'h0, 'h0, 'h0, 'h0); |
|
// Enable RTC, enable external clock, divider 'd18+2 |
ctrl = 1 << `RTC_RRTC_CTRL_EN | 1 << `RTC_RRTC_CTRL_ECLK | 'h12; |
#100 tb_top.wb_master.wr(`RTC_RRTC_CTRL<<2, ctrl, 4'hf); |
`ifdef RTC_DEBUG |
$display; |
#100 showctrl; |
`endif |
|
// Wait for time to advance |
// Generate 5000 external clock cycles |
tb_top.clkrst.gen_rtc_clk(5000); |
|
// Get linear time |
#100 tb_tasks.getlineartime(l1); |
`ifdef RTC_DEBUG |
$display; |
tb_tasks.showtime; |
$display(" linear: %d ", l1); |
`endif |
|
// |
// Phase 2 |
// |
// Run disabled RTC off external clock for 5000 cycles |
// |
|
// Disable RTC, enable external clock, divider 'd18+2 |
ctrl = 1 << `RTC_RRTC_CTRL_ECLK | 'h12; |
#100 tb_top.wb_master.wr(`RTC_RRTC_CTRL<<2, ctrl, 4'hf); |
`ifdef RTC_DEBUG |
$display; |
#100 showctrl; |
`endif |
|
// Wait for time to advance |
// Generate 5000 external clock cycles |
tb_top.clkrst.gen_rtc_clk(5000); |
|
// Get linear time |
tb_tasks.getlineartime(l2); |
`ifdef RTC_DEBUG |
$display; |
tb_tasks.showtime; |
$display(" linear: %d ", l2); |
`endif |
|
// |
// Phase 3 |
// |
// Re-enable RTC and run it off external clock for 5000 cycles |
// |
|
// Enable RTC, enable external clock, divider 'd18+2 |
ctrl = 1 << `RTC_RRTC_CTRL_EN | 1 << `RTC_RRTC_CTRL_ECLK | 'h12; |
#100 tb_top.wb_master.wr(`RTC_RRTC_CTRL<<2, ctrl, 4'hf); |
`ifdef RTC_DEBUG |
$display; |
#100 showctrl; |
`endif |
|
// Wait for time to advance |
// Generate 5000 external clock cycles |
tb_top.clkrst.gen_rtc_clk(5000); |
|
// Get linear time |
tb_tasks.getlineartime(l3); |
`ifdef RTC_DEBUG |
$display; |
tb_tasks.showtime; |
$display(" linear: %d ", l3); |
`endif |
|
// |
// Phase 4 |
// |
// Compare phase 1, phase 2 and phase 3 |
// Phase 1 and 2 should be equal and non-zero. |
// Phase 3 should be more than 1 or 2. |
// |
$display("xxxx", l1, l2, l3); |
if (l1 && (l1 == l2) && (l3 > l2)) |
$display(" OK"); |
else |
failed; |
end |
endtask |
|
// |
// Test operation of control bit RTC_RRTC_CTRL[DIV] |
// |
task test_div; |
integer l1; |
integer l2; |
reg [31:0] ctrl; |
begin |
$write(" Testing control bit RTC_RRTC_CTRL[DIV] ..."); |
|
// |
// Phase 1 |
// |
// Run RTC off external clock for 5000 cycles |
// |
|
// Disable RTC |
ctrl = 0; |
#100 tb_top.wb_master.wr(`RTC_RRTC_CTRL<<2, ctrl, 4'hf); |
|
// Set time to zero |
#100 tb_tasks.settime('h0, 'h0, 'h0, 'h0, 'h0); |
|
// Enable RTC, enable external clock, divider 'd2 |
ctrl = 1 << `RTC_RRTC_CTRL_EN | 1 << `RTC_RRTC_CTRL_ECLK | 'h0; |
#100 tb_top.wb_master.wr(`RTC_RRTC_CTRL<<2, ctrl, 4'hf); |
`ifdef RTC_DEBUG |
$display; |
#100 showctrl; |
`endif |
|
// Wait for time to advance |
// Generate 5000 external clock cycles |
tb_top.clkrst.gen_rtc_clk(5000); |
|
// Get linear time |
tb_tasks.getlineartime(l1); |
`ifdef RTC_DEBUG |
$display; |
tb_tasks.showtime; |
$display(" linear: %d ", l1); |
`endif |
|
// |
// Phase 2 |
// |
// Run RTC for another 5000 cycles with different divider |
// |
|
// Enable RTC, enable external clock, divider 'd2+2 |
ctrl = 1 << `RTC_RRTC_CTRL_EN | 1 << `RTC_RRTC_CTRL_ECLK | 'h1; |
#100 tb_top.wb_master.wr(`RTC_RRTC_CTRL<<2, ctrl, 4'hf); |
`ifdef RTC_DEBUG |
$display; |
#100 showctrl; |
`endif |
|
// Wait for time to advance |
// Generate 5000 external clock cycles |
tb_top.clkrst.gen_rtc_clk(5000); |
|
// Get linear time |
tb_tasks.getlineartime(l2); |
`ifdef RTC_DEBUG |
$display; |
tb_tasks.showtime; |
$display(" linear: %d ", l2); |
`endif |
|
// |
// Phase 3 |
// |
// Phase 1 should be 2500 and phase 2 should be 2500+1250. |
// |
if ((l2 - l1) == 1250) |
$display(" OK"); |
else |
failed; |
end |
endtask |
|
// |
// Test operation of RTC_RRTC_TALRM |
// |
task test_talrm; |
reg a0; |
reg a1; |
reg [31:0] ctrl; |
begin |
|
// Clear date alarms |
#100 tb_tasks.setdalrm('b0000, 'h00, 'h00, 'h0000); |
|
// |
// Phase 1 |
// |
// Check tenths of a second alarm |
// |
|
$write(" Testing Alarm RTC_RRTC_TALRM[CTOS] ..."); |
|
// Disable RTC |
ctrl = 0; |
#100 tb_top.wb_master.wr(`RTC_RRTC_CTRL<<2, ctrl, 4'hf); |
|
// Set time to zero |
#100 tb_tasks.settime('h0, 'h0, 'h0, 'h0, 'h0); |
|
// Set TOS alarm to 9 |
#100 tb_tasks.settalrm('b00001, 'h0, 'h0, 'h0, 'h0, 'h9); |
|
// Enable RTC, enable external clock, divider 'd2 |
ctrl = 1 << `RTC_RRTC_CTRL_EN | 1 << `RTC_RRTC_CTRL_ECLK | 'h0; |
#100 tb_top.wb_master.wr(`RTC_RRTC_CTRL<<2, ctrl, 4'hf); |
`ifdef RTC_DEBUG |
$display; |
#100 showctrl; |
`endif |
|
// Advance time for 0.7 seconds, get alarm flag, |
// advance 0.2 second and get alarm flag again |
tb_top.clkrst.gen_rtc_clk(16); |
tb_top.wb_master.rd(`RTC_RRTC_CTRL<<2, ctrl); |
a0 = ctrl[`RTC_RRTC_CTRL_ALRM]; |
tb_top.clkrst.gen_rtc_clk(2); |
tb_top.wb_master.rd(`RTC_RRTC_CTRL<<2, ctrl); |
a1 = ctrl[`RTC_RRTC_CTRL_ALRM]; |
|
// Is alarm flag set? |
if (a1 > a0) |
$display(" OK"); |
else |
failed; |
|
// |
// Phase 2 |
// |
// Check seconds alarm |
// |
|
$write(" Testing Alarm RTC_RRTC_TALRM[CS] ..."); |
|
// Disable RTC |
ctrl = 0; |
#100 tb_top.wb_master.wr(`RTC_RRTC_CTRL<<2, ctrl, 4'hf); |
|
// Set time to zero |
#100 tb_tasks.settime('h0, 'h0, 'h0, 'h0, 'h0); |
|
// Set seconds alarm to 9 |
#100 tb_tasks.settalrm('b00010, 'h0, 'h0, 'h0, 'h10, 'h0); |
|
// Enable RTC, enable external clock, divider 'd2 |
ctrl = 1 << `RTC_RRTC_CTRL_EN | 1 << `RTC_RRTC_CTRL_ECLK | 'h0; |
#100 tb_top.wb_master.wr(`RTC_RRTC_CTRL<<2, ctrl, 4'hf); |
`ifdef RTC_DEBUG |
$display; |
#100 showctrl; |
`endif |
|
// Advance time for 9.8 seconds, get alarm flag, |
// advance 0.2 second and get alarm flag again |
tb_top.clkrst.gen_rtc_clk(198); |
tb_top.wb_master.rd(`RTC_RRTC_CTRL<<2, ctrl); |
a0 = ctrl[`RTC_RRTC_CTRL_ALRM]; |
tb_top.clkrst.gen_rtc_clk(2); |
tb_top.wb_master.rd(`RTC_RRTC_CTRL<<2, ctrl); |
a1 = ctrl[`RTC_RRTC_CTRL_ALRM]; |
|
// Is alarm flag set? |
if (a1 > a0) |
$display(" OK"); |
else |
failed; |
|
// |
// Phase 3 |
// |
// Check minutes alarm |
// |
|
$write(" Testing Alarm RTC_RRTC_TALRM[CM] ..."); |
|
// Disable RTC |
ctrl = 0; |
#100 tb_top.wb_master.wr(`RTC_RRTC_CTRL<<2, ctrl, 4'hf); |
|
// Set time to 00:02:00:0 |
#100 tb_tasks.settime('h0, 'h0, 'h02, 'h0, 'h0); |
|
// Set minutes alarm to 4 |
#100 tb_tasks.settalrm('b00100, 'h0, 'h0, 'h4, 'h0, 'h0); |
|
// Enable RTC, enable external clock, divider 'd2 |
ctrl = 1 << `RTC_RRTC_CTRL_EN | 1 << `RTC_RRTC_CTRL_ECLK | 'h0; |
#100 tb_top.wb_master.wr(`RTC_RRTC_CTRL<<2, ctrl, 4'hf); |
`ifdef RTC_DEBUG |
$display; |
#100 showctrl; |
`endif |
|
// Advance time for 119.8 seconds, get alarm flag, |
// advance 0.2 second and get alarm flag again |
tb_top.clkrst.gen_rtc_clk(2398); |
tb_top.wb_master.rd(`RTC_RRTC_CTRL<<2, ctrl); |
a0 = ctrl[`RTC_RRTC_CTRL_ALRM]; |
tb_top.clkrst.gen_rtc_clk(2); |
tb_top.wb_master.rd(`RTC_RRTC_CTRL<<2, ctrl); |
a1 = ctrl[`RTC_RRTC_CTRL_ALRM]; |
|
// Is alarm flag set? |
if (a1 > a0) |
$display(" OK"); |
else |
failed; |
|
// |
// Phase 4 |
// |
// Check hours alarm |
// |
|
$write(" Testing Alarm RTC_RRTC_TALRM[CH] ..."); |
|
// Disable RTC |
ctrl = 0; |
#100 tb_top.wb_master.wr(`RTC_RRTC_CTRL<<2, ctrl, 4'hf); |
|
// Set time to zero |
#100 tb_tasks.settime('h0, 'h0, 'h58, 'h0, 'h0); |
|
// Set hours alarm to 01:00:00:0 |
#100 tb_tasks.settalrm('b01000, 'h0, 'h1, 'h0, 'h0, 'h0); |
|
// Enable RTC, enable external clock, divider 'd2 |
ctrl = 1 << `RTC_RRTC_CTRL_EN | 1 << `RTC_RRTC_CTRL_ECLK | 'h0; |
#100 tb_top.wb_master.wr(`RTC_RRTC_CTRL<<2, ctrl, 4'hf); |
`ifdef RTC_DEBUG |
$display; |
#100 showctrl; |
`endif |
|
// Advance time for 119.8 seconds, get alarm flag, |
// advance 0.2 second and get alarm flag again |
tb_top.clkrst.gen_rtc_clk(2398); |
tb_top.wb_master.rd(`RTC_RRTC_CTRL<<2, ctrl); |
a0 = ctrl[`RTC_RRTC_CTRL_ALRM]; |
tb_top.clkrst.gen_rtc_clk(2); |
tb_top.wb_master.rd(`RTC_RRTC_CTRL<<2, ctrl); |
a1 = ctrl[`RTC_RRTC_CTRL_ALRM]; |
|
// Is alarm flag set? |
if (a1 > a0) |
$display(" OK"); |
else |
failed; |
|
// |
// Phase 5 |
// |
// Check day of week alarm |
// |
|
$write(" Testing Alarm RTC_RRTC_TALRM[CDOW] ..."); |
|
// Disable RTC |
ctrl = 0; |
#100 tb_top.wb_master.wr(`RTC_RRTC_CTRL<<2, ctrl, 4'hf); |
|
// Set time to 23:58:00 |
#100 tb_tasks.settime('h1, 'h23, 'h58, 'h0, 'h0); |
|
// Set DOW alarm to 1 |
#100 tb_tasks.settalrm('b10000, 'h2, 'h0, 'h0, 'h0, 'h0); |
|
// Enable RTC, enable external clock, divider 'd2 |
ctrl = 1 << `RTC_RRTC_CTRL_EN | 1 << `RTC_RRTC_CTRL_ECLK | 'h0; |
#100 tb_top.wb_master.wr(`RTC_RRTC_CTRL<<2, ctrl, 4'hf); |
`ifdef RTC_DEBUG |
$display; |
#100 showctrl; |
`endif |
|
// Advance time for 119.8 seconds, get alarm flag, |
// advance 0.2 second and get alarm flag again |
tb_top.clkrst.gen_rtc_clk(2398); |
tb_top.wb_master.rd(`RTC_RRTC_CTRL<<2, ctrl); |
a0 = ctrl[`RTC_RRTC_CTRL_ALRM]; |
tb_top.clkrst.gen_rtc_clk(2); |
tb_top.wb_master.rd(`RTC_RRTC_CTRL<<2, ctrl); |
a1 = ctrl[`RTC_RRTC_CTRL_ALRM]; |
|
// Is alarm flag set? |
if (a1 > a0) |
$display(" OK"); |
else |
failed; |
|
// Clear all time alarms |
#100 tb_tasks.settalrm('b00000, 'h0, 'h0, 'h0, 'h0, 'h0); |
|
end |
endtask |
|
// |
// Test operation of RTC_RRTC_DALRM |
// |
task test_dalrm; |
reg a0; |
reg a1; |
reg [31:0] ctrl; |
begin |
|
// Clear time alarms |
#100 tb_tasks.settalrm('b00000, 'h0, 'h00, 'h00, 'h00, 'h0); |
|
// |
// Phase 1 |
// |
// Check days alarm |
// |
|
$write(" Testing Alarm RTC_RRTC_DALRM[CD] ..."); |
|
// Disable RTC |
ctrl = 0; |
#100 tb_top.wb_master.wr(`RTC_RRTC_CTRL<<2, ctrl, 4'hf); |
|
// Set time to 23:58:00:0 |
#100 tb_tasks.settime('h0, 'h23, 'h58, 'h00, 'h0); |
|
// Set date to 1.1.2000 |
#100 tb_tasks.setdate('h01, 'h01, 'h2000); |
|
// Set days alarm to 2 |
#100 tb_tasks.setdalrm('b0001, 'h2, 'h0, 'h0000); |
|
// Enable RTC, enable external clock, divider 'd2 |
ctrl = 1 << `RTC_RRTC_CTRL_EN | 1 << `RTC_RRTC_CTRL_ECLK | 'h0; |
#100 tb_top.wb_master.wr(`RTC_RRTC_CTRL<<2, ctrl, 4'hf); |
`ifdef RTC_DEBUG |
$display; |
#100 showctrl; |
`endif |
|
// Advance time for 119.8 seconds, get alarm flag, |
// advance 0.2 second and get alarm flag again |
tb_top.clkrst.gen_rtc_clk(2398); |
tb_top.wb_master.rd(`RTC_RRTC_CTRL<<2, ctrl); |
a0 = ctrl[`RTC_RRTC_CTRL_ALRM]; |
tb_top.clkrst.gen_rtc_clk(2); |
tb_top.wb_master.rd(`RTC_RRTC_CTRL<<2, ctrl); |
a1 = ctrl[`RTC_RRTC_CTRL_ALRM]; |
|
// Is alarm flag set? |
if (a1 > a0) |
$display(" OK"); |
else |
failed; |
|
// |
// Phase 2 |
// |
// Check months alarm |
// |
|
$write(" Testing Alarm RTC_RRTC_DALRM[CM] ..."); |
|
// Disable RTC |
ctrl = 0; |
#100 tb_top.wb_master.wr(`RTC_RRTC_CTRL<<2, ctrl, 4'hf); |
|
// Set time to 23:58:00:0 |
#100 tb_tasks.settime('h0, 'h23, 'h58, 'h00, 'h0); |
|
// Set date to 31.1.2000 |
#100 tb_tasks.setdate('h31, 'h01, 'h2000); |
|
// Set months alarm to 2 |
#100 tb_tasks.setdalrm('b0010, 'h0, 'h2, 'h0000); |
|
// Enable RTC, enable external clock, divider 'd2 |
ctrl = 1 << `RTC_RRTC_CTRL_EN | 1 << `RTC_RRTC_CTRL_ECLK | 'h0; |
#100 tb_top.wb_master.wr(`RTC_RRTC_CTRL<<2, ctrl, 4'hf); |
`ifdef RTC_DEBUG |
$display; |
#100 showctrl; |
`endif |
|
// Advance time for 119.8 seconds, get alarm flag, |
// advance 0.2 second and get alarm flag again |
tb_top.clkrst.gen_rtc_clk(2398); |
tb_top.wb_master.rd(`RTC_RRTC_CTRL<<2, ctrl); |
a0 = ctrl[`RTC_RRTC_CTRL_ALRM]; |
tb_top.clkrst.gen_rtc_clk(2); |
tb_top.wb_master.rd(`RTC_RRTC_CTRL<<2, ctrl); |
a1 = ctrl[`RTC_RRTC_CTRL_ALRM]; |
|
// Is alarm flag set? |
if (a1 > a0) |
$display(" OK"); |
else |
failed; |
|
// |
// Phase 3 |
// |
// Check years alarm |
// |
|
$write(" Testing Alarm RTC_RRTC_DALRM[CY] ..."); |
|
// Disable RTC |
ctrl = 0; |
#100 tb_top.wb_master.wr(`RTC_RRTC_CTRL<<2, ctrl, 4'hf); |
|
// Set time to 23:58:00:0 |
#100 tb_tasks.settime('h0, 'h23, 'h58, 'h00, 'h0); |
|
// Set date to 31.12.2000 |
#100 tb_tasks.setdate('h31, 'h12, 'h2000); |
|
// Set year alarm to 01 |
#100 tb_tasks.setdalrm('b0100, 'h0, 'h0, 'h0001); |
|
// Enable RTC, enable external clock, divider 'd2 |
ctrl = 1 << `RTC_RRTC_CTRL_EN | 1 << `RTC_RRTC_CTRL_ECLK | 'h0; |
#100 tb_top.wb_master.wr(`RTC_RRTC_CTRL<<2, ctrl, 4'hf); |
`ifdef RTC_DEBUG |
$display; |
#100 showctrl; |
`endif |
|
// Advance time for 119.8 seconds, get alarm flag, |
// advance 0.2 second and get alarm flag again |
tb_top.clkrst.gen_rtc_clk(2398); |
tb_top.wb_master.rd(`RTC_RRTC_CTRL<<2, ctrl); |
a0 = ctrl[`RTC_RRTC_CTRL_ALRM]; |
tb_top.clkrst.gen_rtc_clk(2); |
tb_top.wb_master.rd(`RTC_RRTC_CTRL<<2, ctrl); |
a1 = ctrl[`RTC_RRTC_CTRL_ALRM]; |
|
// Is alarm flag set? |
if (a1 > a0) |
$display(" OK"); |
else |
failed; |
|
// |
// Phase 4 |
// |
// Check century alarm |
// |
|
$write(" Testing Alarm RTC_RRTC_DALRM[CC] ..."); |
|
// Disable RTC |
ctrl = 0; |
#100 tb_top.wb_master.wr(`RTC_RRTC_CTRL<<2, ctrl, 4'hf); |
|
// Set time to 23:58:00:0 |
#100 tb_tasks.settime('h0, 'h23, 'h58, 'h00, 'h0); |
|
// Set date to 31.12.2099 |
#100 tb_tasks.setdate('h31, 'h12, 'h2099); |
|
// Set century alarm to 21 |
#100 tb_tasks.setdalrm('b1000, 'h0, 'h0, 'h2100); |
|
// Enable RTC, enable external clock, divider 'd2 |
ctrl = 1 << `RTC_RRTC_CTRL_EN | 1 << `RTC_RRTC_CTRL_ECLK | 'h0; |
#100 tb_top.wb_master.wr(`RTC_RRTC_CTRL<<2, ctrl, 4'hf); |
`ifdef RTC_DEBUG |
$display; |
#100 showctrl; |
`endif |
|
// Advance time for 119.8 seconds, get alarm flag, |
// advance 0.2 second and get alarm flag again |
tb_top.clkrst.gen_rtc_clk(2398); |
tb_top.wb_master.rd(`RTC_RRTC_CTRL<<2, ctrl); |
a0 = ctrl[`RTC_RRTC_CTRL_ALRM]; |
tb_top.clkrst.gen_rtc_clk(2); |
tb_top.wb_master.rd(`RTC_RRTC_CTRL<<2, ctrl); |
a1 = ctrl[`RTC_RRTC_CTRL_ALRM]; |
|
// Is alarm flag set? |
if (a1 > a0) |
$display(" OK"); |
else |
failed; |
|
// Clear all date alarms |
#100 tb_tasks.setdalrm('b0000, 'h00, 'h00, 'h0000); |
end |
|
endtask |
|
// |
// Test operation of RTC_RRTC_CTRL[INTE] and RTC_RRTC_CRTL[INT] |
// |
task test_inte_int; |
reg a0; |
reg a1; |
reg [31:0] ctrl; |
begin |
|
// Clear time alarms |
#100 tb_tasks.settalrm('b00000, 'h0, 'h00, 'h00, 'h00, 'h0); |
|
// |
// Phase 1 |
// |
// Set days alarm, disable ints |
// |
|
$write(" Testing RTC_RRTC_CTRL[INTE] ..."); |
|
// Disable RTC |
ctrl = 0; |
#100 tb_top.wb_master.wr(`RTC_RRTC_CTRL<<2, ctrl, 4'hf); |
|
// Set time to 23:58:00:0 |
#100 tb_tasks.settime('h0, 'h23, 'h58, 'h00, 'h0); |
|
// Set date to 1.1.2000 |
#100 tb_tasks.setdate('h01, 'h01, 'h2000); |
|
// Set days alarm to 2 |
#100 tb_tasks.setdalrm('b0001, 'h2, 'h0, 'h0000); |
|
// Enable RTC, enable external clock, divider 'd2 |
ctrl = 1 << `RTC_RRTC_CTRL_EN | 1 << `RTC_RRTC_CTRL_ECLK | 'h0; |
#100 tb_top.wb_master.wr(`RTC_RRTC_CTRL<<2, ctrl, 4'hf); |
`ifdef RTC_DEBUG |
$display; |
#100 showctrl; |
`endif |
|
// Advance time for 119.9 seconds, get alarm flag, |
// advance 0.1 second and get alarm flag again |
tb_top.clkrst.gen_rtc_clk(2398); |
tb_top.wb_master.rd(`RTC_RRTC_CTRL<<2, ctrl); |
a0 = ctrl[`RTC_RRTC_CTRL_ALRM]; |
tb_top.clkrst.gen_rtc_clk(2); |
tb_top.wb_master.rd(`RTC_RRTC_CTRL<<2, ctrl); |
a1 = ctrl[`RTC_RRTC_CTRL_ALRM]; |
|
// Is alarm flag set and interrupt cleared? |
if ((a1 > a0) && !tb_top.rtc.wb_inta_o) |
$display(" OK"); |
else |
failed; |
|
// |
// Phase 2 |
// |
// Set days alarm, enable ints |
// |
|
$write(" Testing interrupt request assertion ..."); |
|
// Disable RTC |
ctrl = 0; |
#100 tb_top.wb_master.wr(`RTC_RRTC_CTRL<<2, ctrl, 4'hf); |
|
// Set time to 23:58:00:0 |
#100 tb_tasks.settime('h0, 'h23, 'h58, 'h00, 'h0); |
|
// Set date to 1.1.2000 |
#100 tb_tasks.setdate('h01, 'h01, 'h2000); |
|
// Set days alarm to 2 |
#100 tb_tasks.setdalrm('b0001, 'h2, 'h0, 'h0000); |
|
// Enable RTC, enable interrupts enable external clock, divider 'd2 |
ctrl = 1 << `RTC_RRTC_CTRL_EN | 1 << `RTC_RRTC_CTRL_INTE | 1 << `RTC_RRTC_CTRL_ECLK | 'h0; |
#100 tb_top.wb_master.wr(`RTC_RRTC_CTRL<<2, ctrl, 4'hf); |
`ifdef RTC_DEBUG |
$display; |
#100 showctrl; |
`endif |
|
// Advance time for 119.8 seconds, get alarm flag, |
// advance 0.2 second and get alarm flag again |
tb_top.clkrst.gen_rtc_clk(2398); |
tb_top.wb_master.rd(`RTC_RRTC_CTRL<<2, ctrl); |
a0 = ctrl[`RTC_RRTC_CTRL_ALRM]; |
tb_top.clkrst.gen_rtc_clk(2); |
tb_top.wb_master.rd(`RTC_RRTC_CTRL<<2, ctrl); |
a1 = ctrl[`RTC_RRTC_CTRL_ALRM]; |
|
// Is alarm flag set and interrupt asserted? |
if ((a1 > a0) && tb_top.rtc.wb_inta_o) |
$display(" OK"); |
else |
failed; |
|
// Clear RTC_RRTC_CTRL[INTE] and RTC_RRTC_CTRL[ALRM] |
ctrl = 1 << `RTC_RRTC_CTRL_EN | 1 << `RTC_RRTC_CTRL_ECLK | 'h0; |
#100 tb_top.wb_master.wr(`RTC_RRTC_CTRL<<2, ctrl, 4'hf); |
|
$write(" Testing interrupt request negation ..."); |
|
// Is interrupt request still asserted? |
tb_top.wb_master.rd(`RTC_RRTC_CTRL<<2, ctrl); |
if (!tb_top.rtc.wb_inta_o) |
$display(" OK"); |
else |
failed; |
end |
|
endtask |
|
// |
// Test correct operation of RTC_RRTC_CTRL[BTOS] bit |
// |
task test_btos; |
reg a0; |
reg a1; |
reg [31:0] ctrl; |
begin |
|
// Clear date alarms |
#100 tb_tasks.setdalrm('b0000, 'h0, 'h0, 'h0000); |
|
// |
// Phase 1 |
// |
// Check RTC_RRTC_CTRL[BTOS] |
// |
|
$write(" Testing RTC_RRTC_CTRL[BTOS] ..."); |
|
// Disable RTC |
ctrl = 0; |
#100 tb_top.wb_master.wr(`RTC_RRTC_CTRL<<2, ctrl, 4'hf); |
|
// Set time to zero |
#100 tb_tasks.settime('h0, 'h0, 'h0, 'h0, 'h0); |
|
// Set seconds alarm to 50 |
#100 tb_tasks.settalrm('b00010, 'h0, 'h0, 'h0, 'h50, 'h0); |
|
// Enable RTC, enable external clock, divider 'd2 |
ctrl = 1 << `RTC_RRTC_CTRL_EN | 1 << `RTC_RRTC_CTRL_BTOS | 1 << `RTC_RRTC_CTRL_ECLK | 'h0; |
#100 tb_top.wb_master.wr(`RTC_RRTC_CTRL<<2, ctrl, 4'hf); |
`ifdef RTC_DEBUG |
$display; |
#100 showctrl; |
`endif |
|
// Advance time for 49.5 seconds, get alarm flag, |
// advance 0.5 second and get alarm flag again |
tb_top.clkrst.gen_rtc_clk(99); |
tb_top.wb_master.rd(`RTC_RRTC_CTRL<<2, ctrl); |
a0 = ctrl[`RTC_RRTC_CTRL_ALRM]; |
tb_top.clkrst.gen_rtc_clk(1); |
tb_top.wb_master.rd(`RTC_RRTC_CTRL<<2, ctrl); |
a1 = ctrl[`RTC_RRTC_CTRL_ALRM]; |
|
// Is alarm flag set? |
if (a1 > a0) |
$display(" OK"); |
else |
failed; |
|
end |
|
endtask |
|
// |
// Test single time/date case |
// |
task test_case; |
input [31:0] stime; |
input [31:0] sdate; |
input [31:0] eclks; |
input [31:0] etime; |
input [31:0] edate; |
reg [31:0] ctrl; |
reg corr_time; |
reg corr_date; |
begin |
|
// Disable RTC |
ctrl = 0; |
#100 tb_top.wb_master.wr(`RTC_RRTC_CTRL<<2, ctrl, 4'hf); |
|
// Set start time |
#100 tb_tasks.settime(stime[30:28], stime[27:20], stime[19:12], stime[11:4], stime[3:0]); |
|
// Set start date |
#100 tb_tasks.setdate(sdate[31:24], sdate[23:16], sdate[15:0]); |
|
// Enable RTC, enable external clock, divider 'd2 |
ctrl = 1 << `RTC_RRTC_CTRL_EN | 1 << `RTC_RRTC_CTRL_ECLK | 'h0; |
#100 tb_top.wb_master.wr(`RTC_RRTC_CTRL<<2, ctrl, 4'hf); |
`ifdef RTC_DEBUG |
$display; |
#100 showctrl; |
`endif |
showtime; |
showdate; |
|
// Wait for time to advance |
// Generate external clock cycles |
tb_top.clkrst.gen_rtc_clk(eclks); |
showtime; |
showdate; |
comp_time(etime[30:28], etime[27:20], etime[19:12], etime[11:4], etime[3:0], corr_time); |
comp_date(edate[31:24], edate[23:16], edate[15:0], corr_date); |
if (corr_time && corr_date) |
$display(" OK"); |
else |
failed; |
end |
|
endtask |
|
// |
// Test time/date compliance with leapyears/Y2K etc |
// |
task test_cases; |
begin |
|
$write(" Testing Y2K compliance: "); |
test_case('h7_23_30_00_0, 'h31_12_1999, 72000, 'h1_00_30_00_0, 'h01_01_2000); |
|
$write(" Testing Y2K leap year compliance: "); |
test_case('h3_23_30_00_0, 'h28_02_2000, 72000, 'h4_00_30_00_0, 'h29_02_2000); |
|
$write(" Testing 2001 leap year compliance: "); |
test_case('h4_23_30_00_0, 'h28_02_2001, 72000, 'h5_00_30_00_0, 'h01_03_2001); |
|
$write(" Testing 2004 leap year compliance: "); |
test_case('h7_23_30_00_0, 'h28_02_2004, 72000, 'h1_00_30_00_0, 'h29_02_2004); |
|
$write(" Testing 2100 leap year compliance: "); |
test_case('h1_23_30_00_0, 'h28_02_2100, 72000, 'h2_00_30_00_0, 'h01_03_2100); |
|
$write(" Testing change from Jan to Feb: "); |
test_case('h1_23_45_00_0, 'h31_01_2000, 36000, 'h2_00_15_00_0, 'h01_02_2000); |
|
$write(" Testing change from Mar to Apr: "); |
test_case('h1_23_45_00_0, 'h31_03_2000, 36000, 'h2_00_15_00_0, 'h01_04_2000); |
|
$write(" Testing change from Apr to May: "); |
test_case('h1_23_45_00_0, 'h30_04_2000, 36000, 'h2_00_15_00_0, 'h01_05_2000); |
|
$write(" Testing change from May to Jun: "); |
test_case('h1_23_45_00_0, 'h31_05_2000, 36000, 'h2_00_15_00_0, 'h01_06_2000); |
|
$write(" Testing change from Jun to Jul: "); |
test_case('h1_23_45_00_0, 'h30_06_2000, 36000, 'h2_00_15_00_0, 'h01_07_2000); |
|
$write(" Testing change from Jul to Aug: "); |
test_case('h1_23_45_00_0, 'h31_07_2000, 36000, 'h2_00_15_00_0, 'h01_08_2000); |
|
$write(" Testing change from Aug to Sep: "); |
test_case('h1_23_45_00_0, 'h31_08_2000, 36000, 'h2_00_15_00_0, 'h01_09_2000); |
|
$write(" Testing change from Sep to Oct: "); |
test_case('h1_23_45_00_0, 'h30_09_2000, 36000, 'h2_00_15_00_0, 'h01_10_2000); |
|
$write(" Testing change from Oct to Nov: "); |
test_case('h1_23_45_00_0, 'h31_10_2000, 36000, 'h2_00_15_00_0, 'h01_11_2000); |
|
$write(" Testing change from Nov to Dec: "); |
test_case('h1_23_45_00_0, 'h30_11_2000, 36000, 'h2_00_15_00_0, 'h01_12_2000); |
|
$write(" Testing change from Dec to Jan: "); |
test_case('h1_23_45_00_0, 'h31_12_2000, 36000, 'h2_00_15_00_0, 'h01_01_2001); |
|
$write(" Testing change of a day: "); |
test_case('h1_12_34_56_7, 'h29_01_2002, 72000*24, 'h2_12_34_56_7, 'h30_01_2002); |
|
end |
|
endtask |
|
// |
// Start of testbench test tasks |
// |
initial begin |
`ifdef RTC_DUMP_VCD |
$dumpfile("../sim/tb_top.vcd"); |
$dumpvars(3, tb_top); |
`endif |
nr_failed = 0; |
$display; |
$display("###"); |
$display("### RTC IP Core Verification ###"); |
$display("###"); |
$display; |
$display("I. Testing correct operation of RTC_RRTC_CTRL control bits"); |
$display; |
tb_tasks.test_btos; |
// tb_tasks.test_eclk; |
tb_tasks.test_en; |
tb_tasks.test_div; |
tb_tasks.test_inte_int; |
$display; |
$display("II. Testing alarms ..."); |
$display; |
tb_tasks.test_talrm; |
tb_tasks.test_dalrm; |
$display; |
$display("III. Testing correct operation of time/date counters"); |
$display; |
tb_tasks.test_cases; |
$display; |
$display("###"); |
$display("### FAILED TESTS: %d ###", nr_failed); |
$display("###"); |
$display; |
#10000; |
$finish; |
end |
|
endmodule |