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

Subversion Repositories theia_gpu

[/] [theia_gpu/] [branches/] [beta_1.2/] [rtl/] [EXE/] [Module_InstructionFetch.v] - Blame information for rev 72

Go to most recent revision | 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
output wire                                                                             oMicroCodeReturnValue,
48
output wire                            oExecutionDone
49 23 diegovalve
);
50 60 diegovalve
`define INSTRUCTION_OPCODE oCurrentInstruction[`INSTRUCTION_WIDTH-1:`INSTRUCTION_WIDTH-`INSTRUCTION_OP_LENGTH]
51
//iInstruction1[`INSTRUCTION_WIDTH-1:`INSTRUCTION_WIDTH-`INSTRUCTION_OP_LENGTH]
52 23 diegovalve
 
53 60 diegovalve
assign oMicroCodeReturnValue = oCurrentInstruction[0];
54
assign oIP2 = oCurrentInstruction[47:32];//iInstruction1[47:32];
55 23 diegovalve
 
56 60 diegovalve
wire wTriggerDelay1,wTriggerDelay2,wIncrementIP_Delay1,wIncrementIP_Delay2,
57
wLastInst_Delay1,wLastInst_Delay2;
58
wire wIncrementIP,wLastInstruction;
59 23 diegovalve
 
60
 
61 60 diegovalve
assign wLastInstruction = (`INSTRUCTION_OPCODE == `RETURN);
62 23 diegovalve
 
63 60 diegovalve
//Increment IP 2 cycles after trigger or everytime EXE is done, but stop if we get to the RETURN
64
assign wIncrementIP =  wTriggerDelay2 | (iEXEDone & ~wLastInstruction);
65
//It takes 1 clock cycle to read the instruction back from IMEM
66
assign oInstructionAvalable = wTriggerDelay2 | (iEXEDone & ~wLastInst_Delay2);
67
//Once we reach the last instruction, wait until EXE says he is done, then assert oExecutionDone
68
assign oExecutionDone = (wLastInstruction & iEXEDone);
69 23 diegovalve
 
70 60 diegovalve
FFD_POSEDGE_SYNCRONOUS_RESET # ( 1 ) FFD2
71 23 diegovalve
(
72
        .Clock( Clock ),
73 60 diegovalve
        .Reset( Reset ),
74
        .Enable(1'b1),
75
        .D( iTrigger ),
76
        .Q( wTriggerDelay1 )
77 23 diegovalve
);
78
 
79
 
80 60 diegovalve
FFD_POSEDGE_SYNCRONOUS_RESET # ( 1 ) FFD3
81 23 diegovalve
(
82
        .Clock( Clock ),
83 60 diegovalve
        .Reset( Reset ),
84
        .Enable(1'b1),
85
        .D( wTriggerDelay1 ),
86
        .Q( wTriggerDelay2 )
87 23 diegovalve
);
88
 
89
 
90 60 diegovalve
FFD_POSEDGE_SYNCRONOUS_RESET # ( 1 ) FFD4
91 23 diegovalve
(
92
        .Clock( Clock ),
93 60 diegovalve
        .Reset( Reset ),
94
        .Enable(wLastInstruction),
95
        .D( oInstructionAvalable ),
96
        .Q( wLastInst_Delay1 )
97 23 diegovalve
);
98
 
99
 
100 60 diegovalve
FFD_POSEDGE_SYNCRONOUS_RESET # ( 1 ) FFD5
101 23 diegovalve
(
102
        .Clock( Clock ),
103 60 diegovalve
        .Reset( Reset ),
104 72 diegovalve
        .Enable(1'b1),//wLastInstruction),
105 60 diegovalve
        .D( wLastInst_Delay1 ),
106
        .Q( wLastInst_Delay2 )
107 23 diegovalve
);
108
 
109 60 diegovalve
wire [`ROM_ADDRESS_WIDTH-1:0] oIP2_Next;
110 23 diegovalve
 
111 60 diegovalve
/*
112
In case the branch is taken:
113
We point current instruction into the iInstruction2 (branch-taken) instruction
114
that corresponds to oIP2.
115
Then, in the next clock cycle we should use the oIP2 incremented by one,
116
so we need to load UPCOUNTER_POSEDGE with oIP2+1
117
*/
118 23 diegovalve
 
119 60 diegovalve
 
120
//If the branch was taken, then use the pre-fetched instruction (iInstruction2)
121
wire[`INSTRUCTION_WIDTH-1:0] wCurrentInstruction_Delay1,wCurrentInstruction_BranchTaken;
122
FFD_POSEDGE_SYNCRONOUS_RESET # ( `INSTRUCTION_WIDTH ) FFDX
123 23 diegovalve
(
124
        .Clock( Clock ),
125 60 diegovalve
        .Reset( Reset ),
126
        .Enable(iBranchTaken),
127
        .D( oCurrentInstruction ),
128
        .Q( wCurrentInstruction_Delay1 )
129 23 diegovalve
);
130
 
131 60 diegovalve
wire wBranchTaken_Delay1;
132
FFD_POSEDGE_SYNCRONOUS_RESET # ( 1 ) FFDY
133 23 diegovalve
(
134
        .Clock( Clock ),
135 60 diegovalve
        .Reset( Reset ),
136
        .Enable(1'b1),
137
        .D( iBranchTaken ),
138
        .Q( wBranchTaken_Delay1 )
139 23 diegovalve
);
140
 
141
 
142 60 diegovalve
assign wCurrentInstruction_BranchTaken = (iBranchTaken ) ? iInstruction2 : iInstruction1;
143 23 diegovalve
 
144 60 diegovalve
assign oCurrentInstruction = (wBranchTaken_Delay1) ?
145
wCurrentInstruction_Delay1 : wCurrentInstruction_BranchTaken;
146 23 diegovalve
 
147 60 diegovalve
INCREMENT # (`ROM_ADDRESS_WIDTH) INC1
148 23 diegovalve
(
149 60 diegovalve
.Clock( Clock ),
150
.Reset( Reset ),
151
.A( oIP2 ),
152
.R( oIP2_Next )
153 23 diegovalve
);
154
 
155 60 diegovalve
wire[`ROM_ADDRESS_WIDTH-1:0] wIPEntryPoint;
156
assign wIPEntryPoint = (iBranchTaken) ? oIP2_Next : iInitialCodeAddress;
157 23 diegovalve
 
158 60 diegovalve
UPCOUNTER_POSEDGE # (`ROM_ADDRESS_WIDTH) InstructionPointer
159 23 diegovalve
(
160 60 diegovalve
        .Clock( Clock ),
161
        .Reset(iTrigger | iBranchTaken),
162
        .Enable(wIncrementIP & ~iBranchTaken ),
163
        .Initial( wIPEntryPoint ),
164
        .Q(oIP)
165 23 diegovalve
);
166
 
167
 
168 60 diegovalve
endmodule
169 23 diegovalve
 
170
//-------------------------------------------------------------------------------

powered by: WebSVN 2.1.0

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