Skip to content

Latest commit

 

History

History
62 lines (50 loc) · 2.76 KB

0031-2020-06-19.md

File metadata and controls

62 lines (50 loc) · 2.76 KB

19 Jun 2020

Calculating note values for test05h

I had hoped to get a Verilog function to work for pre-calculating note div values, instead of having to hard-code them. As it turns out, Xilinx ISE (specifically "XST") doesn't support real numbers in calculations, which surprises me somewhat. Using "EDA Playground", I was able to get it to use this function to generate the values for me originally:

//NOTE: This is our incoming clock frequency, after prescaling:
`define HZ 25_000_000
// We define A5 as 3520Hz:
`define A5 3520

function integer note_div(input real note_num);
  begin
    //NOTE: Extra *2 is because the speaker toggle
    // will halve this frequency again:
    note_div = (`HZ/(`A5*2.0*2.0**(note_num/12.0)))-1;
  end
endfunction

initial
begin
  $display("0: div = ", note_div(0));
  $display("1: div = ", note_div(1));
  $display("2: div = ", note_div(2));
  //...etc...
end

I also tried this, but for loops in Verilog apparently always have to cleanly/predictably unroll in order to resolve, and this is not compatible with the requirements for that. I had hoped it would work anyway since it is just part of a function and not something we're trying to synthesize, but no...

function integer note_div(input integer note);
  begin
    // This method would divide note_div by 1.0594 for each iteration:
    for (note_div=(`HZ/`A5/2); note > 0; note_div=note_div*10000/10594)
      note = note-1;
    note_div = note_div-1;
  end
endfunction

I also thought about trying this in a loop, which can be applied to any note period to get the period of the next highest note, but I'm sure that would have the same problems in a loop:

function integer increment_note_period(input integer note_period);
  // Don't forget that what we return needs 1 subtracted from it to get a loop counter:
  increment_note_period = note_period - note_period>>4 + note_period>>7 - note_period>>9 + note_period>>11;
endfunction

...an interesting idea in terms of how to calculate such a specific scaling, though.

Notes