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

Subversion Repositories theia_gpu

[/] [theia_gpu/] [branches/] [icarus_version/] [rtl/] [Module_InstructionFetch.v] - Blame information for rev 218

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 "Collaterals.v"
5
`include "Module_FixedPointAddtionSubstraction.v"
6
`endif
7 158 diegovalve
/**********************************************************************************
8
Theia, Ray Cast Programable graphic Processing Unit.
9
Copyright (C) 2010  Diego Valverde (diego.valverde.g@gmail.com)
10
 
11
This program is free software; you can redistribute it and/or
12
modify it under the terms of the GNU General Public License
13
as published by the Free Software Foundation; either version 2
14
of the License, or (at your option) any later version.
15
 
16
This program is distributed in the hope that it will be useful,
17
but WITHOUT ANY WARRANTY; without even the implied warranty of
18
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
GNU General Public License for more details.
20
 
21
You should have received a copy of the GNU General Public License
22
along with this program; if not, write to the Free Software
23
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
24
 
25
***********************************************************************************/
26
/**********************************************************************************
27
Description:
28
 This is the instruction fetch unit.
29
 It gets the next instruction from the IMEM module at the MEM unit.
30
 It increments the instruction pointer (IP) in such a way that EXE has always
31
 one instruction per clock cycle (best pipeline performance). In order to achieve this,
32
 IFU has 2 instruction pointers, so that in case of 'branch' instructions,
33
 two instructions pointer are generated and two different instructions are simultaneously
34
 fetched from IMEM: the branch-taken and branch-not-taken instructions, so that once the
35
 branch outcome is calculted in EXE, both possible outcomes are already pre-fetched.
36
**********************************************************************************/
37
module InstructionFetch
38
(
39
input wire Clock,
40
input wire Reset,
41
input wire iTrigger,
42
input wire[`ROM_ADDRESS_WIDTH-1:0]               iInitialCodeAddress,
43
input wire[`INSTRUCTION_WIDTH-1:0]               iInstruction1,                  //Branch not taken instruction
44
input wire[`INSTRUCTION_WIDTH-1:0]               iInstruction2,                  //Branch taken instruction
45
input   wire                                                                            iBranchTaken,
46
output wire                                                                             oInstructionAvalable,
47
output wire [`ROM_ADDRESS_WIDTH-1:0]     oIP,
48
output wire [`ROM_ADDRESS_WIDTH-1:0]     oIP2, //calcule both decide later
49
output wire[`INSTRUCTION_WIDTH-1:0]              oCurrentInstruction,
50
input wire                             iEXEDone,
51
output wire                                                                             oMicroCodeReturnValue,
52
input wire                             iSubroutineReturn,
53
//input wire [`ROM_ADDRESS_WIDTH-1:0]    iReturnAddress,
54
output wire                            oExecutionDone
55
);
56
`define INSTRUCTION_OPCODE oCurrentInstruction[`INSTRUCTION_WIDTH-1:`INSTRUCTION_WIDTH-`INSTRUCTION_OP_LENGTH]
57
 
58
 
59
assign oMicroCodeReturnValue = oCurrentInstruction[0];
60
assign oIP2 = oCurrentInstruction[47:32];
61
 
62
wire wTriggerDelay1,wTriggerDelay2,wIncrementIP_Delay1,wIncrementIP_Delay2,
63
wLastInst_Delay1,wLastInst_Delay2;
64
wire wIncrementIP,wLastInstruction;
65
wire wInstructionAvalable,wSubReturnDelay1,wSubReturnDelay2;
66
 
67
assign wLastInstruction = (`INSTRUCTION_OPCODE == `RETURN );
68
 
69
wire IsCall;
70
reg [`ROM_ADDRESS_WIDTH-1:0]    rReturnAddress;
71
assign IsCall = ( `INSTRUCTION_OPCODE == `CALL ) ? 1'b1 : 1'b0;
72
always @ (posedge IsCall)
73
rReturnAddress <= oIP+1;
74
 
75
//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
76
assign wIncrementIP =  wTriggerDelay2 | (iEXEDone & ~wLastInstruction) | wSubReturnDelay2;
77
//It takes 1 clock cycle to read the instruction back from IMEM
78
 
79
 
80
//Instructions become available to IDU: 
81
//* 2 cycles after IFU is initially triggered
82
//* Everytime previous instruction execution is complete except for the last instruction in
83
//the flow
84
assign wInstructionAvalable = wTriggerDelay2 | (iEXEDone & ~wLastInst_Delay2);
85
 
86
 
87
FFD_POSEDGE_SYNCRONOUS_RESET # ( 1 ) FFD22
88
(
89
        .Clock( Clock ),
90
        .Reset( Reset ),
91
        .Enable(1'b1),
92
        .D( iSubroutineReturn ),
93
        .Q( wSubReturnDelay1 )
94
);
95
 
96
FFD_POSEDGE_SYNCRONOUS_RESET # ( 1 ) FFD23
97
(
98
        .Clock( Clock ),
99
        .Reset( Reset ),
100
        .Enable(1'b1),
101
        .D( wSubReturnDelay1 ),
102
        .Q( wSubReturnDelay2 )
103
);
104
//Special case for instruction available pin: if a return from subroutine instruction was issued,
105
//then wait 1 cycle before anouncing Instruction available to IDU
106
assign oInstructionAvalable =  wInstructionAvalable & ~iSubroutineReturn | wSubReturnDelay2;
107
 
108
 
109
 
110
 
111
 
112
//Once we reach the last instruction, wait until EXE says he is done, then assert oExecutionDone
113
assign oExecutionDone = (wLastInstruction & iEXEDone);
114
 
115
FFD_POSEDGE_SYNCRONOUS_RESET # ( 1 ) FFD2
116
(
117
        .Clock( Clock ),
118
        .Reset( Reset ),
119
        .Enable(1'b1),
120
        .D( iTrigger ),
121
        .Q( wTriggerDelay1 )
122
);
123
 
124
 
125
FFD_POSEDGE_SYNCRONOUS_RESET # ( 1 ) FFD3
126
(
127
        .Clock( Clock ),
128
        .Reset( Reset ),
129
        .Enable(1'b1),
130
        .D( wTriggerDelay1 ),
131
        .Q( wTriggerDelay2 )
132
);
133
 
134
 
135
FFD_POSEDGE_SYNCRONOUS_RESET # ( 1 ) FFD4
136
(
137
        .Clock( Clock ),
138
        .Reset( Reset ),
139
        .Enable(wLastInstruction),
140
        .D( oInstructionAvalable ),
141
        .Q( wLastInst_Delay1 )
142
);
143
 
144
 
145
FFD_POSEDGE_SYNCRONOUS_RESET # ( 1 ) FFD5
146
(
147
        .Clock( Clock ),
148
        .Reset( Reset ),
149
        .Enable(1'b1),//wLastInstruction),
150
        .D( wLastInst_Delay1 ),
151
        .Q( wLastInst_Delay2 )
152
);
153
 
154
wire [`ROM_ADDRESS_WIDTH-1:0] oIP2_Next;
155
 
156
/*
157
In case the branch is taken:
158
We point current instruction into the iInstruction2 (branch-taken) instruction
159
that corresponds to oIP2.
160
Then, in the next clock cycle we should use the oIP2 incremented by one,
161
so we need to load UPCOUNTER_POSEDGE with oIP2+1
162
*/
163
 
164
 
165
//If the branch was taken, then use the pre-fetched instruction (iInstruction2)
166
wire[`INSTRUCTION_WIDTH-1:0] wCurrentInstruction_Delay1,wCurrentInstruction_BranchTaken;
167
FFD_POSEDGE_SYNCRONOUS_RESET # ( `INSTRUCTION_WIDTH ) FFDX
168
(
169
        .Clock( Clock ),
170
        .Reset( Reset ),
171
        .Enable(iBranchTaken),
172
        .D( oCurrentInstruction ),
173
        .Q( wCurrentInstruction_Delay1 )
174
);
175
 
176
wire wBranchTaken_Delay1;
177
FFD_POSEDGE_SYNCRONOUS_RESET # ( 1 ) FFDY
178
(
179
        .Clock( Clock ),
180
        .Reset( Reset ),
181
        .Enable(1'b1),
182
        .D( iBranchTaken ),
183
        .Q( wBranchTaken_Delay1 )
184
);
185
 
186
 
187
assign wCurrentInstruction_BranchTaken = ( iBranchTaken & ~iSubroutineReturn) ? iInstruction2 : iInstruction1;
188
 
189
assign oCurrentInstruction = (wBranchTaken_Delay1 ) ?
190
wCurrentInstruction_Delay1 : wCurrentInstruction_BranchTaken;
191
 
192
INCREMENT # (`ROM_ADDRESS_WIDTH) INC1
193
(
194
.Clock( Clock ),
195
.Reset( Reset ),
196
.A( oIP2 ),
197
.R( oIP2_Next )
198
);
199
 
200
wire[`ROM_ADDRESS_WIDTH-1:0] wIPEntryPoint;
201
//assign wIPEntryPoint = (iBranchTaken) ? oIP2_Next : iInitialCodeAddress;
202
 
203
//iReturnAddress is a register stored @ IDU everytime a CALL instruction is decoded
204
assign wIPEntryPoint = (iBranchTaken & ~wBranchTaken_Delay1) ? (iSubroutineReturn) ? rReturnAddress : oIP2_Next  : iInitialCodeAddress;
205
 
206
 
207
UPCOUNTER_POSEDGE # (`ROM_ADDRESS_WIDTH) InstructionPointer
208
(
209
        .Clock( Clock ),
210
        .Reset(iTrigger | (iBranchTaken & ~wBranchTaken_Delay1)),
211
        .Enable(wIncrementIP & (~iBranchTaken | wBranchTaken_Delay1 ) ),
212
        .Initial( wIPEntryPoint ),
213
        .Q(oIP)
214
);
215
 
216
 
217
endmodule
218
 
219 174 diegovalve
//-------------------------------------------------------------------------------

powered by: WebSVN 2.1.0

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