Nios® V/II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® V/II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++
12589 Discussions

Could not read 8 bit data from custom ram

Altera_Forum
Honored Contributor II
1,056 Views

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^^
0 Kudos
6 Replies
Altera_Forum
Honored Contributor II
314 Views

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].

0 Kudos
Altera_Forum
Honored Contributor II
314 Views

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!
0 Kudos
Altera_Forum
Honored Contributor II
314 Views

 

--- 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
0 Kudos
Altera_Forum
Honored Contributor II
314 Views

 

--- 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
0 Kudos
Altera_Forum
Honored Contributor II
314 Views

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.

0 Kudos
Altera_Forum
Honored Contributor II
314 Views

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.
0 Kudos
Reply