diff --git a/common/dv/run.sh b/common/dv/run.sh index 0e7f808..9fb3e0a 100755 --- a/common/dv/run.sh +++ b/common/dv/run.sh @@ -1,2 +1,5 @@ #!/bin/bash -./snowflake.vvp + +rm test_0.emf +ln -s $2 test_0.emf +./$1 diff --git a/common/dv/tests/test_clkdiv.emf b/common/dv/tests/test_clkdiv.emf index 45f5b88..82af78b 100644 --- a/common/dv/tests/test_clkdiv.emf +++ b/common/dv/tests/test_clkdiv.emf @@ -6,14 +6,6 @@ 00000000_00000000_00000005_01_0080 // 00000000_00000000_00000006_01_0080 // 00000000_00000000_00000007_01_0080 // -00000000_00000000_00000008_01_0080 // -00000000_00000000_00000009_01_0080 // -00000000_00000000_0000000A_01_0080 // -00000000_00000000_0000000B_01_0080 // -00000000_00000000_0000000C_01_0080 // -00000000_00000000_0000000D_01_0080 // -00000000_00000000_0000000E_01_0080 // -00000000_00000000_0000000F_01_0080 // diff --git a/common/hdl/oh_clockdiv.v b/common/hdl/oh_clockdiv.v index d64f9c7..9584b3a 100644 --- a/common/hdl/oh_clockdiv.v +++ b/common/hdl/oh_clockdiv.v @@ -1,31 +1,42 @@ // ############################################################### // # FUNCTION: Synchronous clock divider that divides by integer +// # divcfg: 0 = div1 +// # 1 = div2 +// # 2 = div4 +// # 3 = div8 +// # 4 = div16 +// # 5 = div32 +// # 6 = div64 +// # 7 = div128 +// # 15:8= reserved // ############################################################### module oh_clockdiv(/*AUTOARG*/ // Outputs - clkout, + clkout, clkout90, // Inputs - clkin, divcfg, reset + clk, en, nreset, divcfg ); - input clkin; // Input clock - input [3:0] divcfg; // Divide factor (1-128) - input reset; // Counter init - output clkout; // Divided clock phase aligned with clkin + //signals + input clk; // input clock + input en; // synchronous clock enable + input nreset; // async + input [3:0] divcfg; // divide factor (1-128) + output clkout; // divided clock phase aligned with clkin + output clkout90; // clkout shifted by 90 deg + //regs reg clkout_reg; + reg clkout90_reg; reg [7:0] counter; reg [7:0] divcfg_dec; reg [3:0] divcfg_reg; + reg clkout90_div2; - wire div_bp; wire posedge_match; wire negedge_match; - - // ################### - // # Decode divcfg - // ################### - + + // divider setting always @ (divcfg[3:0]) casez (divcfg[3:0]) 4'b0001 : divcfg_dec[7:0] = 8'b00000010; // Divide by 2 @@ -35,32 +46,58 @@ module oh_clockdiv(/*AUTOARG*/ 4'b0101 : divcfg_dec[7:0] = 8'b00100000; // Divide by 32 4'b0110 : divcfg_dec[7:0] = 8'b01000000; // Divide by 64 4'b0111 : divcfg_dec[7:0] = 8'b10000000; // Divide by 128 - default : divcfg_dec[7:0] = 8'b00000000; // others + default : divcfg_dec[7:0] = 8'b00000000; // others (divide by 1) endcase + + // divcfg change detector + always @ (posedge clk) + divcfg_reg[3:0]<=divcfg[3:0]; + assign cfg_reset = (|(divcfg_reg[3:0] ^ divcfg[3:0])); - always @ (posedge clkin or posedge reset) - if(reset) + // synchronous edge counter + always @ (posedge clk or negedge nreset) + if(!nreset) counter[7:0] <= 8'b00000001; - else if(posedge_match) + else if(posedge_match | cfg_reset) counter[7:0] <= 8'b00000001;// Self resetting else counter[7:0] <= (counter[7:0] + 8'b00000001); assign posedge_match = (counter[7:0]==divcfg_dec[7:0]); assign negedge_match = (counter[7:0]=={1'b0,divcfg_dec[7:1]}); - - always @ (posedge clkin or posedge reset) - if(reset) + assign posedge90_match = (counter[7:0]=={2'b0,divcfg_dec[7:2]}); + assign negedge90_match = (counter[7:0]=={2'b0,divcfg_dec[7:2]}+{1'b0,divcfg_dec[7:1]}); + + // clkout + always @ (posedge clk or negedge nreset) + if(!nreset) clkout_reg <= 1'b0; else if(posedge_match) clkout_reg <= 1'b1; else if(negedge_match) clkout_reg <= 1'b0; - - //Divide by one bypass - assign div_bp = (divcfg[3:0]==4'b0000); - assign clkout = div_bp ? clkin : clkout_reg; + // divide by one special case + assign clkout = (divcfg[3:0]==4'b0000) ? clk : clkout_reg; + + // clkout90 + always @ (posedge clk or negedge nreset) + if(!nreset) + clkout90_reg <= 1'b0; + else if(posedge90_match) + clkout90_reg <= 1'b1; + else if(negedge90_match) + clkout90_reg <= 1'b0; + + // special div2 case, using negedge of clk to delay by 90 deg + always @ (negedge clk) + clkout90_div2 <= clkout_reg; + + // divide by one and two special cases + assign clkout90 = (divcfg[3:0]==4'b0000) ? clk : + (divcfg[3:0]==4'b0001) ? clkout90_div2 : + clkout90_reg; + endmodule // oh_clockdiv