【问题标题】:Outputting a square wave at a specific frequency in verilog在verilog中以特定频率输出方波
【发布时间】:2017-11-16 22:38:40
【问题描述】:

所以我试图通过音频控制器产生声音,方法是创建一个不同频率的方波,具体取决于哪个开关在 FPGA 上被翻转。我正在使用一个具有 48kHz 芯片时钟的音频控制器,所以我使用了一个时钟分频器(每个音符一个,现在没有必要,但如果你想知道我为什么要这样做,那就稍后再说)计算每个音符的占空比,每半个占空比在+幅度和-幅度之间翻转。出于某种原因,我能够输出音频,但音符的音调并不代表我给它们的频率(音调似乎是随机的,而且音调比应有的高得多)。我已经在互联网上进行了搜索,但无法找到解决方案来解释为什么会这样……非常感谢任何帮助!

这是我的代码的 sn-p:

// Positive and negative amplitude parameters for square wave
parameter pos_amp = 32'h7FFFFFFF;
parameter neg_amp = 32'h80000000;

// Determines channel_audio_out via dac_out
wire signed [32:1] channel_audio_out = dac_out ? pos_amp : neg_amp;

// Seperate 8-bit counter for each note
reg [7:0] ac_counter_C4;
reg [7:0] ac_counter_D4;
reg [7:0] ac_counter_E4;
reg [7:0] ac_counter_F4;
reg [7:0] ac_counter_G4;
reg [7:0] ac_counter_A4;
reg [7:0] ac_counter_B4;

reg clear_audio_out_memory;             // To clear audio_out buffer when no SW is flipped
reg write_audio_out;                            // To signal when to write to audio_out buffer
reg dac_out;                                    // Determines pos_amp or neg_amp for channel_audio_out

// Determines dac_out via ac_counter's (AUD_XCK dividers)
always@(posedge AUD_XCK) // 48kHz
begin
    clear_audio_out_memory <= 1'b0;
        if (SW[0] == 1'b1) // C4 --- f = 261.626 Hz --- Duty Cycle = 184
            begin
                ac_counter_C4 <= ac_counter_C4 + 1'b1;
                if (ac_counter_C4 >= 8'd183)
                    ac_counter_C4 <= 8'd0;
                write_audio_out <= 1'b1;
                dac_out = (ac_counter_C4 < 8'd92) ? 1'b1 : 1'b0;
            end
        else if (SW[1] == 1'b1) // D4 --- f = 293.665 Hz --- Duty Cycle = 164
            begin
                ac_counter_D4 <= ac_counter_D4 + 1'b1;
                if (ac_counter_D4 >= 8'd163)
                    ac_counter_D4 <= 8'd0;
                write_audio_out <= 1'b1;
                dac_out = (ac_counter_D4 < 8'd82) ? 1'b1 : 1'b0;
            end
        else if (SW[2] == 1'b1) // E4 --- f = 329.628 Hz --- Duty Cycle = 146
            begin
                ac_counter_E4 <= ac_counter_E4 + 1'b1;
                if (ac_counter_E4 >= 8'd145)
                    ac_counter_E4 <= 8'd0;
                write_audio_out <= 1'b1;
                dac_out = (ac_counter_E4 < 8'd73) ? 1'b1 : 1'b0;
            end
        else if (SW[3] == 1'b1) // F4 --- f = 349.228 Hz --- Duty Cycle = 138 // Wrong note completely
            begin
                ac_counter_F4 <= ac_counter_F4 + 1'b1;
                if (ac_counter_F4 >= 8'd137)
                    ac_counter_F4 <= 8'd0;
                write_audio_out <= 1'b1;
                dac_out = (ac_counter_F4 < 8'd69) ? 1'b1 : 1'b0;
            end
        else if (SW[4] == 1'b1) // G4 --- f = 391.995 Hz --- Duty Cycle = 122
            begin
                ac_counter_G4 <= ac_counter_G4 + 1'b1;
                if (ac_counter_G4 >= 8'd121)
                    ac_counter_G4 <= 8'd0;
                write_audio_out <= 1'b1;
                dac_out = (ac_counter_G4 < 8'd61) ? 1'b1 : 1'b0;
            end
        else if (SW[5] == 1'b1) // A4 --- f = 440 Hz --- Duty Cycle = 110
            begin
                ac_counter_A4 <= ac_counter_A4 + 1'b1;
                if (ac_counter_A4 >= 8'd109)
                    ac_counter_A4 <= 8'd0;
                write_audio_out <= 1'b1;
                dac_out = (ac_counter_A4 < 8'd55) ? 1'b1 : 1'b0;
            end
        else if (SW[6] == 1'b1) // B4 --- f = 493.883 Hz --- Duty Cycle = 98
            begin
                ac_counter_B4 <= ac_counter_B4 + 1'b1;
                if (ac_counter_B4 >= 8'd97)
                    ac_counter_B4 <= 8'd0;
                write_audio_out <= 1'b1;
                dac_out = (ac_counter_B4 < 8'd44) ? 1'b1 : 1'b0;
            end
        else // NO SWITCH ON --- DEFAULT STATE
            begin

                ac_counter_C4 <= 1'd0;
                ac_counter_D4 <= 1'd0;
                ac_counter_E4 <= 1'd0;
                ac_counter_F4 <= 1'd0;
                ac_counter_G4 <= 1'd0;
                ac_counter_A4 <= 1'd0;
                ac_counter_B4 <= 1'd0;

                write_audio_out <= 1'b0;
                clear_audio_out_memory <= 1'b1;
                dac_out <= 1'b0;
            end
end

谢谢!

【问题讨论】:

    标签: audio verilog


    【解决方案1】:

    如果我正确理解了您的系统,您不应该生成指定频率的正弦波幅度值作为 DAC 的输入吗? .如果您将 2 幅度信号馈送到 DAC,我假设模拟输出也是方波,它本质上是您所需的基频和更高次谐波的组合(这些可能会导致明显的更高音调)。

    【讨论】:

    • 感谢您的回复,但我最终找出了问题所在。原来我使用的时钟(DAC_XCK)不是我想象的那样。仍然不确定它是如何工作的,但我将其更改为 CLOCK_50(50MHz 时钟),更改了所有占空比以匹配此更改,现在它可以完美运行。我什至可以改变八度音阶并同时演奏多个音符!昨晚取得了很大进展,我很兴奋。
    猜你喜欢
    • 2014-03-05
    • 1970-01-01
    • 2018-10-19
    • 2023-03-03
    • 1970-01-01
    • 2016-06-11
    • 1970-01-01
    • 2013-07-24
    • 1970-01-01
    相关资源
    最近更新 更多