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++
12600 Discussions

Sending coefficients of degree 1000 from UART to custom logic with Nios II and SOPC.

Altera_Forum
Honored Contributor II
1,020 Views

Hi, I'm pretty new to all this Nios II development and would like to ask advice on the best solution to my project. 

 

After receiving coefficients from an UART I have a 2000(GF3 coefficients) char table(within nios ii) that I would like to send to my custom logic input(which is of type std_logic_vector(1999 downto 0) ) and back again after calculating the new coefficients. To better illustrate what I mean I attached a crude picture. 

 

From what I've read there are 2 options to do this: 

1) Somehow transfer the coefficients from the nios ii block in quartus to my vhdl custom logic, but I can't think of a way to do this with built in IP components(PIO blocks have only max 32 bit length outputs), which draws me to the conclusion that I would need to create a new custom component. Any ideas how to make an component like this as simple as possible? What would I have as inputs and how would I output it(condiut interface)? Generally my plan was to have something like an PIO block except with a 2000 max width output and another 200 width PIO as input from the custom logic after calculating. 

 

2) Use my custom VHDL logic to create a custom component and use it INSIDE the sopc builder. The problem here is I have no idea what interfaces to use to communicate with the logic, ideally I would like to have an input(std_logic_vector(1999 downto 0) ) and output(the same as input), but from what I tried to do by myself I would also need a clock input(?). Can the nios ii even convert a char table to a std_logic_vector? 

 

Because of my low knowledge there are probably other good solutions that I don't know about, I'll welcome any input/help you can provide. Thanks for the help. 

 

Regards, 

Fred
0 Kudos
7 Replies
Altera_Forum
Honored Contributor II
312 Views

Does the logic actually need all 2000 coefficients during the same clock? How fast does the calculation need to take? What calculation are the coefficients used for, eg., a digital filter (if GF3 is supposed to mean something, post a link to details)? 

 

These questions are important as they determine whether your logic can be serialized or has to be implemented in parallel. 

 

Given that you are transferring data via a UART, I suspect you do not have a requirement for high speed. 

 

In either case, you probably want to use dual-ported RAM. The NIOS II processor would write to one side of the RAM, and the logic would read from the other side. 

 

Cheers, 

Dave
0 Kudos
Altera_Forum
Honored Contributor II
312 Views

You are correct I do not need to read them in one clock cycle, the only thing I need is to be able to read the time of calculating the coefficients, the time of sending and reaveiving them doesn't matter. By GF3 I only mean that the coefficients need 3 values(so 00 01 10) hence for a polynomial of degree of 1000 I need 2000 bits to represent it.  

 

Is there any sort of tutorial on how to use the dual-ported RAM? Also how will my logic know that the data is ready to take? And how will the nios ii know that the calculating is over? 

 

Thanks for the help again, it was a month since my last post:D 

 

Regards, 

Fred
0 Kudos
Altera_Forum
Honored Contributor II
312 Views

 

--- Quote Start ---  

the only thing I need is to be able to read the time of calculating the coefficients 

 

--- Quote End ---  

 

You're providing the coefficients. I assume you mean the calculation time, where the calculation uses the coefficients. However, this time will be static - it'll be however many clocks you design the hardware to take. 

 

 

--- Quote Start ---  

 

By GF3 I only mean that the coefficients need 3 values(so 00 01 10) hence for a polynomial of degree of 1000 I need 2000 bits to represent it.  

 

--- Quote End ---  

 

So using 32-bit wide RAM, you can transfer 16 2-bit values to ram on every write, so your 2000-bits require 2000/32 = 62.5 x 32-bit locations. 

 

 

--- Quote Start ---  

 

Is there any sort of tutorial on how to use the dual-ported RAM? 

 

--- Quote End ---  

 

There's a MegaFunction users guide. Just create an instance in Modelsim and simulate it. The RAM operates synchronously; a write occurs when you assert the address data and write-enable signal, a read is a little trickier in that data is output after a pipeline delay. Simulating the RAM will make this clearer. 

 

 

--- Quote Start ---  

 

Also how will my logic know that the data is ready to take? And how will the nios ii know that the calculating is over? 

 

--- Quote End ---  

 

In addition to the RAM, you'll want a control FSM. The inputs/outputs to the FSM will be at least 'enable' and 'done'. Once you've got that working, you might decide that the number of coefficients is variable, so add a register for how many bits are in the RAM, etc. Start off with 'enable' and 'done'. The 'done' signal could be implemented to generate an interrupt to the NIOS II processor. 

 

Once you get the coefficient RAM and control FSM working, you can wrap it into a Avalon-MM slave component; one slave for the RAM logic, and another for the control bits. The control bits could just use a PIO component, but once you've figured out how to get one Avalon-MM slave component working, you'll find its easier just to create your own slave blocks. 

 

Cheers, 

Dave
0 Kudos
Altera_Forum
Honored Contributor II
312 Views

Ok so unfourtunatly I got a bit lost again. 

 

The plan is to instance the RAM in the SOPC builder or as a megafunction in quartus? Currently I'm trying to understand how the second option would work, if I understood correctly I would implement a Dual-port ram(from the altsyncram megafunction) and from the side of the A-port(from the SOPC system) I would have a 32 bit bus and from the B-port(FSM) I would have a 2000 bit bus. Since I'm new to this I also don't understand how to serialize the output from the SOPC,does the 2000 char table in the nios ii automatically serialize if there is only 32 bits output aviable, or do I have to manually divide the input 2000 char coefficients into 32 bit words diffrent with RAM adresses(so ~62,5 different adresses). Finally, how to connect the SOPC system with the RAM in the first place(PIO?).I attached a simple image to describe how I understood the idea correctly, thanks for any advice you can give. 

 

Fred
0 Kudos
Altera_Forum
Honored Contributor II
312 Views

 

--- Quote Start ---  

Ok so unfourtunatly I got a bit lost again. 

 

--- Quote End ---  

 

 

That is understandable, as you are new to this.  

 

To implement your system, you need to understand several aspects of the tools. Rather than trying to understand them all at once, you need to take it step-by-step. 

 

Step 1. Understand how Altera wants you to create systems. Go through this tutorial to understand this step. 

 

http://www.alterawiki.com/wiki/using_the_usb-blaster_as_an_sopc/qsys_avalon-mm_master_tutorial 

 

Step 2. Learn how to use Modelsim to simulate a dual-ported RAM component (as created by the MegaFunction Wizard). 

 

Your testbench would write coefficients to one side of the RAM, and assert a 'go' signal to your control FSM. 

 

Your control FSM would wait for the 'go' signal, read the coefficients from the RAM, perform its processing, and then assert the 'done' signal. 

 

Your testbench would wait for the 'done' signal, and then check the result - whatever that is - perhaps your control FSM can write the result(s) back to the dual ported RAM in another area. 

 

Step 3. Learn how to create an Avalon-MM slave interface to a single-ported RAM, and how to describe this in an _hw.tcl file. From this experience, you will understand how to create an Avalon-MM slave interface to your component. We can come back to this once you have the other steps working. Its actually quite easy. However, I won't just 'give' you the code, you have to try and figure it out first (otherwise you won't really learn how it works). 

 

 

--- Quote Start ---  

 

The plan is to instance the RAM in the SOPC builder or as a megafunction in quartus? 

 

--- Quote End ---  

 

You have to create a component that includes a RAM (which can be created using the MegaFunction Wizard), but then you also have to create a _hw.tcl file to describe your new component as a Qsys or SOPC builder component. 

 

 

--- Quote Start ---  

 

if I understood correctly I would implement a Dual-port ram(from the altsyncram megafunction) and from the side of the A-port(from the SOPC system) I would have a 32 bit bus and from the B-port(FSM) I would have a 2000 bit bus. 

 

--- Quote End ---  

 

You already commented that your logic does not need all 2000-bits during the same clock cycle. If the RAM output is 32-bits, then you can read the 2000-bits in 2000/32 = 62.5 ~ 63 clocks.  

 

 

--- Quote Start ---  

 

Since I'm new to this I also don't understand how to serialize the output from the SOPC,does the 2000 char table in the nios ii automatically serialize if there is only 32 bits output aviable, or do I have to manually divide the input 2000 char coefficients into 32 bit words diffrent with RAM adresses(so ~62,5 different adresses).  

 

--- Quote End ---  

 

Its your job to design the hardware. You need to use Modelsim to simulate the fundamental components offered by the FPGA, and then figure out how you can apply them to your system. 

 

Following the steps above, you will get ideas on how to proceed. 

 

Take small steps, and it'll be less intimidating. 

 

Cheers, 

Dave
0 Kudos
Altera_Forum
Honored Contributor II
312 Views

I now know how to make a _hw.tcl file(with the sopc component generator) so I would have to generate a component with the signals to the RAM(adress out,wren out,ren out,data out,q in) and fsm(rdy out,done in) as conduit signals and signals to the component from the nios ii(coef in, coef out) as avalon-MM slaves . If this is correct I then would like to know how I can access these signals from the nios ii, do I have to write some kind of functions to access the slave registers? Or are there some automatic functions created that I can use to interface with the component(ie. to set the output wren to 1, something similar to the IOWR function)? 

 

My second question is about the serializing the 2000 bits. Don't I have to enventually buffer them somewhere before the custom logic for the 62,5 clock signals and then feed them to my std_logic_vector(1999 downto 0) input? From your description I wasn't able to understand this. I understand that both the input and the output in the RAM is 32 bit wide, but how do I finally converge this to the custom logic input. 

 

Thanks in advance, 

Fred
0 Kudos
Altera_Forum
Honored Contributor II
312 Views

 

--- Quote Start ---  

I now know how to make a _hw.tcl file (with the sopc component generator) 

 

--- Quote End ---  

 

 

That is how I will often obtain the first-cut of a _hw.tcl file. I then edit that file to clean it up. 

 

 

--- Quote Start ---  

 

so I would have to generate a component with the signals to the RAM(adress out,wren out,ren out,data out,q in) and fsm(rdy out,done in) as conduit signals and signals to the component from the nios ii(coef in, coef out) as avalon-MM slaves. 

 

--- Quote End ---  

 

 

You can implement things in a couple of ways; 

 

Option 1: 

a) Avalon-MM slave for the RAM component, and then conduit signals to the top-level. Those conduit signals would connect to one side of a dual-ported RAM. The other port of the RAM would connect to your control logic. 

b) Avalon-MM slave for the control registers, and the conduit signals to the top-level. Those conduit signals would connect to your control logic 'enable' and 'done' signals. You could use a PIO component for these signals. 

 

Option 2: 

Eliminate the conduit signals altogether by creating a component with two Avalon-MM slave interfaces, and put the RAM, registers, and control logic into a single component. 

 

 

--- Quote Start ---  

 

I would like to know how I can access these signals from the nios ii, do I have to write some kind of functions to access the slave registers? 

 

--- Quote End ---  

 

The SOPC/Qsys system will have your RAM at one address and your control registers (or PIO component) at another. 

 

 

--- Quote Start ---  

 

Or are there some automatic functions created that I can use to interface with the component(ie. to set the output wren to 1, something similar to the IOWR function)? 

 

--- Quote End ---  

 

I believe you can write a _sw.tcl, however, I never use NIOS, so you'll have to figure that out. Basically you can use the IOWR function, and the _sw.tcl will just keep track of the address you used in SOPC/Qsys. 

 

 

--- Quote Start ---  

 

My second question is about the serializing the 2000 bits. Don't I have to enventually buffer them somewhere before the custom logic for the 62,5 clock signals and then feed them to my std_logic_vector(1999 downto 0) input? From your description I wasn't able to understand this. I understand that both the input and the output in the RAM is 32 bit wide, but how do I finally converge this to the custom logic input. 

 

--- Quote End ---  

 

The NIOS processor would write the values to RAM; if the NIOS writes 32-bits at a time, then it will take 63 writes to the RAM to load it. 

 

The NIOS processor would then write to the PIO to set the enable bit. 

 

Your control logic would then be enabled to read from the other port of the dual-port RAM. If your logic needs all 2000-bits, it could take 63 clocks to read all the bits, do something with them, write the answer back to another location in RAM, and then set the 'done' bit to indicate to the NIOS processor that the result is ready. 

 

If you can perform a running calculation using data from a single RAM location at a time, then your control logic can read a 32-bit value (16 x 2-bit values), perform a partial calculation, store the partial result, read the next 32-bit value on the next clock, perform the next partial calculation and accumulate it, etc., until all 2000-bits have been read. Since your result is only required every 50Hz, this scheme probably makes the most sense. 

 

Cheers, 

Dave
0 Kudos
Reply