Monday, April 13, 2020

How to implement SAR ADC with a minimum analog content - a simple 3-bit ADC example - Part 2



In the previous blog post: How to implement SAR ADC with a minimum analog content - a simple 3-bit ADC example   I didn't really make an effort to model analog block behavior  properly to resemble how the analog block will look like in a real CMOS process transistor implementation.


So, here is the second part of my simple 3-bit SAR ADC mixed signal design with a minimum analog content and this time I modeled the behavior of the analog block using Verilog A/AMS (closely resembling a final CMOS process transistor implementation ) using also Verilog A/AMS simple behavioral models of a switch, capacitor and a comparator.


While working on my "minimum analog content" 3-bit SAR ADC mixed signal design, I came across several Verilog A/AMS sub-blocks/behavioral models/modules online. After making some modifications to a few of them, I utilized them to create the analog behavior block ( adc_8bit_analog.vams ). Below are summary function descriptions of  the specific sub-blocks I used.

  •  comparator_simple

    • It has an electrical input port ( "in")  and digital ( Verilog type:  reg )  output port ( "out"). 

      • Since it is a comparator it compares a voltage applied to the "in" port with 0V: 

        • if "in" > 0V the result is "out" = 1'b1 otherwise "out" = 1'b0 . 


  • capacitor

    • This is a capacitor Verilog A/AMS behavioral model with capacitance parameter "c" in Farads.


  • dig_ctrl_switch

    • Here is a digitally controlled electrical switch: digital input "s" controls whether two electrical ports "p" and "n" are short or open. There is also a resistance parameter "R" to model the resistance of the "closed" switch.

Here are some assumptions/choices I made in modeling the behavioral analog block using Verilog A/AMS:

  • Unit capacitance is 1pF

  • A resistance of a closed dig_ctrl_switch is by default is R=10Ω. 

    • For the instances of  dig_ctrl_switch used for capacitors connection to GND when the switch is closed,  I chose R=0,01 Ω. 


Please note that there were changes in the digital block (adc_8bit_dig_top.v), since the last blog post, in order to make it work with adc_8bit_analog.vams analog block Verilog A/AMS behavioral model.


As before the digital block  adc_8bit_dig_top.v is designed as a synthesizable  Verilog RTL digital design and it is a design process independent.


  • I have chosen a digital design RTL implementation that uses only a single clock/single reset combination therefore only Power On Reset is used as a reset of D Flip Flops in the digital block ( and the main reset is used only for that ) and the clock signal ( clk ) is the only signal driving clk input of D Flip Flops, and the main clock is used only for that . 

    • Single clock/single reset design strategy simplifies logic gate synthesis, backend handling of clock tree generation and always desired scan insertion for Design For Test (DFT ) ATPG (Automatic Test Pattern Generation).


Also for example I chose a clock frequency of 100MHz ( 10 ns clock period ) for a simulation/verification of the mixed signal design of 3-bit SAR ADC.


In the testbench top_test_adc_8bit.vams ( sorry,  it is not self-checking ) as in the previous blog post, Vref = 1V but this time Vin is driven using a voltage-controlled oscillator ( Verilog A/AMS module "vco" ). 

The vco is set up to generate a sinusoidal signal Vin of an amplitude range between approximately 0.2V-1V and the frequency of the vco output signal is adjusted to 5MHz. 

The vco frequency is set up using vco parameter center_freq in Hz ( e.g. parameter real center_freq = 5000000) as long as vin input port of vco is driven by 0V.

The amplitude range is adjusted by manipulating two additional vco parameters: amp and dc_voltage

·        e.g. for an amplitude range 0.2V-1V I  would need a setup of amp = 0.4 and dc_voltage = 0.6 => sinusoidal output signal will oscillate with a maximum voltage 0.6 + 0.4=1V and a minimum voltage  0.6 - 0.4 = 0.2V .


After enabling ADC ( adc_conversion_en = 1'b1 ) the digital block is waiting for an arbitrarily chosen value of  1000 clock ticks to do a sample of a  Vin value and then it will do the Analog to Digital Conversion.

It just so happens that in this testbench a sampled value is around 0.880V so the expected result of ADC is 3'b111. The same ADC conversion is executed in the loop until the end of simulation or until disabling the ADC ( adc_conversion_en = 1'b0).


Here are some snapshots from the simulation/verification with an explanation of execution of SAR ADC algorithm in this particular example of the simulation/verification:


Simulation/Verification snapshot #1


When the digital state machine is in “state” 0, ADC is in a tracking mode so the input port “in” of “comparator_simple” is  tracking a voltage produced on the output port ( “vout”) of the “vco”. 

  • In this state all four capacitors are connected, on one end, to the output port ( “vout”) of the “vco”.  


When the digital state machine passes from state 0 to state 1, the ADC is now in a hold mode.

  • In this case, the  ADC sampled 880mV value and it is holding it  while in state 1 , as shown on snapshot  1. 

  • In this state all four capacitors are connected, on one end, to the GND. 

    • In the analog block the role of the ground is played by an electrical net named “zero_volt_or_gnd” driven on 0V voltage.


Simulation/Verification snapshot #2

  

When the digital state machine passes from state 1 to state 2, the ADC is now trying to determine the MSB bit ( bit 2 of the 3-bit result ) of the ADC result. 

  • For that reason a capacitor with a capacitance of 4*C needs to connect on one end to Vref and this is enabled by the digital block output:

    •  closing the switch instance dig_ctrl_switch_4_vref.s = 1’b1 and 

    • opening other two 4*C capacitor switches: dig_ctrl_switch_4_vin.s = 1’b0 and dig_ctrl_switch_4_gnd.s = 1’b0.  

      • Since Vref/2 – 880mV < 0 ( 0.5V – 880mV = -380mV as shown in snapshot 2 ) our MSB bit is 1 and further the capacitor 4*C will be,  on one end,  connected to Vref until the end of the Analog to Digital conversion.


Simulation/Verification snapshot #3


When the digital state machine passes to a state 4 it will try to determine bit 1.

  •  Since Vref/2 – 880mV < 0 we will continue a binary search algorithm looking if  Vref/2 + Vref/4   – 880mV is less than 0 and and in this case yes it is ( 0.5V + 0.25V – 880mV < 0 => approximately -130.16mV < 0 as shown on the snapshot 3. ). 

    • To do this we need connect one end of a capacitor with a capacitance value of 2*C to Vref. 

      • As before this is done by controlling 2*C capacitor switches: dig_ctrl_switch_3_vref.s = 1’b1 and opening other two 2*C capacitor switches: dig_ctrl_switch_3_vin.s = 1’b0 and dig_ctrl_switch_3_gnd.s = 1’b0.   

Since   Vref/2 + Vref/4   – 880mV is still less than 0, bit 1 is 1’b1 and further the capacitor 2*C will be, on one end, connected to Vref until the end of the Analog to Digital conversion.

Simulation/Verification snapshot #4


Finally, when the digital state machine passes to a state 6 we will determine the last bit 0.  

  • Since Vref/2 + Vref/4   – 880mV was less than 0 we will continue a binary search algorithm looking if  Vref/2 + Vref/4 + Vref/8  is also less than 0.

  • Also in this case 0.5V + 0.25V +0.125V – 880mV < 0 => approximately -5.105mV < 0 ( as shown on the snapshot 4. ) so bit 0 is 1’b1.

Finally Analog Digital conversion of 880mV is 3’b111 as expected.




Here is the source code of simulation verification testbench ( top_test_adc_8bit.vams, including module vco  ) then analog block model ( adc_8bit_analog , including modules: comparator_simple, capacitor: cap and dig_ctrl_switch) and finally digital block RTL ( adc_8bit_dig_top ):


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
`include "discipline.h"
`include "constants.h"

`define PI     3.14159265358979323846264338327950288419716939937511
//--------------------
// vco.vams
//
// -  voltage-controlled oscillator
//
// vin:          oscillation controlling voltage [V,A]
// vout:        [V,A]
//
// INSTANCE parameters
//    amp         = amplitude of the output signal [V]
//    center_freq = center frequency of oscillation freq 

//                  when 'vin' = 0 [Hz]

//
//    vco_gain    = oscillator conversion gain [Hz/volt]
module vco(vin, vout);
  input vin;
  output vout;
  electrical vin, vout;

  parameter real amp = 0.4;

  parameter real center_freq = 5000000;
 
  parameter real dc_voltage = 0.6 ;

  parameter real vco_gain = 1K;
  parameter integer steps_per_period = 32;


  real phase;
  real inst_freq;                // instantaneous frequency

  analog begin
      //
      // ensure that modulator output is recalculated soon.
      //
      inst_freq = center_freq + vco_gain * V(vin);
      $bound_step (1.0 / (steps_per_period*inst_freq));

      phase = idtmod(inst_freq,0,1);
         
      V(vout) <+ dc_voltage + amp * sin(2 * `PI * phase);
  end
endmodule



/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
`include "discipline.h"
`include "constants.h"
module  top_test_adc_8bit ();

  parameter real vref = 1 ;
  parameter real vin = 0.0;

  reg   POR_sync_i     ;
  reg   clk            ;

   reg adc_conversion_en;

  wire adc_comp_out    ;

  wire sw4_vin         ;
  wire sw4_vref        ;
  wire sw4_gnd         ;

  wire sw3_vin         ;
  wire sw3_vref        ;
  wire sw3_gnd         ;

  wire sw2_vin         ;
  wire sw2_vref        ;
  wire sw2_gnd         ;

  wire sw1_vin         ;
  wire sw1_vref        ;
  wire sw1_gnd         ;

  wire sw0_closed      ;

  electrical Vref, Vin, Vin_first, Vref_first ;

  vco vco (
            .vin  ( Vin_first ),
            .vout ( Vin       )
          );

   adc_8bit_dig_top adc_8bit_dig_top (
    .POR_sync_i          ( POR_sync_i          ) ,
    .clk                 ( clk                 ) ,

    .adc_conversion_en_i ( adc_conversion_en   ) ,

    .adc_comp_out_i      ( adc_comp_out        ) ,

    .sw4_vin_o           ( sw4_vin             ) ,
    .sw4_vref_o          ( sw4_vref            ) ,
    .sw4_gnd_o           ( sw4_gnd             ) ,

    .sw3_vin_o           ( sw3_vin             ) ,
    .sw3_vref_o          ( sw3_vref            ) ,
    .sw3_gnd_o           ( sw3_gnd             ) ,

    .sw2_vin_o           ( sw2_vin             ) ,
    .sw2_vref_o          ( sw2_vref            ) ,
    .sw2_gnd_o           ( sw2_gnd             ) ,

    .sw1_vin_o           ( sw1_vin             ) ,
    .sw1_vref_o          ( sw1_vref            ) ,
    .sw1_gnd_o           ( sw1_gnd             ) ,

    .sw0_closed_o        ( sw0_closed          ));

  adc_8bit_analog adc_8bit_analog(
    .Vin                 ( Vin               ),
    .Vref                ( Vref              ),

    .adc_conversion_en_i ( adc_conversion_en ) ,

    .adc_comp_out_o      ( adc_comp_out      ) ,

    .sw4_vin_i           ( sw4_vin           ) ,
    .sw4_vref_i          ( sw4_vref          ) ,
    .sw4_gnd_i           ( sw4_gnd           ) ,

    .sw3_vin_i           ( sw3_vin           ) ,
    .sw3_vref_i          ( sw3_vref          ) ,
    .sw3_gnd_i           ( sw3_gnd           ) ,

    .sw2_vin_i           ( sw2_vin           ) ,
    .sw2_vref_i          ( sw2_vref          ) ,
    .sw2_gnd_i           ( sw2_gnd           ) ,

    .sw1_vin_i           ( sw1_vin           ) ,
    .sw1_vref_i          ( sw1_vref          ) ,
    .sw1_gnd_i           ( sw1_gnd           ) ,

    .sw0_closed_i        ( sw0_closed        ));

  initial begin
    clk                = 1'b0 ;
    adc_conversion_en  = 1'b0 ;

    POR_sync_i = 1'b1 ;
    #10
    POR_sync_i = 1'b0 ;
    @ ( posedge clk ) ;
    @ ( posedge clk )  ;
    adc_conversion_en  = 1'b1 ;
  end


  always begin
      #5
      clk = !clk ;
  end

  analog begin
    V(Vin_first)  <+ vin  ;
    V(Vref)       <+ vref ;
  end

endmodule


/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
`include "discipline.h"
`include "constants.h"
module comparator_simple (out, in);
  input in;
  output out;

  electrical in;
  reg out;

  initial
    out = 1'b0 ;

  always @( cross( V(in), 1) )
    out = 1'b0 ;
       
  always @( cross( V(in), -1) )
    out = 1'b1 ;
       
endmodule
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
`include "discipline.h"
`include "constants.h"

// $Date: 1997/08/28 05:46:19 $
// $Revision: 1.1 $
//
//
// Based on the OVI Verilog-A Language Reference Manual,

// version 1.0 1996
//--------------------
// cap
//
// -  capacitor
//
// vp,vn:       terminals (V,A)
//
// INSTANCE parameters
//    c = capacitance (F)
//
// MODEL parameters
//    {none}
//

module cap(vp, vn);
  inout vp, vn;
  electrical vp, vn;
  parameter real c = 0;

  analog
      I(vp, vn) <+ ddt(c*V(vp, vn));
endmodule
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////

`include "discipline.h"
`include "constants.h"

module dig_ctrl_switch (p, n, s);
  input s;
  output p, n;

  logic s;
  electrical p, n;

  parameter real R = 10.0 ;

  analog begin
  if (s)
    V(p, n) <+ I(p, n) * R ;
  else
    I(p, n) <+ 0.0;
           
  end
 
endmodule


/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
// adc_8bit_analog.vams
`include "discipline.h"
`include "constants.h"
module  adc_8bit_analog (
 
  Vref                ,
  Vin                 ,
 
  adc_conversion_en_i ,
 
  adc_comp_out_o      ,
 
  sw4_vin_i           ,
  sw4_vref_i          ,
  sw4_gnd_i           ,
                                   
  sw3_vin_i           ,
  sw3_vref_i          ,
  sw3_gnd_i           ,
                                   
  sw2_vin_i           ,
  sw2_vref_i          ,
  sw2_gnd_i           ,
                                   
  sw1_vin_i           ,
  sw1_vref_i          ,
  sw1_gnd_i           ,
                                   
  sw0_closed_i)      ;
                                                                             
parameter real zero_volt_or_gnd_real = 0.0 ;
parameter real c0                    = 1e-12 ;


input  adc_conversion_en_i;
 
output adc_comp_out_o     ;
 
input  sw4_vin_i          ;
input  sw4_vref_i         ;
input  sw4_gnd_i          ;
                               
input  sw3_vin_i          ;
input  sw3_vref_i         ;
input  sw3_gnd_i          ;
                               
input  sw2_vin_i          ;
input  sw2_vref_i         ;
input  sw2_gnd_i          ;
                               
input  sw1_vin_i          ;
input  sw1_vref_i         ;
input  sw1_gnd_i          ;
                               
input  sw0_closed_i       ;
 
inout  Vref, Vin          ;



electrical sigout, sigref, sigin ;

electrical sw_0_vp      , 
          sw_0_n       ,   
          sw_0_vctrlp  ,
          sw_0_vctrln  ;

                   
electrical cap_1_vp     ,      
          cap_1_vn     ;
                   
electrical sw_1_vp      , 
          sw_1_n       ,   
          sw_1_vctrlp  ,
          sw_1_vctrln  ;
                   

electrical cap_2_vp     ,      
          cap_2_vn     ;
                   
electrical sw_2_vp      , 
          sw_2_n       ,   
          sw_2_vctrlp  ,
          sw_2_vctrln  ;                  


electrical cap_3_vp     ,      
          cap_3_vn     ;
                   
electrical sw_3_vp      , 
          sw_3_n       ,   
          sw_3_vctrlp  ,
          sw_3_vctrln  ;                            


electrical cap_4_vp     ,      
          cap_4_vn     ;
                   
electrical sw_4_vp      , 
          sw_4_n       ,   
          sw_4_vctrlp  ,
          sw_4_vctrln  ;                  
                   
                   
electrical zero_volt_or_gnd ;
           
                   
wire adc_comp_out_o ;
                                                                           
comparator_simple comparator_simple (
  .out( adc_comp_out_o        ),
  .in ( sigin                 ));
                                                                           
dig_ctrl_switch #( .R( 0.0 ) ) dig_ctrl_switch_0 (
  .p( sigin                 ),
  .n( zero_volt_or_gnd      ),
  .s( !adc_conversion_en_i  ));
                                                                           
///////////////////////////////////////////////////////                                                                    

cap #(.c(c0))  cap_1 (
  .vn( sigin    ),
  .vp( cap_1_vn ));

                                                 
dig_ctrl_switch dig_ctrl_switch_1_vin (
  .p( cap_1_vn ),                                                                                             
  .n( Vin      ),
  .s( sw1_vin_i));

dig_ctrl_switch #( .R( 0.01 )) dig_ctrl_switch_1_gnd (
  .p( cap_1_vn        ),
  .n( zero_volt_or_gnd),
  .s( sw1_gnd_i ));                                                                               
                                                                   
/////////////////////////////////////////////////////////                                                           
                                                                                                                               
cap #( .c( c0 )) cap_2 (
  .vn( sigin    ),
  .vp( cap_2_vn ));


dig_ctrl_switch dig_ctrl_switch_2_vref (
  .p( cap_2_vn  ),
  .n( Vref      ),
  .s( sw2_vref_i));
                                                                                       
dig_ctrl_switch dig_ctrl_switch_2_vin (
  .p( cap_2_vn  ),
  .n( Vin       ),
  .s( sw2_vin_i ));

dig_ctrl_switch #( .R( 0.01 ) ) dig_ctrl_switch_2_gnd (
  .p( cap_2_vn        ),
  .n( zero_volt_or_gnd),
  .s( sw2_gnd_i       ));                                            

///////////////////////////////////////////////////////////                                                                   
                                                                   
cap  #(.c(2*c0)) cap_3 (
  .vn( sigin    ),
  .vp( cap_3_vn ));


dig_ctrl_switch dig_ctrl_switch_3_vref (
  .p ( cap_3_vn  ),
  .n ( Vref      ),
  .s ( sw3_vref_i));
                                                                                       
dig_ctrl_switch dig_ctrl_switch_3_vin (
  .p ( cap_3_vn  ),
  .n ( Vin       ),
  .s ( sw3_vin_i ));

dig_ctrl_switch #( .R( 0.01 ) ) dig_ctrl_switch_3_gnd (
  .p( cap_3_vn          ),
  .n( zero_volt_or_gnd  ),
  .s( sw3_gnd_i         ));                                                                  

////////////////////////////////////////////////////////////
                                                                   
cap #(.c(4*c0) ) cap_4 (
  .vn ( sigin    ),
  .vp ( cap_4_vn ));
                                                                     
dig_ctrl_switch dig_ctrl_switch_4_vref (
  .p ( cap_4_vn   ),
  .n ( Vref       ),
  .s ( sw4_vref_i ));
                                                                                         
dig_ctrl_switch dig_ctrl_switch_4_vin (
  .p ( cap_4_vn ),
  .n ( Vin      ),
  .s ( sw4_vin_i));

dig_ctrl_switch #( .R( 0.01 ) ) dig_ctrl_switch_4_gnd (
  .p ( cap_4_vn         ),
  .n ( zero_volt_or_gnd ),
  .s ( sw4_gnd_i        ));
 
analog begin
  V (zero_volt_or_gnd ) <+ zero_volt_or_gnd_real ;
end

endmodule


/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
// adc_8bit_dig_top.v
module  adc_8bit_dig_top (

  POR_sync_i          ,
  clk                 ,

  adc_conversion_en_i ,

  adc_comp_out_i      ,

  sw4_vin_o           ,
  sw4_vref_o          ,
  sw4_gnd_o           ,

  sw3_vin_o           ,
  sw3_vref_o          ,
  sw3_gnd_o           ,

  sw2_vin_o           ,
  sw2_vref_o          ,
  sw2_gnd_o           ,

  sw1_vin_o           ,
  sw1_vref_o          ,
  sw1_gnd_o           ,

  sw0_closed_o);

  input  POR_sync_i          ;
  input  clk                 ;

  output adc_comp_out_i      ;

  input  adc_conversion_en_i ;

  output sw4_vin_o           ;
  output sw4_vref_o          ;
  output sw4_gnd_o           ;

  output sw3_vin_o           ;
  output sw3_vref_o          ;
  output sw3_gnd_o           ;

  output sw2_vin_o           ;
  output sw2_vref_o          ;
  output sw2_gnd_o           ;

  output sw1_vin_o           ;
  output sw1_vref_o          ;
  output sw1_gnd_o           ;

  output sw0_closed_o        ;

  parameter START_ST       = 3'b000 ;
  parameter HOLD_ST        = 3'b001 ;
  parameter MSB_ST         = 3'b010 ;
  parameter MSB_HOLD_ST    = 3'b011 ;
  parameter BIT_1_ST       = 3'b100 ;
  parameter BIT_1_HOLD_ST  = 3'b101 ;
  parameter LSB_ST         = 3'b110 ;
  parameter END_ST         = 3'b111 ;


  reg[2:0] state, next_state ;

  reg sw4_vin_o   , next_sw4_vin    ;
  reg sw4_vref_o  , next_sw4_vref   ;
  reg sw4_gnd_o   , next_sw4_gnd    ;

  reg sw3_vin_o   , next_sw3_vin    ;
  reg sw3_vref_o  , next_sw3_vref   ;
  reg sw3_gnd_o   , next_sw3_gnd    ;

  reg sw2_vin_o   , next_sw2_vin    ;
  reg sw2_vref_o  , next_sw2_vref   ;
  reg sw2_gnd_o   , next_sw2_gnd    ;

  reg sw1_vin_o   , next_sw1_vin    ;
  reg sw1_vref_o  , next_sw1_vref   ;
  reg sw1_gnd_o   , next_sw1_gnd    ;

  reg sw0_closed_o, next_sw0_closed ;

  reg[2:0] adc_data,       next_adc_data     ;

  reg      adc_data_rdy,   next_adc_data_rdy ;

  reg[19:0] counter_delay, next_counter_delay;

  reg adc_comp_out_dff1      ,
      next_adc_comp_out_dff1 ,
      adc_comp_out_dff2      ,
      next_adc_comp_out_dff2 ;

  /// SEQ
  always@ ( posedge clk or negedge POR_sync_i  ) begin

    if( POR_sync_i ) begin
      state        <= START_ST ;

      sw4_vin_o    <= 1'b0     ;
      sw4_vref_o   <= 1'b0     ;
      sw4_gnd_o    <= 1'b0     ;

      sw3_vin_o    <= 1'b0     ;
      sw3_vref_o   <= 1'b0     ;
      sw3_gnd_o    <= 1'b0     ;

      sw2_vin_o    <= 1'b0     ;
      sw2_vref_o   <= 1'b0     ;
      sw2_gnd_o    <= 1'b0     ;

      sw1_vin_o    <= 1'b0     ;
      sw1_vref_o   <= 1'b0     ;
      sw1_gnd_o    <= 1'b0     ;

      sw0_closed_o <= 1'b0     ;

      adc_data     <= 3'd0     ;

      adc_data_rdy <= 1'd0     ;

      counter_delay <= 20'd0   ;

      adc_comp_out_dff1 <= 1'b0 ;
      adc_comp_out_dff2 <= 1'b0 ;

    end else begin
      state            <=  next_state      ;

      sw4_vin_o        <=  next_sw4_vin    ;
      sw4_vref_o       <=  next_sw4_vref   ;
      sw4_gnd_o        <=  next_sw4_gnd    ;

      sw3_vin_o        <=  next_sw3_vin    ;
      sw3_vref_o       <=  next_sw3_vref   ;
      sw3_gnd_o        <=  next_sw3_gnd    ;

      sw2_vin_o        <=  next_sw2_vin    ;
      sw2_vref_o       <=  next_sw2_vref   ;
      sw2_gnd_o        <=  next_sw2_gnd    ;

      sw1_vin_o        <=  next_sw1_vin    ;
      sw1_vref_o       <=  next_sw1_vref   ;
      sw1_gnd_o        <=  next_sw1_gnd    ;

      sw0_closed_o     <=  next_sw0_closed ;

      adc_data         <=  next_adc_data   ;

      adc_data_rdy     <=  next_adc_data_rdy  ;

      counter_delay    <= next_counter_delay  ;

      adc_comp_out_dff1 <= adc_comp_out_i         ;
      adc_comp_out_dff2 <= next_adc_comp_out_dff2 ;

    end

  end

  // COMB
  always@( * ) begin
    next_state          = state         ;

    next_sw4_vin        =  sw4_vin_o    ;
    next_sw4_vref       =  sw4_vref_o   ;
    next_sw4_gnd        =  sw4_gnd_o    ;

    next_sw3_vin        =  sw3_vin_o    ;
    next_sw3_vref       =  sw3_vref_o   ;
    next_sw3_gnd        =  sw3_gnd_o    ;

    next_sw2_vin        =  sw2_vin_o    ;
    next_sw2_vref       =  sw2_vref_o   ;
    next_sw2_gnd        =  sw2_gnd_o    ;

    next_sw1_vin        =  sw1_vin_o    ;
    next_sw1_vref       =  sw1_vref_o   ;
    next_sw1_gnd        =  sw1_gnd_o    ;

    next_sw0_closed     =  sw0_closed_o ;

    next_adc_data       =  adc_data     ;

    next_adc_data_rdy   =  adc_data_rdy ;

    next_counter_delay  =  counter_delay ;

    next_adc_comp_out_dff2 = adc_comp_out_dff1 ;

    case( state )
  //////////////////////////////////////////////
  // Sample state
    START_ST: begin
      next_sw4_vin    = 1'b1   ;
      next_sw4_vref   = 1'b0   ;
      next_sw4_gnd    = 1'b0   ;

      next_sw3_vin    = 1'b1   ;
      next_sw3_vref   = 1'b0   ;
      next_sw3_gnd    = 1'b0   ;

      next_sw2_vin    = 1'b1   ;
      next_sw2_vref   = 1'b0   ;
      next_sw2_gnd    = 1'b0   ;

      next_sw1_vin    = 1'b1   ;
      next_sw1_vref   = 1'b0   ;
      next_sw1_gnd    = 1'b0   ;

      next_sw0_closed = 1'b1   ;

      if( adc_conversion_en_i ) begin

        next_sw0_closed = 1'b0   ;

        if ( counter_delay  == 20'd1000 ) begin

            next_counter_delay = 20'd0 ;

            next_sw4_vin    = 1'b0   ;
            next_sw4_gnd    = 1'b1   ;

            next_sw3_vin    = 1'b0   ;
            next_sw3_gnd    = 1'b1   ;

            next_sw2_vin    = 1'b0   ;
            next_sw2_gnd    = 1'b1   ;

            next_sw1_vin    = 1'b0   ;
            next_sw1_gnd    = 1'b1   ;

            next_state  = HOLD_ST ;
        end else
          next_counter_delay = counter_delay + 20'd1 ;

      end
    end

  ///////////////////////////////////////////////
  HOLD_ST: begin
    if( adc_conversion_en_i ) begin
      if ( counter_delay  == 20'd1 ) begin
        next_counter_delay = 20'd0 ;

        next_sw4_vref = 1'b1   ;
        next_sw4_gnd  = 1'b0   ;

        next_state    = MSB_ST ;
      end else
        next_counter_delay = counter_delay + 20'd1 ;

    end else begin
      next_sw0_closed = 1'b1   ;

      next_sw4_vin    = 1'b1   ;
      next_sw4_vref   = 1'b0   ;
      next_sw4_gnd    = 1'b0   ;

      next_sw3_vin    = 1'b1   ;
      next_sw3_vref   = 1'b0   ;
      next_sw3_gnd    = 1'b0   ;

      next_sw2_vin    = 1'b1   ;
      next_sw2_vref   = 1'b0   ;
      next_sw2_gnd    = 1'b0   ;

      next_sw1_vin    = 1'b1   ;
      next_sw1_vref   = 1'b0   ;
      next_sw1_gnd    = 1'b0   ;

      next_state      = START_ST ;

    end
  end // HOLD_ST

  ///////////////////////////////////////////////
  MSB_ST: begin
    if( adc_conversion_en_i ) begin
      if( counter_delay  == 20'd5 ) begin
        next_counter_delay = 20'd0 ;
        if( adc_comp_out_i ==  1'b1 )begin
          next_adc_data[2] = 1'b1;
        end else begin
          next_adc_data[2] = 1'b0;
        end

        next_sw4_vref    = 1'b0   ;
        next_sw4_gnd     = 1'b1   ;
        next_state      = MSB_HOLD_ST ;
      end else
          next_counter_delay = counter_delay + 20'd1 ;

    end else begin
      next_sw0_closed = 1'b1   ;

      next_sw4_vin    = 1'b1   ;
      next_sw4_vref   = 1'b0   ;
      next_sw4_gnd    = 1'b0   ;

      next_state      = START_ST ;
    end
  end

  ///////////////////////////////////////////////
  MSB_HOLD_ST: begin
    if( adc_conversion_en_i ) begin
      if( counter_delay  == 20'd1 ) begin
        next_counter_delay = 20'd0 ;
        if( adc_data[2] == 1'b1  ) begin
          next_sw4_vref = 1'b1   ;
          next_sw4_gnd  = 1'b0   ;
        end else begin
          next_sw4_vref = 1'b0   ;
          next_sw4_gnd  = 1'b1   ;
        end

        next_sw3_gnd    = 1'b0   ;
        next_sw3_vref   = 1'b1   ;

        next_state      = BIT_1_ST ;
      end else
        next_counter_delay = counter_delay + 20'd1 ;

    end else begin
      next_sw0_closed = 1'b1   ;
      next_sw4_vin    = 1'b1   ;
      next_sw4_vref   = 1'b0   ;
      next_sw4_gnd    = 1'b0   ;

      next_state      = START_ST ;
    end
  end

  ///////////////////////////////////////////////
  BIT_1_ST: begin
    if( adc_conversion_en_i ) begin
      if ( counter_delay  == 20'd4 ) begin
        next_counter_delay = 20'd0 ;
        if( adc_comp_out_i ==  1'b1 )begin
          next_adc_data[1] = 1'b1 ;
        end else begin
          next_adc_data[1] = 1'b0 ;
        end
        next_sw3_vref      = 1'b0 ;
        next_sw3_gnd       = 1'b1 ;
        next_state         = BIT_1_HOLD_ST ;

        next_sw2_vin       = 1'b0 ;

        next_sw1_vin       = 1'b0   ;
        next_sw1_gnd        = 1'b1   ;

      end else
        next_counter_delay = counter_delay + 20'd1 ;

    end else begin
      next_sw0_closed = 1'b1 ;
      next_sw3_vin    = 1'b1 ;
      next_sw3_vref   = 1'b0 ;
      next_sw3_gnd    = 1'b0 ;

      next_state      = START_ST ;
    end
  end


  ///////////////////////////////////////////////
  BIT_1_HOLD_ST: begin
    if( adc_conversion_en_i ) begin
      if ( counter_delay  == 20'd1 ) begin
        next_counter_delay = 20'd0 ;
        if( adc_data[1] == 1'b1  ) begin
          next_sw3_vref = 1'b1 ;
          next_sw3_gnd  = 1'b0 ;
        end else begin
          next_sw3_vref = 1'b0 ;
          next_sw3_gnd  = 1'b1 ;
        end
        next_sw2_gnd    = 1'b0 ;
        next_sw2_vref   = 1'b1 ;

        next_state      = LSB_ST ;
      end else
        next_counter_delay = counter_delay + 20'd1 ;

    end else begin
      next_sw0_closed = 1'b1   ;
      next_sw4_vin    = 1'b1   ;
      next_sw4_vref   = 1'b0   ;
      next_sw4_gnd    = 1'b0   ;

      next_state      = START_ST ;
    end
  end

  ///////////////////////////////////////////////
  LSB_ST: begin
    if( adc_conversion_en_i ) begin
      if( counter_delay  == 20'd4 ) begin
        next_counter_delay = 20'd0 ;
        if( adc_comp_out_i == 1'b1 )begin
          next_adc_data[0] = 1'b1 ;

          next_sw2_vref    = 1'b0 ;
          next_sw2_gnd     = 1'b1 ;

          next_sw1_vref    = 1'b0 ;
          next_sw1_gnd     = 1'b1 ;
        end else begin
          next_adc_data[0] = 1'b0 ;

          next_sw2_vref    = 1'b1 ;
          next_sw2_gnd     = 1'b0 ;

          next_sw1_gnd     = 1'b1 ;
        end
        next_adc_data_rdy   = 1'b1   ;
        next_state      = END_ST ;
      end else
        next_counter_delay = counter_delay + 20'd1 ;

    end else begin
      next_sw0_closed = 1'b1 ;

      next_sw2_vin    = 1'b1 ;
      next_sw2_vref   = 1'b0 ;
      next_sw2_gnd    = 1'b0 ;

      next_sw1_vin    = 1'b1 ;
      next_sw1_vref   = 1'b0 ;
      next_sw1_gnd    = 1'b0 ;

      next_state      = START_ST ;
    end
  end

  ///////////////////////////////////////////////
  END_ST: begin
    next_sw0_closed = 1'b1 ;

    next_sw4_vin  = 1'b1 ;
    next_sw4_vref = 1'b0 ;
    next_sw4_gnd  = 1'b0 ;

    next_sw3_vin  = 1'b1 ;
    next_sw3_vref = 1'b0 ;
    next_sw3_gnd  = 1'b0 ;

    next_sw2_vin  = 1'b1 ;
    next_sw2_vref = 1'b0 ;
    next_sw2_gnd  = 1'b0 ;

    next_sw1_vin  = 1'b1 ;
    next_sw1_vref = 1'b0 ;
    next_sw1_gnd  = 1'b0 ;


    next_adc_data_rdy = 1'b0 ;
    next_adc_data     = 3'd0 ;

    next_state        = START_ST ;
  end
endcase
end

endmodule


© 2011-2023 ASIC Stoic. All rights reserved