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.
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; 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; // 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
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:
This is a good starting point for creating a custom component that will work in Platform Designer:
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!