Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
16 years ago

Strange behaviour whene reading custom component register

Hello,

I got a strange problem when reading the registers of a custom component in a Nios II/SOPC system. The system includes a Nios II/e cpu, on-board RAM, external SRAM, interval timer, JTAG-UART, PIO port and a custom component connected via Avalon-MM, called TemperaturePID. The system communicates with a PC terminal over the JTAG-UART.

I wrote a device driver with IOWR and IORD functions for the TemperaturePID. I'm able to write and read the registers with this functions, but i found out, that a read-operation alters the register content.

If I start the system and type in the command to read out the registers, the system outpus the initial values:

IOS            0x00200010
Center frequency    25000
Temperature coefficient    94
Correction value    0
Temperature upper limit    200000
Temperature lower limit    -200000
CTRL            0x0000000F
Setpoint        25000
Proportional gain    100
Integrator time        3.000
Derivation time        0.000
LPF coefficient 0    -1
LPF coefficient 1    1
Output upper limit    10638298
Output lower limit    -10638298
Integrator limit    2147483647
If I retype the command, i get this:

IOS            0x001FFA37
Center frequency    2095665
Temperature coefficient    2095671
Correction value    2095675
Temperature upper limit    2095667
Temperature lower limit    2095679
CTRL            0x001FFA41
Setpoint        2095666
Proportional gain    2134092
Integrator time        Inf
Derivation time        150.900
LPF coefficient 0    2095671
LPF coefficient 1    2095669
Output upper limit    2095669
Output lower limit    2095676
Integrator limit    2095677
If I again retype the command, the values will be different, but stil in the range around 2090000 (decimal). I'am able to write new values in the register, again the first red operation shows the right values and the next read operation shows strange values.

One thing my be interresting: the base-address of the component is 0x00209000 and the strange values are aroung 2090000 (decimal). Maybe this is just coincidence...

This is the code-snipped that is responsible for the screen output:

printf("Currently set values:\n\n");   
printf("IOS\t\t\t0x%08X\n", IORD_TEMPERATUREPID_IOS(TEMPERATUREPID_0_BASE));
printf("Center frequency\t%d\n", IORD_TEMPERATUREPID_CTF(TEMPERATUREPID_0_BASE));
printf("Temperature coefficient\t%d\n", IORD_TEMPERATUREPID_TXC(TEMPERATUREPID_0_BASE));
...
printf("Integrator limit\t%d\n\n", IORD_TEMPERATUREPID_ILIM(TEMPERATUREPID_0_BASE));
And this is the device-driver file:

#ifndef __TEMPERATURE_PID_REGS_H__# define __TEMPERATURE_PID_REGS_H__
# include <io.h>
# define IORD_TEMPERATUREPID_IOS(base)           IORD(base, 0x00) # define IOWR_TEMPERATUREPID_IOS(base, data)     IOWR(base, 0x00, data)
# define IORD_TEMPERATUREPID_CTF(base)           IORD(base, 0x01) # define IOWR_TEMPERATUREPID_CTF(base, data)     IOWR(base, 0x01, data)
...
# endif /* __TEMPERATURE_PID_REGS_H__ */
Does anybody have a clue what is going on here?

If someone needs more information, please ask.

Thanks i advance,

magixD

7 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    It's strongly recommended setting 32 bits data buses for your custom components despite of how many bits it's currently using. Default addressing mode on a custom component is DYNAMIC, you could try setting the deprecated mode NATIVE.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Could you share some source code of your custom component? Especially the Avalon interface.

    What read/write timing settings did you use when you created the component in SOPC builder?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    It's strongly recommended setting 32 bits data buses for your custom components despite of how many bits it's currently using. Default addressing mode on a custom component is DYNAMIC, you could try setting the deprecated mode NATIVE.

    --- Quote End ---

    My component is using 32 bits data bus and 7 bits address bus. I took a look on the avalon specification oct 2008 page 31 ff "3.6 Address Alignment", where it says that native addressing is only avaiable for SOPC builder < v8.0. I'm using v9.0 SP2, so i guess i can not use it?

    --- Quote Start ---

    Could you share some source code of your custom component? Especially the Avalon interface.

    What read/write timing settings did you use when you created the component in SOPC builder?

    --- Quote End ---

    I attached the top-level file (TemperaturePID.vhd), the file that handels the register access (Registers.vhd) and the *_hw.tcl file.

    I don't use the interface properties writewaittime and readwaittime, because I use the waitrequestsignal instate.

    magixD

    edit:

    Change the line

    set_interface_property avalon_mm_slave addressAlignment DYNAMIC

    to

    set_interface_property avalon_mm_slave addressAlignment NATIVE

    in the *_hw.tcl file didn't solve the probleme.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    The problem could come from the fact that you have an asynchronous design, that probably infers latches. Also your waitrequest signal is always 0.

    The Avalon bus is synchronous, and you should make the process run on the rising edge of the clock:

    
    	Avalon : process (Clock, Reset)
    		if (Reset = '1') then
    			-- reset variables / signals
    			
    			
    		elsif rising_edge(Clock) then
    		
    			-- avalon read
    			if (ReadAV = '1') then
    				ReadDataAV <= (others => '0'); -- default
    				
    				case AddressAV is
    				
    					when X"00" =>
    						ReadDataAV<= ***;
    					when ***
                                              
    					when others =>
    						null;
    						
    				end case; -- address
    			
    			-- avalon write
    			elsif (WriteAV = '1') then
    			
    				case AddressAV) is
    				
    					when X"00" =>
    						*** <= WriteDataAV;
    					when ***
                                              
    					when others =>
    						null;
    						
    				end case; -- address
    			
    			end if; -- read/write
    		end if; -- clock cycle
    	end process Avalon;
    

    I would also recommend to use fixed timing instead of WaitRequest. With this process structure, the default 1 wait cycle for read and 0 wait cycle for write will work.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    You are right, it was a bad idea to make the register design asynchronous. I added the clock signal like you suggested and re-compiled the design Quartus II. Than i re-built the software and downloaded it to the board, but i get the following error message:

    Using cable "USB-Blaster ", device 1, instance 0x00
    Processor is already paused
    Initializing CPU cache (if present)
    OK
    Downloading 00100020 ( 0%)
    Downloading 00110000 (83%)
    Downloaded 77KB in 1.3s (59.2KB/s)
    Verifying 00100020 ( 0%)
    Verify failed between address 0x100020 and 0x10FFFF
    Leaving target processor paused
    This happened once before, as i changed something in my custom component.

    I also tried to re-create the component von scratche, generated the SOPC system again and re-compiled the design with Quartus II but i still get this error. When I change back to the asynchronous design, everything works fine.

    The program is stored on an external 1MB SRAM, starting at 0x100000.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    My best guess is that the timing settings that you've set up for the SRAM interface are too tight. But to be sure you should run the memory test software example. For that you should put the software in the on-chip memory, and have it test the SRAM. Maybe it will help you find where the problem is coming from.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    My best guess is that the timing settings that you've set up for the SRAM interface are too tight. But to be sure you should run the memory test software example. For that you should put the software in the on-chip memory, and have it test the SRAM. Maybe it will help you find where the problem is coming from.

    --- Quote End ---

    Hallo Daixiwen,

    After successfully checking the memory with the memory test programm, i had a very close look in every piece of code that has to do with the SRAM, and finaly i found a error in the pin asssignment TLC-script: i called the output enable and write enable signales oe_n and we_n instead of oe and we. Oddley enough, the sytem sometimes worked with the wrong settings.

    So finale i changed the pin assignments, eliminated the waitrequest signal, changed the registers to syncronous design and everything works fine so far. No I'm going to have a look at interrupts (especially timer interrupts), hopefully everything works out cool too.

    Daixiwen, thank you very much for helping me!

    magixD