FPGA Intellectual Property
PCI Express*, Networking and Connectivity, Memory Interfaces, DSP IP, and Video IP
6356 Discussions

problem of adding custom component in SOPC

Altera_Forum
Honored Contributor II
1,711 Views

Hi~~ 

 

My SOPC setting have processor,PIO,SDRAM,FLASH..so on. 

 

I want to add a custom component which is a simple counter IP. 

(behavior: when I push the switch ,then the counter will plus one ) 

 

The following code is the counter IP. 

 

 

--- Quote Start ---  

 

output reg [ 7: 0] readdata; 

input clk; 

input [ 7: 0] in_port; 

reg [7:0] out; 

 

always @ ( clk or in_port) 

begin 

 

if ( in_port[7] == 0 ) 

readdata = 0; 

else if ( in_port[6] == 1 ) 

readdata = out + 8'b00000001; 

else 

readdata = out; 

out = readdata; 

 

end  

 

--- Quote End ---  

 

the IP setting is the following 

 

 

--- Quote Start ---  

 

counter count ( 

.readdata(readdata), // avalon_slave.readdata 

.clk (clk), // clock.clk 

.in_port (in_port) // conduit_end.export 

); 

 

 

--- Quote End ---  

 

 

 

And the follwing code is C langauge in NIOS IDE 

 

 

--- Quote Start ---  

 

while(1){ 

count =IORD_ALTERA_AVALON_PIO_DATA(COUNTER_BASE); 

printf("count %d \n",count); 

}  

 

--- Quote End ---  

 

 

The above counter IP that I simulation with modelsim , and I can get the correct result. 

 

But when I download the .sof file to the DE0 board, I can't get the same result which simulation with modelsim. 

 

I use a lot of time to resolve this bug. 

 

 

Then I find the reg(the red color in first quote) that can't hole the last value. 

Therefore, I can't get the correct result. 

 

 

Normally when I declare the veriable type is reg, and this variable will keep the last value. 

But I run in NIOS, I don't have this feature. 

 

 

 

Counld you give me some suggestion 

 

Thank you very much. 

http://www.alteraforum.com/forum//proweb/misc/progress.gif
0 Kudos
6 Replies
Altera_Forum
Honored Contributor II
272 Views

Replace always @ ( clk or in_port) 

with always @ (posedge clk) 

You may also need to change further, if you want the counter to increment only once when you push the switch: now it keeps on increasing at the clk rate as long as you keep the switch pressed.
0 Kudos
Altera_Forum
Honored Contributor II
272 Views

 

--- Quote Start ---  

Replace always @ ( clk or in_port) 

with always @ (posedge clk) 

You may also need to change further, if you want the counter to increment only once when you push the switch: now it keeps on increasing at the clk rate as long as you keep the switch pressed. 

--- Quote End ---  

 

 

 

Thank you for your reply. 

 

Sorry, I try your suggestion,but it get the incorrect result. 

I don't know whether I misunderstanding your suggestion. 

 

I replace always @ ( clk or in_port)  

with always @ (posedge clk) 

 

In the normal case, when I press the switch, the counter will be increased once. 

However the experimental result shows the counter's number is a random number. 

 

 

The following is my experimental setting 

 

The initial the setting in_port = 8'b0000_0000 

,then the count shows number in NIOSII console with NIOS IDE  

 

 

--- Quote Start ---  

 

count is 0 

 

--- Quote End ---  

 

 

next, I press the switch, I think the in_port = 8'b1000_0000  

,then the count shows number in NIOSII console with NIOS IDE  

 

 

--- Quote Start ---  

 

count is 208 (I want the count is 0) 

 

--- Quote End ---  

 

 

 

next, I keep on the switch pressed, the in_port = 8'b1000_0000  

,then the count shows number in NIOSII console with NIOS IDE  

 

--- Quote Start ---  

 

count is 30 (I want the count is 0) 

 

--- Quote End ---  

 

 

 

next, I keep on the switch pressed, the in_port = 8'b1000_0000  

,then the count shows number in NIOSII console with NIOS IDE  

 

--- Quote Start ---  

 

count is 93 (I want the count is 0) 

 

--- Quote End ---  

 

 

next, I press another switch, the in_port = 8'b1000_0010 

,then the count shows number in NIOSII console with NIOS IDE  

 

 

--- Quote Start ---  

 

count is 93 (I want the count is 1) 

 

--- Quote End ---  

 

 

next, I keep on switch pressed , the in_port = 8'b1000_0010 

,then the count shows number in NIOSII console with NIOS IDE  

 

 

--- Quote Start ---  

 

count is 93 (I want the count is 1) 

 

--- Quote End ---  

 

 

 

next, I release the switch, the in_port = 8'b1000_0000 (It will start to get the random number) 

,then the count shows number in NIOSII console with NIOS IDE  

 

 

--- Quote Start ---  

 

count is 43 (I want the count is 1) 

 

--- Quote End ---  

 

 

next, I keep on the original switch pressed, the in_port = 8'b1000_0000 

,then the count shows number in NIOSII console with NIOS IDE  

 

 

--- Quote Start ---  

 

count is 58 (I want the count is 1) 

 

--- Quote End ---  

 

 

 

next, I press another switch, the in_port = 8'b1000_0010 

,then the count shows number in NIOSII console with NIOS IDE  

 

 

--- Quote Start ---  

 

count is 58 (I want the count is 2) 

 

--- Quote End ---  

 

 

 

Therefore I am almost crazy. 

I don't know why I can get this result. 

 

 

I replace always @ ( clk or in_port)  

with always @ (in_port) 

 

Let the command is executed in "always block" when the in_port changed.  

But the result is the same totally.
0 Kudos
Altera_Forum
Honored Contributor II
272 Views

I think there are a couple of flaws in your code 

 

Issue# 1: 

As I said before, your code increments the counter on each clock pos edge whenever bit6 of input port is asserted.  

Now, what's clk frequency? If this is in the kHz or MHz range you will indeed get random numbers from the counter: I don't think you could keep the switch pressed for a single clock period! You'd rather get thousands of counts for every push, even if you are very very fast. 

 

Issue# 2: 

IMHO, using out and readdata registers in that way is not good. 

Replace = with <= for register assignments: e.g. out <= readdata; 

See http://en.wikipedia.org/wiki/verilog for explanation of difference. 

I guess in this 2 registers case, the = assignment is logically and syntactically correct but is not exactly synthesizable: that's why the simulation works but the real system doesn't. 

Apart this, I'd simply remove the 'out' register; readdata is enough. 

 

 

Example: 

(last is used to keep trace of previous pushbutton status and trigger the count only once) 

 

output reg [ 7: 0] readdata; 

input clk; 

input [ 7: 0] in_port; 

reg last; 

 

always @ ( posedge clk ) 

begin 

if ( in_port[7] == 0 ) 

readdata <= 8'b0; 

else if ( in_port[6] and ~last) // count only if switch has been pushed right now 

readdata <= readdata + 8'b1; 

// no need for else statement; everything is unchanged 

 

last <= in_port[6]; 

end
0 Kudos
Altera_Forum
Honored Contributor II
272 Views

 

--- Quote Start ---  

I think there are a couple of flaws in your code 

 

Issue# 1: 

As I said before, your code increments the counter on each clock pos edge whenever bit6 of input port is asserted.  

Now, what's clk frequency? If this is in the kHz or MHz range you will indeed get random numbers from the counter: I don't think you could keep the switch pressed for a single clock period! You'd rather get thousands of counts for every push, even if you are very very fast. 

 

Issue# 2: 

IMHO, using out and readdata registers in that way is not good. 

Replace = with <= for register assignments: e.g. out <= readdata; 

See http://en.wikipedia.org/wiki/verilog for explanation of difference. 

I guess in this 2 registers case, the = assignment is logically and syntactically correct but is not exactly synthesizable: that's why the simulation works but the real system doesn't. 

Apart this, I'd simply remove the 'out' register; readdata is enough. 

 

 

Example: 

(last is used to keep trace of previous pushbutton status and trigger the count only once) 

 

output reg [ 7: 0] readdata; 

input clk; 

input [ 7: 0] in_port; 

reg last; 

 

always @ ( posedge clk ) 

begin 

if ( in_port[7] == 0 ) 

readdata <= 8'b0; 

else if ( in_port[6] and ~last) // count only if switch has been pushed right now 

readdata <= readdata + 8'b1; 

// no need for else statement; everything is unchanged 

 

last <= in_port[6]; 

end 

--- Quote End ---  

 

 

 

Thank you for your help very much. 

 

It work successfully. 

 

 

Excuse me. May I ask another question? 

It is not related with the above problem. 

 

The following is the problem description. 

 

Now, I have a DE0 board, uClinux kernel, NIOSII processor, and u-boot. 

 

The version of uClinux kernel is uClinux-dist-20110603. 

 

The NIOS II version is 10.1 and quartus II version is 10.1. 

 

The u-boot version is u-boot-2011.06. 

 

I want to download the .sof file to DE0 board and then boot kernel. 

 

 

I have the three way to achieve the goal. I fail in one of them which is used the "bootm" command. 

 

First, I don't use the u-boot to boot kernel. 

Directly download the kernel to the memory and then boot kernel. 

(I use the compressed image kernel which is not .gz file but through "misc.c" ) 

 

Second, I use the u-boot's "go"command to boot kernel.  

Directly download the kernel to flash by using "flash programmer tool" of NIOS IDE. And then I copy the image kernel from flash through "cp.b" command. Finally, I key in "go" command booting kernel.(I use the uncompressed image kernel which is not through "misc.c") 

 

 

--- Quote Start ---  

 

==>cp.b 02400000 01800000 400000 

==>go 01800000 

 

--- Quote End ---  

 

 

 

Third, I use the u-boot's "bootm" command to boot kernel. It failed . 

(I use the compressed image kernel which is not .gz file but through "misc.c") 

 

1. I create the uImage through the "mkimage" tool. 

 

The following is the settings 

 

 

--- Quote Start ---  

 

mkimage -n 'linux- 2.6' -A nios2 -O linux -T kernel -C none -a 0x01800000 -e 0x01800040 -d zImage uImage  

 

--- Quote End ---  

 

 

The following is board information 

 

--- Quote Start ---  

 

==> bdinfo 

mem start = 0x01800000 

mem size = 0x00800000 

flash start = 0x82400000 

flash size = 0x00400000 

flash offset= 0x00000019 

ethaddr = (not set) 

ip_addr = 0.0.0.0 

baudrate = 1 bps  

 

--- Quote End ---  

 

 

2. bootm command 

 

 

--- Quote Start ---  

 

==>cp.b 02400000 01800000 400000 

==>bootm 01800000 - 

 

# # Booting kernel from Legacy Image at 01800000 ... 

Image Name: linux- 2.6 

Image Type: NIOS II Linux Kernel Image (uncompressed) 

Data Size: 1457595 Bytes = 1.4 MiB 

Load Address: 01800000 

Entry Point: 01800040 

Verifying Checksum ... OK 

XIP Kernel Image ... 

OK <-----------------------------(stuck here.......) 

 

--- Quote End ---  

 

 

Could you give me some suggestion. 

Thank you very much. 

 

ps.I know the another address setting which will move the kernel in bootm command. I also try it, but still fail.
0 Kudos
Altera_Forum
Honored Contributor II
272 Views

I'm afraid I neither have a DE0 board nor I ever used Linux kernel, then I can't help you on this point. 

You'd better start a specific thread in the Linux or in the Development Kit section of the forum. But before this, I recommend you search the forum an answer: this could be a common issue.
0 Kudos
Altera_Forum
Honored Contributor II
272 Views

That's fine. 

 

Thank you for your reply.
0 Kudos
Reply