cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
_vls_
Observer
Observer
10,000 Views
Registered: ‎04-14-2012

How to get output from ADC picoblaze

Hi everyone,

 

I know the title of this thread may sound silly. I've just only learn PicoBlaze on Spartan 3E Starter Kit. I learned the theory of Analog Capture Circuit, but I confused about how I get the result of ADC which using PicoBlaze.

After trying to understand the code, I may have conclution that I will get the ADC result value from line 291 in file picoblaze_amp_adc_control.vhd (I attached the file). Is my assumption true? If this is true, so how can I get the 14 bit 2's complement result from Analoge Capture Circuit?

 

Because the point is, I want to use the ADC result for other module. So, it will be useless if I only know the ADC result from LCD on board.

 

Thank you very much! :)

0 Kudos
22 Replies
chapman
Xilinx Employee
Xilinx Employee
9,994 Views
Registered: ‎09-05-2007

You say that you have been trying to understand the code but did you do that whilst referring to the PDF document for the reference design?

 

http://www.xilinx.com/products/boards/s3estarter/files/s3esk_picoblaze_amplifier_and_adc_control.pdf

 

On page 11 you will see the physical connections between PicoBlaze and the A/D converter and the nature of the serial data transaction that is required to read the two 14-bit data samples corresponding with the two A/D channels.

 

Line 291 of the  ‘picoblaze_amp_adc_control.vhd’...

 

      spi_sdi <= out_port(7);

 

....is part of the description of a PicoBlaze OUTPUT port so this is definitely not where PicoBlaze reads the A/D sample data.

 

 

It is line 252 that is part of the definition of an INPUT port....

 

    when "01" =>    in_port <= spi_sdo & spi_amp_sdo & "000000";

 

...and the place where PicoBlaze gets to read each bit of serial data from the A/D converter.

 

 A circuit diagram on page 17 of the PDF document shows you all the input and output ports.

 

 

Page 13 of the PDF document shows you the ‘adc_read’ routine that reads the samples from the A/D converter. At the top of the page it says the following....

 

On return, the register pair [s9,s8] contains the value for Channel0 and the register pair [s7,s6] contains the value for Channel1.

 

So if you use the same code then you now know exactly which registers will hold the data samples and you can decide what to do with them next. 

Ken Chapman
Principal Engineer, Xilinx UK
0 Kudos
_vls_
Observer
Observer
9,973 Views
Registered: ‎04-14-2012

Thank you so very much, Sir

 

So, I may have conclude that the result should be on register [S9, S8] and [S7, S6]. But I'm confused about getting the value from register. Can I use the code below...?

 

...

signal ADC_value: STD_LOGIC_VECTOR (13 downto 0);
signal count: INTEGER range 0 to 13 := 13;

...

when "01" => in_port <= spi_sdo & spi_amp_sdo & "000000";
ADC_value (count) <= spi_sdo;

if count = 0 then
count := 13;
else
count := count - 1;
end if;

...

 

If this not enough to get the value from register, can you please give me some reading materials in order to get this done? The thing is I want to save the ADC result in a variable or signal that have 14 bits so I can use it for other modules.

 

Thank you :)

0 Kudos
chapman
Xilinx Employee
Xilinx Employee
9,967 Views
Registered: ‎09-05-2007

I have the feeling that you don’t really know that PicoBlaze is a processor so I suggest that you first read the documentation for PicoBlaze (UG129 for the Spartan-3 version called KCPSM3). You need to understand what a processor is and the concepts of ‘input ports’, ‘output ports’ and ‘registers’.

 

As previously described, PicoBlaze in this reference design has already performed all the operations (including amplifier control) required to read data samples into 4 of its registers so it would be a very simple modification to the HDL and PSM files in order to have PicoBlaze write the contents of those registers to a set of ‘output ports’. In this case you wouldn’t have to touch any of the interface with the amplifier and A/D converter devices or the code that controls and reads them. The diagram on page 17 of the PDF document already shows an example of a simple output port used to drive the LEDs so add a few more output ports similar to this. I also have the feeling that this may be a university project so it would be inappropriate for me to modify and provide you with the code.

 

Alternatively, you may choose not to use PicoBlaze at all and implement your own hardware based state machine that implements the serial communication to control and read the amplifier and A/D components. That would be a good design exercise but almost certainly far more difficult than to understand the PicoBlaze design and implement some simple modifications.

Ken Chapman
Principal Engineer, Xilinx UK
0 Kudos
_vls_
Observer
Observer
9,960 Views
Registered: ‎04-14-2012

Thank you Sir

 

First of all, I know that PicoBlaze is a processor. And secondly, this is not an uni project. This is an experiment for myself to broaden my knowledge. Beside, FPGA is a new thing in my uni. There's no one expert in this device. I, as a lab asisstant and few months towards graduation, want to learn this and hopefully could give this knowledge to others.

 

I learn FPGA, espescially Spartan 3s500E Starter Kit, by case. I make a system that use sensor MQ-7. The whole project (giving PWM to activate sensor; and control buzzer, led, and fan) already done except for reading sensor using ADC. And this is my problem. :)

 

I have tried to make ADC code but it is failed. I have tried to modify from other people code (not using PicoBlaze), but it is also failed. Then I realize so many people using PicoBlaze. So i decided to learn about it and then I stuck again. :)

 

I'm not saying that you should give me the whole code, but then again I need help to give me the idea (big overview) for me, the newbie, to learn more about it. And I already read the KCPSM3 manual, but still in understanding period.

 

Thank you in advance..

 

 
0 Kudos
_vls_
Observer
Observer
9,958 Views
Registered: ‎04-14-2012

I also in middle of reading UG129 :)

 

Hope I can learn more from it..

0 Kudos
eteam00
Instructor
Instructor
9,956 Views
Registered: ‎07-21-2009

You might consider the beginner projects found here to help you better understand the gates and flip-flops which are used to build digital logic systems.

 

Good luck to you.

 

-- Bob Elkind

SIGNATURE:
README for newbies is here: http://forums.xilinx.com/t5/New-Users-Forum/README-first-Help-for-new-users/td-p/219369

Summary:
1. Read the manual or user guide. Have you read the manual? Can you find the manual?
2. Search the forums (and search the web) for similar topics.
3. Do not post the same question on multiple forums.
4. Do not post a new topic or question on someone else's thread, start a new thread!
5. Students: Copying code is not the same as learning to design.
6 "It does not work" is not a question which can be answered. Provide useful details (with webpage, datasheet links, please).
7. You are not charged extra fees for comments in your code.
8. I am not paid for forum posts. If I write a good post, then I have been good for nothing.
0 Kudos
chapman
Xilinx Employee
Xilinx Employee
9,947 Views
Registered: ‎09-05-2007

Always great to hear when someone like you is learning something because they want to so well done. That said, you’ll still learn most by working through your own problems with pointers rather than answers on a plate. However, now that we understand your position a little more than I a have to agree with ‘eteam00’ and suggest that you start with something easier than reading an serial communication A/D on a board that requires you to set up the amplifier as well.

 

PicoBlaze has been used in education for nearly 20 years so shouldn’t be too much of a challenge if you take it one step at a time. I highly recommend that your first attempt at using it starts with it only connected to switches and LEDs. Not that I want you to cheat but the very first reference design (‘Initial Design for the Spartan-3E FPGA Starter Kit Board’ at http://www.xilinx.com/products/boards/s3estarter/reference_designs.htm) for the Spartan-3E Starter Kit has already set that up for you so just start playing with that to begin with. Of course you’ll need to read the documentation but having your head stuck half way though UG129 can’t be fun and PicoBlaze is supposed to be 90% fun so start playing hands on (hint: JTAG Loader).

Ken Chapman
Principal Engineer, Xilinx UK
0 Kudos
twistek
Observer
Observer
7,770 Views
Registered: ‎06-19-2014

Hi, I am study nuclear science instrumentation, and I have one project for make one multichannel analizar for nuclear spectrometry, I have one starter kit spartan 3e, I study this topic because I want know use the AD converter with picoblaze, I downloaded the example of AD converter with picoblaze, now I want get the output of the AD with contain the 2 registers s9,s8 (channel 0) and s7,s6 (channel 1), I dont know how take this register to VHDL code, and I need compare this hexadecimal number to select external memory location and add a 1 in this location, because the multichannel analyzer use the conversion to select the location in memory and add one value, to make one spectrometry with 65536 locations in agreement to conversion E000 to 1FFF, can you help me? thanks

Student in Master of Nuclear Science, Electronic Instrumentation, University Autonomous of Zacatecas, Mexico.
5x5x500_d.gif
0 Kudos
chapman
Xilinx Employee
Xilinx Employee
7,719 Views
Registered: ‎09-05-2007

It is not clear what your actual specification is but it might be a good idea to start by implementing a simple proof of concept version to begin with. So I’d recommend that you first try connecting an internal memory to PicoBlaze and try storing values in that. Internal memory can be formed of Block Memories (BRAMs) and the Core Generator can be used to make a larger memory out of several BRAMs. The XC3S500 device has 20 BRAMs in total and PicoBlaze only uses one of them leaving you quite a few to play with.

Ken Chapman
Principal Engineer, Xilinx UK
0 Kudos
twistek
Observer
Observer
7,406 Views
Registered: ‎06-19-2014

Thank you Dr. Ken Chapman.

 

ok, to start is correct if sent outside this register (s9, s8) channel 0 , with this routine :

 

adc_read:      CALL SPI_init                                                                ; ensure known state of bus and s0 register
                        XOR s0, SPI_adc_conv                                               ;Pulse AD-CONV High to take sample and start
                       OUTPUT s0, SPI_control_port                                   ; conversion and transmission of data.
                        XOR s0, SPI_adc_conv                                               ;AD-CONV Low
                        OUTPUT s0, SPI_control_port
                        LOAD s1, 22                                                                  ;34 clocks to read all data
                        OUTPUT s8, ADC_output_register_low1                ; lower nibble 1 in address 10 Hex bit 4 ------------- check

                        OUTPUT s9, ADC_output_register_upp1               ; upper nibble 1 in address 20 Hex bit 5 ------------- check

    

next_adc_bit: XOR s0, SPI_sck                                                          ;clock High (bit0)
                         OUTPUT s0, SPI_control_port                                   ;drive clock High
                         XOR s0, SPI_sck                                                           ;clock Low (bit0)
                        OUTPUT s0, SPI_control_port                                    ;drive clock Low
                         INPUT s3, SPI_input_port                                           ;read input bit
                        TEST s3, SPI_sdi                                                           ;detect state of received bit
                         SLA s6                                                                             ;shift new data into result registers
                         SLA s7
                         SLA s8
                         SLA s9
                         SUB s1, 01                                                                     ;count bits
                        JUMP NZ, next_adc_bit                                                 ;repeat until finished
                        SRX s9                                                                             ;sign extend 14-bit result in [s9,s8]
                        SRA s8
                        SRX s9
                        SRA s8
                        SRX s7                                                                              ;sign extend 14-bit result in [s7,s6]
                        SRA s6
                        SRX s7
                        SRA s6
                        RETURN

Student in Master of Nuclear Science, Electronic Instrumentation, University Autonomous of Zacatecas, Mexico.
starter multichannel.jpg
0 Kudos
chapman
Xilinx Employee
Xilinx Employee
7,397 Views
Registered: ‎09-05-2007

In the reference design the interrupt service routine reads the ADC and stores the pair of samples in scratch pad memory.

 

CALL adc_read       ;read A/D Converter

STORE s8, ADC0_lsb  ;store ADC Channel 0

STORE s9, ADC0_msb

STORE s6, ADC1_lsb  ;store ADC Channel 1

STORE s7, ADC1_msb

 

If you want to output the samples then simply define 4 ouput ports and then read the ADC and output the samples to them...

 

CALL adc_read             ;read A/D Converter

OUTPUT s8, ADC0_lsb_port  ;store ADC Channel 0

OUTPUT s9, ADC0_msb_port

OUTPUT s6, ADC1_lsb_port  ;store ADC Channel 1

OUTPUT s7, ADC1_msb_port

 

 

 

Ken Chapman
Principal Engineer, Xilinx UK
0 Kudos
twistek
Observer
Observer
7,391 Views
Registered: ‎06-19-2014

Thank you Dr. Ken Chapman

 

I try to get this register to signals in VHDL, when I have more questions I will contact. 

 

 

regards

Arturo Aref

Student in Master of Nuclear Science, Electronic Instrumentation, University Autonomous of Zacatecas, Mexico.
0 Kudos
twistek
Observer
Observer
7,337 Views
Registered: ‎06-19-2014

Hi Dr. Ken Chapman

 

I have done this configuration, I only use the channel 0 because in the output port encoding is in " one hot"  and only have 8 bits, then I have this code, it is correct ? 

 

;Register Output port Address
;
CONSTANT ADC0_lsb_outport, 10 ; register s8 output port bit 4
CONSTANT ADC0_msb_outport, 20 ; register s9 output port bit 5

;

-------------------------------------------------------------------------------------------------

ISR: CALL adc_read ;read A/D Converter
         STORE s8, ADC0_lsb                                 ;store ADC Channel 0
         STORE s9, ADC0_msb
         STORE s6, ADC1_lsb                                  ;store ADC Channel 1
         STORE s7, ADC1_msb
         ;
         OUTPUT s8, ADC0_lsb_outport                 ;register s8 output port
          OUTPUT s9, ADC0_msb_outport              ;register s9 output port
          ;
         LOAD sF, 00                                                    ;clear flag
         RETURNI ENABLE

 

in VHDL

 

signal reg_msb_s9 : std_logic_vector(7 downto 0);
signal reg_lsb_s8 : std_logic_vector(7 downto 0);
signal mem_address : std_logic_vector(15 downto 0);

 

-- KCPSM3 output ports
----------------------------------------------------------------------------------------------------------------------------------
--

-- adding the output registers to the processor

output_ports: process(clk)
begin

                            if clk'event and clk='1' then
                                if write_strobe='1' then

                                                   .

                                                   .

                                                   .

                                    if port_id(4)='1' then

                                        reg_lsb_s8 <= out_port(7 downto 0);
                                       mem_address <= mem_address(15 downto 8) & reg_lsb_s8;

                                   end if;

                                    if port_id(5)='1' then

                                        reg_msb_s9 <= out_port(7 downto 0);
                                        mem_address <= reg_msb_s9 & mem_address(7 downto 0);

                                    end if;

                         end if;

                end if;

end process output_ports;

Student in Master of Nuclear Science, Electronic Instrumentation, University Autonomous of Zacatecas, Mexico.
circuito picoblaze 1.jpg
0 Kudos
chapman
Xilinx Employee
Xilinx Employee
7,295 Views
Registered: ‎09-05-2007

It looks like you have correctly defined a pair of output ports and output data to them. The only thing that I would change in your VHDL is the way in which the two 8-bit output registers are combined into a single 16-bit bus. You only need one statement as follows...

 

     mem_address <= reg_msb_s9 & reg_lsb_s8;

This statement should be outside of the clocked process. It does not need to be clocked (synchronous) because it only represents connections.

 

 

Ken Chapman
Principal Engineer, Xilinx UK
0 Kudos
timurgepard
Participant
Participant
7,256 Views
Registered: ‎12-13-2013

It is very strange.

 

ADC converter, LCD display is one of the most important part of controllers.

 

Why we should be worried about all this mess with assembler code.

 

We should be given port to take data and port to put data. That's it. Nothing else nothing more.

 

The question was very simple, most of people buy Spartan 3E 500 because of it's ADC/DAC and LCD display capability. Instead of providing just clear answer how to set up ports, why somebody need to be aggresive towards costumers?

 

Student or whoever, does it matter? There are much easier questions regarding regular Xilinx ports and VHDL basics that were well answered.

0 Kudos
timurgepard
Participant
Participant
7,250 Views
Registered: ‎12-13-2013

I dont understand what you are doing.

 

 

If Mr Chapman is right, then

 

this code is pretty much everything:

 

when "01" => in_port <= spi_sdo & spi_amp_sdo & "000000";

 

Every clock period (which is 20ns and clock port is port C9 according to usf file) new adc bit should arrive.

 

I understand that then can be real challenge, since real data that goes to LCD display is not controled by "picoblaze_amp_adc_control". But by assempler code.  If I am right, you can delete pretty much everything else from "picoblaze_amp_adc_control".

 

Instead, if I were in you place I would use other method to send data to LCD display, which is based on documentation of page 53 of Spartan 3E Starter Kit board User guide and this guy genuinely described https://www.youtube.com/watch?v=lQ6YKQt6Rz4. Let us hope it works fine.

0 Kudos
chapman
Xilinx Employee
Xilinx Employee
7,239 Views
Registered: ‎09-05-2007

The A/D converter is associated with ‘spi_sck’ assigned to pin ‘U16’. As shown on page 10 of the design documentation, this clock is generated by PicoBlaze only when an SPI transaction takes place and then it has a frequency of 2.5MHz.

Ken Chapman
Principal Engineer, Xilinx UK
0 Kudos
twistek
Observer
Observer
6,954 Views
Registered: ‎06-19-2014

Hi Dr. Ken Chapman

 

I ready to work after holidays jaja

 

Excuseme Dr. Chapman, about the analizer multichannel, is necesary build one memory ram, this ram need add "1" + "1" when the address repeat, to make one histogram, can you help me with one example of memory ram histogram, I check and find this information 

 

 

something like this

 

if( rising_edge(clk) ) then
  RAM(addr) <= RAM(addr) + '1';
end if;

type RAM_T is array (0 to 65535) of std_logic_vector(7 downto 0);
signal RAM : RAM_T:=(others => (others => '0'));
Student in Master of Nuclear Science, Electronic Instrumentation, University Autonomous of Zacatecas, Mexico.
ramadd1.jpg
ramadd1add1.jpg
histogram radiation.png
0 Kudos
chapman
Xilinx Employee
Xilinx Employee
6,860 Views
Registered: ‎09-05-2007

Looking at the example of a histogram that you have shown it looks like there are only 20 ‘bins’ and that would correspond with only needing a memory with 20 address locations. The highest value is around 12,000 and that would correspond with 14-bit values (i.e. 16-bits can represent values up to 65,535). So for that particular case we could implement a histogram in the scratch pad memory of PicoBlaze.

 

So let’s imagine that we build the histogram using scratch pad memory. Each ‘bin’ will require two bytes (16-bits) requiring 2 memory locations so let’s reserve 40 memory locations (bytes)  00 to 27 hex for the bins.

 

Now let’s imagine the ‘s5’ register contains the value in the range 1 to 20 and this indicates the bin that needs to be incremented. For example, ‘s5’ is the value 7 so we want to increment the value in the 7th bin. We convert the value in ‘s5’ into a memory pointer and then simply fetch the existing value of the bin, increment it and then store it back again.

 

SUB s5, 1’d     ;convert to range 0 to 19 (e.g. 7 becomes 6)

SL0 s5          ;multiply by 2 (e.g. 6 becomes 12 = 0C hex)

FETCH s0, (s5)  ;fetch lower byte of histogram value

ADD s5, 1’d     ;increment memory pointer (e.g. 13 = 0D hex)

FETCH s1, (s5)  ;fetch upper byte of histogram value

ADD s0, 1’d     ;increment histogram value

ADDCY s1, 0’d

STORE s1, (s5)  ;store upper byte of histogram value

SUB s5, 1’d     ;decrement memory pointer

STORE s0, (s5)  ;store lower byte of histogram value

Ken Chapman
Principal Engineer, Xilinx UK
0 Kudos
twistek
Observer
Observer
3,240 Views
Registered: ‎06-19-2014

Hi Dr. Ken Chapman
About the "bins" in the multichannel Analyzer, I need use all bits 16 ( 65536 locations) I thinks is better use one external memory ram bock in VHDL, I builded this block

 


library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

 

entity rams_01 is
                           port (CLK : in std_logic;
                                   WE : in std_logic;
                                   EN : in std_logic;
                                   ADDR : in std_logic_vector(5 downto 0);
                                   DI : in std_logic_vector(15 downto 0);
                                   DO : out std_logic_vector(15 downto 0));
end rams_01;

 

architecture syn of rams_01 is

 

type ram_type is array (63 downto 0) of std_logic_vector (15 downto 0);
signal RAM: ram_type;


begin

 

process (CLK)
begin

 

                     if CLK'event and CLK = '1' then
                          if EN = '1' then
                                 if WE = '1' then
                                            RAM(conv_integer(ADDR)) <= DI;
                                 end if;
                                            DO <= RAM(conv_integer(ADDR)) ;
                          end if;
                      end if;
end process;

end syn;

 

one professor tell me, I need build one ADD and ONE comparator to make the histogram

 

ADD

 

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity add_1 is
                              port(A : in std_logic_vector(7 downto 0);
                                    SUM : out std_logic_vector(7 downto 0));
end add_1;

 

architecture archi of add_1 is

begin

SUM <= A + 1;

end archi;

 

 

and Comparator 

 

entity comparador is
                             Port ( Input_com1 : in STD_LOGIC_VECTOR (7 downto 0);
                                      Input_com2 : in STD_LOGIC_VECTOR (7 downto 0);
                                      Output_com : out STD_LOGIC_VECTOR (7 downto 0));
end comparador;

architecture Behavioral of comparador is

begin

                     Output_com <= "11111111" when Input_com1 = "11111111" else

                      Input_com2;

end Behavioral;

 

 

 

Is correct this approach ???

Student in Master of Nuclear Science, Electronic Instrumentation, University Autonomous of Zacatecas, Mexico.
0 Kudos
twistek
Observer
Observer
3,240 Views
Registered: ‎06-19-2014

sorry , I had one mistake in the RAM is 

 


library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity rams_01 is
                    port (CLK : in std_logic;
                           WE : in std_logic;
                            EN : in std_logic;
                             ADDR : in std_logic_vector(15 downto 0);
                            DI : in std_logic_vector(7 downto 0);
                            DO : out std_logic_vector(7 downto 0));
end rams_01;

architecture syn of rams_01 is
type ram_type is array (65535 downto 0) of std_logic_vector (7 downto 0);
signal RAM: ram_type;

Student in Master of Nuclear Science, Electronic Instrumentation, University Autonomous of Zacatecas, Mexico.
0 Kudos
chapman
Xilinx Employee
Xilinx Employee
3,231 Views
Registered: ‎09-05-2007

Please remember that you are asking these questions on the PicoBlaze forum in a thread titled ‘How to get output from ADC picoblaze”. Your last posts have been related to the pure hardware implementation of memory and adder logic!

 

You have asked me if this is the correct approach but I really still have no idea of your specification. I gave you an example of PicoBlaze code that would form the basis of a histogram for the image that you presented. I can only assume you ignored that because it wasn’t adequate for your specification whatever that is.

 

1)      Decide exactly how much memory you do need for your histogram. What address range do you need to have enough ‘bins’? How many data bits do you need to cover the range of values in each bin?

2)      Work out if you even have enough on-chip memory (BRAMs) to implement a memory that size.

3)      How long there is between samples (i.e. what is the sample rate)? If you have enough clock cycles between samples arriving then you may decide to use PicoBlaze to increment the appropriate location in the memory and generally be available to help manage your histogram. If samples arrive too quickly for PicoBlaze to process then you will need to implement dedicated hardware state machine and increment logic.

Ken Chapman
Principal Engineer, Xilinx UK
0 Kudos