// // 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