If statement Verilog:if语句的意外行为

If statement Verilog:if语句的意外行为,if-statement,mips,verilog,If Statement,Mips,Verilog,我在Verilog中实现MIPS数据路径行为,当我模拟代码时,行为是意外的。 这里显示了BEQ和BNE分支的情况(如果显示相等/不相等指令)。ALU_Out确定两个寄存器是否相等。没有这些真正重要的原因,我的问题基本上是如何真正跳过我的条件。所以,从波形中的信号来看,ALU_out为零,但是在if ALU_out==32'd1中发生的任何事情都执行一次。使我的电脑成为PC+6。现在如果我的ALU_Out实际上等于1,PC变成PC+6+6,它的1==>变成13,我也在这个if语句中集成了一些kin

我在Verilog中实现MIPS数据路径行为,当我模拟代码时,行为是意外的。 这里显示了BEQ和BNE分支的情况(如果显示相等/不相等指令)。ALU_Out确定两个寄存器是否相等。没有这些真正重要的原因,我的问题基本上是如何真正跳过我的条件。所以,从波形中的信号来看,ALU_out为零,但是在if ALU_out==32'd1中发生的任何事情都执行一次。使我的电脑成为PC+6。现在如果我的ALU_Out实际上等于1,PC变成PC+6+6,它的1==>变成13,我也在这个if语句中集成了一些kinna标志,并确保它执行一次。 即使我在if中添加了else,我的标志也清楚地表明if在else之前执行过一次。 在BNE的情况下也会发生同样的情况,并且在if语句执行一次之后检查所需的条件。 你能告诉我这个代码有什么问题吗。 非常感谢

            if (ALU_op == 6'd30)        //BEQ
            begin
                ALU_out = ((ALU_in1) == (ALU_in2));
                if (ALU_out == 32'd1)
                    begin
                        PC = PC + Imm_32;
                    end
            end


        if (ALU_op == 6'd31)        //BNE
            begin
                ALU_out = ((ALU_in1) == (ALU_in2));
                if (ALU_out == 0)
                    begin
                        PC = PC + Imm_32;
                    end
            end
更新:仍然没有做任何关于非阻塞分配的事情,但我确实修改了更新PC的方式,在代码中添加了下一个PC。If语句问题消失了。然而,问题是,当跳转或分支发生时,下一台PC会正确计算,但分支目标处的指令不会在同一时钟内提取!

这应该是一个单周期的MIPS处理器,所以一条指令应该在一个周期内被提取和执行。这就是为什么非阻塞分配造成的延迟是不需要的

always @(*)
    begin
        IR <= Instruction;
    end
always @(posedge clk)
    begin

        PC = next_PC;

        OverFlow = 0;

    end

// Decode + Operand Fetch //    
always @ (IR)
    begin
        Op_code = IR[31:26];
        if (Op_code == 6'd0)        //R-type Instructions
            begin
                Func = IR[5:0];


                if (Func == 6'b100000)  //ADD
                    begin
                        ALU_op = 6'd1;          //as numbered in LAB manual
                        read_addr1 = IR [25:21];    //Rs
                        read_addr2 = IR [20:16];    //Rt

                    end     //end of ADD


                if (Func == 6'b100001)  //ADDU
                    begin
                        ALU_op = 6'd2;          //as numbered in LAB manual
                        read_addr1 = IR [25:21];    //Rs
                        read_addr2 = IR [20:16];    //Rt
                    end     //end of ADDU


                /* some code here skipped to make the code shorter*/

            if (Op_code == 6'b000100)   //BEQ (Branch if Equal)
                begin
                    ALU_op = 6'd30;         //as numbered in LAB manual
                    read_addr1 = IR [25:21];    //Rs
                    read_addr2 = IR [20:16];    //Rt
                    Imm_32 = {{16{IR[15]}},IR [15:0]};  //Offset 2nd operand: imm-32 (Sign Extended Imm_16) 
                    //BT =  PC + Imm_32;
                end


            if (Op_code == 6'b000101)   //BNE (Branch if NOT Equal)
                begin
                    ALU_op = 6'd31;         //as numbered in LAB manual
                    read_addr1 = IR [25:21];    //Rs
                    read_addr2 = IR [20:16];    //Rt 
                    Imm_32 = {{16{IR[15]}},IR [15:0]};  //Offset 2nd operand: imm-32 (Sign Extended Imm_16)  
                end


            if (Op_code == 6'b000001)   
                begin
                    if ( IR [20:16] == 5'b00001)    //BGEZ (Branch on Greater than or Equal to Zero)
                        begin
                            ALU_op = 6'd33;         //as numbered in LAB manual
                            read_addr1 = IR [25:21];    //Rs
                            Imm_32 = {{16{IR[15]}},IR [15:0]};  //Offset 2nd operand: imm-32 (Sign Extended Imm_16)  
                        end


                    if (IR [20:16] == 5'b10000)     //BLTZAL (Branch on less than Zero And Link)
                        begin
                            ALU_op = 6'd34;         //as numbered in LAB manual
                            read_addr1 = IR [25:21];    //Rs
                            Imm_32 = {{16{IR[15]}},IR [15:0]};  //Offset 2nd operand: imm-32 (Sign Extended Imm_16)  
                        end
                end


            if (Op_code == 6'b000010)   //J (Jump)
                begin
                    ALU_op = 6'd35;         //as numbered in LAB manual
                    Imm_32 = {PC [31:26],IR [25:0]};    //Jump Address  
                end


            if (Op_code == 6'b000011)   //JAL (Jump And Link)
                begin
                    ALU_op = 6'd36;         //as numbered in LAB manual
                    Imm_32 = {PC [31:26],IR [25:0]};    //Jump Address  
                end                     


    end // end of DECODE

// Execution & Write Back//

always @ (ALU_op, ALU_in1, ALU_in2)
    begin
        next_PC = PC+1;
        wr_En = 0;  
        DM_wrEn_0 = 0;
        DM_wrEn_1 = 0;
        DM_wrEn_2 = 0;
        DM_wrEn_3 = 0;

        if (ALU_op == 6'd1)     //ADD
            begin
                ALU_out = ALU_in1 + ALU_in2;
                write_addr = IR [15:11];    //Rd
                if( ( (ALU_in1[31]) && (ALU_in2[31]) && (!ALU_out[31]) )||( (!ALU_in1[31]) && (!ALU_in2[31]) && (ALU_out[31]) ) )
                    OverFlow = 1'b1;
                wr_En = 1;
                write_data = ALU_out;                       
            end

        if (ALU_op == 6'd2)     //ADDU
            begin
                ALU_out = ALU_in1 + ALU_in2;
                write_addr = IR [15:11];    //Rd
                wr_En = 1;
                write_data = ALU_out;                   
            end


        /* some code here skipped to make it shorter*/



        if (ALU_op == 6'd30)        //BEQ
            begin
                ALU_out = ((ALU_in1) == (ALU_in2));
                if (ALU_out == 32'd1)
                    begin
                        //PC = PC + Imm_32;
                        next_PC = PC + Imm_32;
                        BT = 32'd56;
                        //PC = BT;
                    end
            end


        if (ALU_op == 6'd31)        //BNE
            begin
                ALU_out = ((ALU_in1) == (ALU_in2));
                if (ALU_out == 0)
                    begin
                        //PC = PC + Imm_32;
                        next_PC = PC + Imm_32;
                        BT = 32'd90;
                    end
            end


        if (ALU_op == 6'd33)        //BGZE
            begin
                ALU_out = ((ALU_in1) >= 0);
                if (ALU_out)
                    begin
                        //PC = PC + Imm_32;
                        next_PC = PC + Imm_32;
                    end
            end


        if (ALU_op == 6'd34)        //BLTZAL
            begin
                ALU_out = ((ALU_in1) < 0);
                if (ALU_out)
                    begin
                        write_addr = 5'd31; //$ra ($31)
                        write_data = PC;
                        wr_En = 1;
                        //PC = PC + Imm_32;
                        next_PC = PC + Imm_32;
                    end
            end


        if (ALU_op == 6'd32)        //JR
            begin
                //PC = ALU_in1;
                next_PC = ALU_in1;
            end


        if (ALU_op == 6'd35)        //J
            begin
                //PC = Imm_32;
                next_PC = Imm_32;
            end


        if (ALU_op == 6'd36)        //JAL
            begin
                write_addr = 5'd31; //$ra
                wr_En = 1;
                write_data = PC;
                //PC = Imm_32;
                next_PC = Imm_32;
            end

    end  //end of EXE and WB always block

既然我们知道你们希望它是单周期的,这就澄清了很多


首先,您需要确定您的寄存器是用于与内存对话的,您是将访问指令内存的地址放在寄存器中还是放在生成的指令中,因为现在使用always@*IR时,这是一个组合过程always@*还是Sequential always@posedge clk?看起来您将混合分配样式blocking=和non-blocking=您是否尝试过ALU_out=ALU_in1==ALU_in2?1 : 0. 在这种情况下,ALU_OUT中的任何前1个剩余。。?如果ALU_in1==ALU_in2 begin ALU_outMorgan可能是正确的,那么您在单个块中混合了组合逻辑和顺序逻辑,从而导致不期望的行为。您可能应该将PC的实际分配分离到它自己的顺序块,并组合确定下一个TPC。@Sharvill111感谢您的响应。我也试过了!我的电脑还是变成了71+6@Morgan谢谢你的回复。实际上,我有两个always块:always@posedge clk,在其中提取指令并确定其对应的ALU_Op。这是解码部分的输入。下一个always块总是对该ALU_Op以及操作数敏感,以防两条连续指令相同。现在,这一切都发生在这里面,非常感谢你!顺便说一句,很好的提示:我确实改变了IR的东西,我做了一根电线,使用了assign语句,但是我得到了非常相同的波形在分支或跳转的情况下,PC会正确更改,但会获取以下指令,而不是PC指向分支目标的位置!与我链接的第二个波形屏幕截图相同,顺便说一下,我使用@LadyMillionM创建了相同的文件指令内存是什么样子的?如果访问需要一个周期,则必须更改此型号。IP核心内存块-单端口RAM,宽32位,长1024。我敢肯定这不需要一个周期。当if语句执行错误时,从inst内存中提取inst的延迟在我的波形中是可见的,大约是100 ps,我的时钟周期现在是20 ns
always @(posedge clk) begin
  IR <= Instruction;
  PC <= nextPC;
end
always @(posedge clk) begin
  PC <= nextPC;
end

assign IR = Instruction;