Gloria

Questions about SPIADC on Papilio Pro LX9

Recommended Posts

Hi all, I'm trying to work with SPIADC on Papilio Pro LX9 and I have some questions:

1. What type of ADC device is the analogue example sketch written for? In SPIADC example sketch, the WISHBONESLOT(6) was used but it was not found in schematics of Papilio Pro LX9 board.

2. If we use slot1 on Vanilla, how do we enable MOSI etc. signals to route them to a Wing pin?

 

Thanks a million.

Share this post


Link to post
Share on other sites

Hello,

 

All of the SPI ADC examples are for the Analog Grove Wing.

 

Please see this page for an example of shifting a pin with the Vanilla variant.

http://www.papilio.cc/index.php?n=Papilio.ZPUinoUserGuide#PPS

 

For tutorials about the Schematic library look at tutorials here:

http://learn.gadgetfactory.net/

Share this post


Link to post
Share on other sites

I use the following code to process ADC input from a Retrocade mega wing. That board has 2x8bit ADC chips communicating over SPI.

 

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
//
// Engineer:       Stephen Davies
//
// Create Date:    21:05:48 10 Jan 2013
// Design Name:    
// Module Name:    ADC
// Project Name:   MiniMoog sim
// Target Devices: Spartan 6
// Tool versions:  ISE 14.4
// Description:    State machine logic for polling a TI ADC088S102 ADC chip.
//                 Logic operates in a loop, polling the current port value in a
//                 single 'frame'. Each input port (of 8) is sampled in its own
//                 frame, delimited by CS, so that synchronisation is maintained.
//
//                 A future implementation could make the frames larger, querying all
//                 8 ports in a single frame. This would improve throughput. Maximum
//                 throughput would sample each individual port @125k samples/s. Per port
//                 framing reduces this a little but not enough to worry about given
//                 that the main function for the analog pins is to attach pots & switches.
//
// Dependencies:
//
// Revision:       0.01
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////

module ADC
    #(
        parameter ADC_WIDTH=8            // ADC sample size in bits
    )
    (
   input clk,                        // 16 MHz clk (max for ADC088S102)
   input reset,                    // active high

   output sck,                        // SPI clock (16MHz max for ADC088S102)
   output reg cs_n,                // ADC chip select, active low
   input  din,                        // data stream from ADC chip, sampled on rising edge of SCK
   output reg dout,                // data stream to ADC, ADC chip samples on rising edge of SCK
    
    input [2:0] addr,                // register read address
    output [ADC_WIDTH-1:0] q    // register output value
   );

    // State machine states
   localparam RESYNC = 1'b0;    // ADC chip select (CS) taken high
   localparam SAMPLE = 1'b1;    // ADC chip select (CS) taken low, analog data being sampled

    // Variables
   reg  [6:0]  count;            // 7 bit counter, low order 4 bits count 16 SCK pulses per frame.
                                        // high order 3 bits indicate current port
    wire [2:0]  currentPort;    // port we are receiving dataIn for
   reg  [4:0]  dataOut;            // Output shift register, contains next port address and two 0 bits. Not all 16 bits are required as unused bits default to 0.
    reg  [15:0] dataIn;            // Input shift register, contains current anaolg sample plus padding
    wire [2:0]  nextPort;        // next analog port to be read, sent as part of current dataOut frame
    wire        endFrameTick;    // indicates end of frame has been reached, drives FSM through RESYNC state

   (* RAM_STYLE="DISTRIBUTED" *)
   reg [ADC_WIDTH-1:0] adcReg [7:0];

   (* FSM_ENCODING="SEQUENTIAL", SAFE_IMPLEMENTATION="YES", SAFE_RECOVERY_STATE="RESYNC" *)
    reg state = RESYNC;                            // FSM state (at initial state)
    
    assign endFrameTick = &count[3:0];        // at end EOF when count == 4'b1111
    assign currentPort = count[6:4];            // values 0-7
    assign nextPort = currentPort + 3'd1;
    assign q = adcReg[addr];
    
    //
    // FSM
    //
   always@(posedge clk, posedge reset)
      if (reset) begin                            // system reset
         state <= RESYNC;
            count <= 7'b0;
            cs_n  <= 1'b1;
      end
      else
         (* PARALLEL_CASE, FULL_CASE *) case (state)
            RESYNC : begin                        // immediately moves to SAMPLE state after resetting key values
               state <= SAMPLE;
                    count <= { count[6:4], 4'b0 };    // preserves nextPort value
               cs_n  <= 1'b0;
            end
            SAMPLE : begin
               if (endFrameTick) begin                // when 15 SCK cycles have occurred, RESYNC for next analog port
                  state <= RESYNC;
                        count <= count + 7'd1;
                        cs_n <= 1'b1;
                    end
               else begin                                // keep on clocking...
                  state <= state;
                        count <= count + 7'd1;
                        cs_n <= 1'b0;
                    end
            end
            default: begin                                // Fault Recovery
               state <= RESYNC;
                    count <= 7'b0;
                    cs_n  <= 1'b1;
             end
         endcase
    
    //
    // DOUT shift register, selects next port to sample
    // 5 bits long because first 3 bits are zero, next 3 are port and next 10 are zero.
    //
    always @(negedge clk, posedge reset)
      if (reset) begin
         dataOut <= 5'b0;
         dout    <= 1'b0;
      end
      else if (cs_n) begin        // load register at start of frame
         dataOut <= { nextPort[0], nextPort[1], nextPort[2], 2'b0 };
         dout    <= 1'b0;
      end
      else if (!cs_n) begin    // shift next bit
         dataOut <= { 1'b0, dataOut[4:1] };
         dout    <= dataOut[0];
      end

    //
    // DIN shift register
    //
   always @(posedge clk)
      if (!cs_n)
         dataIn <= { dataIn[14:0], din };
        else
            adcReg[currentPort] <= dataIn[11:4];
        
    //
    // Spartan 6 requires special handling for sending clk16 on SCK pin. (not a 'special' clock output pin apparently)
    //
    ODDR2 ODDR2_inst (.Q(sck), .C0(clk), .C1(!clk), .CE(1'b1), .D0(1'b1), .D1(1'b0), .R(1'b0), .S(1'b0));
        
endmodule
 

Share this post


Link to post
Share on other sites

Hi Jack,

you're welcome. Feel free to redistribute. Probably not clear from the code but it uses dual ported RAM to store all 8 samples (adcReg). Data is available externally through use of addr inputs and q outputs.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now