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

Subversion Repositories theia_gpu

[/] [theia_gpu/] [trunk/] [rtl/] [Unit_MEM.v] - Blame information for rev 224

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 152 diegovalve
`timescale 1ns / 1ps
2
`include "aDefinitions.v"
3
/**********************************************************************************
4
Theia, Ray Cast Programable graphic Processing Unit.
5
Copyright (C) 2010  Diego Valverde (diego.valverde.g@gmail.com)
6
 
7
This program is free software; you can redistribute it and/or
8
modify it under the terms of the GNU General Public License
9
as published by the Free Software Foundation; either version 2
10
of the License, or (at your option) any later version.
11
 
12
This program is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
GNU General Public License for more details.
16
 
17
You should have received a copy of the GNU General Public License
18
along with this program; if not, write to the Free Software
19
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20
 
21
***********************************************************************************/
22
/*
23
The memory unit has all the memory related modules for THEIA.
24
There a 3 memories in the core:
25
DMEM: The data memory, it is a R/W dual channel RAM, stores the data locations.
26
IMEM: The instruction memory, R/W dual channel RAM, stores user shaders.
27
IROM: RO instruction memory, stores default shaders and other internal code.
28
I use two ROMs with the same data, so that simulates dual channel.
29
This unit also has a Control register.
30
*/
31
`define USER_CODE_ENABLED 2
32
//-------------------------------------------------------------------
33
module MemoryUnit
34
(
35
input wire                              Clock,
36
input wire                              Reset,
37
input wire                                  iFlipMemory,
38
 
39
//Data bus for EXE Unit
40
input wire                              iDataWriteEnable_EXE,
41
input wire[`DATA_ADDRESS_WIDTH-1:0]     iDataReadAddress1_EXE,
42
output wire[`DATA_ROW_WIDTH-1:0]        oData1_EXE,
43
input wire[`DATA_ADDRESS_WIDTH-1:0]     iDataReadAddress2_EXE,
44
output wire[`DATA_ROW_WIDTH-1:0]        oData2_EXE,
45
input wire[`DATA_ADDRESS_WIDTH-1:0]     iDataWriteAddress_EXE,
46
input wire[`DATA_ROW_WIDTH-1:0]         iData_EXE,
47
 
48
//Data bus for IO Unit
49
input wire                              iDataWriteEnable_IO,
50
input wire[`DATA_ADDRESS_WIDTH-1:0]     iDataReadAddress1_IO,
51
output wire[`DATA_ROW_WIDTH-1:0]        oData1_IO,
52
input wire[`DATA_ADDRESS_WIDTH-1:0]     iDataReadAddress2_IO,
53
output wire[`DATA_ROW_WIDTH-1:0]        oData2_IO,
54
input wire[`DATA_ADDRESS_WIDTH-1:0]     iDataWriteAddress_IO,
55
input wire[`DATA_ROW_WIDTH-1:0]         iData_IO,
56
 
57
//Instruction bus
58
input wire                              iInstructionWriteEnable,
59
input  wire [`ROM_ADDRESS_WIDTH-1:0]    iInstructionReadAddress1,
60
input  wire [`ROM_ADDRESS_WIDTH-1:0]    iInstructionReadAddress2,
61
input wire [`ROM_ADDRESS_WIDTH-1:0]     iInstructionWriteAddress,
62
input wire [`INSTRUCTION_WIDTH-1:0]     iInstruction,
63
output wire [`INSTRUCTION_WIDTH-1:0]    oInstruction1,
64
output wire [`INSTRUCTION_WIDTH-1:0]    oInstruction2,
65
 
66
`ifdef DEBUG
67
input wire [`MAX_CORES-1:0]            iDebug_CoreID,
68
`endif
69
 
70
 
71
//Control Register
72
input wire[15:0]                       iControlRegister,
73
output wire[15:0]                       oControlRegister
74
 
75
 
76
);
77
 
78
wire [`ROM_ADDRESS_WIDTH-1:0] wROMInstructionAddress,wRAMInstructionAddress;
79
wire [`INSTRUCTION_WIDTH-1:0] wIMEM2_IMUX__DataOut1,wIMEM2_IMUX__DataOut2,
80
wIROM2_IMUX__DataOut1,wIROM2_IMUX__DataOut2;
81
wire wFlipSelect;
82
 
83
wire wInstructionSelector,wInstructionSelector2;
84
FFD_POSEDGE_SYNCRONOUS_RESET # ( 1 ) FFD1
85
(
86
        .Clock(Clock),
87
        .Reset(Reset),
88
        .Enable( 1'b1 ),
89
        .D( iInstructionReadAddress1[`ROM_ADDRESS_WIDTH-1]  ),
90
        .Q( wInstructionSelector )
91
);
92
 
93
FFD_POSEDGE_SYNCRONOUS_RESET # ( 1 ) FFD2
94
(
95
        .Clock(Clock),
96
        .Reset(Reset),
97
        .Enable( 1'b1 ),
98
        .D( iInstructionReadAddress2[`ROM_ADDRESS_WIDTH-1]  ),
99
        .Q( wInstructionSelector2 )
100
);
101
 
102
assign oInstruction1 = (wInstructionSelector == 1) ?
103
        wIMEM2_IMUX__DataOut1 : wIROM2_IMUX__DataOut1;
104
 
105
 
106
assign oInstruction2 = (wInstructionSelector2 == 1) ?
107
        wIMEM2_IMUX__DataOut2 : wIROM2_IMUX__DataOut2;
108
//-------------------------------------------------------------------
109
 
110
wire wDataWriteEnable_RMEM,wDataWriteEnable_SMEM,wDataWriteEnable_XMEM;
111
wire [`DATA_ROW_WIDTH-1:0] wData_SMEM1,wData_SMEM2;
112
wire [`DATA_ROW_WIDTH-1:0] wData_RMEM1,wData_RMEM2,wData_IMEM1,wData_IMEM2,wData_XMEM1,wData_XMEM2;
113
wire [`DATA_ROW_WIDTH-1:0] wIOData_SMEM1,wIOData_SMEM2;//,wData_OMEM1,wData_OMEM2;
114
 
115
/*******************************************************
116
The Data memory is divided into several memory banks.
117
Each Bank has different characteristics:
118
 
119
* IO MEM: Input Registers, Written by IO, Read by EXE.
120
* SWAP MEM: Swap registers, while IO reads/write values,
121
  EXE reads/write values.
122
* C1-C7, R1- R12: General purpose registers,
123
  EXE can R/W, IO can not see these sections of the memory
124
* OREG*: Output registers written by EXE, Read by IO.
125
 
126
Whenever an input address is received, this imput address
127
is divided in a bank selector and offset in the following way:
128
 
129
  __________________________
130
  | b6 b5 | b4 b3 b2 b1 b0 |
131
 
132
The bits b4 .. b0 are the LSB of the address, this give the
133
position relative to the bank
134
 
135
The bits b6 and b5 give the actual Bank to select.
136
Please see aDefinitions.v for a description of each
137
register location.
138
 
139
       0____________________
140
        |      IO MEM      |
141
        |                  |
142
        |                  | b6b5 = 00
143
      32|__________________|
144
        |     SWAP MEM     |
145
        |                  | b6b5 = 01
146
        |                  |
147
      64|__________________|
148
        |     C1 - C7      |
149
        |     R1 - R12     | b6b5 = 10
150
        |                  |
151
      96|__________________|
152
        |     CREG*        |
153
        |                  | b6b5 = 11
154
        |                  |
155
        |__________________|
156
 
157
 
158
*******************************************************/
159
 
160
 
161
 
162
MUXFULLPARALELL_2SEL_GENERIC # ( `DATA_ROW_WIDTH ) MUX1
163
 (
164
 .Sel( iDataReadAddress1_EXE[6:5] ),
165
 .I1( wData_IMEM1                ), //IO MEM
166
 .I2( wData_SMEM1                ), //SWAP MEM
167
 .I3( wData_RMEM1                ), //R*, C*
168
 .I4( wData_XMEM1                ), //CREG*
169
 .O1( oData1_EXE                 )
170
 );
171
 
172
 
173
MUXFULLPARALELL_2SEL_GENERIC # ( `DATA_ROW_WIDTH ) MUX2
174
 (
175
 .Sel( iDataReadAddress2_EXE[6:5] ),
176
 .I1( wData_IMEM2                ), //IO MEM
177
 .I2( wData_SMEM2                ), //SWAP MEM
178
 .I3( wData_RMEM2                ), //R*, C*
179
 .I4( wData_XMEM2                ), //CREG*
180
 .O1( oData2_EXE                 )
181
 );
182
 
183
assign wDataWriteEnable_SMEM = ( iDataWriteAddress_EXE[6:5] == 2'b01 && iDataWriteEnable_EXE ); //Enable WE for SMEM if bank == 01
184
assign wDataWriteEnable_RMEM = ( iDataWriteAddress_EXE[6:5] == 2'b10 && iDataWriteEnable_EXE); //Enable WE for RMEM if bank == 10
185
assign wDataWriteEnable_XMEM = ( iDataWriteAddress_EXE[6:5] == 2'b11 && iDataWriteEnable_EXE); //Enable WE for RMEM if bank == 11
186
 
187
 
188
//Input Registers, Written by IO, Read by EXE
189
RAM_DUAL_READ_PORT  # (`DATA_ROW_WIDTH,5,/*42*/32) IMEM //16 here is enough, I hate small devices!
190
(
191
        .Clock( Clock ),
192
        .iWriteEnable(  iDataWriteEnable_IO        ), //Only IO can write into this bank
193
        .iReadAddress0( iDataReadAddress1_EXE[4:0] ), //EXE read address channel 1
194
        .iReadAddress1( iDataReadAddress2_EXE[4:0] ), //EXE read address channel 2
195
        .iWriteAddress( iDataWriteAddress_IO[4:0]  ), //Only IO can write into this bank
196
        .iDataIn( iData_IO ),
197
        .oDataOut0( wData_IMEM1 ),
198
        .oDataOut1( wData_IMEM2 )
199
);
200
 
201
//Swap registers, while IO reads/write values, EXE reads/write values
202
//the pointers get filped in the next iteration
203
 
204
SWAP_MEM  # (`DATA_ROW_WIDTH,5,32) SMEM
205
(
206
        .Clock( Clock ),
207
        .iSelect( wFlipSelect ),
208
 
209
        .iWriteEnableA( wDataWriteEnable_SMEM ),
210
        .iReadAddressA0( iDataReadAddress1_EXE[4:0] ),
211
        .iReadAddressA1( iDataReadAddress2_EXE[4:0] ),
212
        .iWriteAddressA( iDataWriteAddress_EXE[4:0] ),
213
        .iDataInA( iData_EXE ),
214
        .oDataOutA0( wData_SMEM1 ),
215
        .oDataOutA1( wData_SMEM2 ),
216
 
217
        .iWriteEnableB( iDataWriteEnable_IO ),
218
        .iReadAddressB0( iDataReadAddress1_IO ),
219
        .iReadAddressB1( iDataReadAddress2_IO ),
220
        .iWriteAddressB( iDataWriteAddress_IO ),
221
        .iDataInB( iData_IO )
222
//      .oDataOutB0( wIOData_SMEM1 ),
223
//      .oDataOutB1( wIOData_SMEM2 )
224
 
225
);
226
 
227
//General purpose registers, EXE can R/W, IO can not see these sections
228
//of the memory
229
RAM_DUAL_READ_PORT  # (`DATA_ROW_WIDTH,5,32) RMEM //Ok so we have fewer Registers then...
230
(
231
        .Clock( Clock ),
232
        .iWriteEnable( wDataWriteEnable_RMEM ),
233
        .iReadAddress0( iDataReadAddress1_EXE[4:0] ),
234
        .iReadAddress1( iDataReadAddress2_EXE[4:0] ),
235
        .iWriteAddress( iDataWriteAddress_EXE[4:0] ),
236
        .iDataIn( iData_EXE ),
237
        .oDataOut0( wData_RMEM1 ),
238
        .oDataOut1( wData_RMEM2 )
239
);
240
 
241
RAM_DUAL_READ_PORT  # (`DATA_ROW_WIDTH,5,32) XMEM //Ok so we have fewer Registers then...
242
(
243
        .Clock( Clock ),
244
        .iWriteEnable( wDataWriteEnable_XMEM ),
245
        .iReadAddress0( iDataReadAddress1_EXE[4:0] ),
246
        .iReadAddress1( iDataReadAddress2_EXE[4:0] ),
247
        .iWriteAddress( iDataWriteAddress_EXE[4:0] ),
248
        .iDataIn( iData_EXE ),
249
        .oDataOut0( wData_XMEM1 ),
250
        .oDataOut1( wData_XMEM2 )
251
);
252
 
253
 
254
UPCOUNTER_POSEDGE # (1) UPC1
255
(
256
.Clock(Clock),
257
.Reset( Reset ),
258
.Initial(1'b0),
259
.Enable(iFlipMemory),
260
.Q(wFlipSelect)
261
);
262
 
263
 
264
 
265
//-------------------------------------------------------------------
266
/*
267
Instruction memory.
268
*/
269
 
270
// ROM_ADDRESS_WIDTH exceds the array size it may get trimmed...
271
RAM_DUAL_READ_PORT  # (`INSTRUCTION_WIDTH,`ROM_ADDRESS_WIDTH,/*512*/128) INST_MEM //Only 128 instructions :( well this is for the user anyway
272
(
273
        .Clock( Clock ),
274
        .iWriteEnable( iInstructionWriteEnable ),
275
        .iReadAddress0( {1'b0,iInstructionReadAddress1[`ROM_ADDRESS_WIDTH-2:0]} ),
276
        .iReadAddress1( {1'b0,iInstructionReadAddress2[`ROM_ADDRESS_WIDTH-2:0]} ),
277
        .iWriteAddress( iInstructionWriteAddress ),
278
        .iDataIn( iInstruction ),
279
        .oDataOut0( wIMEM2_IMUX__DataOut1 ),
280
        .oDataOut1( wIMEM2_IMUX__DataOut2 )
281
 
282
);
283
//-------------------------------------------------------------------
284
/*
285
 Default code stored in ROM.
286
*/
287
wire [`INSTRUCTION_WIDTH-1:0] wRomDelay1,wRomDelay2;
288
//In real world ROM will take at least 1 clock cycle,
289
//since ROMs are not syhtethizable, I won't hurt to put
290
//this delay
291
 
292
FFD_POSEDGE_SYNCRONOUS_RESET # ( `INSTRUCTION_WIDTH ) FFDA
293
(
294
        .Clock(Clock),
295
        .Reset(Reset),
296
        .Enable(1'b1),
297
        .D(wRomDelay1),
298
        .Q(wIROM2_IMUX__DataOut1 )
299
);
300
 
301
 
302
FFD_POSEDGE_SYNCRONOUS_RESET # ( `INSTRUCTION_WIDTH ) FFDB
303
(
304
        .Clock(Clock),
305
        .Reset(Reset),
306
        .Enable(1'b1),
307
        .D(wRomDelay2),
308
        .Q(wIROM2_IMUX__DataOut2 )
309
);
310
 
311
//The reason I put two ROMs is because I need to read 2 different Instruction 
312
//addresses at the same time (branch-taken and branch-not-taken) and not sure
313
//how to write dual read channel ROM this way...
314
 
315
ROM IROM
316
(
317
        .Address( {1'b0,iInstructionReadAddress1[`ROM_ADDRESS_WIDTH-2:0]} ),
318
        `ifdef DEBUG
319
        .iDebug_CoreID(iDebug_CoreID),
320
        `endif
321
        .I( wRomDelay1 )
322
);
323
 
324
ROM IROM2
325
(
326
        .Address( {1'b0,iInstructionReadAddress2[`ROM_ADDRESS_WIDTH-2:0]} ),
327
        `ifdef DEBUG
328
        .iDebug_CoreID(iDebug_CoreID),
329
        `endif
330
        .I( wRomDelay2 )
331
);
332
//--------------------------------------------------------
333
ControlRegister CR
334
(
335
        .Clock( Clock ),
336
        .Reset( Reset ),
337
        .iControlRegister( iControlRegister ),
338
        .oControlRegister( oControlRegister )
339
);
340
 
341
 
342
endmodule
343
//-------------------------------------------------------------------

powered by: WebSVN 2.1.0

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