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

Subversion Repositories s6soc

[/] [s6soc/] [trunk/] [rtl/] [cpu/] [idecode.v] - Blame information for rev 47

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 46 dgisselq
////////////////////////////////////////////////////////////////////////////////
2 2 dgisselq
//
3
// Filename:    idecode.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.  This is specifically a version
9
//      designed to support a "Next Generation", or "Version 2" instruction
10
//      set as (currently) activated by the OPT_NEW_INSTRUCTION_SET option
11
//      in cpudefs.v.
12
//
13
//      I expect to (eventually) retire the old instruction set, at which point
14
//      this will become the default instruction set decoder.
15
//
16
//
17
// Creator:     Dan Gisselquist, Ph.D.
18
//              Gisselquist Technology, LLC
19
//
20 46 dgisselq
////////////////////////////////////////////////////////////////////////////////
21 2 dgisselq
//
22 46 dgisselq
// Copyright (C) 2015-2017, Gisselquist Technology, LLC
23 2 dgisselq
//
24
// This program is free software (firmware): you can redistribute it and/or
25
// modify it under the terms of  the GNU General Public License as published
26
// by the Free Software Foundation, either version 3 of the License, or (at
27
// your option) any later version.
28
//
29
// This program is distributed in the hope that it will be useful, but WITHOUT
30
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
31
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
32
// for more details.
33
//
34 46 dgisselq
// You should have received a copy of the GNU General Public License along
35
// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no
36
// target there if the PDF file isn't present.)  If not, see
37
// <http://www.gnu.org/licenses/> for a copy.
38
//
39 2 dgisselq
// License:     GPL, v3, as defined and found on www.gnu.org,
40
//              http://www.gnu.org/licenses/gpl.html
41
//
42
//
43 46 dgisselq
////////////////////////////////////////////////////////////////////////////////
44 2 dgisselq
//
45
//
46
//
47 46 dgisselq
`define CPU_SP_REG      4'hd
48 2 dgisselq
`define CPU_CC_REG      4'he
49
`define CPU_PC_REG      4'hf
50
//
51
`include "cpudefs.v"
52
//
53
//
54
//
55
module  idecode(i_clk, i_rst, i_ce, i_stalled,
56
                i_instruction, i_gie, i_pc, i_pf_valid,
57
                        i_illegal,
58
                o_phase, o_illegal,
59
                o_pc, o_gie,
60
                o_dcdR, o_dcdA, o_dcdB, o_I, o_zI,
61
                o_cond, o_wF,
62
                o_op, o_ALU, o_M, o_DV, o_FP, o_break, o_lock,
63
                o_wR, o_rA, o_rB,
64
                o_early_branch, o_branch_pc, o_ljmp,
65 46 dgisselq
                o_pipe,
66
                o_sim, o_sim_immv
67 2 dgisselq
                );
68
        parameter       ADDRESS_WIDTH=24, IMPLEMENT_MPY=1, EARLY_BRANCHING=1,
69
                        IMPLEMENT_DIVIDE=1, IMPLEMENT_FPU=0, AW = ADDRESS_WIDTH;
70
        input                   i_clk, i_rst, i_ce, i_stalled;
71
        input   [31:0]           i_instruction;
72
        input                   i_gie;
73
        input   [(AW-1):0]       i_pc;
74
        input                   i_pf_valid, i_illegal;
75
        output  wire            o_phase;
76
        output  reg             o_illegal;
77 46 dgisselq
        output  reg     [AW:0]   o_pc;
78 2 dgisselq
        output  reg             o_gie;
79
        output  reg     [6:0]    o_dcdR, o_dcdA, o_dcdB;
80
        output  wire    [31:0]   o_I;
81 46 dgisselq
        output  reg             o_zI;
82 2 dgisselq
        output  reg     [3:0]    o_cond;
83
        output  reg             o_wF;
84
        output  reg     [3:0]    o_op;
85 11 dgisselq
        output  reg             o_ALU, o_M, o_DV, o_FP, o_break;
86
        output  wire            o_lock;
87 2 dgisselq
        output  reg             o_wR, o_rA, o_rB;
88
        output  wire            o_early_branch;
89
        output  wire    [(AW-1):0]       o_branch_pc;
90
        output  wire            o_ljmp;
91 11 dgisselq
        output  wire            o_pipe;
92 46 dgisselq
        output  reg             o_sim           /* verilator public_flat */;
93
        output  reg     [22:0]   o_sim_immv      /* verilator public_flat */;
94 2 dgisselq
 
95
        wire    dcdA_stall, dcdB_stall, dcdF_stall;
96
        wire                    o_dcd_early_branch;
97
        wire    [(AW-1):0]       o_dcd_branch_pc;
98 46 dgisselq
        reg     o_dcdI, o_dcdIz;
99 11 dgisselq
`ifdef  OPT_PIPELINED
100 46 dgisselq
        reg     r_lock;
101 11 dgisselq
`endif
102 46 dgisselq
`ifdef  OPT_PIPELINED_BUS_ACCESS
103
        reg     r_pipe;
104
`endif
105 2 dgisselq
 
106
 
107
        wire    [4:0]    w_op;
108 11 dgisselq
        wire            w_ldi, w_mov, w_cmptst, w_ldilo, w_ALU, w_brev, w_noop;
109 2 dgisselq
        wire    [4:0]    w_dcdR, w_dcdB, w_dcdA;
110
        wire            w_dcdR_pc, w_dcdR_cc;
111
        wire            w_dcdA_pc, w_dcdA_cc;
112
        wire            w_dcdB_pc, w_dcdB_cc;
113
        wire    [3:0]    w_cond;
114 46 dgisselq
        wire            w_wF, w_mem, w_sto, w_lod, w_div, w_fpu;
115 2 dgisselq
        wire            w_wR, w_rA, w_rB, w_wR_n;
116 46 dgisselq
        wire            w_ljmp, w_ljmp_dly, w_cis_ljmp;
117 11 dgisselq
        wire    [31:0]   iword;
118 2 dgisselq
 
119
 
120 46 dgisselq
`ifdef  OPT_CIS
121
        reg     [15:0]   r_nxt_half;
122 2 dgisselq
        assign  iword = (o_phase)
123 46 dgisselq
                                // set second half as a NOOP ... but really
124 2 dgisselq
                                // shouldn't matter
125 46 dgisselq
                        ? { r_nxt_half[15:0], i_instruction[15:0] }
126 2 dgisselq
                        : i_instruction;
127
`else
128
        assign  iword = { 1'b0, i_instruction[30:0] };
129
`endif
130
 
131 11 dgisselq
        generate
132
        if (EARLY_BRANCHING != 0)
133 46 dgisselq
        begin
134
`ifdef  OPT_CIS
135
                reg     r_pre_ljmp;
136
                always @(posedge i_clk)
137
                if ((i_rst)||(o_early_branch))
138
                        r_pre_ljmp <= 1'b0;
139
                else if ((i_ce)&&(i_pf_valid))
140
                        r_pre_ljmp <= (!o_phase)&&(i_instruction[31])
141
                                &&(i_instruction[14:0] == 15'h7cf8);
142
                else if (i_ce)
143
                        r_pre_ljmp <= 1'b0;
144
 
145
                assign  w_cis_ljmp = r_pre_ljmp;
146
`else
147
                assign  w_cis_ljmp = 1'b0;
148
`endif
149
                // 0.1111.10010.000.1.1111.000000000...
150
                // 0111.1100.1000.0111.11000....
151 11 dgisselq
                assign  w_ljmp = (iword == 32'h7c87c000);
152 46 dgisselq
        end else begin
153
                assign  w_cis_ljmp = 1'b0;
154 11 dgisselq
                assign  w_ljmp = 1'b0;
155 46 dgisselq
        end
156 11 dgisselq
        endgenerate
157
 
158 46 dgisselq
`ifdef  OPT_CIS
159
`ifdef  VERILATOR
160
        wire    [4:0]    w_cis_op;
161
        always @(iword)
162
                if (!iword[31])
163
                        w_cis_op = w_op;
164
                else case(iword[26:24])
165
                3'h0: w_cis_op = 5'h00;
166
                3'h1: w_cis_op = 5'h01;
167
                3'h2: w_cis_op = 5'h02;
168
                3'h3: w_cis_op = 5'h10;
169
                3'h4: w_cis_op = 5'h12;
170
                3'h5: w_cis_op = 5'h13;
171
                3'h6: w_cis_op = 5'h18;
172
                3'h7: w_cis_op = 5'h0d;
173
                endcase
174
`else
175
        reg     [4:0]    w_cis_op;
176
        always @(iword,w_op)
177
                if (!iword[31])
178
                        w_cis_op <= w_op;
179
                else case(iword[26:24])
180
                3'h0: w_cis_op <= 5'h00;
181
                3'h1: w_cis_op <= 5'h01;
182
                3'h2: w_cis_op <= 5'h02;
183
                3'h3: w_cis_op <= 5'h10;
184
                3'h4: w_cis_op <= 5'h12;
185
                3'h5: w_cis_op <= 5'h13;
186
                3'h6: w_cis_op <= 5'h18;
187
                3'h7: w_cis_op <= 5'h0d;
188
                endcase
189
`endif
190
`else
191
        wire    [4:0]    w_cis_op;
192
        assign  w_cis_op = w_op;
193
`endif
194 11 dgisselq
 
195 2 dgisselq
        assign  w_op= iword[26:22];
196 46 dgisselq
        assign  w_mov    = (w_cis_op      == 5'h0d);
197
        assign  w_ldi    = (w_cis_op[4:1] == 4'hc);
198
        assign  w_brev   = (w_cis_op      == 5'h8);
199
        assign  w_cmptst = (w_cis_op[4:1] == 4'h8);
200
        assign  w_ldilo  = (w_cis_op[4:0] == 5'h9);
201
        assign  w_ALU    = (!w_cis_op[4]) // anything with [4]==0, but ...
202
                                &&(w_cis_op[3:1] != 3'h7); // not the divide
203 2 dgisselq
 
204 46 dgisselq
 
205
        // w_dcdR (4 LUTs)
206 11 dgisselq
        //
207 46 dgisselq
        // What register will we be placing results into (if at all)?
208
        //
209 11 dgisselq
        // Two parts to the result register: the register set, given for
210 46 dgisselq
        // moves in iword[18] but only for the supervisor, and the other
211 11 dgisselq
        // four bits encoded in the instruction.
212
        //
213 46 dgisselq
        assign  w_dcdR = { ((!iword[31])&&(w_mov)&&(~i_gie))?iword[18]:i_gie,
214 2 dgisselq
                                iword[30:27] };
215 11 dgisselq
        // 2 LUTs
216
        //
217
        // If the result register is either CC or PC, and this would otherwise
218
        // be a floating point instruction with floating point opcode of 0,
219
        // then this is a NOOP.
220 46 dgisselq
        assign  w_noop   = (!iword[31])&&(w_op[4:0] == 5'h1f)&&(
221
                        ((IMPLEMENT_FPU>0)&&(w_dcdR[3:1] == 3'h7))
222
                        ||(IMPLEMENT_FPU==0));
223 11 dgisselq
 
224 46 dgisselq
        // dcdB - What register is used in the opB?
225
        //
226
        assign w_dcdB[4] = ((!iword[31])&&(w_mov)&&(~i_gie))?iword[13]:i_gie;
227
        assign w_dcdB[3:0]= (iword[31])
228
                                ? (((!iword[23])&&(iword[26:25]==2'b10))
229
                                        ? `CPU_SP_REG : iword[22:19])
230
                                : iword[17:14];
231 2 dgisselq
 
232
        // 0 LUTs
233 46 dgisselq
        assign  w_dcdA = w_dcdR;        // on ZipCPU, A is always result reg
234 2 dgisselq
        // 2 LUTs, 1 delay each
235
        assign  w_dcdR_pc = (w_dcdR == {i_gie, `CPU_PC_REG});
236
        assign  w_dcdR_cc = (w_dcdR == {i_gie, `CPU_CC_REG});
237
        // 0 LUTs
238
        assign  w_dcdA_pc = w_dcdR_pc;
239
        assign  w_dcdA_cc = w_dcdR_cc;
240
        // 2 LUTs, 1 delays each
241 46 dgisselq
        assign  w_dcdB_pc = (w_rB)&&(w_dcdB[3:0] == `CPU_PC_REG);
242
        assign  w_dcdB_cc = (w_rB)&&(w_dcdB[3:0] == `CPU_CC_REG);
243 2 dgisselq
 
244
        // Under what condition will we execute this
245
        // instruction?  Only the load immediate instruction
246
        // is completely unconditional.
247
        //
248
        // 3+4 LUTs
249 46 dgisselq
        assign  w_cond = ((w_ldi)||(iword[31])) ? 4'h8 :
250
                        { (iword[21:19]==3'h0), iword[21:19] };
251 2 dgisselq
 
252
        // 1 LUT
253 46 dgisselq
        assign  w_mem    = (w_cis_op[4:3] == 2'b10)&&(w_cis_op[2:1] !=2'b00);
254
        assign  w_sto     = (w_mem)&&( w_cis_op[0]);
255
        assign  w_lod     = (w_mem)&&(!w_cis_op[0]);
256 2 dgisselq
        // 1 LUT
257 46 dgisselq
        assign  w_div     = (!iword[31])&&(w_op[4:1] == 4'h7);
258
        // 2 LUTs
259
        assign  w_fpu   = (!iword[31])&&(w_op[4:3] == 2'b11)
260
                                &&(w_dcdR[3:1] != 3'h7)&&(w_op[2:1] != 2'b00);
261
        //
262
        // rA - do we need to read register A?
263
        assign  w_rA = // Floating point reads reg A
264
                        ((w_fpu)&&(w_cis_op[4:1] != 4'hf))
265
                        // Divide's read A
266
                        ||(w_div)
267
                        // ALU ops read A,
268
                        //      except for MOV's and BREV's which don't
269
                        ||((w_ALU)&&(!w_brev)&&(!w_mov))
270
                        // STO's read A
271
                        ||(w_sto)
272
                        // Test/compares
273
                        ||(w_cmptst);
274
        // rB -- do we read a register for operand B?  Specifically, do we
275
        // add the registers value to the immediate to create opB?
276
        assign  w_rB     = (w_mov)
277
                                ||((!iword[31])&&(iword[18])&&(!w_ldi))
278
                                ||(( iword[31])&&(iword[23])&&(!w_ldi))
279
                                // If using compressed instruction sets,
280
                                // we *always* read on memory operands.
281
                                ||(( iword[31])&&(w_mem));
282
        // wR -- will we be writing our result back?
283
        // wR_n = !wR
284 2 dgisselq
        // 1 LUT: All but STO, NOOP/BREAK/LOCK, and CMP/TST write back to w_dcdR
285 46 dgisselq
        assign  w_wR_n   = (w_sto)
286
                                ||((!iword[31])&&(w_cis_op[4:3]==2'b11)
287
                                        &&(w_cis_op[2:1]!=2'b00)
288
                                        &&(w_dcdR[3:1]==3'h7))
289 2 dgisselq
                                ||(w_cmptst);
290
        assign  w_wR     = ~w_wR_n;
291
        //
292 46 dgisselq
        // wF -- do we write flags when we are done?
293
        //
294 2 dgisselq
        assign  w_wF     = (w_cmptst)
295 46 dgisselq
                        ||((w_cond[3])&&((w_fpu)||(w_div)
296
                                ||((w_ALU)&&(!w_mov)&&(!w_ldilo)&&(!w_brev)
297
                                        &&(w_dcdR[3:1] != 3'h7))));
298 2 dgisselq
 
299
        // Bottom 13 bits: no LUT's
300
        // w_dcd[12: 0] -- no LUTs
301
        // w_dcd[   13] -- 2 LUTs
302
        // w_dcd[17:14] -- (5+i0+i1) = 3 LUTs, 1 delay
303
        // w_dcd[22:18] : 5 LUTs, 1 delay (assuming high bit is o/w determined)
304
        reg     [22:0]   r_I;
305
        wire    [22:0]   w_I, w_fullI;
306
        wire            w_Iz;
307
 
308
        assign  w_fullI = (w_ldi) ? { iword[22:0] } // LDI
309 46 dgisselq
                        // MOVE immediates have one less bit
310
                        :((w_mov) ?{ {(23-13){iword[12]}}, iword[12:0] }
311
                        // Normal Op-B immediate ... 18 or 14 bits
312 2 dgisselq
                        :((~iword[18]) ? { {(23-18){iword[17]}}, iword[17:0] }
313
                        : { {(23-14){iword[13]}}, iword[13:0] }
314
                        ));
315
 
316 46 dgisselq
`ifdef  OPT_CIS
317
        wire    [7:0]    w_halfbits;
318
        assign  w_halfbits = iword[23:16];
319
 
320
        wire    [7:0]    w_halfI;
321
        assign  w_halfI = (iword[26:24]==3'h6) ? w_halfbits[7:0]
322
                        :(w_halfbits[7])?
323
                                { {(6){w_halfbits[2]}}, w_halfbits[1:0]}
324
                                :{ w_halfbits[6], w_halfbits[6:0] };
325
        assign  w_I  = (iword[31])?{{(23-8){w_halfI[7]}}, w_halfI }:w_fullI;
326 2 dgisselq
`else
327
        assign  w_I  = w_fullI;
328
`endif
329
        assign  w_Iz = (w_I == 0);
330
 
331
 
332 46 dgisselq
`ifdef  OPT_CIS
333 2 dgisselq
        //
334
        // The o_phase parameter is special.  It needs to let the software
335
        // following know that it cannot break/interrupt on an o_phase asserted
336
        // instruction, lest the break take place between the first and second
337 46 dgisselq
        // half of a CIS instruction.  To do this, o_phase must be asserted
338 2 dgisselq
        // when the first instruction half is valid, but not asserted on either
339
        // a 32-bit instruction or the second half of a 2x16-bit instruction.
340
        reg     r_phase;
341
        initial r_phase = 1'b0;
342
        always @(posedge i_clk)
343 46 dgisselq
                if ((i_rst) // When no instruction is in the pipe, phase is zero
344
                        ||(o_early_branch)||(w_ljmp_dly))
345 2 dgisselq
                        r_phase <= 1'b0;
346 46 dgisselq
                else if ((i_ce)&&(i_pf_valid))
347
                        r_phase <= (o_phase)? 1'b0
348
                                : ((i_instruction[31])&&(i_pf_valid));
349 2 dgisselq
                else if (i_ce)
350 46 dgisselq
                        r_phase <= 1'b0;
351 2 dgisselq
        // Phase is '1' on the first instruction of a two-part set
352
        // But, due to the delay in processing, it's '1' when our output is
353
        // valid for that first part, but that'll be the same time we
354
        // are processing the second part ... so it may look to us like a '1'
355
        // on the second half of processing.
356
 
357
        assign  o_phase = r_phase;
358
`else
359
        assign  o_phase = 1'b0;
360
`endif
361
 
362
 
363
        initial o_illegal = 1'b0;
364
        always @(posedge i_clk)
365
                if (i_rst)
366
                        o_illegal <= 1'b0;
367
                else if (i_ce)
368
                begin
369 46 dgisselq
`ifdef  OPT_CIS
370 2 dgisselq
                        o_illegal <= (i_illegal);
371
`else
372
                        o_illegal <= ((i_illegal) || (i_instruction[31]));
373
`endif
374 46 dgisselq
                        if ((IMPLEMENT_MPY==0)&&((w_cis_op[4:1]==4'h5)||(w_cis_op[4:0]==5'h0c)))
375 2 dgisselq
                                o_illegal <= 1'b1;
376
 
377 46 dgisselq
                        if ((IMPLEMENT_DIVIDE==0)&&(w_div))
378 2 dgisselq
                                o_illegal <= 1'b1;
379 46 dgisselq
                        else if ((IMPLEMENT_DIVIDE!=0)&&(w_div)&&(w_dcdR[3:1]==3'h7))
380 2 dgisselq
                                o_illegal <= 1'b1;
381
 
382
 
383 46 dgisselq
                        if ((IMPLEMENT_FPU==0)&&(w_fpu))
384 2 dgisselq
                                o_illegal <= 1'b1;
385
 
386 46 dgisselq
                        if ((w_cis_op[4:3]==2'b11)&&(w_cis_op[2:1]!=2'b00)
387
                                &&(w_dcdR[3:1]==3'h7)
388 2 dgisselq
                                &&(
389 46 dgisselq
                                        (w_cis_op[2:0] != 3'h4)  // BREAK
390 11 dgisselq
`ifdef  OPT_PIPELINED
391 46 dgisselq
                                        &&(w_cis_op[2:0] != 3'h5)        // LOCK
392 11 dgisselq
`endif
393 46 dgisselq
                                        // SIM instructions are always illegal
394
                                        &&(w_cis_op[2:0] != 3'h7)))      // NOOP
395 2 dgisselq
                                o_illegal <= 1'b1;
396
                end
397
 
398
 
399
        always @(posedge i_clk)
400
                if (i_ce)
401
                begin
402 46 dgisselq
`ifdef  OPT_CIS
403
                        if (!o_phase)
404 2 dgisselq
                                o_gie<= i_gie;
405 46 dgisselq
 
406
                        if ((iword[31])&&(!o_phase))
407
                                o_pc <= { i_pc, 1'b1 };
408
                        else if ((iword[31])&&(i_pf_valid))
409
                                o_pc <= { i_pc, 1'b0 };
410
                        else
411
                                o_pc <= { i_pc + 1'b1, 1'b0 };
412 2 dgisselq
`else
413
                        o_gie<= i_gie;
414 46 dgisselq
                        o_pc <= { i_pc + 1'b1, 1'b0 };
415 2 dgisselq
`endif
416
 
417
                        // Under what condition will we execute this
418
                        // instruction?  Only the load immediate instruction
419
                        // is completely unconditional.
420
                        o_cond <= w_cond;
421
                        // Don't change the flags on conditional instructions,
422
                        // UNLESS: the conditional instruction was a CMP
423
                        // or TST instruction.
424
                        o_wF <= w_wF;
425
 
426
                        // Record what operation/op-code (4-bits) we are doing
427
                        //      Note that LDI magically becomes a MOV
428
                        //      instruction here.  That way it's a pass through
429
                        //      the ALU.  Likewise, the two compare instructions
430
                        //      CMP and TST becomes SUB and AND here as well.
431
                        // We keep only the bottom four bits, since we've
432 46 dgisselq
                        // already done the rest of the decode necessary to
433 2 dgisselq
                        // settle between the other instructions.  For example,
434
                        // o_FP plus these four bits uniquely defines the FP
435
                        // instruction, o_DV plus the bottom of these defines
436
                        // the divide, etc.
437 46 dgisselq
                        o_op <= ((w_ldi)||(w_noop))? 4'hd : w_cis_op[3:0];
438 2 dgisselq
 
439
                        // Default values
440
                        o_dcdR <= { w_dcdR_cc, w_dcdR_pc, w_dcdR};
441
                        o_dcdA <= { w_dcdA_cc, w_dcdA_pc, w_dcdA};
442
                        o_dcdB <= { w_dcdB_cc, w_dcdB_pc, w_dcdB};
443
                        o_wR  <= w_wR;
444
                        o_rA  <= w_rA;
445
                        o_rB  <= w_rB;
446
                        r_I    <= w_I;
447 46 dgisselq
                        o_zI   <= w_Iz;
448 2 dgisselq
 
449 46 dgisselq
                        // Turn a NOOP into an ALU operation--subtract in
450 11 dgisselq
                        // particular, although it doesn't really matter as long
451
                        // as it doesn't take longer than one clock.  Note
452
                        // also that this depends upon not setting any registers
453
                        // or flags, which should already be true.
454 46 dgisselq
                        o_ALU  <=  (w_ALU)||(w_ldi)||(w_cmptst)||(w_noop);
455
                        o_M    <=  w_mem;
456
                        o_DV   <=  w_div;
457
                        o_FP   <=  w_fpu;
458 2 dgisselq
 
459 46 dgisselq
                        o_break <= (!iword[31])&&(w_op[4:0]==5'h1c)&&(
460
                                ((IMPLEMENT_FPU>0)&&(w_dcdR[3:1]==3'h7))
461
                                ||(IMPLEMENT_FPU==0));
462 11 dgisselq
`ifdef  OPT_PIPELINED
463 46 dgisselq
                        r_lock  <= (!iword[31])&&(w_op[4:0]==5'h1d)&&(
464
                                ((IMPLEMENT_FPU>0)&&(w_dcdR[3:1]==3'h7))
465
                                ||(IMPLEMENT_FPU==0));
466 11 dgisselq
`endif
467 46 dgisselq
`ifdef  OPT_CIS
468
                        r_nxt_half <= { iword[31], iword[14:0] };
469 2 dgisselq
`endif
470 46 dgisselq
 
471
`ifdef  VERILATOR
472
                        // Support the SIM instruction(s)
473
                        o_sim <= (!iword[31])&&(w_op[4:1] == 4'hf)
474
                                &&(w_dcdR[3:1] == 3'h7);
475
`else
476
                        o_sim <= 1'b0;
477
`endif
478
                        o_sim_immv <= iword[22:0];
479 2 dgisselq
                end
480
 
481 11 dgisselq
`ifdef  OPT_PIPELINED
482
        assign  o_lock = r_lock;
483
`else
484
        assign  o_lock = 1'b0;
485
`endif
486
 
487 2 dgisselq
        generate
488
        if (EARLY_BRANCHING!=0)
489
        begin
490
                reg                     r_early_branch, r_ljmp;
491
                reg     [(AW-1):0]       r_branch_pc;
492
 
493
                initial r_ljmp = 1'b0;
494
                always @(posedge i_clk)
495
                        if (i_rst)
496
                                r_ljmp <= 1'b0;
497 46 dgisselq
`ifdef  OPT_CIS
498
                        else if ((i_ce)&&(o_phase))
499
                                r_ljmp <= w_cis_ljmp;
500
`endif
501 2 dgisselq
                        else if ((i_ce)&&(i_pf_valid))
502
                                r_ljmp <= (w_ljmp);
503
                assign  o_ljmp = r_ljmp;
504
 
505
                always @(posedge i_clk)
506
                if (i_rst)
507
                        r_early_branch <= 1'b0;
508
                else if ((i_ce)&&(i_pf_valid))
509
                begin
510
                        if (r_ljmp)
511
                                // LOD (PC),PC
512
                                r_early_branch <= 1'b1;
513 46 dgisselq
                        else if ((!iword[31])&&(iword[30:27]==`CPU_PC_REG)
514
                                        &&(w_cond[3]))
515 2 dgisselq
                        begin
516 46 dgisselq
                                if ((w_op[4:0]==5'h02)&&(!iword[18]))
517 2 dgisselq
                                        // Add x,PC
518
                                        r_early_branch     <= 1'b1;
519 46 dgisselq
                                else
520 2 dgisselq
                                        r_early_branch     <= 1'b0;
521
                        end else
522
                                r_early_branch <= 1'b0;
523
                end else if (i_ce)
524
                        r_early_branch <= 1'b0;
525
 
526
                always @(posedge i_clk)
527
                        if (i_ce)
528
                        begin
529
                                if (r_ljmp)
530 46 dgisselq
                                        r_branch_pc <= iword[(AW+1):2];
531 2 dgisselq
                                else // Add x,PC
532
                                r_branch_pc <= i_pc
533 46 dgisselq
                                        + {{(AW-15){iword[17]}},iword[16:2]}
534 2 dgisselq
                                        + {{(AW-1){1'b0}},1'b1};
535
                        end
536
 
537 46 dgisselq
                assign  w_ljmp_dly         = r_ljmp;
538 2 dgisselq
                assign  o_early_branch     = r_early_branch;
539
                assign  o_branch_pc        = r_branch_pc;
540
        end else begin
541 46 dgisselq
                assign  w_ljmp_dly         = 1'b0;
542 2 dgisselq
                assign  o_early_branch = 1'b0;
543
                assign  o_branch_pc = {(AW){1'b0}};
544
                assign  o_ljmp = 1'b0;
545
        end endgenerate
546
 
547
 
548
        // To be a pipeable operation there must be ...
549
        //      1. Two valid adjacent instructions
550
        //      2. Both must be memory operations, of the same time (both lods
551
        //              or both stos)
552
        //      3. Both must use the same register base address
553
        //      4. Both must be to the same address, or the address incremented
554
        //              by one
555
        // Note that we're not using iword here ... there's a lot of logic
556
        // taking place, and it's only valid if the new word is not compressed.
557
        //
558
        reg     r_valid;
559 46 dgisselq
`ifdef  OPT_PIPELINED_BUS_ACCESS
560 11 dgisselq
        initial r_pipe = 1'b0;
561 2 dgisselq
        always @(posedge i_clk)
562
                if (i_ce)
563 46 dgisselq
                        r_pipe <= (r_valid)&&((i_pf_valid)||(o_phase))
564
                                // Both must be memory operations
565
                                &&(w_mem)&&(o_M)
566
                                // Both must be writes, or both stores
567
                                &&(o_op[0] == w_cis_op[0])
568
                                // Both must be register ops
569
                                &&(w_rB)
570
                                // Both must use the same register for B
571
                                &&(w_dcdB[3:0] == o_dcdB[3:0])
572
                                // But ... the result can never be B
573
                                &&((o_op[0])
574
                                        ||(w_dcdB[3:0] != o_dcdA[3:0]))
575
                                // Needs to be to the mode, supervisor or user
576 2 dgisselq
                                &&(i_gie == o_gie)
577 46 dgisselq
                                // Same condition, or no condition before
578 2 dgisselq
                                &&((i_instruction[21:19]==o_cond[2:0])
579
                                        ||(o_cond[2:0] == 3'h0))
580 46 dgisselq
                                // Same immediate
581
                                &&((w_I[13:2]==r_I[13:2])
582
                                        ||({1'b0, w_I[13:2]}==(r_I[13:2]+12'h1)));
583 11 dgisselq
        assign o_pipe = r_pipe;
584 46 dgisselq
`else
585
        assign o_pipe = 1'b0;
586
`endif
587 11 dgisselq
 
588 2 dgisselq
        always @(posedge i_clk)
589
                if (i_rst)
590
                        r_valid <= 1'b0;
591
                else if ((i_ce)&&(o_ljmp))
592
                        r_valid <= 1'b0;
593
                else if ((i_ce)&&(i_pf_valid))
594
                        r_valid <= 1'b1;
595
                else if (~i_stalled)
596
                        r_valid <= 1'b0;
597
 
598 46 dgisselq
 
599 2 dgisselq
        assign  o_I = { {(32-22){r_I[22]}}, r_I[21:0] };
600
 
601
endmodule

powered by: WebSVN 2.1.0

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