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

2019-07-15 21:27发布

代码是一个用于产生音乐(控制音符时长和频率)的模块,是整个程序的一部分。在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


希望大家能帮我看一下问题出在哪里,谢谢!!
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。