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

Subversion Repositories theia_gpu

[/] [theia_gpu/] [trunk/] [rtl/] [Module_InstructionFetch.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
Description:
24
 This is the instruction fetch unit.
25
 It gets the next instruction from the IMEM module at the MEM unit.
26
 It increments the instruction pointer (IP) in such a way that EXE has always
27
 one instruction per clock cycle (best pipeline performance). In order to achieve this,
28
 IFU has 2 instruction pointers, so that in case of 'branch' instructions,
29
 two instructions pointer are generated and two different instructions are simultaneously
30
 fetched from IMEM: the branch-taken and branch-not-taken instructions, so that once the
31
 branch outcome is calculted in EXE, both possible outcomes are already pre-fetched.
32
**********************************************************************************/
33
module InstructionFetch
34
(
35
input wire Clock,
36
input wire Reset,
37
input wire iTrigger,
38
input wire[`ROM_ADDRESS_WIDTH-1:0]               iInitialCodeAddress,
39
input wire[`INSTRUCTION_WIDTH-1:0]               iInstruction1,                  //Branch not taken instruction
40
input wire[`INSTRUCTION_WIDTH-1:0]               iInstruction2,                  //Branch taken instruction
41
input   wire                                                                            iBranchTaken,
42
output wire                                                                             oInstructionAvalable,
43
output wire [`ROM_ADDRESS_WIDTH-1:0]     oIP,
44
output wire [`ROM_ADDRESS_WIDTH-1:0]     oIP2, //calcule both decide later
45
output wire[`INSTRUCTION_WIDTH-1:0]              oCurrentInstruction,
46
input wire                             iEXEDone,
47
output wire                                                                             oMicroCodeReturnValue,
48
input wire                             iSubroutineReturn,
49
//input wire [`ROM_ADDRESS_WIDTH-1:0]    iReturnAddress,
50
output wire                            oExecutionDone
51
);
52
`define INSTRUCTION_OPCODE oCurrentInstruction[`INSTRUCTION_WIDTH-1:`INSTRUCTION_WIDTH-`INSTRUCTION_OP_LENGTH]
53
 
54
 
55
assign oMicroCodeReturnValue = oCurrentInstruction[0];
56
assign oIP2 = oCurrentInstruction[47:32];
57
 
58
wire wTriggerDelay1,wTriggerDelay2,wIncrementIP_Delay1,wIncrementIP_Delay2,
59
wLastInst_Delay1,wLastInst_Delay2;
60
wire wIncrementIP,wLastInstruction;
61
wire wInstructionAvalable,wSubReturnDelay1,wSubReturnDelay2;
62
 
63
assign wLastInstruction = (`INSTRUCTION_OPCODE == `RETURN );
64
 
65
wire IsCall;
66
reg [`ROM_ADDRESS_WIDTH-1:0]    rReturnAddress;
67
assign IsCall = ( `INSTRUCTION_OPCODE == `CALL ) ? 1'b1 : 1'b0;
68
always @ (posedge IsCall)
69
rReturnAddress <= oIP+1;
70
 
71
//Increment IP 2 cycles after trigger or everytime EXE is done, or 2 cycles after return from sub, but stop if we get to the RETURN
72
assign wIncrementIP =  wTriggerDelay2 | (iEXEDone & ~wLastInstruction) | wSubReturnDelay2;
73
//It takes 1 clock cycle to read the instruction back from IMEM
74
 
75
 
76
//Instructions become available to IDU: 
77
//* 2 cycles after IFU is initially triggered
78
//* Everytime previous instruction execution is complete except for the last instruction in
79
//the flow
80
assign wInstructionAvalable = wTriggerDelay2 | (iEXEDone & ~wLastInst_Delay2);
81
 
82
 
83
FFD_POSEDGE_SYNCRONOUS_RESET # ( 1 ) FFD22
84
(
85
        .Clock( Clock ),
86
        .Reset( Reset ),
87
        .Enable(1'b1),
88
        .D( iSubroutineReturn ),
89
        .Q( wSubReturnDelay1 )
90
);
91
 
92
FFD_POSEDGE_SYNCRONOUS_RESET # ( 1 ) FFD23
93
(
94
        .Clock( Clock ),
95
        .Reset( Reset ),
96
        .Enable(1'b1),
97
        .D( wSubReturnDelay1 ),
98
        .Q( wSubReturnDelay2 )
99
);
100
//Special case for instruction available pin: if a return from subroutine instruction was issued,
101
//then wait 1 cycle before anouncing Instruction available to IDU
102
assign oInstructionAvalable =  wInstructionAvalable & ~iSubroutineReturn | wSubReturnDelay2;
103
 
104
 
105
 
106
 
107
 
108
//Once we reach the last instruction, wait until EXE says he is done, then assert oExecutionDone
109
assign oExecutionDone = (wLastInstruction & iEXEDone);
110
 
111
FFD_POSEDGE_SYNCRONOUS_RESET # ( 1 ) FFD2
112
(
113
        .Clock( Clock ),
114
        .Reset( Reset ),
115
        .Enable(1'b1),
116
        .D( iTrigger ),
117
        .Q( wTriggerDelay1 )
118
);
119
 
120
 
121
FFD_POSEDGE_SYNCRONOUS_RESET # ( 1 ) FFD3
122
(
123
        .Clock( Clock ),
124
        .Reset( Reset ),
125
        .Enable(1'b1),
126
        .D( wTriggerDelay1 ),
127
        .Q( wTriggerDelay2 )
128
);
129
 
130
 
131
FFD_POSEDGE_SYNCRONOUS_RESET # ( 1 ) FFD4
132
(
133
        .Clock( Clock ),
134
        .Reset( Reset ),
135
        .Enable(wLastInstruction),
136
        .D( oInstructionAvalable ),
137
        .Q( wLastInst_Delay1 )
138
);
139
 
140
 
141
FFD_POSEDGE_SYNCRONOUS_RESET # ( 1 ) FFD5
142
(
143
        .Clock( Clock ),
144
        .Reset( Reset ),
145
        .Enable(1'b1),//wLastInstruction),
146
        .D( wLastInst_Delay1 ),
147
        .Q( wLastInst_Delay2 )
148
);
149
 
150
wire [`ROM_ADDRESS_WIDTH-1:0] oIP2_Next;
151
 
152
/*
153
In case the branch is taken:
154
We point current instruction into the iInstruction2 (branch-taken) instruction
155
that corresponds to oIP2.
156
Then, in the next clock cycle we should use the oIP2 incremented by one,
157
so we need to load UPCOUNTER_POSEDGE with oIP2+1
158
*/
159
 
160
 
161
//If the branch was taken, then use the pre-fetched instruction (iInstruction2)
162
wire[`INSTRUCTION_WIDTH-1:0] wCurrentInstruction_Delay1,wCurrentInstruction_BranchTaken;
163
FFD_POSEDGE_SYNCRONOUS_RESET # ( `INSTRUCTION_WIDTH ) FFDX
164
(
165
        .Clock( Clock ),
166
        .Reset( Reset ),
167
        .Enable(iBranchTaken),
168
        .D( oCurrentInstruction ),
169
        .Q( wCurrentInstruction_Delay1 )
170
);
171
 
172
wire wBranchTaken_Delay1;
173
FFD_POSEDGE_SYNCRONOUS_RESET # ( 1 ) FFDY
174
(
175
        .Clock( Clock ),
176
        .Reset( Reset ),
177
        .Enable(1'b1),
178
        .D( iBranchTaken ),
179
        .Q( wBranchTaken_Delay1 )
180
);
181
 
182
 
183
assign wCurrentInstruction_BranchTaken = ( iBranchTaken & ~iSubroutineReturn) ? iInstruction2 : iInstruction1;
184
 
185
assign oCurrentInstruction = (wBranchTaken_Delay1 ) ?
186
wCurrentInstruction_Delay1 : wCurrentInstruction_BranchTaken;
187
 
188
INCREMENT # (`ROM_ADDRESS_WIDTH) INC1
189
(
190
.Clock( Clock ),
191
.Reset( Reset ),
192
.A( oIP2 ),
193
.R( oIP2_Next )
194
);
195
 
196
wire[`ROM_ADDRESS_WIDTH-1:0] wIPEntryPoint;
197
//assign wIPEntryPoint = (iBranchTaken) ? oIP2_Next : iInitialCodeAddress;
198
 
199
//iReturnAddress is a register stored @ IDU everytime a CALL instruction is decoded
200
assign wIPEntryPoint = (iBranchTaken & ~wBranchTaken_Delay1) ? (iSubroutineReturn) ? rReturnAddress : oIP2_Next  : iInitialCodeAddress;
201
 
202
 
203
UPCOUNTER_POSEDGE # (`ROM_ADDRESS_WIDTH) InstructionPointer
204
(
205
        .Clock( Clock ),
206
        .Reset(iTrigger | (iBranchTaken & ~wBranchTaken_Delay1)),
207
        .Enable(wIncrementIP & (~iBranchTaken | wBranchTaken_Delay1 ) ),
208
        .Initial( wIPEntryPoint ),
209
        .Q(oIP)
210
);
211
 
212
 
213
endmodule
214
 
215
//-------------------------------------------------------------------------------

powered by: WebSVN 2.1.0

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