Forum Discussion

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

Could not read 8 bit data from custom ram

Hi every body!

I'm a newbie in SOPC system design.

I'm trying to create a custom ip, which has an internal RAM (declare as an array) and contacts with NIOS via Avalon MM bus.

I'm using DE2 and this is my code for that ip:


library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_unsigned.all;
entity PIXELS_BUFFER is
	port(
		--- NIOS
		clock: IN STD_LOGIC;
		reset: IN STD_LOGIC;
		address: IN STD_LOGIC_VECTOR(3 downto 0); -- for testing
		chipselect: IN STD_LOGIC;
		byteenable: IN STD_LOGIC;
		writedata: IN STD_LOGIC_VECTOR(7 downto 0); -- 8-bit data
		readdata: OUT STD_LOGIC_VECTOR(7 downto 0); -- 8-bit data
		write: IN STD_LOGIC;
		read: IN STD_LOGIC
	);
end PIXELS_BUFFER;
architecture Behavioral of PIXELS_BUFFER is
	type ram_type is array (0 to 15) of std_logic_vector(7 downto 0);
	--- ROM definition
	signal RAM_CONTENT: ram_type := (
	"00000000",
	"00000001",
	"00000010",
	"00000011",
	"00000100",
	"00000101",
	"00000110",
	"00000111",
	"00001000",
	"00001001",
	"00001010",
	"00001011",
	"00001100",
	"00001101",
	"00001110",
	"00001111"	
	);
begin
	process(clock, reset, address, chipselect, byteenable, read, write, writedata)
	begin
		if(rising_edge(clock)) then
			if(chipselect='1') then
				if(read='1') then
					readdata <= RAM_CONTENT(conv_integer(address));
				end if;
				if(write='1') then
					RAM_CONTENT(conv_integer(address)) <= writedata;
				end if;
			end if;
		end if;
	end process;
end Behavioral;

In SOPC, I added my IP as:


signal	| Interface        | Signal type | WIDTH|Direction
clock       |  clock           | clk         |  1   | IN 
reset       |  reset           | reset       |  1   | IN 
address     | avalon_slave_0   | address     |  4   | IN 
chipselect  | avalon_slave_0   | chipselect  |  1   | IN 
byteenable  | avalon_slave_0   | byteenable  |  1   | IN 
writedata   | avalon_slave_0   | writedata   |  7   | IN 
readdata    | avalon_slave_0   | readdata    |  7   | OUT
write       | avalon_slave_0   | write       |  1   | IN 
read        | avalon_slave_0   | read        |  1   | IN 

my first work is reading RAM_CONTENT but i saw wrong result in my NIOS :((


# include <stdio.h>   
# include <io.h>       // using IORD_8DIRECT
# include "system.h" // using PIXELS_BUFFER_0_BASE
int main()
{
  int i;
  printf("Hello from Nios II!\n");
  for(i=0; i<16; i++) 
    // read byte by byte
    printf("Addr: %i\t%i \n", i, IORD_8DIRECT(PIXELS_BUFFER_0_BASE, i));
    
  return 0;
}

Results:


Addr: 0	0 
Addr: 1	0 
Addr: 2	1 
Addr: 3	2 
Addr: 4	3 
Addr: 5	4 
Addr: 6	5 
Addr: 7	6 
Addr: 8	7 
Addr: 9	8 
Addr: 10	9 
Addr: 11	10 
Addr: 12	11 
Addr: 13	12 
Addr: 14	13 
Addr: 15	14 

Why did it show that? I had no delay when transfering data to avalon bus, or no wait cycle in SOPC IP. Attach file is my project.

Could anybody help me? Thanks^^

6 Replies

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

    i believe your error is that there should be a read wait state. just as an fyi, there is no reason to use the read signal, you could have just always assigned readdata to the ram[address].

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

    Hi again,

    I just modified code vhdl ( add 1 when calculating address to read ram_content)

    
    if(read='1') then
            --- readdata <= RAM_CONTENT(conv_integer(address));
    	readdata <= RAM_CONTENT(conv_integer(address)+1); -- add 1
    end if;
    

    then i ran this code in NIOS:

    
    # include <stdio.h>
    # include <io.h>
    # include "system.h"
    int main()
    {
      int i;
      printf("Hello from Nios II!\n");
      printf("refill content of RAM\n");
      for(i=0; i<16; i++)
        IOWR_8DIRECT(PIXELS_BUFFER_0_BASE, i, i);
      
      printf("check wrote content\n");
      for(i=0; i<16; i++)
      {
        char x = IORD_8DIRECT(PIXELS_BUFFER_0_BASE, i);
        printf("Addr: %i\t%i\t", i, x);
        if(x!=i) printf(" <= ERROR\n");
        else printf("\n");
      }
      
      printf(" check again\n");
      for(i=0; i<16; i++)
      {
        char x = IORD_8DIRECT(PIXELS_BUFFER_0_BASE, i);
        printf("Addr: %i\t%i\t", i, x);
        if(x!=i) printf(" <= ERROR\n");
        else printf("\n");
      }
      
      printf("refill content but with new data\n");
      for(i=0; i<16; i++)
        IOWR_8DIRECT(PIXELS_BUFFER_0_BASE, i, 15-i); // add 0: 15 , add 1:14 ...
        
      printf("check wrote content\n");
        for(i=0; i<16; i++)
          {
            char x = IORD_8DIRECT(PIXELS_BUFFER_0_BASE, i);
            printf("Addr: %i\t%i\t", i, x);
            if(x!=15-i) printf(" <= ERROR\n");
            else printf("\n");
          }
          
      printf("check again\n");
        for(i=0; i<16; i++)
          {
            char x = IORD_8DIRECT(PIXELS_BUFFER_0_BASE, i);
            printf("Addr: %i\t%i\t", i, x);
            if(x!=15-i) printf(" <= ERROR\n");
            else printf("\n");
          }
      return 0;
    }
    

    I received new result, something still wrong, but in special case, as u see below:

    
    Hello from Nios II!
    refill content of RAM
    check wrote content
    Addr: 0	15	 <= ERROR
    Addr: 1	1	
    Addr: 2	2	
    Addr: 3	3	
    Addr: 4	4	
    Addr: 5	5	
    Addr: 6	6	
    Addr: 7	7	
    Addr: 8	8	
    Addr: 9	9	
    Addr: 10	10	
    Addr: 11	11	
    Addr: 12	12	
    Addr: 13	13	
    Addr: 14	14	
    Addr: 15	15
    	
    check again
    Addr: 0	0	
    Addr: 1	1	
    Addr: 2	2	
    Addr: 3	3	
    Addr: 4	4	
    Addr: 5	5	
    Addr: 6	6	
    Addr: 7	7	
    Addr: 8	8	
    Addr: 9	9	
    Addr: 10	10	
    Addr: 11	11	
    Addr: 12	12	
    Addr: 13	13	
    Addr: 14	14	
    Addr: 15	15
    	
    refill content but with new data
    check wrote content
    Addr: 0	0	 <= ERROR
    Addr: 1	14	
    Addr: 2	13	
    Addr: 3	12	
    Addr: 4	11	
    Addr: 5	10	
    Addr: 6	9	
    Addr: 7	8	
    Addr: 8	7	
    Addr: 9	6	
    Addr: 10	5	
    Addr: 11	4	
    Addr: 12	3	
    Addr: 13	2	
    Addr: 14	1	
    Addr: 15	0
    	
    check again
    Addr: 0	15	
    Addr: 1	14	
    Addr: 2	13	
    Addr: 3	12	
    Addr: 4	11	
    Addr: 5	10	
    Addr: 6	9	
    Addr: 7	8	
    Addr: 8	7	
    Addr: 9	6	
    Addr: 10	5	
    Addr: 11	4	
    Addr: 12	3	
    Addr: 13	2	
    Addr: 14	1	
    Addr: 15	0
    

    I still dont known what happened. When i rewrite data at offset 0, then first read bring me wrong number, but in the 2nd, it became right number. hix, could anybody explain that for me? Thanks!
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    i believe your error is that there should be a read wait state. just as an fyi, there is no reason to use the read signal, you could have just always assigned readdata to the ram[address].

    --- Quote End ---

    thank dwesterg,

    did u mean i would bypass the read signal, just simple assign data like:

    
    begin
    readdata <= RAM_CONTENT(conv_integer(address));
    process(...) -- for writing data
    ...
    end process;
    end behav;
    

    i will do a try :) and report in this thread, thanks again :x
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    thank dwesterg,

    did u mean i would bypass the read signal, just simple assign data like:

    
    begin
    readdata <= RAM_CONTENT(conv_integer(address));
    process(...) -- for writing data
    ...
    end process;
    end behav;
    

    i will do a try :) and report in this thread, thanks again :x

    --- Quote End ---

    THANK dwesterg SO MUCH!!!

    It returned right number. Why did i think like you :| I think address will be avaible before read signal is pulled up, as waveform in sopc. Oh, sometime, A small mistake is too hard to recognize.

    Thank dwesterg many, many times :x
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    the availability of signals is dependant on the setup and wait settings in your hw.tcl file. having address available early is entirely plausible if you specify the behaviour in your hw.tcl file.

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

    I would recommend making your slave have 32 data bits - even if the top 24 are ignored on writes and return 0 on reads.

    An 8 bit slave will always see 4 bus cycles when the NIOS doe a byte access to it.

    On writes three of theses will have the byte enable de-asserted.

    However the NIOS always asserts all 4 byte enables on reads - so you'll see 4 separate read cycles for each cpu byte read.