Reference Design
Active Project
Nanosoc ADC Integration
SoClabs

ADC Integration in nanoSoC

Rationale

The aim of this project is to define a mixed signal subsystem for the nanosoc reference design

In order to interface with real-world signals in a digital SoC, an analog to digital conversion is needed. The mixed signal subsystem should be able to sample analog signals at a regular sampling rate, and transmit a digital representation of this signal to the rest of the nanosoc system. 

Technical overview

From the digital side, there needs to be an interface that can be used to read and write to registers within the ADC, these include data as well as some control registers. On the analog side there needs to be a way of sampling the analog signal and converting it to a digital representation.

Analog to digital conversion

For this project the analog to digital converter portion of the subsystem is chosen to be a successive approximation register (SAR) type ADC. These are good, power efficient ADCs for reasonable speeds and bit resolution. They work by comparing the input signal to a signal produced by a DAC, and when the two match the data is stored in the output register. 

Block diagram of SAR ADC

Ideal Specifications

These are the ideal specification that the ADC should have. 

  • 8 bit resolution
  • 100 kHz sampling rate
  • 0-1.2V conversion
  • Low differential nonlinearity and integral nonlinearity
  • Low power (<1mW)

 

FPGA prototyping

To be added

 

Architecture

Digital to Analog Convertor

For simplicity, the DAC design is based on a R-2R summing amplifier. For a more detailed explaination of how this circuit works, you can find a good resource here

DAC Schematic

The schematic above shows the implementated R-2R DAC subsystem. Due to the sizing restrictions of the resistors in the TSMC65nm PDK, in order to get the correct resistor values, parallel resistors are used for the R values, with each resistor having a value of 2R (the actual value is 335 Ohm).

The opamp design is the same one used in the TSMC 65nm PLL. As the gain of this opamp setup is 1, the available bandwidth of this should be around 240 MHz. This is consistent with the simulations of the DAC, as the settling time for the conversion of the MSB is around 4ns. This suggests that this DAC circuit will work well for an ADC sampling frequency of 100 kHz.

 

Simulation of DAC

Simulating the DAC with increasing binary input shows a fairly linear increase in voltage from ~0V to ~1.2V. By simulating the change in voltage 1 bit at a time, the actual voltage for each bit can be measured. The results from this are shown below for each bit from MSB to LSB. The integral nonlinearity is -8.14 LSBs, this is the sum of all differences in number of LSBs. 

Ideal Voltage (mV)Actual Voltage (mV)Difference (mV)Difference (LSBs)
600.00590.22-9.78-2.09
300.00291.78-8.22-1.75
150.00142.33-7.67-1.64
75.0069.09-5.91-1.26
37.5034.07-3.43-0.73
18.7516.94-1.81-0.39
9.388.47-0.91-0.19
4.694.29-0.40-0.09

Digital Interface

For the digital interface:

  • APB read and write
  • Clock divider control
  • Enable/disable ADC (with clock gating)
  • Busy status register
  • Interrupt enable

Interconnect fabric

The nanosoc reference design bus matrix is generated using the Arm Academic Access tools as described in Building system-optimised AMBA interconnect. The bus system within the SoC should be carefully planned to manage bandwidth and access latency. The nanosoc design uses a Multi-layer interconnect that allows multiple bus transaction Initiators (traditionally called 'Masters') to communicate concurrently with the particular memory-mapped target responder peripherals or subsystems (traditionally called 'Slaves')
The Advanced Peripheral Bus (APB)  is not pipelined and is used to connect to low bandwidth peripherals and is optimized for low power consumption and reduced interface complexity. An AHB-APB bridge acts as a responder on the nanosoc AHB bus synchronizing the time domains of the high-speed AHB bus with the lower-speed clocks used by peripherals.

This project will utilise the simple APB bus interface for integration of real-world analog signals into nanosoc. In order to add this to the nanosoc peripheral region, an extra port has been added to the AHB MUX, to include a AHB to APB bridge and APB Mux for multiple ADC's to be added in the system. We end up with a subsystem as shown below for the ADC integration in nanosoc

nanosoc peripheral subsystem with added ADC regions

Address Map

The address for a peripheral is determined by the bus to which the peripheral is attached. nanosoc has a defined address map with the range allocated to the System Peripheral Region. We are going to add an ADC region at the end of the nanosoc peripheral bus region as shown below

nanosoc system io address map
start-addressend-addressnotes
0x400000000x40000FFFTimer 0
0x400010000x40001FFFTimer 1
0x400020000x40003FFFDual Timer
0x400040000x40004FFFUART 0
0x400050000x40005FFFUART 1
0x400060000x40006FFFUART 2
0x400080000x40008FFFWatchdog Timer
0x4000E0000x4000EFFFUSRT 2
0x4000F0000x4000FFFFDMA 0 Base
0x400100000x40010FFFGPIO 0
0x400110000x40011FFFGPIO 1
0x4001F0000x4001FFFFSystem Control
0x40020000x4002FFFADC Region

CPU Interrupts

Define the system interrupt for a measurement.

Integration Modelling

To develop the integration of an ADC in nanosoc, a simplified verilog-AMS model of an ADC was used. Verilog-AMS allows for the simulation of analog and mixed signal modules alongside digital verilog or other HDL's. The benefit of using verilog-AMS is that it is also technology independant so can be simulated without needing access to PDK's, the disadvantage is that it is not synthesizable, however the analog/mixed signal modules can easily be replaced with macro's of the final IP's. 

The development of the ADC subsystem was done within the nanosoc test environment. The benefit of this is that it was easy to develop and run C code from the Cortex-M0, without the need for creating a testbench that could handle APB transfers.

APB Register interface behavioural modelling

The APB register interface is handled by a simple state machine. This FSM waits in the APB_IDLE state until the PSEL signal goes high, and checks whether PWRITE is asserted or not. If PWRITE is high it will go into the APB_WRITE state, otherwise the APB_READ state. Within these states it eather writes to or reads from the register as pointed to by PADDR. You can see in APB_WRITE that PSLVERR is asserted if certain read only registers are attempted to be writen to. And currently the only registers that are R/W are the clock divider (CLK_DIV) and ENABLE (which enables the ADC if bit 0 is written as 1).

PREADY is asserted high if the state machine is in either APB_READ or APB_WRITE, otherwise it is 0. 

// APB interface
localparam  APB_IDLE = 2'd0,
            APB_WRITE = 2'd1,
            APB_READ = 2'd2;

reg [1:0] apb_current_state;
reg [1:0] apb_next_state;

always @(posedge PCLK or negedge PRESETn) begin
    if(~PRESETn) begin
        apb_current_state <= APB_IDLE;
        PSLVERR_reg <= 1'b0;
    end else begin
        apb_current_state <= apb_next_state;
    end
end

always @(*) begin
    case(apb_current_state)
        APB_IDLE: begin
            PSLVERR_reg = 1'b0;
            if(PSEL) begin
                if(PWRITE) begin
                    apb_next_state = APB_WRITE;
                end else begin
                    apb_next_state = APB_READ;
                end
            end
            else begin
                apb_next_state = APB_IDLE;
            end
        end
        APB_WRITE: begin
            case(PADDR)
                10'h000: PSLVERR_reg = 1'b1;
                10'h001: PSLVERR_reg = 1'b1;
                10'h002: CLK_DIV = PWDATA;
                10'h003: ENABLE_reg = PWDATA[7:0];
                10'h3F0: PSLVERR_reg = 1'b1;
                10'h3F1: PSLVERR_reg = 1'b1;
                10'h3F2: PSLVERR_reg = 1'b1;
                10'h3F3: PSLVERR_reg = 1'b1;
                10'h3F4: PSLVERR_reg = 1'b1;
                10'h3F5: PSLVERR_reg = 1'b1;
                10'h3F6: PSLVERR_reg = 1'b1;
                10'h3F7: PSLVERR_reg = 1'b1;
            endcase
            apb_next_state = APB_IDLE;
        end
        APB_READ: begin
            case(PADDR)
                10'h000: PRDATA_reg = DATA_reg;
                10'h001: PRDATA_reg = STATUS_reg;
                10'h002: PRDATA_reg = CLK_DIV;
                10'h003: PRDATA_reg = {24'd0, ENABLE_reg};
                10'h3F0: PRDATA_reg = {24'd0, ID_reg[63:56]};
                10'h3F1: PRDATA_reg = {24'd0, ID_reg[55:48]};
                10'h3F2: PRDATA_reg = {24'd0, ID_reg[47:40]};
                10'h3F3: PRDATA_reg = {24'd0, ID_reg[39:32]};
                10'h3F4: PRDATA_reg = {24'd0, ID_reg[31:24]};
                10'h3F5: PRDATA_reg = {24'd0, ID_reg[23:16]};
                10'h3F6: PRDATA_reg = {24'd0, ID_reg[15:8]};
                10'h3F7: PRDATA_reg = {24'd0, ID_reg[7:0]};
                default: PRDATA_reg = 32'hDEADDEAD;
            endcase 
            apb_next_state = APB_IDLE;
        end
    endcase
end

assign PREADY = (apb_current_state==APB_READ|apb_current_state==APB_WRITE)? 1'b1:1'b0;

This module is instantiated within nanosoc_sysio_adc_ss, which is a child of nanosoc_region_sysio. To add this to nanosoc, a new port in the AHB mux was added, and an APB bus was created off this port. To verify this module, some simple read/write tests were excecuted:

  • Read from ID registers and verify contents
  • Read from CLK_DIV register for the default 0x0A (as set by the reset condition not shown in above code)
  • Write to CLK_DIV and then read contents to ensure they have changed
  • Write to ENABLE register 
  • Read from DATA register.

 

SAR ADC Verilog-AMS modelling

parameter integer bits = 8;// from [1:24];	// resolution (bits)
parameter real fullscale = 1.2;		// input range is from 0 to fullscale (V)
electrical EXTIN;
real sample, midpoint, cmp;
integer i;
reg [bits-1:0] buffer;
reg [bits-1:0] out;

assign DATA=out;
assign midpoint = fullscale/2.0;

assign cmp = buffer[7]*(fullscale/2.0) + buffer[6]*(fullscale/4.0) + buffer[5]*(fullscale/8.0) + buffer[4]*(fullscale/16.0)
	 + buffer[3]*(fullscale/32.0) + buffer[2]*(fullscale/64.0) + buffer[1]*(fullscale/128.0) + buffer[0]*(fullscale/256.0);
always @(posedge adc_clk or negedge resetn) begin
	if(~resetn) begin
		i <= 7;
		buffer <= 8'h80;
		out <= 8'h00;
	end else begin
		if(i==0) begin
			if (sample>cmp) 
				out <= {buffer[7:1], 1'b1};
			else
				out <= {buffer[7:1], 1'b0};
			buffer <= 8'h80;
			i <= 7;
			sample = 0.51;
		end else begin
			if (sample>cmp) 
				buffer[i]<=1'b1;
			else
				buffer[i]<=1'b0;
			if(i!=0)
				buffer[i-1]<=1'b1;
			i <= i-1;
		end
	end
end

The main bulk of the ADC model is shown in the above code. You can see from this that at each clock cycle, the sample which is captured every 8 clock cycles, is compared against the output of a DAC. 

SAR ADC verilog AMS simulation

To test the verilog-AMS model, a constant 0.51V was applied to the input. At each clock edge, the sampled value is compared to ''cmp'' which is effectively the DAC output. This DAC output is generated from the value in 'buffer'. It can be seen from this model, that after 8 clock cycles the output is captured as 0x6C, which for a 1.2V full scale ADC gives a corresponding voltage of 0.50625 V, just below the applied 0.51 V. 

Over the APB Interface the read output is 0x6C, confirming that both the ADC model works, and that APB register access is working as expected

Pinlist

Define the pin configuration for the external signal to interface to the ADC function.

Design and validation testbench

To be added

 

Project Milestones

  1. Behavioural Design

    Target Date

    Design of the components of the Analog-digital converter

  2. Behavioural Modelling

    Target Date

    Model the analog behaviour of the subsystem and confirm it meets the requirements

  3. Mixed Signal Simulations

    Target Date

    Simulation of the full mixed signal subsystem

  4. Integration with nanoSoC

    Target Date

    Integration of the top level interface within nanoSoC with mixed signal simulations

  5. Floor Planning

    Design Flow
    Target Date

    Floor planning and layout of the subsystem

Team

Research Area
Low power system design
Role
Consultant

Additional Project for:

Reference Design
nanoSoC demo: kNN project
nanoSoC
A simple, low cost, entry level microcontroller SoC extendable for custom accelerators or simple signal processing, ideal for PhD or other students.

Comments

Although the actual work of Integration with nanosoc comes later in the milestone I feel we should complete the Architecture definition as soon as we can. This will help contestants in the educational/collaboration track with their own Architecture definitions.

Hi Ayodeji,

I think from the front end side, the best place to start is to consider what kind of sensors you want to connect to, and what requirements they have. Particularly - voltage range, input type (single ended or differential are most common),  are they active or passive, how frequently you want to read the sensor, and what digital resolution you need.
I think once you have this information you can start thinking about what the requirements are on the analog front end. For instance if you have a differential input, you will need some sort of differential amplifier that feeds into the ADC. 

Once you have done this if you could add this information on your project we can continue to assist you there
We will make this work public on the accelerator project repository shortly, I'm just trying to get it working in a way that doesn't break the digital only flow, so you can possibly integrate this into your design as well

Daniel

 

There have been some recent discussions of how to improve the design of nanoSoC to enable finer power management of parts of the system to enable more precise measurement of energy consumption.

It would be interesting to understand the potential for the sensor subsystem. One option might be to have a power management function that distributes the AHB clock to only a selected set of peripherals where the external environment can determine the set to select. This might be configured as part of the SoC startup or perhaps as  masks that can be set at run time to distribute the clock to a limited number of selected peripherals.

There was some discussion on whether to use simple registers to keep the gate count low, as is a key driver for nanoSoC or to use a specific power management controller.

Any power management design may need to consider what other considerations need to be taken, for example,  any voltage regulators that can be set to run in low-power mode, if any of the sensor system needs some energy even in an idel state. 

The  interrupt mechanism that causes the re-selection of the peripheral device to return to active operation and any latency associated with this action.

Add new comment

To post a comment on this article, please log in to your account. New users can create an account.

Project Creator
Daniel Newbrook

Digital Design Engineer at University of Southampton
Research area: IoT Devices
ORCID Profile

Submitted on

Actions

Log-in to Join the Team