Altera_Forum
Honored Contributor
12 years agocustom peripheral memory-mapping issue
Hello everyone.
It's my first approach with addressing custom peripheral in a nios II based system, so I started developing a simple custom hardware that reads a 32 bit input and gives back "input+1". All seemed to work fine, in the C code I used IOWR_32DIRECT(base, 0, input) and IORD_32DIRECT(base, 0) to query the custom logic; I gave 8 as input and I got 9 as output. So I did the next step :) , writing another peripheral which needs a 64-bit transfer. I know Nios only supports 32-bit transfers, so i chunked the single tranfer into two 32-bit ones, using an address bit to distinguish between the two half-words. here is the vhdl code (obtained from the first that worked, with some modifications) , I simulated it with modelsim and seems to work fine:library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
-- define interface
entity des_wrapper64 is
port (
-- inputs:
address : IN STD_LOGIC;
chipselect : IN STD_LOGIC;
clk : IN STD_LOGIC;
reset_n : IN STD_LOGIC;
write_n : IN STD_LOGIC;
read_n : IN STD_LOGIC;
writedata : IN UNSIGNED(0 to 31);
-- outputs:
readdata : OUT UNSIGNED(0 to 31)
--d: OUT UNSIGNED(0 to 63)--
);
end entity;
architecture arch of des_wrapper64 is
begin
process(clk,reset_n)
variable data:UNSIGNED(0 to 63);
begin
if reset_n='0' then
--nop
elsif clk='1' and clk'event then
-- writing
if chipselect='1' and write_n='0' then
case address is
when '0' => data(32 to 63) :=writedata(0 to 31); --write lsb
when '1' => data(0 to 31) :=writedata(0 to 31); --write msb
when others => readdata<=x"FFFFFFFF";
end case;
end if;
-- reading (must send input + 1)
if chipselect='1' and read_n='0' then
data:=data +1;
case address is
when '0' => readdata(0 to 31)<= data(0 to 31); --read lsb
when '1' => readdata(0 to 31)<= data(32 to 63); --read msb
when others => readdata<=x"FFFFFFFF";
end case;
end if;
end if;
--d<=data;
end process;
end arch;
here is the C code: //base address (Custom Peripheral)# define CP_ADDR (0x01001030)
int main()
{
unsigned int data2writelsb=0xAAAAAAAA; // two halves of input
unsigned int data2writemsb=0xBBBBBBBB;
unsigned int data2readlsb=3; // two halves of output initialized to some value
unsigned int data2readmsb=3;
IOWR_32DIRECT(CP_ADDR,0,data2writelsb);
IOWR_32DIRECT(CP_ADDR,1,data2writemsb);
data2readlsb=IORD_32DIRECT(CP_ADDR,0);
data2readmsb=IORD_32DIRECT(CP_ADDR,1);
return 0;
}
The problem is I always have: data2readlsb=0x00000000; data2readmsb=0x00000000; i initialized the two data2read halves to 3 to be sure that IORD works (initializing them to 0 i couldn't see if something is actually read or the IORD doesn't work and the zeroes are simply the initialization value unmodified). I suppose IORD works because modifying randomly the offset I can get values other than zero, so it is actually reading somewhere in the address space! I really don't know how to fix this problem...can anyone help me?:confused: Thanks Anna