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

Subversion Repositories zipcpu

[/] [zipcpu/] [trunk/] [rtl/] [core/] [idecode.v] - Blame information for rev 69

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

Line No. Rev Author Line
1 69 dgisselq
///////////////////////////////////////////////////////////////////////////////
2
//
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
///////////////////////////////////////////////////////////////////////////////
21
//
22
// Copyright (C) 2015, Gisselquist Technology, LLC
23
//
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
// License:     GPL, v3, as defined and found on www.gnu.org,
35
//              http://www.gnu.org/licenses/gpl.html
36
//
37
//
38
///////////////////////////////////////////////////////////////////////////////
39
//
40
//
41
//
42
`define CPU_CC_REG      4'he
43
`define CPU_PC_REG      4'hf
44
//
45
`include "cpudefs.v"
46
//
47
//
48
//
49
module  idecode(i_clk, i_rst, i_ce, i_stalled,
50
                i_instruction, i_gie, i_pc, i_pf_valid,
51
                        i_illegal,
52
                o_phase, o_illegal,
53
                o_pc, o_gie,
54
                o_dcdR, o_dcdA, o_dcdB, o_I, o_zI,
55
                o_cond, o_wF,
56
                o_op, o_ALU, o_M, o_DV, o_FP, o_break, o_lock,
57
                o_wR, o_rA, o_rB,
58
                o_early_branch, o_branch_pc
59
                );
60
        parameter       ADDRESS_WIDTH=24, IMPLEMENT_MPY=1, EARLY_BRANCHING=1,
61
                        IMPLEMENT_DIVIDE=1, IMPLEMENT_FPU=0, AW = ADDRESS_WIDTH;
62
        input                   i_clk, i_rst, i_ce, i_stalled;
63
        input   [31:0]           i_instruction;
64
        input                   i_gie;
65
        input   [(AW-1):0]       i_pc;
66
        input                   i_pf_valid, i_illegal;
67
        output  wire            o_phase;
68
        output  reg             o_illegal;
69
        output  reg     [(AW-1):0]       o_pc;
70
        output  reg             o_gie;
71
        output  reg     [6:0]    o_dcdR, o_dcdA, o_dcdB;
72
        output  wire    [31:0]   o_I;
73
        output  reg             o_zI;
74
        output  reg     [3:0]    o_cond;
75
        output  reg             o_wF;
76
        output  reg     [3:0]    o_op;
77
        output  reg             o_ALU, o_M, o_DV, o_FP, o_break, o_lock;
78
        output  reg             o_wR, o_rA, o_rB;
79
        output  wire            o_early_branch;
80
        output  wire    [(AW-1):0]       o_branch_pc;
81
 
82
        wire    dcdA_stall, dcdB_stall, dcdF_stall;
83
        wire                    o_dcd_early_branch;
84
        wire    [(AW-1):0]       o_dcd_branch_pc;
85
        reg     o_dcdI, o_dcdIz;
86
 
87
 
88
        wire    [4:0]    w_op;
89
        wire            w_ldi, w_mov, w_cmptst, w_ldixx, w_ALU;
90
        wire    [4:0]    w_dcdR, w_dcdB, w_dcdA;
91
        wire            w_dcdR_pc, w_dcdR_cc;
92
        wire            w_dcdA_pc, w_dcdA_cc;
93
        wire            w_dcdB_pc, w_dcdB_cc;
94
        wire    [3:0]    w_cond;
95
        wire            w_wF, w_dcdM, w_dcdDV, w_dcdFP;
96
        wire            w_wR, w_rA, w_rB, w_wR_n;
97
 
98
 
99
        wire    [31:0]   iword;
100
`ifdef  OPT_VLIW
101
        reg     [16:0]   r_nxt_half;
102
        assign  iword = (o_phase)
103
                                // set second half as a NOOP ... but really 
104
                                // shouldn't matter
105
                        ? { r_nxt_half[16:7], 1'b0, r_nxt_half[6:0], 5'b11000, 3'h7, 6'h00 }
106
                        : i_instruction;
107
`else
108
        assign  iword = { 1'b0, i_instruction[30:0] };
109
`endif
110
 
111
        assign  w_op= iword[26:22];
112
        assign  w_mov    = (w_op      == 5'h0f);
113
        assign  w_ldi    = (w_op[4:1] == 4'hb);
114
        assign  w_cmptst = (w_op[4:1] == 4'h8);
115
        assign  w_ldixx  = (w_op[4:1] == 4'h4);
116
        assign  w_ALU    = (~w_op[4]);
117
 
118
        // 4 LUTs
119
        assign  w_dcdR = { ((~iword[31])&&(w_mov)&&(~i_gie))?iword[18]:i_gie,
120
                                iword[30:27] };
121
        // 4 LUTs
122
        assign  w_dcdB = { ((~iword[31])&&(w_mov)&&(~i_gie))?iword[13]:i_gie,
123
                                iword[17:14] };
124
 
125
        // 0 LUTs
126
        assign  w_dcdA = w_dcdR;
127
        // 2 LUTs, 1 delay each
128
        assign  w_dcdR_pc = (w_dcdR == {i_gie, `CPU_PC_REG});
129
        assign  w_dcdR_cc = (w_dcdR == {i_gie, `CPU_CC_REG});
130
        // 0 LUTs
131
        assign  w_dcdA_pc = w_dcdR_pc;
132
        assign  w_dcdA_cc = w_dcdR_cc;
133
        // 2 LUTs, 1 delays each
134
        assign  w_dcdB_pc = (w_dcdB[3:0] == `CPU_PC_REG);
135
        assign  w_dcdB_cc = (w_dcdB[3:0] == `CPU_CC_REG);
136
 
137
        // Under what condition will we execute this
138
        // instruction?  Only the load immediate instruction
139
        // is completely unconditional.
140
        //
141
        // 3+4 LUTs
142
        assign  w_cond = (w_ldi) ? 4'h8 :
143
                        (iword[31])?{(iword[20:19]==2'b00),
144
                                        1'b0,iword[20:19]}
145
                        : { (iword[21:19]==3'h0), iword[21:19] };
146
 
147
        // 1 LUT
148
        assign  w_dcdM    = (w_op[4:1] == 4'h9);
149
        // 1 LUT
150
        assign  w_dcdDV   = (w_op[4:1] == 4'ha);
151
        // 1 LUT
152
        assign  w_dcdFP   = (w_op[4:3] == 2'b11)&&(w_dcdR[3:1] != 3'h7);
153
        // 4 LUT's--since it depends upon FP/NOOP condition (vs 1 before)
154
        //      Everything reads A but ... NOOP/BREAK/LOCK, LDI, LOD, MOV
155
        assign  w_rA     = (w_dcdFP)
156
                                // Divide's read A
157
                                ||(w_dcdDV)
158
                                // ALU read's A, unless it's a MOV to A
159
                                // This includes LDIHI/LDILO
160
                                ||((~w_op[4])&&(w_op[3:0]!=4'hf))
161
                                // STO's read A
162
                                ||((w_dcdM)&&(w_op[0]))
163
                                // Test/compares
164
                                ||(w_op[4:1]== 4'h8);
165
        // 1 LUTs -- do we read a register for operand B?  Specifically, do
166
        // we need to stall if the register is not (yet) ready?
167
        assign  w_rB     = (w_mov)||((iword[18])&&((~w_ldi)&&(~w_ldixx)));
168
        // 1 LUT: All but STO, NOOP/BREAK/LOCK, and CMP/TST write back to w_dcdR
169
        assign  w_wR_n   = ((w_dcdM)&&(w_op[0]))
170
                                ||((w_op[4:3]==2'b11)&&(w_dcdR[3:1]==3'h7))
171
                                ||(w_cmptst);
172
        assign  w_wR     = ~w_wR_n;
173
        // 1-output bit (5 Opcode bits, 3 out-reg bits, 3 condition bits)
174
        //      
175
        //      This'd be 4 LUTs, save that we have the carve out for NOOPs
176
        assign  w_wF     = (w_cmptst)
177
                        ||((w_cond[3])&&((w_dcdFP)||(w_dcdDV)
178
                                ||((w_ALU)&&(~w_mov)&&(~w_ldixx))));
179
 
180
        // Bottom 13 bits: no LUT's
181
        // w_dcd[12: 0] -- no LUTs
182
        // w_dcd[   13] -- 2 LUTs
183
        // w_dcd[17:14] -- (5+i0+i1) = 3 LUTs, 1 delay
184
        // w_dcd[22:18] : 5 LUTs, 1 delay (assuming high bit is o/w determined)
185
        reg     [22:0]   r_I;
186
        wire    [22:0]   w_I, w_fullI;
187
        wire            w_Iz;
188
 
189
        assign  w_fullI = (w_ldi) ? { iword[22:0] } // LDI
190
                        :((w_mov) ?{ {(23-13){iword[12]}}, iword[12:0] } // Move
191
                        :((~iword[18]) ? { {(23-18){iword[17]}}, iword[17:0] }
192
                        : { {(23-14){iword[13]}}, iword[13:0] }
193
                        ));
194
 
195
`ifdef  OPT_VLIW
196
        wire    [5:0]    w_halfI;
197
        assign  w_halfI = (w_ldi) ? iword[5:0]
198
                                :((iword[5]) ? 6'h00 : {iword[4],iword[4:0]});
199
        assign  w_I  = (iword[31])? {{(23-6){w_halfI[5]}}, w_halfI }:w_fullI;
200
`else
201
        assign  w_I  = w_fullI;
202
`endif
203
        assign  w_Iz = (w_I == 0);
204
 
205
 
206
`ifdef  OPT_VLIW
207
        //
208
        // The o_phase parameter is special.  It needs to let the software
209
        // following know that it cannot break/interrupt on an o_phase asserted
210
        // instruction, lest the break take place between the first and second
211
        // half of a VLIW instruction.  To do this, o_phase must be asserted
212
        // when the first instruction half is valid, but not asserted on either
213
        // a 32-bit instruction or the second half of a 2x16-bit instruction.
214
        reg     r_phase;
215
        initial r_phase = 1'b0;
216
        always @(posedge i_clk)
217
                if (i_rst) // When no instruction is in the pipe, phase is zero
218
                        r_phase <= 1'b0;
219
                else if (i_ce)
220
                        r_phase <= (o_phase)? 1'b0:(i_instruction[31]);
221
        // Phase is '1' on the first instruction of a two-part set
222
        // But, due to the delay in processing, it's '1' when our output is
223
        // valid for that first part, but that'll be the same time we
224
        // are processing the second part ... so it may look to us like a '1'
225
        // on the second half of processing.
226
 
227
        assign  o_phase = r_phase;
228
`else
229
        assign  o_phase = 1'b0;
230
`endif
231
 
232
 
233
        always @(posedge i_clk)
234
                if (i_ce)
235
                begin
236
`ifdef  OPT_VLIW
237
                        if (~o_phase)
238
                        begin
239
                                o_gie<= i_gie;
240
                                // i.e. dcd_pc+1
241
                                o_pc <= i_pc+{{(AW-1){1'b0}},1'b1};
242
                        end
243
 
244
                        o_illegal <=  (i_illegal);
245
`else
246
                        o_illegal <= ((i_illegal) || (i_instruction[31]));
247
                        o_gie<= i_gie;
248
                        o_pc <= i_pc+{{(AW-1){1'b0}},1'b1};
249
`endif
250
 
251
                        if ((IMPLEMENT_MPY!=1)&&(w_op[4:1]==4'h5))
252
                                o_illegal <= 1'b1;
253
 
254
                        if ((IMPLEMENT_DIVIDE==0)&&(w_dcdDV))
255
                                o_illegal <= 1'b1;
256
                        else if ((IMPLEMENT_DIVIDE!=0)&&(w_dcdDV)&&(w_dcdR[3:1]==3'h7))
257
                                o_illegal <= 1'b1;
258
 
259
 
260
                        if ((IMPLEMENT_FPU!=0)&&(w_dcdFP)&&(w_dcdR[3:1]==3'h7))
261
                                o_illegal <= 1'b1;
262
                        else if ((IMPLEMENT_FPU==0)&&(w_dcdFP))
263
                                o_illegal <= 1'b1;
264
 
265
                        // Under what condition will we execute this
266
                        // instruction?  Only the load immediate instruction
267
                        // is completely unconditional.
268
                        o_cond <= w_cond;
269
                        // Don't change the flags on conditional instructions,
270
                        // UNLESS: the conditional instruction was a CMP
271
                        // or TST instruction.
272
                        o_wF <= w_wF;
273
 
274
                        // Record what operation/op-code (4-bits) we are doing
275
                        //      Note that LDI magically becomes a MOV
276
                        //      instruction here.  That way it's a pass through
277
                        //      the ALU.  Likewise, the two compare instructions
278
                        //      CMP and TST becomes SUB and AND here as well.
279
                        // We keep only the bottom four bits, since we've
280
                        // already done the rest of the decode necessary to 
281
                        // settle between the other instructions.  For example,
282
                        // o_FP plus these four bits uniquely defines the FP
283
                        // instruction, o_DV plus the bottom of these defines
284
                        // the divide, etc.
285
                        o_op <= (w_ldi)? 4'hf:w_op[3:0];
286
 
287
                        // Default values
288
                        o_dcdR <= { w_dcdR_cc, w_dcdR_pc, w_dcdR};
289
                        o_dcdA <= { w_dcdA_cc, w_dcdA_pc, w_dcdA};
290
                        o_dcdB <= { w_dcdB_cc, w_dcdB_pc, w_dcdB};
291
                        o_wR  <= w_wR;
292
                        o_rA  <= w_rA;
293
                        o_rB  <= w_rB;
294
                        r_I    <= w_I;
295
                        o_zI   <= w_Iz;
296
 
297
                        o_ALU  <=  (w_ALU)||(w_ldi)||(w_cmptst); // 1 LUT
298
                        o_M    <=  w_dcdM;
299
                        o_DV   <=  w_dcdDV;
300
                        o_FP   <=  w_dcdFP;
301
 
302
                        o_break <= (w_op[4:3]==2'b11)&&(w_dcdR[3:1]==3'h7)&&(w_op[2:0]==3'b001);
303
                        o_lock  <= (w_op[4:3]==2'b11)&&(w_dcdR[3:1]==3'h7)&&(w_op[2:0]==3'b010);
304
                        if ((w_op[4:3]==2'b11)&&(w_dcdR[3:1]==3'h7)
305
                                &&((w_op[2])||(w_op[1:0]==2'b11)))
306
                                o_illegal <= 1'b1;
307
 
308
`ifdef  OPT_VLIW
309
                        r_nxt_half <= { iword[31], iword[13:5],
310
                                ((iword[21])? iword[20:19] : 2'h0),
311
                                iword[4:0] };
312
`endif
313
                end
314
 
315
 
316
        generate
317
        if (EARLY_BRANCHING!=0)
318
        begin
319
                reg                     r_early_branch;
320
                reg     [(AW-1):0]       r_branch_pc;
321
                always @(posedge i_clk)
322
                        if ((i_ce)&&(w_dcdR_pc)&&(w_cond[3]))
323
                        begin
324
                                if ((w_op == 5'hf)&&(w_dcdB_pc)&&(w_dcdA_pc))
325
                                begin // Move (X+PC) to PC
326
                                        r_early_branch     <= 1'b1;
327
                                end else if (w_op[4:1] == 4'hb) // LDI to PC
328
                                begin // LDI x,PC
329
                                        r_early_branch     <= 1'b1;
330
                                end else if ((w_op[4:0] == 5'h00)&&(~w_rB)&&(w_dcdA_pc))
331
                                begin // Add x,PC
332
                                        r_early_branch     <= 1'b1;
333
                                end else begin
334
                                        r_early_branch     <= 1'b0;
335
                                end
336
                        end else begin
337
                                if (i_ce)
338
                                        r_early_branch <= 1'b0;
339
                        end
340
                always @(posedge i_clk)
341
                        if (i_ce)
342
                        begin
343
                                if (w_op[4:1] == 4'hb)
344
                                        r_branch_pc <= {{(AW-23){w_I[22]}},w_I};
345
                                else
346
                                r_branch_pc <= i_pc+{{(AW-23){w_I[22]}},w_I}
347
                                                +{{(AW-1){1'b0}},1'b1};
348
                        end
349
 
350
                assign  o_early_branch     = r_early_branch;
351
                assign  o_branch_pc        = r_branch_pc;
352
        end else begin
353
                assign  o_early_branch = 1'b0;
354
                assign  o_branch_pc = {(AW){1'b0}};
355
        end endgenerate
356
 
357
        assign  o_I = { {(32-22){r_I[22]}}, r_I[21:0] };
358
 
359
endmodule

powered by: WebSVN 2.1.0

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