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

Subversion Repositories mips32r1

[/] [mips32r1/] [trunk/] [Hardware/] [MIPS32_Standalone/] [MemControl.v] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 ayersg
`timescale 1ns / 1ps
2
/*
3
 * File         : MemControl.v
4
 * Project      : University of Utah, XUM Project MIPS32 core
5
 * Creator(s)   : Grant Ayers (ayers@cs.utah.edu)
6
 *
7
 * Modification History:
8
 *   Rev   Date         Initials  Description of Change
9
 *   1.0   24-Jun-2011  GEA       Initial design.
10
 *   2.0   28-Jun-2012  GEA       Expanded from a simple byte/half/word unit to
11
 *                                An advanced data memory controller capable of
12
 *                                handling big/little endian, atomic and unaligned
13
 *                                memory accesses.
14
 *
15
 * Standards/Formatting:
16
 *   Verilog 2001, 4 soft tab, wide column.
17
 *
18
 * Description:
19
 *   A Data Memory Controller which handles all read and write requests from the
20
 *   processor to data memory. All data accesses--whether big endian, little endian,
21
 *   byte, half, word, or unaligned transfers--are transformed into a simple read
22
 *   and write command to data memory over a 32-bit data bus, where the read command
23
 *   is one bit and the write command is 4 bits, one for each byte in the 32-bit word.
24
 */
25
module MemControl(
26
    input  clock,
27
    input  reset,
28
    input  [31:0] DataIn,           // Data from CPU
29
    input  [31:0] Address,          // From CPU
30
    input  [31:0] MReadData,        // Data from Memory
31
    input  MemRead,                 // Memory Read command from CPU
32
    input  MemWrite,                // Memory Write command from CPU
33
    input  DataMem_Ready,           // Ready signal from Memory
34
    input  Byte,                    // Load/Store is Byte (8-bit)
35
    input  Half,                    // Load/Store is Half (16-bit)
36
    input  SignExtend,              // Sub-word load should be sign extended
37
    input  KernelMode,              // (Exception logic)
38
    input  ReverseEndian,           // Reverse Endian Memory for User Mode
39
    input  LLSC,                    // (LLSC logic)
40
    input  ERET,                    // (LLSC logic)
41
    input  Left,                    // Unaligned Load/Store Word Left
42
    input  Right,                   // Unaligned Load/Store Word Right
43
    input  M_Exception_Stall,
44
    input  IF_Stall,                // XXX Clean this up between this module and HAZ/FWD
45
    output reg [31:0] DataOut,      // Data to CPU
46
    output [31:0] MWriteData,       // Data to Memory
47
    output reg [3:0] WriteEnable,   // Write Enable to Memory for each of 4 bytes of Memory
48
    output ReadEnable,              // Read Enable to Memory
49
    output M_Stall,
50
    output EXC_AdEL,                // Load Exception
51
    output EXC_AdES                 // Store Exception
52
    );
53
 
54
    `include "MIPS_Parameters.v"
55
 
56
    /*** Reverse Endian Mode
57
         Normal memory accesses in the processor are Big Endian. The endianness can be reversed
58
         to Little Endian in User Mode only.
59
    */
60
    wire BE = KernelMode | ~ReverseEndian;
61
 
62
    /*** Indicator that the current memory reference must be word-aligned ***/
63
    wire Word = ~(Half | Byte | Left | Right);
64
 
65
    // Exception Detection
66
    wire EXC_KernelMem = ~KernelMode & (Address < UMem_Lower);
67
    wire EXC_Word = Word & (Address[1] | Address[0]);
68
    wire EXC_Half = Half & Address[0];
69
    assign EXC_AdEL = MemRead  & (EXC_KernelMem | EXC_Word | EXC_Half);
70
    assign EXC_AdES = MemWrite & (EXC_KernelMem | EXC_Word | EXC_Half);
71
 
72
    /*** Load Linked and Store Conditional logic ***
73
 
74
         A 32-bit register keeps track of the address for atomic Load Linked / Store Conditional
75
         operations. This register can be updated during stalls since it is not visible to
76
         forward stages. It does not need to be flushed during exceptions, since ERET destroys
77
         the atomicity condition and there are no detrimental effects in an exception handler.
78
 
79
         The atomic condition is set with a Load Linked instruction, and cleared on an ERET
80
         instruction or when any store instruction writes to one or more bytes covered by
81
         the word address register. It does not update on a stall condition.
82
 
83
         The MIPS32 spec states that an ERET instruction between LL and SC will cause the
84
         atomicity condition to fail. This implementation uses the ERET signal from the ID
85
         stage, which means instruction sequences such as "LL SC" could appear to have an
86
         ERET instruction between them even though they don't. One way to fix this is to pass
87
         the ERET signal through the pipeline to the MEM stage. However, because of the nature
88
         of LL/SC operations (they occur in a loop which checks the result at each iteration),
89
         an ERET will normally never be inserted into the pipeline programmatically until the
90
         LL/SC sequence has completed (exceptions such as interrupts can still cause ERET, but
91
         they can still cause them in the LL SC sequence as well). In other words, by not passing
92
         ERET through the pipeline, the only possible effect is a performance penalty. Also this
93
         may be irrelevant since currently ERET stalls for forward stages which can cause exceptions,
94
         which includes LL and SC.
95
    */
96
    reg  [29:0] LLSC_Address;
97
    reg  LLSC_Atomic;
98
    wire LLSC_MemWrite_Mask;
99
 
100
    always @(posedge clock) begin
101
        LLSC_Address <= (reset) ? 30'b0 : (MemRead & LLSC) ? Address[31:2] : LLSC_Address;
102
    end
103
 
104
    always @(posedge clock) begin
105
        if (reset) begin
106
            LLSC_Atomic <= 0;
107
        end
108
        else if (MemRead) begin
109
            LLSC_Atomic <= (LLSC) ? 1 : LLSC_Atomic;
110
        end
111
        // XXX GEA Bug for Ganesh: remove "& ~IF_Stall" from below, then SC will always fail:
112
        else if (ERET | (~M_Stall & ~IF_Stall & MemWrite & (Address[31:2] == LLSC_Address))) begin
113
            LLSC_Atomic <= 0;
114
        end
115
        else begin
116
            LLSC_Atomic <= LLSC_Atomic;
117
        end
118
    end
119
    assign LLSC_MemWrite_Mask = (LLSC & MemWrite & (~LLSC_Atomic | (Address[31:2] != LLSC_Address)));
120
 
121
    wire WriteCondition = MemWrite & ~(EXC_KernelMem | EXC_Word | EXC_Half) & ~LLSC_MemWrite_Mask;
122
    wire ReadCondition  = MemRead  & ~(EXC_KernelMem | EXC_Word | EXC_Half);
123
 
124
    reg RW_Mask;
125
    always @(posedge clock) begin
126
        RW_Mask <= (reset) ? 0 : (((MemWrite | MemRead) & DataMem_Ready) ? 1 : ((~M_Stall & ~IF_Stall) ? 0 : RW_Mask));
127
    end
128
    assign M_Stall = ReadEnable | (WriteEnable != 4'b0000) | DataMem_Ready    | M_Exception_Stall;
129
    assign ReadEnable  = ReadCondition  & ~RW_Mask;
130
 
131
    wire Half_Access_L  = (Address[1] ^  BE);
132
    wire Half_Access_R  = (Address[1] ~^ BE);
133
    wire Byte_Access_LL = Half_Access_L & (Address[1] ~^ Address[0]);
134
    wire Byte_Access_LM = Half_Access_L & (Address[0] ~^ BE);
135
    wire Byte_Access_RM = Half_Access_R & (Address[0] ^  BE);
136
    wire Byte_Access_RR = Half_Access_R & (Address[1] ~^ Address[0]);
137
 
138
    // Write-Enable Signals to Memory
139
    always @(*) begin
140
        if (WriteCondition & ~RW_Mask) begin
141
            if (Byte) begin
142
                WriteEnable[3] <= Byte_Access_LL;
143
                WriteEnable[2] <= Byte_Access_LM;
144
                WriteEnable[1] <= Byte_Access_RM;
145
                WriteEnable[0] <= Byte_Access_RR;
146
            end
147
            else if (Half) begin
148
                WriteEnable[3] <= Half_Access_L;
149
                WriteEnable[2] <= Half_Access_L;
150
                WriteEnable[1] <= Half_Access_R;
151
                WriteEnable[0] <= Half_Access_R;
152
            end
153
            else if (Left) begin
154
                case (Address[1:0])
155
                    2'b00 : WriteEnable <= (BE) ? 4'b1111 : 4'b0001;
156
                    2'b01 : WriteEnable <= (BE) ? 4'b0111 : 4'b0011;
157
                    2'b10 : WriteEnable <= (BE) ? 4'b0011 : 4'b0111;
158
                    2'b11 : WriteEnable <= (BE) ? 4'b0001 : 4'b1111;
159
                endcase
160
            end
161
            else if (Right) begin
162
                case (Address[1:0])
163
                    2'b00 : WriteEnable <= (BE) ? 4'b1000 : 4'b1111;
164
                    2'b01 : WriteEnable <= (BE) ? 4'b1100 : 4'b1110;
165
                    2'b10 : WriteEnable <= (BE) ? 4'b1110 : 4'b1100;
166
                    2'b11 : WriteEnable <= (BE) ? 4'b1111 : 4'b1000;
167
                endcase
168
            end
169
            else begin
170
                WriteEnable <= 4'b1111;
171
            end
172
        end
173
        else begin
174
            WriteEnable <= 4'b0000;
175
        end
176
    end
177
 
178
    // Data Going to Memory
179
    assign MWriteData[31:24] = (Byte) ? DataIn[7:0] : ((Half) ? DataIn[15:8] : DataIn[31:24]);
180
    assign MWriteData[23:16] = (Byte | Half) ? DataIn[7:0] : DataIn[23:16];
181
    assign MWriteData[15:8]  = (Byte) ? DataIn[7:0] : DataIn[15:8];
182
    assign MWriteData[7:0]   = DataIn[7:0];
183
 
184
    // Data Read from Memory
185
    always @(*) begin
186
        if (Byte) begin
187
            if (Byte_Access_LL) begin
188
                DataOut <= (SignExtend & MReadData[31]) ? {24'hFFFFFF, MReadData[31:24]} : {24'h000000, MReadData[31:24]};
189
            end
190
            else if (Byte_Access_LM) begin
191
                DataOut <= (SignExtend & MReadData[23]) ? {24'hFFFFFF, MReadData[23:16]} : {24'h000000, MReadData[23:16]};
192
            end
193
            else if (Byte_Access_RM) begin
194
                DataOut <= (SignExtend & MReadData[15]) ? {24'hFFFFFF, MReadData[15:8]}  : {24'h000000, MReadData[15:8]};
195
            end
196
            else begin
197
                DataOut <= (SignExtend & MReadData[7])  ? {24'hFFFFFF, MReadData[7:0]}   : {24'h000000, MReadData[7:0]};
198
            end
199
        end
200
        else if (Half) begin
201
            if (Half_Access_L) begin
202
                DataOut <= (SignExtend & MReadData[31]) ? {16'hFFFF, MReadData[31:16]} : {16'h0000, MReadData[31:16]};
203
            end
204
            else begin
205
                DataOut <= (SignExtend & MReadData[15]) ? {16'hFFFF, MReadData[15:0]}  : {16'h0000, MReadData[15:0]};
206
            end
207
        end
208
        else if (LLSC & MemWrite) begin
209
            DataOut <= (LLSC_Atomic & (Address[31:2] == LLSC_Address)) ? 32'h0000_0001 : 32'h0000_0000;
210
        end
211
        else if (Left) begin
212
            case (Address[1:0])
213
                2'b00 : DataOut <= (BE) ?  MReadData                      : {MReadData[7:0],  DataIn[23:0]};
214
                2'b01 : DataOut <= (BE) ? {MReadData[23:0], DataIn[7:0]}  : {MReadData[15:0], DataIn[15:0]};
215
                2'b10 : DataOut <= (BE) ? {MReadData[15:0], DataIn[15:0]} : {MReadData[23:0], DataIn[7:0]};
216
                2'b11 : DataOut <= (BE) ? {MReadData[7:0],  DataIn[23:0]} :  MReadData;
217
            endcase
218
        end
219
        else if (Right) begin
220
            case (Address[1:0])
221
                2'b00 : DataOut <= (BE) ? {DataIn[31:8],  MReadData[31:24]} : MReadData;
222
                2'b01 : DataOut <= (BE) ? {DataIn[31:16], MReadData[31:16]} : {DataIn[31:24], MReadData[31:8]};
223
                2'b10 : DataOut <= (BE) ? {DataIn[31:24], MReadData[31:8]}  : {DataIn[31:16], MReadData[31:16]};
224
                2'b11 : DataOut <= (BE) ? MReadData                         : {DataIn[31:8],  MReadData[31:24]};
225
            endcase
226
        end
227
        else begin
228
            DataOut <= MReadData;
229
        end
230
    end
231
 
232
endmodule
233 3 ayersg
 

powered by: WebSVN 2.1.0

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