blob: cf112a83aeaded190581ff06a28f0194616b18bc [file] [log] [blame]
//
// Switch between two clock sources testbench.
//
//
// Design by G.J. van Loo, FenLogic Ltd, 15-January-2017.
//
// This program is free software. It comes without any guarantees or
// warranty to the extent permitted by applicable law. Although the
// author has attempted to find and correct any bugs in this free software
// program, the author is not responsible for any damage or losses of any
// kind caused by the use or misuse of the program. You can redistribute
// the program and or modify it in any form without obligations, but the
// author would appreciated if the credits stays in.
//
module clock_mux_test;
// For specify to work CLK1PERIOD must be <= CLK2PERIOD !!
localparam CLK1PERIOD = 8,
CLK2PERIOD = 10;
reg clk1; // Clock 1
reg clk2; // Clock 2
reg reset_n; // System reset
reg sel_clk2; // Select clock2 when high
wire clk1or2; // Selected clock
integer l,r1,r2;
initial
begin
sel_clk2 = 1'b0;
reset_n = 1'b0;
#50;
reset_n = 1'b1;
#250;
sel_clk2 = 1'b1;
#250;
sel_clk2 = 1'b0;
#1000;
// Test reset release with sel2 high
reset_n = 1'b0;
#50;
sel_clk2 = 1'b1;
#50;
reset_n = 1'b1;
#250;
// Test reset release and sel2 high at the same time
reset_n = 1'b0;
#50;
sel_clk2 = 1'b1;
reset_n = 1'b1;
#250;
#1000;
//
// Test clock not present
//
force clk2 = 1'b0;
#250;
// switch to not running clk2
sel_clk2 = 1'b1;
#250;
// switch back to clk1
sel_clk2 = 1'b0;
#250;
// switch to not running clk2
sel_clk2 = 1'b1;
#250;
// now clock2 comes on again
// whilst it is selected
release clk2;
#250;
// switch back to clk1
sel_clk2 = 1'b0;
#250;
// Switch often but never faster then 2xslowest input clock period
for (l=0; l<10000; l=l+1)
begin
r1 = (($random>>3)&32'h1F)+2*CLK2PERIOD;
r2 = (($random>>4)&32'h1F)+2*CLK2PERIOD;
sel_clk2 = 1'b1;
#r1;
sel_clk2 = 1'b0;
#r2;
end
#1000;
// Really nasty and illegal clock switching.
// Causes low period violations.
// This gives more confidence that the testbench seems to work.
$display("@%0t Illegal 'sel_clk2' pattern hereafter",$time);
$display(" gives rise to low period violations.");
$display(" Ignore all warnings from here.");
for (l=0; l<500; l=l+1)
begin
r1 = ($random>>3)&32'h1F+CLK2PERIOD;
r2 = ($random>>4)&32'h1F+CLK2PERIOD;
sel_clk2 = 1'b1;
#r1;
sel_clk2 = 1'b0;
#r2;
end
$stop;
end
initial
begin
clk1 = 1'b0;
forever
#(CLK1PERIOD/2) clk1 <= ~clk1;
end
initial
begin
clk2 = 1'b0;
forever
#(CLK2PERIOD/2) clk2 <= ~clk2;
end
clock_mux clock_mux0
(
.clk1 (clk1), // Clock 1
.clk2 (clk2), // Clock 2
.reset_n (reset_n), // System reset
.sel_clk2(sel_clk2), // Select clock2 when high
.clk1or2 (clk1or2) // Selected clock
);
// Now check if time high or low is ever smaller than CLK1PERIOD/2
// (This is why CLK1PERIOD <= CLK2PERIOD)
specify
$width(posedge clk1or2, CLK1PERIOD/2);
$width(negedge clk1or2, CLK1PERIOD/2);
endspecify
endmodule // clock_mux_test