C Header files for User Design Logic in the Nios.

T

Ted

Guest
Hello Guys,

I am using the SOPC builder to design a simple system that integrates
a couple of UARTS, a soft processor and a VHDL blackbox (Connected
internally in user design logic). I export a 8-bit wide signal which
are connected to LEDs on-board from the blackbox. I am using the Nios
Development Board Pro Edition. My VHDL code is as follows:
Libraries blah blah...
entity count is
port(
clk: in std_logic;
write_con: in std_logic;
chipsel: in std_logic;
write_data: in std_logic_vector(1 downto 0);
export
dataout: out std_logic_vector(7 downto 0));
end count;

architecture RTL of count is

signal counter: std_logic_vector(7 downto 0);
signal write_data_d: std_logic_vector(1 downto 0);
signal resetn_d: std_logic;
signal control: std_logic;

begin

control<= write_con and chipsel;

count_proc: process(clk, control, counter, write_data)
begin
if clk'event and clk='1' then
if ((write_data="00") and control='1') then
counter<=(OTHERS=>'1');
elsif ((write_data="01") and control='1') then
counter<=counter+1;
elsif ((write_data="10") and control='1') then
counter<="00001111";
else
counter<= "01010000";
end if;
end if;
end process count_proc;

dataout<= counter;

end RTL;
////////////////////////////////////////////////////////////////////////////

My C code in the src directory is as follows:

#define point1 *((int *)(na_user_logic_altera_avalon_pwm_0_base))

void main()
{
while(1)
{
point1=1;
}
}

I am assuming that I am writing directly to the write_data port (In
VHDL) so I should be expecting a dim LED for the MSB and a bright one
at the LSB. However, all I get is 2 bright LEDs (else condition). I
checked the manuals but there wasn't any explicit instructions on how
to use the header files for user design logic. Any direct help will be
greatly appreaciated. Any reference to material will also be welcomed
too. Cheerio!

Ted
 
etd606@hotmail.com (Ted) wrote in message news:<58811c5e.0406151809.2e18b0dc@posting.google.com>...
My C code in the src directory is as follows:

#define point1 *((int *)(na_user_logic_altera_avalon_pwm_0_base))

void main()
{
while(1)
{
point1=1;
}
}

I am assuming that I am writing directly to the write_data port (In
VHDL) so I should be expecting a dim LED for the MSB and a bright one
at the LSB. However, all I get is 2 bright LEDs (else condition). I
checked the manuals but there wasn't any explicit instructions on how
to use the header files for user design logic. Any direct help will be
greatly appreaciated. Any reference to material will also be welcomed
too. Cheerio!

Ted
Hi Ted,

A couple of potential issues:

1. point1 is declared a pointer, when you assign it something "point1
= something", what you're doing is changing the address it points to.
Use * to dereference the pointer (standard C code stuff)... so the
first thing I'd do is change point1 = 1; to *point1 = 1;

2. If you're using Nios I with a data cache, you should declare point1
to be "volatile int*(blah)"... this isn't critical as the Nios I data
cache was write-through, but it is good practice and will prevent
cache-coherency issues down the road. If you're using Nios II (without
the legacy SDK) we have some I/O macros which direct the CPU to bypass
the cache.

Obviously your C code above is pretty simple, but in a more complex
situation its advisable to use the debugger to see what is happening
(at least with the pointers & variables declared in your C code)....
the debugger would probably catch, for example, that the pointer's
address was being written, rather than the actual address off in
memory.

Another general suggestion: when designing a peripheral as you are,
consider (at least for bring-up purposes), include registers that
allow you to read back the data... some HDL pseudo code would look
like this (I am a Verilog guy :) --

at posedge clock
handle reset
if (chipselect and write)
case addressbus:
00:
reg0 = writedata
01:
reg1 = writedata
...
...
if (chipselect and read)
case addressbus:
00:
readdata = reg0
01:
readdata = reg1


....and so forth. You'll burn some logic in the registers, but again,
this is a fine idea for prototyping as it allows you to debug your
hardware straight from the C code (then you can dereference the
pointer and call printf() to display what is going on in your
peripheral), which is kind of nice depending on what you're used to.
Once you're up and running and want to shave off LEs, remove the
registers and read logic as appropriate. This is just one idea, of
course.. Additional debug options include using signal tap and
triggering on the chipselect to your peripheral, or simulating in
ModelSim (see the app note on simulating Nios systems) -- you can have
an RTL view of what happens when your C code executes.

Hope this helps.

Jesse Kempa
Altera Corp.
jkempa at altera dot com
 
Another general suggestion: when designing a peripheral as you are,
consider (at least for bring-up purposes), include registers that
allow you to read back the data...
Good suggestion. Often you can do it with almost no additional hardware.

Sometimes a CSR type register has enough bits for this purpose. You
just have to readback the C bits while reading the S bits. If there
are any unused bits, you can make them R/W but not connected
to anything (else).

Sometimes you can make a write only data register read/write with
the read path being used only for this purpose.

--
The suespammers.org mail server is located in California. So are all my
other mailboxes. Please do not send unsolicited bulk e-mail or unsolicited
commercial e-mail to my suespammers.org address or any of my other addresses.
These are my opinions, not necessarily my employer's. I hate spam.
 
Another question: Referring to
http://www.altera.com/literature/lit-sop.jsp where the PWM is used as
an example for a Verilog Blackbox, The lowest-level of the C headers
contains the following:

#ifndef __ALTERA_AVALON_PWM00_H
#define __ALTERA_AVALON_PWM00_H

#define ALTERA_AVALON_PWM_CLOCK_DIVIDER(base_addr)
(ALTERA_AVALON_PWM_TYPE (base_addr + 0x0 ))
#define ALTERA_AVALON_PWM_CLOCK_DIVIDER_MSK (0xFFFFFFFF)
#define ALTERA_AVALON_PWM_CLOCK_DIVIDER_OFST (0)

#define ALTERA_AVALON_PWM_DUTY_CYCLE(base_addr)
(ALTERA_AVALON_PWM_TYPE (base_addr + 0x4 ))
#define ALTERA_AVALON_PWM_DUTY_CYCLE_MSK (0xFFFFFFFF)
#define ALTERA_AVALON_PWM_DUTY_CYCLE_OFST (0)

#define ALTERA_AVALON_PWM_ENABLE(base_addr) (ALTERA_AVALON_PWM_TYPE
(base_addr + 0x8 ))
#define ALTERA_AVALON_PWM_ENABLE_MSK (0x1)
#define ALTERA_AVALON_PWM_ENABLE_OFST (0)


#endif /* __ALTERA_AVALON_PWM00_H */

What exactly does ALTERA_AVALON_PWM_TYPE do? What does
ALTERA_AVALON_PWM_ENABLE_MSK and ALTERA_AVALON_PWM_ENABLE_OFST mean?
If the former is a subroutine, I can't seem to find it in any of the
files.

In the exacalibur.h file, there is a line:

#define na_user_logic_altera_avalon_pwm_0 ((void *)
0x00020020) // user_logic_altera_avalon_pwm

Since the base address is always pointing to void, then can I say that
ALTERA_AVALON_PWM_CLOCK_DIVIDER always has the input 0?

What exactly is np_usersocket and why is it set to point to void?
 
Another question: Referring to
http://www.altera.com/literature/lit-sop.jsp where the PWM is used as
an example for a Verilog Blackbox, The lowest-level of the C headers
contains the following:

#ifndef __ALTERA_AVALON_PWM00_H
#define __ALTERA_AVALON_PWM00_H

#define ALTERA_AVALON_PWM_CLOCK_DIVIDER(base_addr)
(ALTERA_AVALON_PWM_TYPE (base_addr + 0x0 ))
#define ALTERA_AVALON_PWM_CLOCK_DIVIDER_MSK (0xFFFFFFFF)
#define ALTERA_AVALON_PWM_CLOCK_DIVIDER_OFST (0)

#define ALTERA_AVALON_PWM_DUTY_CYCLE(base_addr)
(ALTERA_AVALON_PWM_TYPE (base_addr + 0x4 ))
#define ALTERA_AVALON_PWM_DUTY_CYCLE_MSK (0xFFFFFFFF)
#define ALTERA_AVALON_PWM_DUTY_CYCLE_OFST (0)

#define ALTERA_AVALON_PWM_ENABLE(base_addr) (ALTERA_AVALON_PWM_TYPE
(base_addr + 0x8 ))
#define ALTERA_AVALON_PWM_ENABLE_MSK (0x1)
#define ALTERA_AVALON_PWM_ENABLE_OFST (0)


#endif /* __ALTERA_AVALON_PWM00_H */

What exactly does ALTERA_AVALON_PWM_TYPE do? What does
ALTERA_AVALON_PWM_ENABLE_MSK and ALTERA_AVALON_PWM_ENABLE_OFST mean?
If the former is a subroutine, I can't seem to find it in any of the
files.

In the exacalibur.h file, there is a line:

#define na_user_logic_altera_avalon_pwm_0 ((void *)
0x00020020) // user_logic_altera_avalon_pwm

Since the base address is always pointing to void, then can I say that
ALTERA_AVALON_PWM_CLOCK_DIVIDER always has the input 0?

What exactly is np_usersocket and why is it set to point to void?
 
Hello,

A more direct question, for the above VHDL code, how do I access the
write_data port in C i.e. in cmd mode? I tried changing the contents
of the base address of the VHDL blackbox but the else condition ALWAYS
occurs. In my excalibur.h file, I get the blackbox base address as
0x00020020. No end address is specified.

Is it required to have a register file? Must I include the
byte_enable, reset signals to get it to work? When I do something like
i=*point1, then it goes into the else condition. Probably something to
do with exception handling.

Is it a problem with the VHDL coding (Checked seperately in ModelSim)
or something to do with the C?

Perplexed...
 
Ted,
I think you have a bug in your VHDL. The reason you always see two
bright LEDs is that on every clock cycle _except_ the one in which you
access your peripheral, your else clause (counter<= "01010000";) is
active.

I think you intended your count_proc to be more like this (caveat: I'm
not fluent in VHDL):

count_proc: process(clk, control, counter, write_data)
begin
if clk'event and clk='1' and control='1' then
if ((write_data="00")) then
counter<=(OTHERS=>'1');
elsif ((write_data="01")) then
counter<=counter+1;
elsif ((write_data="10")) then
counter<="00001111";
else
counter<= "01010000";
end if;
end if;
end process count_proc;

By the way, your point1 #define should work, but you really should
make it a volatile pointer (as another poster said). Also, I'm more
used to seeing something like this:

#define point1 ((volatile int
*)(na_user_logic_altera_avalon_pwm_0_base))

and then to access the peripheral,

*point1 = 1;

Hope this helps.

etd606@hotmail.com (Ted) wrote in message news:<58811c5e.0406151809.2e18b0dc@posting.google.com>...
Hello Guys,

I am using the SOPC builder to design a simple system that integrates
a couple of UARTS, a soft processor and a VHDL blackbox (Connected
internally in user design logic). I export a 8-bit wide signal which
are connected to LEDs on-board from the blackbox. I am using the Nios
Development Board Pro Edition. My VHDL code is as follows:
Libraries blah blah...
entity count is
port(
clk: in std_logic;
write_con: in std_logic;
chipsel: in std_logic;
write_data: in std_logic_vector(1 downto 0);
export
dataout: out std_logic_vector(7 downto 0));
end count;

architecture RTL of count is

signal counter: std_logic_vector(7 downto 0);
signal write_data_d: std_logic_vector(1 downto 0);
signal resetn_d: std_logic;
signal control: std_logic;

begin

control<= write_con and chipsel;

count_proc: process(clk, control, counter, write_data)
begin
if clk'event and clk='1' then
if ((write_data="00") and control='1') then
counter<=(OTHERS=>'1');
elsif ((write_data="01") and control='1') then
counter<=counter+1;
elsif ((write_data="10") and control='1') then
counter<="00001111";
else
counter<= "01010000";
end if;
end if;
end process count_proc;

dataout<= counter;

end RTL;
////////////////////////////////////////////////////////////////////////////

My C code in the src directory is as follows:

#define point1 *((int *)(na_user_logic_altera_avalon_pwm_0_base))

void main()
{
while(1)
{
point1=1;
}
}

I am assuming that I am writing directly to the write_data port (In
VHDL) so I should be expecting a dim LED for the MSB and a bright one
at the LSB. However, all I get is 2 bright LEDs (else condition). I
checked the manuals but there wasn't any explicit instructions on how
to use the header files for user design logic. Any direct help will be
greatly appreaciated. Any reference to material will also be welcomed
too. Cheerio!

Ted
 
Hi Aaron,

Thanks for your reply. Through a process of trial and error, I managed
to find the write port at base_address+3. I was just wondering if the
compiler treats data-bitwidth as 32 bits and therefore assign the LSB
at base_address+3. Since relevant data is only 8-bits wide, the upper
bits would be always 0.

But SOPC builder is supposed to have a dynamic bitwidth right so this
shouldn't happen. Like u said, the *point1=1 should work (*point4=1
works in this instance) but it doesn't. Might it be something to do
with the settings i.e. how the compiler or device and pins settings
are made etc. affecting the optimisation process or affecting how data
is communicated to the device?

My design works but it is at best erratic. I am inserting a multiplier
into the blackbox now with 32-bits and it is not working.

Ed
 
Ted,
void* just means a generic pointer. In your code, you're casting it
to int*, which should work fine. Since your component has no address
input, it spans only a single int* location. I'm not sure I
understand what you mean when you say you found the write port at
base_address+3.

Just to reiterate, I think you have a bug in your HDL which makes it
look like you aren't able to access your hardware at the device base
address.

etd606@hotmail.com (Ted) wrote in message news:<58811c5e.0406230313.53b01cb3@posting.google.com>...
Hi Aaron,

Thanks for your reply. Through a process of trial and error, I managed
to find the write port at base_address+3. I was just wondering if the
compiler treats data-bitwidth as 32 bits and therefore assign the LSB
at base_address+3. Since relevant data is only 8-bits wide, the upper
bits would be always 0.

But SOPC builder is supposed to have a dynamic bitwidth right so this
shouldn't happen. Like u said, the *point1=1 should work (*point4=1
works in this instance) but it doesn't. Might it be something to do
with the settings i.e. how the compiler or device and pins settings
are made etc. affecting the optimisation process or affecting how data
is communicated to the device?

My design works but it is at best erratic. I am inserting a multiplier
into the blackbox now with 32-bits and it is not working.

Ed
 

Welcome to EDABoard.com

Sponsor

Back
Top