Search code examples
verilogfpgaquartusintel-fpga

Weird behavior of registers on Quartus II using Verilog


I'm creating my own processor based on MIPS32 using the Quartus II and Verilog. Everything was working fine until suddenly my Registers stopped working (I don't remember making any modifications to the code). I probably made some mistake but I can't seem to find it.

I've already tried using an older version of the code (that was 100% working) but the error persists, even when I'm testing the registers isolated from the rest of the system. I've also tried deleting Quartus' temporary files and recompiling with no success.

    module RegFile
    (
        output [31:0] Debug2,       //Outputs Reg 2
        output [31:0] Debug3,       //Outputs Reg 3
        input Reset,                //Makes sure Reg 0 is always 0
        input Slow_Clock,           //Write Clock
        input Fast_Clock,           //Read Clock
        input Reg_Write,            //Write to Reg Flag
        input [31:0] Write_Data,    //Data that will be written in the Reg selected by Reg_WR
        input [5:0] Reg_1,          //First Register Selection (Read)
        input [5:0] Reg_2,          //Second Register Selection (Read)
        input [5:0] Reg_WR,         //Third Register Selection (Read or Write)
        output reg [31:0] Data_1,   //Data that will outputted by the Reg selected by Reg_1
        output reg [31:0] Data_2,   //Data that will outputted by the Reg selected by Reg_2
        output reg [31:0] Data_3    //Data that will outputted by the Reg selected by Reg_WR
    );


    reg [31:0] DataReg[63:0];       //64x 32bit Register

    assign Debug2 = DataReg[2]; //Hardwired Reg2 (for testing)
    assign Debug3 = DataReg[3]; //Hardwired Reg3 (for testing)

    always @ (posedge Fast_Clock)   //Reads from Registers at posedge Read Clock
    begin
        Data_1 <= DataReg[Reg_1];
        Data_2 <= DataReg[Reg_2];
        Data_3 <= DataReg[Reg_WR];
    end

    always @ (negedge Slow_Clock) //Writes on Registers at negedge Write Clock
    begin
        if (Reset)
        begin
            DataReg[0] <= 32'b00000000_00000000_00000000_00000000; //Forces Reg0 to be 0 when Reset is activated
        end
        else if (Reg_Write && (Reg_WR != 0)) //If you are writing to some register and this register isn't Reg0...
        begin
            DataReg[Reg_WR] <= Write_Data; //...write to the register selected by Reg_WR
        end
    end

    endmodule

Waveform 1

Waveform 2

I expect the ending result to be the number 3 on register 2 and the number 4 on register 3 but, as you can see, register 2 ends with the number 4 and the register 3 ends with the number 0.


Solution

  • I figured it out.

    There was an inconsistency when writing and loading the new values in the next clock.

    I fixed it by creating two aux. variables that hold Write_Data and Reg_WR until right before writing and updating the values. I used a faster clock to be able to keep these aux. variables updated.

    This is the solution I found:

    module RegFile
    (
        //output [31:0] Debug2,       //Outputs Reg 2
        output [31:0] Debug3,       //Outputs Reg 3
        input Reset,                //Makes sure Reg 0 is always 0
        input Slow_Clock,             //Write Clock
        input Fast_Clock,
         input Reg_Write,            //Write to Reg Flag
        input [31:0] Write_Data,    //Data that will be written in the Reg selected by Reg_WR
        input [5:0] Reg_1,          //First Register Selection (Read)
        input [5:0] Reg_2,          //Second Register Selection (Read)
        input [5:0] Reg_WR,         //Third Register Selection (Read or Write)
        output [31:0] Data_1,         //Data that will outputted by the Reg selected by Reg_1
        output [31:0] Data_2,       //Data that will outputted by the Reg selected by Reg_2
        output [31:0] Data_3        //Data that will outputted by the Reg selected by Reg_WR
    );
    
    reg [31:0] RegBank[63:0];
    
    reg [31:0] Aux_WD;
    reg [5:0] Aux_Reg;
    
    assign Data_1 = RegBank[Reg_1];
    assign Data_2 = RegBank[Reg_2];
    assign Data_3 = RegBank[Reg_WR];
    
    //assign Debug2 = RegBank[2];
    assign Debug3 = RegBank[3];
    
    always @ (negedge Fast_Clock)
    begin
        Aux_WD <= Write_Data;
        Aux_Reg <= Reg_WR;
    end
    
    always @ (negedge Slow_Clock)
    begin
        if (Reset)
        begin
            RegBank[0] <= {32{1'b0}};
        end
        else if (Reg_Write && (Aux_Reg != 6'b000000))
        begin
            RegBank[Aux_Reg] <= Aux_WD;
        end
    end
    
    endmodule