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

Subversion Repositories theia_gpu

[/] [theia_gpu/] [tags/] [latest_stable/] [rtl/] [GPU/] [CORES/] [EXE/] [Module_InstructionFetch.v] - Blame information for rev 150

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 23 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 60 diegovalve
/**********************************************************************************
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 23 diegovalve
(
35 60 diegovalve
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 105 diegovalve
output wire                                                                             oMicroCodeReturnValue,
48
input wire                             iSubroutineReturn,
49
//input wire [`ROM_ADDRESS_WIDTH-1:0]    iReturnAddress,
50 60 diegovalve
output wire                            oExecutionDone
51 23 diegovalve
);
52 60 diegovalve
`define INSTRUCTION_OPCODE oCurrentInstruction[`INSTRUCTION_WIDTH-1:`INSTRUCTION_WIDTH-`INSTRUCTION_OP_LENGTH]
53 23 diegovalve
 
54 105 diegovalve
 
55 60 diegovalve
assign oMicroCodeReturnValue = oCurrentInstruction[0];
56 105 diegovalve
assign oIP2 = oCurrentInstruction[47:32];
57 23 diegovalve
 
58 60 diegovalve
wire wTriggerDelay1,wTriggerDelay2,wIncrementIP_Delay1,wIncrementIP_Delay2,
59
wLastInst_Delay1,wLastInst_Delay2;
60
wire wIncrementIP,wLastInstruction;
61 105 diegovalve
wire wInstructionAvalable,wSubReturnDelay1,wSubReturnDelay2;
62 23 diegovalve
 
63 105 diegovalve
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 23 diegovalve
 
71 105 diegovalve
//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 23 diegovalve
 
108 60 diegovalve
//Once we reach the last instruction, wait until EXE says he is done, then assert oExecutionDone
109
assign oExecutionDone = (wLastInstruction & iEXEDone);
110 23 diegovalve
 
111 60 diegovalve
FFD_POSEDGE_SYNCRONOUS_RESET # ( 1 ) FFD2
112 23 diegovalve
(
113
        .Clock( Clock ),
114 60 diegovalve
        .Reset( Reset ),
115
        .Enable(1'b1),
116
        .D( iTrigger ),
117
        .Q( wTriggerDelay1 )
118 23 diegovalve
);
119
 
120
 
121 60 diegovalve
FFD_POSEDGE_SYNCRONOUS_RESET # ( 1 ) FFD3
122 23 diegovalve
(
123
        .Clock( Clock ),
124 60 diegovalve
        .Reset( Reset ),
125
        .Enable(1'b1),
126
        .D( wTriggerDelay1 ),
127
        .Q( wTriggerDelay2 )
128 23 diegovalve
);
129
 
130
 
131 60 diegovalve
FFD_POSEDGE_SYNCRONOUS_RESET # ( 1 ) FFD4
132 23 diegovalve
(
133
        .Clock( Clock ),
134 60 diegovalve
        .Reset( Reset ),
135
        .Enable(wLastInstruction),
136
        .D( oInstructionAvalable ),
137
        .Q( wLastInst_Delay1 )
138 23 diegovalve
);
139
 
140
 
141 60 diegovalve
FFD_POSEDGE_SYNCRONOUS_RESET # ( 1 ) FFD5
142 23 diegovalve
(
143
        .Clock( Clock ),
144 60 diegovalve
        .Reset( Reset ),
145 72 diegovalve
        .Enable(1'b1),//wLastInstruction),
146 60 diegovalve
        .D( wLastInst_Delay1 ),
147
        .Q( wLastInst_Delay2 )
148 23 diegovalve
);
149
 
150 60 diegovalve
wire [`ROM_ADDRESS_WIDTH-1:0] oIP2_Next;
151 23 diegovalve
 
152 60 diegovalve
/*
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 23 diegovalve
 
160 60 diegovalve
 
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 23 diegovalve
(
165
        .Clock( Clock ),
166 60 diegovalve
        .Reset( Reset ),
167
        .Enable(iBranchTaken),
168
        .D( oCurrentInstruction ),
169
        .Q( wCurrentInstruction_Delay1 )
170 23 diegovalve
);
171
 
172 60 diegovalve
wire wBranchTaken_Delay1;
173
FFD_POSEDGE_SYNCRONOUS_RESET # ( 1 ) FFDY
174 23 diegovalve
(
175
        .Clock( Clock ),
176 60 diegovalve
        .Reset( Reset ),
177
        .Enable(1'b1),
178
        .D( iBranchTaken ),
179
        .Q( wBranchTaken_Delay1 )
180 23 diegovalve
);
181
 
182
 
183 105 diegovalve
assign wCurrentInstruction_BranchTaken = ( iBranchTaken & ~iSubroutineReturn) ? iInstruction2 : iInstruction1;
184 23 diegovalve
 
185 105 diegovalve
assign oCurrentInstruction = (wBranchTaken_Delay1 ) ?
186 60 diegovalve
wCurrentInstruction_Delay1 : wCurrentInstruction_BranchTaken;
187 23 diegovalve
 
188 60 diegovalve
INCREMENT # (`ROM_ADDRESS_WIDTH) INC1
189 23 diegovalve
(
190 60 diegovalve
.Clock( Clock ),
191
.Reset( Reset ),
192
.A( oIP2 ),
193
.R( oIP2_Next )
194 23 diegovalve
);
195
 
196 60 diegovalve
wire[`ROM_ADDRESS_WIDTH-1:0] wIPEntryPoint;
197 105 diegovalve
//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 23 diegovalve
 
202 105 diegovalve
 
203 60 diegovalve
UPCOUNTER_POSEDGE # (`ROM_ADDRESS_WIDTH) InstructionPointer
204 23 diegovalve
(
205 60 diegovalve
        .Clock( Clock ),
206 105 diegovalve
        .Reset(iTrigger | (iBranchTaken & ~wBranchTaken_Delay1)),
207
        .Enable(wIncrementIP & (~iBranchTaken | wBranchTaken_Delay1 ) ),
208 60 diegovalve
        .Initial( wIPEntryPoint ),
209
        .Q(oIP)
210 23 diegovalve
);
211
 
212
 
213 60 diegovalve
endmodule
214 23 diegovalve
 
215
//-------------------------------------------------------------------------------

powered by: WebSVN 2.1.0

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