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

Help learning to write an avalon wrapper for new custom component

TwoBit
Beginner
712 Views

I am a beginner learning Quartus. I am trying to write the HDL for a new component to make 2 LEDs blink in a system using a NIOS II processor. I'm trying to learn SystemVerilog rather than verilog. This HDL compiles without errors but is unfinished because I am still learning and and not fully certain how the avalon MM interface actually works. What is written is my understanding so far.

 

  1. Can someone please shed some light on how the addressing part works? I've been reading through the altera manuals but am starting to get muddled in all the info. I do not understand how to set addresses so that the LSB of writedata will alert my go_flag to make my hardware actually start and be enabled.
  2. Is my state machine correct? To get my module to show that it is in action I can just use the go_flag and the go_Flag_Start relationship to get the writedata[0] bit?
  3. Where can I find learn how to write the c-code for the NIOS II processor? I'm googling and see examples using commands like IOWR and stuff like that but I can't yet find resources for learning that. I know C but not these commands in C.
  4. Any general coding (HDL) tips are welcomed to. I look forward to hearing back. Thank you!

 

Here's the module and the interface for it that I've written so far:

 

/* Memory Map * * Write - 0x00 * * Read - 0x01 * /*     /******LEDFlash Modules *******/   module LEDFlash   ( input logic clock_50, //50MHz clock input logic reset, // button 0 input logic enable1, //switch 0 input logic enable100Hz, // switch 2 input logic [31:0]goFlag, // Flag to start the module // (info will come from first bit of writedata[0]; output logic state = 1'b0, //0.5sec blink LED output logic led100Hz = 1'b0, //100Hz blink LED // for read state output logic readLED = 1'b0 // LED to show when the nios is sending read data );     //Counter registers declared: logic [24:0] counter = 25'b0; // 0.5sec counter bits start set to 0 logic [18:0] counter100Hz = 19'b0; // 100Hz counter bits starts at 0 // (ctr needs 16 bits at count up to 50,000 cycles in binary)   //Counter: count for every 0.5 seconds always_ff @ (posedge clock_50) // at every pos clock edge do this: begin counter[24:0] <= counter[24:0] + 25'b1; // all counter bits = counters + 1 if (counter[24:0] == 25'd12500000) // if counter bits = 25,000,000 cycles begin counter[24:0] <= 25'b0; // reset counter to zero end end //State: blink for 0.5 seconds always_ff @ (posedge clock_50) // at every pos clock edge do this: begin if (enable1 == 1'b1) begin if (counter[24:0] == 25'd12500000) // if counter bits = 25,000,000 AND // enable is ON - blink begin state <= ~state; // LED blinks every 25'd500,000 //(switch state from what it was previously - // blinks on for 0.5 sec, then off for 0.5 // sec) end end else state <= 1'b0; // else, keep LED off end // Not sure this actually works correctly...   //100Hz counter (500,000 cycles) always_ff @ (posedge clock_50) begin counter100Hz[18:0] <= counter100Hz[18:0] + 19'b1; //start counting if (counter100Hz[18:0] == 19'd500000) //if 50,000 cycles are reached begin counter100Hz[18:0] <= 19'b0; //reset counter100Hz end end // 100Hz blink always_ff @ (posedge clock_50) // why always_ff? should it be always_combo? begin if (enable100Hz == 1'b1) begin if (counter100Hz[18:0] == 19'd500000) begin led100Hz <= ~led100Hz; end end else led100Hz <= 1'b0; end endmodule       /************************ The Avalon Interface ****************************/   module avs_blinking_interface (   // Signals between FPGA and NIOS: // avs clock and reset input logic csi_clk, input logic rsi_rst_n, // avs slave signals: input logic avs_s0_read, // for a load transmission - reads/loads from master input logic avs_s0_write, // for a store transmission - write to the master input logic [3:0] avs_s0_address, // Why do I need an address? input logic [31:0] avs_s0_writedata, // Comes from C code in NIOS output logic [31:0] avs_s0_readdata // FPGA to NIOS ); // Internal Logic logic [0:0]goFlag_Start = 1'b0; // FYI: Would automatically be set to a 1 bit register // Blinking LED Instantiation LEDFlash U1 ( .Clock_50(csi_clk), .reset (rsi_rst_n), .goFlag(goFlag_Start) ); // How system should work when it talks through avs: always_ff @ (posedge csi_clk) begin if (!rsi_rst_n) begin // If I don't press reset button (KEY0) // If no reset, start in Idle State = nothing happening on FPGA goFlag_Start <= 1'b0; // go_flag_Start keeps anything from happening // because it's staying low right? if (avs_s0_write && avs_s0_address == 0) begin // if sent a write command: slave is getting // data goFlag_Start <= avs_s0_writedata[0]; // set the go flag is based on LSB of //writedata // State depends on go flag case (goFlag_Start) 1'b0: begin // don't let U1 module activate - Idle state end 1'b1: begin // start U1 module, start blinking - Blink state goFlag_Start <= 1'b0; // reset goFlag end default: begin //pick a default end endcase end //if read command sent: if (avs_s0_read && avs_s0_address == 1) begin // send something back...light up an LED? // just so I know read is actually working end // reset is pressed: else goFlag_Start <= 1'b0; // Stay in idle state, go flag is LOW end end   endmodule

 

 

0 Kudos
4 Replies
sstrell
Honored Contributor III
442 Views

There's a lot going on here. Things I've noticed:

 

goFlag isn't doing anything in your LEDFlash. How is it supposed to work there? Is it supposed to be what you call "enable1"?

 

Your LEDFlash instantiation is missing a number of the I/O defined in the module (enable1, enable100Hz, goFlag, etc.).

 

You don't need an address input unless there is more than 1 addressable location required for reading from or writing to. That does not look to be the case here. You could just use the avs_s0_read, avs_s0_readdata, avs_s0_write, and avs_s0_writedata signals to read from or write to goFlag_Start.

 

I don't see why you even need a state machine here. You already created enable signals for the flashing in the LEDFlash module and you're not doing anything more complicated than enabling or disabling the flashing.

 

I suggest you take a look at a number of online trainings. Search for "avalon", "platform designer", and "verilog" to find things that may be applicable:

 

https://www.intel.com/content/www/us/en/programmable/support/training/catalog.html

 

This is a good starting point for creating a custom component that will work in Platform Designer:

 

https://www.intel.com/content/www/us/en/programmable/support/training/course/oqsys3000.html

 

#iwork4intel

 

 

 

TwoBit
Beginner
442 Views

Wow, thank you for so much input! I was given this project to learn Quartus/FPGA stuff. It's really interesting to me but this is a lot to learn. The end goal of the project was to use memory mapping which is why I was trying to use the read/write/readdata/writedata/address parts and I wanted the LSB of writedata to read from/write to the go_Flag_Start. I will look into all the links you suggest and hopefully be back with improvements but I'm sure more questions will arise. Thank you again!

0 Kudos
sstrell
Honored Contributor III
442 Views
0 Kudos
AnandRaj_S_Intel
Employee
442 Views

Hi Rachel,

 

Refer to the previous case which addresses most of your query and has supporting documents and example.

https://forums.intel.com/s/question/0D50P00004NfSbxSAF/custom-ip-core

 

Regards

Anand

0 Kudos
Reply