Search code examples
verilogfpgaspartan

Changing Counter target according to input


I'm working on a project for a digital design course, and I have to play musical notes using frequencies in my project. I must say I'm fairly inexperienced in verilog (have to use verilog for the project). I researched a bit regarding the topic and found (here) the following code snippet:

    module music(clk, speaker);
    input clk;
    output speaker;
    parameter clkdivider = 25000000/440/2;

    reg [14:0] counter;
    always @(posedge clk) if(counter==0) counter <= clkdivider-1; else counter <= counter-1;

    reg speaker;
    always @(posedge clk) if(counter==0) speaker <= ~speaker;
    endmodule

In this code the clock is 25MHz and the frequency of the output is 440, what I want to do is change the frequency of the output according to user input, so I assume I just have to change the value the counter counts to. How can I neatly add that to the code so it should work ?


Solution

  • To get you started, I've set-up an environment for you. You must add you're logic to make the correct functionality (homework) especially in counter register where in you have to calculate the required frequency.

              // change logic here (to add userinput)
                counter <= clkdivider-1; 
    

    Since you want to change the frequency of the output according to user input, you should add an input port to the music module.

    module music(clk, reset, userinput, valid, speaker);
        input clk, valid, reset;
        input [7:0] userinput;
        output speaker;
    

    userinput is 8 bits but you can change this based from your requirements. Take note that a valid signal is also needed for handshaking with the other modules.

    Reset is also added to clear your music module.

    Here is your testbench

    module testmusic;
    reg clk;
    reg [7:0] userinput;
    wire speaker;
    reg valid;
     reg reset;
    
    
    initial begin
      forever begin
        #1 clk = !clk;
      end
    end
    
    initial begin
      clk = 0;
      userinput = 0;
      valid = 0;
      @(posedge clk);
      $monitor("userinput: %0h valid: %0h speaker: %0h\n", userinput, valid, speaker);
    end
    
    
     task resetdut;
       reset = 0;
    
       repeat (3) begin
        @(posedge clk);
       end
    
       reset <= 1;
    
       repeat (3) begin
        @(posedge clk);
       end
    
       reset <= 0;
     endtask
    
     music dut(clk, reset, userinput, valid, speaker);
    
     initial begin
       #10000; $finish;
     end
    
     // perform our testing here
     initial begin
       // perform reset to initialize our dut
       resetdut;
       testuserinput;
     end
    
     task testuserinput;
       @(posedge clk);
       userinput <= 8'hF; // insert user input here
       valid <= 1;
       @(posedge clk);
       userinput <= 0;
       valid <= 0;
       @(posedge clk);
     endtask
    
    
    endmodule
    

    Here is your RTL code that you need to fix.

    module music(clk, reset, userinput, valid, speaker);
        input clk, valid, reset;
        input [7:0] userinput;
        output speaker;
        parameter clkdivider = 25000000/440/2;
    
        reg [14:0] counter;
    
      reg [7:0] reginput;
    
        always @(posedge clk) begin
          if (reset) begin
            counter <= 0;
          end
          else begin
            if(counter==0) begin
              // change logic here (to add userinput)
                counter <= clkdivider-1; 
            end
            else begin
                counter <= counter-1;
            end
          end
        end
    
        reg speaker;
        always @(posedge clk) begin
          if (reset) begin
            speaker <= 0;
          end
          else begin
            if(counter==0) begin
                speaker <= ~speaker;
            end
          end
        end
    
        // handshake
      always @(posedge clk) begin
        if (reset) begin
          reginput <= 0;
        end
        else begin
            if (valid) begin
              reginput <= userinput;
            end
        end
      end
    
    endmodule
    

    You may want to compile the code here http://www.edaplayground.com/x/PR2