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

Subversion Repositories theia_gpu

[/] [theia_gpu/] [branches/] [icarus_version/] [rtl/] [Unit_MEM.v] - Blame information for rev 228

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

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

powered by: WebSVN 2.1.0

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