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.
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.
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.
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.00 | 590.22 | -9.78 | -2.09 |
300.00 | 291.78 | -8.22 | -1.75 |
150.00 | 142.33 | -7.67 | -1.64 |
75.00 | 69.09 | -5.91 | -1.26 |
37.50 | 34.07 | -3.43 | -0.73 |
18.75 | 16.94 | -1.81 | -0.39 |
9.38 | 8.47 | -0.91 | -0.19 |
4.69 | 4.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
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
start-address | end-address | notes |
---|---|---|
0x40000000 | 0x40000FFF | Timer 0 |
0x40001000 | 0x40001FFF | Timer 1 |
0x40002000 | 0x40003FFF | Dual Timer |
0x40004000 | 0x40004FFF | UART 0 |
0x40005000 | 0x40005FFF | UART 1 |
0x40006000 | 0x40006FFF | UART 2 |
0x40008000 | 0x40008FFF | Watchdog Timer |
0x4000E000 | 0x4000EFFF | USRT 2 |
0x4000F000 | 0x4000FFFF | DMA 0 Base |
0x40010000 | 0x40010FFF | GPIO 0 |
0x40011000 | 0x40011FFF | GPIO 1 |
0x4001F000 | 0x4001FFFF | System Control |
0x4002000 | 0x4002FFF | ADC 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.
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
-
Behavioural DesignDesign FlowTarget Date
Design of the components of the Analog-digital converter
-
Behavioural ModellingDesign FlowTarget Date
Model the analog behaviour of the subsystem and confirm it meets the requirements
-
Mixed Signal SimulationsTarget Date
Simulation of the full mixed signal subsystem
-
Integration with nanoSoCTarget Date
Integration of the top level interface within nanoSoC with mixed signal simulations
-
Floor PlanningDesign FlowTarget Date
Floor planning and layout of the subsystem
Comments
Integration with nanosoc
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.
Tutorials
Hello John,
I need some tutorials to help me with approach to progress in my design.
Thank you and kind regards,
Progressing
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
Power Management to enable measurement of energy consumption
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.