1 |
3 |
dgisselq |
///////////////////////////////////////////////////////////////////////////////
|
2 |
|
|
//
|
3 |
|
|
// Filename: ifastdec.v
|
4 |
|
|
//
|
5 |
|
|
// Project: Zip CPU -- a small, lightweight, RISC CPU soft core
|
6 |
|
|
//
|
7 |
|
|
// Purpose: This RTL file specifies how instructions are to be decoded
|
8 |
|
|
// into their underlying meanings. It is different from the
|
9 |
|
|
// standard idecode.v file in that this one takes two clocks, and is
|
10 |
|
|
// pipelined. This one is designed for a 5ns clock cycle, hence it is
|
11 |
|
|
// a "fast" decoder--even though the old decoder took one cycle in 10ns.
|
12 |
|
|
// From that standpoint, the two may well be ... comparable in speed.
|
13 |
|
|
//
|
14 |
|
|
//
|
15 |
|
|
// Creator: Dan Gisselquist, Ph.D.
|
16 |
|
|
// Gisselquist Technology, LLC
|
17 |
|
|
//
|
18 |
|
|
///////////////////////////////////////////////////////////////////////////////
|
19 |
|
|
//
|
20 |
|
|
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
|
21 |
|
|
//
|
22 |
|
|
// This program is free software (firmware): you can redistribute it and/or
|
23 |
|
|
// modify it under the terms of the GNU General Public License as published
|
24 |
|
|
// by the Free Software Foundation, either version 3 of the License, or (at
|
25 |
|
|
// your option) any later version.
|
26 |
|
|
//
|
27 |
|
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
28 |
|
|
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
|
29 |
|
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
30 |
|
|
// for more details.
|
31 |
|
|
//
|
32 |
|
|
// License: GPL, v3, as defined and found on www.gnu.org,
|
33 |
|
|
// http://www.gnu.org/licenses/gpl.html
|
34 |
|
|
//
|
35 |
|
|
//
|
36 |
|
|
///////////////////////////////////////////////////////////////////////////////
|
37 |
|
|
//
|
38 |
|
|
//
|
39 |
|
|
//
|
40 |
|
|
`define CPU_CC_REG 4'he
|
41 |
|
|
`define CPU_PC_REG 4'hf
|
42 |
|
|
//
|
43 |
|
|
`include "cpudefs.v"
|
44 |
|
|
//
|
45 |
|
|
//
|
46 |
|
|
//
|
47 |
|
|
module ifastdec(i_clk, i_rst, i_ce, i_stalled,
|
48 |
|
|
i_instruction, i_gie, i_pc, i_pf_valid,
|
49 |
|
|
i_illegal,
|
50 |
|
|
o_phase, o_illegal,
|
51 |
|
|
o_pc, o_gie,
|
52 |
|
|
o_R, o_A, o_B, o_I, o_zI,
|
53 |
|
|
o_cond, o_wF,
|
54 |
|
|
o_op, o_ALU, o_M, o_DV, o_FP, o_break, o_lock,
|
55 |
|
|
o_wR, o_rA, o_rB,
|
56 |
|
|
o_early_branch, o_branch_pc, o_ljmp,
|
57 |
|
|
o_pipe
|
58 |
|
|
);
|
59 |
|
|
parameter ADDRESS_WIDTH=24, IMPLEMENT_MPY=1, EARLY_BRANCHING=1,
|
60 |
|
|
IMPLEMENT_DIVIDE=1, IMPLEMENT_FPU=0, AW = ADDRESS_WIDTH;
|
61 |
|
|
input i_clk, i_rst, i_ce, i_stalled;
|
62 |
|
|
input [31:0] i_instruction;
|
63 |
|
|
input i_gie;
|
64 |
|
|
input [(AW-1):0] i_pc;
|
65 |
|
|
input i_pf_valid, i_illegal;
|
66 |
|
|
output reg o_phase;
|
67 |
|
|
output reg o_illegal;
|
68 |
|
|
output reg [(AW-1):0] o_pc;
|
69 |
|
|
output reg o_gie;
|
70 |
|
|
output reg [6:0] o_R, o_A, o_B;
|
71 |
|
|
output reg [31:0] o_I;
|
72 |
|
|
output reg o_zI;
|
73 |
|
|
output reg [3:0] o_cond;
|
74 |
|
|
output reg o_wF;
|
75 |
|
|
output reg [3:0] o_op;
|
76 |
|
|
output reg o_ALU, o_M, o_DV, o_FP, o_break;
|
77 |
|
|
output reg o_lock;
|
78 |
|
|
output reg o_wR, o_rA, o_rB;
|
79 |
|
|
output reg o_early_branch;
|
80 |
|
|
output reg [(AW-1):0] o_branch_pc;
|
81 |
|
|
output reg o_ljmp;
|
82 |
|
|
output reg o_pipe;
|
83 |
|
|
|
84 |
|
|
|
85 |
|
|
//////
|
86 |
|
|
//
|
87 |
|
|
// Path 1: Full size instruction
|
88 |
|
|
//
|
89 |
|
|
// Prefix: wf (wire, full)
|
90 |
|
|
//
|
91 |
|
|
//////
|
92 |
|
|
|
93 |
|
|
// The 5-bit opcode, as extracted
|
94 |
|
|
wire [4:0] wf_op;
|
95 |
|
|
// Instruction types
|
96 |
|
|
wire wf_ldi, wf_mov, wf_cmptst, wf_ldilo, wf_brev, wf_noop,
|
97 |
|
|
wf_break, wf_lock,
|
98 |
|
|
wf_ljmp, wf_ALU, wf_MEM, wf_DIV, wf_FPU;
|
99 |
|
|
wire [4:0] wf_R, wf_A, wf_B; // Instruction registers
|
100 |
|
|
wire [3:0] wf_cond;
|
101 |
|
|
wire wf_wF; // Write flags?
|
102 |
|
|
wire wf_wR_n, // Write destination register? or not?
|
103 |
|
|
wf_rA, // Read register A?
|
104 |
|
|
wf_rB; // Read register B?
|
105 |
|
|
wire [22:0] wf_pI; // Partial immediate ...
|
106 |
|
|
wire wf_Iz;
|
107 |
|
|
|
108 |
|
|
assign wf_op = i_instruction[26:22];
|
109 |
|
|
assign wf_brev = (wf_op == 5'hc);
|
110 |
|
|
assign wf_mov = (wf_op == 5'h0f);
|
111 |
|
|
assign wf_ldi = (wf_op[4:1] == 4'hb);
|
112 |
|
|
assign wf_cmptst=(wf_op[4:1] == 4'h8);
|
113 |
|
|
assign wf_ldilo= (wf_op[4:0] == 5'h9);
|
114 |
|
|
assign wf_noop = (wf_op[4:0] == 5'h18)&&(wf_R[3:1] == 3'h7);
|
115 |
|
|
assign wf_break= (wf_op[4:0] == 5'h19)&&(wf_R[3:1] == 3'h7);
|
116 |
|
|
assign wf_lock = (wf_op[4:0] == 5'h1a)&&(wf_R[3:1] == 3'h7);
|
117 |
|
|
//
|
118 |
|
|
assign wf_R = { (wf_mov)&&(i_gie)?i_instruction[18]:i_gie, (i_instruction[30:27]) };
|
119 |
|
|
assign wf_A = { (wf_mov)&&(i_gie)?i_instruction[18]:i_gie, (i_instruction[30:27]) };
|
120 |
|
|
assign wf_B = { (wf_mov)&&(i_gie)?i_instruction[13]:i_gie, (i_instruction[17:14]) };
|
121 |
|
|
//
|
122 |
|
|
assign wf_ALU = (~wf_op[4]);
|
123 |
|
|
assign wf_MEM = ( wf_op[4:1] == 4'h9);
|
124 |
|
|
assign wf_DIV = ( wf_op[4:1] == 4'ha);
|
125 |
|
|
assign wf_FPU = ( wf_op[4:2] == 3'h7)&&(i_instruction[30:28]==3'h7);
|
126 |
|
|
assign wf_ljmp = (i_instruction == 32'h7c87c000);
|
127 |
|
|
|
128 |
|
|
assign wf_pI = (wf_ldi) ? { i_instruction[22:0] } // LDI
|
129 |
|
|
:((wf_mov) ?{ {(23-13){i_instruction[12]}}, i_instruction[12:0] } // Move
|
130 |
|
|
:((~i_instruction[18]) ? { {(23-18){i_instruction[17]}}, i_instruction[17:0] }
|
131 |
|
|
: { {(23-14){i_instruction[13]}}, i_instruction[13:0] }
|
132 |
|
|
));
|
133 |
|
|
assign wf_Iz= (wf_pI == 23'h00);
|
134 |
|
|
|
135 |
|
|
// Will we be writing register R?
|
136 |
|
|
assign wf_wR_n = ((wf_MEM)&&(wf_op[0])) // Store's dont write regs
|
137 |
|
|
// Neither do NOOP, BREAK, or LOCKs
|
138 |
|
|
||((wf_op[4:3]==2'b11)&&(wf_R[3:1]==3'h7))
|
139 |
|
|
// nor CMPs and TSTs
|
140 |
|
|
||(wf_cmptst);
|
141 |
|
|
// Do we read register 'A'?
|
142 |
|
|
assign wf_rA = (wf_FPU)&&(wf_op[4:1]!=4'he) // FPU, but not CVT or INT
|
143 |
|
|
||(wf_DIV)
|
144 |
|
|
||(wf_ALU)&&(~wf_mov)
|
145 |
|
|
||(wf_MEM)&&(wf_op[0])
|
146 |
|
|
||(wf_cmptst);
|
147 |
|
|
// Do we need to read register 'B'?
|
148 |
|
|
assign wf_rB = (wf_mov)||((i_instruction[18])&&(~wf_ldi));
|
149 |
|
|
|
150 |
|
|
// What are the conditions for this instruction? NOOP, BREAK, and LOCK
|
151 |
|
|
// are also unconditional, but they'll just ignore this setting
|
152 |
|
|
assign wf_cond = (wf_ldi) ? 4'h8 // LDI is unconditional
|
153 |
|
|
: { (i_instruction[21:19]==3'h0), i_instruction[21:19] };
|
154 |
|
|
// How about the flags, will we be writing them?
|
155 |
|
|
assign wf_wF = (wf_cmptst) // Compares always write flags
|
156 |
|
|
||((wf_cond[3])&&(
|
157 |
|
|
// FPU and DIV instructions always write flags
|
158 |
|
|
(wf_FPU)||(wf_DIV)
|
159 |
|
|
// So do ALU instructions, UNLESS the ALU
|
160 |
|
|
// instruction is a MOV, LDILO, or BREV, or
|
161 |
|
|
// the results are being written into the PC
|
162 |
|
|
// or CC register--those don't set flags
|
163 |
|
|
||((wf_ALU)&&(~wf_mov)&&(~wf_ldilo)&&(~wf_brev)
|
164 |
|
|
&&(i_instruction[30:28] != 3'h7))));
|
165 |
|
|
|
166 |
|
|
reg [3:0] rf_op;
|
167 |
|
|
reg rf_break, rf_lock;
|
168 |
|
|
reg [4:0] rf_R, rf_A, rf_B;
|
169 |
|
|
reg rf_ALU, rf_MEM, rf_DIV, rf_FPU, rf_ljmp;
|
170 |
|
|
reg [3:0] rf_cond;
|
171 |
|
|
reg rf_rA, rf_rB, rf_wR, rf_wF;
|
172 |
|
|
|
173 |
|
|
reg [22:0] rf_pI;
|
174 |
|
|
reg rf_Iz;
|
175 |
|
|
wire [31:0] wf_I;
|
176 |
|
|
assign wf_I = { {(32-22){rf_pI[22]}}, rf_pI[21:0] };
|
177 |
|
|
|
178 |
|
|
reg rf_early_branch;
|
179 |
|
|
reg [(AW-1):0] rf_branch_pc;
|
180 |
|
|
always @(posedge i_clk)
|
181 |
|
|
if (i_ce)
|
182 |
|
|
begin
|
183 |
|
|
rf_op <= wf_op[3:0];
|
184 |
|
|
rf_break<= wf_break;
|
185 |
|
|
rf_lock <= wf_lock;
|
186 |
|
|
//
|
187 |
|
|
rf_R <= (wf_R);
|
188 |
|
|
rf_A <= (wf_A);
|
189 |
|
|
rf_B <= (wf_B);
|
190 |
|
|
//
|
191 |
|
|
rf_ALU <= (~wf_op[4]);
|
192 |
|
|
rf_MEM <= ( wf_op[4:1] == 4'h9);
|
193 |
|
|
rf_DIV <= ( wf_op[4:1] == 4'ha);
|
194 |
|
|
rf_FPU <= ( wf_op[4:2] == 3'h7)&&(i_instruction[30:28]==3'h7);
|
195 |
|
|
rf_ljmp <= (i_instruction == 32'h7c87c000);
|
196 |
|
|
|
197 |
|
|
rf_pI <= wf_pI;
|
198 |
|
|
rf_Iz<= wf_Iz;
|
199 |
|
|
|
200 |
|
|
// What are the conditions of this instruction?
|
201 |
|
|
rf_cond <= wf_cond;
|
202 |
|
|
|
203 |
|
|
// Do we read register 'A'?
|
204 |
|
|
rf_rA <= wf_rA;
|
205 |
|
|
// Do we need to read register 'B'?
|
206 |
|
|
rf_rB <= wf_rB;
|
207 |
|
|
// Will we be writing register 'R'?
|
208 |
|
|
rf_wR <= ~wf_wR_n;
|
209 |
|
|
// How about the flags, will we be writing those?
|
210 |
|
|
rf_wF <= wf_wF;
|
211 |
|
|
|
212 |
|
|
//
|
213 |
|
|
rf_early_branch <=
|
214 |
|
|
// PC is the result
|
215 |
|
|
(wf_R[3:0]==4'hf)
|
216 |
|
|
// Unconditional instruction
|
217 |
|
|
&&(i_instruction[21:19]==3'h0)
|
218 |
|
|
&&
|
219 |
|
|
// Either an ADD #x,PC
|
220 |
|
|
((wf_op == 5'h02)&&(~i_instruction[18])
|
221 |
|
|
// Or a LOD #x,PC
|
222 |
|
|
||(wf_ldi));
|
223 |
|
|
rf_branch_pc <= (wf_ldi)?{{(AW-22){wf_pI[22]}},wf_pI[21:0]}
|
224 |
|
|
:(i_pc + {{(AW-18){i_instruction[17]}},
|
225 |
|
|
i_instruction[16:0]});
|
226 |
|
|
end
|
227 |
|
|
|
228 |
|
|
//////
|
229 |
|
|
//
|
230 |
|
|
// Path 2: Half size instruction, high half
|
231 |
|
|
//
|
232 |
|
|
// Prefix: wh (wire, high-half)
|
233 |
|
|
//
|
234 |
|
|
//////
|
235 |
|
|
|
236 |
|
|
// The 5-bit opcode, as extracted -- same as wf_
|
237 |
|
|
// Instruction types -- same as wf_
|
238 |
|
|
wire [4:0] wh_R, wh_A, wh_B; // Instruction registers
|
239 |
|
|
wire [3:0] wh_cond;
|
240 |
|
|
wire wh_wF; // Write flags?
|
241 |
|
|
wire wh_wR, wh_wR_n, // Write destination register? or not?
|
242 |
|
|
wh_rA, // Read register A?
|
243 |
|
|
wh_rB; // Read register B?
|
244 |
|
|
wire [4:0] wh_pI; // Partial immediate ...
|
245 |
|
|
wire wh_Iz;
|
246 |
|
|
|
247 |
|
|
assign wh_R = { i_gie, (i_instruction[30:27]) };
|
248 |
|
|
assign wh_A = { i_gie, (i_instruction[30:27]) };
|
249 |
|
|
assign wh_B = { i_gie, (i_instruction[17:14]) };
|
250 |
|
|
//
|
251 |
|
|
|
252 |
|
|
assign wh_pI = (wf_ldi) ? { i_instruction[18:14] } // LDI
|
253 |
|
|
:((~i_instruction[18])
|
254 |
|
|
? { i_instruction[17], i_instruction[17:14] }
|
255 |
|
|
: 5'h0);
|
256 |
|
|
assign wh_Iz= (wh_pI == 5'h0);
|
257 |
|
|
|
258 |
|
|
// Will we be writing register R?
|
259 |
|
|
assign wh_wR_n = ((wf_MEM)&&(wf_op[0])) // Store's dont write regs
|
260 |
|
|
// Neither do NOOP, BREAK, or LOCKs
|
261 |
|
|
||((wf_op[4:3]==2'b11)&&(wh_R[3:1]==3'h7))
|
262 |
|
|
// nor CMPs and TSTs
|
263 |
|
|
||(wf_cmptst);
|
264 |
|
|
|
265 |
|
|
assign wh_cond = (wf_ldi) ? 4'h8 // LDI is unconditional
|
266 |
|
|
: { (i_instruction[20:19]==2'h0), 1'b0, i_instruction[20:19] };
|
267 |
|
|
// How about the flags, will we be writing them?
|
268 |
|
|
assign wh_wF = (wf_cmptst) // Compares always write flags
|
269 |
|
|
||((wh_cond[3])&&(
|
270 |
|
|
// FPU and DIV instructions always write flags
|
271 |
|
|
(wf_FPU)||(wf_DIV)
|
272 |
|
|
// So do ALU instructions, UNLESS the ALU
|
273 |
|
|
// instruction is a MOV, LDILO, or BREV, or
|
274 |
|
|
// the results are being written into the PC
|
275 |
|
|
// or CC register--those don't set flags
|
276 |
|
|
||((wf_ALU)&&(~wf_mov)&&(~wf_ldilo)&&(~wf_brev)
|
277 |
|
|
&&(i_instruction[30:28] != 3'h7))));
|
278 |
|
|
|
279 |
|
|
reg [3:0] rh_op;
|
280 |
|
|
reg rh_break, rh_lock;
|
281 |
|
|
reg [4:0] rh_R, rh_A, rh_B;
|
282 |
|
|
reg rh_ALU, rh_MEM, rh_DIV, rh_FPU;
|
283 |
|
|
reg [3:0] rh_cond;
|
284 |
|
|
reg rh_rA, rh_rB, rh_wR, rh_wF;
|
285 |
|
|
wire [31:0] wh_I;
|
286 |
|
|
reg [4:0] rh_pI;
|
287 |
|
|
reg rh_Iz;
|
288 |
|
|
assign wh_I = { {(32-4){rh_pI[4]}}, rh_pI[3:0] };
|
289 |
|
|
always @(posedge i_clk)
|
290 |
|
|
if (i_ce)
|
291 |
|
|
begin
|
292 |
|
|
rh_op <= wf_op[3:0];
|
293 |
|
|
rh_break<= wf_break;
|
294 |
|
|
rh_lock <= wf_lock;
|
295 |
|
|
//
|
296 |
|
|
rh_R <= (wh_R);
|
297 |
|
|
rh_A <= (wh_A);
|
298 |
|
|
rh_B <= (wh_B);
|
299 |
|
|
//
|
300 |
|
|
rh_ALU <= wf_ALU;
|
301 |
|
|
rh_MEM <= wf_MEM;
|
302 |
|
|
rh_DIV <= wf_DIV;
|
303 |
|
|
rh_FPU <= wf_FPU;
|
304 |
|
|
|
305 |
|
|
rh_pI <= wh_pI;
|
306 |
|
|
rh_Iz <= wh_Iz;
|
307 |
|
|
|
308 |
|
|
// What are the conditions of this instruction?
|
309 |
|
|
rh_cond <= wh_cond;
|
310 |
|
|
|
311 |
|
|
// Do we read register 'A'?
|
312 |
|
|
rh_rA <= (wf_FPU)&&(wf_op[4:1]!=4'he)
|
313 |
|
|
||(wf_DIV)
|
314 |
|
|
||(wf_ALU)&&(~wf_mov)
|
315 |
|
|
||(wf_MEM)&&(wf_op[0])
|
316 |
|
|
||(wf_cmptst);
|
317 |
|
|
// Do we need to read register 'B'?
|
318 |
|
|
rh_rB <= (i_instruction[18])&&(~wf_ldi);
|
319 |
|
|
// Will we be writing register 'R'?
|
320 |
|
|
rh_wR <= ~wh_wR_n;
|
321 |
|
|
rh_wF <= wh_wF;
|
322 |
|
|
end
|
323 |
|
|
|
324 |
|
|
|
325 |
|
|
//////
|
326 |
|
|
//
|
327 |
|
|
// Path 3: Half size instruction, low half
|
328 |
|
|
//
|
329 |
|
|
//////
|
330 |
|
|
|
331 |
|
|
// The 5-bit opcode, as extracted
|
332 |
|
|
wire [4:0] wl_op;
|
333 |
|
|
// Instruction types
|
334 |
|
|
wire wl_ldi, wl_mov, wl_cmptst, wl_ldilo, wl_brev, wl_noop,
|
335 |
|
|
wl_break, wl_lock,
|
336 |
|
|
wl_ljmp, wl_ALU, wl_MEM, wl_DIV, wl_FPU;
|
337 |
|
|
wire [4:0] wl_R, wl_A, wl_B; // Instruction registers
|
338 |
|
|
wire [3:0] wl_cond;
|
339 |
|
|
wire wl_wF; // Write flags?
|
340 |
|
|
wire wl_wR, wl_wR_n, // Write destination register? or not?
|
341 |
|
|
wl_rA, // Read register A?
|
342 |
|
|
wl_rB; // Read register B?
|
343 |
|
|
wire [4:0] wl_pI; // Partial immediate ...
|
344 |
|
|
wire wl_Iz;
|
345 |
|
|
|
346 |
|
|
assign wl_op = i_instruction[9:5];
|
347 |
|
|
assign wl_brev = (wl_op == 5'hc);
|
348 |
|
|
assign wl_mov = (wl_op == 5'h0f);
|
349 |
|
|
assign wl_ldi = (wl_op[4:1] == 4'hb);
|
350 |
|
|
assign wl_cmptst=(wl_op[4:1] == 4'h8);
|
351 |
|
|
assign wl_ldilo= (wl_op[4:0] == 5'h9);
|
352 |
|
|
assign wl_noop = (wl_op[4:0] == 5'h18)&&(wl_R[3:1] == 3'h7);
|
353 |
|
|
assign wl_break= (wl_op[4:0] == 5'h19)&&(wl_R[3:1] == 3'h7);
|
354 |
|
|
assign wl_lock = (wl_op[4:0] == 5'h1a)&&(wl_R[3:1] == 3'h7);
|
355 |
|
|
//
|
356 |
|
|
assign wl_R = { i_gie, i_instruction[13:10] };
|
357 |
|
|
assign wl_A = { i_gie, i_instruction[13:10] };
|
358 |
|
|
assign wl_B = { i_gie, i_instruction[ 3: 0] };
|
359 |
|
|
//
|
360 |
|
|
assign wl_ALU = (~wl_op[4]);
|
361 |
|
|
assign wl_MEM = ( wl_op[4:1] == 4'h9);
|
362 |
|
|
assign wl_DIV = ( wl_op[4:1] == 4'ha);
|
363 |
|
|
assign wl_FPU = ( wl_op[4:2] == 3'h7)&&(i_instruction[30:28]==3'h7);
|
364 |
|
|
assign wl_ljmp = ( i_instruction[21:19] == 3'h00) // 1111_10010_1_1111
|
365 |
|
|
&&(i_instruction[13:0]==14'h3e5f);
|
366 |
|
|
|
367 |
|
|
assign wl_pI = (wl_ldi) ? { i_instruction[4:0] } // LDI
|
368 |
|
|
:((~i_instruction[4])
|
369 |
|
|
? { i_instruction[3], i_instruction[3:0] }
|
370 |
|
|
: 5'h0);
|
371 |
|
|
assign wl_Iz= (wl_pI == 5'h0);
|
372 |
|
|
|
373 |
|
|
// Will we be writing register R?
|
374 |
|
|
assign wl_wR_n = ((wl_MEM)&&(wl_op[0])) // Store's dont write regs
|
375 |
|
|
// Neither do NOOP, BREAK, or LOCKs
|
376 |
|
|
||((wl_op[4:3]==2'b11)&&(wl_R[3:1]==3'h7))
|
377 |
|
|
// nor CMPs and TSTs
|
378 |
|
|
||(wl_cmptst);
|
379 |
|
|
|
380 |
|
|
// What are the conditions for this instruction? NOOP, BREAK, and LOCK
|
381 |
|
|
// are also unconditional, but they'll just ignore this setting
|
382 |
|
|
assign wl_cond = (wl_ldi) ? 4'h8 // LDI is unconditional
|
383 |
|
|
: { (i_instruction[20:19]==2'h0),
|
384 |
|
|
1'b0, i_instruction[20:19] };
|
385 |
|
|
// How about the flags, will we be writing them?
|
386 |
|
|
assign wl_wF = (wl_cmptst) // Compares always write flags
|
387 |
|
|
||((wl_cond[3])&&(
|
388 |
|
|
// FPU and DIV instructions always write flags
|
389 |
|
|
(wl_FPU)||(wl_DIV)
|
390 |
|
|
// So do ALU instructions, UNLESS the ALU
|
391 |
|
|
// instruction is a MOV, LDILO, or BREV, or
|
392 |
|
|
// the results are being written into the PC
|
393 |
|
|
// or CC register--those don't set flags
|
394 |
|
|
||((wl_ALU)&&(~wl_mov)&&(~wl_ldilo)&&(~wl_brev)
|
395 |
|
|
&&(i_instruction[13:11] != 3'h7))));
|
396 |
|
|
|
397 |
|
|
reg [3:0] rl_op;
|
398 |
|
|
reg rl_break, rl_lock;
|
399 |
|
|
reg [4:0] rl_R, rl_A, rl_B;
|
400 |
|
|
reg rl_ALU, rl_MEM, rl_DIV, rl_FPU, rl_ljmp;
|
401 |
|
|
reg [3:0] rl_cond;
|
402 |
|
|
reg rl_rA, rl_rB, rl_wR, rl_wF;
|
403 |
|
|
wire [31:0] wl_I;
|
404 |
|
|
reg [4:0] rl_pI;
|
405 |
|
|
reg rl_Iz;
|
406 |
|
|
assign wl_I = { {(32-4){rl_pI[4]}}, rl_pI[3:0] };
|
407 |
|
|
always @(posedge i_clk)
|
408 |
|
|
if (i_ce)
|
409 |
|
|
begin
|
410 |
|
|
rl_op <= wl_op[3:0];
|
411 |
|
|
rl_break<= wl_break;
|
412 |
|
|
rl_lock <= wl_lock;
|
413 |
|
|
//
|
414 |
|
|
rl_R <= (wl_R);
|
415 |
|
|
rl_A <= (wl_A);
|
416 |
|
|
rl_B <= (wl_B);
|
417 |
|
|
//
|
418 |
|
|
rl_ALU <= (~wl_op[4]);
|
419 |
|
|
rl_MEM <= ( wl_op[4:1] == 4'h9);
|
420 |
|
|
rl_DIV <= ( wl_op[4:1] == 4'ha);
|
421 |
|
|
rl_FPU <= ( wl_op[4:2] == 3'h7)&&(i_instruction[30:28]==3'h7);
|
422 |
|
|
rl_ljmp <= wl_ljmp;
|
423 |
|
|
|
424 |
|
|
rl_pI <= wl_pI;
|
425 |
|
|
rl_Iz<= wl_Iz;
|
426 |
|
|
|
427 |
|
|
// What are the conditions of this instruction?
|
428 |
|
|
rl_cond <= wl_cond;
|
429 |
|
|
|
430 |
|
|
// Do we read register 'A'?
|
431 |
|
|
rl_rA <= (wl_FPU)&&(wl_op[4:1]!=4'he)
|
432 |
|
|
||(wl_DIV)
|
433 |
|
|
||(wl_ALU)&&(~wf_mov)
|
434 |
|
|
||(wl_MEM)&&(wl_op[0])
|
435 |
|
|
||(wl_cmptst);
|
436 |
|
|
// Do we need to read register 'B'?
|
437 |
|
|
rl_rB <= (i_instruction[18])&&(~wl_ldi);
|
438 |
|
|
// Will we be writing register 'R'?
|
439 |
|
|
rl_wR <= ~wl_wR_n;
|
440 |
|
|
// How about the flags?
|
441 |
|
|
rl_wF <= wl_wF;
|
442 |
|
|
end
|
443 |
|
|
|
444 |
|
|
//////
|
445 |
|
|
//
|
446 |
|
|
// Path 4: triplet instruction: MOV A,B; OP C,B
|
447 |
|
|
// becomes OP C,A -> B
|
448 |
|
|
//
|
449 |
|
|
//////
|
450 |
|
|
wire w_triplet;
|
451 |
|
|
reg r_triplet;
|
452 |
|
|
assign w_triplet =
|
453 |
|
|
// Must be a VLIW instruction
|
454 |
|
|
(i_instruction[31])
|
455 |
|
|
// First half must be a move
|
456 |
|
|
&&(i_instruction[26:22] == 5'h0f)
|
457 |
|
|
// Move destination must also be register A in 2nd Op
|
458 |
|
|
&&(i_instruction[30:27]==i_instruction[13:10])
|
459 |
|
|
// Only if this is unconditional, or share conditions
|
460 |
|
|
&&((i_instruction[21])|(i_instruction[20:19]==2'h0))
|
461 |
|
|
// Not if the destination is PC or CC regs
|
462 |
|
|
&&(i_instruction[30:28]!=3'h7);
|
463 |
|
|
always @(posedge i_clk)
|
464 |
|
|
if (i_ce)
|
465 |
|
|
r_triplet <= w_triplet;
|
466 |
|
|
|
467 |
|
|
// Now, let's string our instruction(s) together to create a useful
|
468 |
|
|
// decoded instruction
|
469 |
|
|
reg r_singlet, r_gie;
|
470 |
|
|
reg [(AW-1):0] r_pc;
|
471 |
|
|
always @(posedge i_clk)
|
472 |
|
|
if (i_ce)
|
473 |
|
|
begin
|
474 |
|
|
r_gie <= i_gie;
|
475 |
|
|
o_gie<= r_gie;
|
476 |
|
|
r_singlet <= ~i_instruction[31];
|
477 |
|
|
r_pc <= i_pc;
|
478 |
|
|
|
479 |
|
|
if (r_triplet)
|
480 |
|
|
begin
|
481 |
|
|
o_phase <= 1'b0;
|
482 |
|
|
o_pc <= r_pc + {{(AW-1){1'b0}}, 1'b1};
|
483 |
|
|
o_lock <= 1'b0;
|
484 |
|
|
o_break <= 1'b0;
|
485 |
|
|
o_R<={(rl_R=={r_gie, 4'he }),(rl_R=={r_gie,4'hf}),rl_R};
|
486 |
|
|
o_A<={(rh_B=={r_gie, 4'he }),(rh_B=={r_gie,4'hf}),rh_B};
|
487 |
|
|
o_B<={(rl_B=={r_gie, 4'he }),(rl_B=={r_gie,4'hf}),rl_B};
|
488 |
|
|
o_wR <= rl_wR;
|
489 |
|
|
o_rA <= 1'b1;
|
490 |
|
|
o_rB <= rl_rB;
|
491 |
|
|
o_cond<= rh_cond;
|
492 |
|
|
o_wF <= rl_wF;
|
493 |
|
|
o_I <= wl_I;
|
494 |
|
|
o_zI <= rl_Iz;
|
495 |
|
|
o_op <= rl_op;
|
496 |
|
|
o_ALU<= rl_ALU;
|
497 |
|
|
o_M<= rl_MEM;
|
498 |
|
|
o_DV<= rl_DIV;
|
499 |
|
|
o_FP <= rl_FPU;
|
500 |
|
|
o_ljmp <= 1'b0;
|
501 |
|
|
o_early_branch <= 1'b0;
|
502 |
|
|
o_branch_pc <= 0;
|
503 |
|
|
// o_pipe will never be true for a triplet
|
504 |
|
|
end else if (r_singlet)
|
505 |
|
|
begin
|
506 |
|
|
o_phase <= 1'b0;
|
507 |
|
|
o_pc <= r_pc + {{(AW-1){1'b0}}, 1'b1};
|
508 |
|
|
o_R<={(rf_R=={r_gie, 4'he }),(rf_R=={r_gie,4'hf}),rf_R};
|
509 |
|
|
o_A<={(rf_A=={r_gie, 4'he }),(rf_A=={r_gie,4'hf}),rf_A};
|
510 |
|
|
o_B<={(rf_B=={r_gie, 4'he }),(rf_B=={r_gie,4'hf}),rf_B};
|
511 |
|
|
o_break <= rf_break;
|
512 |
|
|
o_lock <= rf_lock;
|
513 |
|
|
o_wR <= rf_wR;
|
514 |
|
|
o_rA <= rf_rA;
|
515 |
|
|
o_rB <= rf_rB;
|
516 |
|
|
o_cond<= rf_cond;
|
517 |
|
|
o_wF <= rf_wF;
|
518 |
|
|
o_I <= wf_I;
|
519 |
|
|
o_zI <= rf_Iz;
|
520 |
|
|
o_op <= rf_op;
|
521 |
|
|
o_ALU<= rf_ALU;
|
522 |
|
|
o_M<= rf_MEM;
|
523 |
|
|
o_DV<= rf_DIV;
|
524 |
|
|
o_FP <= rf_FPU;
|
525 |
|
|
o_ljmp <= rf_ljmp;
|
526 |
|
|
o_early_branch <= (rf_ljmp);
|
527 |
|
|
o_branch_pc <= i_instruction[(AW-1):0];
|
528 |
|
|
end else if (~o_phase)
|
529 |
|
|
begin
|
530 |
|
|
o_phase <= 1'b1;
|
531 |
|
|
o_pc <= r_pc;
|
532 |
|
|
o_R<={(rh_R=={r_gie, 4'he }),(rh_R=={r_gie,4'hf}),rh_R};
|
533 |
|
|
o_A<={(rh_A=={r_gie, 4'he }),(rh_A=={r_gie,4'hf}),rh_A};
|
534 |
|
|
o_B<={(rh_B=={r_gie, 4'he }),(rh_B=={r_gie,4'hf}),rh_B};
|
535 |
|
|
o_lock <= rh_lock;
|
536 |
|
|
o_break <= rh_break;
|
537 |
|
|
o_wR <= rh_wR;
|
538 |
|
|
o_rA <= rh_rA;
|
539 |
|
|
o_rB <= rh_rB;
|
540 |
|
|
o_cond<= rh_cond;
|
541 |
|
|
o_wF <= rh_wF;
|
542 |
|
|
o_I <= wh_I;
|
543 |
|
|
o_zI <= rh_Iz;
|
544 |
|
|
o_op <= rh_op;
|
545 |
|
|
o_ALU<= rh_ALU;
|
546 |
|
|
o_M<= rh_MEM;
|
547 |
|
|
o_DV<= rh_DIV;
|
548 |
|
|
o_FP <= rh_FPU;
|
549 |
|
|
o_ljmp <= 1'b0; // Can't jump from high-half
|
550 |
|
|
o_early_branch <= 1'b0;
|
551 |
|
|
// o_branch_pc <= i_instruction;
|
552 |
|
|
end else begin
|
553 |
|
|
o_phase <= 1'b0;
|
554 |
|
|
o_pc <= r_pc + {{(AW-1){1'b0}}, 1'b1};
|
555 |
|
|
o_lock <= rl_lock;
|
556 |
|
|
o_break <= rl_break;
|
557 |
|
|
o_R<={(rl_R=={r_gie, 4'he }),(rl_R=={r_gie,4'hf}),rl_R};
|
558 |
|
|
o_A<={(rl_A=={r_gie, 4'he }),(rl_A=={r_gie,4'hf}),rl_A};
|
559 |
|
|
o_B<={(rl_B=={r_gie, 4'he }),(rl_B=={r_gie,4'hf}),rl_B};
|
560 |
|
|
o_wR <= rl_wR;
|
561 |
|
|
o_rA <= rl_rA;
|
562 |
|
|
o_rB <= rl_rB;
|
563 |
|
|
o_cond<= rl_cond;
|
564 |
|
|
o_wF <= rl_wF;
|
565 |
|
|
o_I <= wl_I;
|
566 |
|
|
o_zI <= rl_Iz;
|
567 |
|
|
o_op <= rl_op;
|
568 |
|
|
o_ALU<= rl_ALU;
|
569 |
|
|
o_M<= rl_MEM;
|
570 |
|
|
o_DV<= rl_DIV;
|
571 |
|
|
o_FP <= rl_FPU;
|
572 |
|
|
o_ljmp <= rl_ljmp;
|
573 |
|
|
o_early_branch <= 1'b0;
|
574 |
|
|
o_branch_pc <= i_instruction[(AW-1):0];
|
575 |
|
|
end
|
576 |
|
|
o_illegal <= 1'b0;
|
577 |
|
|
end
|
578 |
|
|
|
579 |
|
|
/*
|
580 |
|
|
always @(posedge i_clk)
|
581 |
|
|
begin
|
582 |
|
|
pipe_M <= { o_M, o_op[0] };
|
583 |
|
|
pipe_I <= o_I;
|
584 |
|
|
pipe_pI <= o_I+1;
|
585 |
|
|
pipe_B <= o_B[3:0];
|
586 |
|
|
pipe_rB<= o_rB;
|
587 |
|
|
pipe_AB <= ({ o_A[6:5], o_B[6:5] } == 4'h00) // 12 inputs
|
588 |
|
|
&&(o_A[3:0] != o_B[3:0]);
|
589 |
|
|
pipe_gie<= o_gie;
|
590 |
|
|
|
591 |
|
|
// 36 bits (18*2)
|
592 |
|
|
match_sI <= (pipe_I == o_I);
|
593 |
|
|
// 36 bits
|
594 |
|
|
match_pI <= (pipe_pI == o_I);
|
595 |
|
|
// 9 bits
|
596 |
|
|
match_regs <= (pipe_M[1])&&(pipe_M == { o_M, o_op[0] })
|
597 |
|
|
&&((~pipe_rB)||(pipe_B == o_B[3:0]));
|
598 |
|
|
// 9 inputs
|
599 |
|
|
match_cnd <= ((pipe_cnd == o_cond)||(o_cond[3]));
|
600 |
|
|
// 5 inputs
|
601 |
|
|
match_aux <= (pipe_gie == o_gie)&&(pipeAB)&&(pipe_rB==o_rB)
|
602 |
|
|
|
603 |
|
|
o_pipe <= ((match_sI)||(match_pI))&&(match_regs)&&(match_cnd)
|
604 |
|
|
&&(match_aux)&&(pipe_AB);
|
605 |
|
|
end
|
606 |
|
|
*/
|
607 |
|
|
|
608 |
|
|
/*
|
609 |
|
|
always @(posedge i_clk)
|
610 |
|
|
if (i_rst)
|
611 |
|
|
r_valid <= 1'b0;
|
612 |
|
|
else if ((i_ce)&&(o_ljmp))
|
613 |
|
|
r_valid <= 1'b0;
|
614 |
|
|
else if ((i_ce)&&(i_pf_valid))
|
615 |
|
|
r_valid <= 1'b1;
|
616 |
|
|
else if (~i_stalled)
|
617 |
|
|
r_valid <= 1'b0;
|
618 |
|
|
*/
|
619 |
|
|
|
620 |
|
|
endmodule
|