Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Altera_Forum
Honored Contributor I
727 Views

Configure custom component with Nios?

Hello, 

 

I started writing my own custom components for the SOPC builder. But I didn't understand yet, how I can configure my own component via Nios. I still worked with generic parameters, but now I want to give my component a register space which can be accessed via Nios. 

 

How does it work? 

 

Can you please give me a hint? 

 

Best Regards! 

tonib
0 Kudos
5 Replies
Altera_Forum
Honored Contributor I
27 Views

you need to create a custom component with an Avalon Memory Mapped Slave interface, and use the Nios to write to registers within your component 

 

have you seen this video training? it may cover this area: 

 

http://www.altera.com/education/training/courses/oemb1111
Altera_Forum
Honored Contributor I
27 Views

Ok, thanks! But how does it work exactly? Do I have to write a process which observs write transfers to my component and set a variable with the received data e.g.? Or is it possible to map addresses direct to variables? 

I want to use the memory interface to configure my component, so i have to store some "variables"... 

 

Thanks for your assistance! 

tonib
Altera_Forum
Honored Contributor I
27 Views

You have to write a process that waits for 'read' and 'write' control signals on the Avalon interface, yes.

Altera_Forum
Honored Contributor I
27 Views

Ok thanks, but how is the general usage of storing configuration registers in own components? Do you use signals which are set and read by the process waiting for 'read' and 'write' control signals? Or how do you realize this storing of data? 

In my case I want to store some variables which control the behavior of my own component... 

 

Thanks!
Altera_Forum
Honored Contributor I
27 Views

You almost have it. 

 

1. Declare regs in your module to hold the parameters you need with the appropriate number of bits you require for each parameter. These are your "variables". 

 

2. Decide which address(es) will be associated with your parameter register(s). 

 

3. When a read or write control signal becomes active, decode the address lines (usually done with a case statement) and read or set the appropriate register. 

 

For example, to write to a parameter you might use "my_parameter_reg <= writedata;", or "my_parameter_reg[5:0] <= writedata[5:0];" if you have a configuration flags register to hold 6 boolean values. This is verilog syntax by the way. 

 

For reading, you might have something like "readdata_reg <= my_parameter_reg;", or "readdata_reg <= {26'b0, my_parameter_reg[5:0]};" and somewhere in your module "assign readdata = readdata_reg;" In this scenario, you would need 1 read waitstate to allow a specific parameter_reg to set the generic readdata_reg, which is then available to the readdata wires on the next clock. 

 

There are ways to avoid the waitstate, but you need to fairly complicated logical anding and oring operation to do so. Here is some essential snippets of code from one component I did: 

 

assign readdata = {32 {(address == 3'b000)}} & position | {32 {(address == 3'b001)}} & r_counter_period | {32 {(address == 3'b010)}} & r_step_pulse_length | {32 {(address == 3'b011)}} & r_captured_position | {32 {(address == 3'b100)}} & r_pulse_generator_value | {32 {(address == 3'b111)}} & {r_position_has_been_captured, encoder_error, r_control_register}; always @(posedge clk or negedge reset_n) begin if (!reset_n) begin r_reset_position_has_been_captured <= 1'b1; r_reset_encoder_error <= 1'b1; r_set_counter <= 1'b1; r_control_register <= 10'b0; r_counter_period <= -1; r_step_pulse_length <= 16'hFF; r_new_counter_value <= 1'b0; end else begin if (chipselect) begin if (~write_n) begin case (address) 3'b000: begin r_new_counter_value <= writedata; r_set_counter <= 1'b1; end 3'b001: begin r_counter_period <= writedata; end 3'b010: begin r_step_pulse_length <= writedata; end 3'b011: begin r_reset_position_has_been_captured <= 1'b1; end 3'b100: begin r_reset_encoder_error <= 1'b1; end 3'b101: begin end 3'b110: begin end 3'b111: begin r_control_register <= writedata; end endcase end // ~write_n end // chipselect else begin r_reset_encoder_error <= 1'b0; r_reset_position_has_been_captured <= 1'b0; r_set_counter <= 1'b0; end end // not in reset end
Reply