OpenCores
URL https://opencores.org/ocsvn/mips32r1/mips32r1/trunk

Subversion Repositories mips32r1

[/] [mips32r1/] [trunk/] [Hardware/] [MIPS32_Standalone/] [MemControl.v] - Diff between revs 2 and 3

Only display areas with differences | Details | Blame | View Log

Rev 2 Rev 3
`timescale 1ns / 1ps
`timescale 1ns / 1ps
/*
/*
 * File         : MemControl.v
 * File         : MemControl.v
 * Project      : University of Utah, XUM Project MIPS32 core
 * Project      : University of Utah, XUM Project MIPS32 core
 * Creator(s)   : Grant Ayers (ayers@cs.utah.edu)
 * Creator(s)   : Grant Ayers (ayers@cs.utah.edu)
 *
 *
 * Modification History:
 * Modification History:
 *   Rev   Date         Initials  Description of Change
 *   Rev   Date         Initials  Description of Change
 *   1.0   24-Jun-2011  GEA       Initial design.
 *   1.0   24-Jun-2011  GEA       Initial design.
 *   2.0   28-Jun-2012  GEA       Expanded from a simple byte/half/word unit to
 *   2.0   28-Jun-2012  GEA       Expanded from a simple byte/half/word unit to
 *                                An advanced data memory controller capable of
 *                                An advanced data memory controller capable of
 *                                handling big/little endian, atomic and unaligned
 *                                handling big/little endian, atomic and unaligned
 *                                memory accesses.
 *                                memory accesses.
 *
 *
 * Standards/Formatting:
 * Standards/Formatting:
 *   Verilog 2001, 4 soft tab, wide column.
 *   Verilog 2001, 4 soft tab, wide column.
 *
 *
 * Description:
 * Description:
 *   A Data Memory Controller which handles all read and write requests from the
 *   A Data Memory Controller which handles all read and write requests from the
 *   processor to data memory. All data accesses--whether big endian, little endian,
 *   processor to data memory. All data accesses--whether big endian, little endian,
 *   byte, half, word, or unaligned transfers--are transformed into a simple read
 *   byte, half, word, or unaligned transfers--are transformed into a simple read
 *   and write command to data memory over a 32-bit data bus, where the read command
 *   and write command to data memory over a 32-bit data bus, where the read command
 *   is one bit and the write command is 4 bits, one for each byte in the 32-bit word.
 *   is one bit and the write command is 4 bits, one for each byte in the 32-bit word.
 */
 */
module MemControl(
module MemControl(
    input  clock,
    input  clock,
    input  reset,
    input  reset,
    input  [31:0] DataIn,           // Data from CPU
    input  [31:0] DataIn,           // Data from CPU
    input  [31:0] Address,          // From CPU
    input  [31:0] Address,          // From CPU
    input  [31:0] MReadData,        // Data from Memory
    input  [31:0] MReadData,        // Data from Memory
    input  MemRead,                 // Memory Read command from CPU
    input  MemRead,                 // Memory Read command from CPU
    input  MemWrite,                // Memory Write command from CPU
    input  MemWrite,                // Memory Write command from CPU
    input  DataMem_Ready,           // Ready signal from Memory
    input  DataMem_Ready,           // Ready signal from Memory
    input  Byte,                    // Load/Store is Byte (8-bit)
    input  Byte,                    // Load/Store is Byte (8-bit)
    input  Half,                    // Load/Store is Half (16-bit)
    input  Half,                    // Load/Store is Half (16-bit)
    input  SignExtend,              // Sub-word load should be sign extended
    input  SignExtend,              // Sub-word load should be sign extended
    input  KernelMode,              // (Exception logic)
    input  KernelMode,              // (Exception logic)
    input  ReverseEndian,           // Reverse Endian Memory for User Mode
    input  ReverseEndian,           // Reverse Endian Memory for User Mode
    input  LLSC,                    // (LLSC logic)
    input  LLSC,                    // (LLSC logic)
    input  ERET,                    // (LLSC logic)
    input  ERET,                    // (LLSC logic)
    input  Left,                    // Unaligned Load/Store Word Left
    input  Left,                    // Unaligned Load/Store Word Left
    input  Right,                   // Unaligned Load/Store Word Right
    input  Right,                   // Unaligned Load/Store Word Right
    input  M_Exception_Stall,
    input  M_Exception_Stall,
    input  IF_Stall,                // XXX Clean this up between this module and HAZ/FWD
    input  IF_Stall,                // XXX Clean this up between this module and HAZ/FWD
    output reg [31:0] DataOut,      // Data to CPU
    output reg [31:0] DataOut,      // Data to CPU
    output [31:0] MWriteData,       // Data to Memory
    output [31:0] MWriteData,       // Data to Memory
    output reg [3:0] WriteEnable,   // Write Enable to Memory for each of 4 bytes of Memory
    output reg [3:0] WriteEnable,   // Write Enable to Memory for each of 4 bytes of Memory
    output ReadEnable,              // Read Enable to Memory
    output ReadEnable,              // Read Enable to Memory
    output M_Stall,
    output M_Stall,
    output EXC_AdEL,                // Load Exception
    output EXC_AdEL,                // Load Exception
    output EXC_AdES                 // Store Exception
    output EXC_AdES                 // Store Exception
    );
    );
 
 
    `include "MIPS_Parameters.v"
    `include "MIPS_Parameters.v"
 
 
    /*** Reverse Endian Mode
    /*** Reverse Endian Mode
         Normal memory accesses in the processor are Big Endian. The endianness can be reversed
         Normal memory accesses in the processor are Big Endian. The endianness can be reversed
         to Little Endian in User Mode only.
         to Little Endian in User Mode only.
    */
    */
    wire BE = KernelMode | ~ReverseEndian;
    wire BE = KernelMode | ~ReverseEndian;
 
 
    /*** Indicator that the current memory reference must be word-aligned ***/
    /*** Indicator that the current memory reference must be word-aligned ***/
    wire Word = ~(Half | Byte | Left | Right);
    wire Word = ~(Half | Byte | Left | Right);
 
 
    // Exception Detection
    // Exception Detection
    wire EXC_KernelMem = ~KernelMode & (Address < UMem_Lower);
    wire EXC_KernelMem = ~KernelMode & (Address < UMem_Lower);
    wire EXC_Word = Word & (Address[1] | Address[0]);
    wire EXC_Word = Word & (Address[1] | Address[0]);
    wire EXC_Half = Half & Address[0];
    wire EXC_Half = Half & Address[0];
    assign EXC_AdEL = MemRead  & (EXC_KernelMem | EXC_Word | EXC_Half);
    assign EXC_AdEL = MemRead  & (EXC_KernelMem | EXC_Word | EXC_Half);
    assign EXC_AdES = MemWrite & (EXC_KernelMem | EXC_Word | EXC_Half);
    assign EXC_AdES = MemWrite & (EXC_KernelMem | EXC_Word | EXC_Half);
 
 
    /*** Load Linked and Store Conditional logic ***
    /*** Load Linked and Store Conditional logic ***
 
 
         A 32-bit register keeps track of the address for atomic Load Linked / Store Conditional
         A 32-bit register keeps track of the address for atomic Load Linked / Store Conditional
         operations. This register can be updated during stalls since it is not visible to
         operations. This register can be updated during stalls since it is not visible to
         forward stages. It does not need to be flushed during exceptions, since ERET destroys
         forward stages. It does not need to be flushed during exceptions, since ERET destroys
         the atomicity condition and there are no detrimental effects in an exception handler.
         the atomicity condition and there are no detrimental effects in an exception handler.
 
 
         The atomic condition is set with a Load Linked instruction, and cleared on an ERET
         The atomic condition is set with a Load Linked instruction, and cleared on an ERET
         instruction or when any store instruction writes to one or more bytes covered by
         instruction or when any store instruction writes to one or more bytes covered by
         the word address register. It does not update on a stall condition.
         the word address register. It does not update on a stall condition.
 
 
         The MIPS32 spec states that an ERET instruction between LL and SC will cause the
         The MIPS32 spec states that an ERET instruction between LL and SC will cause the
         atomicity condition to fail. This implementation uses the ERET signal from the ID
         atomicity condition to fail. This implementation uses the ERET signal from the ID
         stage, which means instruction sequences such as "LL SC" could appear to have an
         stage, which means instruction sequences such as "LL SC" could appear to have an
         ERET instruction between them even though they don't. One way to fix this is to pass
         ERET instruction between them even though they don't. One way to fix this is to pass
         the ERET signal through the pipeline to the MEM stage. However, because of the nature
         the ERET signal through the pipeline to the MEM stage. However, because of the nature
         of LL/SC operations (they occur in a loop which checks the result at each iteration),
         of LL/SC operations (they occur in a loop which checks the result at each iteration),
         an ERET will normally never be inserted into the pipeline programmatically until the
         an ERET will normally never be inserted into the pipeline programmatically until the
         LL/SC sequence has completed (exceptions such as interrupts can still cause ERET, but
         LL/SC sequence has completed (exceptions such as interrupts can still cause ERET, but
         they can still cause them in the LL SC sequence as well). In other words, by not passing
         they can still cause them in the LL SC sequence as well). In other words, by not passing
         ERET through the pipeline, the only possible effect is a performance penalty. Also this
         ERET through the pipeline, the only possible effect is a performance penalty. Also this
         may be irrelevant since currently ERET stalls for forward stages which can cause exceptions,
         may be irrelevant since currently ERET stalls for forward stages which can cause exceptions,
         which includes LL and SC.
         which includes LL and SC.
    */
    */
    reg  [29:0] LLSC_Address;
    reg  [29:0] LLSC_Address;
    reg  LLSC_Atomic;
    reg  LLSC_Atomic;
    wire LLSC_MemWrite_Mask;
    wire LLSC_MemWrite_Mask;
 
 
    always @(posedge clock) begin
    always @(posedge clock) begin
        LLSC_Address <= (reset) ? 30'b0 : (MemRead & LLSC) ? Address[31:2] : LLSC_Address;
        LLSC_Address <= (reset) ? 30'b0 : (MemRead & LLSC) ? Address[31:2] : LLSC_Address;
    end
    end
 
 
    always @(posedge clock) begin
    always @(posedge clock) begin
        if (reset) begin
        if (reset) begin
            LLSC_Atomic <= 0;
            LLSC_Atomic <= 0;
        end
        end
        else if (MemRead) begin
        else if (MemRead) begin
            LLSC_Atomic <= (LLSC) ? 1 : LLSC_Atomic;
            LLSC_Atomic <= (LLSC) ? 1 : LLSC_Atomic;
        end
        end
        // XXX GEA Bug for Ganesh: remove "& ~IF_Stall" from below, then SC will always fail:
        // XXX GEA Bug for Ganesh: remove "& ~IF_Stall" from below, then SC will always fail:
        else if (ERET | (~M_Stall & ~IF_Stall & MemWrite & (Address[31:2] == LLSC_Address))) begin
        else if (ERET | (~M_Stall & ~IF_Stall & MemWrite & (Address[31:2] == LLSC_Address))) begin
            LLSC_Atomic <= 0;
            LLSC_Atomic <= 0;
        end
        end
        else begin
        else begin
            LLSC_Atomic <= LLSC_Atomic;
            LLSC_Atomic <= LLSC_Atomic;
        end
        end
    end
    end
    assign LLSC_MemWrite_Mask = (LLSC & MemWrite & (~LLSC_Atomic | (Address[31:2] != LLSC_Address)));
    assign LLSC_MemWrite_Mask = (LLSC & MemWrite & (~LLSC_Atomic | (Address[31:2] != LLSC_Address)));
 
 
    wire WriteCondition = MemWrite & ~(EXC_KernelMem | EXC_Word | EXC_Half) & ~LLSC_MemWrite_Mask;
    wire WriteCondition = MemWrite & ~(EXC_KernelMem | EXC_Word | EXC_Half) & ~LLSC_MemWrite_Mask;
    wire ReadCondition  = MemRead  & ~(EXC_KernelMem | EXC_Word | EXC_Half);
    wire ReadCondition  = MemRead  & ~(EXC_KernelMem | EXC_Word | EXC_Half);
 
 
    reg RW_Mask;
    reg RW_Mask;
    always @(posedge clock) begin
    always @(posedge clock) begin
        RW_Mask <= (reset) ? 0 : (((MemWrite | MemRead) & DataMem_Ready) ? 1 : ((~M_Stall & ~IF_Stall) ? 0 : RW_Mask));
        RW_Mask <= (reset) ? 0 : (((MemWrite | MemRead) & DataMem_Ready) ? 1 : ((~M_Stall & ~IF_Stall) ? 0 : RW_Mask));
    end
    end
    assign M_Stall = ReadEnable | (WriteEnable != 4'b0000) | DataMem_Ready    | M_Exception_Stall;
    assign M_Stall = ReadEnable | (WriteEnable != 4'b0000) | DataMem_Ready    | M_Exception_Stall;
    assign ReadEnable  = ReadCondition  & ~RW_Mask;
    assign ReadEnable  = ReadCondition  & ~RW_Mask;
 
 
    wire Half_Access_L  = (Address[1] ^  BE);
    wire Half_Access_L  = (Address[1] ^  BE);
    wire Half_Access_R  = (Address[1] ~^ BE);
    wire Half_Access_R  = (Address[1] ~^ BE);
    wire Byte_Access_LL = Half_Access_L & (Address[1] ~^ Address[0]);
    wire Byte_Access_LL = Half_Access_L & (Address[1] ~^ Address[0]);
    wire Byte_Access_LM = Half_Access_L & (Address[0] ~^ BE);
    wire Byte_Access_LM = Half_Access_L & (Address[0] ~^ BE);
    wire Byte_Access_RM = Half_Access_R & (Address[0] ^  BE);
    wire Byte_Access_RM = Half_Access_R & (Address[0] ^  BE);
    wire Byte_Access_RR = Half_Access_R & (Address[1] ~^ Address[0]);
    wire Byte_Access_RR = Half_Access_R & (Address[1] ~^ Address[0]);
 
 
    // Write-Enable Signals to Memory
    // Write-Enable Signals to Memory
    always @(*) begin
    always @(*) begin
        if (WriteCondition & ~RW_Mask) begin
        if (WriteCondition & ~RW_Mask) begin
            if (Byte) begin
            if (Byte) begin
                WriteEnable[3] <= Byte_Access_LL;
                WriteEnable[3] <= Byte_Access_LL;
                WriteEnable[2] <= Byte_Access_LM;
                WriteEnable[2] <= Byte_Access_LM;
                WriteEnable[1] <= Byte_Access_RM;
                WriteEnable[1] <= Byte_Access_RM;
                WriteEnable[0] <= Byte_Access_RR;
                WriteEnable[0] <= Byte_Access_RR;
            end
            end
            else if (Half) begin
            else if (Half) begin
                WriteEnable[3] <= Half_Access_L;
                WriteEnable[3] <= Half_Access_L;
                WriteEnable[2] <= Half_Access_L;
                WriteEnable[2] <= Half_Access_L;
                WriteEnable[1] <= Half_Access_R;
                WriteEnable[1] <= Half_Access_R;
                WriteEnable[0] <= Half_Access_R;
                WriteEnable[0] <= Half_Access_R;
            end
            end
            else if (Left) begin
            else if (Left) begin
                case (Address[1:0])
                case (Address[1:0])
                    2'b00 : WriteEnable <= (BE) ? 4'b1111 : 4'b0001;
                    2'b00 : WriteEnable <= (BE) ? 4'b1111 : 4'b0001;
                    2'b01 : WriteEnable <= (BE) ? 4'b0111 : 4'b0011;
                    2'b01 : WriteEnable <= (BE) ? 4'b0111 : 4'b0011;
                    2'b10 : WriteEnable <= (BE) ? 4'b0011 : 4'b0111;
                    2'b10 : WriteEnable <= (BE) ? 4'b0011 : 4'b0111;
                    2'b11 : WriteEnable <= (BE) ? 4'b0001 : 4'b1111;
                    2'b11 : WriteEnable <= (BE) ? 4'b0001 : 4'b1111;
                endcase
                endcase
            end
            end
            else if (Right) begin
            else if (Right) begin
                case (Address[1:0])
                case (Address[1:0])
                    2'b00 : WriteEnable <= (BE) ? 4'b1000 : 4'b1111;
                    2'b00 : WriteEnable <= (BE) ? 4'b1000 : 4'b1111;
                    2'b01 : WriteEnable <= (BE) ? 4'b1100 : 4'b1110;
                    2'b01 : WriteEnable <= (BE) ? 4'b1100 : 4'b1110;
                    2'b10 : WriteEnable <= (BE) ? 4'b1110 : 4'b1100;
                    2'b10 : WriteEnable <= (BE) ? 4'b1110 : 4'b1100;
                    2'b11 : WriteEnable <= (BE) ? 4'b1111 : 4'b1000;
                    2'b11 : WriteEnable <= (BE) ? 4'b1111 : 4'b1000;
                endcase
                endcase
            end
            end
            else begin
            else begin
                WriteEnable <= 4'b1111;
                WriteEnable <= 4'b1111;
            end
            end
        end
        end
        else begin
        else begin
            WriteEnable <= 4'b0000;
            WriteEnable <= 4'b0000;
        end
        end
    end
    end
 
 
    // Data Going to Memory
    // Data Going to Memory
    assign MWriteData[31:24] = (Byte) ? DataIn[7:0] : ((Half) ? DataIn[15:8] : DataIn[31:24]);
    assign MWriteData[31:24] = (Byte) ? DataIn[7:0] : ((Half) ? DataIn[15:8] : DataIn[31:24]);
    assign MWriteData[23:16] = (Byte | Half) ? DataIn[7:0] : DataIn[23:16];
    assign MWriteData[23:16] = (Byte | Half) ? DataIn[7:0] : DataIn[23:16];
    assign MWriteData[15:8]  = (Byte) ? DataIn[7:0] : DataIn[15:8];
    assign MWriteData[15:8]  = (Byte) ? DataIn[7:0] : DataIn[15:8];
    assign MWriteData[7:0]   = DataIn[7:0];
    assign MWriteData[7:0]   = DataIn[7:0];
 
 
    // Data Read from Memory
    // Data Read from Memory
    always @(*) begin
    always @(*) begin
        if (Byte) begin
        if (Byte) begin
            if (Byte_Access_LL) begin
            if (Byte_Access_LL) begin
                DataOut <= (SignExtend & MReadData[31]) ? {24'hFFFFFF, MReadData[31:24]} : {24'h000000, MReadData[31:24]};
                DataOut <= (SignExtend & MReadData[31]) ? {24'hFFFFFF, MReadData[31:24]} : {24'h000000, MReadData[31:24]};
            end
            end
            else if (Byte_Access_LM) begin
            else if (Byte_Access_LM) begin
                DataOut <= (SignExtend & MReadData[23]) ? {24'hFFFFFF, MReadData[23:16]} : {24'h000000, MReadData[23:16]};
                DataOut <= (SignExtend & MReadData[23]) ? {24'hFFFFFF, MReadData[23:16]} : {24'h000000, MReadData[23:16]};
            end
            end
            else if (Byte_Access_RM) begin
            else if (Byte_Access_RM) begin
                DataOut <= (SignExtend & MReadData[15]) ? {24'hFFFFFF, MReadData[15:8]}  : {24'h000000, MReadData[15:8]};
                DataOut <= (SignExtend & MReadData[15]) ? {24'hFFFFFF, MReadData[15:8]}  : {24'h000000, MReadData[15:8]};
            end
            end
            else begin
            else begin
                DataOut <= (SignExtend & MReadData[7])  ? {24'hFFFFFF, MReadData[7:0]}   : {24'h000000, MReadData[7:0]};
                DataOut <= (SignExtend & MReadData[7])  ? {24'hFFFFFF, MReadData[7:0]}   : {24'h000000, MReadData[7:0]};
            end
            end
        end
        end
        else if (Half) begin
        else if (Half) begin
            if (Half_Access_L) begin
            if (Half_Access_L) begin
                DataOut <= (SignExtend & MReadData[31]) ? {16'hFFFF, MReadData[31:16]} : {16'h0000, MReadData[31:16]};
                DataOut <= (SignExtend & MReadData[31]) ? {16'hFFFF, MReadData[31:16]} : {16'h0000, MReadData[31:16]};
            end
            end
            else begin
            else begin
                DataOut <= (SignExtend & MReadData[15]) ? {16'hFFFF, MReadData[15:0]}  : {16'h0000, MReadData[15:0]};
                DataOut <= (SignExtend & MReadData[15]) ? {16'hFFFF, MReadData[15:0]}  : {16'h0000, MReadData[15:0]};
            end
            end
        end
        end
        else if (LLSC & MemWrite) begin
        else if (LLSC & MemWrite) begin
            DataOut <= (LLSC_Atomic & (Address[31:2] == LLSC_Address)) ? 32'h0000_0001 : 32'h0000_0000;
            DataOut <= (LLSC_Atomic & (Address[31:2] == LLSC_Address)) ? 32'h0000_0001 : 32'h0000_0000;
        end
        end
        else if (Left) begin
        else if (Left) begin
            case (Address[1:0])
            case (Address[1:0])
                2'b00 : DataOut <= (BE) ?  MReadData                      : {MReadData[7:0],  DataIn[23:0]};
                2'b00 : DataOut <= (BE) ?  MReadData                      : {MReadData[7:0],  DataIn[23:0]};
                2'b01 : DataOut <= (BE) ? {MReadData[23:0], DataIn[7:0]}  : {MReadData[15:0], DataIn[15:0]};
                2'b01 : DataOut <= (BE) ? {MReadData[23:0], DataIn[7:0]}  : {MReadData[15:0], DataIn[15:0]};
                2'b10 : DataOut <= (BE) ? {MReadData[15:0], DataIn[15:0]} : {MReadData[23:0], DataIn[7:0]};
                2'b10 : DataOut <= (BE) ? {MReadData[15:0], DataIn[15:0]} : {MReadData[23:0], DataIn[7:0]};
                2'b11 : DataOut <= (BE) ? {MReadData[7:0],  DataIn[23:0]} :  MReadData;
                2'b11 : DataOut <= (BE) ? {MReadData[7:0],  DataIn[23:0]} :  MReadData;
            endcase
            endcase
        end
        end
        else if (Right) begin
        else if (Right) begin
            case (Address[1:0])
            case (Address[1:0])
                2'b00 : DataOut <= (BE) ? {DataIn[31:8],  MReadData[31:24]} : MReadData;
                2'b00 : DataOut <= (BE) ? {DataIn[31:8],  MReadData[31:24]} : MReadData;
                2'b01 : DataOut <= (BE) ? {DataIn[31:16], MReadData[31:16]} : {DataIn[31:24], MReadData[31:8]};
                2'b01 : DataOut <= (BE) ? {DataIn[31:16], MReadData[31:16]} : {DataIn[31:24], MReadData[31:8]};
                2'b10 : DataOut <= (BE) ? {DataIn[31:24], MReadData[31:8]}  : {DataIn[31:16], MReadData[31:16]};
                2'b10 : DataOut <= (BE) ? {DataIn[31:24], MReadData[31:8]}  : {DataIn[31:16], MReadData[31:16]};
                2'b11 : DataOut <= (BE) ? MReadData                         : {DataIn[31:8],  MReadData[31:24]};
                2'b11 : DataOut <= (BE) ? MReadData                         : {DataIn[31:8],  MReadData[31:24]};
            endcase
            endcase
        end
        end
        else begin
        else begin
            DataOut <= MReadData;
            DataOut <= MReadData;
        end
        end
    end
    end
 
 
endmodule
endmodule
 
 
 No newline at end of file
 No newline at end of file
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.