微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > FPGA,CPLD和ASIC > 一个verilogHDL语言的音乐产生模块,赋值总是有问题,求大家帮忙看下问题出在哪……

一个verilogHDL语言的音乐产生模块,赋值总是有问题,求大家帮忙看下问题出在哪……

时间:10-02 整理:3721RD 点击:
代码是一个用于产生音乐(控制音符时长和频率)的模块,是整个程序的一部分。在start信号等于1之后,通过判断前方模块给出的plus信号是1还是0,分别播放两段不同的音乐。我是用状态机来写的,即位于不同的状态播放不同音乐。
现在的问题是:不管plus是1还是0,都播放代码中的第二个乐谱(opern0)对应的音乐,我把状态state和plus信号都输出到板子的二极管上看了,都是对的,然而只有乐谱是不对的!好诡异!
下面是代码:
module mus_generator (outbuzz, clk4, clk0, clk, reset, button, plus, start, Aflag, Bflag, mus_note, opern);
reg buzz;  //由于还需要根据reset和一个拨码开关button决定是否播放音乐,所以这里设置一个中间变量buzz
input clk4, clk0, clk, b7, plus, reset, start, Aflag, Bflag;  
output reg outbuzz; //最终输出给蜂鸣器buzz的信号
reg[2:0]state;  //fsm的状态
output reg[3:0]opern;  //最终输出的乐谱
reg opernflag;
reg [1:0]count1;
reg [14:0] count;
reg [14:0] pitch_data;  //每个音符对应的音调or频率
output reg [2:0] mus_note;  //音符
reg [3:0] opern0, opern1;  //两个不同的乐谱中间变量
parameter S0=0, S1=1, S2=2, S3=3, S4=4;
initial
begin
opern=0;
end
always @ (posedge clk or negedge reset)   //clk是fsm工作时钟,250Hz
begin
if (~reset)
        state <= S0;  //按下reset停止播放
else
        case (state)
                S0:begin
                        if (start)
                        begin
                                count1<=2'b11;  
                                state <= S1;  //因为plus信号比start来得晚一些,所以设置S1和S2缓冲,等一下plus
                        end
                        else
                        begin
                                state <= S0;
                        end
                        end
                S1:begin
                        if (count1==0)
                        begin
                        state<=S2;
                        end
                        else
                        begin
                        count1<=count1-1'b1;
                        state<=S1;
                        end
                        end
                S2:begin
                        case (plus)
                        1'b1:state<=S3;
                        1'b0:state<=S4;  //plus为1和0去往不同状态,输出不同乐谱
                        default:state<=S0;
                        endcase
                        end
                S3:begin
                        if ((~button)|(Aflag==1)|(Bflag==1))  //当button=0或者另外两个flag(前级传来的信号)为1时停止播放
                        begin
                                state <= S0;
                        end
                        else
                        begin
                                state <= S3;
                        end
                        end
                S4:begin
                        if ((~button)|(Aflag==1)|(Bflag==1))
                        begin
                                state <= S0;
                        end
                        else
                        begin
                                state <= S4;
                        end
                        end
        endcase
end
always @ (state or mus_note or opern0 or opern1 or plus or buzz)  //输出方程
begin
case (state)
S0:begin outbuzz=1;opernflag=0;opern=0;end
S1:begin outbuzz=1;opernflag=0;opern=0;end
S2:begin outbuzz=1;opernflag=0;opern=0;end
S3:begin opern=opern1;opernflag=1;outbuzz=buzz;end
S4:begin opern=opern0;opernflag=1;outbuzz=buzz;end  //这里规定了S3和S4时分别输出不同的乐谱,但是!最终结果却是,状态是对的,乐谱是错的!不管是在S3还是S4,都会输出S4的乐谱!opern0!
default:begin outbuzz=1;opernflag=0;opern=0; end
endcase
case(mus_note)  //音调or频率与音符的对应(从25MHz分频)
3'd0:pitch_data=15'd23886;
3'd1:pitch_data=15'd21283;
3'd2:pitch_data=15'd18959;
3'd3:pitch_data=15'd18128;
3'd4:pitch_data=15'd15943;
3'd5:pitch_data=15'd11944;
3'd6:pitch_data=15'd9479;
3'd7:pitch_data=15'd0;
default:pitch_data=15'd0;
endcase
case(opern1)  //第一个乐谱,对应S3,plus=1时
4'd0:mus_note=3'd3;
4'd1:mus_note=3'd3;
4'd2:mus_note=3'd4;
4'd3:mus_note=3'd4;
4'd4:mus_note=3'd2;
4'd5:mus_note=3'd2;
4'd6:mus_note=3'd4;
4'd7:mus_note=3'd4;
4'd8:mus_note=3'd1;
4'd9:mus_note=3'd1;
4'd10:mus_note=3'd4;
4'd11:mus_note=3'd4;
4'd12:mus_note=3'd3;
4'd13:mus_note=3'd3;
4'd14:mus_note=3'd6;
4'd15:mus_note=3'd5;
default:mus_note=3'd7;
endcase
case(opern0)  //第二个乐谱,对应S4,plus=0时
4'd0:mus_note=3'd2;
4'd1:mus_note=3'd3;
4'd2:mus_note=3'd4;
4'd3:mus_note=3'd3;
4'd4:mus_note=3'd2;
4'd5:mus_note=3'd3;
4'd6:mus_note=3'd4;
4'd7:mus_note=3'd3;
4'd8:mus_note=3'd2;
4'd9:mus_note=3'd3;
4'd10:mus_note=3'd4;
4'd11:mus_note=3'd4;
4'd12:mus_note=3'd3;
4'd13:mus_note=3'd4;
4'd14:mus_note=3'd6;
4'd15:mus_note=3'd5;
default:mus_note=3'd7;
endcase
end
always @ (posedge clk0 or negedge reset)
begin
        if(~reset)
   begin
                count <= 0;
      buzz <= 1'b1;
   end
        else begin
      if(count==pitch_data)  //根据乐谱中每个节拍的音符的频率不同,buzz的频率也不同
      begin buzz <= ~buzz; count<=0; end
      else
      count <= count + 1'b1;
   end
end
always @(posedge clk4 or negedge opernflag)
begin
if (~opernflag) //在输出方程里规定了只有在S3,S4时opernflag才为1,所以不输出时两个乐谱中间变量是初始化在0的,确保每次都从头播放
        begin
        opern0<=0; opern1<=0;
        end
else begin
        if(opern0==4'd15) begin  //让两个乐谱循环播放
        opern0<=0; end
        else begin
        opern0<=opern0+1'd1;
        end
        if(opern1==4'd15) begin
        opern1<=0; end
        else begin
        opern1<=opern1+1'd1;
        end
        end
end
endmodule

希望大家能帮我看一下问题出在哪里,谢谢!

你好,方便提供下之前那个模块的代码么, 看下plus信号和start信号。不然不知道你的两信号之间的延迟是否和你的状态机部分用计数器控制的延迟匹配。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top