During comparator design one is often (but not always) interested in the systematic and mismatch-related offset. When dealing with continuous-time open-loop comparators the offset measurement methodology is similar conventional OTA offset measurement e.g. DC sweep, while latched comparators require a somewhat more discrete-like manner of measuring offset.
One possible approach is to use a very precise (long sloped) linear ramp, and using massive oversampling and comparator decision storage. This approach seems to be a bit tedious as its precision is solely dependent on the ramp's slope.
An alternative method for measuring offset of latched comparators would be the binary search method. One can possibly use an ideal DAC to apply "search" voltages and depending on the comparator's decision reach a settling value with a constant binary-weighted precision. E.g. to achieve 16 bits of search accuracy only 16 cycles would be required. Here are some basic illustrative examples of the two methods.
The binary search method for measurement can be applied in various ways. One practical implementation was to implement the algorithm using Verilog-A and directly add a "search" instance where you can test your comparator directly in your existing SPICE simulation. Here is a very simple example of a possible implementation.
Indeed there is no need to calculate all 2^N code steps and later on comare them in a look-up table fashion. This is some code inefficiency which has not been realized back in the day, my lord... Nevertheless, the code (either way) works and it is the concept that matters. For this reason I have left the old code untouched, as it has been tested. I am however encouraging you to explore and write your own implementaton. Nevertheless, here's the original version and an aka inefficient implementation:
// VerilogA for daisyCycAd, daisyCycAdBinSchSAR, veriloga // // A component handy in comparator offset measurement. Uses a binary search algorithm with a "dive" coefficient of 2. See comments for more information. // // Initial version P1A - Deyan Dimitrov firstname.lastname@example.org // `include "constants.vams" `include "disciplines.vams" module daisyCycAdBinSchSAR(vCompIn, vCompOut, vClk, vdd, gnd, vCompRef); input vCompIn, vClk; output vCompOut, vCompRef; inout vdd, gnd; electrical vCompIn, vCompOut, vClk, vdd, gnd, vCompRef; parameter real vTransClk = 1.65; parameter real vTransComp = 1.65; parameter real vSchTop = 3.3; parameter real vSchBot = 0; parameter real vCompReference = 1.5; //parameter integer Resolution = 16; parameter integer NrOfCodes = 65535; //parameter real tCompSpeed = 100e-12; real vRefInReal; real vBinSch; real vComp; real scharray[0:NrOfCodes]; //real next; integer imid; integer imin; integer imax; integer i; integer codes; analog begin @(initial_step) begin vBinSch = vSchBot + (vSchTop-vSchBot)/2; // Mid point as a start of the search imin = 0; imax = NrOfCodes-2; imid = (NrOfCodes-2)/2; for (i = 0; i < NrOfCodes-1; i = i + 1) begin scharray[i] = (((vSchTop-vSchBot)/NrOfCodes)*i)+vSchBot; // Creating reference array end $strobe("Array Max %g", scharray[imax]); $strobe("Array Min %g", scharray[imin]); end @(cross(V(vClk) - vTransClk, 1)) begin // next = $abstime + tCompSpeed; // Possible internal compensation for comparator's delay // end // @(timer(next)) begin // $strobe("Imax: %d", imax); // $strobe("Imid: %d", imid); // $strobe("Imin: %d", imin); vComp = V(vCompIn); // Strobe comparator decision // vRefInReal = V(vRefIn, gnd); if (imax >= imin) begin // Continue searching if imax >= imin if (V(vCompIn) > vTransComp) begin // Find-out which sub-array to search $strobe("%g",vComp); // vBinSch = vBinSch + (vSchTop-vBinSch)/2; imin = imid + 1; // Change min index for the upper sub-array imid = imin + ((imax-imin)/2); // Update imid to be used for strobing-out end else begin $strobe("%g",vComp); // vBinSch = vBinSch - (vBinSch-vSchBot)/2; imax = imid - 1; // Change max index for the upper sub-array imid = imin + ((imax-imin)/2); // Update imid to be used for strobing-out end end vBinSch = scharray[imid]; // Look-up at the reference array and assign to vBinSch (Votage to be strobed-out) end V(vCompOut) <+ vBinSch; // Update search voltage V(vCompRef) <+ vCompReference; // Update comparator reference end endmodule
The whole principle is simple and self-explanatory. Some delay between the latch clock and S/H clock of the search component is required to compensate for the comparator's speed. Here are some practical usage illustrations.
If you find this useful the component's symbol for Virtuoso 6 as well as the *.va code can be found here.
08 Jul 2017, 02:19
Thank you very much for sharing such a fantastic experience.
Would you please share ADE too? or give more details on the parameters? I want to resimulate the test bench with Verilog-A comparator and check with the result you showed to make sure that I am in aright path.
10 Jul 2017, 13:28
This block basically forms an ideal successive approximation DAC with one sample delay. Here's a brief info on the parameters and their use:
vTransClk - threshold for the clcok
vTransComp - threshold for the comparator transition
vSchTop - high output voltage level
vSchBot - low output voltage level
vCompReference - reference voltage for the comparator
NrOfCodes - number of sar search codes this determines the iterations
I think you can try pasting this veriloga module into an indivisual block and play around with the testbench. I am not sure if I keep all ADE simulation states for this module, but it really is straight forward and nothing complicated.
Thanks and let me know if you haven't wrapped it around.