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

Interfacing custom module with Nios II

Altera_Forum
Honored Contributor II
1,297 Views

Hello, 

 

I have written an AES-128 Encryption module in SystemVerilog, and instead of just flashing it onto the DE2-115 board, and having it show results on LED/7-Segment's etc, I want to connect it to a Nios II Processor - so I can program it using C/C++. 

So far I have used SOPC and created a Nios II with JTAG_UART, Onchip Memory, and many PIO's. 

My AES module has - Clock Input (can connect to CLOCK_50), Key[128 bits], PlainText[128 bits], Load, Reset and Outputs are CipherText[128 bits] and a "Done" bit. 

As PIO's are 32 bit max, I created 4 x 32 bit PIO for each Key, PlainText and CiperText and individual PIO for the others. 

Then in Top Module I instantiated my Nios II and my AES Module, and simply created Wires and connected the correct outputs from Nios II to inputs on AES and AES Outputs to Nios II inputs. My first question is....is this the correct way to go about it? 

 

I then started a project in Eclipse, and have tried writing data down the PIO's from Nios II to the AES module and then try and collect the CipherText thatcomes into the Nios II Input PIO's, and am having little luck. 

For example I used the following code to write a Key to the AES Module... 

 

IOWR_ALTERA_AVALON_PIO_DATA(PIO_KEY12796_BASE, Key0); 

IOWR_ALTERA_AVALON_PIO_DATA(PIO_KEY9564_BASE, Key1); 

IOWR_ALTERA_AVALON_PIO_DATA(PIO_KEY6332_BASE, Key2); 

IOWR_ALTERA_AVALON_PIO_DATA(PIO_KEY3100_BASE, Key3); 

 

Where Key"x" are integers which ive preset to 32 bit values. 

 

Are these the correct functions to use...I mean, do they hold their value on the wire, or do they simply just send a quick pulse to the module? 

 

I just need a bit of a push in the right direction to get this interface working between the two. Any help would be very much appreciated as always :)
0 Kudos
10 Replies
Altera_Forum
Honored Contributor II
341 Views

PIOs hold the value until you change it or (if PIO is bidirectional) until you change it from output to input. So, your idea is supposed to work. 

Anyway, using PIO to transfer data to an external device in this way is easy but is not convenient in cases like yours, where you have a lot of data bits, and then multiple PIOs. 

You'd better integrate the module in SOPC builder as an Avalon Memory Mapped slave. Then, your data could be read/written from/to module registers like ordinary memory. 

First of all you need to write wrapper code to interface Avalon bus, but this is rather simple; I think you can find several examples on opencores.org. 

Then you must create the custom MM-slave component for SOPC builder: you can use the component wizard or (better) write directly the tcl file using that of another component as a template.
0 Kudos
Altera_Forum
Honored Contributor II
341 Views

OK great, I think im going to go the Avalon route...it sounds better! 

 

I have found and downloaded this .zip http://www.altera.com/support/examples/nios2/exm-avalon-memory-slave.html#figure1 

 

I am a bit confused as to what to do with it, and have done some reading and have opened the .V to see you can edit data width parameters etc, and there are up to 16 user input/outputs. Do I edit the names of the user inputs/outputs, or simply in that .v file just instantiate my AES module and connect up the inputs/outputs I need? 

 

Sorry for being a noob :(
0 Kudos
Altera_Forum
Honored Contributor II
341 Views

I haven't never used this template but I took a quick look at it and I definitely think this is perfect for you.  

Follow these steps: 

- replace all <slave_template> occurrences with a name you like and place the files into the \altera\<version>\ip\user_components directory 

- instantiate your Verilog module in slave_template.v, connecting your data i/o (namely the AES key value) to user_datain and user_dataout  

- add your .v files to the list in the .tcl file 

- the next time you open sopc builder, the new component will be available; include it in your system 

- rebuild all 

- access AES key and results with IOWR and IORD macros, as shown in .h file 

That's all. I hope I didn't forget anything
0 Kudos
Altera_Forum
Honored Contributor II
341 Views

Fantastic reply! 

 

One last question (hopefully) - in that template you can set a fixed DATA-WIDTH vid a parameter. I need to set this to 128 I believe, however the input pins Load, Reset and output pin Done on my design are only 1 bit...will the synthesis tool or SOPC automatically figure out im only using 1 bit?
0 Kudos
Altera_Forum
Honored Contributor II
341 Views

According to the pdf file you can set DATA_WIDTH to 128. But the tcl file allows you to select only a 8,16 or 32 bit data width.  

I don't know if a 128 width could actually be used and how it would be synthesized. Since Avalon is a 32bit bus, at least 8 bus cycles are required even so.  

Then, I'd rather define DATA_WIDTH=32 and span the 128 key data on multiple user_data registers. 

Regarding the 1bit signals there's no problem: you can route one single user_data line to your custom logic and discard all the others.
0 Kudos
Altera_Forum
Honored Contributor II
341 Views

And if I was to change DATA_WIDTH to 32 bits, and my module declaration of Key is 128 bits, how do I instantiate it? 

 

For e.g. 

 

With DATA_WIDTH set to 128 I can put this in the slave.v  

 

// Clock Key PlainText Load Reset CipherText Done 

AES_128_EncryptionCore u0(clk,user_dataout_0,user_dataout_1,user_dataout_2,reset,user_datain_0,user_datain_1); 

 

However if I set DATA_WIDTH to 32 surely I cant pass the Key input, or is there a way to concatenate? 

OR would I have to edit my actual custom logic and have 4 x 32 bit key inputs?
0 Kudos
Altera_Forum
Honored Contributor II
341 Views

It is easier than you think 

Instantiate this way: 

AES_128_EncryptionCore u0(clk,key,PlainText,Load,reset,CipherText,Done); 

 

You only need to add this glue logic: 

 

wire key[127:0] = { user_dataout_4, user_dataout_3, user_dataout_2, user_dataout_1 }; 

wire PlainText = user_dataout_0[0]; 

wire Load = user_dataout_0[1]; 

wire CipherText 

wire Done; 

assign user_datain_0[0] = CipherText; 

assign user_datain_0[1] = Done; 

 

Here I assumed these register functions: 

- the AES key is stored into user_dataout_1 to 4 

- user_dataout_0 is a 'control register', where bit 0 is used as data input and bit 1 as load command 

- user_datain_0 is a 'status register', where bit 0 is your encrypted data output and bit 1 is the completion signal. 

 

Please note that this is a minimal addresses implementation; these 4 bits can be as well mapped singularly on 4 separated registers. 

If you want a smarter code, replace all those user_data_ with the actual register functions, eg control_reg,status_reg,key0,key1,...
0 Kudos
Altera_Forum
Honored Contributor II
341 Views

You are a hero! 

 

Thank you very much for your help - lets see if I can get something working :)
0 Kudos
Altera_Forum
Honored Contributor II
341 Views

Ive given this a go now and seem to have "partially" got somewhere. 

 

I created the Component in SOPC builder and put it into my design, however whats confusing me is that even though its linked up, in the SOPC module code, the module header is 

 

 

module NIOS_AES ( 

// 1) global signals: 

clk_0, 

reset_n, 

 

// the_AES_AvalonSlave_0 

user_byteenable_from_the_AES_AvalonSlave_0, 

user_chipselect_from_the_AES_AvalonSlave_0, 

user_datain_10_to_the_AES_AvalonSlave_0, 

user_datain_11_to_the_AES_AvalonSlave_0, 

user_datain_12_to_the_AES_AvalonSlave_0, 

user_datain_13_to_the_AES_AvalonSlave_0, 

user_datain_9_to_the_AES_AvalonSlave_0, 

user_dataout_0_from_the_AES_AvalonSlave_0, 

user_dataout_10_from_the_AES_AvalonSlave_0, 

user_dataout_11_from_the_AES_AvalonSlave_0, 

user_dataout_12_from_the_AES_AvalonSlave_0, 

user_dataout_13_from_the_AES_AvalonSlave_0, 

user_dataout_1_from_the_AES_AvalonSlave_0, 

user_dataout_2_from_the_AES_AvalonSlave_0, 

user_dataout_3_from_the_AES_AvalonSlave_0, 

user_dataout_4_from_the_AES_AvalonSlave_0, 

user_dataout_5_from_the_AES_AvalonSlave_0, 

user_dataout_6_from_the_AES_AvalonSlave_0, 

user_dataout_7_from_the_AES_AvalonSlave_0, 

user_dataout_8_from_the_AES_AvalonSlave_0, 

user_dataout_9_from_the_AES_AvalonSlave_0, 

user_read_from_the_AES_AvalonSlave_0, 

user_write_from_the_AES_AvalonSlave_0 

); 

 

Why has the module header for my SOPC got inputs and outputs for my AES Avalon Slave module? I thought the whole point was that the Avalon Slave module would be encapsulated inside and controlled by the Nios II CPU?  

 

I must have messed something up!?
0 Kudos
Altera_Forum
Honored Contributor II
341 Views

In the tcl file, remove these lines: 

add_interface user_interface conduit end 

add_interface_port user_interface user_dataout_0 export Output -1 

add_interface_port user_interface user_datain_0 export Input -1 

... and so on 

 

These directives instruct sopc builder to expose the listed signals to an external port. 

If your design is not supposed to connect to external logic, you don't need these.
0 Kudos
Reply